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 ----