arduino stuffs
Diffstat (limited to 'libraries/Firmata/utility/SerialFirmata.cpp')
-rw-r--r--libraries/Firmata/utility/SerialFirmata.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/libraries/Firmata/utility/SerialFirmata.cpp b/libraries/Firmata/utility/SerialFirmata.cpp
new file mode 100644
index 0000000..8b703e1
--- /dev/null
+++ b/libraries/Firmata/utility/SerialFirmata.cpp
@@ -0,0 +1,342 @@
+/*
+ SerialFirmata.cpp
+ Copyright (C) 2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ This version of SerialFirmata.cpp differs from the ConfigurableFirmata
+ version in the following ways:
+
+ - handlePinMode calls Firmata::setPinMode
+
+ Last updated October 16th, 2016
+*/
+
+#include "SerialFirmata.h"
+
+SerialFirmata::SerialFirmata()
+{
+#if defined(SoftwareSerial_h)
+ swSerial0 = NULL;
+ swSerial1 = NULL;
+ swSerial2 = NULL;
+ swSerial3 = NULL;
+#endif
+
+ serialIndex = -1;
+}
+
+boolean SerialFirmata::handlePinMode(byte pin, int mode)
+{
+ // used for both HW and SW serial
+ if (mode == PIN_MODE_SERIAL) {
+ Firmata.setPinMode(pin, PIN_MODE_SERIAL);
+ return true;
+ }
+ return false;
+}
+
+void SerialFirmata::handleCapability(byte pin)
+{
+ if (IS_PIN_SERIAL(pin)) {
+ Firmata.write(PIN_MODE_SERIAL);
+ Firmata.write(getSerialPinType(pin));
+ }
+}
+
+boolean SerialFirmata::handleSysex(byte command, byte argc, byte *argv)
+{
+ if (command == SERIAL_MESSAGE) {
+
+ Stream *serialPort;
+ byte mode = argv[0] & SERIAL_MODE_MASK;
+ byte portId = argv[0] & SERIAL_PORT_ID_MASK;
+
+ switch (mode) {
+ case SERIAL_CONFIG:
+ {
+ long baud = (long)argv[1] | ((long)argv[2] << 7) | ((long)argv[3] << 14);
+ serial_pins pins;
+
+ if (portId < 8) {
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ pins = getSerialPinNumbers(portId);
+ if (pins.rx != 0 && pins.tx != 0) {
+ Firmata.setPinMode(pins.rx, PIN_MODE_SERIAL);
+ Firmata.setPinMode(pins.tx, PIN_MODE_SERIAL);
+ // Fixes an issue where some serial devices would not work properly with Arduino Due
+ // because all Arduino pins are set to OUTPUT by default in StandardFirmata.
+ pinMode(pins.rx, INPUT);
+ }
+ ((HardwareSerial*)serialPort)->begin(baud);
+ }
+ } else {
+#if defined(SoftwareSerial_h)
+ byte swTxPin, swRxPin;
+ if (argc > 4) {
+ swRxPin = argv[4];
+ swTxPin = argv[5];
+ } else {
+ // RX and TX pins must be specified when using SW serial
+ Firmata.sendString("Specify serial RX and TX pins");
+ return false;
+ }
+ switch (portId) {
+ case SW_SERIAL0:
+ if (swSerial0 == NULL) {
+ swSerial0 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ case SW_SERIAL1:
+ if (swSerial1 == NULL) {
+ swSerial1 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ case SW_SERIAL2:
+ if (swSerial2 == NULL) {
+ swSerial2 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ case SW_SERIAL3:
+ if (swSerial3 == NULL) {
+ swSerial3 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ }
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ Firmata.setPinMode(swRxPin, PIN_MODE_SERIAL);
+ Firmata.setPinMode(swTxPin, PIN_MODE_SERIAL);
+ ((SoftwareSerial*)serialPort)->begin(baud);
+ }
+#endif
+ }
+ break; // SERIAL_CONFIG
+ }
+ case SERIAL_WRITE:
+ {
+ byte data;
+ serialPort = getPortFromId(portId);
+ if (serialPort == NULL) {
+ break;
+ }
+ for (byte i = 1; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ serialPort->write(data);
+ }
+ break; // SERIAL_WRITE
+ }
+ case SERIAL_READ:
+ if (argv[1] == SERIAL_READ_CONTINUOUSLY) {
+ if (serialIndex + 1 >= MAX_SERIAL_PORTS) {
+ break;
+ }
+
+ if (argc > 2) {
+ // maximum number of bytes to read from buffer per iteration of loop()
+ serialBytesToRead[portId] = (int)argv[2] | ((int)argv[3] << 7);
+ } else {
+ // read all available bytes per iteration of loop()
+ serialBytesToRead[portId] = 0;
+ }
+ serialIndex++;
+ reportSerial[serialIndex] = portId;
+ } else if (argv[1] == SERIAL_STOP_READING) {
+ byte serialIndexToSkip = 0;
+ if (serialIndex <= 0) {
+ serialIndex = -1;
+ } else {
+ for (byte i = 0; i < serialIndex + 1; i++) {
+ if (reportSerial[i] == portId) {
+ serialIndexToSkip = i;
+ break;
+ }
+ }
+ // shift elements over to fill space left by removed element
+ for (byte i = serialIndexToSkip; i < serialIndex + 1; i++) {
+ if (i < MAX_SERIAL_PORTS) {
+ reportSerial[i] = reportSerial[i + 1];
+ }
+ }
+ serialIndex--;
+ }
+ }
+ break; // SERIAL_READ
+ case SERIAL_CLOSE:
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ if (portId < 8) {
+ ((HardwareSerial*)serialPort)->end();
+ } else {
+#if defined(SoftwareSerial_h)
+ ((SoftwareSerial*)serialPort)->end();
+ if (serialPort != NULL) {
+ free(serialPort);
+ serialPort = NULL;
+ }
+#endif
+ }
+ }
+ break; // SERIAL_CLOSE
+ case SERIAL_FLUSH:
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ getPortFromId(portId)->flush();
+ }
+ break; // SERIAL_FLUSH
+#if defined(SoftwareSerial_h)
+ case SERIAL_LISTEN:
+ // can only call listen() on software serial ports
+ if (portId > 7) {
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ ((SoftwareSerial*)serialPort)->listen();
+ }
+ }
+ break; // SERIAL_LISTEN
+#endif
+ } // end switch
+ return true;
+ }
+ return false;
+}
+
+void SerialFirmata::update()
+{
+ checkSerial();
+}
+
+void SerialFirmata::reset()
+{
+#if defined(SoftwareSerial_h)
+ Stream *serialPort;
+ // free memory allocated for SoftwareSerial ports
+ for (byte i = SW_SERIAL0; i < SW_SERIAL3 + 1; i++) {
+ serialPort = getPortFromId(i);
+ if (serialPort != NULL) {
+ free(serialPort);
+ serialPort = NULL;
+ }
+ }
+#endif
+
+ serialIndex = -1;
+ for (byte i = 0; i < SERIAL_READ_ARR_LEN; i++) {
+ serialBytesToRead[i] = 0;
+ }
+}
+
+// get a pointer to the serial port associated with the specified port id
+Stream* SerialFirmata::getPortFromId(byte portId)
+{
+ switch (portId) {
+ case HW_SERIAL0:
+ // block use of Serial (typically pins 0 and 1) until ability to reclaim Serial is implemented
+ //return &Serial;
+ return NULL;
+#if defined(PIN_SERIAL1_RX)
+ case HW_SERIAL1:
+ return &Serial1;
+#endif
+#if defined(PIN_SERIAL2_RX)
+ case HW_SERIAL2:
+ return &Serial2;
+#endif
+#if defined(PIN_SERIAL3_RX)
+ case HW_SERIAL3:
+ return &Serial3;
+#endif
+#if defined(PIN_SERIAL4_RX)
+ case HW_SERIAL4:
+ return &Serial4;
+#endif
+#if defined(PIN_SERIAL5_RX)
+ case HW_SERIAL5:
+ return &Serial5;
+#endif
+#if defined(PIN_SERIAL6_RX)
+ case HW_SERIAL6:
+ return &Serial6;
+#endif
+#if defined(SoftwareSerial_h)
+ case SW_SERIAL0:
+ if (swSerial0 != NULL) {
+ // instances of SoftwareSerial are already pointers so simply return the instance
+ return swSerial0;
+ }
+ break;
+ case SW_SERIAL1:
+ if (swSerial1 != NULL) {
+ return swSerial1;
+ }
+ break;
+ case SW_SERIAL2:
+ if (swSerial2 != NULL) {
+ return swSerial2;
+ }
+ break;
+ case SW_SERIAL3:
+ if (swSerial3 != NULL) {
+ return swSerial3;
+ }
+ break;
+#endif
+ }
+ return NULL;
+}
+
+// Check serial ports that have READ_CONTINUOUS mode set and relay any data
+// for each port to the device attached to that port.
+void SerialFirmata::checkSerial()
+{
+ byte portId, serialData;
+ int bytesToRead = 0;
+ int numBytesToRead = 0;
+ Stream* serialPort;
+
+ if (serialIndex > -1) {
+
+ // loop through all reporting (READ_CONTINUOUS) serial ports
+ for (byte i = 0; i < serialIndex + 1; i++) {
+ portId = reportSerial[i];
+ bytesToRead = serialBytesToRead[portId];
+ serialPort = getPortFromId(portId);
+ if (serialPort == NULL) {
+ continue;
+ }
+#if defined(SoftwareSerial_h)
+ // only the SoftwareSerial port that is "listening" can read data
+ if (portId > 7 && !((SoftwareSerial*)serialPort)->isListening()) {
+ continue;
+ }
+#endif
+ if (serialPort->available() > 0) {
+ Firmata.write(START_SYSEX);
+ Firmata.write(SERIAL_MESSAGE);
+ Firmata.write(SERIAL_REPLY | portId);
+
+ if (bytesToRead == 0 || (serialPort->available() <= bytesToRead)) {
+ numBytesToRead = serialPort->available();
+ } else {
+ numBytesToRead = bytesToRead;
+ }
+
+ // relay serial data to the serial device
+ while (numBytesToRead > 0) {
+ serialData = serialPort->read();
+ Firmata.write(serialData & 0x7F);
+ Firmata.write((serialData >> 7) & 0x7F);
+ numBytesToRead--;
+ }
+ Firmata.write(END_SYSEX);
+ }
+
+ }
+ }
+}