diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..00c2433 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +arduino/dj/build diff --git a/arduino/dj/dj.ino b/arduino/dj/dj.ino new file mode 100644 index 0000000..d7b47b7 --- /dev/null +++ b/arduino/dj/dj.ino @@ -0,0 +1,298 @@ +#include + +class Mux { +private: + uint8_t _pins[4]; + uint8_t _enablePin = 255; + uint8_t _channel = 0; + uint8_t _comm; +public: + Mux(uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t comm) { + _pins[0] = s0; + _pins[1] = s1; + _pins[2] = s2; + _pins[3] = s3; + _comm = comm; + + for (uint8_t i=0; i<4; i++) { + pinMode(_pins[i], OUTPUT); + digitalWrite(_pins[i], LOW); + } + pinMode(_comm, INPUT); + _channel = 0; + } + + bool setChannel(uint8_t channel) { + if (channel > 15) return false; + uint8_t _new = channel; + if (_new != _channel) { + uint8_t _changed = _new ^ _channel; + uint8_t mask = 0x08; + uint8_t i = 3; + while (mask) { + // only write changed pins. + if (mask & _changed) digitalWrite(_pins[i], (mask & _new)); + i--; + mask >>= 1; + } + _channel = _new; + } + return true; + } + + bool digitalR(uint8_t chann) { + setChannel(chann); + return digitalRead(_comm); + } + + int analogR(uint8_t chann) { + setChannel(chann); + return analogRead(_comm); + } +}; + +class Button { +private: + + uint8_t _chann; + Mux * _mux; + bool _state; + bool _debounceState; + uint32_t _lastDebounce = 0; + uint16_t _debounceDelay; + +public: + + const char* name; + + Button(const char * newName ,uint8_t chann, Mux * mux, uint16_t debounceDelay=10) { + _chann = chann; + _mux = mux; + _debounceDelay = debounceDelay; + name = newName; + } + + bool stateChanged() { + bool tmpState = !_mux->digitalR(_chann); + if (tmpState != _debounceState) _lastDebounce = millis(); + if (millis() - _lastDebounce > _debounceDelay) { + if (tmpState != _state) { + _state = tmpState; + return true; + } + } + _debounceState = tmpState; + return false; + } + + // Returns true if something has changed + bool update() { + if (stateChanged()) { + Serial.print(name); + Serial.print(": "); + if (_state == true) Serial.println("pressed"); + else Serial.println("Released"); + return true; + } + return false; + } + + // Eventos + // - state (down or up) + // - press (up-down) + // - release (down-up) + // - single click (press-release en menos de n millis) + // - double click (single-single en menos de n millis) + // - triple click (single-single-single en menos de n millis) + // +}; + +class Pot { +private: + + uint8_t _chann; + Mux * _mux; + int _prevValue; + uint8_t _diff; // A change bigger than this indicates that the pot has moved + +public: + + const char* name; + int value; + + Pot(const char * newName ,uint8_t chann, Mux * mux, uint8_t diff=5) { + _chann = chann; + _mux = mux; + _diff = diff; + name = newName; + } + + bool valueChanged() { + value = _mux->analogR(_chann); + if (abs(value - _prevValue) > _diff) { + _prevValue = value; + return true; + } + return false; + } + + // Returns true if something has changed + bool update() { + if (valueChanged()) { + Serial.print(name); + Serial.print(": "); + Serial.println(value); + return true; + } + return false; + } + + // TODO + // Un rolling average que suvice un poco los movimientos +}; + +Mux mux_A(26, 25, 27, 32, 33); // (s0, s1, s2, s3, comm) +// 6, 7, 8, 9, 10, 15 -> NC + +Mux mux_B(16, 17, 18, 19, 34); // (s0, s1, s2, s3, comm) +// 3 -> ANO_ENC_A +// 4 -> ANO_ENC_B +Button ACenter("A Center", 5, &mux_B); // SW1 +Button ADown("A Down", 6, &mux_B); // SW2 +Button ARight("A Right", 7, &mux_B); // SW3 +Button AUp("A Up", 8, &mux_B); // SW4 +Button ALeft("A Left", 9, &mux_B); // SW5 + +Pot MLevel("M Level", 0, &mux_A); +Pot LLevel("L Level", 1, &mux_A); // Slide +Pot LHigh("L High", 2, &mux_A); +Pot LMiddle("L Middle", 3, &mux_A); +Pot LLow("L Low", 4, &mux_A); +Pot LFx("L FX", 5, &mux_A); + +Pot RLevel("R Level", 14, &mux_B); // Slide +Pot RHigh("R High", 13, &mux_B); +Pot RMiddle("R Middle", 12, &mux_B); +Pot RLow("R Low", 11, &mux_B); +Pot RFx("R FX", 10, &mux_B); + +Pot * pots[11]; + +Button LPlay("L Play", 12, &mux_A); +Button LCue("L Cue", 11, &mux_A); +Button LSync("L Sync", 13, &mux_A); +Button LPhones("L Phones", 14, &mux_A); + +Button RPlay("R Play", 0, &mux_B); +Button RCue("R Cue", 15, &mux_B); // BUG: Al mover el slider (channel 14) se mete ruido al boton (pareciera ser un problema de hardware) +Button RSync("R Sync", 1, &mux_B); +Button RPhones("R Phones", 2, &mux_B); + +Button * botones[8]; + +const int BATT_CHG_SIGNAL_PIN = 14; +const int BATT_VOLT_PIN = 35; + +// 5% steps +float battTable[] = { + 4.2, // 100 + 4.15, // 95 + 4.11, // 90 + 4.08, // 85 + 4.02, // 80 + 3.98, // 75 + 3.95, // 70 + 3.91, // 65 + 3.87, // 60 + 3.85, // 55 + 3.84, // 50 + 3.82, // 45 + 3.80, // 40 (Storage recomended) + 3.79, // 35 + 3.77, // 30 + 3.75, // 25 + 3.73, // 20 + 3.71, // 15 (Sane limit) + 3.69 // 10 (Danger limit) +}; + +uint8_t battLevel() { + + // Vin = Vout * ((R1 + R2) / R2) + // ((R1 + R2) / R2) = (1,200,000 / 200,000) = 6 + int Vout = analogRead(BATT_VOLT_PIN); + float Vin = Vout * 6.0; + + uint8_t percent = 100; + for (uint8_t l=0; l<19; l++) { + if (Vin >= battTable[l]) return percent; + percent -= 5; + } + return 0; + // TODO + // Interpolar los porcentajes +} + +bool battIsCharging() { + return !digitalRead(BATT_CHG_SIGNAL_PIN); +} + +#define NUM_LEDS 17 +CRGB leds[NUM_LEDS]; +uint32_t ledChanged = 0; +uint8_t ledIndex = 0; + +void refreshLeds() { + if (millis() - ledChanged < 500) return; + ledChanged = millis(); + if (ledIndex == NUM_LEDS) ledIndex = 0; + + fill_solid(&(leds[0]), NUM_LEDS, CRGB::Black); + leds[ledIndex] = CRGB::Red; + FastLED.show(); + ledIndex++; +} + +void setup() { + + FastLED.addLeds(leds, NUM_LEDS); + + pinMode(BATT_VOLT_PIN, INPUT); + pinMode(BATT_CHG_SIGNAL_PIN, INPUT); + + Serial.begin(115200); + + botones[0] = &LPlay; + botones[1] = &LCue; + botones[2] = &LSync; + botones[3] = &LPhones; + botones[4] = &RPlay; + botones[5] = &RCue; + botones[6] = &RSync; + botones[7] = &RPhones; + + pots[0] = &MLevel; + pots[1] = &LLevel; // Slide + pots[2] = &LHigh; + pots[3] = &LMiddle; + pots[4] = &LLow; + pots[5] = &LFx; + pots[6] = &RLevel; // Slide + pots[7] = &RHigh; + pots[8] = &RMiddle; + pots[9] = &RLow; + pots[10] = &RFx; + +} + +void loop() { + + for (uint8_t i=0; i<8; i++) { + botones[i]->update(); + } + for (uint8_t i=0; i<11; i++) { + pots[i]->update(); + } + + refreshLeds(); +} diff --git a/arduino/dj/sketch.yaml b/arduino/dj/sketch.yaml new file mode 100644 index 0000000..27bfe2f --- /dev/null +++ b/arduino/dj/sketch.yaml @@ -0,0 +1,2 @@ +default_port: /dev/ttyUSB0 +default_fqbn: arduino:esp32