IDuino

   1 /*
   2  * Copyright (C) 2006 Free Software Foundation
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public License
   6  * as published by the Free Software Foundation; either version 2
   7  * of the License, or (at your option) any later version.
   8  *
   9  * See file LICENSE for further informations on licensing terms.
  10  *
  11  * This program is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  * GNU General Public License for more details.
  15  *
  16  * You should have received a copy of the GNU General Public License
  17  * along with this program; if not, write to the Free Software Foundation,
  18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19  *
  20  * -----------------------------------------------------------
  21  * Firmata, the general purpose sensorbox firmware for Arduino
  22  * -----------------------------------------------------------
  23  * 
  24  * Firmata turns the Arduino into a Plug-n-Play sensorbox, servo
  25  * controller, and/or PWM motor/lamp controller.
  26  *
  27  * It was originally designed to work with the Pd object [arduino]
  28  * which is included in Pd-extended.  This firmware is intended to
  29  * work with any host computer software package.  It can easily be
  30  * used with other programs like Max/MSP, Processing, or whatever can
  31  * do serial communications.
  32  *
  33  * @author: Hans-Christoph Steiner <hans@at.or.at>
  34  *   help with initial protocol redesign: Jamie Allen <jamie@heavyside.net>
  35  *   much protocol discussion: the Arduino developers mailing list
  36  *   key bugfixes: Georg Holzmann <grh@mur.at>
  37  *                 Gerda Strobl <gerda.strobl@student.tugraz.at>
  38  * @date: 2006-05-19
  39  * @locations: STEIM, Amsterdam, Netherlands
  40  *             IDMI/Polytechnic University, Brookyn, NY, USA
  41  *             Electrolobby Ars Electronica, Linz, Austria
  42  */
  43 
  44 /* 
  45  * TODO: add pulseOut functionality for servos
  46  * TODO: add software PWM for servos, etc (servo.h or pulse.h)
  47  * TODO: add device type reporting (i.e. some firmwares will use the Firmata
  48  *       protocol, but will only support specific devices, like ultrasound 
  49  *       rangefinders or servos)
  50  * TODO: use Program Control to load stored profiles from EEPROM
  51  */
  52 
  53 /* cvs version: $Id: Pd_firmware.pde,v 1.29 2007/03/08 05:37:22 eighthave Exp $ */
  54 /* svn version: 334 */
  55 
  56 /*==============================================================================
  57  * MESSAGE FORMATS
  58  *============================================================================*/
  59 
  60 /* -----------------------------------------------------------------------------
  61  * MAPPING DATA TO MIDI
  62  *
  63  * This protocol uses the MIDI message format, but does not use the whole
  64  * protocol.  Most of the command mappings here will not be directly usable in
  65  * terms of MIDI controllers and synths.  It should co-exist with MIDI without
  66  * trouble and can be parsed by standard MIDI interpreters.  Just some of the
  67  * message data is used differently.
  68  *
  69  * MIDI format: http://www.harmony-central.com/MIDI/Doc/table1.html
  70  * 
  71  *                              MIDI       
  72  * type                command  channel    first byte            second byte 
  73  * -----------------------------------------------------------------------------
  74  * analog I/O            0xE0   pin #      LSB(bits 0-6)         MSB(bits 7-13)
  75  * digital I/O           0x90   port base  LSB(bits 0-6)         MSB(bits 7-13)
  76  * report analog pin     0xC0   pin #      disable/enable(0/1)   - n/a -
  77  * report digital ports  0xD0   port base  disable/enable(0/1)   - n/a -
  78  *
  79  * digital pin mode(I/O) 0xF4   - n/a -    pin # (0-63)          pin state(0=in)
  80  * firmware version      0xF9   - n/a -    minor version         major version
  81  * system reset          0xFF   - n/a -    - n/a -               - n/a -
  82  *
  83  */
  84  
  85 /* nl.tue.id.creapro +>>>>>
  86  * Extensions nl.tue.id.creapro
  87  * configuration        0xFD   - n/a -     0x00                   serial pulling rate (ms)
  88  *                                         0x10                   analog pulling rate (ms)
  89  *                                         0x20                   analog step (1-1023)
  90  * debug                0xFD   - n/a -     0x40                   data received (bytes)
  91  *                                         0x50                   data sent (bytes)
  92  *                                         0x60                   number of commands received
  93  *                                         0x70                   number of commands sent
  94 
  95  * nl.tue.id.creapro +<<<<<
  96 */
  97 
  98 /* proposed extensions using SysEx
  99  *
 100  * type      SysEx start  command  data bytes                         SysEx stop
 101  * -----------------------------------------------------------------------------
 102  * pulse I/O   0xF0        0xA0   five 7-bit chunks, LSB first             0xF7 
 103  * shiftOut    0xF0        0xF5   dataPin; clockPin; 7-bit LSB; 7-bit MSB  0xF7
 104  */
 105 
 106 /* -----------------------------------------------------------------------------
 107  * DATA MESSAGE FORMAT */
 108 
 109 /* two byte digital data format
 110  * ----------------------------
 111  * 0  digital data, 0x90-0x9F, (MIDI NoteOn, but different data usage)
 112  * 1  digital pins 0-6 bitmask
 113  * 2  digital pins 7-13 bitmask 
 114  */
 115 
 116 /* analog 14-bit data format
 117  * -------------------------
 118  * 0  analog pin, 0xE0-0xEF, (MIDI Pitch Wheel)
 119  * 1  analog least significant 7 bits
 120  * 2  analog most significant 7 bits
 121  */
 122 
 123 /* version report format
 124  * Send a single byte 0xF9, Arduino will reply with:
 125  * -------------------------------------------------
 126  * 0  version report header (0xF9) (MIDI Undefined)
 127  * 1  minor version (0-127)
 128  * 2  major version (0-127)
 129  */
 130 
 131 /* pulseIn/Out (uses 32-bit value)
 132  * -------------------------------
 133  * 0  START_SYSEX (0xF0) (MIDI System Exclusive)
 134  * 1  pulseIn/Out (0xA0-0xAF)
 135  * 2  bits 0-6 (least significant byte)
 136  * 3  bits 7-13
 137  * 4  bits 14-20
 138  * 5  bits 21-27
 139  * 6  bits 28-34 (most significant byte)
 140  * 7  END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
 141  */
 142 
 143 /* shiftIn/Out (uses 8-bit value)
 144  * ------------------------------
 145  * 0  START_SYSEX (0xF0)
 146  * 1  shiftOut (0xF5)
 147  * 2  dataPin (0-127)
 148  * 3  clockPin (0-127)
 149  * 4  bits 0-6 (least significant byte)
 150  * 5  bit 7 (most significant bit)
 151  * 6  END_SYSEX (0xF7)
 152  */
 153 
 154 /* -----------------------------------------------------------------------------
 155  * CONTROL MESSAGES */
 156 
 157 /* set digital pin mode
 158  * --------------------
 159  * 1  set digital pin mode (0xF4) (MIDI Undefined)
 160  * 2  pin number (0-127)
 161  * 3  state (INPUT/OUTPUT, 0/1)
 162  */
 163 
 164 /* toggle analogIn reporting by pin
 165  * --------------------------------
 166  * 0  toggle digitalIn reporting (0xC0-0xCF) (MIDI Program Change)
 167  * 1  disable(0)/enable(non-zero) 
 168  */
 169 
 170 /* toggle digitalIn reporting by port pairs
 171  * ----------------------------------------
 172  * 0  toggle digitalIn reporting (0xD0-0xDF) (MIDI Aftertouch)
 173  * 1  disable(0)/enable(non-zero) 
 174  */
 175 
 176 /* request version report
 177  * ----------------------
 178  * 0  request version report (0xF9) (MIDI Undefined)
 179  */
 180 
 181 /*==============================================================================
 182  * MACROS
 183  *============================================================================*/
 184 
 185 /* Version numbers for the protocol.  The protocol is still changing, so these
 186  * version numbers are important.  This number can be queried so that host
 187  * software can test whether it will be compatible with the currently
 188  * installed firmware. */
 189 #define FIRMATA_MAJOR_VERSION   1 // for non-compatible changes
 190 #define FIRMATA_MINOR_VERSION   0 // for backwards compatible changes
 191 
 192 /* total number of pins currently supported */  
 193 #define TOTAL_ANALOG_PINS       6
 194 #define TOTAL_DIGITAL_PINS      14
 195 
 196 // for comparing along with INPUT and OUTPUT
 197 #define PWM                     2
 198 
 199 // for selecting digital inputs
 200 #define PB  2  // digital input, pins 8-13
 201 #define PC  3  // analog input port
 202 #define PD  4  // digital input, pins 0-7
 203 
 204 #define MAX_DATA_BYTES 2 // max number of data bytes in non-SysEx messages
 205 /* message command bytes */
 206 #define DIGITAL_MESSAGE         0x90 // send data for a digital pin
 207 #define ANALOG_MESSAGE          0xE0 // send data for an analog pin (or PWM)
 208 //#define PULSE_MESSAGE           0xA0 // proposed pulseIn/Out message (SysEx)
 209 //#define SHIFTOUT_MESSAGE        0xB0 // proposed shiftOut message (SysEx)
 210 #define REPORT_ANALOG_PIN       0xC0 // enable analog input by pin #
 211 #define REPORT_DIGITAL_PORTS    0xD0 // enable digital input by port pair
 212 #define START_SYSEX             0xF0 // start a MIDI SysEx message
 213 #define SET_DIGITAL_PIN_MODE    0xF4 // set a digital pin to INPUT or OUTPUT 
 214 #define END_SYSEX               0xF7 // end a MIDI SysEx message
 215 #define REPORT_VERSION          0xF9 // report firmware version
 216 #define SYSTEM_RESET            0xFF // reset from MIDI
 217 
 218 
 219 // nl.tue.id.creapro +>>>>>
 220 #define CONFIG                  0xFD
 221 #define SERIAL_PULL_RATE        0x00
 222 #define ANALOG_PULL_RATE        0x10
 223 #define ANALOG_STEP             0x20
 224 
 225 #define DEBUG                   0xFD
 226 #define READ_COUNT              0x40
 227 #define WRITE_COUNT             0x50
 228 #define COMMAND_COUNT           0x60
 229 #define EVENT_COUNT             0x70
 230 
 231 // nl.tue.id.creapro +<<<<<
 232 
 233 
 234 /*==============================================================================
 235  * GLOBAL VARIABLES
 236  *============================================================================*/
 237 
 238 /* input message handling */
 239 byte waitForData = 0; // this flag says the next serial input will be data
 240 byte executeMultiByteCommand = 0; // execute this after getting multi-byte data
 241 byte multiByteChannel = 0; // channel data for multiByteCommands
 242 byte storedInputData[MAX_DATA_BYTES] = {0,0}; // multi-byte data
 243 /* digital pins */
 244 boolean digitalInputsEnabled = false; // output digital inputs or not
 245 int digitalInputs = 0;
 246 int previousDigitalInputs; // previous output to test for change
 247 // nl.tue.id.creapro -+>>>>>
 248 //int digitalPinStatus = 3; // bitwise array to store pin status, ignore RxTx pins
 249 int digitalPinStatus = 0xFFFF; //ignore all pins
 250 // nl.tue.id.creapro -+>>>>>
 251 /* PWM/analog outputs */
 252 int pwmStatus = 0; // bitwise array to store PWM status
 253 /* analog inputs */
 254 int analogPinsToReport = 0; // bitwise array to store pin reporting
 255 int analogPin = 0; // counter for reading analog pins
 256 int analogData; // storage variable for data from analogRead()
 257 /* timer variables */
 258 extern volatile unsigned long timer0_overflow_count; // timer0 from wiring.c
 259 unsigned long nextExecuteTime = 0; // for comparison with timer0_overflow_count
 260 
 261 // nl.tue.id.creapro +>>>>>
 262 int storedAnalogData[TOTAL_ANALOG_PINS];
 263 unsigned long nextAnalogExecuteTime = 0; // for comparison with timer0_overflow_count
 264 
 265 int serialPullRate = 20;
 266 int analogPullRate = 20;
 267 int analogStep = 1;
 268 
 269 int writeCount = 0;
 270 int readCount = 0;
 271 int commandCount = 0;
 272 int eventCount = 0;
 273 // nl.tue.id.creapro +<<<<< 
 274 
 275 
 276 /*==============================================================================
 277  * FUNCTIONS                                                                
 278  *============================================================================*/
 279 // nl.tue.id.creapro +>>>>>
 280 void serialPrint(int byte1, int byte2, int byte3){
 281   Serial.print(byte1, BYTE);
 282   Serial.print(byte2, BYTE);
 283   Serial.print(byte3, BYTE);
 284 }
 285 
 286 void eventSerialPrint(int byte1, int byte2, int byte3){
 287   serialPrint(byte1, byte2, byte3);
 288   writeCount = writeCount + 3;
 289   eventCount++;
 290 }
 291 // nl.tue.id.creapro +<<<<< 
 292  
 293 /* -----------------------------------------------------------------------------
 294  * output the version message to the serial port  */
 295 void printVersion() {
 296   // nl.tue.id.creapro ->>>>>
 297   // Serial.print(REPORT_VERSION, BYTE);
 298   // Serial.print(FIRMATA_MINOR_VERSION, BYTE);
 299   // Serial.print(FIRMATA_MAJOR_VERSION, BYTE);
 300   // nl.tue.id.creatpro -<<<<<
 301   // nl.tue.id.creapro +>>>>>
 302   serialPrint(REPORT_VERSION,FIRMATA_MINOR_VERSION,FIRMATA_MAJOR_VERSION);
 303   // nl.tue.id.creapro +<<<<<  
 304 }
 305 
 306 /* -----------------------------------------------------------------------------
 307  * output digital bytes received from the serial port  */
 308 void outputDigitalBytes(byte pin0_6, byte pin7_13) {
 309   int i;
 310   int mask;
 311   int twoBytesForPorts;
 312     
 313 // this should be converted to use PORTs
 314   twoBytesForPorts = pin0_6 + (pin7_13 << 7);
 315   for(i=2; i<TOTAL_DIGITAL_PINS; ++i) { // ignore Rx,Tx pins (0 and 1)
 316     mask = 1 << i;
 317     if( (digitalPinStatus & mask) && !(pwmStatus & mask) ) {
 318       digitalWrite(i, twoBytesForPorts & mask ? HIGH : LOW);
 319     } 
 320   }
 321 }
 322 
 323 /* -----------------------------------------------------------------------------
 324  * check all the active digital inputs for change of state, then add any events
 325  * to the Serial output queue using Serial.print() */
 326 void checkDigitalInputs(void) {
 327   if(digitalInputsEnabled) {
 328         previousDigitalInputs = digitalInputs;
 329         digitalInputs = PINB << 8;  // get pins 8-13
 330         digitalInputs += PIND;      // get pins 0-7
 331         digitalInputs = digitalInputs & ~digitalPinStatus; // ignore pins set OUTPUT
 332         if(digitalInputs != previousDigitalInputs) {
 333           // TODO: implement more ports as channels for more than 16 digital pins
 334           // nl.tue.id.creapro ->>>>>
 335           // Serial.print(DIGITAL_MESSAGE,BYTE);
 336           // Serial.print(digitalInputs % 128, BYTE); // Tx pins 0-6
 337           // Serial.print(digitalInputs >> 7, BYTE);  // Tx pins 7-13
 338           // nl.tue.id.creatpro -<<<<<
 339           eventSerialPrint(DIGITAL_MESSAGE,
 340                       digitalInputs % 128, // Tx pins 0-6
 341                       digitalInputs >> 7); // Tx pins 7-13
 342         }
 343   }
 344 }
 345 
 346 // -----------------------------------------------------------------------------
 347 /* sets the pin mode to the correct state and sets the relevant bits in the
 348  * two bit-arrays that track Digital I/O and PWM status
 349  */
 350 void setPinMode(byte pin, byte mode) {
 351   if(pin > 1) { // ignore RxTx pins (0,1)
 352         if(mode == INPUT) {
 353           digitalPinStatus = digitalPinStatus &~ (1 << pin);
 354           pwmStatus = pwmStatus &~ (1 << pin);
 355           digitalWrite(pin,LOW); // turn off pin before switching to INPUT
 356           pinMode(pin,INPUT);
 357         }
 358         else if(mode == OUTPUT) {
 359           digitalPinStatus = digitalPinStatus | (1 << pin);
 360           pwmStatus = pwmStatus &~ (1 << pin);
 361           pinMode(pin,OUTPUT);
 362         }
 363         else if( mode == PWM ) {
 364           digitalPinStatus = digitalPinStatus | (1 << pin);
 365           pwmStatus = pwmStatus | (1 << pin);
 366           pinMode(pin,OUTPUT);
 367         }
 368   // TODO: save status to EEPROM here, if changed
 369   }
 370 }
 371 
 372 // -----------------------------------------------------------------------------
 373 /* sets bits in a bit array (int) to toggle the reporting of the analogIns
 374  */
 375 void setAnalogPinReporting(byte pin, byte state) {
 376   if(state == 0) {
 377     analogPinsToReport = analogPinsToReport &~ (1 << pin);
 378   }
 379   else { // everything but 0 enables reporting of that pin
 380     analogPinsToReport = analogPinsToReport | (1 << pin);
 381   }
 382   // TODO: save status to EEPROM here, if changed
 383 }
 384 
 385 /* -----------------------------------------------------------------------------
 386  * processInput() is called whenever a byte is available on the
 387  * Arduino's serial port.  This is where the commands are handled. */
 388 void processInput(int inputData) {
 389   int command;
 390   // nl.tue.id.creapro +>>>>>
 391   readCount ++;
 392   // nl.tue.id.creapro +<<<<<
 393   
 394   // a few commands have byte(s) of data following the command
 395   if( (waitForData > 0) && (inputData < 128) ) {  
 396     waitForData--;
 397     storedInputData[waitForData] = inputData;
 398     if( (waitForData==0) && executeMultiByteCommand ) { // got the whole message
 399       // nl.tue.id.creapro +>>>>>
 400       commandCount++;
 401       // nl.tue.id.creapro +<<<<<
 402       switch(executeMultiByteCommand) {
 403       case ANALOG_MESSAGE:
 404                 setPinMode(multiByteChannel,PWM);
 405                 analogWrite(multiByteChannel, 
 406                 (storedInputData[0] << 7) + storedInputData[1] );
 407         break;
 408       case DIGITAL_MESSAGE:
 409                 outputDigitalBytes(storedInputData[1], storedInputData[0]); //(LSB, MSB)
 410                 break;
 411       case SET_DIGITAL_PIN_MODE:
 412                 setPinMode(storedInputData[1], storedInputData[0]); // (pin#, mode)
 413                 if(storedInputData[0] == INPUT) 
 414                   digitalInputsEnabled = true; // enable reporting of digital inputs
 415         break;
 416       case REPORT_ANALOG_PIN:
 417                 setAnalogPinReporting(multiByteChannel,storedInputData[0]);
 418         break;
 419       case REPORT_DIGITAL_PORTS:
 420                 // TODO: implement MIDI channel as port base for more than 16 digital inputs
 421                 if(storedInputData[0] == 0)
 422                   digitalInputsEnabled = false;
 423                 else
 424                   digitalInputsEnabled = true;
 425         break;
 426       // nl.tue.id.creapro +>>>>>
 427       case CONFIG:
 428       //case DEBUG:
 429             switch(storedInputData[1]&0xF0){
 430               case SERIAL_PULL_RATE:
 431                   serialPullRate = (storedInputData[1]&0x0F)*128 + storedInputData[0];
 432                   break;
 433               case ANALOG_PULL_RATE:
 434                   analogPullRate = (storedInputData[1]&0x0F)*128 + storedInputData[0];
 435                   break;
 436               case ANALOG_STEP:
 437                   analogStep = (storedInputData[1]&0x0F)*128 + storedInputData[0];
 438                   break;
 439               case READ_COUNT:
 440                    switch(storedInputData[0]){
 441                      case 0:
 442                          readCount = 0;
 443                          break;
 444                      case 1:
 445                          readCount -= 2;
 446                          serialPrint(DEBUG, READ_COUNT|((readCount>>7)&0x0F), readCount % 128);
 447                          break;
 448                    }
 449                    break;
 450               case WRITE_COUNT:
 451                    switch(storedInputData[0]){
 452                      case 0:
 453                          writeCount = 0;
 454                          break;
 455                      case 1:
 456                          serialPrint(DEBUG, WRITE_COUNT|((writeCount>>7)&0x0F), writeCount % 128);
 457                          break;
 458                    }
 459                    break;                 
 460               case COMMAND_COUNT:
 461                    switch(storedInputData[0]){
 462                      case 0:
 463                          commandCount = 0;
 464                          break;
 465                      case 1:
 466                          commandCount -= 1;
 467                          serialPrint(DEBUG, COMMAND_COUNT|((commandCount>>7)&0x0F), commandCount % 128);
 468                          break;
 469                    }
 470                    break;    
 471               case EVENT_COUNT:
 472                    switch(storedInputData[0]){
 473                      case 0:
 474                          eventCount = 0;
 475                          break;
 476                      case 1:
 477                          serialPrint(DEBUG, EVENT_COUNT|((eventCount>>7)&0x0F), eventCount % 128);
 478                          break;
 479                    }
 480                    break;               
 481             }
 482             break;
 483       // nl.tue.id.creapro +<<<<<
 484       }
 485       executeMultiByteCommand = 0;
 486     }   
 487   } else {
 488     // remove channel info from command byte if less than 0xF0
 489     if(inputData < 0xF0) {
 490       command = inputData & 0xF0;
 491           multiByteChannel = inputData & 0x0F;
 492     } else {
 493       command = inputData;
 494           // commands in the 0xF* range don't use channel data
 495     }
 496     switch (command) { // TODO: these needs to be switched to command
 497     case ANALOG_MESSAGE:
 498     case DIGITAL_MESSAGE:
 499     case SET_DIGITAL_PIN_MODE:
 500     // nl.tue.id.creapro +>>>>>
 501     case CONFIG:
 502     //case DEBUG:
 503     // nl.tue.id.creapro +<<<<<   
 504       waitForData = 2; // two data bytes needed
 505       executeMultiByteCommand = command;
 506       break;
 507     case REPORT_ANALOG_PIN:
 508     case REPORT_DIGITAL_PORTS:
 509       waitForData = 1; // two data bytes needed
 510       executeMultiByteCommand = command;
 511       break;
 512     case SYSTEM_RESET:
 513       // this doesn't do anything yet
 514       break;
 515     case REPORT_VERSION:
 516           printVersion();
 517       break;
 518     }
 519   }
 520 }
 521 
 522 /* -----------------------------------------------------------------------------
 523  * this function checks to see if there is data waiting on the serial port 
 524  * then processes all of the stored data
 525  */
 526 void checkForSerialReceive() {
 527   while(Serial.available())
 528         processInput(Serial.read());
 529 }
 530 
 531 // =============================================================================
 532 // used for flashing the pin for the version number
 533 void pin13strobe(int count, int onInterval, int offInterval) {
 534   byte i;
 535   pinMode(13, OUTPUT);
 536   for(i=0; i<count; i++) {
 537     delay(offInterval);
 538     digitalWrite(13,1);
 539     delay(onInterval);
 540     digitalWrite(13,0);
 541   }
 542 }
 543 
 544 /*==============================================================================
 545  * SETUP()
 546  *============================================================================*/
 547 void setup() {
 548   byte i;
 549 
 550   Serial.begin(57600); // 9600, 14400, 38400, 57600, 115200
 551 
 552   // flash the pin 13 with the protocol version
 553   pinMode(13,OUTPUT);
 554   pin13strobe(2,1,4); // separator, a quick burst
 555   delay(500);
 556   pin13strobe(FIRMATA_MAJOR_VERSION, 200, 400);
 557   delay(500);
 558   pin13strobe(2,1,4); // separator, a quick burst
 559   delay(500);
 560   pin13strobe(FIRMATA_MINOR_VERSION, 200, 400);
 561   delay(500);
 562   pin13strobe(2,1,4); // separator, a quick burst
 563 
 564 
 565   // nl.tue.id.creapro +>>>>>
 566   for(i=0; i<TOTAL_ANALOG_PINS; ++i) {
 567     storedAnalogData[i] = 0;
 568   // nl.tue.id.creapro +<<<<< 
 569  
 570   }
 571   // TODO: load state from EEPROM here
 572 
 573   printVersion();
 574  
 575  // nl.tue.id.creapro +>>>>>
 576  // make sure we did not miss anything important
 577  checkForSerialReceive();
 578  // nl.tue.id.creapro +<<<<<
 579 
 580   /* TODO: send digital inputs here, if enabled, to set the initial state on the
 581    * host computer, since once in the loop(), the Arduino will only send data on
 582    * change. */
 583 }
 584 
 585 /*==============================================================================
 586  * LOOP()
 587  *============================================================================*/
 588 // nl.tue.id.creapro ->>>>>
 589 //void loop() {
 590 ///* DIGITALREAD - as fast as possible, check for changes and output them to the
 591 // * FTDI buffer using Serial.print()  */
 592 //  checkDigitalInputs();  
 593 //  if(timer0_overflow_count > nextExecuteTime) {  
 594 //      nextExecuteTime = timer0_overflow_count + 19; // run this every 20ms
 595 //      /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle
 596 //       * all serialReads at once, i.e. empty the buffer */
 597 //      checkForSerialReceive();
 598 //      /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
 599 //       * 60 bytes. use a timer to sending an event character every 4 ms to
 600 //       * trigger the buffer to dump. */
 601 //      
 602 //      /* ANALOGREAD - right after the event character, do all of the
 603 //       * analogReads().  These only need to be done every 4ms. */
 604 //      for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) {
 605 //        if( analogPinsToReport & (1 << analogPin) ) {
 606 //              analogData = analogRead(analogPin);
 607 //              Serial.print(ANALOG_MESSAGE + analogPin, BYTE);
 608 //              // These two bytes converted back into the 10-bit value on host
 609 //              Serial.print(analogData % 128, BYTE);
 610 //              Serial.print(analogData >> 7, BYTE); 
 611 //        }
 612 //      }
 613 //  }
 614 //}
 615 // nl.tue.id.creapro +>>>>>
 616 void loop() {
 617 /* DIGITALREAD - as fast as possible, check for changes and output them to the
 618  * FTDI buffer using Serial.print()  */
 619   checkDigitalInputs();  
 620   if(timer0_overflow_count > nextExecuteTime) {  
 621         nextExecuteTime = timer0_overflow_count + serialPullRate -1; // run this every 20ms
 622         /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle
 623          * all serialReads at once, i.e. empty the buffer */
 624         checkForSerialReceive();
 625         /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
 626          * 60 bytes. use a timer to sending an event character every 4 ms to
 627          * trigger the buffer to dump. */
 628 
 629   }
 630   
 631   if(timer0_overflow_count > nextAnalogExecuteTime) {  
 632         nextAnalogExecuteTime = timer0_overflow_count + analogPullRate -1; // run this every 20ms
 633         /* ANALOGREAD - right after the event character, do all of the
 634          * analogReads().  These only need to be done every 4ms. */
 635         for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) {
 636           if( analogPinsToReport & (1 << analogPin) ) {
 637                 analogData = analogRead(analogPin);
 638 
 639                 if(abs(analogData - storedAnalogData[analogPin])<analogStep) continue;
 640 
 641                 storedAnalogData[analogPin] = analogData;
 642                 eventSerialPrint(ANALOG_MESSAGE + analogPin, 
 643                             analogData % 128,
 644                             analogData >> 7);
 645           }
 646         }
 647   }  
 648 }
 649 // nl.tue.id.creapro +<<<<<
 650