Update of /cvsroot/pure-data/externals/hardware/arduino/Pd_firmware In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12782/Pd_firmware
Modified Files: Pd_firmware.pde Log Message:
- Removed lots of cruft and various attempts at fixing things.
- Removed timer2 interrupt code because it was interfering with the hardware PWM on some pins. Replaced it with timer0_overflow_count from wiring.c but that's not fully functional yet, I think I have to get the time units right. Right now it seems to just output everytime rather than every 4ms
- removed second [arduino] object in arduino-test.pd that was causing lost serial data.
WORKING - analog input working - hardware PWM output working - digital output working - setPinMode to INPUT/OUTPUT for digital pins working
NOT WORKING YET - digital inputs - software PWM on non-hardware-PWM pins - save state to EEPROM
Index: Pd_firmware.pde =================================================================== RCS file: /cvsroot/pure-data/externals/hardware/arduino/Pd_firmware/Pd_firmware.pde,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** Pd_firmware.pde 5 Mar 2007 04:34:32 -0000 1.26 --- Pd_firmware.pde 5 Mar 2007 17:08:51 -0000 1.27 *************** *** 174,187 **** * software can test whether it will be compatible with the currently * installed firmware. */ ! #define MAJOR_VERSION 1 // for non-compatible changes ! #define MINOR_VERSION 0 // for backwards compatible changes
/* total number of pins currently supported */ ! #define TOTAL_ANALOG_PINS 6 ! #define TOTAL_DIGITAL_PINS 14
// for comparing along with INPUT and OUTPUT ! #define PWM 2
#define DIGITAL_MESSAGE 0x90 // send data for a digital pin #define ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM) --- 174,189 ---- * software can test whether it will be compatible with the currently * installed firmware. */ ! #define FIRMATA_MAJOR_VERSION 1 // for non-compatible changes ! #define FIRMATA_MINOR_VERSION 0 // for backwards compatible changes
/* total number of pins currently supported */ ! #define TOTAL_ANALOG_PINS 6 ! #define TOTAL_DIGITAL_PINS 14
// for comparing along with INPUT and OUTPUT ! #define PWM 2
+ #define MAX_DATA_BYTES 2 // max number of data bytes in non-SysEx messages + /* message command bytes */ #define DIGITAL_MESSAGE 0x90 // send data for a digital pin #define ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM) *************** *** 200,232 **** *============================================================================*/
! // circular buffer for receiving bytes from the serial port ! #define RINGBUFFER_MAX 64 // must be a power of 2 ! byte ringBuffer[RINGBUFFER_MAX]; ! byte readPosition=0, writePosition=0; ! ! // maximum number of post-command data bytes (non-SysEx) ! #define MAX_DATA_BYTES 2 ! // this flag says the next serial input will be data ! byte waitForData = 0; byte executeMultiByteCommand = 0; // command to execute after getting multi-byte data byte multiByteChannel = 0; // channel data for multiByteCommands byte storedInputData[MAX_DATA_BYTES] = {0,0}; // multi-byte data ! ! byte previousDigitalInputHighByte = 0; ! byte previousDigitalInputLowByte = 0; byte digitalInputHighByte = 0; byte digitalInputLowByte = 0; ! unsigned int digitalPinStatus = 65535;// bit-wise array to store pin status 0=INPUT, 1=OUTPUT ! /* this byte stores the status off whether PWM is on or not ! * bit 9 = PWM0, bit 10 = PWM1, bit 11 = PWM2 ! * the rest of the bits are unused and should remain 0 */ ! int pwmStatus = 0; ! /* analog inputs */ ! unsigned int analogPinsToReport = 0; // bit-wise array to store pin reporting int analogPin = 0; // counter for reading analog pins int analogData; // storage variable for data from analogRead() ! /* interrupt variables */ ! volatile int int_counter = 0; // ms counter for scheduling
/*============================================================================== --- 202,226 ---- *============================================================================*/
! /* input message handling */ ! byte waitForData = 0; // this flag says the next serial input will be data byte executeMultiByteCommand = 0; // command to execute after getting multi-byte data byte multiByteChannel = 0; // channel data for multiByteCommands byte storedInputData[MAX_DATA_BYTES] = {0,0}; // multi-byte data ! /* digital pins */ ! boolean digitalInputsEnabled = false; // output digital inputs or not byte digitalInputHighByte = 0; byte digitalInputLowByte = 0; ! byte previousDigitalInputHighByte = 0; // previous output to test for change ! byte previousDigitalInputLowByte = 0; // previous output to test for change ! int digitalPinStatus = 0; // bitwise array to store pin status 0=INPUT,1=OUTPUT ! /* PWM/analog outputs */ ! int pwmStatus = 0; // bitwise array to store PWM status /* analog inputs */ ! unsigned int analogPinsToReport = 0; // bitwise array to store pin reporting int analogPin = 0; // counter for reading analog pins int analogData; // storage variable for data from analogRead() ! /* timer variables */ ! extern volatile unsigned long timer0_overflow_count; // timer0 from wiring.c ! unsigned long nextExecuteTime; // for comparison with timer0_overflow_count
/*============================================================================== *************** *** 234,248 **** *============================================================================*/ /* ----------------------------------------------------------------------------- ! * output the version message to the serial port ! */ void printVersion() { Serial.print(REPORT_VERSION, BYTE); ! Serial.print(MINOR_VERSION, BYTE); ! Serial.print(MAJOR_VERSION, BYTE); }
/* ----------------------------------------------------------------------------- ! * output digital bytes received from the serial port ! */ void outputDigitalBytes(byte pin0_6, byte pin7_13) { int i; --- 228,240 ---- *============================================================================*/ /* ----------------------------------------------------------------------------- ! * output the version message to the serial port */ void printVersion() { Serial.print(REPORT_VERSION, BYTE); ! Serial.print(FIRMATA_MINOR_VERSION, BYTE); ! Serial.print(FIRMATA_MAJOR_VERSION, BYTE); }
/* ----------------------------------------------------------------------------- ! * output digital bytes received from the serial port */ void outputDigitalBytes(byte pin0_6, byte pin7_13) { int i; *************** *** 261,267 ****
/* ----------------------------------------------------------------------------- ! * processInput() is called whenever a byte is available on the ! * Arduino's serial port. This is where the commands are handled. */ void processInput(int inputData) { int command; --- 253,304 ----
/* ----------------------------------------------------------------------------- ! * check all the active digital inputs for change of state, then add any events ! * to the Serial output queue using Serial.print() */ ! void checkDigitalInputs(void) { ! if(digitalInputsEnabled) { ! // this should use _SFR_IO8() ! } ! } ! ! // ----------------------------------------------------------------------------- ! /* sets the pin mode to the correct state and sets the relevant bits in the ! * two bit-arrays that track Digital I/O and PWM status */ + void setPinMode(byte pin, byte mode) { + if(mode == INPUT) { + digitalPinStatus = digitalPinStatus &~ (1 << pin); + pwmStatus = pwmStatus &~ (1 << pin); + digitalWrite(pin,LOW); // turn off pin before switching to INPUT + pinMode(pin,INPUT); + } + else if(mode == OUTPUT) { + digitalPinStatus = digitalPinStatus | (1 << pin); + pwmStatus = pwmStatus &~ (1 << pin); + pinMode(pin,OUTPUT); + } + else if( mode == PWM ) { + digitalPinStatus = digitalPinStatus | (1 << pin); + pwmStatus = pwmStatus | (1 << pin); + pinMode(pin,OUTPUT); + } + // TODO: save status to EEPROM here, if changed + } + + // ----------------------------------------------------------------------------- + /* sets bits in a bit array (int) to toggle the reporting of the analogIns + */ + void setAnalogPinReporting(byte pin, byte state) { + if(state == 0) { + analogPinsToReport = analogPinsToReport &~ (1 << pin); + } + else { // everything but 0 enables reporting of that pin + analogPinsToReport = analogPinsToReport | (1 << pin); + } + // TODO: save status to EEPROM here, if changed + } + + /* ----------------------------------------------------------------------------- + * processInput() is called whenever a byte is available on the + * Arduino's serial port. This is where the commands are handled. */ void processInput(int inputData) { int command; *************** *** 271,278 **** waitForData--; storedInputData[waitForData] = inputData; ! if( (waitForData==0) && executeMultiByteCommand ) { ! //we got everything switch(executeMultiByteCommand) { case ANALOG_MESSAGE: break; case DIGITAL_MESSAGE: --- 308,317 ---- waitForData--; storedInputData[waitForData] = inputData; ! if( (waitForData==0) && executeMultiByteCommand ) { // got the whole message switch(executeMultiByteCommand) { case ANALOG_MESSAGE: + setPinMode(multiByteChannel,PWM); + analogWrite(multiByteChannel, + (storedInputData[0] << 7) + storedInputData[1] ); break; case DIGITAL_MESSAGE: *************** *** 281,295 **** case SET_DIGITAL_PIN_MODE: setPinMode(storedInputData[1], storedInputData[0]); // (pin#, mode) ! //if(storedInputData[0] == INPUT) // enable input if set to INPUT ! // TODO: enable REPORT_DIGITAL_PORTS break; case REPORT_ANALOG_PIN: setAnalogPinReporting(multiByteChannel,storedInputData[0]); - //Serial.print(multiByteChannel,BYTE); - //Serial.print(storedInputData[0],BYTE); - //Serial.print(analogPinsToReport,BYTE); - //Serial.print(analogPinsToReport & (1 << multiByteChannel),BYTE); break; case REPORT_DIGITAL_PORTS: break; } --- 320,335 ---- case SET_DIGITAL_PIN_MODE: setPinMode(storedInputData[1], storedInputData[0]); // (pin#, mode) ! if(storedInputData[0] == INPUT) ! digitalInputsEnabled = true; // enable reporting of digital inputs break; case REPORT_ANALOG_PIN: setAnalogPinReporting(multiByteChannel,storedInputData[0]); break; case REPORT_DIGITAL_PORTS: + // TODO: implement MIDI channel as port base for more than 16 digital inputs + if(storedInputData[0] == 0) + digitalInputsEnabled = false; + else + digitalInputsEnabled = true; break; } *************** *** 327,383 **** }
- /* ----------------------------------------------------------------------------- * this function checks to see if there is data waiting on the serial port * then processes all of the stored data */ ! ! /* TODO: switch this to a timer interrupt. The timer is set in relation to ! * the bitrate, when the interrupt is triggered, then it runs checkForInput(). ! * Therefore, it only checks for input once per cycle of the serial port. ! */ ! void checkForInput() { while(Serial.available()) ! processInput( Serial.read() ); ! } ! ! // ----------------------------------------------------------------------------- ! /* sets the pin mode to the correct state and sets the relevant bits in the ! * two bit-arrays that track Digital I/O and PWM status ! */ ! void setPinMode(byte pin, byte mode) { ! if(mode == INPUT) { ! digitalPinStatus = digitalPinStatus &~ (1 << pin); ! pwmStatus = pwmStatus &~ (1 << pin); ! digitalWrite(pin,LOW); // turn off pin before switching to INPUT ! pinMode(pin,INPUT); ! } ! else if(mode == OUTPUT) { ! digitalPinStatus = digitalPinStatus | (1 << pin); ! pwmStatus = pwmStatus &~ (1 << pin); ! pinMode(pin,OUTPUT); ! } ! else if( mode == PWM ) { ! digitalPinStatus = digitalPinStatus | (1 << pin); ! pwmStatus = pwmStatus | (1 << pin); ! pinMode(pin,OUTPUT); ! } ! // TODO: save status to EEPROM here, if changed ! } ! ! // ----------------------------------------------------------------------------- ! /* sets bits in a bit array (int) to toggle the reporting of the analogIns ! */ ! void setAnalogPinReporting(byte pin, byte state) { ! if(state == 0) { ! analogPinsToReport = analogPinsToReport &~ (1 << pin); ! } ! else { // everything but 0 enables reporting of that pin ! analogPinsToReport = analogPinsToReport | (1 << pin); ! } }
// ============================================================================= - // used for flashing the pin for the version number void pin13strobe(int count, int onInterval, int offInterval) { --- 367,380 ---- }
/* ----------------------------------------------------------------------------- * this function checks to see if there is data waiting on the serial port * then processes all of the stored data */ ! void checkForSerialReceive() { while(Serial.available()) ! processInput(Serial.read()); }
// ============================================================================= // used for flashing the pin for the version number void pin13strobe(int count, int onInterval, int offInterval) { *************** *** 392,402 **** }
- // ----------------------------------------------------------------------------- - /* handle timer interrupts - Arduino runs at 16 Mhz, so we have 1000 Overflows - * per second... 1/ ((16000000 / 64) / 256) = 1 / 1000 */ - ISR(TIMER2_OVF_vect) { - int_counter++; - }; - /*============================================================================== * SETUP() --- 389,392 ---- *************** *** 405,445 **** byte i;
- // TODO: load state from EEPROM here Serial.begin(57600); // 9600, 14400, 38400, 57600, 115200
! /* set up timer interrupt */ ! //Timer2 Settings: Timer Prescaler /64, ! TCCR2 |= (1<<CS22); ! TCCR2 &= ~((1<<CS21) | (1<<CS20)); ! // Use normal mode ! TCCR2 &= ~((1<<WGM21) | (1<<WGM20)); ! // Use internal clock - external clock not used in Arduino ! ASSR |= (0<<AS2); ! //Timer2 Overflow Interrupt Enable ! TIMSK |= (1<<TOIE2) | (0<<OCIE2); ! // RESET_TIMER2; ! sei(); ! ! ! /* TODO: send digital inputs here, if enabled, to set the initial state on the ! * host computer, since once in the loop(), the Arduino will only send data on ! * change. */ ! ! // flash the pin 13 with the protocol minor version (add major once > 0) pinMode(13,OUTPUT); pin13strobe(2,1,4); // separator, a quick burst delay(500); ! pin13strobe(MAJOR_VERSION, 200, 400); delay(500); pin13strobe(2,1,4); // separator, a quick burst delay(500); ! pin13strobe(MINOR_VERSION, 200, 400); delay(500); pin13strobe(2,1,4); // separator, a quick burst - printVersion();
for(i=0; i<TOTAL_DIGITAL_PINS; ++i) { ! setPinMode(i,OUTPUT); } }
--- 395,422 ---- byte i;
Serial.begin(57600); // 9600, 14400, 38400, 57600, 115200
! // flash the pin 13 with the protocol version pinMode(13,OUTPUT); pin13strobe(2,1,4); // separator, a quick burst delay(500); ! pin13strobe(FIRMATA_MAJOR_VERSION, 200, 400); delay(500); pin13strobe(2,1,4); // separator, a quick burst delay(500); ! pin13strobe(FIRMATA_MINOR_VERSION, 200, 400); delay(500); pin13strobe(2,1,4); // separator, a quick burst
for(i=0; i<TOTAL_DIGITAL_PINS; ++i) { ! setPinMode(i,INPUT); } + // TODO: load state from EEPROM here + + printVersion(); + + /* TODO: send digital inputs here, if enabled, to set the initial state on the + * host computer, since once in the loop(), the Arduino will only send data on + * change. */ }
*************** *** 448,469 **** *============================================================================*/ void loop() { ! /* DIGITALREAD - as fast as possible, check for changes and output them to the ! * FTDI buffer using serialWrite) */ ! // this should use _SFR_IO8() ! ! if(int_counter > 3) { // run this every 4ms ! ! ! /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle all ! * serialReads at once, i.e. empty the buffer */ ! checkForInput(); ! ! /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over 60 ! * bytes. use a timer to sending an event character every 4 ms to trigger the ! * buffer to dump. */ ! ! /* ANALOGREAD - right after the event character, do all of the analogReads(). ! * These only need to be done every 4ms. */ for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) { if( analogPinsToReport & (1 << analogPin) ) { --- 425,443 ---- *============================================================================*/ void loop() { ! ///analogWrite(11, tmp);++tmp;delay(2); /* DIGITALREAD - as fast as possible, check for changes and output them to the ! * FTDI buffer using Serial.print() */ ! checkDigitalInputs(); ! if(timer0_overflow_count > nextExecuteTime) { ! nextExecuteTime = timer0_overflow_count + 4; // run this every 4ms ! /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle ! * all serialReads at once, i.e. empty the buffer */ ! checkForSerialReceive(); ! /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over ! * 60 bytes. use a timer to sending an event character every 4 ms to ! * trigger the buffer to dump. */ ! ! /* ANALOGREAD - right after the event character, do all of the ! * analogReads(). These only need to be done every 4ms. */ for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) { if( analogPinsToReport & (1 << analogPin) ) { *************** *** 475,479 **** } } - int_counter = 0; // reset ms counter } } --- 449,452 ----