diff --git a/bombatuino-pro.ino b/bombatuino-pro.ino new file mode 100644 index 0000000..af85cce --- /dev/null +++ b/bombatuino-pro.ino @@ -0,0 +1,95 @@ +#include + +#include +#include + +#include "MIDIUSB.h" + +#define debug true + +//MCP23017 I2C addresses 0,1,2,3 and 4 +INPUT_MCP23017 input_MCP23017_0; +INPUT_MCP23017 input_MCP23017_1; +INPUT_MCP23017 input_MCP23017_2; +INPUT_MCP23017 input_MCP23017_3; +INPUT_MCP23017 input_MCP23017_4; + +//three 74HC4051 on analog pins A1,A2,A3; select on digital pins 7,8,9 +INPUT_74HC4051 input_4051_A1; +INPUT_74HC4051 input_4051_A2; +INPUT_74HC4051 input_4051_A3; + +int channel = 0; +int velocity = 120; +const uint8_t NO_PINS = 0b00000000; + +void setup() { +#ifdef debug + Serial.begin(9600); +#endif + //initialize MCP23017s + input_MCP23017_0.begin(0,digitalCallback); + input_MCP23017_1.begin(1,digitalCallback); + input_MCP23017_2.begin(2,digitalCallback); + input_MCP23017_3.begin(3,digitalCallback); + input_MCP23017_4.begin(4,digitalCallback); + //initialize 74HC4051s + input_4051_A1.begin(A1,7,8,9,analogCallback); + input_4051_A1.setPins(0b00001000); + input_4051_A2.begin(A2,7,8,9,analogCallback); + input_4051_A2.setPins(NO_PINS); + input_4051_A3.begin(A3,7,8,9,analogCallback); + input_4051_A3.setPins(NO_PINS); + + +} + +void loop() { + //loop MCP23017s for callbacks + input_MCP23017_0.loop(); + input_MCP23017_1.loop(); + input_MCP23017_2.loop(); + input_MCP23017_3.loop(); + input_MCP23017_4.loop(); + //loop 74HC4051s for callback + input_4051_A1.loop(); + input_4051_A2.loop(); + input_4051_A3.loop(); + MidiUSB.flush(); +} + + +//callback for analog, sends CC message with unique controller id +void analogCallback(int id, int pin, int value) { +#ifdef debug + Serial.print("analog"); + Serial.print("\tid\t"); + Serial.print(id-A0); + Serial.print("\tpin\t"); + Serial.print(pin); + Serial.print("\tvalue\t"); + Serial.println(value); +#endif + midiEventPacket_t event = {0x0B, 0xB0 | channel, ((id-A0) * 8 + pin), value}; + MidiUSB.sendMIDI(event); +} + +//default callback for buttons, sends note-on/off message with unique note value +void digitalCallback(int id, int pin, int value) { +#ifdef debug + Serial.print("digital"); + Serial.print("\tid\t"); + Serial.print(id); + Serial.print("\tpin\t"); + Serial.print(pin); + Serial.print("\tvalue\t"); + Serial.println(value); +#endif + if (value == HIGH) { + midiEventPacket_t noteOn = {0x09, 0x90 | channel, (id * 16 + pin), velocity}; + MidiUSB.sendMIDI(noteOn); + } else { + midiEventPacket_t noteOff = {0x08, 0x80 | channel, (id * 16 + pin), 0}; + MidiUSB.sendMIDI(noteOff); + } +} diff --git a/bombatuino_INPUT_74HC4051/bombatuino_INPUT_74HC4051.cpp b/bombatuino_INPUT_74HC4051/bombatuino_INPUT_74HC4051.cpp new file mode 100644 index 0000000..776bb6b --- /dev/null +++ b/bombatuino_INPUT_74HC4051/bombatuino_INPUT_74HC4051.cpp @@ -0,0 +1,81 @@ +#include "Arduino.h" +#include "bombatuino_INPUT_74HC4051.h" + +//should be called in setup() +void INPUT_74HC4051::begin(uint8_t analog, uint8_t s0, uint8_t s1, uint8_t s2,CallbackFunction cbF) { + + //analog pin which output Z is connected to + _analog = analog; + + //3 digital pins where S0,S1,S2 are connected to + _s0 = s0; + _s1 = s1; + _s2 = s2; + + + pinMode(_analog,INPUT); + + pinMode(_s0,OUTPUT); + pinMode(_s1,OUTPUT); + pinMode(_s2,OUTPUT); + + _callbackFunction = cbF; + + //initalize start values + uint8_t pin,r0,r1,r2; + //run through the 8 I/O pins + for (pin=0; pin<8; pin++) { + r0 = bitRead(pin,0); + r1 = bitRead(pin,1); + r2 = bitRead(pin,2); + digitalWrite(_s0, r0); + digitalWrite(_s1, r1); + digitalWrite(_s2, r2); + //delayMicroseconds(10); + _value[pin] = analogRead(_analog); + } +} + +void INPUT_74HC4051::setPins(uint8_t pins) { + _pins = pins; +} + +//should be called in loop(), read values and call callback function on change +void INPUT_74HC4051::loop() { + uint8_t pin,r0,r1,r2; + int value; + for (pin=0; pin<8; pin++) { + if (_pins & (1< value) { + _value[pin] = value; + (*_callbackFunction)(_analog,pin,value); + } + } + } +} + +//maybe useful later +int INPUT_74HC4051::getSpecificValue(uint8_t pin) { + if (pin >= 8 || !(_pins & (1< + +#include "Arduino.h" +#include "bombatuino_INPUT_MCP23017.h" + +void INPUT_MCP23017::begin(uint8_t addr,CallbackFunction cbF) { + Wire.begin(); + + //check hardware address + if (addr > 7) + _addr = 7; + else _addr = addr; + + _callbackFunction = cbF; + + //set all ports as inputs + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write((byte)MCP23017_IODIR_A); //PORT A + Wire.write(0xFF); + Wire.endTransmission(); + + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_IODIR_B); //PORT B + Wire.write(0xFF); + Wire.endTransmission(); + + //activate pullup resistors + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_GPPU_A); //PORT A + Wire.write(0xFF); + Wire.endTransmission(); + + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_GPPU_B); //PORT B + Wire.write(0xFF); + Wire.endTransmission(); + + //inverse all inputs + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write((byte)MCP23017_IPOL_A); //PORT A + Wire.write(0xFF); + Wire.endTransmission(); + + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_IPOL_B); //PORT B + Wire.write(0xFF); + Wire.endTransmission(); + + //init start values + uint8_t pin,bank; + //read bank A + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_GPIO_A); + Wire.endTransmission(); + Wire.requestFrom(MCP23017_ADDRESS | _addr, 1); + bank = Wire.read(); + for (pin=0; pin<8; pin++) + _value[pin] = (bank >> pin) & 0x1; + //read bank B + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_GPIO_B); + Wire.endTransmission(); + Wire.requestFrom(MCP23017_ADDRESS | _addr, 1); + bank = Wire.read(); + for (pin=8; pin<16; pin++) + _value[pin] = (bank >> (pin-8)) & 0x1; +} + +void INPUT_MCP23017::loop() { + uint8_t pin,bank; + int value; + //read bank A + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_GPIO_A); + Wire.endTransmission(); + Wire.requestFrom(MCP23017_ADDRESS | _addr, 1); + bank = Wire.read(); + for (pin=0; pin<8; pin++) { + value = (bank >> pin) & 0x1; + if (_value[pin] != value) { + _value[pin] = value; + (*_callbackFunction)(_addr,pin,value); + } + } + //read bank B + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + Wire.write(MCP23017_GPIO_B); + Wire.endTransmission(); + Wire.requestFrom(MCP23017_ADDRESS | _addr, 1); + bank = Wire.read(); + for (pin=8; pin<16; pin++) { + value = (bank >> (pin-8)) & 0x1; + if (_value[pin] != value) { + _value[pin] = value; + (*_callbackFunction)(_addr,pin,value); + } + } +} + +//maybe useful later +int INPUT_MCP23017::getSpecificValue(uint8_t pin) { + if (pin > 16) + return LOW; + Wire.beginTransmission(MCP23017_ADDRESS | _addr); + uint8_t p = pin; + if (pin > 8) { + Wire.write(MCP23017_GPIO_B); + p -= 8; + } else + Wire.write(MCP23017_GPIO_A); + Wire.endTransmission(); + uint8_t bank = Wire.read(); + int value = (bank >> p) & 0x1; + _value[pin] = value; + return value; +} + + diff --git a/bombatuino_INPUT_MCP23017/bombatuino_INPUT_MCP23017.h b/bombatuino_INPUT_MCP23017/bombatuino_INPUT_MCP23017.h new file mode 100644 index 0000000..794f749 --- /dev/null +++ b/bombatuino_INPUT_MCP23017/bombatuino_INPUT_MCP23017.h @@ -0,0 +1,89 @@ +/** + * @file bombatuino_INPUT_MCP23017.h + * + * @author Lukas Haubaum (lukas@haubaum.de) + * + * @date February, 2013 + * + * @brief arduino library for reading inputs from MCP23017 port Expander + * + * library is for specialiced use: all I/O ports are used as digital inputs with internal pullup resistor active, values are stored and a callback function is called, when a value changes. + * ATTETION: Wire.h must be included in sketch #include + * + * */ +#ifndef bombatuino_INPUT_MCP23017_h +#define bombatuino_INPUT_MCP23017_h + +#if !defined(CallbackFunction) +/** + * callback function + * + * @param address + * @param pin + * @param value + */ +typedef void (*CallbackFunction)(int,int,int); +#endif + +class INPUT_MCP23017 +{ + public: + /** + * initalize the class, should be called in setup() function + * + * @param hardware address (0-7) + * @param callback function + */ + void begin(uint8_t addr,CallbackFunction cbF); + /** + * read values and call callback function on change, should be called in loop() + */ + void loop(void); + /** + * get value of specific pin (0-15) + * + * @param pin + * @return value of pin + */ + int getSpecificValue(uint8_t pin); + private: + uint8_t _addr; /**< hardware address (0-7) */ + int _value[16]; /**< read values */ + CallbackFunction _callbackFunction; /**< callback function */ +}; + +#define MCP23017_ADDRESS 0x20 /**< hardware address */ + +/** + * registers of MCP23017 (BANK = 0) + * + * default is 0 except for I/O DIRECTION REGISTERS + * + * for detailed description see http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf + * + * */ +#define MCP23017_IODIR_A 0x00 /**< I/O DIRECTION REGISTER PORT A - Controls the direction of the data I/O. */ +#define MCP23017_IODIR_B 0x01 /**< I/O DIRECTION REGISTER PORT B - Controls the direction of the data I/O. */ +#define MCP23017_IPOL_A 0x02 /**< INPUT POLARITY REGISTER PORT A - This register allows the user to configure the polarity on the corresponding GPIO port bits. */ +#define MCP23017_IPOL_B 0x03 /**< INPUT POLARITY REGISTER PORT B - This register allows the user to configure the polarity on the corresponding GPIO port bits. */ +#define MCP23017_GPINTEN_A 0x04 /**< INTERRUPT-ON-CHANGE CONTROL REGISTER PORT A - The GPINTEN register controls the interrupt-on-change feature for each pin. */ +#define MCP23017_GPINTEN_B 0x05 /**< INTERRUPT-ON-CHANGE CONTROL REGISTER PORT B - The GPINTEN register controls the interrupt-on-change feature for each pin. */ +#define MCP23017_DEFVAL_A 0x06 /**< DEFAULT COMPARE REGISTER FOR INTERRUPT-ON-CHANGE PORT A - The default comparison value is configured in the DEFVAL register. */ +#define MCP23017_DEFVAL_B 0x07 /**< DEFAULT COMPARE REGISTER FOR INTERRUPT-ON-CHANGE PORT B - The default comparison value is configured in the DEFVAL register.. */ +#define MCP23017_INTCON_A 0x08 /**< INTERRUPT CONTROL REGISTER PORT A - The INTCON register controls how the associated pin value is compared for the interrupt-on-change feature. */ +#define MCP23017_INTCON_B 0x09 /**< INTERRUPT CONTROL REGISTER PORT B - The INTCON register controls how the associated pin value is compared for the interrupt-on-change feature.*/ +#define MCP23017_IOCON_A 0x0A /**< CONFIGURATION REGISTER - The IOCON register contains several bits for configuring the device. BANK/MIRROR/SEQOP/DISSLW/HAEN/ODR/INTPOL/— */ +#define MCP23017_IOCON_B 0x0B /**< CONFIGURATION REGISTER - The IOCON register contains several bits for configuring the device. BANK/MIRROR/SEQOP/DISSLW/HAEN/ODR/INTPOL/— */ +#define MCP23017_GPPU_A 0x0C /**< PULL-UP RESISTOR CONFIGURATION REGISTER PORT A - The GPPU register controls the pull-up resistors for the port pins. */ +#define MCP23017_GPPU_B 0x0D /**< PULL-UP RESISTOR CONFIGURATION REGISTER PORT B - The GPPU register controls the pull-up resistors for the port pins. */ +#define MCP23017_INTF_A 0x0E /**< INTERRUPT FLAG REGISTER PORT A - The INTF register reflects the interrupt condition on the port pins of any pin that is enabled for interrupts via the GPINTEN register. */ +#define MCP23017_INTF_B 0x0F /**< INTERRUPT FLAG REGISTER PORT B - The INTF register reflects the interrupt condition on the port pins of any pin that is enabled for interrupts via the GPINTEN register. */ +#define MCP23017_INTCAP_A 0x10 /**< INTERRUPT CAPTURE REGISTER PORT A - The INTCAP register captures the GPIO port value at the time the interrupt occurred. */ +#define MCP23017_INTCAP_B 0x11 /**< INTERRUPT CAPTURE REGISTER PORT B - The INTCAP register captures the GPIO port value at the time the interrupt occurred. */ +#define MCP23017_GPIO_A 0x12 /**< PORT REGISTER PORT A - The GPIO register reflects the value on the port. */ +#define MCP23017_GPIO_B 0x13 /**< PORT REGISTER PORT B - The GPIO register reflects the value on the port. */ +#define MCP23017_OLAT_A 0x14 /**< OUTPUT LATCH REGISTER PORT A - The OLAT register provides access to the output latches. */ +#define MCP23017_OLAT_B 0x15 /**< OUTPUT LATCH REGISTER PORT B - The OLAT register provides access to the output latches. */ + + +#endif