From e97830542e92dbecde9b19f8d4e93d191c76d023 Mon Sep 17 00:00:00 2001 From: travis-farmer Date: Mon, 16 Dec 2024 06:14:59 -0500 Subject: [PATCH] change to full-duplex token ring style --- IO_RSproto.cpp | 34 ++++++++++----------- IO_RSproto.h | 80 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/IO_RSproto.cpp b/IO_RSproto.cpp index c150101..edfd666 100644 --- a/IO_RSproto.cpp +++ b/IO_RSproto.cpp @@ -1,6 +1,6 @@ /* * © 2024, Travis Farmer. All rights reserved. - * © 2024, Chris Bulliner. All rights reserved. https://github.com/CMB27 + * © 2021 Chris Harlow * * This file is part of DCC++EX API * @@ -47,25 +47,22 @@ void taskBuffer::doCommand(uint8_t *commandBuffer, int commandSize) { void taskBuffer::doCommand2(uint8_t *commandBuffer, int commandSize) { // process commands here to be sent - uint8_t crcBuffer[2]; //_serial->begin(115200); //ArduinoPins::fastWriteDigital(bus->_txPin, HIGH); - digitalWrite(_txPin,HIGH); + if (_txPin != -1) digitalWrite(_txPin,HIGH); serial->write(commandBuffer, 7); serial->write(endChar, 1); serial->flush(); - digitalWrite(_txPin,LOW); + if (_txPin != -1) digitalWrite(_txPin,LOW); } -void taskBuffer::init(unsigned long baud, int8_t txPin) { -#ifdef RS485_SERIAL - RS485_SERIAL.begin(baud, SERIAL_8N1); - new taskBuffer(&RS485_SERIAL); -#endif +void taskBuffer::init(HardwareSerial &hwSerial, unsigned long baud, int8_t txPin) { + hwSerial.begin(baud, SERIAL_8N1); + new taskBuffer(&hwSerial); for (taskBuffer * t=first;t;t=t->next) t->_txPin = txPin; - pinMode(txPin, OUTPUT); - digitalWrite(txPin, LOW); + if (txPin != -1) pinMode(txPin, OUTPUT); + if (txPin != -1) digitalWrite(txPin, LOW); } void taskBuffer::loop() { @@ -132,6 +129,7 @@ void taskBuffer::parseOne(uint8_t *buf) { uint8_t toNode = buf[0]; if (toNode != 0) return; // not for master uint8_t fromNode = buf[1]; + if (fromNode == 0) return; // why did out own data come round the ring back to us? uint8_t opcode = buf[2]; RSproto *bus = RSproto::findBus(0); RSprotonode *node = bus->findNode(fromNode); @@ -227,11 +225,12 @@ void taskBuffer::parseOne(uint8_t *buf) { ************************************************************/ // Constructor for RSproto -RSproto::RSproto(unsigned long baud, int8_t txPin) { +RSproto::RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin) { + _serial = &serial; _baud = baud; _txPin = txPin; - _busNo = 0; - task->init(baud, txPin); + _busNo = busNo; + task->init(serial, baud, txPin); if (_waitA < 3) _waitA = 3; // Add device to HAL device chain IODevice::addDevice(this); @@ -281,7 +280,8 @@ RSprotonode::RSprotonode(VPIN firstVpin, int nPins, uint8_t nodeID) { _nodeID = nodeID; //bus = bus->findBus(0); //_serial = bus->_serialD; - if (_nodeID > 254) _nodeID = 254; + if (_nodeID > 252) _nodeID = 252; // cannot have a node with the frame flags + if (_nodeID < 1) _nodeID = 1; // cannot have a node with the master ID // Add this device to HAL device list IODevice::addDevice(this); @@ -299,8 +299,8 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun if (paramCount != 1) return false; int pin = vpin - _firstVpin; - uint16_t pullup = params[0]; - uint8_t outBuffer[6] = {EXIODPUP, pin, pullup}; + uint8_t pullup = (uint8_t)params[0]; + uint8_t outBuffer[6] = {EXIODPUP, (uint8_t)pin, pullup}; unsigned long startMillis = millis(); task->doCommand(outBuffer,3); while (resFlag == 0 && millis() - startMillis < 500); // blocking for now diff --git a/IO_RSproto.h b/IO_RSproto.h index 9a8ece6..a564068 100644 --- a/IO_RSproto.h +++ b/IO_RSproto.h @@ -1,33 +1,35 @@ /* - * © 2024, Travis Farmer. All rights reserved. - * © 2024, Chris Bulliner. All rights reserved. https://github.com/CMB27 - * - * This file is part of DCC++EX API - * - * This is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * It is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with CommandStation. If not, see . - */ +* © 2024, Travis Farmer. All rights reserved. +* © 2021 Chris Harlow +* +* This file is part of DCC++EX API +* +* This is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* It is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with CommandStation. If not, see . +*/ /* * RSproto * ======= * To define a RSproto, example syntax: - * RSproto::create(serial, baud[, cycletime[, pin]]); + * RSproto::create(busNo, serial, baud[, pin]); * + * busNo = the Bus no of the instance. should = 0, unless more than one bus configured for some reason. * serial = serial port to be used (e.g. Serial3) * baud = baud rate (9600, 19200, 28800, 57600 or 115200) * cycletime = minimum time between successive updates/reads of a node in millisecs (default 500ms) - * pin = pin number connected to RSproto module's DE and !RE terminals for half-duplex operation (default VPIN_NONE) + * pin = pin number connected to RSproto module's DE and !RE terminals for half-duplex operation (default -1) + * if omitted (default), hardware MUST support full-duplex opperation! * * * RSprotoNode @@ -37,7 +39,7 @@ * * firstVPIN = first vpin in block allocated to this device * numVPINs = number of vpins - * nodeID = 0-254 + * nodeID = 1-252 */ #ifndef IO_RS485_H @@ -48,12 +50,32 @@ class RSproto; class RSprotonode; + + #ifndef COMMAND_BUFFER_SIZE #define COMMAND_BUFFER_SIZE 100 #endif -#ifndef RS485_SERIAL - #define RS485_SERIAL Serial1 -#endif + +/********************************************************************** + * taskBuffer class + * + * this stores the task list, and processes the data within it for + * sending. it also handles the incomming data responce. + * Data Frame: + * 0xFD : toNode : fromNode : ~data packet~ : 0xFE + * Start: TO : FROM : DATA : End + * + * Data frame must always start with the Start byte, follow with the + * destination (toNode), follow with the Source (fromNode), contain + * the data packet, and follow with the End byte. + * + * + * Data Packet: + * Command Byte : ~Command Params~ + * + * Data Packet must always precede the parameters with the Command byte. + * this way the data is processed by the correct routine. + **********************************************************************/ class taskBuffer { private: @@ -96,7 +118,7 @@ public: taskBuffer(Stream * myserial); ~taskBuffer(); static void doCommand(uint8_t *commandBuffer=NULL, int commandSize=0); - static void init(unsigned long baud, int8_t txPin=-1); + static void init(HardwareSerial &hwSerial, unsigned long baud, int8_t txPin=-1); static void loop(); }; @@ -259,10 +281,10 @@ private: } public: - static void create(unsigned long baud, int8_t txPin=-1) { - new RSproto(baud, txPin); + static void create(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin=-1) { + new RSproto(busNo, serial, baud, txPin); } - + HardwareSerial* _serial; int _CommMode = 0; int _opperation = 0; uint16_t _pullup; @@ -333,7 +355,7 @@ public: } protected: - RSproto(unsigned long baud, int8_t txPin); + RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin); public: