diff --git a/docs/api.md b/docs/api.md index acaf10c..df47a40 100644 --- a/docs/api.md +++ b/docs/api.md @@ -64,6 +64,12 @@ void onBleConnectionChange(void (*fptr)(bool t_connected)); // triggered when a Menu Command is handled by a button, encoder, API, etc. void onMenu(void (*fptr)(uint8_t t_command)); +// triggered when the Typer value has been Updated +void onTyperUpdate(void (*fptr)(uint16_t t_value)); + +// triggered when the Typer value has been Updated and you set it to custom calback +void onTyperCustomUpdate(void (*fptr)(uint16_t t_value)); + // triggered when BMC runs it's update() method the first time. void onFirstLoop(void (*fptr)()); diff --git a/docs/multiplexers.md b/docs/multiplexers.md index 7cb75c6..0041605 100644 --- a/docs/multiplexers.md +++ b/docs/multiplexers.md @@ -8,6 +8,10 @@ *********************************************** ***BMC now allows for up to 127 Analog Mux Pins, Digital Mux In will still be limited to 64 pins*** *********************************************** +*********************************************** +***BMC now supports Mux Out with the 74HC595*** +*********************************************** + While BMC uses a Teensy's pins to read inputs it also has support for up 64 Mux inputs. These include: @@ -20,6 +24,11 @@ IC | Input Type | Inputs | Pins Required **74HC4067** | Analog Only | 16 | 5 *(1 must be analog)* **74HC4051** | Analog Only | 8 | 4 *(1 must be analog)* +#### MUX OUT: + +IC | Output Type | Outputs | Pins Required +-|-|-|- +**74HC595** | Digital Only | 8 | 3 (4 optional for PWM) BMC has code to read all chips above however there are a few limits. For digital inputs you can only use one type of chip, so if you want to have 32 inputs you can either use four 74HC165 or two MCP23017 or two MCP23018, you can not combine them. @@ -57,12 +66,14 @@ BMC also lets you use other ICs, however you have to write the code to read them For Digital Inputs you can use these API functions: ```c++ -// for the first 32 pins -void setMuxIn1To32(uint32_t values); +// @n the digital pin index, this is the actual index, that is if it's the very first digital pin, n will be 0 +// @value false if button is pressed, true is released +void setMuxDigitalValue(uint8_t n, bool value); +``` -// for the last 32 pins -// (only available if more than 32 Digital Mux In pins compiled) -void setMuxIn33To64(uint32_t values); +For Digital Output +```c++ +void setMuxDigitalOutValue(uint8_t pin, bool value); ``` For Analog Inputs you can use: @@ -70,12 +81,11 @@ For Analog Inputs you can use: ```c++ // @n the analog pin index, this is the actual index, that is if it's the very first analog pin, n will be 0 // @value the 10-bit analog value 0 to 1023 -void setMuxInAnalogValue(uint8_t n, uint16_t value); +void setMuxAnalogValue(uint8_t n, uint16_t value); ``` -Since digital inputs only have 2 states on/off, true/false, 0/1, etc, you have to think of each digital input as a ***bit***, so bit-0 of `values` in `setMuxIn1To32` is the very first digital pin. -Additionally, BMC reads digital inputs **Active Low** that is when a button is inactive (depressed) that bit must be **1**, when a button is pressed that bit must be **0** +Additionally, BMC reads digital inputs **Active Low** that is when a button is inactive (depressed) that value passed must be **1**, when a button is pressed the value passed must be **0** With the API could use a touch sensor to trigger a Pot and send MIDI messages from assigned to that Pot, MIDI Theremin anybody? @@ -84,38 +94,39 @@ There are many API callbacks and functions available for use, these may not refl ##### FUNCTIONS - +For Digital Input ```c++ -// Only available if Mux In is set to *Other* -// for the first 32 pins -// each bit of the 32-bit int represents the digital input -// they must be active low -void setMuxIn1To32(uint32_t values); - -// Only available if Mux In is set to *Other* -// for the last 32 pins -// (only available if more than 32 Digital Mux In pins compiled) -void setMuxIn33To64(uint32_t values); +// @n the digital pin index, this is the actual index, that is if it's the very first digital pin, n will be 0 +// @value false if button is pressed, true is released +void setMuxDigitalValue(uint8_t n, bool value); // Only available for supported Mux ICs, useful when you want to read pins // to be handled by your sketch // read a digital mux in pin -bool getMuxInValue(uint8_t n); +bool getMuxValue(uint8_t n); +``` + +For Digital Output +```c++ +// set the value of a custom mux output pin +void setMuxDigitalOutValue(uint8_t pin, bool value); + +// get the value of a mux output pin +bool getMuxOutValue(uint8_t n); ``` For Analog Inputs you can use these API functions: ```c++ -// Only available if Mux In is set to *Other* // @n the analog pin index, this is the actual index, that is if it's the very first analog pin, n will be 0 // @value the 10-bit analog value 0 to 1023 -void setMuxInAnalogValue(uint8_t n, uint16_t value); +void setMuxAnalogValue(uint8_t n, uint16_t value); // Only available for supported Analog Mux ICs, useful when you want to read pins // to be handled by your sketch // @n the analog pin index, this is the actual index, that is if it's the very first analog pin, n will be 0 // returns a 10-bit value -uint16_t getMuxInAnalogValue(uint8_t n); +uint16_t getMuxAnalogValue(uint8_t n); ``` diff --git a/library.properties b/library.properties index 6b93447..9eb69dd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=BMC -version=0.0.14 +version=0.0.15 author=Nero Rox maintainer=Nero Rox sentence=Badass MIDI Controller (BMC), a fully featured MIDI Controller with a Desktop Editor App. For 32-bit Teensy Only diff --git a/src/BMC-Api.h b/src/BMC-Api.h index 4ccff39..027e851 100644 --- a/src/BMC-Api.h +++ b/src/BMC-Api.h @@ -244,6 +244,16 @@ class BMCApi : public BMC { void onMenu(void (*fptr)(uint8_t t_command)){ callback.menuCommand = fptr; } + // triggered when the Typer value has been Updated + void onTyperUpdate(void (*fptr)(uint16_t t_value)){ + callback.typerCommand = fptr; + } + // triggered when the Typer value has been Updated and you set it to custom calback + void onTyperCustomUpdate(void (*fptr)(uint16_t t_value)){ + callback.typerCustomCommand = fptr; + } + + // triggered when BMC runs it's update() method the first time. void onFirstLoop(void (*fptr)()){ callback.firstLoop = fptr; @@ -759,25 +769,28 @@ class BMCApi : public BMC { #if BMC_MAX_MUX_IN > 0 #if BMC_MUX_IN_CHIPSET==BMC_MUX_IN_CHIPSET_OTHER - // for the first 32 pins - // each bit of the 32-bit int represents the digital input - // they must be active low - void setMuxIn1To32(uint32_t values){ - muxIn.setPinValues1To32(values); - } - #if BMC_MAX_MUX_IN > 32 - // for the last 32 pins - // (only available if more than 32 Digital Mux In pins compiled) - void setMuxIn33To64(uint32_t values){ - muxIn.setPinValues33To64(values); - } - #endif + // set the value of a custom mux input pin + void setMuxDigitalValue(uint8_t pin, bool value){ + mux.setDigitalValue(pin, value); + } #else - // available for supported Mux ICs, useful when you want to read pins - // to be handled by your sketch - // read a digital mux in pin - bool getMuxInValue(uint8_t n){ - return muxIn.getPinValue(n); + // get the value of a mux input pin + bool getMuxValue(uint8_t n){ + return mux.readDigital(n); + } + #endif +#endif + +#if BMC_MAX_MUX_OUT > 0 + #if BMC_MUX_OUT_CHIPSET==BMC_MUX_OUT_CHIPSET_OTHER + // set the value of a custom mux output pin + void setMuxDigitalOutValue(uint8_t pin, bool value){ + mux.writeDigital(pin, value); + } + #else + // get the value of a mux output pin + bool getMuxOutValue(uint8_t n){ + return mux.getDigitalValue(n); } #endif #endif @@ -786,16 +799,16 @@ class BMCApi : public BMC { #if BMC_MUX_IN_ANALOG_CHIPSET==BMC_MUX_IN_ANALOG_CHIPSET_OTHER // @n the analog pin index, this is the actual index, that is if it's the very first analog pin, n will be 0 // @value the 10-bit analog value 0 to 1023 - void setMuxInAnalogValue(uint8_t n, uint16_t value){ - muxInAnalog.setPinValue(n, value); + void setMuxAnalogValue(uint8_t n, uint16_t value){ + mux.setAnalogValue(n, value); } #else // available for supported Analog Mux ICs, useful when you want to read pins // to be handled by your sketch // @n the analog pin index, this is the actual index, that is if it's the very first analog pin, n will be 0 // returns a 10-bit value - uint16_t getMuxInAnalogValue(uint8_t n){ - return muxInAnalog.getPinValue(n); + uint16_t getMuxAnalogValue(uint8_t n){ + return mux.readAnalog(n); } #endif #endif diff --git a/src/BMC-Version.h b/src/BMC-Version.h index 57dac99..cd84d54 100644 --- a/src/BMC-Version.h +++ b/src/BMC-Version.h @@ -23,7 +23,7 @@ // BMC Version stored in EEPROM (for editor usage) #define BMC_VERSION_MAJ 0 #define BMC_VERSION_MIN 0 -#define BMC_VERSION_PATCH 14 +#define BMC_VERSION_PATCH 15 //16 bits unsigned, LSB byte is minor, MSB byte is major #define BMC_VERSION ((BMC_VERSION_MAJ<<8) | BMC_VERSION_MIN) diff --git a/src/BMC.cpp b/src/BMC.cpp index 47fb897..e1e6ef3 100644 --- a/src/BMC.cpp +++ b/src/BMC.cpp @@ -11,6 +11,7 @@ BMC::BMC(): globalData(store.global), settings(store.global.settings), midi(callback, globals, store.global.portPresets), + valueTyper(callback), editor(store, midi, settings, messenger), midiClock(midi), midiActiveSense(midi) diff --git a/src/BMC.debug.cpp b/src/BMC.debug.cpp index b79969d..37fdcff 100644 --- a/src/BMC.debug.cpp +++ b/src/BMC.debug.cpp @@ -57,7 +57,8 @@ void BMC::readDebug(){ BMC_PRINTLN("storageDebug = Prints the time it takes to read/write/clear EEPROM everytime the actions happens"); BMC_PRINTLN("metrics = Prints some metrics of the performance of BMC like loops per second, etc. Happens every other second."); - + BMC_PRINTLN("nextPage = Go to next page"); + BMC_PRINTLN("prevPage = Go to previous page"); BMC_PRINTLN("midiClockInfo = Display Master/Slave Clock Info"); BMC_PRINTLN("midiIn = Toggles displaying all incoming MIDI Messages (excludes Clock)"); BMC_PRINTLN("midiOut = Toggles displaying all outgoing MIDI Messages (excludes Clock)"); @@ -126,6 +127,14 @@ void BMC::readDebug(){ } printDebugHeader(debugInput); + } else if(BMC_STR_MATCH(debugInput,"nextPage")){ + + nextPage(); + + } else if(BMC_STR_MATCH(debugInput,"prevPage")){ + + prevPage(); + } else if(BMC_STR_MATCH(debugInput,"midiClockInfo")){ printDebugHeader(debugInput); diff --git a/src/BMC.h b/src/BMC.h index a03e171..26c9297 100644 --- a/src/BMC.h +++ b/src/BMC.h @@ -67,12 +67,8 @@ #include "addon/BMC-Kemper.h" #endif -#if BMC_MAX_MUX_IN > 0 - #include "hardware/BMC-MuxIn.h" -#endif - -#if BMC_MAX_MUX_IN_ANALOG - #include "hardware/BMC-MuxInAnalog.h" +#if defined(BMC_MUX_AVAILABLE) + #include "mux/BMC-Mux.h" #endif #if BMC_MAX_BUTTONS > 0 || BMC_MAX_GLOBAL_BUTTONS > 0 @@ -156,6 +152,8 @@ class BMC { // go to a new page // @reassignSettings if true will reassign all global settings void setPage(uint8_t page, bool reassignSettings=false); + void nextPage(); + void prevPage(); // scroll to a different page, either the previous or next page void scrollPage(uint8_t t_flags, uint8_t t_min, uint8_t t_max, uint8_t t_amount); @@ -198,6 +196,8 @@ class BMC { BMCSettings settings; // the global midi object BMCMidi midi; + // value typer object + BMCTyper valueTyper; // struct to hold messenger data sent between sketch and editor app BMCMessenger messenger; // editor handling all editing of the store @@ -334,12 +334,8 @@ class BMC { uint8_t parseMidiEventType(uint8_t t_type); uint8_t parseUserEventType(uint8_t t_type); -#if BMC_MAX_MUX_IN > 0 - BMCMuxIn muxIn; -#endif - -#if BMC_MAX_MUX_IN_ANALOG > 0 - BMCMuxInAnalog muxInAnalog; +#if defined(BMC_MUX_AVAILABLE) + BMCMux mux; #endif // PIXELS AND LEDS diff --git a/src/BMC.hardware.buttons.cpp b/src/BMC.hardware.buttons.cpp index 59f2418..bdcf4c3 100644 --- a/src/BMC.hardware.buttons.cpp +++ b/src/BMC.hardware.buttons.cpp @@ -83,7 +83,7 @@ void BMC::readButtons(){ // GET THE PIN STATE FROM MUX #if BMC_MAX_MUX_IN > 0 - buttons[i].setMuxValue(muxIn.getPinValue(buttons[i].getMuxPin())); + buttons[i].setMuxValue(mux.readDigital(buttons[i].getMuxPin())); #endif uint8_t buttonTrigger = buttons[i].read(); @@ -196,7 +196,7 @@ void BMC::readGlobalButtons(){ for(uint8_t i = 0; i < BMC_MAX_GLOBAL_BUTTONS; i++){ // GET THE PIN STATE FROM MUX #if BMC_MAX_MUX_IN > 0 - globalButtons[i].setMuxValue(muxIn.getPinValue(globalButtons[i].getMuxPin())); + globalButtons[i].setMuxValue(mux.readDigital(globalButtons[i].getMuxPin())); #endif #if BMC_MAX_GLOBAL_BUTTONS == 1 @@ -717,6 +717,32 @@ void BMC::handleGlobalButton(uint8_t index, uint8_t t_trigger){ // byteB = Channel midiProgramBankTrigger(byteA, byteB, ports); break; + case BMC_BUTTON_EVENT_TYPE_TYPER_CMD: + { + uint8_t cmd = valueTyper.cmd(byteA, byteB); + if(cmd > 10){// cmd 10 is Clear + if(cmd==12){// page + setPage(valueTyper.getOutput()); + } else if(cmd==13){// preset + #if BMC_MAX_PRESETS > 0 + presets.set(valueTyper.getOutput()); + #endif + } else if(cmd==14){// fas preset + #if defined(BMC_USE_FAS) + fas.setPreset(valueTyper.getOutput()); + #endif + } else if(cmd==15){// fas scene + #if defined(BMC_USE_FAS) + fas.setSceneNumber(valueTyper.getOutput(), false); + #endif + } else if(cmd==16){// fas scene revert + #if defined(BMC_USE_FAS) + fas.setSceneNumber(valueTyper.getOutput(), true); + #endif + } + } + } + break; #if BMC_MAX_CUSTOM_SYSEX > 0 case BMC_BUTTON_EVENT_TYPE_CUSTOM_SYSEX: diff --git a/src/BMC.hardware.cpp b/src/BMC.hardware.cpp index 164d896..e6ed6b1 100644 --- a/src/BMC.hardware.cpp +++ b/src/BMC.hardware.cpp @@ -16,7 +16,7 @@ void BMC::setupHardware(){ BMC_PRINTLN("BMC_MAX_AUX_JACKS", BMC_MAX_AUX_JACKS); for(uint8_t i=0;i 0 || BMC_MAX_MUX_IN_ANALOG > 0 + #if BMC_MAX_MUX_IN > 0 || BMC_MAX_MUX_OUT > 0 || BMC_MAX_MUX_IN_ANALOG > 0 if( BMCBuildData::getPotPin(BMCBuildData::getPotMergeItem(i, 0))>=64 || BMCBuildData::getButtonPin(BMCBuildData::getPotMergeItem(i, 1))>=64 || @@ -34,12 +34,8 @@ void BMC::setupHardware(){ } #endif -#if BMC_MAX_MUX_IN > 0 - muxIn.begin(); -#endif - -#if BMC_MAX_MUX_IN_ANALOG > 0 - muxInAnalog.begin(); +#if defined(BMC_MUX_AVAILABLE) + mux.begin(); #endif #if BMC_MAX_PIXELS > 0 @@ -151,12 +147,8 @@ void BMC::assignHardware() { // Read the hardware items for changes void BMC::readHardware(){ -#if BMC_MAX_MUX_IN > 0 - muxIn.update(); -#endif - -#if BMC_MAX_MUX_IN_ANALOG > 0 - muxInAnalog.update(); +#if defined(BMC_MUX_AVAILABLE) + mux.update(); #endif #if BMC_MAX_AUX_JACKS > 0 diff --git a/src/BMC.hardware.encoders.cpp b/src/BMC.hardware.encoders.cpp index 77bdf8a..3e433ca 100644 --- a/src/BMC.hardware.encoders.cpp +++ b/src/BMC.hardware.encoders.cpp @@ -41,8 +41,8 @@ void BMC::readEncoders(){ // GET THE PIN STATE FROM MUX #if BMC_MAX_MUX_IN > 0 if(encoders[i].hasMux()){ - encoders[i].setMuxValue(0, muxIn.getPinValue(encoders[i].getMuxPin(0))); - encoders[i].setMuxValue(1, muxIn.getPinValue(encoders[i].getMuxPin(1))); + encoders[i].setMuxValue(0, mux.readDigital(encoders[i].getMuxPin(0))); + encoders[i].setMuxValue(1, mux.readDigital(encoders[i].getMuxPin(1))); } #endif @@ -78,8 +78,8 @@ void BMC::readGlobalEncoders(){ // GET THE PIN STATE FROM MUX #if BMC_MAX_MUX_IN > 0 if(globalEncoders[i].hasMux()){ - globalEncoders[i].setMuxValue(0, muxIn.getPinValue(globalEncoders[i].getMuxPin(0))); - globalEncoders[i].setMuxValue(1, muxIn.getPinValue(globalEncoders[i].getMuxPin(1))); + globalEncoders[i].setMuxValue(0, mux.readDigital(globalEncoders[i].getMuxPin(0))); + globalEncoders[i].setMuxValue(1, mux.readDigital(globalEncoders[i].getMuxPin(1))); } #endif diff --git a/src/BMC.hardware.ledEvents.cpp b/src/BMC.hardware.ledEvents.cpp index 66dff48..56dcd77 100644 --- a/src/BMC.hardware.ledEvents.cpp +++ b/src/BMC.hardware.ledEvents.cpp @@ -340,7 +340,7 @@ void BMC::handleClockLeds(){ #if BMC_MAX_LEDS > 0 for(uint8_t index = 0; index < BMC_MAX_LEDS; index++){ bmcStoreLed& item = store.pages[page].leds[index]; - if(BMCTools::isMidiClockLedEvent(item.event>>1)){ + if(BMCTools::isMidiClockLedEvent(item.event)){ leds[index].pulse(); } } @@ -349,7 +349,7 @@ void BMC::handleClockLeds(){ #if BMC_MAX_GLOBAL_LEDS > 0 for(uint8_t index = 0; index < BMC_MAX_GLOBAL_LEDS; index++){ bmcStoreLed& item = globalData.leds[index]; - if(BMCTools::isMidiClockLedEvent(item.event>>1)){ + if(BMCTools::isMidiClockLedEvent(item.event)){ globalLeds[index].pulse(); } } diff --git a/src/BMC.hardware.leds.cpp b/src/BMC.hardware.leds.cpp index d9fec23..42de534 100644 --- a/src/BMC.hardware.leds.cpp +++ b/src/BMC.hardware.leds.cpp @@ -16,15 +16,26 @@ void BMC::setupLeds(){ #if BMC_PAGE_LED_DIM == true leds[index].setPwmOffValue(settings.getPwmDimWhenOff()); #endif + #if BMC_MAX_MUX_OUT > 0 + if(leds[i].muxTesting()){ + mux.testDigital(leds[i].getMuxPin()); + } + #endif } #endif #if BMC_MAX_GLOBAL_LEDS > 0 - for(uint8_t index = 0; index < BMC_MAX_GLOBAL_LEDS; index++){ - globalLeds[index].begin(BMCBuildData::getGlobalLedPin(index)); + for(uint8_t i = 0; i < BMC_MAX_GLOBAL_LEDS; i++){ + globalLeds[i].begin(BMCBuildData::getGlobalLedPin(i)); #if BMC_GLOBAL_LED_DIM == true - globalLeds[index].setPwmOffValue(settings.getPwmDimWhenOff()); + globalLeds[i].setPwmOffValue(settings.getPwmDimWhenOff()); + #endif + + #if BMC_MAX_MUX_OUT > 0 + if(globalLeds[i].muxTesting()){ + mux.testDigital(globalLeds[i].getMuxPin()); + } #endif } assignGlobalLeds(); @@ -66,6 +77,14 @@ void BMC::readLeds(){ leds[i].setState(bitRead(state, 3)); } bitWrite(_ledStates, i, leds[i].update()); + +#if BMC_MAX_MUX_OUT > 0 + mux.writeDigital(leds[i].getPin(), leds[i].getMuxState()); + if(leds[i].muxTesting()){ + mux.testDigital(leds[i].getMuxPin()); + } +#endif + } if(ledStates != _ledStates){ ledStates = _ledStates; @@ -108,6 +127,12 @@ void BMC::readGlobalLeds(){ globalLeds[i].setState(bitRead(state, 3)); } bitWrite(_globalLedStates,i,globalLeds[i].update()); +#if BMC_MAX_MUX_OUT > 0 + mux.writeDigital(globalLeds[i].getPin(), globalLeds[i].getMuxState()); + if(globalLeds[i].muxTesting()){ + mux.testDigital(globalLeds[i].getMuxPin()); + } +#endif } if(_globalLedStates!=globalLedStates){ globalLedStates = _globalLedStates; diff --git a/src/BMC.hardware.pots.cpp b/src/BMC.hardware.pots.cpp index e4dcb2e..0a1b539 100644 --- a/src/BMC.hardware.pots.cpp +++ b/src/BMC.hardware.pots.cpp @@ -66,7 +66,7 @@ void BMC::readPots(){ #endif #if BMC_MAX_MUX_IN_ANALOG > 0 - pots[i].setMuxValue(muxInAnalog.getPinValue(pots[i].getMuxPin())); + pots[i].setMuxValue(mux.readAnalog(pots[i].getMuxPin())); #endif #if defined(BMC_USE_POT_TOE_SWITCH) @@ -128,7 +128,7 @@ void BMC::potCalibrationToggle(uint8_t n){ } uint16_t BMC::getPotAnalogValue(uint8_t n){ #if BMC_MAX_MUX_IN_ANALOG > 0 - pots[n].setMuxValue(muxInAnalog.getPinValue(pots[n].getMuxPin())); + pots[n].setMuxValue(mux.readAnalog(pots[n].getMuxPin())); #endif return pots[n].getAnalogValue(); } @@ -150,7 +150,7 @@ void BMC::readGlobalPots(){ } for(uint8_t i = 0; i < BMC_MAX_GLOBAL_POTS; i++){ #if BMC_MAX_MUX_IN_ANALOG > 0 - globalPots[i].setMuxValue(muxInAnalog.getPinValue(globalPots[i].getMuxPin())); + globalPots[i].setMuxValue(mux.readAnalog(globalPots[i].getMuxPin())); #endif #if defined(BMC_USE_POT_TOE_SWITCH) @@ -192,7 +192,7 @@ void BMC::globalPotCalibrationToggle(uint8_t n){ } uint16_t BMC::getGlobalPotAnalogValue(uint8_t n){ #if BMC_MAX_MUX_IN_ANALOG > 0 - globalPots[n].setMuxValue(muxInAnalog.getPinValue(globalPots[n].getMuxPin())); + globalPots[n].setMuxValue(mux.readAnalog(globalPots[n].getMuxPin())); #endif return globalPots[n].getAnalogValue(); } diff --git a/src/BMC.midi.cpp b/src/BMC.midi.cpp index d07523a..000a998 100644 --- a/src/BMC.midi.cpp +++ b/src/BMC.midi.cpp @@ -134,7 +134,6 @@ void BMC::incomingMidi(BMCMidiMessage message){ void BMC::handleMidiClock(bool isClock, bool isStartOrContinue){ if(midiClock.read(isClock, isStartOrContinue)){ - #if (BMC_TOTAL_LEDS+BMC_TOTAL_PIXELS) > 0 handleClockLeds(); #endif diff --git a/src/BMC.page.cpp b/src/BMC.page.cpp index 347c977..6b324c7 100644 --- a/src/BMC.page.cpp +++ b/src/BMC.page.cpp @@ -60,6 +60,14 @@ bool BMC::pageChangedPeek(){ uint8_t BMC::getPage(){ return page; } +void BMC::nextPage(){ + BMCScroller scroller(0, BMC_MAX_PAGES-1); + setPage(scroller.scroll(1, true, true, page, 0, BMC_MAX_PAGES-1)); +} +void BMC::prevPage(){ + BMCScroller scroller(0, BMC_MAX_PAGES-1); + setPage(scroller.scroll(1, false, true, page, 0, BMC_MAX_PAGES-1)); +} void BMC::scrollPage(uint8_t t_flags, uint8_t t_min, uint8_t t_max, uint8_t t_amount){ // t_flags bit-0 = direction // t_flags bit-1 = endless diff --git a/src/addon/BMC-Fas.h b/src/addon/BMC-Fas.h index 025263c..03e5601 100644 --- a/src/addon/BMC-Fas.h +++ b/src/addon/BMC-Fas.h @@ -57,7 +57,7 @@ #define BMC_FAS_FUNC_ID_DISCONNECT 0x42 #define BMC_FAS_FUNC_ID_GENERAL_PURPOSE 0x64 -//#define BMC_FAS_DEBUG +#define BMC_FAS_DEBUG #if defined(BMC_FAS_DEBUG) && !defined(BMC_DEBUG) #undef BMC_FAS_DEBUG @@ -125,6 +125,7 @@ class BMCFas { device.reset(); flags.on(BMC_FAS_FLAG_DEVICE_SEARCH); findDeviceTimer.start(3000); + BMC_PRINTLN("FAS Sync Version 1.0"); } // PUBLIC @@ -347,16 +348,11 @@ class BMCFas { controlBlockParameter(blockId, parameterId, 0, false); } - void setPreset(uint16_t value){ - sendControlChange(0, (value & 0x7F)); - sendProgramChange((value>>7) & 0x7F); - /* - BMCMidiMessage message; - prepSysEx(message, BMC_FAS_FUNC_ID_SET_PRESET_NUMBER); - message.appendToSysEx14Bits(value); - sendFractMidiSysEx(message); - */ + // Send CC#0 + sendControlChange(0, (value>>7) & 0x7F); + // Send Program Change + sendProgramChange((value & 0x7F)); } void presetScroll(bool t_up=true, bool t_endless=true, uint16_t t_min=0, uint16_t t_max=7){ if(!connected()){ @@ -371,8 +367,6 @@ class BMCFas { } - - private: // send the message that will trigger a response void sendDeviceSearch(){ @@ -574,6 +568,7 @@ class BMCFas { uint8_t blockId = (block>>24) & 0xFF; #ifdef BMC_FAS_DEBUG + BMC_PRINTLN("--> Received Blocks"); uint8_t bypassCC = (block>>8) & 0x7F; uint8_t xyCC = (block>>16) & 0x7F; if(blockId>=100 && blockId<=170){ @@ -593,9 +588,6 @@ class BMCFas { if(flags.toggleIfTrue(BMC_FAS_FLAG_SYNC_EXPECTING_BLOCKS)){ resyncTimer.start(BMC_FAS_RESYNC_QUEUE_TIMEOUT); } -#ifdef BMC_FAS_DEBUG - BMC_PRINTLN("--> Received Blocks"); -#endif } // received the current scene number void receivedSceneNumber(BMCMidiMessage& message){ diff --git a/src/hardware/BMC-Led.h b/src/hardware/BMC-Led.h index 8f10166..70667f3 100644 --- a/src/hardware/BMC-Led.h +++ b/src/hardware/BMC-Led.h @@ -33,8 +33,10 @@ #define BMC_FLAG_LED_TEMP_BLINK 4 #define BMC_FLAG_LED_IS_PWM 5 #define BMC_FLAG_LED_USE_OFF_VALUE 6 - - +// flag 7 available +#define BMC_FLAG_LED_MUX 8 +#define BMC_FLAG_LED_MUX_VALUE 9 +#define BMC_FLAG_LED_MUX_TESTING 10 class BMCLed { public: @@ -48,7 +50,6 @@ class BMCLed { // the BMC-Pins.h object will return 255 if the pot doesn't have a pin defined // this method will only work the first time it's called void begin(uint8_t t_pin){ - // if(pin!=255){ return; } @@ -59,6 +60,32 @@ class BMCLed { ); BMC_HALT(); } +#if BMC_MAX_MUX_OUT > 0 + // all mux pins start with pin number 64, that includes MUX_IN MUX_IN_ANALOG + // BMC will group them in this order MUX_IN then MUX_IN_ANALOG + // so if you have 10 MUX_IN pins then pins 64 to 73 are MUX_IN pins + // then MUX_IN_ANALOG pins start at pin 74 and so on + // so we want to make sure this pot was set to a MUX_IN_ANALOG + if(t_pin>=64){ + if(BMCBuildData::isMuxOutPin(t_pin)){ + flags.on(BMC_FLAG_LED_MUX); + pin = t_pin; + reset(); + #if !defined(BMC_NO_LED_TEST_AT_LAUNCH) + test(); + #endif + blinker.start(BMC_LED_BLINK_TIMEOUT); + return; + } else { + BMC_ERROR( + "Mux Pin:", t_pin, + "Can NOT be used with Leds as it is NOT a Mux Out Pin" + ); + BMC_HALT(); + } + } +#endif + if(!BMCBuildData::isDigitalPin(t_pin) && !BMCBuildData::isPwmPin(t_pin)){ BMC_ERROR( "PIN:", t_pin, @@ -86,6 +113,26 @@ class BMCLed { blinker.start(BMC_LED_BLINK_TIMEOUT); } + uint8_t getPin(){ + return pin; + } + +#if BMC_MAX_MUX_OUT > 0 + uint8_t getMuxPin(){ +#if BMC_MAX_MUX_OUT > 0 + if(flags.read(BMC_FLAG_LED_MUX)){ + return pin-64; + } +#endif + return pin; + } + bool getMuxState(){ + return flags.read(BMC_FLAG_LED_MUX_VALUE); + } + bool muxTesting(){ + return flags.toggleIfTrue(BMC_FLAG_LED_MUX_TESTING); + } +#endif void overrideState(bool t_value){ writeToPin(t_value); } @@ -104,6 +151,12 @@ class BMCLed { // at startup or if the editor is triggering a test of the LED // the LED will return to it's state before the test began void test(){ +#if BMC_MAX_MUX_OUT > 0 + if(flags.read(BMC_FLAG_LED_MUX)){ + flags.on(BMC_FLAG_LED_MUX_TESTING); + return; + } +#endif bool state = flags.read(BMC_FLAG_LED_STATE); for(uint8_t i=0;i<3;i++){ writeToPin(!state); @@ -233,7 +286,11 @@ class BMCLed { } private: uint8_t pin = 255; +#if BMC_MAX_MUX_OUT == 0 BMCFlags flags; +#else + BMCFlags flags; +#endif // endeless timer used for blinking the LED BMCEndlessTimer blinker; // temporary blinker @@ -251,7 +308,12 @@ class BMCLed { bool userPwmOffValue = flags.read(BMC_FLAG_LED_USE_OFF_VALUE); bool blinkerState = flags.read(BMC_FLAG_LED_BLINKER_STATE); - flags.reset(); + #if BMC_MAX_MUX_OUT == 0 + flags.reset(); + #else + flags.reset((1 << BMC_FLAG_LED_MUX)); + #endif + flags.write(BMC_FLAG_LED_IS_PWM, isPWM); flags.write(BMC_FLAG_LED_USE_OFF_VALUE, userPwmOffValue); flags.write(BMC_FLAG_LED_BLINKER_STATE, blinkerState); @@ -261,10 +323,17 @@ class BMCLed { // turn the LED off writeToPin(false); } - FASTRUN void writeToPin(bool t_value){ + void writeToPin(bool t_value){ #if defined(BMC_REVERSE_LED_POLARITY) t_value = !t_value; #endif + +#if BMC_MAX_MUX_OUT > 0 + if(flags.read(BMC_FLAG_LED_MUX)){ + flags.write(BMC_FLAG_LED_MUX_VALUE, t_value); + return; + } +#endif if(isPwmCapable()){ if(flags.read(BMC_FLAG_LED_USE_OFF_VALUE)){ analogWrite(pin, (t_value ? BMC_LED_PWM_MAX_VALUE : BMC_LED_PWM_DIM_VALUE)); diff --git a/src/mux/BMC-Mux.h b/src/mux/BMC-Mux.h new file mode 100644 index 0000000..0788319 --- /dev/null +++ b/src/mux/BMC-Mux.h @@ -0,0 +1,139 @@ +/* + See https://www.RoxXxtar.com/bmc for more details + Copyright (c) 2020 RoxXxtar.com + Licensed under the MIT license. + See LICENSE file in the project root for full license information. +*/ +#ifndef BMC_MUX_H +#define BMC_MUX_H + +#include "utility/BMC-Def.h" + +#if defined(BMC_MUX_AVAILABLE) + +#if BMC_MAX_MUX_GPIO > 0 + #include "mux/BMC-MuxGPIO.h" +#endif + +#if BMC_MAX_MUX_IN > 0 + #include "mux/BMC-MuxIn.h" +#endif + +#if BMC_MAX_MUX_OUT > 0 + #include "mux/BMC-MuxOut.h" +#endif + +#if BMC_MAX_MUX_IN_ANALOG > 0 + #include "mux/BMC-MuxInAnalog.h" +#endif + +class BMCMux { +private: +#if BMC_MAX_MUX_GPIO > 0 + BMCMuxGPIO muxGPIO; +#endif +#if BMC_MAX_MUX_IN > 0 + BMCMuxIn muxIn; +#endif +#if BMC_MAX_MUX_OUT > 0 + BMCMuxOut muxOut; +#endif +#if BMC_MAX_MUX_IN_ANALOG > 0 + BMCMuxInAnalog muxInAnalog; +#endif +public: + BMCMux(){ + + } + void begin(){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.begin(); +#endif +#if BMC_MAX_MUX_IN > 0 + muxIn.begin(); +#endif +#if BMC_MAX_MUX_OUT > 0 + muxOut.begin(); +#endif +#if BMC_MAX_MUX_IN_ANALOG > 0 + muxInAnalog.begin(); +#endif + } + // update the muxes + void update(){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.update(); +#endif +#if BMC_MAX_MUX_IN > 0 + muxIn.update(); +#endif +#if BMC_MAX_MUX_OUT > 0 + muxOut.update(); +#endif +#if BMC_MAX_MUX_IN_ANALOG > 0 + muxInAnalog.update(); +#endif + } + + // digitalRead equivalent + bool readDigital(uint8_t n){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.readPin(n); +#elif BMC_MAX_MUX_IN > 0 + return muxIn.getPinValue(n); +#else + return 0; +#endif + } + // digitalWrite equivalent + void writeDigital(uint8_t n, bool on){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.writePin(n, on); +#elif BMC_MAX_MUX_OUT > 0 + muxOut.setPinValue(n, on); +#endif + } + + // when using custom MUX + void setDigitalValue(uint8_t t_pin, bool t_value){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.setPinValue(t_pin, t_value); +#elif BMC_MAX_MUX_IN > 0 + muxIn.setPinValues(t_pin, t_value); +#endif + } + bool getDigitalValue(uint8_t t_pin){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.getPinValue(t_pin); +#elif BMC_MAX_MUX_OUT > 0 + return muxOut.getPinValue(t_pin); +#else + return 0; +#endif + } + + void testDigital(uint8_t n){ +#if BMC_MAX_MUX_GPIO > 0 + muxGPIO.test(n); +#elif BMC_MAX_MUX_OUT > 0 + muxOut.test(n); +#endif + } + + // read an analog mux input pin + uint16_t readAnalog(uint8_t n){ +#if BMC_MAX_MUX_IN_ANALOG > 0 + return muxInAnalog.getPinValue(n); +#else + return 0; +#endif + } + // read an analog mux input pin + void setAnalogValue(uint8_t n, uint16_t t_value){ +#if BMC_MAX_MUX_IN_ANALOG > 0 + muxInAnalog.setPinValue(n, t_value); +#endif + } +}; +#endif +#endif diff --git a/src/mux/BMC-MuxGPIO.h b/src/mux/BMC-MuxGPIO.h new file mode 100644 index 0000000..8a41c8c --- /dev/null +++ b/src/mux/BMC-MuxGPIO.h @@ -0,0 +1,86 @@ +/* + See https://www.RoxXxtar.com/bmc for more details + Copyright (c) 2020 RoxXxtar.com + Licensed under the MIT license. + See LICENSE file in the project root for full license information. + + Work in progress +*/ +#ifndef BMC_MUX_GPIO_H +#define BMC_MUX_GPIO_H + +#include "utility/BMC-Def.h" + +#if BMC_MAX_MUX_GPIO > 0 + +#if BMC_MUX_GPIO_CHIPSET == BMC_MUX_GPIO_CHIPSET_MCP + #include "mux/BMC-MuxGpioMcp.h" +#endif + +#if BMC_MAX_MUX_GPIO > 32 + #define BMC_MUX_GPIO_COUNT 2 +#else + #define BMC_MUX_GPIO_COUNT 1 +#endif + +class BMCMuxGpio { +private: +#if BMC_MUX_GPIO_CHIPSET == BMC_MUX_GPIO_CHIPSET_OTHER + uint32_t states[BMC_MUX_GPIO_COUNT]; +#elif BMC_MUX_GPIO_CHIPSET == BMC_MUX_GPIO_CHIPSET_MCP + BMCMuxGpioMCP mux; +#endif + + uint8_t parsePinNumber(uint8_t t_pin){ + if(t_pin>=64){ + t_pin -= 64; + } + return constrain(t_pin, 0, (BMC_MAX_MUX_GPIO-1)); + } +public: + BMCMuxGpio(){ + + } + void begin(){ + BMC_PRINTLN(""); + BMC_PRINTLN("BMCMuxGpio::begin()"); + +#if BMC_MUX_GPIO_CHIPSET == BMC_MUX_GPIO_CHIPSET_OTHER + BMC_PRINTLN(""); + BMC_PRINTLN("BMC MUX OUT set to use a chip other than the MCP23017."); + BMC_PRINTLN(""); + for(uint8_t i=0;i 0 && BMC_MUX_GPIO_CHIPSET == BMC_MUX_GPIO_CHIPSET_MCP2301X + +// pin mode +#define BMC_MCP2301X_IO_MODE 0x00 +// Interrupts +#define BMC_MCP2301X_INT_ENABLE 0x04 +#define BMC_MCP2301X_DEFAULT_VALUE 0x06 +#define BMC_MCP2301X_INT_CONFIG 0x08 +#define BMC_MCP2301X_IO_CONFIG 0x0A +// pullups +#define BMC_MCP2301X_PULLUP 0x0C +// read +#define BMC_MCP2301X_IO 0x12 + +#include + +class BMCMuxGpioMCP { +public: + BMCMuxGpioMCP(){} + void begin(){ + BMC_PRINTLN("Mux GPIO using MCP23017/MCP23018"); + Wire.begin(); + Wire.setClock(BMC_I2C_FREQ); + setupPins(BMC_MUX_GPIO_ADDR_1); + + #if defined(BMC_MUX_GPIO_ADDR_2) && BMC_MAX_MUX_GPIO > 16 + setupPins(BMC_MUX_GPIO_ADDR_2); + + #if defined(BMC_MUX_GPIO_ADDR_3) && BMC_MAX_MUX_GPIO > 32 + setupPins(BMC_MUX_GPIO_ADDR_3); + + #if defined(BMC_MUX_GPIO_ADDR_4) && BMC_MAX_MUX_GPIO > 48 + setupPins(BMC_MUX_GPIO_ADDR_4); + #endif + #endif + #endif + } + void setupPins(uint8_t addr){ + // set all pins of first MCP2301X as outputs + // bit set to 1 is input, 0 is output + writeData(addr, BMC_MCP2301X_IO_MODE, 0x00); + writeData(addr, BMC_MCP2301X_IO_MODE+1, 0x00); + + // set all pins of first MCP2301X to use built-in pullup + // if you have external pullup resistors then set 0xFF to 0 on both + // if bit is 0 internal pullup is off, 1 internal pullup is on + writeData(addr, BMC_MCP2301X_PULLUP, 0x00); + writeData(addr, BMC_MCP2301X_PULLUP+1, 0x00); + } + + void update(){ + readAllPins(); + } + + + uint32_t read1To32(){ + return states; + } +#if BMC_MAX_MUX_GPIO > 32 + uint32_t read33To64(){ + return states2; + } +#endif + +private: + uint32_t states = 0; +#if BMC_MAX_MUX_GPIO > 32 + uint32_t states2 = 0; +#endif + void readAllPins(){ + states = readPins(BMC_MUX_GPIO_ADDR_1); + + #if defined(BMC_MUX_GPIO_ADDR_2) && BMC_MAX_MUX_GPIO > 16 + states = (readPins(BMC_MUX_GPIO_ADDR_2)<<16) | states; + #endif + + #if defined(BMC_MUX_GPIO_ADDR_3) && BMC_MAX_MUX_GPIO > 32 + states2 = readPins(BMC_MUX_GPIO_ADDR_3); + + #if defined(BMC_MUX_GPIO_ADDR_4) && BMC_MAX_MUX_GPIO > 48 + states2 = (readPins(BMC_MUX_GPIO_ADDR_4)<<16) | states2; + #endif + #endif + } + void writeData(uint8_t t_chipAddr, uint8_t t_reg, uint8_t t_value){ + Wire.beginTransmission(t_chipAddr); + Wire.write((uint8_t) t_reg); + Wire.write((uint8_t) t_value); + Wire.endTransmission(); + } + uint8_t readData(uint8_t t_chipAddr, uint8_t t_reg){ + Wire.beginTransmission(t_chipAddr); + Wire.write((uint8_t) t_reg); + Wire.endTransmission(); + + Wire.requestFrom((int) t_chipAddr, (int) 1); + return Wire.read(); + } + uint16_t readPins(uint8_t t_chipAddr){ + Wire.beginTransmission(t_chipAddr); + Wire.write((uint8_t) BMC_MCP2301X_IO); + Wire.endTransmission(); + // request 2 bytes + // always read both ports A and B + Wire.requestFrom((int) t_chipAddr, (int) 2); + uint8_t a = Wire.read(); + uint8_t b = Wire.read(); + return (uint16_t) ((b << 8) | a); + } + +}; +#endif +#endif diff --git a/src/hardware/BMC-MuxIn.h b/src/mux/BMC-MuxIn.h similarity index 83% rename from src/hardware/BMC-MuxIn.h rename to src/mux/BMC-MuxIn.h index 34701f5..90aa0db 100644 --- a/src/hardware/BMC-MuxIn.h +++ b/src/mux/BMC-MuxIn.h @@ -12,22 +12,25 @@ #if BMC_MAX_MUX_IN > 0 #if BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_MCP2301X - #include "hardware/BMC-MuxInMCP2301x.h" + #include "mux/BMC-MuxInMCP2301x.h" #elif BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_74HC165 - #include "hardware/BMC-MuxIn74HC165.h" + #include "mux/BMC-MuxIn74HC165.h" #endif #ifndef BMC_MUX_IN_DELAY_MICROS #define BMC_MUX_IN_DELAY_MICROS 500 #endif +#if BMC_MAX_MUX_IN > 32 + #define BMC_MAX_MUX_IN_ARR 2 +#else + #define BMC_MAX_MUX_IN_ARR 1 +#endif + class BMCMuxIn { private: #if BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_OTHER - uint32_t states = 0; - #if BMC_MAX_MUX_IN > 32 - uint32_t states2 = 0; - #endif + uint32_t states[BMC_MAX_MUX_IN_ARR]; #elif BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_MCP2301X BMCMuxInMCP2301x mux; #elif BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_74HC165 @@ -57,7 +60,10 @@ class BMCMuxIn { BMC_PRINTLN("BMC MUX IN set to use a chip other than the MCP23017, MCP23018 or 74HC165."); BMC_PRINTLN("You must read the chip with your sketch and use bmc.setMuxInValues() to set the states of the pins used."); BMC_PRINTLN(""); - states = 0xFFFFFFFF; + for(uint8_t i=0;i 32 if(t_pin>=32){ - return bitRead(states2, (t_pin-32)); + return bitRead(states[1], (t_pin-32)); } #endif - return bitRead(states, t_pin); + return bitRead(states[0], t_pin); #else #if BMC_MAX_MUX_IN > 32 @@ -109,13 +115,13 @@ class BMCMuxIn { // for custom chip only void setPinValues1To32(uint32_t t_states){ #if BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_OTHER - states = t_states; + states[0] = t_states; #endif } // for custom chip only void setPinValues33To64(uint32_t t_states){ #if BMC_MUX_IN_CHIPSET == BMC_MUX_IN_CHIPSET_OTHER && BMC_MAX_MUX_IN > 32 - states2 = t_states; + states[1] = t_states; #endif } @@ -126,11 +132,10 @@ class BMCMuxIn { #if BMC_MAX_MUX_IN > 32 if(t_pin>=32){ - return bitRead(states2, (t_pin-32)); + return bitRead(states[1], (t_pin-32)); } #endif - - bitWrite(states, t_pin, t_value); + bitWrite(states[0], t_pin, t_value); } #endif } diff --git a/src/hardware/BMC-MuxIn74HC165.h b/src/mux/BMC-MuxIn74HC165.h similarity index 89% rename from src/hardware/BMC-MuxIn74HC165.h rename to src/mux/BMC-MuxIn74HC165.h index e19c73e..bc33abd 100644 --- a/src/hardware/BMC-MuxIn74HC165.h +++ b/src/mux/BMC-MuxIn74HC165.h @@ -40,10 +40,7 @@ class BMCMuxIn74HC165 { private: - uint32_t states = 0; -#if BMC_MAX_MUX_IN > 32 - uint32_t states2 = 0; -#endif + uint32_t states[(BMC_MAX_MUX_IN>32)?2:1]; public: BMCMuxIn74HC165(){} @@ -55,6 +52,7 @@ class BMCMuxIn74HC165 { digitalWriteFast(BMC_MUX_IN_74HC165_CLOCK, LOW); digitalWriteFast(BMC_MUX_IN_74HC165_LOAD, HIGH); } + void update(){ // set load pin digitalWriteFast(BMC_MUX_IN_74HC165_LOAD, LOW); @@ -66,16 +64,15 @@ class BMCMuxIn74HC165 { for(uint8_t mux = 0, n=total/8; mux < n; mux++){ for(int i = 7, bitN = ((mux + 1) * 8); i >= 0; i--, bitN--){ uint8_t bit = digitalReadFast(BMC_MUX_IN_74HC165_DATA); - #if BMC_MAX_MUX_IN > 32 if(bitN>=32){ // states2 starting with bit 0 so remove 33 from the value - bitWrite(states2, bitN-33, bit); + bitWrite(states[1], bitN-33, bit); } else { - bitWrite(states, bitN-1, bit); + bitWrite(states[0], bitN-1, bit); } #else - bitWrite(states, bitN-1, bit); + bitWrite(states[0], bitN-1, bit); #endif digitalWriteFast(BMC_MUX_IN_74HC165_CLOCK, HIGH); @@ -84,28 +81,25 @@ class BMCMuxIn74HC165 { } } } + uint32_t read1To32(){ - return states; + return states[0]; } + #if BMC_MAX_MUX_IN > 32 uint32_t read33To64(){ - return states2; + return states[1]; } #endif - #if BMC_MAX_MUX_IN > 32 - uint32_t read(uint8_t n=0){ - return (n > 0) ? states2 : states; + return states[(n>0)?1:0]; } - #else - uint32_t read(){ - return states; + return states[0]; } - #endif }; #endif diff --git a/src/hardware/BMC-MuxInAnalog.h b/src/mux/BMC-MuxInAnalog.h similarity index 96% rename from src/hardware/BMC-MuxInAnalog.h rename to src/mux/BMC-MuxInAnalog.h index de40af1..ac4afd6 100644 --- a/src/hardware/BMC-MuxInAnalog.h +++ b/src/mux/BMC-MuxInAnalog.h @@ -15,7 +15,7 @@ #if BMC_MAX_MUX_IN_ANALOG > 0 #if (BMC_MUX_IN_ANALOG_CHIPSET == BMC_MUX_IN_ANALOG_CHIPSET_74HC4067 || BMC_MUX_IN_ANALOG_CHIPSET == BMC_MUX_IN_ANALOG_CHIPSET_74HC4051) - #include "hardware/BMC-MuxInAnalog74HC40XX.h" + #include "mux/BMC-MuxInAnalog74HC40XX.h" #endif class BMCMuxInAnalog { @@ -27,7 +27,7 @@ class BMCMuxInAnalog { #endif uint8_t parsePinNumber(uint8_t t_pin){ if(t_pin>=64){ - t_pin -= (64+BMC_MAX_MUX_IN); + t_pin -= (64+BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT); } return constrain(t_pin, 0, (BMC_MAX_MUX_IN_ANALOG-1)); } @@ -72,14 +72,14 @@ class BMCMuxInAnalog { return 0; } -#if BMC_MUX_IN_ANALOG_CHIPSET == BMC_MUX_IN_ANALOG_CHIPSET_OTHER void setPinValue(uint8_t n, uint16_t t_value){ +#if BMC_MUX_IN_ANALOG_CHIPSET == BMC_MUX_IN_ANALOG_CHIPSET_OTHER n = parsePinNumber(n); if(n < BMC_MAX_MUX_IN_ANALOG){ values[n] = t_value; } - } #endif + } }; #endif diff --git a/src/hardware/BMC-MuxInAnalog74HC40XX.h b/src/mux/BMC-MuxInAnalog74HC40XX.h similarity index 100% rename from src/hardware/BMC-MuxInAnalog74HC40XX.h rename to src/mux/BMC-MuxInAnalog74HC40XX.h diff --git a/src/hardware/BMC-MuxInMCP2301x.h b/src/mux/BMC-MuxInMCP2301x.h similarity index 100% rename from src/hardware/BMC-MuxInMCP2301x.h rename to src/mux/BMC-MuxInMCP2301x.h diff --git a/src/mux/BMC-MuxOut.h b/src/mux/BMC-MuxOut.h new file mode 100644 index 0000000..f843c4e --- /dev/null +++ b/src/mux/BMC-MuxOut.h @@ -0,0 +1,131 @@ +/* + See https://www.RoxXxtar.com/bmc for more details + Copyright (c) 2020 RoxXxtar.com + Licensed under the MIT license. + See LICENSE file in the project root for full license information. +*/ +#ifndef BMC_MUX_OUT_H +#define BMC_MUX_OUT_H + +#include "utility/BMC-Def.h" + +#if BMC_MAX_MUX_OUT > 0 + +#if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_74HC595 + #include "mux/BMC-MuxOut74HC595.h" +#endif + +#ifndef BMC_MUX_OUT_DELAY_MICROS + #define BMC_MUX_OUT_DELAY_MICROS 500 +#endif + +class BMCMuxOut { +private: + +#if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_OTHER + #if BMC_MAX_MUX_OUT > 32 + uint32_t states[2]; + #else + uint32_t states[1]; + #endif +#elif BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_74HC595 + BMCMuxOut74HC595 mux; +#endif + + uint8_t parsePinNumber(uint8_t t_pin){ + if(t_pin>=64){ + t_pin -= (64+BMC_MAX_MUX_IN); + } + return constrain(t_pin, 0, (BMC_MAX_MUX_OUT-1)); + } +public: + BMCMuxOut(){ + + } + void begin(){ + BMC_PRINTLN(""); + BMC_PRINTLN("BMCMuxOut::begin()"); + +#if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_OTHER + BMC_PRINTLN(""); + BMC_PRINTLN("BMC MUX OUT set to use a chip other than the 74HC595."); + BMC_PRINTLN(""); + states[0] = 0xFFFFFFFF; + #if BMC_MAX_MUX_OUT > 32 + states[1] = 0xFFFFFFFF; + #endif +#else + mux.begin(); + delay(50); + mux.update(); +#endif + BMC_PRINTLN(""); + } + + void update(){ +#if BMC_MUX_OUT_CHIPSET != BMC_MUX_OUT_CHIPSET_OTHER + mux.update(); +#endif + } + void test(uint8_t t_pin){ +#if BMC_MUX_OUT_CHIPSET != BMC_MUX_OUT_CHIPSET_OTHER + mux.test(t_pin); +#endif + } + void setPinValue(uint8_t t_pin, bool on){ + if(t_pin>=64){ + t_pin -= (64+BMC_MAX_MUX_IN); + } +#if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_OTHER + uint8_t index = 0; + #if BMC_MAX_MUX_OUT > 32 + if(t_pin>=32){ + index = 1; + t_pin -= 32; + } + #endif + bitWrite(states[index], t_pin, on); +#elif BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_74HC595 + mux.writePin(t_pin, on); +#endif + } + void setPinValues1To32(uint32_t t_states){ +#if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_OTHER + states[0] = t_states; +#elif BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_74HC595 + //mux.write1To32(t_states); +#endif + } + + void setPinValues33To64(uint32_t t_states){ +#if BMC_MAX_MUX_OUT > 32 + #if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_OTHER + states[1] = t_states; + #elif BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_74HC595 + mux.write33To64(t_states); + #endif +#endif + } + + + bool getPinValue(uint8_t t_pin){ + t_pin = parsePinNumber(t_pin); + +#if BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_OTHER + #if BMC_MAX_MUX_OUT > 32 + if(t_pin>=32){ + return bitRead(states[1], (t_pin-32)); + } + #endif + return bitRead(states[0], t_pin); +#else + + return mux.getPinState(t_pin); +#endif + } + + + +}; +#endif +#endif diff --git a/src/mux/BMC-MuxOut74HC595.h b/src/mux/BMC-MuxOut74HC595.h new file mode 100644 index 0000000..2a78fea --- /dev/null +++ b/src/mux/BMC-MuxOut74HC595.h @@ -0,0 +1,157 @@ +/* + See https://www.RoxXxtar.com/bmc for more details + Copyright (c) 2020 RoxXxtar.com + Licensed under the MIT license. + See LICENSE file in the project root for full license information. + + Control up to 4 74HC595, these are 8 pin multiplexers and they must have a + pullup resistor on each pin, 10k should work +*/ +#ifndef BMC_MUX_OUT_74HC595_H +#define BMC_MUX_OUT_74HC595_H + +#include "utility/BMC-Def.h" + +#if BMC_MAX_MUX_OUT > 0 && BMC_MUX_OUT_CHIPSET == BMC_MUX_OUT_CHIPSET_74HC595 + +#ifndef BMC_MUX_OUT_74HC595_CLOCK + #error "BMC_MUX_OUT_74HC595_CLOCK was NOT defined" +#elif BMC_MUX_OUT_74HC595_CLOCK >= 64 + #error "BMC_MUX_OUT_74HC595_CLOCK is not a valid pin" +#endif + +#ifndef BMC_MUX_OUT_74HC595_LATCH + #error "BMC_MUX_OUT_74HC595_LATCH was NOT defined" +#elif BMC_MUX_OUT_74HC595_LATCH >= 64 + #error "BMC_MUX_OUT_74HC595_LATCH is not a valid pin" +#endif + +#ifndef BMC_MUX_OUT_74HC595_DATA + #error "BMC_MUX_OUT_74HC595_DATA was NOT defined" +#elif BMC_MUX_OUT_74HC595_DATA >= 64 + #error "BMC_MUX_OUT_74HC595_DATA is not a valid pin" +#endif + +#define BMC_MUX_OUT_74HC595_DELAY 0 + +#define BMC_MUX_OUT_74HC595_FLAG_CHANGED 0 + +#if BMC_MAX_MUX_OUT > 32 + #define BMC_74HC595_MUX_ARR_LEN 2 +#else + #define BMC_74HC595_MUX_ARR_LEN 1 +#endif + +#define BMC_74HC595_MUX_COUNT (ceil(BMC_MAX_MUX_OUT/8)) + +class BMCMuxOut74HC595 { +private: + BMCFlags flags; + uint8_t states[BMC_74HC595_MUX_ARR_LEN]; + + void _updateMuxReverse(){ + for(int mux = BMC_74HC595_MUX_COUNT-1; mux >= 0; mux--){ + for(uint8_t mask=0x80; mask; mask >>= 1){ + _writeToMux(mux, mask); + } + } + } + void _updateMux(){ + for(int mux = 0; mux < BMC_74HC595_MUX_COUNT; mux++){ + for(uint8_t mask=0x80; mask; mask >>= 1){ + _writeToMux(mux, mask); + } + } + } + void _writeToMux(uint8_t mux, uint8_t mask){ + digitalWriteFast(BMC_MUX_OUT_74HC595_DATA, (states[mux] & mask)); + digitalWriteFast(BMC_MUX_OUT_74HC595_CLOCK, HIGH); + #if BMC_MUX_OUT_74HC595_DELAY > 0 + delayMicroseconds(BMC_MUX_OUT_74HC595_DELAY); + #endif + digitalWriteFast(BMC_MUX_OUT_74HC595_CLOCK, LOW); + digitalWriteFast(BMC_MUX_OUT_74HC595_DATA, LOW); + } + +public: + BMCMuxOut74HC595(){} + void begin(){ + BMC_PRINTLN("BMCMuxOut74HC595::begin()"); + pinMode(BMC_MUX_OUT_74HC595_CLOCK, OUTPUT); + pinMode(BMC_MUX_OUT_74HC595_LATCH, OUTPUT); + pinMode(BMC_MUX_OUT_74HC595_DATA, OUTPUT); + +#ifdef BMC_MUX_OUT_74HC595_PWM + #if BMC_MUX_OUT_74HC595_PWM < 64 + if(!BMCBuildData::isPwmPin(BMC_MUX_OUT_74HC595_PWM)){ + BMC_ERROR( + "PIN:", BMC_MUX_OUT_74HC595_PWM, + "Can NOT be used with to for 74HC595 PWM as it's not PWM capable." + ); + BMC_HALT(); + } + pinMode(BMC_MUX_OUT_74HC595_PWM, OUTPUT); + uint8_t maxBrightness = map(BMC_LED_PWM_MAX_VALUE, 0, 255, 255, 0); + analogWrite(BMC_MUX_OUT_74HC595_PWM, maxBrightness); + #endif +#endif + + digitalWriteFast(BMC_MUX_OUT_74HC595_CLOCK, LOW); + digitalWriteFast(BMC_MUX_OUT_74HC595_LATCH, HIGH); + + flags.on(BMC_MUX_OUT_74HC595_FLAG_CHANGED); + } + void update(){ + if(flags.toggleIfTrue(BMC_MUX_OUT_74HC595_FLAG_CHANGED)){ + // set load pin + digitalWriteFast(BMC_MUX_OUT_74HC595_LATCH, LOW); + digitalWriteFast(BMC_MUX_OUT_74HC595_DATA, LOW); + if(BMC_74HC595_MUX_COUNT>1){ + _updateMuxReverse(); + } else { + _updateMux(); + } + digitalWriteFast(BMC_MUX_OUT_74HC595_LATCH, HIGH); + } + } + void test(uint8_t t_pin){ + // hold the current state + bool currentState = getPinState(t_pin); + + for(uint8_t i=0;i<3;i++){ + // now tell the update function that a change has happened + //flags.on(BMC_MUX_OUT_74HC595_FLAG_CHANGED); + writePin(t_pin, !currentState); + update(); + delay(BMC_MAX_LED_TEST_DELAY); + + //flags.on(BMC_MUX_OUT_74HC595_FLAG_CHANGED); + writePin(t_pin, currentState); + update(); + delay(BMC_MAX_LED_TEST_DELAY); + } + } + // expects a zero-index value + void writePin(uint8_t t_pin, bool on){ + uint8_t muxIndex = (uint8_t)floor(t_pin/8.0); + if(muxIndex>0){ + t_pin -= (muxIndex*8); + } + if(bitRead(states[muxIndex], t_pin) != on){ + flags.on(BMC_MUX_OUT_74HC595_FLAG_CHANGED); + } + bitWrite(states[muxIndex], t_pin, on); + } + // expects a zero-index value + bool getPinState(uint8_t t_pin){ + uint8_t muxIndex = (uint8_t)floor(t_pin/8.0); + if(muxIndex>0){ + t_pin -= (muxIndex*8); + } + return bitRead(states[muxIndex], t_pin); + } + + +}; +#endif +#endif diff --git a/src/utility/BMC-BuildData.h b/src/utility/BMC-BuildData.h index 6776ebb..1be3950 100644 --- a/src/utility/BMC-BuildData.h +++ b/src/utility/BMC-BuildData.h @@ -7506,16 +7506,31 @@ return false; } static bool isMuxInPin(uint8_t n){ -#if BMC_MAX_MUX_IN > 0 +#if BMC_MAX_MUX_GPIO > 0 + return isMuxGpioPin(n); +#elif BMC_MAX_MUX_IN > 0 return (n>=64 && n<(64+BMC_MAX_MUX_IN)); #endif return false; } +static bool isMuxOutPin(uint8_t n){ +#if BMC_MAX_MUX_GPIO > 0 + return isMuxGpioPin(n); +#elif BMC_MAX_MUX_OUT > 0 + return (n>=(64+BMC_MAX_MUX_IN) && n<(64+BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT)); +#endif + return false; +} static bool isMuxInAnalogPin(uint8_t n){ #if BMC_MAX_MUX_IN_ANALOG > 0 - return (n>=(64+BMC_MAX_MUX_IN) && n<(64+BMC_MAX_MUX_IN+BMC_MAX_MUX_IN_ANALOG)); + return (n>=(64+BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT) && n<(64+BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT+BMC_MAX_MUX_IN_ANALOG)); #endif return false; } -}; +static bool isMuxGpioPin(uint8_t n){ +#if BMC_MAX_MUX_GPIO > 0 + return (n >= 64 && n < BMC_MAX_MUX_GPIO); +#endif + return false; +}}; #endif diff --git a/src/utility/BMC-Callbacks.h b/src/utility/BMC-Callbacks.h index 34a5e3d..0829674 100644 --- a/src/utility/BMC-Callbacks.h +++ b/src/utility/BMC-Callbacks.h @@ -18,6 +18,8 @@ class BMCCallbacks { storeUpdated = 0; oneSecondPassed = 0; menuCommand = 0; + typerCommand = 0; + typerCustomCommand = 0; buttonDualPress = 0; buttonActivity = 0; @@ -108,8 +110,8 @@ class BMCCallbacks { void (*storeUpdated)(); void (*pageChanged)(uint8_t page); void (*menuCommand)(uint8_t t_command); - - + void (*typerCommand)(uint16_t t_value); + void (*typerCustomCommand)(uint16_t t_value); void (*buttonDualPress)(uint8_t btn1, uint8_t btn2); diff --git a/src/utility/BMC-ConfigCheck.h b/src/utility/BMC-ConfigCheck.h index 5a4c116..fef2ec5 100644 --- a/src/utility/BMC-ConfigCheck.h +++ b/src/utility/BMC-ConfigCheck.h @@ -76,6 +76,28 @@ #error "BMC supports up to 64 Mux In Pins" #endif + #ifndef BMC_MAX_MUX_OUT + #define BMC_MAX_MUX_OUT 0 + #endif + #if BMC_MAX_MUX_OUT > 64 + #error "BMC supports up to 64 Mux Out Pins" + #endif + + + #ifndef BMC_MAX_MUX_GPIO + #define BMC_MAX_MUX_GPIO 0 + #endif + #if BMC_MAX_MUX_GPIO > 64 + #error "BMC supports up to 64 Mux GPIO Pins" + #endif + + #if BMC_MAX_MUX_GPIO > 0 + #undef BMC_MAX_MUX_IN + #undef BMC_MAX_MUX_OUT + #define BMC_MAX_MUX_IN 0 + #define BMC_MAX_MUX_OUT 0 + #endif + #ifndef BMC_MAX_MUX_IN_ANALOG #define BMC_MAX_MUX_IN_ANALOG 0 #endif @@ -83,8 +105,12 @@ #error "BMC supports up to 127 Analog Mux Pins" #endif - #if (BMC_MAX_MUX_IN+BMC_MAX_MUX_IN_ANALOG)>127 - #error "BMC supports a maximum of 127 Mux Pins total, that inclues a sum of BMC_MAX_MUX_IN and BMC_MAX_MUX_IN_ANALOG" + #if (BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT)>64 + #error "BMC supports a maximum of 64 Mux Digital Pins, that inclues a sum of BMC_MAX_MUX_IN & BMC_MAX_MUX_OUT" + #endif + + #if (BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT+BMC_MAX_MUX_IN_ANALOG)>127 + #error "BMC supports a maximum of 127 Mux Pins total, that inclues a sum of BMC_MAX_MUX_IN, BMC_MAX_MUX_OUT & BMC_MAX_MUX_IN_ANALOG" #endif #if BMC_MAX_MUX_IN > 0 && (BMC_MAX_BUTTONS==0 && BMC_MAX_ENCODERS==0) @@ -92,6 +118,11 @@ #define BMC_MAX_MUX_IN 0 #endif + #if BMC_MAX_MUX_OUT > 0 && (BMC_MAX_LEDS==0 && BMC_MAX_GLOBAL_LEDS==0) + #undef BMC_MAX_MUX_OUT + #define BMC_MAX_MUX_OUT 0 + #endif + #if BMC_MAX_MUX_IN_ANALOG > 0 && BMC_MAX_POTS==0 #undef BMC_MAX_MUX_IN_ANALOG #define BMC_MAX_MUX_IN_ANALOG 0 @@ -105,9 +136,11 @@ #define BMC_MUX_IN_CHIPSET 0 #endif + #define BMC_TOTAL_MUX_PINS (BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT+BMC_MAX_MUX_IN_ANALOG) - - #define BMC_TOTAL_MUX_PINS (BMC_MAX_MUX_IN+BMC_MAX_MUX_IN_ANALOG) + #if (BMC_MAX_MUX_IN+BMC_MAX_MUX_OUT+BMC_MAX_MUX_IN_ANALOG) > 0 + #define BMC_MUX_AVAILABLE + #endif diff --git a/src/utility/BMC-Def.h b/src/utility/BMC-Def.h index 1ca0c41..276a366 100644 --- a/src/utility/BMC-Def.h +++ b/src/utility/BMC-Def.h @@ -277,6 +277,10 @@ #define BMC_MUX_IN_CHIPSET_MCP2301X 2 #define BMC_MUX_IN_CHIPSET_74HC165 3 +// Supported chipsets for Mux OUT +#define BMC_MUX_OUT_CHIPSET_OTHER 1 +#define BMC_MUX_OUT_CHIPSET_74HC595 2 + // Supported chipsets for Mux In Analog #define BMC_MUX_IN_ANALOG_CHIPSET_OTHER 1 #define BMC_MUX_IN_ANALOG_CHIPSET_74HC4067 2 @@ -905,6 +909,7 @@ #define BMC_BUTTON_EVENT_TYPE_SETLIST_SONG_SCROLL 48 #define BMC_BUTTON_EVENT_TYPE_PROGRAM_BANKING_SCROLL 49 #define BMC_BUTTON_EVENT_TYPE_PROGRAM_BANKING_TRIGGER 50 +#define BMC_BUTTON_EVENT_TYPE_TYPER_CMD 51 // id 51 to id 79 availabel #define BMC_BUTTON_EVENT_TYPE_FAS_COMMAND 80 #define BMC_BUTTON_EVENT_TYPE_FAS_PRESET 81 @@ -2039,6 +2044,7 @@ #include "utility/BMC-MidiControl.h" #include "utility/BMC-Timer.h" #include "utility/BMC-Flags.h" +#include "utility/BMC-Typer.h" #include "utility/BMC-Tools.h" #include "utility/BMC-Settings.h" #include "utility/BMC-BpmCalculator.h" diff --git a/src/utility/BMC-Flags.h b/src/utility/BMC-Flags.h index 540f29b..2e4d9c2 100644 --- a/src/utility/BMC-Flags.h +++ b/src/utility/BMC-Flags.h @@ -147,7 +147,7 @@ class BMCFlags { } } // reset all flags execpt the bit passed - void resetNotBit(uint8_t n){ + void resetNotBit(T n){ uint8_t tmp = 0; bitWrite(tmp, n, bitRead(flags, n)); flags = tmp; diff --git a/src/utility/BMC-Typer.h b/src/utility/BMC-Typer.h new file mode 100644 index 0000000..781d1e1 --- /dev/null +++ b/src/utility/BMC-Typer.h @@ -0,0 +1,88 @@ +/* + See https://www.RoxXxtar.com/bmc for more details + Copyright (c) 2020 RoxXxtar.com + Licensed under the MIT license. + See LICENSE file in the project root for full license information. +*/ +#ifndef BMC_TYPER_H +#define BMC_TYPER_H + +#include +#include "utility/BMC-Callbacks.h" + +#define BMC_TYPER_MODE 1 +#if !defined(BMC_TYPER_MODE) + #define BMC_TYPER_MODE 0 +#endif + +class BMCTyper { +private: + BMCFlags flags; + uint8_t vtCount = 0; + uint16_t vtValue = 0; + uint16_t output = 0; + BMCCallbacks& callback; + void buildOutput(){ +#if BMC_TYPER_MODE == 0 + output = (((vtValue>>0)&0x0F)*100) + (((vtValue>>4)&0x0F)*10) + ((vtValue>>1)&0x0F); +#else + output = (((vtValue>>8)&0x0F)*100) + (((vtValue>>4)&0x0F)*10) + ((vtValue>>0)&0x0F); +#endif + } +public: + BMCTyper(BMCCallbacks& cb):callback(cb){} + uint16_t getOutput(){ + return output; + } + uint8_t cmd(uint8_t value, uint8_t autoTrigger=0){ + if(value >= 10){ + // 10 is clear + // 11 is custom callback + // 12 is page + // 13 is preset + // 14 is fas preset + // 15 is fas scene + vtValue = 0; + vtCount = 0; + if(value==10){ + output = 0; + } + + if(value==11){ + if(callback.typerCustomCommand){ + callback.typerCustomCommand(output); + return value; + } + } + if(callback.typerCommand){ + callback.typerCommand(output); + } + // trigger display callback + return value; + } + if(vtCount >= 3){ + vtCount = 0; + vtValue = 0; + } + +#if BMC_TYPER_MODE == 0 + vtValue |= (value << (vtCount*4)); +#else + // shift the value to the left + vtValue = (vtValue << 4) | (value & 0x0F); +#endif + + buildOutput(); + vtCount++; + + if(vtCount>=3 && autoTrigger>0){ + return cmd(autoTrigger+10, 0); + } + // trigger display callback + if(callback.typerCommand){ + callback.typerCommand(output); + } + return 0; + } +}; +#endif