source: rtos_arduino/trunk/arduino_lib/libraries/Firmata/utility/SerialFirmata.cpp@ 224

Last change on this file since 224 was 224, checked in by ertl-honda, 8 years ago

1.7.10のファイルに更新

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