root / arduino-1.0 / libraries / Firmata / examples / OldStandardFirmata / OldStandardFirmata.ino @ 58d82c77
History | View | Annotate | Download (8.01 KB)
1 | 58d82c77 | Tom Mullins | /* |
---|---|---|---|
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 */ |
||
38 | int analogInputsToReport = 0; // bitwise array to store pin reporting |
||
39 | int analogPin = 0; // counter for reading analog pins |
||
40 | |||
41 | /* digital pins */ |
||
42 | byte reportPINs[TOTAL_PORTS]; // PIN == input port |
||
43 | byte previousPINs[TOTAL_PORTS]; // PIN == input port |
||
44 | byte pinStatus[TOTAL_PINS]; // store pin status, default OUTPUT |
||
45 | byte portStatus[TOTAL_PORTS]; |
||
46 | |||
47 | /* timer variables */ |
||
48 | unsigned long currentMillis; // store the current value from millis() |
||
49 | unsigned long previousMillis; // for comparison with currentMillis |
||
50 | |||
51 | |||
52 | /*============================================================================== |
||
53 | * FUNCTIONS |
||
54 | *============================================================================*/ |
||
55 | |||
56 | void 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() */ |
||
69 | void 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 | */ |
||
87 | void 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 | |||
123 | void analogWriteCallback(byte pin, int value) |
||
124 | { |
||
125 | setPinModeCallback(pin,PWM); |
||
126 | analogWrite(pin, value); |
||
127 | } |
||
128 | |||
129 | void 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 | //} |
||
150 | void 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 | |||
161 | void 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 | *============================================================================*/ |
||
171 | void 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 | *============================================================================*/ |
||
215 | void 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 | } |