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(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;
|
||||
first=this;
|
||||
bufferLength=0;
|
||||
inCommandPayload=PAYLOAD_FALSE;
|
||||
|
||||
RSproto *bus = RSproto::findBus(0);
|
||||
if (bus != NULL) {
|
||||
bus->addTask(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
taskBuffer::~taskBuffer()
|
||||
@ -41,27 +48,20 @@ taskBuffer::~taskBuffer()
|
||||
// destructor
|
||||
}
|
||||
|
||||
int taskBuffer::getCharsRightOfPosition(char* str, char position, char* outStr, int size) {
|
||||
//if (position >= 0 && position < strlen(str)) {
|
||||
int pos;
|
||||
char retStr[size];
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
if (str[i] == position) {
|
||||
pos = i;
|
||||
break; // Exit the loop once the character is found
|
||||
void RSproto::remove_nulls(char *str, int len) {
|
||||
int i, j = 0;
|
||||
for (i = 0; i<len; i++) {
|
||||
if (str[i] != '\0') {
|
||||
str[j++] = str[i];
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
retStr[i] = str[i+pos+1];
|
||||
}
|
||||
memcpy(outStr, retStr, i+pos+1);
|
||||
return i+pos+2;
|
||||
//}
|
||||
str[j] = '\0'; // Ensure the string is null-terminated
|
||||
}
|
||||
|
||||
void taskBuffer::getCharsLeft(char *str, char position, char *result) {
|
||||
int RSproto::getCharsLeft(char *str, char position) {
|
||||
int pos;
|
||||
char result[25];
|
||||
memset(result, '\0', 25);
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
if (str[i] == position) {
|
||||
pos = i;
|
||||
@ -73,124 +73,25 @@ void taskBuffer::getCharsLeft(char *str, char position, char *result) {
|
||||
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) {
|
||||
char curBuff[400];
|
||||
memset(curBuff, '\0', 25);
|
||||
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::doCommand(unsigned long taskID, int *commandBuffer) {
|
||||
// add commands here to be sent
|
||||
new taskBuffer(taskID, commandBuffer);
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
if (txPin != -1) pinMode(txPin, OUTPUT);
|
||||
if (txPin != -1) digitalWrite(txPin, LOW);
|
||||
}
|
||||
|
||||
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) {
|
||||
void RSproto::parseRx(int * outArray) {
|
||||
int nodeFr = (outArray[3] << 8) | outArray[2];
|
||||
int AddrCode = (outArray[5] << 8) | outArray[4];
|
||||
DIAG(F("From: %i, To: %i"), nodeFr,(outArray[1] << 8) | outArray[0]);
|
||||
RSprotonode *node = findNode(nodeFr);
|
||||
switch (AddrCode) {
|
||||
case EXIOPINS:
|
||||
{node->_numDigitalPins = buf[3];
|
||||
node->_numAnaloguePins = buf[4];
|
||||
{node->_numDigitalPins = (outArray[7] << 8) | outArray[6];
|
||||
node->_numAnaloguePins = (outArray[9] << 8) | outArray[8];
|
||||
|
||||
// See if we already have suitable buffers assigned
|
||||
if (node->_numDigitalPins>0) {
|
||||
@ -201,7 +102,7 @@ void taskBuffer::parseOne(int *buf) {
|
||||
if ((node->_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) {
|
||||
node->_digitalPinBytes = digitalBytesNeeded;
|
||||
} 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;
|
||||
node->_digitalPinBytes = 0;
|
||||
return;
|
||||
@ -226,7 +127,7 @@ void taskBuffer::parseOne(int *buf) {
|
||||
node->_analoguePinMap != NULL) {
|
||||
node->_analoguePinBytes = analogueBytesNeeded;
|
||||
} 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;
|
||||
node->_analoguePinBytes = 0;
|
||||
return;
|
||||
@ -237,15 +138,15 @@ void taskBuffer::parseOne(int *buf) {
|
||||
break;}
|
||||
case EXIOINITA: {
|
||||
for (int i = 3; i < node->_numAnaloguePins; i++) {
|
||||
node->_analoguePinMap[i] = buf[i];
|
||||
node->_analoguePinMap[i] = (outArray[7] << 8) | outArray[6];
|
||||
}
|
||||
node->resFlag = 1;
|
||||
break;
|
||||
}
|
||||
case EXIOVER: {
|
||||
node->_majorVer = buf[3];
|
||||
node->_minorVer = buf[4];
|
||||
node->_patchVer = buf[5];
|
||||
node->_majorVer = (outArray[7] << 8) | outArray[6];
|
||||
node->_minorVer = (outArray[9] << 8) | outArray[8];
|
||||
node->_patchVer = (outArray[11] << 8) | outArray[10];
|
||||
node->resFlag = 1;
|
||||
break;
|
||||
}
|
||||
@ -258,15 +159,15 @@ void taskBuffer::parseOne(int *buf) {
|
||||
break;
|
||||
}
|
||||
case EXIORDD: {
|
||||
for (int i = 3; i < (node->_numDigitalPins+7)/8; i++) {
|
||||
node->_digitalInputStates[i-3] = buf[i];
|
||||
for (int i = 0; i < (node->_numDigitalPins+7)/8; i=i+2) {
|
||||
node->_digitalInputStates[i-3] = (outArray[i+1] << 8) | outArray[i];
|
||||
}
|
||||
node->resFlag = 1;
|
||||
break;
|
||||
}
|
||||
case EXIORDAN: {
|
||||
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;
|
||||
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) {
|
||||
_serial = &serial;
|
||||
_baud = baud;
|
||||
|
||||
_txPin = txPin;
|
||||
_busNo = busNo;
|
||||
_cycleTime = cycleTime;
|
||||
task->init(serial, baud, txPin);
|
||||
if (_waitA < 3) _waitA = 3;
|
||||
bufferLength=0;
|
||||
inCommandPayload=PAYLOAD_FALSE;
|
||||
// Add device to HAL device chain
|
||||
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
|
||||
// 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) {
|
||||
_currentMicros = currentMicros;
|
||||
if (_busy == true) return;
|
||||
if (_currentTask == NULL) {
|
||||
_currentTask = _taskListStart;
|
||||
|
||||
//if (_currentNode == NULL) {
|
||||
// _currentNode = _nodeListStart;
|
||||
|
||||
//}
|
||||
}
|
||||
|
||||
if (_currentMicros - _cycleStartTime < _cycleTime) return;
|
||||
_cycleStartTime = _currentMicros;
|
||||
//if (_currentNode == NULL) return;
|
||||
task->loop();
|
||||
if (_currentTask != NULL && _currentTask->commandArray[0] != 0) {
|
||||
|
||||
// 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.
|
||||
@ -355,10 +355,22 @@ bool RSprotonode::_configure(VPIN vpin, ConfigTypeEnum configType, int paramCoun
|
||||
int pin = vpin - _firstVpin;
|
||||
|
||||
uint8_t pullup = (uint8_t)params[0];
|
||||
char buff[25];
|
||||
sprintf(buff, "<5|%i %i %i %i %i>", _nodeID, 0, EXIODPUP, pin, pullup);
|
||||
int buff[ARRAY_SIZE];
|
||||
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();
|
||||
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
|
||||
if (resFlag != 1) {
|
||||
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 pin = vpin - _firstVpin;
|
||||
//RSproto *mainrs = RSproto::findBus(_busNo);
|
||||
char buff[25];
|
||||
sprintf(buff, "<6|%i %i %i %i %i %i>", _nodeID, 0, EXIOENAN, pin, _firstVpin);
|
||||
int buff[ARRAY_SIZE];
|
||||
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();
|
||||
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
|
||||
if (resFlag != 1) {
|
||||
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() {
|
||||
char buff[25];
|
||||
sprintf(buff, "<6|%i %i %i %i %i %i>", _nodeID, 0, EXIOINIT, _nPins, (_firstVpin & 0xFF), (_firstVpin >> 8));
|
||||
int buff[ARRAY_SIZE];
|
||||
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();
|
||||
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
|
||||
if (resFlag != 1) {
|
||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINIT"), _nodeID);
|
||||
}
|
||||
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();
|
||||
task->doCommand(buff,_nodeID);
|
||||
bus->_busy = true;
|
||||
bus->sendInstantCommand(buff);
|
||||
bus->_busy = false;
|
||||
while (resFlag == 0 && millis() - startMillis < 1000); // blocking for now
|
||||
if (resFlag != 1) {
|
||||
DIAG(F("EX-IOExpander485 Node:%d ERROR EXIOINITA"), _nodeID);
|
||||
}
|
||||
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();
|
||||
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
|
||||
if (resFlag != 1) {
|
||||
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) {
|
||||
if (_deviceState == DEVSTATE_FAILED) return;
|
||||
int pin = vpin - _firstVpin;
|
||||
char buff[25];
|
||||
sprintf(buff, "<5|%i %i %i %i %i>", _nodeID, 0, EXIOWRD, pin, value);
|
||||
int buff[ARRAY_SIZE];
|
||||
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();
|
||||
task->doCommand(buff,_nodeID);
|
||||
RSproto *bus = RSproto::findBus(0);
|
||||
task->doCommand(bus->taskCounter++, buff);
|
||||
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
||||
if (resFlag != 1) {
|
||||
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) {
|
||||
int pin = vpin - _firstVpin;
|
||||
char buff[25];
|
||||
sprintf(buff, "<7|%i %i %i %i %i %i %i>", _nodeID, 0, EXIOWRAN, pin, value, profile, duration);
|
||||
int buff[ARRAY_SIZE];
|
||||
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();
|
||||
task->doCommand(buff,_nodeID);
|
||||
RSproto *bus = RSproto::findBus(0);
|
||||
task->doCommand(bus->taskCounter++, buff);
|
||||
while (resFlag == 0 && millis() - startMillis < 500); // blocking for now
|
||||
if (resFlag != 1) {
|
||||
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
|
||||
#define COMMAND_BUFFER_SIZE 400
|
||||
#define COMMAND_BUFFER_SIZE 900
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
@ -79,18 +79,26 @@ class RSprotonode;
|
||||
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;
|
||||
byte bufferLength;
|
||||
char buffer[COMMAND_BUFFER_SIZE];
|
||||
unsigned long _cycleTimer = 0ul;
|
||||
|
||||
taskBuffer *next;
|
||||
uint8_t startChar[1] = {0xFD};
|
||||
uint8_t endChar[1] = {0xFE};
|
||||
byte inCommandPayload;
|
||||
|
||||
int commandArray[ARRAY_SIZE];
|
||||
int _commandSize = 0;
|
||||
// EX-IOExpander protocol flags
|
||||
enum {
|
||||
EXIOINIT = 0xE0, // Flag to initialise setup procedure
|
||||
@ -111,19 +119,34 @@ static taskBuffer *first;
|
||||
STARTBYTE = 0xFD,
|
||||
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);
|
||||
void loop2();
|
||||
void parseRx(char * rxbuffer, int rxBufLen, int fieldCnt);
|
||||
void parseOne(int *buf);
|
||||
public:
|
||||
taskBuffer(Stream * myserial);
|
||||
|
||||
|
||||
|
||||
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, int *commandBuffer);
|
||||
~taskBuffer();
|
||||
static void doCommand(char *commandBuffer, int commandSize=0);
|
||||
static void init(HardwareSerial &hwSerial, unsigned long baud, int8_t txPin=-1);
|
||||
static void loop();
|
||||
void doCommand(unsigned long taskID, int *commandBuffer);
|
||||
};
|
||||
|
||||
|
||||
@ -148,7 +171,6 @@ private:
|
||||
RSproto *bus;
|
||||
taskBuffer *task;
|
||||
HardwareSerial* _serial;
|
||||
// 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
|
||||
@ -163,7 +185,7 @@ private:
|
||||
EXIOWRAN = 0xEA, // Flag we're sending an analogue write (PWM)
|
||||
EXIOERR = 0xEF, // Flag we've received an error
|
||||
};
|
||||
|
||||
static const int ARRAY_SIZE = 254;
|
||||
public:
|
||||
static RSprotonode *_nodeList;
|
||||
enum ProfileType : int {
|
||||
@ -253,7 +275,10 @@ private:
|
||||
unsigned long _byteTransmitTime; // time in us for transmission of one byte
|
||||
int _operationCount = 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
|
||||
bool waitReceive = false;
|
||||
int _waitCounter = 0;
|
||||
@ -274,6 +299,7 @@ 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.
|
||||
|
||||
@ -285,6 +311,26 @@ private:
|
||||
}
|
||||
|
||||
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) {
|
||||
new RSproto(busNo, serial, baud, txPin, cycleTime);
|
||||
}
|
||||
@ -298,10 +344,14 @@ public:
|
||||
unsigned long _baud;
|
||||
int taskCnt = 0;
|
||||
uint8_t initBuffer[1] = {0xFE};
|
||||
|
||||
unsigned long taskCounter=0;
|
||||
// Device-specific initialisation
|
||||
void _begin() override {
|
||||
|
||||
_serial->begin(_baud, SERIAL_8N1);
|
||||
if (_txPin >0) {
|
||||
pinMode(_txPin, OUTPUT);
|
||||
digitalWrite(_txPin, LOW);
|
||||
}
|
||||
#if defined(RSproto_STM_OK)
|
||||
pinMode(RSproto_STM_OK, OUTPUT);
|
||||
ArduinoPins::fastWriteDigital(RSproto_STM_OK,LOW);
|
||||
@ -338,6 +388,13 @@ public:
|
||||
}
|
||||
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;
|
||||
@ -357,7 +414,15 @@ public:
|
||||
_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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user