diff --git a/IO_RSproto.cpp b/IO_RSproto.cpp index 6779438..639a027 100644 --- a/IO_RSproto.cpp +++ b/IO_RSproto.cpp @@ -25,12 +25,15 @@ static const byte PAYLOAD_FALSE = 0; static const byte PAYLOAD_NORMAL = 1; static const byte PAYLOAD_STRING = 2; +taskBuffer * taskBuffer::first=NULL; + taskBuffer::taskBuffer(Stream * myserial) { - // constructor + serial = myserial; next=first; first=this; - serial = myserial; + bufferLength=0; + inCommandPayload=PAYLOAD_FALSE; } taskBuffer::~taskBuffer() @@ -81,7 +84,7 @@ uint16_t taskBuffer::_calculateCrc(uint8_t *buf, uint16_t len) { } void taskBuffer::doCommand(uint8_t *commandBuffer, int commandSize) { - for (taskBuffer * t=first;t;t=t->next) t->doCommand2(nodeID,commandBuffer,commandSize); + for (taskBuffer * t=first;t;t=t->next) t->doCommand2(commandBuffer,commandSize); } void taskBuffer::doCommand2(uint8_t *commandBuffer, int commandSize) { @@ -100,7 +103,7 @@ void taskBuffer::doCommand2(uint8_t *commandBuffer, int commandSize) { digitalWrite(_txPin,LOW); } -void taskBuffer::init(unsigned long baud, uint16_t cycleTimeMS, int8_t txPin) { +void taskBuffer::init(unsigned long baud, int8_t txPin) { #ifdef RS485_SERIAL RS485_SERIAL.begin(baud, SERIAL_8N1); new taskBuffer(&RS485_SERIAL); @@ -175,8 +178,8 @@ void taskBuffer::parseOne(uint8_t *buf) { if (toNode != 0) return; // not for master uint8_t fromNode = buf[1]; uint8_t opcode = buf[2]; - - RSprotonode *node = RSprotonode::findNode(fromNode); + RSproto *bus = RSproto::findBus(0); + RSprotonode *node = bus->findNode(fromNode); switch (opcode) { case EXIOPINS: {node->_numDigitalPins = buf[3]; @@ -223,17 +226,20 @@ void taskBuffer::parseOne(uint8_t *buf) { } } } + node->resFlag = 1; break;} - case EXIOPINS: { + case EXIOINITA: { for (int i = 3; i < node->_numAnaloguePins; i++) { node->_analoguePinMap[i] = buf[i]; } + node->resFlag = 1; break; } case EXIOVER: { node->_majorVer = buf[3]; node->_minorVer = buf[4]; node->_patchVer = buf[5]; + node->resFlag = 1; break; } case EXIORDY: { @@ -248,12 +254,14 @@ void taskBuffer::parseOne(uint8_t *buf) { for (int i = 3; i < (node->_numDigitalPins+7)/8; i++) { node->_digitalInputStates[i-3] = buf[i]; } + node->resFlag = 1; break; } case EXIORDAN: { for (int i = 3; i < node->_numAnaloguePins*2; i++) { node->_analogueInputBuffer[i-3] = buf[i]; } + node->resFlag = 1; break; } } @@ -264,14 +272,11 @@ void taskBuffer::parseOne(uint8_t *buf) { ************************************************************/ // Constructor for RSproto -RSproto::RSproto(HardwareSerial &serial, unsigned long baud, uint16_t cycleTimeMS, int8_t txPin, int waitA) { +RSproto::RSproto(unsigned long baud, int8_t txPin) { _baud = baud; - _serialD = &serial; _txPin = txPin; _busNo = 0; - task->init(baud, cycleTimeMS, txPin); - _cycleTime = cycleTimeMS * 1000UL; // convert from milliseconds to microseconds. - _waitA = waitA; + task->init(baud, txPin); if (_waitA < 3) _waitA = 3; // Add device to HAL device chain IODevice::addDevice(this); @@ -281,22 +286,6 @@ RSproto::RSproto(HardwareSerial &serial, unsigned long baud, uint16_t cycleTimeM _busList = this; } - - -/* -= clearRxBuffer =- -// -// BLOCKING method to empty stray data in RX buffer -*/ -void RSproto::clearRxBuffer() { - unsigned long startMicros = micros(); - do { - if (_serialD->available() > 0) { - startMicros = micros(); - _serialD->read(); - } - } while (micros() - startMicros < _frameTimeout || !_serialD->available()); -} - /* -= _loop =- // // Main loop function for RSproto. @@ -357,97 +346,58 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun uint16_t pullup = params[0]; uint8_t outBuffer[6] = {EXIODPUP, pin, pullup}; - task->doCommand(outBuffer,3); unsigned long startMillis = millis(); + task->doCommand(outBuffer,3); while (resFlag == 0 && millis() - startMillis < 500); // blocking for now - if (resFlag != 1) { - DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin); - } + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin); + } + resFlag = 0; } int RSprotonode::_configureAnalogIn(VPIN vpin) { int pin = vpin - _firstVpin; //RSproto *mainrs = RSproto::findBus(_busNo); - uint8_t commandBuffer[5] = {(uint8_t) _nodeID, EXIOENAN, (uint8_t) pin}; - uint8_t responseBuffer[3]; - bus->_busy = true; - bus->updateCrc(commandBuffer,3); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, HIGH); - _serial->write(commandBuffer, 5); - _serial->write(initBuffer, 1); - _serial->flush(); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, LOW); + uint8_t commandBuffer[5] = {EXIOENAN, (uint8_t) pin}; unsigned long startMillis = millis(); - while (!_serial->available()) { - if (millis() - startMillis > 500) return 0; - } - uint16_t len = 0; - unsigned long startMicros = micros(); - bool rxDone = false; - byte tmpByte; - len = _serial->readBytesUntil(0xFE,responseBuffer, 25); - bus->_busy = false; - if (true/*bus->crcGood(responseBuffer,sizeof(responseBuffer)-2)*/) { - if (!bus->testAndStripMasterFlag(responseBuffer)) DIAG(F("Foreign RSproto Device! no master flag from node %d"),_nodeID); - if (responseBuffer[0] != EXIORDY) { - DIAG(F("EX-IOExpander485: Vpin %u on node %d cannot be used as an analogue input pin"), (int) pin, (int) _nodeID); - } - } else { - DIAG(F("EX-IOExpander485 node %d CRC Error"), (int) _nodeID); + task->doCommand(commandBuffer, 2); + while (resFlag == 0 && millis() - startMillis < 500); // blocking for now + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin); } + resFlag = 0; return false; } void RSprotonode::_begin() { + uint8_t commandBuffer[4] = {EXIOINIT, (uint8_t)_nPins, (uint8_t)(_firstVpin & 0xFF), (uint8_t)(_firstVpin >> 8)}; + unsigned long startMillis = millis(); + task->doCommand(commandBuffer,4); + while (resFlag == 0 && millis() - startMillis < 500); // blocking for now + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINIT"), _nodeID); + } + resFlag = 0; + commandBuffer[0] = EXIOINITA; + startMillis = millis(); + task->doCommand(commandBuffer,1); + while (resFlag == 0 && millis() - startMillis < 500); // blocking for now + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINITA"), _nodeID); + } + resFlag = 0; + commandBuffer[0] = EXIOVER; + startMillis = millis(); + task->doCommand(commandBuffer,1); + while (resFlag == 0 && millis() - startMillis < 500); // blocking for now + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID); + } else DIAG(F("EX-IOExpander device found, Node:%d, Version v%d.%d.%d"), _nodeID, _majorVer, _minorVer, _patchVer); + resFlag = 0; + - commandBuffer[0] = _nodeID; - commandBuffer[1] = EXIOINITA; - bus->updateCrc(commandBuffer,2); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, HIGH); - _serial->write(commandBuffer, 4); - _serial->write(initBuffer, 1); - _serial->flush(); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, LOW); - startMillis = millis(); - while (!_serial->available()) { - if (millis() - startMillis >= 500) return; - } - len = 0; - startMicros = micros(); - rxDone = false; - len = _serial->readBytesUntil(0xFE,receiveBuffer, 25); - - DIAG(F("rxcode:%d from node"),receiveBuffer[1]); - if (true/*bus->crcGood(receiveBuffer,sizeof(receiveBuffer)-2)*/) { - if (!bus->testAndStripMasterFlag(receiveBuffer)) DIAG(F("Foreign RSproto Device! no master flag from node %d"),_nodeID); - - } - uint8_t versionBuffer[5]; - commandBuffer[0] = _nodeID; - commandBuffer[1] = EXIOVER; - bus->updateCrc(commandBuffer,2); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, HIGH); - _serial->write(commandBuffer, 4); - _serial->write(initBuffer, 1); - _serial->flush(); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, LOW); - startMillis = millis(); - while (!_serial->available()) { - if (millis() - startMillis >= 500) return; - } - len = 0; - startMicros = micros(); - rxDone = false; - len = _serial->readBytesUntil(0xFE,receiveBuffer, 25); - - DIAG(F("rxcode:%d.%d.%d from node"),versionBuffer[1],versionBuffer[2],versionBuffer[3]); - if (true/*bus->crcGood(versionBuffer,sizeof(versionBuffer)-2)*/) { - if (!bus->testAndStripMasterFlag(versionBuffer)) DIAG(F("Foreign RSproto Device! no master flag from node %d"),_nodeID); - - DIAG(F("EX-IOExpander485 device found, node:%d, Version v%d.%d.%d"), _nodeID, _majorVer, _minorVer, _patchVer); - } #ifdef DIAG_IO - _display(); + _display(); #endif } @@ -462,43 +412,18 @@ void RSprotonode::_write(VPIN vpin, int value) { if (_deviceState == DEVSTATE_FAILED) return; int pin = vpin - _firstVpin; uint8_t digitalOutBuffer[6]; - uint8_t responseBuffer[3]; - digitalOutBuffer[0] = (uint8_t) _nodeID; - digitalOutBuffer[1] = EXIOWRD; - digitalOutBuffer[2] = (uint8_t) pin; - digitalOutBuffer[3] = (uint8_t) value; - bus->_busy = true; - bus->updateCrc(digitalOutBuffer,4); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, HIGH); - _serial->write(digitalOutBuffer, 6); - _serial->write(initBuffer, 1); - _serial->flush(); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, LOW); - unsigned long startMillis = millis(); - while (!_serial->available()) { - if (millis() - startMillis >= 500) return; - } - uint16_t len = 0; - unsigned long startMicros = micros(); - bool rxDone = false; - byte tmpByte; - len = _serial->readBytesUntil(0xFE,responseBuffer, 25); - bus->_busy = false; - if (true/*bus->crcGood(responseBuffer,sizeof(responseBuffer)-2)*/) { - if (!testAndStripMasterFlag(responseBuffer)) DIAG(F("Foreign RSproto Device! no master flag from node %d"),_nodeID); - if (responseBuffer[0] != EXIORDY) { - DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital output pin"), pin); - } - } else { - DIAG(F("EX-IOExpander485 node %d CRC Error"), _nodeID); - } + digitalOutBuffer[1] = EXIOWRD; + digitalOutBuffer[2] = (uint8_t) pin; + digitalOutBuffer[3] = (uint8_t) value; + unsigned long startMillis = millis(); + task->doCommand(digitalOutBuffer,3); + while (resFlag == 0 && millis() - startMillis < 500); // blocking for now + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID); + } + resFlag = 0; } - bool RSprotonode::testAndStripMasterFlag(uint8_t *buf) { - if (buf[0] != 0xFF) return false; // why did we not get a master flag? bad node? - for (int i = 0; i < sizeof(buf)-1; i++) buf[i] = buf[i+1]; // shift array to begining - return true; - } int RSprotonode::_readAnalogue(VPIN vpin) { if (_deviceState == DEVSTATE_FAILED) return 0; int pin = vpin - _firstVpin; @@ -515,41 +440,19 @@ void RSprotonode::_write(VPIN vpin, int value) { void RSprotonode::_writeAnalogue(VPIN vpin, int value, uint8_t profile, uint16_t duration) { uint8_t servoBuffer[7]; uint8_t responseBuffer[1]; - - if (_deviceState == DEVSTATE_FAILED) return; int pin = vpin - _firstVpin; - servoBuffer[0] = (uint8_t) _nodeID; - servoBuffer[1] = EXIOWRAN; - servoBuffer[2] = (uint8_t) pin; - servoBuffer[3] = (uint8_t) value & 0xFF; - servoBuffer[4] = (uint8_t) value >> 8; - servoBuffer[5] = (uint8_t) profile; - servoBuffer[6] = (uint8_t) duration & 0xFF; - servoBuffer[7] = (uint8_t) duration >> 8; - bus->_busy = true; - bus->updateCrc(servoBuffer,8); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, HIGH); - _serial->write(servoBuffer, 10); - _serial->write(initBuffer, 1); - _serial->flush(); - if (bus->_txPin != VPIN_NONE) ArduinoPins::fastWriteDigital(bus->_txPin, LOW); - unsigned long startMillis = millis(); - while (!_serial->available()) { - if (millis() - startMillis >= 500) return; - } - uint16_t len = 0; - unsigned long startMicros = micros(); - bool rxDone = false; - byte tmpByte; - len = _serial->readBytesUntil(0xFE,responseBuffer, 25); - bus->_busy = false; - if (!true/*bus->crcGood(responseBuffer,sizeof(responseBuffer)-2)*/) { - DIAG(F("EX-IOExpander485 node %d CRC Error"), (int) _nodeID); - //_deviceState = DEVSTATE_FAILED; - } else { - if (!bus->testAndStripMasterFlag(responseBuffer)) DIAG(F("Foreign RSproto Device! no master flag from node %d"),_nodeID); - if (responseBuffer[0] != EXIORDY) { - DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a servo/PWM pin"), pin); - } - } + servoBuffer[0] = EXIOWRAN; + servoBuffer[1] = (uint8_t) pin; + servoBuffer[2] = (uint8_t) value & 0xFF; + servoBuffer[3] = (uint8_t) value >> 8; + servoBuffer[4] = (uint8_t) profile; + servoBuffer[5] = (uint8_t) duration & 0xFF; + servoBuffer[6] = (uint8_t) duration >> 8; + unsigned long startMillis = millis(); + task->doCommand(servoBuffer,7); + while (resFlag == 0 && millis() - startMillis < 500); // blocking for now + if (resFlag != 1) { + DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID); + } + resFlag = 0; } \ No newline at end of file diff --git a/IO_RSproto.h b/IO_RSproto.h index 1f9aea4..d39a615 100644 --- a/IO_RSproto.h +++ b/IO_RSproto.h @@ -57,7 +57,7 @@ class RSprotonode; class taskBuffer { private: -static taskBuffer * first; +static taskBuffer *first; RSprotonode *node; Stream * serial; uint8_t _txPin; @@ -65,7 +65,7 @@ static taskBuffer * first; uint8_t _commandType; byte bufferLength; byte buffer[COMMAND_BUFFER_SIZE]; - taskBuffer * next; + taskBuffer *next; uint8_t endChar[1] = {0xFE}; byte inCommandPayload; // EX-IOExpander protocol flags @@ -99,7 +99,7 @@ public: void updateCrc(uint8_t *crcBuf, uint8_t *buf, uint16_t len); bool crcGood(uint8_t *buf, uint16_t len); static void doCommand(uint8_t *commandBuffer=NULL, int commandSize=0); - static void init(unsigned long baud, uint16_t cycleTimeMS=500, int8_t txPin=-1); + static void init(unsigned long baud, int8_t txPin=-1); static void loop(); }; @@ -140,8 +140,9 @@ private: EXIOWRAN = 0xEA, // Flag we're sending an analogue write (PWM) EXIOERR = 0xEF, // Flag we've received an error }; - static RSprotonode *_nodeList; + public: + static RSprotonode *_nodeList; enum ProfileType : int { Instant = 0, // Moves immediately between positions (if duration not specified) UseDuration = 0, // Use specified duration @@ -182,13 +183,7 @@ public: RSprotonode *getNext() { return _next; } - static RSprotonode *findNode(uint8_t nodeID) { - for (RSprotonode *node = _nodeList; node != NULL; node = node->getNext()) { - if (node->getNodeID() == nodeID) - return node; - } - return NULL; - } + void setNext(RSprotonode *node) { _next = node; } @@ -285,6 +280,10 @@ private: } public: + static void create(unsigned long baud, int8_t txPin=-1) { + new RSproto(baud, txPin); + } + int _CommMode = 0; int _opperation = 0; uint16_t _pullup; @@ -294,19 +293,7 @@ public: unsigned long _baud; int taskCnt = 0; uint8_t initBuffer[1] = {0xFE}; - bool testAndStripMasterFlag(uint8_t *buf) { - if (buf[0] != 0xFD) return false; // why did we not get a master flag? bad node? - for (int i = 0; i < sizeof(buf)-1; i++) buf[i] = buf[i+1]; // shift array to begining - return true; - } - - - void clearRxBuffer(); - static void create(unsigned long baud, uint16_t cycleTimeMS=500, int8_t txPin=-1, int waitA=10) { - new RSproto(baud, cycleTimeMS, txPin, waitA); - } - // Device-specific initialisation void _begin() override { @@ -367,7 +354,7 @@ public: } protected: - RSproto(unsigned long baud, uint16_t cycleTimeMS, int8_t txPin, int waitA); + RSproto(unsigned long baud, int8_t txPin); public: