450 lines
11 KiB
Plaintext
450 lines
11 KiB
Plaintext
/*
|
|
* BahiaFirmware.pde
|
|
*
|
|
* Copyright 2011 Carlos Jenkins <cjenkins@softwarelibrecr.org>
|
|
* Kevin Esquivel <kevinesquivel21@gmail.com>
|
|
* J Nathan Guillen A <aguzzi7@gmail.com>
|
|
*
|
|
* 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;
|
|
}
|