]> AND Private Git Repository - Cipher_code.git/blob - Arduino/libraries/Firmata/utility/SerialFirmata.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
aze
[Cipher_code.git] / Arduino / libraries / Firmata / utility / SerialFirmata.cpp
1 /*
2   SerialFirmata.cpp
3   Copyright (C) 2016 Jeff Hoefs. All rights reserved.
4
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   See file LICENSE.txt for further informations on licensing terms.
11
12   This version of SerialFirmata.cpp differs from the ConfigurableFirmata
13   version in the following ways:
14
15   - handlePinMode calls Firmata::setPinMode
16
17   Last updated October 16th, 2016
18 */
19
20 #include "SerialFirmata.h"
21
22 SerialFirmata::SerialFirmata()
23 {
24 #if defined(SoftwareSerial_h)
25   swSerial0 = NULL;
26   swSerial1 = NULL;
27   swSerial2 = NULL;
28   swSerial3 = NULL;
29 #endif
30
31   serialIndex = -1;
32 }
33
34 boolean SerialFirmata::handlePinMode(byte pin, int mode)
35 {
36   // used for both HW and SW serial
37   if (mode == PIN_MODE_SERIAL) {
38     Firmata.setPinMode(pin, PIN_MODE_SERIAL);
39     return true;
40   }
41   return false;
42 }
43
44 void SerialFirmata::handleCapability(byte pin)
45 {
46   if (IS_PIN_SERIAL(pin)) {
47     Firmata.write(PIN_MODE_SERIAL);
48     Firmata.write(getSerialPinType(pin));
49   }
50 }
51
52 boolean SerialFirmata::handleSysex(byte command, byte argc, byte *argv)
53 {
54   if (command == SERIAL_MESSAGE) {
55
56     Stream *serialPort;
57     byte mode = argv[0] & SERIAL_MODE_MASK;
58     byte portId = argv[0] & SERIAL_PORT_ID_MASK;
59
60     switch (mode) {
61       case SERIAL_CONFIG:
62         {
63           long baud = (long)argv[1] | ((long)argv[2] << 7) | ((long)argv[3] << 14);
64           serial_pins pins;
65
66           if (portId < 8) {
67             serialPort = getPortFromId(portId);
68             if (serialPort != NULL) {
69               pins = getSerialPinNumbers(portId);
70               if (pins.rx != 0 && pins.tx != 0) {
71                 Firmata.setPinMode(pins.rx, PIN_MODE_SERIAL);
72                 Firmata.setPinMode(pins.tx, PIN_MODE_SERIAL);
73                 // Fixes an issue where some serial devices would not work properly with Arduino Due
74                 // because all Arduino pins are set to OUTPUT by default in StandardFirmata.
75                 pinMode(pins.rx, INPUT);
76               }
77               ((HardwareSerial*)serialPort)->begin(baud);
78             }
79           } else {
80 #if defined(SoftwareSerial_h)
81             byte swTxPin, swRxPin;
82             if (argc > 4) {
83               swRxPin = argv[4];
84               swTxPin = argv[5];
85             } else {
86               // RX and TX pins must be specified when using SW serial
87               Firmata.sendString("Specify serial RX and TX pins");
88               return false;
89             }
90             switch (portId) {
91               case SW_SERIAL0:
92                 if (swSerial0 == NULL) {
93                   swSerial0 = new SoftwareSerial(swRxPin, swTxPin);
94                 }
95                 break;
96               case SW_SERIAL1:
97                 if (swSerial1 == NULL) {
98                   swSerial1 = new SoftwareSerial(swRxPin, swTxPin);
99                 }
100                 break;
101               case SW_SERIAL2:
102                 if (swSerial2 == NULL) {
103                   swSerial2 = new SoftwareSerial(swRxPin, swTxPin);
104                 }
105                 break;
106               case SW_SERIAL3:
107                 if (swSerial3 == NULL) {
108                   swSerial3 = new SoftwareSerial(swRxPin, swTxPin);
109                 }
110                 break;
111             }
112             serialPort = getPortFromId(portId);
113             if (serialPort != NULL) {
114               Firmata.setPinMode(swRxPin, PIN_MODE_SERIAL);
115               Firmata.setPinMode(swTxPin, PIN_MODE_SERIAL);
116               ((SoftwareSerial*)serialPort)->begin(baud);
117             }
118 #endif
119           }
120           break; // SERIAL_CONFIG
121         }
122       case SERIAL_WRITE:
123         {
124           byte data;
125           serialPort = getPortFromId(portId);
126           if (serialPort == NULL) {
127             break;
128           }
129           for (byte i = 1; i < argc; i += 2) {
130             data = argv[i] + (argv[i + 1] << 7);
131             serialPort->write(data);
132           }
133           break; // SERIAL_WRITE
134         }
135       case SERIAL_READ:
136         if (argv[1] == SERIAL_READ_CONTINUOUSLY) {
137           if (serialIndex + 1 >= MAX_SERIAL_PORTS) {
138             break;
139           }
140
141           if (argc > 2) {
142             // maximum number of bytes to read from buffer per iteration of loop()
143             serialBytesToRead[portId] = (int)argv[2] | ((int)argv[3] << 7);
144           } else {
145             // read all available bytes per iteration of loop()
146             serialBytesToRead[portId] = 0;
147           }
148           serialIndex++;
149           reportSerial[serialIndex] = portId;
150         } else if (argv[1] == SERIAL_STOP_READING) {
151           byte serialIndexToSkip = 0;
152           if (serialIndex <= 0) {
153             serialIndex = -1;
154           } else {
155             for (byte i = 0; i < serialIndex + 1; i++) {
156               if (reportSerial[i] == portId) {
157                 serialIndexToSkip = i;
158                 break;
159               }
160             }
161             // shift elements over to fill space left by removed element
162             for (byte i = serialIndexToSkip; i < serialIndex + 1; i++) {
163               if (i < MAX_SERIAL_PORTS) {
164                 reportSerial[i] = reportSerial[i + 1];
165               }
166             }
167             serialIndex--;
168           }
169         }
170         break; // SERIAL_READ
171       case SERIAL_CLOSE:
172         serialPort = getPortFromId(portId);
173         if (serialPort != NULL) {
174           if (portId < 8) {
175             ((HardwareSerial*)serialPort)->end();
176           } else {
177 #if defined(SoftwareSerial_h)
178             ((SoftwareSerial*)serialPort)->end();
179             if (serialPort != NULL) {
180               free(serialPort);
181               serialPort = NULL;
182             }
183 #endif
184           }
185         }
186         break; // SERIAL_CLOSE
187       case SERIAL_FLUSH:
188         serialPort = getPortFromId(portId);
189         if (serialPort != NULL) {
190           getPortFromId(portId)->flush();
191         }
192         break; // SERIAL_FLUSH
193 #if defined(SoftwareSerial_h)
194       case SERIAL_LISTEN:
195         // can only call listen() on software serial ports
196         if (portId > 7) {
197           serialPort = getPortFromId(portId);
198           if (serialPort != NULL) {
199             ((SoftwareSerial*)serialPort)->listen();
200           }
201         }
202         break; // SERIAL_LISTEN
203 #endif
204     } // end switch
205     return true;
206   }
207   return false;
208 }
209
210 void SerialFirmata::update()
211 {
212   checkSerial();
213 }
214
215 void SerialFirmata::reset()
216 {
217 #if defined(SoftwareSerial_h)
218   Stream *serialPort;
219   // free memory allocated for SoftwareSerial ports
220   for (byte i = SW_SERIAL0; i < SW_SERIAL3 + 1; i++) {
221     serialPort = getPortFromId(i);
222     if (serialPort != NULL) {
223       free(serialPort);
224       serialPort = NULL;
225     }
226   }
227 #endif
228
229   serialIndex = -1;
230   for (byte i = 0; i < SERIAL_READ_ARR_LEN; i++) {
231     serialBytesToRead[i] = 0;
232   }
233 }
234
235 // get a pointer to the serial port associated with the specified port id
236 Stream* SerialFirmata::getPortFromId(byte portId)
237 {
238   switch (portId) {
239     case HW_SERIAL0:
240       // block use of Serial (typically pins 0 and 1) until ability to reclaim Serial is implemented
241       //return &Serial;
242       return NULL;
243 #if defined(PIN_SERIAL1_RX)
244     case HW_SERIAL1:
245       return &Serial1;
246 #endif
247 #if defined(PIN_SERIAL2_RX)
248     case HW_SERIAL2:
249       return &Serial2;
250 #endif
251 #if defined(PIN_SERIAL3_RX)
252     case HW_SERIAL3:
253       return &Serial3;
254 #endif
255 #if defined(PIN_SERIAL4_RX)
256     case HW_SERIAL4:
257       return &Serial4;
258 #endif
259 #if defined(PIN_SERIAL5_RX)
260     case HW_SERIAL5:
261       return &Serial5;
262 #endif
263 #if defined(PIN_SERIAL6_RX)
264     case HW_SERIAL6:
265       return &Serial6;
266 #endif
267 #if defined(SoftwareSerial_h)
268     case SW_SERIAL0:
269       if (swSerial0 != NULL) {
270         // instances of SoftwareSerial are already pointers so simply return the instance
271         return swSerial0;
272       }
273       break;
274     case SW_SERIAL1:
275       if (swSerial1 != NULL) {
276         return swSerial1;
277       }
278       break;
279     case SW_SERIAL2:
280       if (swSerial2 != NULL) {
281         return swSerial2;
282       }
283       break;
284     case SW_SERIAL3:
285       if (swSerial3 != NULL) {
286         return swSerial3;
287       }
288       break;
289 #endif
290   }
291   return NULL;
292 }
293
294 // Check serial ports that have READ_CONTINUOUS mode set and relay any data
295 // for each port to the device attached to that port.
296 void SerialFirmata::checkSerial()
297 {
298   byte portId, serialData;
299   int bytesToRead = 0;
300   int numBytesToRead = 0;
301   Stream* serialPort;
302
303   if (serialIndex > -1) {
304
305     // loop through all reporting (READ_CONTINUOUS) serial ports
306     for (byte i = 0; i < serialIndex + 1; i++) {
307       portId = reportSerial[i];
308       bytesToRead = serialBytesToRead[portId];
309       serialPort = getPortFromId(portId);
310       if (serialPort == NULL) {
311         continue;
312       }
313 #if defined(SoftwareSerial_h)
314       // only the SoftwareSerial port that is "listening" can read data
315       if (portId > 7 && !((SoftwareSerial*)serialPort)->isListening()) {
316         continue;
317       }
318 #endif
319       if (serialPort->available() > 0) {
320         Firmata.write(START_SYSEX);
321         Firmata.write(SERIAL_MESSAGE);
322         Firmata.write(SERIAL_REPLY | portId);
323
324         if (bytesToRead == 0 || (serialPort->available() <= bytesToRead)) {
325           numBytesToRead = serialPort->available();
326         } else {
327           numBytesToRead = bytesToRead;
328         }
329
330         // relay serial data to the serial device
331         while (numBytesToRead > 0) {
332           serialData = serialPort->read();
333           Firmata.write(serialData & 0x7F);
334           Firmata.write((serialData >> 7) & 0x7F);
335           numBytesToRead--;
336         }
337         Firmata.write(END_SYSEX);
338       }
339
340     }
341   }
342 }