3 Copyright (C) 2016 Jeff Hoefs. All rights reserved.
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.
10 See file LICENSE.txt for further informations on licensing terms.
12 This version of SerialFirmata.cpp differs from the ConfigurableFirmata
13 version in the following ways:
15 - handlePinMode calls Firmata::setPinMode
17 Last updated October 16th, 2016
20 #include "SerialFirmata.h"
22 SerialFirmata::SerialFirmata()
24 #if defined(SoftwareSerial_h)
34 boolean SerialFirmata::handlePinMode(byte pin, int mode)
36 // used for both HW and SW serial
37 if (mode == PIN_MODE_SERIAL) {
38 Firmata.setPinMode(pin, PIN_MODE_SERIAL);
44 void SerialFirmata::handleCapability(byte pin)
46 if (IS_PIN_SERIAL(pin)) {
47 Firmata.write(PIN_MODE_SERIAL);
48 Firmata.write(getSerialPinType(pin));
52 boolean SerialFirmata::handleSysex(byte command, byte argc, byte *argv)
54 if (command == SERIAL_MESSAGE) {
57 byte mode = argv[0] & SERIAL_MODE_MASK;
58 byte portId = argv[0] & SERIAL_PORT_ID_MASK;
63 long baud = (long)argv[1] | ((long)argv[2] << 7) | ((long)argv[3] << 14);
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);
77 ((HardwareSerial*)serialPort)->begin(baud);
80 #if defined(SoftwareSerial_h)
81 byte swTxPin, swRxPin;
86 // RX and TX pins must be specified when using SW serial
87 Firmata.sendString("Specify serial RX and TX pins");
92 if (swSerial0 == NULL) {
93 swSerial0 = new SoftwareSerial(swRxPin, swTxPin);
97 if (swSerial1 == NULL) {
98 swSerial1 = new SoftwareSerial(swRxPin, swTxPin);
102 if (swSerial2 == NULL) {
103 swSerial2 = new SoftwareSerial(swRxPin, swTxPin);
107 if (swSerial3 == NULL) {
108 swSerial3 = new SoftwareSerial(swRxPin, swTxPin);
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);
120 break; // SERIAL_CONFIG
125 serialPort = getPortFromId(portId);
126 if (serialPort == NULL) {
129 for (byte i = 1; i < argc; i += 2) {
130 data = argv[i] + (argv[i + 1] << 7);
131 serialPort->write(data);
133 break; // SERIAL_WRITE
136 if (argv[1] == SERIAL_READ_CONTINUOUSLY) {
137 if (serialIndex + 1 >= MAX_SERIAL_PORTS) {
142 // maximum number of bytes to read from buffer per iteration of loop()
143 serialBytesToRead[portId] = (int)argv[2] | ((int)argv[3] << 7);
145 // read all available bytes per iteration of loop()
146 serialBytesToRead[portId] = 0;
149 reportSerial[serialIndex] = portId;
150 } else if (argv[1] == SERIAL_STOP_READING) {
151 byte serialIndexToSkip = 0;
152 if (serialIndex <= 0) {
155 for (byte i = 0; i < serialIndex + 1; i++) {
156 if (reportSerial[i] == portId) {
157 serialIndexToSkip = i;
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];
170 break; // SERIAL_READ
172 serialPort = getPortFromId(portId);
173 if (serialPort != NULL) {
175 ((HardwareSerial*)serialPort)->end();
177 #if defined(SoftwareSerial_h)
178 ((SoftwareSerial*)serialPort)->end();
179 if (serialPort != NULL) {
186 break; // SERIAL_CLOSE
188 serialPort = getPortFromId(portId);
189 if (serialPort != NULL) {
190 getPortFromId(portId)->flush();
192 break; // SERIAL_FLUSH
193 #if defined(SoftwareSerial_h)
195 // can only call listen() on software serial ports
197 serialPort = getPortFromId(portId);
198 if (serialPort != NULL) {
199 ((SoftwareSerial*)serialPort)->listen();
202 break; // SERIAL_LISTEN
210 void SerialFirmata::update()
215 void SerialFirmata::reset()
217 #if defined(SoftwareSerial_h)
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) {
230 for (byte i = 0; i < SERIAL_READ_ARR_LEN; i++) {
231 serialBytesToRead[i] = 0;
235 // get a pointer to the serial port associated with the specified port id
236 Stream* SerialFirmata::getPortFromId(byte portId)
240 // block use of Serial (typically pins 0 and 1) until ability to reclaim Serial is implemented
243 #if defined(PIN_SERIAL1_RX)
247 #if defined(PIN_SERIAL2_RX)
251 #if defined(PIN_SERIAL3_RX)
255 #if defined(PIN_SERIAL4_RX)
259 #if defined(PIN_SERIAL5_RX)
263 #if defined(PIN_SERIAL6_RX)
267 #if defined(SoftwareSerial_h)
269 if (swSerial0 != NULL) {
270 // instances of SoftwareSerial are already pointers so simply return the instance
275 if (swSerial1 != NULL) {
280 if (swSerial2 != NULL) {
285 if (swSerial3 != NULL) {
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()
298 byte portId, serialData;
300 int numBytesToRead = 0;
303 if (serialIndex > -1) {
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) {
313 #if defined(SoftwareSerial_h)
314 // only the SoftwareSerial port that is "listening" can read data
315 if (portId > 7 && !((SoftwareSerial*)serialPort)->isListening()) {
319 if (serialPort->available() > 0) {
320 Firmata.write(START_SYSEX);
321 Firmata.write(SERIAL_MESSAGE);
322 Firmata.write(SERIAL_REPLY | portId);
324 if (bytesToRead == 0 || (serialPort->available() <= bytesToRead)) {
325 numBytesToRead = serialPort->available();
327 numBytesToRead = bytesToRead;
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);
337 Firmata.write(END_SYSEX);