[PD-cvs] externals/hardware/arduino/Pd_firmware Pd_firmware.pde, 1.26, 1.27

Hans-Christoph Steiner eighthave at users.sourceforge.net
Mon Mar 5 18:08:53 CET 2007


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





More information about the Pd-cvs mailing list