mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-04-21 12:31:19 +02:00
save current
This commit is contained in:
parent
8414ff737c
commit
415dc2674a
410
IO_RSproto.cpp
410
IO_RSproto.cpp
@ -27,13 +27,20 @@ static const byte PAYLOAD_STRING = 2;
|
|||||||
|
|
||||||
taskBuffer * taskBuffer::first=NULL;
|
taskBuffer * taskBuffer::first=NULL;
|
||||||
|
|
||||||
taskBuffer::taskBuffer(Stream * myserial)
|
taskBuffer::taskBuffer(unsigned long taskID, int *commandBuffer)
|
||||||
{
|
{
|
||||||
serial = myserial;
|
_taskID = taskID;
|
||||||
|
memset(commandArray, 0, ARRAY_SIZE);
|
||||||
|
memcpy(commandArray, commandBuffer, ARRAY_SIZE);
|
||||||
|
|
||||||
next=first;
|
next=first;
|
||||||
first=this;
|
first=this;
|
||||||
bufferLength=0;
|
|
||||||
inCommandPayload=PAYLOAD_FALSE;
|
RSproto *bus = RSproto::findBus(0);
|
||||||
|
if (bus != NULL) {
|
||||||
|
bus->addTask(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
taskBuffer::~taskBuffer()
|
taskBuffer::~taskBuffer()
|
||||||
@ -41,27 +48,20 @@ taskBuffer::~taskBuffer()
|
|||||||
// destructor
|
// destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
int taskBuffer::getCharsRightOfPosition(char* str, char position, char* outStr, int size) {
|
void RSproto::remove_nulls(char *str, int len) {
|
||||||
//if (position >= 0 && position < strlen(str)) {
|
int i, j = 0;
|
||||||
int pos;
|
for (i = 0; i<len; i++) {
|
||||||
char retStr[size];
|
if (str[i] != '\0') {
|
||||||
for (int i = 0; str[i] != '\0'; i++) {
|
str[j++] = str[i];
|
||||||
if (str[i] == position) {
|
|
||||||
pos = i;
|
|
||||||
break; // Exit the loop once the character is found
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int i;
|
str[j] = '\0'; // Ensure the string is null-terminated
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
retStr[i] = str[i+pos+1];
|
|
||||||
}
|
|
||||||
memcpy(outStr, retStr, i+pos+1);
|
|
||||||
return i+pos+2;
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void taskBuffer::getCharsLeft(char *str, char position, char *result) {
|
int RSproto::getCharsLeft(char *str, char position) {
|
||||||
int pos;
|
int pos;
|
||||||
|
char result[25];
|
||||||
|
memset(result, '\0', 25);
|
||||||
for (int i = 0; str[i] != '\0'; i++) {
|
for (int i = 0; str[i] != '\0'; i++) {
|
||||||
if (str[i] == position) {
|
if (str[i] == position) {
|
||||||
pos = i;
|
pos = i;
|
||||||
@ -73,124 +73,25 @@ void taskBuffer::getCharsLeft(char *str, char position, char *result) {
|
|||||||
if (i < pos) result[i] = str[i];
|
if (i < pos) result[i] = str[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result != NULL) return atoi(result);
|
||||||
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int taskBuffer::getValues(char *buf, int lenBuf, int fieldCnt, int *outArray) {
|
void taskBuffer::doCommand(unsigned long taskID, int *commandBuffer) {
|
||||||
char curBuff[400];
|
// add commands here to be sent
|
||||||
memset(curBuff, '\0', 25);
|
new taskBuffer(taskID, commandBuffer);
|
||||||
int byteCntr = 0;
|
|
||||||
int counter = 0;
|
|
||||||
for (int i = 0; i< lenBuf; i++) {
|
|
||||||
|
|
||||||
if (buf[i] == ' ' || buf[i] == '\0'){
|
|
||||||
//outArray[counter] = 0x00;
|
|
||||||
outArray[byteCntr] = atoi(curBuff);
|
|
||||||
//DIAG(F("byte: %i"),outArray[byteCntr]);
|
|
||||||
byteCntr++;
|
|
||||||
memset(curBuff, '\0', sizeof(curBuff));
|
|
||||||
counter = 0;
|
|
||||||
} else {
|
|
||||||
curBuff[counter] = buf[i];
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
if (byteCntr > fieldCnt || buf[i] == '\0') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return byteCntr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskBuffer::doCommand(char *commandBuffer, int commandSize) {
|
|
||||||
for (taskBuffer * t=first;t;t=t->next) t->doCommand2(commandBuffer,commandSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskBuffer::doCommand2(char *commandBuffer, int commandSize) {
|
|
||||||
// process commands here to be sent
|
|
||||||
|
|
||||||
//_serial->begin(115200);
|
|
||||||
//ArduinoPins::fastWriteDigital(bus->_txPin, HIGH);
|
|
||||||
//int counter = 0;
|
|
||||||
//RSproto *bus = RSproto::findBus(0);
|
|
||||||
//RSprotonode *node = bus->findNode(commandSize);
|
|
||||||
//while (node->resFlag == 0 && counter < 5) {
|
|
||||||
if (_txPin != -1) digitalWrite(_txPin,HIGH);
|
|
||||||
serial->print(commandBuffer);
|
|
||||||
if (_txPin != -1) digitalWrite(_txPin,LOW);
|
|
||||||
//counter++;
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void taskBuffer::init(HardwareSerial &hwSerial, unsigned long baud, int8_t txPin) {
|
void RSproto::parseRx(int * outArray) {
|
||||||
hwSerial.begin(baud, SERIAL_8N1);
|
int nodeFr = (outArray[3] << 8) | outArray[2];
|
||||||
new taskBuffer(&hwSerial);
|
int AddrCode = (outArray[5] << 8) | outArray[4];
|
||||||
for (taskBuffer * t=first;t;t=t->next) t->_txPin = txPin;
|
DIAG(F("From: %i, To: %i"), nodeFr,(outArray[1] << 8) | outArray[0]);
|
||||||
if (txPin != -1) pinMode(txPin, OUTPUT);
|
RSprotonode *node = findNode(nodeFr);
|
||||||
if (txPin != -1) digitalWrite(txPin, LOW);
|
switch (AddrCode) {
|
||||||
}
|
|
||||||
|
|
||||||
void taskBuffer::loop() {
|
|
||||||
for (taskBuffer * t=first;t;t=t->next) t->loop2();
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskBuffer::loop2() {
|
|
||||||
// process received commands here
|
|
||||||
char ch;
|
|
||||||
while (serial->available()) {
|
|
||||||
ch = serial->read();
|
|
||||||
//RS485_SERIAL.write(ch,1); // send round the ring in case not ours
|
|
||||||
if (!inCommandPayload) {
|
|
||||||
if (ch == '<') {
|
|
||||||
inCommandPayload = PAYLOAD_NORMAL;
|
|
||||||
bufferLength = 0;
|
|
||||||
//tmpBuffer[0] = '\0';
|
|
||||||
}
|
|
||||||
} else { // if (inCommandPayload)
|
|
||||||
if (inCommandPayload == PAYLOAD_NORMAL) {
|
|
||||||
if (ch == '>') {
|
|
||||||
//tmpBuffer[bufferLength] = '\0';
|
|
||||||
|
|
||||||
char chrSize[3];
|
|
||||||
getCharsLeft(buffer,'|', chrSize);
|
|
||||||
char chrSend[400];
|
|
||||||
int remainder = getCharsRightOfPosition(buffer,'|',chrSend, sizeof(buffer));
|
|
||||||
DIAG(F("%s:%i:%i"),chrSend, remainder,atoi(chrSize));
|
|
||||||
parseRx(chrSend, remainder, atoi(chrSize));
|
|
||||||
memset(buffer, '\0', sizeof(buffer));
|
|
||||||
bufferLength = 0;
|
|
||||||
inCommandPayload = PAYLOAD_FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bufferLength < (COMMAND_BUFFER_SIZE-1) && inCommandPayload == PAYLOAD_NORMAL) {
|
|
||||||
buffer[bufferLength] = ch;
|
|
||||||
bufferLength++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskBuffer::parseRx(char * rxbuffer, int rxBufLen, int fieldCnt) {
|
|
||||||
// pass on what we got
|
|
||||||
int outValues[fieldCnt];
|
|
||||||
memset(outValues, 0, sizeof(outValues));
|
|
||||||
int realCnt = getValues(rxbuffer, rxBufLen, fieldCnt, outValues);
|
|
||||||
parseOne(outValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taskBuffer::parseOne(int *buf) {
|
|
||||||
// finaly, process the darn data
|
|
||||||
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);
|
|
||||||
switch (opcode) {
|
|
||||||
case EXIOPINS:
|
case EXIOPINS:
|
||||||
{node->_numDigitalPins = buf[3];
|
{node->_numDigitalPins = (outArray[7] << 8) | outArray[6];
|
||||||
node->_numAnaloguePins = buf[4];
|
node->_numAnaloguePins = (outArray[9] << 8) | outArray[8];
|
||||||
|
|
||||||
// See if we already have suitable buffers assigned
|
// See if we already have suitable buffers assigned
|
||||||
if (node->_numDigitalPins>0) {
|
if (node->_numDigitalPins>0) {
|
||||||
@ -201,7 +102,7 @@ void taskBuffer::parseOne(int *buf) {
|
|||||||
if ((node->_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) {
|
if ((node->_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) {
|
||||||
node->_digitalPinBytes = digitalBytesNeeded;
|
node->_digitalPinBytes = digitalBytesNeeded;
|
||||||
} else {
|
} else {
|
||||||
DIAG(F("EX-IOExpander485 node:%d ERROR alloc %d bytes"), fromNode, digitalBytesNeeded);
|
DIAG(F("EX-IOExpander485 node:%d ERROR alloc %d bytes"), nodeFr, digitalBytesNeeded);
|
||||||
//_deviceState = DEVSTATE_FAILED;
|
//_deviceState = DEVSTATE_FAILED;
|
||||||
node->_digitalPinBytes = 0;
|
node->_digitalPinBytes = 0;
|
||||||
return;
|
return;
|
||||||
@ -226,7 +127,7 @@ void taskBuffer::parseOne(int *buf) {
|
|||||||
node->_analoguePinMap != NULL) {
|
node->_analoguePinMap != NULL) {
|
||||||
node->_analoguePinBytes = analogueBytesNeeded;
|
node->_analoguePinBytes = analogueBytesNeeded;
|
||||||
} else {
|
} else {
|
||||||
DIAG(F("EX-IOExpander485 node:%d ERROR alloc analog pin bytes"), fromNode);
|
DIAG(F("EX-IOExpander485 node:%d ERROR alloc analog pin bytes"), nodeFr);
|
||||||
//_deviceState = DEVSTATE_FAILED;
|
//_deviceState = DEVSTATE_FAILED;
|
||||||
node->_analoguePinBytes = 0;
|
node->_analoguePinBytes = 0;
|
||||||
return;
|
return;
|
||||||
@ -237,15 +138,15 @@ void taskBuffer::parseOne(int *buf) {
|
|||||||
break;}
|
break;}
|
||||||
case EXIOINITA: {
|
case EXIOINITA: {
|
||||||
for (int i = 3; i < node->_numAnaloguePins; i++) {
|
for (int i = 3; i < node->_numAnaloguePins; i++) {
|
||||||
node->_analoguePinMap[i] = buf[i];
|
node->_analoguePinMap[i] = (outArray[7] << 8) | outArray[6];
|
||||||
}
|
}
|
||||||
node->resFlag = 1;
|
node->resFlag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EXIOVER: {
|
case EXIOVER: {
|
||||||
node->_majorVer = buf[3];
|
node->_majorVer = (outArray[7] << 8) | outArray[6];
|
||||||
node->_minorVer = buf[4];
|
node->_minorVer = (outArray[9] << 8) | outArray[8];
|
||||||
node->_patchVer = buf[5];
|
node->_patchVer = (outArray[11] << 8) | outArray[10];
|
||||||
node->resFlag = 1;
|
node->resFlag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -258,15 +159,15 @@ void taskBuffer::parseOne(int *buf) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EXIORDD: {
|
case EXIORDD: {
|
||||||
for (int i = 3; i < (node->_numDigitalPins+7)/8; i++) {
|
for (int i = 0; i < (node->_numDigitalPins+7)/8; i=i+2) {
|
||||||
node->_digitalInputStates[i-3] = buf[i];
|
node->_digitalInputStates[i-3] = (outArray[i+1] << 8) | outArray[i];
|
||||||
}
|
}
|
||||||
node->resFlag = 1;
|
node->resFlag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EXIORDAN: {
|
case EXIORDAN: {
|
||||||
for (int i = 3; i < node->_numAnaloguePins*2; i++) {
|
for (int i = 3; i < node->_numAnaloguePins*2; i++) {
|
||||||
node->_analogueInputBuffer[i-3] = buf[i];
|
node->_analogueInputBuffer[i-3] = (outArray[i+1] << 8) | outArray[i];
|
||||||
}
|
}
|
||||||
node->resFlag = 1;
|
node->resFlag = 1;
|
||||||
break;
|
break;
|
||||||
@ -282,11 +183,12 @@ void taskBuffer::parseOne(int *buf) {
|
|||||||
RSproto::RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin, int cycleTime) {
|
RSproto::RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin, int cycleTime) {
|
||||||
_serial = &serial;
|
_serial = &serial;
|
||||||
_baud = baud;
|
_baud = baud;
|
||||||
|
|
||||||
_txPin = txPin;
|
_txPin = txPin;
|
||||||
_busNo = busNo;
|
_busNo = busNo;
|
||||||
_cycleTime = cycleTime;
|
_cycleTime = cycleTime;
|
||||||
task->init(serial, baud, txPin);
|
bufferLength=0;
|
||||||
if (_waitA < 3) _waitA = 3;
|
inCommandPayload=PAYLOAD_FALSE;
|
||||||
// Add device to HAL device chain
|
// Add device to HAL device chain
|
||||||
IODevice::addDevice(this);
|
IODevice::addDevice(this);
|
||||||
|
|
||||||
@ -301,19 +203,117 @@ RSproto::RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8
|
|||||||
// Work through list of nodes. For each node, in separate loop entries
|
// Work through list of nodes. For each node, in separate loop entries
|
||||||
// When the slot time has finished, move on to the next device.
|
// When the slot time has finished, move on to the next device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// CRC-16 implementation (replace with your preferred CRC library if needed)
|
||||||
|
uint16_t RSproto::crc16(uint8_t *data, uint16_t length) {
|
||||||
|
uint16_t crc = 0xFFFF;
|
||||||
|
for (uint16_t i = 0; i < length; i++) {
|
||||||
|
crc ^= data[i];
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
bool bit = ((crc & 0x0001) != 0);
|
||||||
|
crc >>= 1;
|
||||||
|
if (bit) {
|
||||||
|
crc ^= 0xA001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RSproto::sendInstantCommand(int *buf) {
|
||||||
|
// Calculate CRC for response data
|
||||||
|
uint16_t response_crc = crc16((uint8_t*)buf, ARRAY_SIZE);
|
||||||
|
if (_txPin != -1) digitalWrite(_txPin,HIGH);
|
||||||
|
// Send response data with CRC
|
||||||
|
for (int i = 0; i < ARRAY_SIZE; i++) {
|
||||||
|
_serial->write(buf[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
_serial->write(response_crc >> 8);
|
||||||
|
_serial->write(response_crc & 0xFF);
|
||||||
|
_serial->flush();
|
||||||
|
if (_txPin != -1) digitalWrite(_txPin,LOW);
|
||||||
|
// delete task command after sending, for now
|
||||||
|
|
||||||
|
DIAG(F("SA: %I"),_serial->available());
|
||||||
|
if (_serial->available() >= ARRAY_SIZE) {
|
||||||
|
int received_data[ARRAY_SIZE];
|
||||||
|
|
||||||
|
// Read data and CRC
|
||||||
|
for (int i = 0; i < ARRAY_SIZE; i++) {
|
||||||
|
received_data[i] = _serial->read();
|
||||||
|
}
|
||||||
|
uint16_t received_crc = (_serial->read() << 8) | _serial->read();
|
||||||
|
|
||||||
|
// Calculate CRC for received data
|
||||||
|
uint16_t calculated_crc = crc16((uint8_t*)received_data, ARRAY_SIZE);
|
||||||
|
|
||||||
|
// Check CRC validity
|
||||||
|
if (calculated_crc == received_crc) {
|
||||||
|
// Data received successfully, process it (e.g., print)
|
||||||
|
int nodeTo = (received_data[1] << 8) | received_data[0];
|
||||||
|
if (nodeTo == 0) { // for master. master does not retransmit, or a loop will runaway.
|
||||||
|
parseRx(received_data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DIAG(F("IO_RSproto: CRC Error!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RSproto::_loop(unsigned long currentMicros) {
|
void RSproto::_loop(unsigned long currentMicros) {
|
||||||
_currentMicros = currentMicros;
|
_currentMicros = currentMicros;
|
||||||
|
if (_busy == true) return;
|
||||||
|
if (_currentTask == NULL) {
|
||||||
|
_currentTask = _taskListStart;
|
||||||
|
|
||||||
//if (_currentNode == NULL) {
|
}
|
||||||
// _currentNode = _nodeListStart;
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (_currentMicros - _cycleStartTime < _cycleTime) return;
|
if (_currentMicros - _cycleStartTime < _cycleTime) return;
|
||||||
_cycleStartTime = _currentMicros;
|
_cycleStartTime = _currentMicros;
|
||||||
//if (_currentNode == NULL) return;
|
if (_currentTask != NULL && _currentTask->commandArray[0] != 0) {
|
||||||
task->loop();
|
|
||||||
|
|
||||||
|
// Calculate CRC for response data
|
||||||
|
uint16_t response_crc = crc16((uint8_t*)_currentTask->commandArray, ARRAY_SIZE);
|
||||||
|
if (_txPin != -1) digitalWrite(_txPin,HIGH);
|
||||||
|
// Send response data with CRC
|
||||||
|
for (int i = 0; i < ARRAY_SIZE; i++) {
|
||||||
|
_serial->write(_currentTask->commandArray[i]);
|
||||||
|
}
|
||||||
|
_serial->write(response_crc >> 8);
|
||||||
|
_serial->write(response_crc & 0xFF);
|
||||||
|
_serial->flush();
|
||||||
|
if (_txPin != -1) digitalWrite(_txPin,LOW);
|
||||||
|
// delete task command after sending, for now
|
||||||
|
memset(_currentTask->commandArray, 0, ARRAY_SIZE);
|
||||||
|
_currentTask->_commandSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_serial->available() >= ARRAY_SIZE) {
|
||||||
|
int received_data[ARRAY_SIZE];
|
||||||
|
|
||||||
|
// Read data and CRC
|
||||||
|
for (int i = 0; i < ARRAY_SIZE; i++) {
|
||||||
|
received_data[i / sizeof(int)] = _serial->read();
|
||||||
|
}
|
||||||
|
uint16_t received_crc = (_serial->read() << 8) | _serial->read();
|
||||||
|
|
||||||
|
// Calculate CRC for received data
|
||||||
|
uint16_t calculated_crc = crc16((uint8_t*)received_data, ARRAY_SIZE);
|
||||||
|
|
||||||
|
// Check CRC validity
|
||||||
|
if (calculated_crc == received_crc) {
|
||||||
|
// Data received successfully, process it (e.g., print)
|
||||||
|
int nodeTo = (received_data[1] << 8) | received_data[0];
|
||||||
|
if (nodeTo == 0) { // for master. master does not retransmit, or a loop will runaway.
|
||||||
|
parseRx(received_data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DIAG(F("IO_RSproto: CRC Error!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task->getNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link to chain of RSproto instances, left over from RSproto template.
|
// Link to chain of RSproto instances, left over from RSproto template.
|
||||||
@ -355,10 +355,22 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun
|
|||||||
int pin = vpin - _firstVpin;
|
int pin = vpin - _firstVpin;
|
||||||
|
|
||||||
uint8_t pullup = (uint8_t)params[0];
|
uint8_t pullup = (uint8_t)params[0];
|
||||||
char buff[25];
|
int buff[ARRAY_SIZE];
|
||||||
sprintf(buff, "<5|%i %i %i %i %i>", _nodeID, 0, EXIODPUP, pin, pullup);
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIODPUP);
|
||||||
|
buff[5] = lowByte(EXIODPUP);
|
||||||
|
buff[6] = highByte(pin);
|
||||||
|
buff[7] = lowByte(pin);
|
||||||
|
buff[8] = highByte(pullup);
|
||||||
|
buff[9] = lowByte(pullup);
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
task->doCommand(buff,_nodeID);
|
RSproto *bus = RSproto::findBus(0);
|
||||||
|
bus->_busy = true;
|
||||||
|
bus->sendInstantCommand(buff);
|
||||||
|
bus->_busy = false;
|
||||||
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin);
|
DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin);
|
||||||
@ -371,10 +383,22 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun
|
|||||||
int RSprotonode::_configureAnalogIn(VPIN vpin) {
|
int RSprotonode::_configureAnalogIn(VPIN vpin) {
|
||||||
int pin = vpin - _firstVpin;
|
int pin = vpin - _firstVpin;
|
||||||
//RSproto *mainrs = RSproto::findBus(_busNo);
|
//RSproto *mainrs = RSproto::findBus(_busNo);
|
||||||
char buff[25];
|
int buff[ARRAY_SIZE];
|
||||||
sprintf(buff, "<6|%i %i %i %i %i %i>", _nodeID, 0, EXIOENAN, pin, _firstVpin);
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIOENAN);
|
||||||
|
buff[5] = lowByte(EXIOENAN);
|
||||||
|
buff[6] = highByte(pin);
|
||||||
|
buff[7] = lowByte(pin);
|
||||||
|
buff[8] = highByte(_firstVpin);
|
||||||
|
buff[9] = lowByte(_firstVpin);
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
task->doCommand(buff, _nodeID);
|
RSproto *bus = RSproto::findBus(0);
|
||||||
|
bus->_busy = true;
|
||||||
|
bus->sendInstantCommand(buff);
|
||||||
|
bus->_busy = false;
|
||||||
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin);
|
DIAG(F("EX-IOExpander485 Vpin %u cannot be used as a digital input pin"), pin);
|
||||||
@ -385,26 +409,52 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RSprotonode::_begin() {
|
void RSprotonode::_begin() {
|
||||||
char buff[25];
|
int buff[ARRAY_SIZE];
|
||||||
sprintf(buff, "<6|%i %i %i %i %i %i>", _nodeID, 0, EXIOINIT, _nPins, (_firstVpin & 0xFF), (_firstVpin >> 8));
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIOINIT);
|
||||||
|
buff[5] = lowByte(EXIOINIT);
|
||||||
|
buff[6] = highByte(_nPins);
|
||||||
|
buff[7] = lowByte(_nPins);
|
||||||
|
buff[8] = highByte((_firstVpin & 0xFF));
|
||||||
|
buff[9] = lowByte((_firstVpin >> 8));
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
task->doCommand(buff,_nodeID);
|
RSproto *bus = RSproto::findBus(0);
|
||||||
|
bus->_busy = true;
|
||||||
|
bus->sendInstantCommand(buff);
|
||||||
|
bus->_busy = false;
|
||||||
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINIT"), _nodeID);
|
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINIT"), _nodeID);
|
||||||
}
|
}
|
||||||
resFlag = 0;
|
resFlag = 0;
|
||||||
sprintf(buff, "<3|%i %i %i>", _nodeID, 0, EXIOINITA);
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIOINITA);
|
||||||
|
buff[5] = lowByte(EXIOINITA);
|
||||||
startMillis = millis();
|
startMillis = millis();
|
||||||
task->doCommand(buff,_nodeID);
|
bus->_busy = true;
|
||||||
|
bus->sendInstantCommand(buff);
|
||||||
|
bus->_busy = false;
|
||||||
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINITA"), _nodeID);
|
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINITA"), _nodeID);
|
||||||
}
|
}
|
||||||
resFlag = 0;
|
resFlag = 0;
|
||||||
sprintf(buff, "<3|%i %i %i>", _nodeID, 0, EXIOVER);
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIOVER);
|
||||||
|
buff[5] = lowByte(EXIOVER);
|
||||||
startMillis = millis();
|
startMillis = millis();
|
||||||
task->doCommand(buff,_nodeID);
|
bus->_busy = true;
|
||||||
|
bus->sendInstantCommand(buff);
|
||||||
|
bus->_busy = false; task->doCommand(bus->taskCounter++, buff);
|
||||||
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID);
|
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID);
|
||||||
@ -427,10 +477,20 @@ int RSprotonode::_read(VPIN vpin) {
|
|||||||
void RSprotonode::_write(VPIN vpin, int value) {
|
void RSprotonode::_write(VPIN vpin, int value) {
|
||||||
if (_deviceState == DEVSTATE_FAILED) return;
|
if (_deviceState == DEVSTATE_FAILED) return;
|
||||||
int pin = vpin - _firstVpin;
|
int pin = vpin - _firstVpin;
|
||||||
char buff[25];
|
int buff[ARRAY_SIZE];
|
||||||
sprintf(buff, "<5|%i %i %i %i %i>", _nodeID, 0, EXIOWRD, pin, value);
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIOWRD);
|
||||||
|
buff[5] = lowByte(EXIOWRD);
|
||||||
|
buff[6] = highByte(pin);
|
||||||
|
buff[7] = lowByte(pin);
|
||||||
|
buff[8] = highByte(value);
|
||||||
|
buff[9] = lowByte(value);
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
task->doCommand(buff,_nodeID);
|
RSproto *bus = RSproto::findBus(0);
|
||||||
|
task->doCommand(bus->taskCounter++, buff);
|
||||||
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID);
|
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID);
|
||||||
@ -453,10 +513,24 @@ void RSprotonode::_write(VPIN vpin, int value) {
|
|||||||
|
|
||||||
void RSprotonode::_writeAnalogue(VPIN vpin, int value, uint8_t profile, uint16_t duration) {
|
void RSprotonode::_writeAnalogue(VPIN vpin, int value, uint8_t profile, uint16_t duration) {
|
||||||
int pin = vpin - _firstVpin;
|
int pin = vpin - _firstVpin;
|
||||||
char buff[25];
|
int buff[ARRAY_SIZE];
|
||||||
sprintf(buff, "<7|%i %i %i %i %i %i %i>", _nodeID, 0, EXIOWRAN, pin, value, profile, duration);
|
buff[0] = highByte(_nodeID);
|
||||||
|
buff[1] = lowByte(_nodeID);
|
||||||
|
buff[2] = highByte(0);
|
||||||
|
buff[3] = lowByte(0);
|
||||||
|
buff[4] = highByte(EXIOWRAN);
|
||||||
|
buff[5] = lowByte(EXIOWRAN);
|
||||||
|
buff[6] = highByte(pin);
|
||||||
|
buff[7] = lowByte(pin);
|
||||||
|
buff[8] = highByte(value);
|
||||||
|
buff[9] = lowByte(value);
|
||||||
|
buff[8] = highByte(profile);
|
||||||
|
buff[9] = lowByte(profile);
|
||||||
|
buff[8] = highByte(duration);
|
||||||
|
buff[9] = lowByte(duration);
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
task->doCommand(buff,_nodeID);
|
RSproto *bus = RSproto::findBus(0);
|
||||||
|
task->doCommand(bus->taskCounter++, buff);
|
||||||
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
||||||
if (resFlag != 1) {
|
if (resFlag != 1) {
|
||||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID);
|
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOVER"), _nodeID);
|
||||||
|
109
IO_RSproto.h
109
IO_RSproto.h
@ -53,7 +53,7 @@ class RSprotonode;
|
|||||||
|
|
||||||
|
|
||||||
#ifndef COMMAND_BUFFER_SIZE
|
#ifndef COMMAND_BUFFER_SIZE
|
||||||
#define COMMAND_BUFFER_SIZE 400
|
#define COMMAND_BUFFER_SIZE 900
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
@ -79,18 +79,26 @@ class RSprotonode;
|
|||||||
class taskBuffer
|
class taskBuffer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
HardwareSerial * hwSerial;
|
||||||
|
unsigned long _baud;
|
||||||
|
static const int ARRAY_SIZE = 254;
|
||||||
|
public:
|
||||||
static taskBuffer *first;
|
static taskBuffer *first;
|
||||||
|
static taskBuffer *end;
|
||||||
RSprotonode *node;
|
RSprotonode *node;
|
||||||
|
unsigned long _taskID;
|
||||||
Stream * serial;
|
Stream * serial;
|
||||||
uint8_t _txPin;
|
uint8_t _txPin;
|
||||||
uint8_t _nodeID;
|
uint8_t _nodeID;
|
||||||
uint8_t _commandType;
|
uint8_t _commandType;
|
||||||
byte bufferLength;
|
unsigned long _cycleTimer = 0ul;
|
||||||
char buffer[COMMAND_BUFFER_SIZE];
|
|
||||||
taskBuffer *next;
|
taskBuffer *next;
|
||||||
uint8_t startChar[1] = {0xFD};
|
uint8_t startChar[1] = {0xFD};
|
||||||
uint8_t endChar[1] = {0xFE};
|
uint8_t endChar[1] = {0xFE};
|
||||||
byte inCommandPayload;
|
|
||||||
|
int commandArray[ARRAY_SIZE];
|
||||||
|
int _commandSize = 0;
|
||||||
// EX-IOExpander protocol flags
|
// EX-IOExpander protocol flags
|
||||||
enum {
|
enum {
|
||||||
EXIOINIT = 0xE0, // Flag to initialise setup procedure
|
EXIOINIT = 0xE0, // Flag to initialise setup procedure
|
||||||
@ -111,19 +119,34 @@ static taskBuffer *first;
|
|||||||
STARTBYTE = 0xFD,
|
STARTBYTE = 0xFD,
|
||||||
ENDBYTE = 0xFE,
|
ENDBYTE = 0xFE,
|
||||||
};
|
};
|
||||||
int getCharsRightOfPosition(char* str, char position, char* outStr, int size);
|
|
||||||
void getCharsLeft(char *str, char position, char *result);
|
|
||||||
int getValues(char *buf, int lenBuf, int fieldCnt, int *outArray);
|
|
||||||
void doCommand2(char *commandBuffer, int commandSize=0);
|
unsigned long getTaskID() {
|
||||||
void loop2();
|
return _taskID;
|
||||||
void parseRx(char * rxbuffer, int rxBufLen, int fieldCnt);
|
}
|
||||||
void parseOne(int *buf);
|
void setTaskID(unsigned long taskID) {
|
||||||
public:
|
_taskID = taskID;
|
||||||
taskBuffer(Stream * myserial);
|
}
|
||||||
|
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, int *commandBuffer);
|
||||||
~taskBuffer();
|
~taskBuffer();
|
||||||
static void doCommand(char *commandBuffer, int commandSize=0);
|
void doCommand(unsigned long taskID, int *commandBuffer);
|
||||||
static void init(HardwareSerial &hwSerial, unsigned long baud, int8_t txPin=-1);
|
|
||||||
static void loop();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -148,7 +171,6 @@ private:
|
|||||||
RSproto *bus;
|
RSproto *bus;
|
||||||
taskBuffer *task;
|
taskBuffer *task;
|
||||||
HardwareSerial* _serial;
|
HardwareSerial* _serial;
|
||||||
// EX-IOExpander protocol flags
|
|
||||||
enum {
|
enum {
|
||||||
EXIOINIT = 0xE0, // Flag to initialise setup procedure
|
EXIOINIT = 0xE0, // Flag to initialise setup procedure
|
||||||
EXIORDY = 0xE1, // Flag we have completed setup procedure, also for EX-IO to ACK setup
|
EXIORDY = 0xE1, // Flag we have completed setup procedure, also for EX-IO to ACK setup
|
||||||
@ -163,7 +185,7 @@ private:
|
|||||||
EXIOWRAN = 0xEA, // Flag we're sending an analogue write (PWM)
|
EXIOWRAN = 0xEA, // Flag we're sending an analogue write (PWM)
|
||||||
EXIOERR = 0xEF, // Flag we've received an error
|
EXIOERR = 0xEF, // Flag we've received an error
|
||||||
};
|
};
|
||||||
|
static const int ARRAY_SIZE = 254;
|
||||||
public:
|
public:
|
||||||
static RSprotonode *_nodeList;
|
static RSprotonode *_nodeList;
|
||||||
enum ProfileType : int {
|
enum ProfileType : int {
|
||||||
@ -253,7 +275,10 @@ private:
|
|||||||
unsigned long _byteTransmitTime; // time in us for transmission of one byte
|
unsigned long _byteTransmitTime; // time in us for transmission of one byte
|
||||||
int _operationCount = 0;
|
int _operationCount = 0;
|
||||||
int _refreshOperation = 0;
|
int _refreshOperation = 0;
|
||||||
|
byte bufferLength;
|
||||||
|
static const int ARRAY_SIZE = 254;
|
||||||
|
int buffer[ARRAY_SIZE];
|
||||||
|
byte inCommandPayload;
|
||||||
static RSproto *_busList; // linked list of defined bus instances
|
static RSproto *_busList; // linked list of defined bus instances
|
||||||
bool waitReceive = false;
|
bool waitReceive = false;
|
||||||
int _waitCounter = 0;
|
int _waitCounter = 0;
|
||||||
@ -274,6 +299,7 @@ private:
|
|||||||
|
|
||||||
RSprotonode *_nodeListStart = NULL, *_nodeListEnd = NULL;
|
RSprotonode *_nodeListStart = NULL, *_nodeListEnd = NULL;
|
||||||
RSprotonode *_currentNode = NULL;
|
RSprotonode *_currentNode = NULL;
|
||||||
|
taskBuffer *_taskListStart = NULL, *_taskListEnd = NULL, *_currentTask=NULL;
|
||||||
uint16_t _receiveDataIndex = 0; // Index of next data byte to be received.
|
uint16_t _receiveDataIndex = 0; // Index of next data byte to be received.
|
||||||
RSproto *_nextBus = NULL; // Pointer to next bus instance in list.
|
RSproto *_nextBus = NULL; // Pointer to next bus instance in list.
|
||||||
|
|
||||||
@ -285,6 +311,26 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
uint16_t crc16(uint8_t *data, uint16_t length);
|
||||||
|
void remove_nulls(char *str, int len);
|
||||||
|
int getCharsLeft(char *str, char position);
|
||||||
|
void parseRx(int * outArray);
|
||||||
|
void sendInstantCommand(int *buf);
|
||||||
|
// 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
|
||||||
|
};
|
||||||
static void create(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin=-1, int cycleTime=500) {
|
static void create(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin=-1, int cycleTime=500) {
|
||||||
new RSproto(busNo, serial, baud, txPin, cycleTime);
|
new RSproto(busNo, serial, baud, txPin, cycleTime);
|
||||||
}
|
}
|
||||||
@ -298,10 +344,14 @@ public:
|
|||||||
unsigned long _baud;
|
unsigned long _baud;
|
||||||
int taskCnt = 0;
|
int taskCnt = 0;
|
||||||
uint8_t initBuffer[1] = {0xFE};
|
uint8_t initBuffer[1] = {0xFE};
|
||||||
|
unsigned long taskCounter=0;
|
||||||
// Device-specific initialisation
|
// Device-specific initialisation
|
||||||
void _begin() override {
|
void _begin() override {
|
||||||
|
_serial->begin(_baud, SERIAL_8N1);
|
||||||
|
if (_txPin >0) {
|
||||||
|
pinMode(_txPin, OUTPUT);
|
||||||
|
digitalWrite(_txPin, LOW);
|
||||||
|
}
|
||||||
#if defined(RSproto_STM_OK)
|
#if defined(RSproto_STM_OK)
|
||||||
pinMode(RSproto_STM_OK, OUTPUT);
|
pinMode(RSproto_STM_OK, OUTPUT);
|
||||||
ArduinoPins::fastWriteDigital(RSproto_STM_OK,LOW);
|
ArduinoPins::fastWriteDigital(RSproto_STM_OK,LOW);
|
||||||
@ -338,6 +388,13 @@ public:
|
|||||||
}
|
}
|
||||||
return NULL;
|
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 nodesInitialized() {
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
@ -357,7 +414,15 @@ public:
|
|||||||
_nodeListEnd->setNext(newNode);
|
_nodeListEnd->setNext(newNode);
|
||||||
//DIAG(F("RSproto: 260h nodeID:%d _nodeListStart:%d _nodeListEnd:%d"), newNode, _nodeListStart, _nodeListEnd);
|
//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:
|
protected:
|
||||||
RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin, int cycleTime);
|
RSproto(uint8_t busNo, HardwareSerial &serial, unsigned long baud, int8_t txPin, int cycleTime);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user