source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/libraries/Firmata/examples/OldStandardFirmata/OldStandardFirmata.ino @ 46

Last change on this file since 46 was 46, checked in by jrpelegrina, 4 years ago

First release to Xenial

File size: 7.7 KB
Line 
1/*
2 * Firmata is a generic protocol for communicating with microcontrollers
3 * from software on a host computer. It is intended to work with
4 * any host computer software package.
5 *
6 * To download a host software package, please clink on the following link
7 * to open the download page in your default browser.
8 *
9 * http://firmata.org/wiki/Download
10 */
11
12/*
13  Copyright (C) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
14
15  This library is free software; you can redistribute it and/or
16  modify it under the terms of the GNU Lesser General Public
17  License as published by the Free Software Foundation; either
18  version 2.1 of the License, or (at your option) any later version.
19
20  See file LICENSE.txt for further informations on licensing terms.
21 */
22
23/*
24 * This is an old version of StandardFirmata (v2.0).  It is kept here because
25 * its the last version that works on an ATMEGA8 chip.  Also, it can be used
26 * for host software that has not been updated to a newer version of the
27 * protocol.  It also uses the old baud rate of 115200 rather than 57600.
28 */
29
30#include <EEPROM.h>
31#include <Firmata.h>
32
33/*==============================================================================
34 * GLOBAL VARIABLES
35 *============================================================================*/
36
37/* analog inputs */
38int analogInputsToReport = 0; // bitwise array to store pin reporting
39int analogPin = 0; // counter for reading analog pins
40
41/* digital pins */
42byte reportPINs[TOTAL_PORTS];   // PIN == input port
43byte previousPINs[TOTAL_PORTS]; // PIN == input port
44byte pinStatus[TOTAL_PINS]; // store pin status, default OUTPUT
45byte portStatus[TOTAL_PORTS];
46
47/* timer variables */
48unsigned long currentMillis;     // store the current value from millis()
49unsigned long previousMillis;    // for comparison with currentMillis
50
51
52/*==============================================================================
53 * FUNCTIONS
54 *============================================================================*/
55
56void outputPort(byte portNumber, byte portValue)
57{
58  portValue = portValue & ~ portStatus[portNumber];
59  if (previousPINs[portNumber] != portValue) {
60    Firmata.sendDigitalPort(portNumber, portValue);
61    previousPINs[portNumber] = portValue;
62    Firmata.sendDigitalPort(portNumber, portValue);
63  }
64}
65
66/* -----------------------------------------------------------------------------
67 * check all the active digital inputs for change of state, then add any events
68 * to the Serial output queue using Serial.print() */
69void checkDigitalInputs(void)
70{
71  byte i, tmp;
72  for (i = 0; i < TOTAL_PORTS; i++) {
73    if (reportPINs[i]) {
74      switch (i) {
75        case 0: outputPort(0, PIND & ~ B00000011); break; // ignore Rx/Tx 0/1
76        case 1: outputPort(1, PINB); break;
77        case 2: outputPort(2, PINC); break;
78      }
79    }
80  }
81}
82
83// -----------------------------------------------------------------------------
84/* sets the pin mode to the correct state and sets the relevant bits in the
85 * two bit-arrays that track Digital I/O and PWM status
86 */
87void setPinModeCallback(byte pin, int mode) {
88  byte port = 0;
89  byte offset = 0;
90
91  if (pin < 8) {
92    port = 0;
93    offset = 0;
94  } else if (pin < 14) {
95    port = 1;
96    offset = 8;
97  } else if (pin < 22) {
98    port = 2;
99    offset = 14;
100  }
101
102  if (pin > 1) { // ignore RxTx (pins 0 and 1)
103    pinStatus[pin] = mode;
104    switch (mode) {
105      case INPUT:
106        pinMode(pin, INPUT);
107        portStatus[port] = portStatus[port] & ~ (1 << (pin - offset));
108        break;
109      case OUTPUT:
110        digitalWrite(pin, LOW); // disable PWM
111      case PWM:
112        pinMode(pin, OUTPUT);
113        portStatus[port] = portStatus[port] | (1 << (pin - offset));
114        break;
115      //case ANALOG: // TODO figure this out
116      default:
117        Firmata.sendString("");
118    }
119    // TODO: save status to EEPROM here, if changed
120  }
121}
122
123void analogWriteCallback(byte pin, int value)
124{
125  setPinModeCallback(pin, PIN_MODE_PWM);
126  analogWrite(pin, value);
127}
128
129void digitalWriteCallback(byte port, int value)
130{
131  switch (port) {
132    case 0: // pins 2-7 (don't change Rx/Tx, pins 0 and 1)
133      // 0xFF03 == B1111111100000011    0x03 == B00000011
134      PORTD = (value & ~ 0xFF03) | (PORTD & 0x03);
135      break;
136    case 1: // pins 8-13 (14,15 are disabled for the crystal)
137      PORTB = (byte)value;
138      break;
139    case 2: // analog pins used as digital
140      PORTC = (byte)value;
141      break;
142  }
143}
144
145// -----------------------------------------------------------------------------
146/* sets bits in a bit array (int) to toggle the reporting of the analogIns
147 */
148//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
149//}
150void reportAnalogCallback(byte pin, int value)
151{
152  if (value == 0) {
153    analogInputsToReport = analogInputsToReport & ~ (1 << pin);
154  }
155  else { // everything but 0 enables reporting of that pin
156    analogInputsToReport = analogInputsToReport | (1 << pin);
157  }
158  // TODO: save status to EEPROM here, if changed
159}
160
161void reportDigitalCallback(byte port, int value)
162{
163  reportPINs[port] = (byte)value;
164  if (port == 2) // turn off analog reporting when used as digital
165    analogInputsToReport = 0;
166}
167
168/*==============================================================================
169 * SETUP()
170 *============================================================================*/
171void setup()
172{
173  byte i;
174
175  Firmata.setFirmwareVersion(2, 0);
176
177  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
178  Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
179  Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
180  Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
181  Firmata.attach(SET_PIN_MODE, setPinModeCallback);
182
183  portStatus[0] = B00000011;  // ignore Tx/RX pins
184  portStatus[1] = B11000000;  // ignore 14/15 pins
185  portStatus[2] = B00000000;
186
187  //    for(i=0; i<TOTAL_PINS; ++i) { // TODO make this work with analogs
188  for (i = 0; i < 14; ++i) {
189    setPinModeCallback(i, OUTPUT);
190  }
191  // set all outputs to 0 to make sure internal pull-up resistors are off
192  PORTB = 0; // pins 8-15
193  PORTC = 0; // analog port
194  PORTD = 0; // pins 0-7
195
196  // TODO rethink the init, perhaps it should report analog on default
197  for (i = 0; i < TOTAL_PORTS; ++i) {
198    reportPINs[i] = false;
199  }
200  // TODO: load state from EEPROM here
201
202  /* send digital inputs here, if enabled, to set the initial state on the
203   * host computer, since once in the loop(), this firmware will only send
204   * digital data on change. */
205  if (reportPINs[0]) outputPort(0, PIND & ~ B00000011); // ignore Rx/Tx 0/1
206  if (reportPINs[1]) outputPort(1, PINB);
207  if (reportPINs[2]) outputPort(2, PINC);
208
209  Firmata.begin(115200);
210}
211
212/*==============================================================================
213 * LOOP()
214 *============================================================================*/
215void loop()
216{
217  /* DIGITALREAD - as fast as possible, check for changes and output them to the
218   * FTDI buffer using Serial.print()  */
219  checkDigitalInputs();
220  currentMillis = millis();
221  if (currentMillis - previousMillis > 20) {
222    previousMillis += 20;     // run this every 20ms
223    /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle
224     * all serialReads at once, i.e. empty the buffer */
225    while (Firmata.available())
226      Firmata.processInput();
227    /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
228     * 60 bytes. use a timer to sending an event character every 4 ms to
229     * trigger the buffer to dump. */
230
231    /* ANALOGREAD - right after the event character, do all of the
232     * analogReads().  These only need to be done every 4ms. */
233    for (analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) {
234      if ( analogInputsToReport & (1 << analogPin) ) {
235        Firmata.sendAnalog(analogPin, analogRead(analogPin));
236      }
237    }
238  }
239}
Note: See TracBrowser for help on using the repository browser.