From a3d8d4c6b618895480ad9b4e1b53792e5ff6d433 Mon Sep 17 00:00:00 2001 From: Marc Monka <77387009+marcmonka@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:57:48 +0100 Subject: [PATCH] Add files via upload --- arduino/XDJ100SX.ino | 408 +++++++++++++++++++++++++++++++++++++++++++ arduino/name.c | 10 ++ 2 files changed, 418 insertions(+) create mode 100644 arduino/XDJ100SX.ino create mode 100644 arduino/name.c diff --git a/arduino/XDJ100SX.ino b/arduino/XDJ100SX.ino new file mode 100644 index 0000000..a6931db --- /dev/null +++ b/arduino/XDJ100SX.ino @@ -0,0 +1,408 @@ +#include +#include +#include +#include + + +// MIDI IN - botons +const int eject_pin = 0; +const int track_previous_pin = 1; +const int track_next_pin = 2; +const int search_back_pin = 3; +const int search_forward_pin = 4; +const int cue_pin = 5; +const int play_pin = 6; +const int jet_pin = 7; +const int zip_pin = 8; +const int wah_pin = 9; +const int hold_pin = 10; +const int time_pin = 11; +const int mastertempo_pin = 12; + +//encoder jog +const int jogA_pin = 20; +const int jogB_pin = 15; +const int midiChannel = 2; +const int jogControlNumber = 20; +Encoder jog(jogA_pin, jogB_pin); +long lastPosition_jog = 0; + + + +//encoder browser +const int browseA_pin = 22; +const int browseB_pin = 21; +const int load_pin= 23; +const int midiChannelb = 3; +const int DEBOUNCE_MS = 3; // Debounce curt +const int NOTE_SCROLL_DOWN = 70; +const int NOTE_SCROLL_UP = 71; +elapsedMillis debounceTime_browse; // Temps per filtrar rebots browse¡ +Encoder browse(browseA_pin, browseB_pin); +long lastPosition_browse = 0; // Última posició llegida + +//Pitch slider old +const int pitch_pin = A0; +const int channel_pitch = 3; +const int controllerA0 = 7; +int previousA0 = -1; +elapsedMillis msec = 0; +ResponsiveAnalogRead analog(pitch_pin, true); + + + + +// MIDI OUT - Leds + +const int ledCue = 16; +const int ledPlay = 17; +const int ledIntern = 18; +const int ledCd = 19; + +// Canals MIDI +const int channel = 1; + +//Notes que rebo de Mixxx pel play, cue, etc +const int PLAY_NOTE_INDICATOR = 61; +const int CUE_NOTE_INDICATOR = 62; +const int LEDINTERN_NOTE_INDICATOR = 63; +const int LEDCD_NOTE_INDICATOR = 64; +const int SIESTAPLAY_NOTE_INDICATOR = 65; +bool siestaplay = false; + +//Parpadeig final de track +bool parpadeig = false; +unsigned long tempsAnterior = 0; + + + +//Bounce botons cada 5ms +Bounce eject_boto = Bounce (eject_pin, 50); +Bounce trackprevious_boto = Bounce (track_previous_pin, 50); +Bounce track_next_boto = Bounce (track_next_pin, 50); +Bounce search_back_boto = Bounce (search_back_pin, 50); +Bounce search_forward_boto = Bounce (search_forward_pin, 50); +Bounce play_boto = Bounce (play_pin, 50); +Bounce cue_boto = Bounce (cue_pin, 50); +Bounce jet_boto = Bounce (jet_pin, 50); +Bounce zip_boto = Bounce (zip_pin, 50); +Bounce wah_boto = Bounce (wah_pin, 50); +Bounce hold_boto = Bounce (hold_pin, 50); +Bounce time_boto = Bounce (time_pin, 50); +Bounce mastertempo_boto = Bounce (mastertempo_pin, 50); +Bounce load_boto = Bounce (load_pin, 50); + + + + +// --- FUNCIONS QUE S'EXECUtEN QUAN ES REP UN MISSATGE MIDI --- + + +// Aquesta funció s'executarà automàticament quan es rebi un "Note On" +void handleNoteOn(byte channel, byte note, byte velocity) { + // Comprovem si la nota rebuda és la del nostre indicador de Play + if (note == PLAY_NOTE_INDICATOR) { + // Si la velocitat és més gran que 0, vol dir "Play", així que encenem el LED + if (velocity > 0) { + digitalWrite(ledPlay, HIGH); + } + // Si la velocitat és 0, es tracta com un Note Off, així que l'apaguem + else { + digitalWrite(ledPlay, LOW); + } + } + if (note == CUE_NOTE_INDICATOR) { + // Si la velocitat és més gran que 0, vol dir "Play", així que encenem el LED + if (velocity > 0) { + digitalWrite(ledCue, HIGH); + } + // Si la velocitat és 0, es tracta com un Note Off, així que l'apaguem + else { + digitalWrite(ledCue, LOW); + } + } +//LED INTERN MARCA EL BPM, NOMÉS SI ESTÀ EN PLAY +if(note == SIESTAPLAY_NOTE_INDICATOR){ + siestaplay = true; +} +if (note == LEDINTERN_NOTE_INDICATOR && siestaplay == true) +{ + digitalWrite(ledIntern, HIGH); +} + //LED CD el farem parpadejar quan rebi informació que la cançó s'està acabant (mixxx envia 1) + if (note == LEDCD_NOTE_INDICATOR) { + parpadeig = (velocity > 0); + } + + +} + + +// Aquesta funció s'executarà automàticament quan es rebi un "Note Off" +void handleNoteOff(byte channel, byte note, byte velocity) { + // Comprovem si la nota rebuda és la del nostre indicador de Play + if (note == PLAY_NOTE_INDICATOR) { + // Si rebem un Note Off per a aquesta nota, apaguem el LED + digitalWrite(ledPlay, LOW); + } + if (note == CUE_NOTE_INDICATOR) { + // Si rebem un Note Off per a aquesta nota, apaguem el LED + digitalWrite(ledCue, LOW); + } + + if (note == LEDCD_NOTE_INDICATOR) { + parpadeig = false; + } + + if(note == SIESTAPLAY_NOTE_INDICATOR){ + siestaplay = false; + } + if (note == LEDINTERN_NOTE_INDICATOR || siestaplay == false){ + digitalWrite(ledIntern, LOW); + } + +} + +void JogNudge(){ + long newPosition_jog = jog.read(); + + if (newPosition_jog % 4 == 0 && newPosition_jog != lastPosition_jog) { + if (newPosition_jog > lastPosition_jog) { + // Dreta -> Envia 65 + usbMIDI.sendControlChange(jogControlNumber, 65, midiChannel); + } else { + // Esquerra -> Envia 63 + usbMIDI.sendControlChange(jogControlNumber, 63, midiChannel); + } + lastPosition_jog = newPosition_jog; + } + +} + + + + +void setup() { + +pinMode(eject_pin, INPUT_PULLUP); +pinMode(track_previous_pin, INPUT_PULLUP); +pinMode(track_next_pin, INPUT_PULLUP); +pinMode(search_back_pin, INPUT_PULLUP); +pinMode(search_forward_pin, INPUT_PULLUP); +pinMode(cue_pin, INPUT_PULLUP); +pinMode(play_pin, INPUT_PULLUP); +pinMode(jet_pin, INPUT_PULLUP); +pinMode(eject_pin, INPUT_PULLUP); +pinMode(zip_pin, INPUT_PULLUP); +pinMode(wah_pin, INPUT_PULLUP); +pinMode(hold_pin, INPUT_PULLUP); +pinMode(time_pin, INPUT_PULLUP); +pinMode(mastertempo_pin, INPUT_PULLUP); +pinMode(load_pin, INPUT_PULLUP); + + +pinMode(ledCue, OUTPUT); +pinMode(ledPlay, OUTPUT); +pinMode(ledIntern, OUTPUT); +pinMode(ledCd, OUTPUT); + + // --- CONFIGURació MIDI --- + // Assignem les nostres funcions "callback" als esdeveniments MIDI + usbMIDI.setHandleNoteOn(handleNoteOn); + usbMIDI.setHandleNoteOff(handleNoteOff); + + //Inicialitzo jog + jog.write(0); + + //Inicialitzo browse + browse.write(0); + lastPosition_browse = 0; + + + + +} + + +void loop() { + +eject_boto.update(); +trackprevious_boto.update(); +track_next_boto.update(); +search_back_boto.update(); +search_forward_boto.update(); +cue_boto.update(); +play_boto.update(); +jet_boto.update(); +zip_boto.update(); +wah_boto.update(); +hold_boto.update(); +time_boto.update(); +mastertempo_boto.update(); +load_boto.update(); + + +//Play + if(play_boto.fallingEdge()){ + usbMIDI.sendNoteOn(60, 127, channel); + } + if(play_boto.risingEdge()){ + usbMIDI.sendNoteOff(60, 0, channel); + } + //CUE + if(cue_boto.fallingEdge()){ + usbMIDI.sendNoteOn(61, 127, channel); + } + if(cue_boto.risingEdge()){ + usbMIDI.sendNoteOff(61, 0, channel); + } + + +//Master Tempo + if(mastertempo_boto.fallingEdge()){ + usbMIDI.sendNoteOn(62, 127, channel); + } + if(mastertempo_boto.risingEdge()){ + usbMIDI.sendNoteOff(62, 0, channel); + } + +//Eject +if(eject_boto.fallingEdge()){ + usbMIDI.sendNoteOn(63, 127, channel); + } + if(eject_boto.risingEdge()){ + usbMIDI.sendNoteOff(63, 0, channel); + } + //trackprevious +if(trackprevious_boto.fallingEdge()){ + usbMIDI.sendNoteOn(64, 127, channel); + } + if(trackprevious_boto.risingEdge()){ + usbMIDI.sendNoteOff(64, 0, channel); + } + //tracknext +if(track_next_boto.fallingEdge()){ + usbMIDI.sendNoteOn(65, 127, channel); + } + if(track_next_boto.risingEdge()){ + usbMIDI.sendNoteOff(65, 0, channel); + } + //search_back +if(search_back_boto.fallingEdge()){ + usbMIDI.sendNoteOn(66, 127, channel); + } + if(search_back_boto.risingEdge()){ + usbMIDI.sendNoteOff(66, 0, channel); + } + //search_forward +if(search_forward_boto.fallingEdge()){ + usbMIDI.sendNoteOn(67, 127, channel); + } + if(search_forward_boto.risingEdge()){ + usbMIDI.sendNoteOff(67, 0, channel); + } + //jet +if(jet_boto.fallingEdge()){ + usbMIDI.sendNoteOn(68, 127, channel); + } + if(jet_boto.risingEdge()){ + usbMIDI.sendNoteOff(68, 0, channel); + } + //zip +if(zip_boto.fallingEdge()){ + usbMIDI.sendNoteOn(69, 127, channel); + } + if(zip_boto.risingEdge()){ + usbMIDI.sendNoteOff(69, 0, channel); + } + //wah +if(wah_boto.fallingEdge()){ + usbMIDI.sendNoteOn(70, 127, channel); + } + if(wah_boto.risingEdge()){ + usbMIDI.sendNoteOff(70, 0, channel); + } + //hold +if(hold_boto.fallingEdge()){ + usbMIDI.sendNoteOn(71, 127, channel); + } + if(hold_boto.risingEdge()){ + usbMIDI.sendNoteOff(71, 0, channel); + } + //time +if(time_boto.fallingEdge()){ + usbMIDI.sendNoteOn(72, 127, channel); + } + if(time_boto.risingEdge()){ + usbMIDI.sendNoteOff(72, 0, channel); + } + //load +if(load_boto.fallingEdge()){ + usbMIDI.sendNoteOn(73, 127, channel); + } + if(load_boto.risingEdge()){ + usbMIDI.sendNoteOff(73, 0, channel); + } + + + //Jog: cridem la funció JogNudge +JogNudge(); + + +//Browse +long newPosition_browse = browse.read(); + long delta_browse = newPosition_browse - lastPosition_browse; + + if (debounceTime_browse > DEBOUNCE_MS && delta_browse != 0) { + // Convertim els passos de l'encoder a "clics" (canvis de +1 o -1) + // LA CLAU ÉS AQUÍ: Només actuem si la posició és un múltiple de 4 + // i si és diferent de l'última posició VÀLIDA que vam guardar. + if (newPosition_browse % 4 == 0 && newPosition_browse != lastPosition_browse) { + + if (newPosition_browse > lastPosition_browse) { + // Direcció: DRETA (baixar a la llista) + usbMIDI.sendNoteOn(NOTE_SCROLL_DOWN, 127, midiChannelb); + usbMIDI.sendNoteOff(NOTE_SCROLL_DOWN, 0, midiChannelb); + + } else { + // Direcció: ESQUERRA (pujar a la llista) + usbMIDI.sendNoteOn(NOTE_SCROLL_UP, 127, midiChannelb); + usbMIDI.sendNoteOff(NOTE_SCROLL_UP, 0, midiChannelb); + } + + // Actualitzem la posició "antiga" NOMÉS quan tenim un clic complet. + lastPosition_browse = newPosition_browse; + } +} + +//Pitch +if (msec >= 100){ + msec = 0; + int n0 = analogRead(A0) / 8; + //transmetre MIDI si A0 canvia + if(n0 != previousA0){ + usbMIDI.sendControlChange(controllerA0, n0, channel_pitch); + previousA0 = n0; + } +} + + + +//Parpadeig LED CD si s'acaba la cançó (MIXX envia 127) +if (parpadeig){ + if (millis () - tempsAnterior >= 1000){ + tempsAnterior = millis(); + digitalWrite(ledCd, !digitalRead(ledCd)); + } +} +else{ + digitalWrite(ledCd, LOW); + } + +// Aquesta línia és l'única cosa que necessitem al loop. + // Constantment comprova si ha arribat algun missatge de Mixxx + // i, si és així, crida automàticament a les funcions 'handleNoteOn' o 'handleNoteOff'. + while (usbMIDI.read()){}; + + +} diff --git a/arduino/name.c b/arduino/name.c new file mode 100644 index 0000000..1977a82 --- /dev/null +++ b/arduino/name.c @@ -0,0 +1,10 @@ +#include "usb_names.h" + +#define MIDI_NAME {'X','D','J','1','0','0','S','X'} +#define MIDI_NAME_LEN 8 + +struct usb_string_descriptor_struct usb_string_product_name = { + 2 + MIDI_NAME_LEN * 2, + 3, + MIDI_NAME +};