/* * BahiaFirmware.pde * * Copyright 2011 Carlos Jenkins * Kevin Esquivel * J Nathan Guillen A * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ ///////////////////////////// // INCLUDES ///////////////////////////// ///////////////////////////// // DEFINITIONS ///////////////////////////// /* Board ID */ #define BAHIA_ID 1 /* Address Bus pins */ #define ADDR_A 2 #define ADDR_B 3 #define ADDR_C 4 /* Amount of non-multiplexes IOs */ #define PINS 14 /* Amount of multiplexed pins and how many */ #define PINS_MULTI 6 #define PINS_MULTI_AMOUNT 8 /* According to "Digi Connect ME and Wi-ME Hardware Reference" page 39 Data Rates (bps): 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800 (Digi Connect ME 9210 only), 921600 (Digi Connect ME 9210 only) */ #define BAUD_RATE 9600 /* OSC message size */ #define MESSAGE_SIZE 20 /* Pin mode definitions Digital Input Digital Output Analog Input Analog Output (PWM) */ #define MODE_DI 0 #define MODE_DO 1 #define MODE_AI 2 #define MODE_AO 3 ///////////////////////////// // VARIABLES ///////////////////////////// // Map bahia_pin with Arduino pins const static uint8_t bahia_to_arduino[PINS] = { A0, //X1 A1, //X2 A2, //X3 A3, //X4 A4, //X5 A5, //X6 13, //X7_0 12, //X7_1 11, //X7_2 9, //X7_3 5, //X7_4 6, //X7_5 7, //X7_6 8 //X7_7 }; // Hardware table definitions const static boolean can_analog_input[PINS] = { true, //X1 true, //X2 true, //X3 true, //X4 true, //X5 true, //X6 false, //X7_0 false, //X7_1 false, //X7_2 false, //X7_3 false, //X7_4 false, //X7_5 false, //X7_6 false //X7_7 }; const static boolean can_pwm_output[PINS] = { false, //X1 false, //X2 false, //X3 false, //X4 false, //X5 false, //X6 false, //X7_0 false, //X7_1 true, //X7_2 true, //X7_3 true, //X7_4 true, //X7_5 false, //X7_6 false //X7_7 }; const static boolean is_multiplexed[PINS] = { true, //X1 true, //X2 true, //X3 true, //X4 true, //X5 true, //X6 false, //X7_0 false, //X7_1 false, //X7_2 false, //X7_3 false, //X7_4 false, //X7_5 false, //X7_6 false //X7_7 }; static boolean read_enabled[PINS] = { true, //X1 (Digital In) true, //X2 (Digital In) false, //X3 false, //X4 true, //X5 (Analog In) true, //X6 (Analog In) false, //X7_0 false, //X7_1 false, //X7_2 false, //X7_3 false, //X7_4 false, //X7_5 false, //X7_6 false //X7_7 }; static boolean read_enabled_multiplexed[PINS_MULTI][PINS_MULTI_AMOUNT] = { {true , true , true , true , true , true , true , true }, // X1_ {true , true , true , true , true , true , true , true }, // X2_ {false, false, false, false, false, false, false, false}, // X3_ {false, false, false, false, false, false, false, false}, // X4_ {true , true , true , true , true , true , true , true }, // X5_ {true , true , true , true , true , true , true , true } // X6_ }; static byte pin_mode[PINS] = { MODE_DI, //X1 MODE_DI, //X2 MODE_DO, //X3 MODE_DO, //X4 MODE_AI, //X5 MODE_AI, //X6 MODE_DO, //X7_0 MODE_DO, //X7_1 MODE_AO, //X7_2 MODE_AO, //X7_3 MODE_AO, //X7_4 MODE_AO, //X7_5 MODE_DO, //X7_6 MODE_DO //X7_7 }; static char incomming_message[MESSAGE_SIZE] = { // Message template '/', 'a', 'r', 'd', '/', B0, '/', 'o', 'p', '/', B0, '\0', ',', 'i', '\0', '\0', B0, B0, B0, B0 }; static int incomming_value = 0; ///////////////////////////// // MAIN FUNCTIONS ///////////////////////////// // Arduino main setup function void setup() { // Configure Hardware for(byte i = 0; i < PINS; i++) { if((pin_mode[i] == MODE_DI) || (pin_mode[i] == MODE_AI)) { pinMode(bahia_to_arduino[i], INPUT); } else { pinMode(bahia_to_arduino[i], OUTPUT); } } // Configure Serial port Serial.begin(BAUD_RATE); } // Arduino main loop function void loop() { // Check for incomming messages checkIncomming(); // Now, stream values for(byte i = 0; i < PINS; i++) { if(read_enabled[i]) { // Read for that pin is enable if(is_multiplexed[i]) { // Check if is multiplexed // It is, so check if multiplexed channel is enabled to read for(byte j = 0; j < PINS_MULTI_AMOUNT; j++) { if(read_enabled_multiplexed[i][j]) { read_and_broadcast(i, j); } } } else { // We know it's a X7 pin read_and_broadcast(i, 255); } } } } ///////////////////////////// // HELPER FUNCTIONS ///////////////////////////// // Check Incomming Messages void checkIncomming() { // Check for new configuration messages if(Serial.available() >= MESSAGE_SIZE) { // Get the message for(byte i = 0; i < MESSAGE_SIZE; i++) { incomming_message[i] = Serial.read(); } // Check OSC Message if(incomming_message[0] != '/') { return; } // Check namespace if( (incomming_message[1] != 'a') || (incomming_message[2] != 'r') || (incomming_message[3] != 'd') ) { return; } // Check id if(incomming_message[5] != BAHIA_ID) { return; } // Check instruction type and perform action char instruction_type = incomming_message[7]; byte pin_n = incomming_message[10]; int argument = int(word(byte(incomming_message[18]), byte(incomming_message[19]))); switch(instruction_type) { case 'w': // Write value instructionWrite(pin_n, argument); break; case 'e': // Enable/disable sensor instructionEnable(pin_n, argument == 0 ? true : false); break; case 'c': // Configure pin funtion instructionConfigure(pin_n, argument); break; default: return; // Unknown instruction, ignoring } }// If not enough bytes in buffer, then do nothing } // Perform a Write instruction void instructionWrite(byte pin_n, int value) { // Check bounds if(pin_n > 57) { return; // Out of bounds, ignoring } // Get the pin number in pin_bahia byte pin = (pin_n - 1) / PINS_MULTI_AMOUNT; if(pin_mode[pin] == MODE_DO) { if(value == 0) { digitalWrite(bahia_to_arduino[pin], LOW); } else { digitalWrite(bahia_to_arduino[pin], HIGH); } } else if(pin_mode[pin] == MODE_AO) { if(value < 256) { analogWrite(bahia_to_arduino[pin], value); } // Ignoring values out of range } // Ignoring pins configured as input return; } // Perform a Enable/Disable sensor instruction void instructionEnable(byte pin_n, boolean value) { // Check bounds if(pin_n > 57) { return; // Out of bounds, ignoring } // Get the pin number in pin_bahia byte pin = (pin_n - 1) / PINS_MULTI_AMOUNT; // Check if is configured as output if((pin_mode[pin] != MODE_AO) && (pin_mode[pin] != MODE_DO)) { return; } // Check if is multiplexed if(pin < 7) { byte channel = (pin_n - 1) - (pin * PINS_MULTI_AMOUNT); read_enabled_multiplexed[pin][channel] = value; //TODO Optimize: analize if all the colums are false to disable pin in read_enable } else { read_enabled[pin] = value; } return; } // Perform a Configure pin mode instruction void instructionConfigure(byte pin_n, int value) { // Check bounds if(pin_n > 57) { return; // Out of bounds, ignoring } // Get the pin number in pin_bahia byte pin = (pin_n - 1) / PINS_MULTI_AMOUNT; switch(value) { case 1: // Digital out pinMode(bahia_to_arduino[pin], OUTPUT); pin_mode[pin] = MODE_DO; break; case 2: // Digital in pinMode(bahia_to_arduino[pin], INPUT); pin_mode[pin] = MODE_DI; break; case 3: // "Analog out" (PWM) if(can_pwm_output[pin]) { pinMode(bahia_to_arduino[pin], OUTPUT); pin_mode[pin] = MODE_AO; } break; case 4: // Analog in if(can_analog_input[pin]) { pinMode(bahia_to_arduino[pin], INPUT); pin_mode[pin] = MODE_AI; } break; } // Ignoring unknown values return; } // Read the current pin and channel, if needed. Then, broadcast the value through serial using OSC Protocol // Note: This function check that the pin is configured as input, but it asumes you actually want to read the pin. void read_and_broadcast(byte pin, byte channel) { //Serial.print("Goind to read and broadcast: "); //Serial.print(pin, DEC); //Serial.print(", "); //Serial.println(channel, DEC); // Select channel, if needed if(channel < PINS_MULTI_AMOUNT) { // Note: HIGH is defined as 0x1 and LOW as 0x0 in wiring.h digitalWrite(ADDR_A, channel & B00000001); digitalWrite(ADDR_B, (channel & B00000010) >> 1); digitalWrite(ADDR_C, (channel & B00000100) >> 2); } // Read the pin int reported_value = 0; if(pin_mode[pin] == MODE_DI) { reported_value = digitalRead(bahia_to_arduino[pin]); } else if(pin_mode[pin] == MODE_AI) { reported_value = analogRead(bahia_to_arduino[pin]); } // Calculate the pin number byte pin_n = 0; if(pin < PINS_MULTI) { pin_n = (pin * PINS_MULTI_AMOUNT) + channel + 1; } else { pin_n = (PINS_MULTI * PINS_MULTI_AMOUNT) + (pin - PINS_MULTI_AMOUNT) + 1; } // Broadcast the value Serial.write("/ard/"); //OSC Address Pattern Serial.print(BAHIA_ID, DEC); Serial.write('/'); Serial.print(pin_n, DEC); Serial.write("\0\0\0\0"); Serial.write(",i\0\0"); //OSC Type Tag String Serial.write("\0\0"); //OSC Arguments Serial.write(reported_value); // For debug only Serial.println(""); return; }