diff --git a/IO_RSproto.cpp b/IO_RSproto.cpp index 8f06ae0..f2123b7 100644 --- a/IO_RSproto.cpp +++ b/IO_RSproto.cpp @@ -25,159 +25,6 @@ static const byte PAYLOAD_FALSE = 0; static const byte PAYLOAD_NORMAL = 1; static const byte PAYLOAD_STRING = 2; -taskBuffer * taskBuffer::first=NULL; - -taskBuffer::taskBuffer(unsigned long taskID, uint8_t *commandBuffer, int byteCount, uint8_t retFlag) -{ - _taskID = taskID; - _byteCount = byteCount; - _retFlag = retFlag; - memset(commandArray, 0, byteCount); - memcpy(commandArray, commandBuffer, byteCount); - - next=first; - first=this; - - RSproto *bus = RSproto::findBus(0); - if (bus != NULL) { - bus->addTask(this); - return; - } -} - -taskBuffer::~taskBuffer() -{ - // destructor -} - -void RSproto::remove_nulls(char *str, int len) { - int i, j = 0; - for (i = 0; i= 0 && pos < strlen(str)) { - for (int i = 0; i < strlen(str); i++) { - if (i < pos) result[i] = str[i]; - } - } - if (result != NULL) return atoi(result); - else return 0; -} - -void taskBuffer::doCommand(unsigned long taskID, uint8_t *commandBuffer, int byteCount, uint8_t retFlag) { - // add commands here to be sent - new taskBuffer(taskID, commandBuffer, byteCount, retFlag); - -} - -void RSproto::parseRx(uint8_t * outArray, uint8_t retFlag) { - int nodeTo = outArray[0]; - int nodeFr = outArray[1]; - int AddrCode = outArray[2]; - DIAG(F("From: %i, To: %i | %i %i %i %i %i"), nodeFr,nodeTo, outArray[3], outArray[4], outArray[5], outArray[6],outArray[7]); - return; - RSprotonode *node = findNode(nodeFr); - switch (AddrCode) { - case EXIOPINS: - {node->_numDigitalPins = outArray[3]; - node->_numAnaloguePins = outArray[4]; - - // See if we already have suitable buffers assigned - if (node->_numDigitalPins>0) { - size_t digitalBytesNeeded = (node->_numDigitalPins + 7) / 8; - if (node->_digitalPinBytes < digitalBytesNeeded) { - // Not enough space, free any existing buffer and allocate a new one - if (node->_digitalPinBytes > 0) free(node->_digitalInputStates); - if ((node->_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) { - node->_digitalPinBytes = digitalBytesNeeded; - } else { - DIAG(F("EX-IOExpander485 node:%d ERROR alloc %d bytes"), nodeFr, digitalBytesNeeded); - //_deviceState = DEVSTATE_FAILED; - node->_digitalPinBytes = 0; - return; - } - } - } - - if (node->_numAnaloguePins>0) { - size_t analogueBytesNeeded = node->_numAnaloguePins * 2; - if (node->_analoguePinBytes < analogueBytesNeeded) { - // Free any existing buffers and allocate new ones. - if (node->_analoguePinBytes > 0) { - free(node->_analogueInputBuffer); - free(node->_analogueInputStates); - free(node->_analoguePinMap); - } - node->_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1); - node->_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1); - node->_analoguePinMap = (uint8_t*) calloc(node->_numAnaloguePins, 1); - if (node->_analogueInputStates != NULL && - node->_analogueInputBuffer != NULL && - node->_analoguePinMap != NULL) { - node->_analoguePinBytes = analogueBytesNeeded; - } else { - DIAG(F("EX-IOExpander485 node:%d ERROR alloc analog pin bytes"), nodeFr); - //_deviceState = DEVSTATE_FAILED; - node->_analoguePinBytes = 0; - return; - } - } - } - node->resFlag[retFlag] = 1; - break;} - case EXIOINITA: { - for (int i = 0; i < node->_numAnaloguePins; i++) { - node->_analoguePinMap[i] = outArray[i+3]; - } - node->resFlag[retFlag] = 1; - break; - } - case EXIOVER: { - node->_majorVer = outArray[3]; - node->_minorVer = outArray[4]; - node->_patchVer = outArray[5]; - node->resFlag[retFlag] = 1; - break; - } - case EXIORDY: { - node->resFlag[retFlag] = 1; - break; - } - case EXIOERR: { - node->resFlag[retFlag] = -1; - break; - } - case EXIORDD: { - for (int i = 0; i < (node->_numDigitalPins+7)/8; i++) { - node->_digitalInputStates[i] = outArray[i+3]; - } - node->resFlag[retFlag] = 1; - break; - } - case EXIORDAN: { - for (int i = 0; i < node->_numAnaloguePins; i++) { - node->_analogueInputBuffer[i] = outArray[i+3]; - } - node->resFlag[retFlag] = 1; - break; - } - } -} /************************************************************ * RSproto implementation @@ -224,384 +71,203 @@ uint16_t RSproto::crc16(uint8_t *data, uint16_t length) { return crc; } -void RSproto::sendInstantCommand(uint8_t *buf, int byteCount, uint8_t retFlag) { - // Calculate CRC for response data - uint16_t response_crc = crc16((uint8_t*)buf, byteCount-1); - if (_txPin != -1) digitalWrite(_txPin,HIGH); - // Send response data with CRC - _serial->write(0xFE); - _serial->write(0xFE); - _serial->write(response_crc >> 8); - _serial->write(response_crc & 0xFF); - _serial->write(byteCount); - for (int i = 0; i < byteCount; i++) { - _serial->write(buf[i]); - - } - _serial->write(0xFD); - _serial->write(0xFD); - _serial->flush(); - if (_txPin != -1) digitalWrite(_txPin,LOW); - - bool flagProc = false; -uint8_t Ireceived_data[ARRAY_SIZE]; - //int received_data[ARRAY_SIZE]; - uint16_t received_crc; - int byteCounted = 0; - unsigned long startMillis = millis(); - while (!flagEnded) { - if (millis() - startMillis > 500) return; // safeguard timeout - while(_serial->available()) { - if (_serial->available()) { - - - uint16_t calculated_crc; - int byteCountRx = 100; - - int curByte = _serial->read(); - - if (curByte == 0xFE && flagStart == false) flagStart = true; - else if ( curByte == 0xFE && flagStart == true) { - byteCounter = 0; - flagStarted = true; - flagStart = false; - flagEnded = false; - rxStart = true; - rxEnd = false; - crcPass = false; - }else if (flagStarted) { - crc[0] = curByte; - byteCounter++; - flagStarted = false; - } else if (byteCounter == 1) { - crc[1] = curByte; - received_crc = (crc[0] << 8) | crc[1]; - byteCounter++; - } else if (byteCounter == 2) { - byteCountRx = curByte; - byteCounter++; - } else if (flagEnded == false && byteCounter >= 3) { - Ireceived_data[byteCounter-3] = curByte; - byteCounter++; - } - if (curByte == 0xFD && flagEnd == false) flagEnd = true; - else if ( curByte == 0xFD && flagEnd == true) { - flagEnded = true; - flagEnd = false; - rxEnd = true; - byteCounted = byteCounter; - byteCounter = 0; - calculated_crc = crc16((uint8_t*)Ireceived_data, byteCounted-6); - if (received_crc == calculated_crc) { - crcPass = true; - DIAG(F("CRC PASS %x %x BC: %i"), received_crc, calculated_crc, byteCounted); - } else { - DIAG(F("CRC FAIL %x %x BC: %i"), received_crc, calculated_crc, byteCounted); - } - return; - } - // Check CRC validity - if (crcPass) { - // Data received successfully, process it (e.g., print) - /*if (received_data[0] == 0) */flagProc = true; - //else DIAG(F("To Node: %i"), received_data[0]); - - } else { - //DIAG(F("IO_RSproto: CRC Error!")); - } - } - } - } - if (flagProc) { - flagProc = false; - int nodeTo = Ireceived_data[0]; - int nodeFr = Ireceived_data[1]; - int AddrCode = Ireceived_data[2]; - DIAG(F("From: %i, To: %i | %i %i %i %i %i"), nodeFr,nodeTo, Ireceived_data[3], Ireceived_data[4], Ireceived_data[5], Ireceived_data[6],Ireceived_data[7]); - return; - RSprotonode *node = findNode(nodeFr); - switch (AddrCode) { - case EXIOPINS: - {node->_numDigitalPins = Ireceived_data[3]; - node->_numAnaloguePins = Ireceived_data[4]; - - // See if we already have suitable buffers assigned - if (node->_numDigitalPins>0) { - size_t digitalBytesNeeded = (node->_numDigitalPins + 7) / 8; - if (node->_digitalPinBytes < digitalBytesNeeded) { - // Not enough space, free any existing buffer and allocate a new one - if (node->_digitalPinBytes > 0) free(node->_digitalInputStates); - if ((node->_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) { - node->_digitalPinBytes = digitalBytesNeeded; - } else { - DIAG(F("EX-IOExpander485 node:%d ERROR alloc %d bytes"), nodeFr, digitalBytesNeeded); - //_deviceState = DEVSTATE_FAILED; - node->_digitalPinBytes = 0; - return; - } - } - } - - if (node->_numAnaloguePins>0) { - size_t analogueBytesNeeded = node->_numAnaloguePins * 2; - if (node->_analoguePinBytes < analogueBytesNeeded) { - // Free any existing buffers and allocate new ones. - if (node->_analoguePinBytes > 0) { - free(node->_analogueInputBuffer); - free(node->_analogueInputStates); - free(node->_analoguePinMap); - } - node->_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1); - node->_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1); - node->_analoguePinMap = (uint8_t*) calloc(node->_numAnaloguePins, 1); - if (node->_analogueInputStates != NULL && - node->_analogueInputBuffer != NULL && - node->_analoguePinMap != NULL) { - node->_analoguePinBytes = analogueBytesNeeded; - } else { - DIAG(F("EX-IOExpander485 node:%d ERROR alloc analog pin bytes"), nodeFr); - //_deviceState = DEVSTATE_FAILED; - node->_analoguePinBytes = 0; - return; - } - } - } - node->resFlag[retFlag] = 1; - break;} - case EXIOINITA: { - for (int i = 0; i < node->_numAnaloguePins; i++) { - node->_analoguePinMap[i] = Ireceived_data[i+3]; - } - node->resFlag[retFlag] = 1; - break; - } - case EXIOVER: { - node->_majorVer = Ireceived_data[3]; - node->_minorVer = Ireceived_data[4]; - node->_patchVer = Ireceived_data[5]; - DIAG(F("EX-IOExpander device found, Node:%d, Version v%d.%d.%d"), node->getNodeID(), node->_majorVer, node->_minorVer, node->_patchVer); - break; - } - case EXIORDY: { - node->resFlag[retFlag] = 1; - break; - } - case EXIOERR: { - node->resFlag[retFlag] = -1; - break; - } - case EXIORDD: { - for (int i = 0; i < (node->_numDigitalPins+7)/8; i++) { - node->_digitalInputStates[i] = Ireceived_data[i+3]; - } - node->resFlag[retFlag] = 1; - break; - } - case EXIORDAN: { - for (int i = 0; i < node->_numAnaloguePins; i++) { - node->_analogueInputBuffer[i] = Ireceived_data[i+3]; - } - node->resFlag[retFlag] = 1; - break; - } - } - } -} - void RSproto::_loop(unsigned long currentMicros) { _currentMicros = currentMicros; - if (_busy == true) return; - if (_currentTask == NULL) { - _currentTask = _taskListStart; - - } - + //if (_busy == true) return; if (_currentMicros - _cycleStartTime < _cycleTime) return; _cycleStartTime = _currentMicros; - if (_currentTask != NULL && _currentTask->_byteCount > 0) { + + Task currentTask = getNextTask(); + if (currentTask.completed != true) { // Check if a task was found // Calculate CRC for response data - - uint16_t response_crc = crc16((uint8_t*)_currentTask->commandArray, _currentTask->_byteCount-6); - if (_txPin != -1) digitalWrite(_txPin,HIGH); - // Send response data with CRC - _serial->write(0xFE); - _serial->write(0xFE); - _serial->write(response_crc >> 8); - _serial->write(response_crc & 0xFF); - _serial->write(_currentTask->_byteCount); - for (int i = 0; i < _currentTask->_byteCount; i++) { - _serial->write(_currentTask->commandArray[i]); - } - _serial->write(0xFD); - _serial->write(0xFD); - _serial->flush(); - if (_txPin != -1) digitalWrite(_txPin,LOW); - // delete task command after sending, for now - memset(_currentTask->commandArray, 0, _currentTask->_byteCount); - _currentTask->_byteCount = 0; - } - - if (_serial->available()) { - - - uint16_t calculated_crc; - int byteCount = 100; - - uint8_t byte_array[byteCount]; - int curByte = _serial->read(); - - if (curByte == 0xFE && flagStart == false) flagStart = true; - else if ( curByte == 0xFE && flagStart == true) { - flagProc = false; - byteCounter = 0; - flagStarted = true; - flagStart = false; - flagEnded = false; - rxStart = true; - rxEnd = false; - crcPass = false; - }else if (flagStarted) { - crc[0] = curByte; - byteCounter++; - flagStarted = false; - } else if (byteCounter == 1) { - crc[1] = curByte; - received_crc = (crc[0] << 8) | crc[1]; - byteCounter++; - } else if (byteCounter == 2) { - byteCount = curByte; - byteCounter++; - } else if (flagEnded == false && byteCounter >= 3) { - received_data[byteCounter-3] = curByte; - byteCounter++; - } - if (curByte == 0xFD && flagEnd == false) flagEnd = true; - else if ( curByte == 0xFD && flagEnd == true) { - flagEnded = true; - flagEnd = false; - rxEnd = true; - byteCount = byteCounter; - byteCounter = 0; - } - if (flagEnded) { - calculated_crc = crc16((uint8_t*)received_data, byteCount-6); - if (received_crc == calculated_crc) { - DIAG(F("Loop CRC PASS")); - crcPass = true; - }else DIAG(F("Loop CRC Fail %x %x"),received_crc,calculated_crc); - flagEnded = false; - } - // Check CRC validity - if (crcPass) { - // Data received successfully, process it (e.g., print) - int nodeTo = received_data[0]; - if (nodeTo == 0) { // for master. master does not retransmit, or a loop will runaway. - flagProc = true; - + if (!currentTask.rxMode) { + currentTask.crcPassFail = 0; + uint16_t response_crc = crc16((uint8_t*)currentTask.commandArray, currentTask.byteCount-1); + if (_txPin != -1) digitalWrite(_txPin,HIGH); + // Send response data with CRC + _serial->write(0xFE); + _serial->write(0xFE); + _serial->write(response_crc >> 8); + _serial->write(response_crc & 0xFF); + _serial->write(currentTask.byteCount); + for (int i = 0; i < currentTask.byteCount; i++) { + _serial->write(currentTask.commandArray[i]); } - - } else { - //DIAG(F("IO_RSproto: CRC Error!")); + _serial->write(0xFD); + _serial->write(0xFD); + _serial->flush(); + if (_txPin != -1) digitalWrite(_txPin,LOW); + // delete task command after sending, for now + markTaskCompleted(currentTask.taskID); } - task->getNext(); - } - if (flagProc) { - flagProc = false; - int nodeTo = received_data[0]; - int nodeFr = received_data[1]; - int AddrCode = received_data[2]; - DIAG(F("From: %i, To: %i | %i %i %i %i %i"), nodeFr,nodeTo, received_data[3], received_data[4], received_data[5], received_data[6],received_data[7]); - return; - RSprotonode *node = findNode(nodeFr); - switch (AddrCode) { - case EXIOPINS: - {node->_numDigitalPins = received_data[3]; - node->_numAnaloguePins = received_data[4]; - // See if we already have suitable buffers assigned - if (node->_numDigitalPins>0) { - size_t digitalBytesNeeded = (node->_numDigitalPins + 7) / 8; - if (node->_digitalPinBytes < digitalBytesNeeded) { - // Not enough space, free any existing buffer and allocate a new one - if (node->_digitalPinBytes > 0) free(node->_digitalInputStates); - if ((node->_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) { - node->_digitalPinBytes = digitalBytesNeeded; - } else { - DIAG(F("EX-IOExpander485 node:%d ERROR alloc %d bytes"), nodeFr, digitalBytesNeeded); - //_deviceState = DEVSTATE_FAILED; - node->_digitalPinBytes = 0; - return; - } - } + if (_serial->available() && currentTask.rxMode) { + + + uint16_t calculated_crc; + int byteCount = 100; + + uint8_t byte_array[byteCount]; + int curByte = _serial->read(); + + if (curByte == 0xFE && flagStart == false) flagStart = true; + else if ( curByte == 0xFE && flagStart == true) { + flagProc = false; + byteCounter = 0; + flagStarted = true; + flagStart = false; + flagEnded = false; + rxStart = true; + rxEnd = false; + crcPass = false; + }else if (flagStarted) { + crc[0] = curByte; + byteCounter++; + flagStarted = false; + } else if (byteCounter == 1) { + crc[1] = curByte; + received_crc = (crc[0] << 8) | crc[1]; + byteCounter++; + } else if (byteCounter == 2) { + byteCount = curByte; + byteCounter++; + } else if (flagEnded == false && byteCounter >= 3) { + received_data[byteCounter-3] = curByte; + byteCounter++; + } + if (curByte == 0xFD && flagEnd == false) flagEnd = true; + else if ( curByte == 0xFD && flagEnd == true) { + flagEnded = true; + flagEnd = false; + rxEnd = true; + byteCount = byteCounter; + byteCounter = 0; + } + if (flagEnded) { + calculated_crc = crc16((uint8_t*)received_data, byteCount-7); + if (received_crc == calculated_crc) { + DIAG(F("Loop CRC PASS")); + crcPass = true; + currentTask.crcPassFail = 1; + }else { + DIAG(F("Loop CRC Fail %x %x"),received_crc,calculated_crc); + currentTask.crcPassFail = -1; + } + flagEnded = false; + + + } + // Check CRC validity + if (crcPass) { + // Data received successfully, process it (e.g., print) + int nodeTo = received_data[0]; + if (nodeTo == 0) { // for master. master does not retransmit, or a loop will runaway. + flagProc = true; + currentTask.gotCallback = true; + } - if (node->_numAnaloguePins>0) { - size_t analogueBytesNeeded = node->_numAnaloguePins * 2; - if (node->_analoguePinBytes < analogueBytesNeeded) { - // Free any existing buffers and allocate new ones. - if (node->_analoguePinBytes > 0) { - free(node->_analogueInputBuffer); - free(node->_analogueInputStates); - free(node->_analoguePinMap); - } - node->_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1); - node->_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1); - node->_analoguePinMap = (uint8_t*) calloc(node->_numAnaloguePins, 1); - if (node->_analogueInputStates != NULL && - node->_analogueInputBuffer != NULL && - node->_analoguePinMap != NULL) { - node->_analoguePinBytes = analogueBytesNeeded; - } else { - DIAG(F("EX-IOExpander485 node:%d ERROR alloc analog pin bytes"), nodeFr); - //_deviceState = DEVSTATE_FAILED; - node->_analoguePinBytes = 0; - return; - } - } - } - node->resFlag[_currentTask->_retFlag] = 1; - break;} - case EXIOINITA: { - for (int i = 0; i < node->_numAnaloguePins; i++) { - node->_analoguePinMap[i] = received_data[i+3]; - } - node->resFlag[_currentTask->_retFlag] = 1; - break; - } - case EXIOVER: { - node->_majorVer = received_data[3]; - node->_minorVer = received_data[4]; - node->_patchVer = received_data[5]; - node->resFlag[_currentTask->_retFlag] = 1; - break; - } - case EXIORDY: { - node->resFlag[_currentTask->_retFlag] = 1; - break; - } - case EXIOERR: { - node->resFlag[_currentTask->_retFlag] = -1; - break; - } - case EXIORDD: { - for (int i = 0; i < (node->_numDigitalPins+7)/8; i++) { - node->_digitalInputStates[i] = received_data[i+3]; - } - node->resFlag[_currentTask->_retFlag] = 1; - break; - } - case EXIORDAN: { - for (int i = 0; i < node->_numAnaloguePins; i++) { - node->_analogueInputBuffer[i] = received_data[i+3]; - } - node->resFlag[_currentTask->_retFlag] = 1; - break; + } else { + //DIAG(F("IO_RSproto: CRC Error!")); } } + + // temp debug + //end debug + + if (flagProc) { + int nodeTo = received_data[0]; + int nodeFr = received_data[1]; + int AddrCode = received_data[2]; + //DIAG(F("From: %i, To: %i | %i %i %i %i %i"), nodeFr,nodeTo, received_data[3], received_data[4], received_data[5], received_data[6],received_data[7]); + //return; + RSprotonode *node = findNode(nodeFr); + switch (AddrCode) { + case EXIOPINS: + {node->setnumDigitalPins(received_data[3]); + node->setnumAnalogPins(received_data[4]); + + // See if we already have suitable buffers assigned + if (node->getnumDigialPins()>0) { + size_t digitalBytesNeeded = (node->getnumDigialPins() + 7) / 8; + if (node->getdigitalPinBytes() < digitalBytesNeeded) { + // Not enough space, free any existing buffer and allocate a new one + if (node->cleandigitalPinStates(digitalBytesNeeded)) { + node->setdigitalPinBytes(digitalBytesNeeded); + } else { + DIAG(F("EX-IOExpander485 node:%d ERROR alloc %d bytes"), nodeFr, digitalBytesNeeded); + //_deviceState = DEVSTATE_FAILED; + node->setdigitalPinBytes(0); + return; + } + } + } + + if (node->getnumAnalogPins()>0) { + size_t analogueBytesNeeded = node->getnumAnalogPins() * 2; + if (node->getanalogPinBytes() < analogueBytesNeeded) { + // Free any existing buffers and allocate new ones. + + if (node->cleanAnalogStates(analogueBytesNeeded)) { + node->setanalogPinBytes(analogueBytesNeeded); + } else { + DIAG(F("EX-IOExpander485 node:%d ERROR alloc analog pin bytes"), nodeFr); + //_deviceState = DEVSTATE_FAILED; + node->setanalogPinBytes(0); + return; + } + } + } + node->resFlag[currentTask.retFlag] = 1; + break;} + case EXIOINITA: { + for (int i = 0; i < node->getnumAnalogPins(); i++) { + node->setanalogPinMap(received_data[i+3], i); + } + node->resFlag[currentTask.retFlag] = 1; + break; + } + case EXIOVER: { + node->setMajVer(received_data[3]); + node->setMinVer(received_data[4]); + node->setPatVer(received_data[5]); + DIAG(F("EX-IOExpander485: Found node %i v%i.%i.%i"),node->getNodeID(), node->getMajVer(), node->getMinVer(), node->getPatVer()); + node->resFlag[currentTask.retFlag] = 1; + break; + } + case EXIORDY: { + node->resFlag[currentTask.retFlag] = 1; + break; + } + case EXIOERR: { + node->resFlag[currentTask.retFlag] = -1; + break; + } + case EXIORDD: { + for (int i = 0; i < (node->_numDigitalPins+7)/8; i++) { + node->setanalogInputStates(received_data[i+3], i); + } + node->resFlag[currentTask.retFlag] = 1; + break; + } + case EXIORDAN: { + for (int i = 0; i < node->_numAnaloguePins; i++) { + node->setanalogInputBuffer(received_data[i+3], i); + } + + node->resFlag[currentTask.retFlag] = 1; + break; + } + } + + } + if (currentTask.gotCallback) { + + } + } - } // Link to chain of RSproto instances, left over from RSproto template. @@ -653,7 +319,7 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun unsigned long startMillis = millis(); RSproto *bus = RSproto::findBus(0); bus->_busy = true; - bus->sendInstantCommand(buff, 5, EXIODPUP); + bus->addTask(bus->taskIDCntr++, buff, 5, EXIODPUP); bus->_busy = false; return true; @@ -672,7 +338,7 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun unsigned long startMillis = millis(); RSproto *bus = RSproto::findBus(0); bus->_busy = true; - bus->sendInstantCommand(buff, 6, EXIOENAN); + bus->addTask(bus->taskIDCntr++, buff, 6, EXIOENAN); bus->_busy = false; return true; @@ -689,7 +355,7 @@ void RSprotonode::_begin() { unsigned long startMillis = millis(); RSproto *bus = RSproto::findBus(0); bus->_busy = true; - bus->sendInstantCommand(buff, 6, EXIOINIT); + bus->addTask(bus->taskIDCntr++, buff, 6, EXIOINIT); bus->_busy = false; buff[0] = (_nodeID); @@ -697,16 +363,16 @@ void RSprotonode::_begin() { buff[2] = (EXIOINITA); startMillis = millis(); bus->_busy = true; - bus->sendInstantCommand(buff,3, EXIOINITA); - bus->_busy = false; + bus->addTask(bus->taskIDCntr++, buff, 3, EXIOINITA); + bus->_busy = false; buff[0] = (_nodeID); buff[1] = (0); buff[2] = (EXIOVER); startMillis = millis(); bus->_busy = true; - bus->sendInstantCommand(buff,3, EXIOVER); - bus->_busy = false; + bus->addTask(bus->taskIDCntr++, buff, 3, EXIOVER); + bus->_busy = false; @@ -733,7 +399,7 @@ void RSprotonode::_write(VPIN vpin, int value) { buff[4] = (value); unsigned long startMillis = millis(); RSproto *bus = RSproto::findBus(0); - task->doCommand(bus->taskCounter++, buff, 5, EXIOWRD); + bus->addTask(bus->taskIDCntr++, buff, 5, EXIOWRD); } @@ -764,6 +430,6 @@ void RSprotonode::_write(VPIN vpin, int value) { buff[8] = lowByte(duration); unsigned long startMillis = millis(); RSproto *bus = RSproto::findBus(0); - task->doCommand(bus->taskCounter++, buff, 9, EXIOWRAN); + bus->addTask(bus->taskIDCntr++, buff, 9, EXIOWRAN); } \ No newline at end of file diff --git a/IO_RSproto.h b/IO_RSproto.h index c4a99ac..c1404f3 100644 --- a/IO_RSproto.h +++ b/IO_RSproto.h @@ -76,81 +76,6 @@ class RSprotonode; * Data Packet must always precede the parameters with the Command byte. * this way the data is processed by the correct routine. **********************************************************************/ -class taskBuffer -{ -private: - HardwareSerial * hwSerial; - unsigned long _baud; - static const int ARRAY_SIZE = 254; -public: - static taskBuffer *first; - static taskBuffer *end; - RSprotonode *node; - unsigned long _taskID; - Stream * serial; - uint8_t _txPin; - uint8_t _nodeID; - uint8_t _commandType; - unsigned long _cycleTimer = 0ul; - - taskBuffer *next; - uint8_t startChar[1] = {0xFD}; - uint8_t endChar[1] = {0xFE}; - - int commandArray[ARRAY_SIZE]; - int _byteCount = 0; - uint8_t _retFlag = 0; - // EX-IOExpander protocol flags - enum { - EXIOINIT = 0xE0, // Flag to initialise setup procedure - EXIORDY = 0xE1, // Flag we have completed setup procedure, also for EX-IO to ACK setup - EXIODPUP = 0xE2, // Flag we're sending digital pin pullup configuration - EXIOVER = 0xE3, // Flag to get version - EXIORDAN = 0xE4, // Flag to read an analogue input - EXIOWRD = 0xE5, // Flag for digital write - EXIORDD = 0xE6, // Flag to read digital input - EXIOENAN = 0xE7, // Flag to enable an analogue pin - EXIOINITA = 0xE8, // Flag we're receiving analogue pin mappings - EXIOPINS = 0xE9, // Flag we're receiving pin counts for buffers - EXIOWRAN = 0xEA, // Flag we're sending an analogue write (PWM) - EXIOERR = 0xEF, // Flag we've received an error - }; - // RSproto protocol frame bytes - enum { - STARTBYTE = 0xFD, - ENDBYTE = 0xFE, - }; - - - - unsigned long getTaskID() { - return _taskID; - } - void setTaskID(unsigned long taskID) { - _taskID = taskID; - } - taskBuffer *getNext() { - return next; - } - - void setNext(taskBuffer *task) { - next = task; - } - void addTask(taskBuffer *newTask) { - if (!first) - first = newTask; - if (!end) - end = newTask; - else - end->setNext(newTask); - //DIAG(F("RSproto: 260h nodeID:%d _nodeListStart:%d _nodeListEnd:%d"), newNode, _nodeListStart, _nodeListEnd); - } - taskBuffer(unsigned long taskID, uint8_t *commandBuffer, int byteCount, uint8_t retFlag); - ~taskBuffer(); - void doCommand(unsigned long taskID, uint8_t *commandBuffer, int byteCount, uint8_t retFlag); -}; - - @@ -170,7 +95,6 @@ private: RSprotonode *_next = NULL; bool _initialised = false; RSproto *bus; - taskBuffer *task; HardwareSerial* _serial; enum { EXIOINIT = 0xE0, // Flag to initialise setup procedure @@ -200,17 +124,103 @@ public: }; uint8_t _numDigitalPins = 0; + uint8_t getnumDigialPins() { + return _numDigitalPins; + } + void setnumDigitalPins(uint8_t value) { + _numDigitalPins = value; + } uint8_t _numAnaloguePins = 0; + uint8_t getnumAnalogPins() { + return _numAnaloguePins; + } + void setnumAnalogPins(uint8_t value) { + _numAnaloguePins = value; + } uint8_t _majorVer = 0; + uint8_t getMajVer() { + return _majorVer; + } + void setMajVer(uint8_t value) { + _majorVer = value; + } uint8_t _minorVer = 0; + uint8_t getMinVer() { + return _minorVer; + } + void setMinVer(uint8_t value) { + _minorVer = value; + } uint8_t _patchVer = 0; + uint8_t getPatVer() { + return _patchVer; + } + void setPatVer(uint8_t value) { + _patchVer = value; + } uint8_t* _digitalInputStates = NULL; + uint8_t getdigitalInputStates(int index) { + return _digitalInputStates[index]; + } + void setdigitalInputStates(uint8_t value, int index) { + _digitalInputStates[index] = value; + } + bool cleandigitalPinStates(int size) { + if (_digitalPinBytes > 0) free(_digitalInputStates); + if ((_digitalInputStates = (byte*) calloc(size, 1)) != NULL) { + return true; + } else return false; + } uint8_t* _analogueInputStates = NULL; + uint8_t getanalogInputStates(int index) { + return _analogueInputStates[index]; + } + void setanalogInputStates(uint8_t value, int index) { + _analogueInputStates[index] = value; + } + uint8_t* _analogueInputBuffer = NULL; // buffer for I2C input transfers - uint8_t _readCommandBuffer[4]; + uint8_t getanalogInpuBuffer(int index) { + return _analogueInputBuffer[index]; + } + void setanalogInputBuffer(uint8_t value, int index) { + _analogueInputBuffer[index] = value; + memcpy(_analogueInputStates, _analogueInputBuffer, _analoguePinBytes); + } + uint8_t _readCommandBuffer[4]; // unused? uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed) + uint8_t getdigitalPinBytes() { + return _digitalPinBytes; + } + void setdigitalPinBytes(uint8_t value) { + _digitalPinBytes = value; + } uint8_t _analoguePinBytes = 0; // Size of allocated memory buffer (may be longer than needed) + uint8_t getanalogPinBytes() { + return _analoguePinBytes; + } + void setanalogPinBytes(uint8_t value) { + _analoguePinBytes = value; + } uint8_t* _analoguePinMap = NULL; + uint8_t getanalogPinMap(int index) { + return _analoguePinMap[index]; + } + void setanalogPinMap(uint8_t value, int index) { + _analoguePinMap[index] = value; + } + bool cleanAnalogStates(int size) { + if (_analoguePinBytes > 0) { + free(_analogueInputBuffer); + free(_analogueInputStates); + free(_analoguePinMap); + } + _analogueInputStates = (uint8_t*) calloc(size, 1); + _analogueInputBuffer = (uint8_t*) calloc(size, 1); + _analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1); + if (_analogueInputStates != NULL && _analogueInputBuffer != NULL && _analoguePinMap != NULL) return true; + else return false; + } int resFlag[255]; bool _initalized; static void create(VPIN firstVpin, int nPins, uint8_t nodeID) { @@ -266,7 +276,6 @@ class RSproto : public IODevice { private: // Here we define the device-specific variables. uint8_t _busNo; - taskBuffer *task; unsigned long _cycleStartTime = 0; unsigned long _timeoutStart = 0; unsigned long _cycleTime; // target time between successive read/write cycles, microseconds @@ -300,7 +309,6 @@ private: RSprotonode *_nodeListStart = NULL, *_nodeListEnd = NULL; RSprotonode *_currentNode = NULL; - taskBuffer *_taskListStart = NULL, *_taskListEnd = NULL, *_currentTask=NULL; uint16_t _receiveDataIndex = 0; // Index of next data byte to be received. RSproto *_nextBus = NULL; // Pointer to next bus instance in list. @@ -312,6 +320,54 @@ private: } int byteCounter = 0; public: +struct Task { + static const int ARRAY_SIZE = 254; + int taskID; + uint8_t commandArray[ARRAY_SIZE]; + int byteCount; + uint8_t retFlag; + bool gotCallback; + bool rxMode; + int crcPassFail; + bool completed = false; + }; + int taskIDCntr = 0; +Task taskBuffer[100]; // Buffer to hold up to 100 tasks +int taskCount = 0; +void addTask(int id, const uint8_t* cmd, int byteCount, uint8_t retFlag, bool gotCallBack=false, bool rxMode=false, int crcPassFail=0) { + if (taskCount < 100) { // Check if buffer is not full + taskBuffer[taskCount].taskID = id; + memcpy(taskBuffer[taskCount].commandArray, cmd, ARRAY_SIZE); + taskBuffer[taskCount].commandArray[ARRAY_SIZE] = 0; // Ensure null-termination + taskBuffer[taskCount].byteCount = byteCount; + taskBuffer[taskCount].retFlag = retFlag; + taskBuffer[taskCount].gotCallback = false; + taskBuffer[taskCount].rxMode = false; + taskBuffer[taskCount].crcPassFail = 0; + taskBuffer[taskCount].completed = false; + taskCount++; + } else { + Serial.println("Task buffer overflow!"); + } +} +Task getNextTask() { + for (int i = 0; i < taskCount; i++) { + if (!taskBuffer[i].completed) { + return taskBuffer[i]; + } + } + // Return a default task if no uncompleted tasks found + Task emptyTask; + return emptyTask; +} +void markTaskCompleted(int taskID) { + for (int i = 0; i < taskCount; i++) { + if (taskBuffer[i].taskID == taskID) { + taskBuffer[i].completed = true; + break; + } + } +} bool flagEnd = false; bool flagEnded = false; bool flagStart = false; @@ -327,7 +383,6 @@ uint16_t crc16(uint8_t *data, uint16_t length); void remove_nulls(char *str, int len); int getCharsLeft(char *str, char position); void parseRx(uint8_t * outArray, uint8_t retFlag); - void sendInstantCommand(uint8_t *buf, int byteCount, uint8_t retFlag); // EX-IOExpander protocol flags enum { EXIOINIT = 0xE0, // Flag to initialise setup procedure @@ -356,7 +411,7 @@ uint16_t crc16(uint8_t *data, uint16_t length); unsigned long _baud; int taskCnt = 0; uint8_t initBuffer[1] = {0xFE}; - unsigned long taskCounter=0; + unsigned long taskCounter=0ul; // Device-specific initialisation void _begin() override { _serial->begin(_baud, SERIAL_8N1); @@ -400,13 +455,6 @@ uint16_t crc16(uint8_t *data, uint16_t length); } return NULL; } - taskBuffer *findTask(uint8_t taskID) { - for (taskBuffer *task = _taskListStart; task != NULL; task = task->getNext()) { - if (task->getTaskID() == taskID) - return task; - } - return NULL; - } bool nodesInitialized() { bool retval = true; @@ -426,15 +474,7 @@ uint16_t crc16(uint8_t *data, uint16_t length); _nodeListEnd->setNext(newNode); //DIAG(F("RSproto: 260h nodeID:%d _nodeListStart:%d _nodeListEnd:%d"), newNode, _nodeListStart, _nodeListEnd); } -void addTask(taskBuffer *newTask) { - if (!_taskListStart) - _taskListStart = newTask; - if (!_nodeListEnd) - _taskListEnd = newTask; - else - _taskListEnd->setNext(newTask); - //DIAG(F("RSproto: 260h nodeID:%d _nodeListStart:%d _nodeListEnd:%d"), newNode, _nodeListStart, _nodeListEnd); - } + protected: RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin, int cycleTime);