Statistics
| Branch: | Revision:

root / arduino-1.0 / libraries / Firmata / examples / OldStandardFirmata / OldStandardFirmata.ino @ 58d82c77

History | View | Annotate | Download (8.01 KB)

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 */
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
}