diff --git a/arduino/protocol/lib/commsControl/commsConstants.h b/arduino/protocol/lib/commsControl/commsConstants.h index dc430bafeceb3c277ba91190e29c0658323291ad..03b7a83eea5b28bff11b75141918d2624bbe79b7 100644 --- a/arduino/protocol/lib/commsControl/commsConstants.h +++ b/arduino/protocol/lib/commsControl/commsConstants.h @@ -7,7 +7,9 @@ #define CONST_TIMEOUT_DATA 5000 #define CONST_TIMEOUT_CMD 50 -#define CONST_MAX_SIZE_QUEUE 2 + +#define CONST_MAX_SIZE_RB_RECEIVING 10 +#define CONST_MAX_SIZE_RB_SENDING 5 #define CONST_MAX_SIZE_PACKET 64 #define CONST_MAX_SIZE_BUFFER 128 #define CONST_MIN_SIZE_PACKET 7 @@ -27,24 +29,112 @@ #define PACKET_ALARM 0xC0 #define PACKET_CMD 0x80 #define PACKET_DATA 0x40 -#define PACKET_SET 0x20 //set vs get +#define PACKET_SET 0x20 //set vs get ? // TODO: make sensible #define PRESSURE_PEEP_LOW 0x01 #define PRESSURE_PEEP_HIGH 0x02 // struct for all data sent -// TODO: the same for all settings? struct dataFormat { - uint16_t count; - uint16_t pressure; + uint8_t version; + uint8_t size = 3; + uint8_t count = 0; +}; + +struct cmdFormat { + uint8_t version; + uint8_t size = 2; +}; + +struct alarmFormat { + uint8_t version; + uint8_t size = 2; }; // enum of all transfer types -enum dataType { - dataAlarm, - dataNormal, - dataCommand +enum payloadType { + payloadData, + payloadCmd, + payloadAlarm, + payloadUnset +}; + +// payload consists of type and information +// type is set as address in the protocol +// information is set as information in the protocol +class payload { +public: + payload(payloadType type = payloadType::payloadUnset) {type_ = type; data_ = nullptr; cmd_ = nullptr; alarm_ = nullptr; } + ~payload() {unsetData(); unsetAlarm(); unsetCmd();} + + void setType(payloadType type) { type_ = type; } + payloadType getType() {return type_; } + + // requires argument as new struct + void setData (dataFormat *data) { unsetAll(); data_ = new dataFormat; memcpy( data_, data, data->size); } + void setCmd (cmdFormat *cmd) { unsetAll(); cmd_ = new cmdFormat; memcpy( cmd_, cmd, cmd->size); } + void setAlarm(alarmFormat *alarm) { unsetAll(); alarm_ = new alarmFormat; memcpy(alarm_, alarm, alarm->size); } + + dataFormat *getData () {return data_; } + cmdFormat *getCmd () {return cmd_; } + alarmFormat *getAlarm() {return alarm_; } + + void unsetAll() { unsetData(); unsetAlarm(); unsetCmd(); } + void unsetData() { if ( data_ != nullptr) { delete data_; data_ = nullptr; } } + void unsetCmd() { if ( cmd_ != nullptr) { delete cmd_; cmd_ = nullptr; } } + void unsetAlarm() { if (alarm_ != nullptr) { delete alarm_; alarm_ = nullptr; } } + + void setPayload(payloadType type, void* dt) { + setType(type); + switch (type) { + case payloadType::payloadData: + setData(reinterpret_cast<dataFormat*>(dt)); + break; + case payloadType::payloadCmd: + setCmd(reinterpret_cast<cmdFormat*>(dt)); + break; + case payloadType::payloadAlarm: + setAlarm(reinterpret_cast<alarmFormat*>(dt)); + break; + default: + break; + } + } + + // returns void pointer, in case you know what to do with data + void *getInformation() { + switch (type_) { + case payloadType::payloadData: + return reinterpret_cast<void*>(getData()); + case payloadType::payloadCmd: + return reinterpret_cast<void*>(getCmd()); + case payloadType::payloadAlarm: + return reinterpret_cast<void*>(getAlarm()); + default: + return nullptr; + } + } + + uint8_t getInformationSize() { + switch (type_) { + case payloadType::payloadData: + return getData()->size; + case payloadType::payloadCmd: + return getCmd()->size; + case payloadType::payloadAlarm: + return getAlarm()->size; + default: + return 0; + } + } + +private: + payloadType type_; + + dataFormat *data_; + cmdFormat *cmd_; + alarmFormat *alarm_; }; #endif diff --git a/arduino/protocol/lib/commsControl/commsControl.cpp b/arduino/protocol/lib/commsControl/commsControl.cpp index 6600534b5224d04223643be61a50b7a3f65fe1b0..86c7570df6c608075484654af5d8c09a14f6fc95 100644 --- a/arduino/protocol/lib/commsControl/commsControl.cpp +++ b/arduino/protocol/lib/commsControl/commsControl.cpp @@ -15,9 +15,11 @@ commsControl::commsControl(uint32_t baudrate) { memset(commsReceived_, 0, sizeof(commsReceived_)); memset(commsSend_ , 0, sizeof(commsSend_ )); - queueAlarm_ = new RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE>(); - queueData_ = new RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE>(); - queueCmd_ = new RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE>(); + queueAlarm_ = new RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING>(); + queueData_ = new RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING>(); + queueCmd_ = new RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING>(); + + queueReceived_ = new RingBuf<payload *, CONST_MAX_SIZE_RB_RECEIVING>(); commsTmp_ = commsFormat(CONST_MAX_SIZE_PACKET - CONST_MIN_SIZE_PACKET ); @@ -81,36 +83,39 @@ void commsControl::receiver() { // if managed to decode and compare CRC if (decoder(lastTrans_, startTransIndex_, lastTransIndex_)) { - // FIXME really need to move commsReceived_ to be commsFormat type - lot of control, address operations - // to decide ACK/NACK/other - uint8_t control[2]; - memcpy(control, commsReceived_ + 2, 2); - sequenceReceive_ = (control[0] >> 1) & 0x7F; + sequenceReceive_ = (*(commsTmp_.getControl()) >> 1 ) & 0x7F; + // to decide ACK/NACK/other; for other gain sequenceReceive + uint8_t control = *(commsTmp_.getControl() + 1); // to decide what kind of packets received - uint8_t address = commsReceived_[1]; - RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *tmpQueue = getQueue(address); - if (tmpQueue != nullptr) { - // switch on received data to know what to do - received ACK/NACK or other - switch(control[1] & COMMS_CONTROL_TYPES) { - case COMMS_CONTROL_NACK: - // received NACK - // TODO: modify timeout for next sent frame? - resendPacket(tmpQueue); - break; - case COMMS_CONTROL_ACK: - // received ACK - finishPacket(tmpQueue); - break; - default: - // received DATA - receivePacket(tmpQueue); - - commsAck_->setAddress(&address); - commsAck_->setSequenceReceive(((control[1] >> 1) & 0x7F) + 1); + payloadType type = getInfoType(commsTmp_.getAddress()); + + // switch on received data to know what to do - received ACK/NACK or other + switch(control & COMMS_CONTROL_TYPES) { + case COMMS_CONTROL_NACK: + // received NACK + // TODO: modify timeout for next sent frame? + // resendPacket(&address); + break; + case COMMS_CONTROL_ACK: + // received ACK + finishPacket(&type); + break; + default: + uint8_t tmpSequenceReceive = (control >> 1 ) & 0x7F; + tmpSequenceReceive += 1; + // received DATA + if (receivePacket(&type)) { + commsAck_->setAddress(commsTmp_.getAddress()); + commsAck_->setSequenceReceive(tmpSequenceReceive); sendPacket(commsAck_); - break; - } + } else { + commsNck_->setAddress(commsTmp_.getAddress()); + commsNck_->setSequenceReceive(tmpSequenceReceive); + sendPacket(commsNck_); + } + + break; } } @@ -130,34 +135,50 @@ void commsControl::receiver() { } } +bool commsControl::writePayload(payload *pl) { + commsFormat* tmpComms; -// adding new values into queue -// WIP -void commsControl::registerData(dataType type, dataFormat *values) { - commsFormat *newValue = commsFormat::generateDATA(); - - // switch on different received data types - switch(type) { - case dataAlarm: + // switch on different received payload types + // TODO simplify the static functions + switch(pl->getType()) { + case payloadAlarm: + tmpComms = commsFormat::generateALARM(pl); break; - case dataNormal: - newValue->setInformation(values); + case payloadData: + tmpComms = commsFormat::generateDATA(pl); break; - case dataCommand: + case payloadCmd: + tmpComms = commsFormat::generateCMD(pl); break; default: - break; + return false; } // add new entry to the queue if (queueData_->isFull()) { - commsFormat *tmpComms; - queueData_->pop(tmpComms); - delete tmpComms; + commsFormat *tmpCommsRm; + if (queueData_->pop(tmpCommsRm)) { + delete tmpCommsRm; + } } - queueData_->push(newValue); + + if (queueData_->push(tmpComms) ) { + return true; + } + return false; } +bool commsControl::readPayload( payload* pl) { + if ( !queueReceived_->isEmpty()) { + payload *tmpPl; + if (queueReceived_->pop(tmpPl)) { + memcpy(pl, tmpPl, sizeof(payload)); + delete tmpPl; + return true; + } + } + return false; +} // general encoder of any transmission bool commsControl::encoder(uint8_t *data, uint8_t dataSize) { @@ -209,7 +230,7 @@ bool commsControl::decoder(uint8_t* data, uint8_t dataStart, uint8_t dataStop) { } // sending anything of commsDATA format -void commsControl::sendQueue(RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue) { +void commsControl::sendQueue(RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queue) { // if have data to send if (!queue->isEmpty()) { // reset sending counter @@ -232,39 +253,86 @@ void commsControl::sendPacket(commsFormat *packet) { // resending the packet, can lower the timeout since either NACK or wrong FCS already checked //WIP -void commsControl::resendPacket(RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue) { +void commsControl::resendPacket(RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queue) { ; } // receiving anything of commsFormat -// WIP -void commsControl::receivePacket(RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue) { - ; +// TODO remove address and use commsTmp only +bool commsControl::receivePacket(payloadType *type) { + payload *tmpPl = new payload(*type); + + void *tmpInformation = nullptr; + switch (*type) { + case payloadType::payloadData: + tmpInformation = reinterpret_cast<void*>(new dataFormat); + break; + case payloadType::payloadCmd: + tmpInformation = reinterpret_cast<void*>(new cmdFormat); + break; + case payloadType::payloadAlarm: + tmpInformation = reinterpret_cast<void*>(new alarmFormat); + break; + default: + break; + } + + if (tmpInformation == nullptr) { + return false; + } + memcpy(tmpInformation, commsTmp_.getInformation(), commsTmp_.getInfoSize()); + tmpPl->setPayload(*type, tmpInformation); + + // remove first entry if RB is full + if (queueReceived_->isFull()) { + payload *tmpDataRm = nullptr; + if (queueReceived_->pop(tmpDataRm)) { + delete tmpDataRm; + } + } + + return queueReceived_->push(tmpPl); } // if FCS is ok, remove from queue -void commsControl::finishPacket(RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue) { - if (!queue->isEmpty()) { +void commsControl::finishPacket(payloadType *type) { + RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *tmpQueue = getQueue(type); + + if (tmpQueue != nullptr && !tmpQueue->isEmpty()) { // get the sequence send from first entry in the queue, add one as that should be return // 0x7F to deal with possible overflows (0 should follow after 127) - if (((queue->operator [](0)->getSequenceSend() + 1) & 0x7F) == sequenceReceive_) { + if (((tmpQueue->operator [](0)->getSequenceSend() + 1) & 0x7F) == sequenceReceive_) { sequenceSend_ = (sequenceSend_ + 1) % 128; commsFormat * tmpComms; - queue->pop(tmpComms); - delete tmpComms; + if (tmpQueue->pop(tmpComms)) { + delete tmpComms; + } } } } -// get link to queue according to packet format -RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *commsControl::getQueue(uint8_t address) { - switch (address & PACKET_TYPE) { +payloadType commsControl::getInfoType(uint8_t *address) { + switch (*address & PACKET_TYPE) { case PACKET_ALARM: - return queueAlarm_; + return payloadType::payloadAlarm; case PACKET_CMD: - return queueCmd_; + return payloadType::payloadCmd; case PACKET_DATA: + return payloadType::payloadData; + default: + return payloadType::payloadUnset; + } +} + +// get link to queue according to packet format +RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *commsControl::getQueue(payloadType *type) { + switch (*type) { + case payloadType::payloadAlarm: + return queueAlarm_; + case payloadType::payloadCmd: + return queueCmd_; + case payloadType::payloadData: return queueData_; default: return nullptr; diff --git a/arduino/protocol/lib/commsControl/commsControl.h b/arduino/protocol/lib/commsControl/commsControl.h index 4b88b2213e24950f636a96ed72d8434653e092f9..e04178845cd027df1d57c7e8a7cefb56e38dcfda 100644 --- a/arduino/protocol/lib/commsControl/commsControl.h +++ b/arduino/protocol/lib/commsControl/commsControl.h @@ -19,22 +19,23 @@ public: void beginSerial(); - // TODO: passed as struct, or simply array of size and memcpy? should be dataType or just define? - void registerData(dataType type, dataFormat* values); + bool writePayload(payload *pl); + bool readPayload (payload *pl); void sender(); void receiver(); private: - RingBuf<commsFormat *,CONST_MAX_SIZE_QUEUE> *getQueue(uint8_t address); + RingBuf<commsFormat *,CONST_MAX_SIZE_RB_SENDING> *getQueue(payloadType *type); + payloadType getInfoType(uint8_t *address); - void sendQueue (RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue); - void resendPacket (RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue); - void receivePacket(RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue); - void finishPacket (RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queue); + void sendQueue (RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queue); + void resendPacket (RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queue); + bool receivePacket(payloadType *type); + void finishPacket (payloadType *type); - bool encoder(uint8_t* data, uint8_t dataSize); - bool decoder(uint8_t* data, uint8_t dataStart, uint8_t dataStop); + bool encoder(uint8_t* payload, uint8_t dataSize); + bool decoder(uint8_t* payload, uint8_t dataStart, uint8_t dataStop); void sendPacket(commsFormat* packet); @@ -45,9 +46,11 @@ private: commsFormat* commsAck_; commsFormat* commsNck_; - RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queueAlarm_; - RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queueData_; - RingBuf<commsFormat *, CONST_MAX_SIZE_QUEUE> *queueCmd_; + RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queueAlarm_; + RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queueData_; + RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queueCmd_; + + RingBuf<payload *, CONST_MAX_SIZE_RB_RECEIVING> *queueReceived_; commsFormat commsTmp_; diff --git a/arduino/protocol/lib/commsControl/commsFormat.cpp b/arduino/protocol/lib/commsControl/commsFormat.cpp index 9b082e71403c721f5ba507d563bdaa29a8220c6b..affb4200f9bbfb8aba9709c026e5b45bdd366ffa 100644 --- a/arduino/protocol/lib/commsControl/commsFormat.cpp +++ b/arduino/protocol/lib/commsControl/commsFormat.cpp @@ -79,18 +79,34 @@ void commsFormat::generateCrc(bool assign) { } // assign received information to packet -// TODO: set according to TBD dataFormat -void commsFormat::setInformation(dataFormat* values) { - // assign values to - memcpy(getInformation(), &values->count, 2); - - generateCrc(); +void commsFormat::setInformation(payload *pl) { + assignBytes(getInformation(), reinterpret_cast<uint8_t*>(pl->getInformation()), getInfoSize()); } void commsFormat::copyData(uint8_t* data, uint8_t dataSize) { - infoSize_ = dataSize - CONST_MIN_SIZE_PACKET; packetSize_ = dataSize; - memset(data_, 0, sizeof(data_)); + infoSize_ = dataSize - CONST_MIN_SIZE_PACKET; + memset(getData(), 0, sizeof(data_)); assignBytes(getData(), data, dataSize); } + + +// STATIC METHODS +// TODO rewrite in a slightly better way using the enum +commsFormat* commsFormat::generateALARM(payload *pl) { + commsFormat *tmpComms = new commsFormat(pl->getInformationSize(), PACKET_ALARM); + tmpComms->setInformation(pl); + return tmpComms; +} +commsFormat* commsFormat::generateCMD (payload *pl) { + commsFormat *tmpComms = new commsFormat(pl->getInformationSize(), PACKET_CMD ); + tmpComms->setInformation(pl); + return tmpComms; +} +commsFormat* commsFormat::generateDATA (payload *pl) { + commsFormat *tmpComms = new commsFormat(pl->getInformationSize(), PACKET_DATA ); + tmpComms->setInformation(pl); + return tmpComms; +} + diff --git a/arduino/protocol/lib/commsControl/commsFormat.h b/arduino/protocol/lib/commsControl/commsFormat.h index 301fedd7e111ef41b4bfc148aa1b93bb88331091..ddfc6e3a73fd50cde0b073cf1874f46d82234e84 100644 --- a/arduino/protocol/lib/commsControl/commsFormat.h +++ b/arduino/protocol/lib/commsControl/commsFormat.h @@ -20,7 +20,7 @@ public: void setAddress(uint8_t* address) {assignBytes(getAddress(), address, 1); } void setControl(uint8_t* control) {assignBytes(getControl(), control, 2); } - void setInformation(dataFormat* values); + void setInformation(payload *pl); void assignBytes(uint8_t* target, uint8_t* source, uint8_t size, bool calcCrc = true); @@ -35,6 +35,7 @@ public: uint8_t* getFcs() {return data_ + 4 + infoSize_;} // checksum uint8_t* getStop() {return data_ + 4 + infoSize_ + 2;} // ending flag of the chain + uint8_t getInfoSize() { return infoSize_; } void setSequenceSend (uint8_t counter); void setSequenceReceive(uint8_t counter); @@ -42,14 +43,14 @@ public: uint8_t getSequenceSend (); uint8_t getSequenceReceive(); - void copyData(uint8_t* data, uint8_t dataSize); + void copyData(uint8_t* payload, uint8_t dataSize); static commsFormat* generateACK() { return new commsFormat(0, 0, COMMS_CONTROL_ACK << 8); } static commsFormat* generateNACK() { return new commsFormat(0, 0, COMMS_CONTROL_NACK << 8); } - static commsFormat* generateALARM() { return new commsFormat(4, PACKET_ALARM); } - static commsFormat* generateCMD() { return new commsFormat(8, PACKET_CMD ); } - static commsFormat* generateDATA() { return new commsFormat(8, PACKET_DATA ); } + static commsFormat* generateALARM(payload *pl); + static commsFormat* generateCMD (payload *pl); + static commsFormat* generateDATA (payload *pl); private: uint8_t data_[CONST_MAX_SIZE_PACKET]; diff --git a/arduino/protocol/platformio.ini b/arduino/protocol/platformio.ini index 7cd7932e33d3e3ffb47d156251f55babfc9ff26b..46ff784048a7388b5f9d13e53b04d75b8f1d51de 100644 --- a/arduino/protocol/platformio.ini +++ b/arduino/protocol/platformio.ini @@ -44,10 +44,10 @@ platform = atmelavr framework = arduino board = yun -[env:mkrwifi1010] -platform = atmelsam -framework = arduino -board = mkrwifi1010 +;[env:mkrwifi1010] +;platform = atmelsam +;framework = arduino +;board = mkrwifi1010 [env:nodemcu-32s] platform = espressif32 diff --git a/arduino/protocol/src/protocol.cpp b/arduino/protocol/src/protocol.cpp index 072548e2fc4995dc57c55471ca0ba5d42b3eeb99..da9d4dc624a0c80d28a69da540df2ff51b9297b3 100644 --- a/arduino/protocol/src/protocol.cpp +++ b/arduino/protocol/src/protocol.cpp @@ -7,8 +7,10 @@ #define BTN 8 -dataFormat data; -commsControl comms; +payload plReceive_; +payload plSend_; +commsControl comms_; +dataFormat data_; int currentState = 0; int previousState = 0; @@ -18,6 +20,7 @@ bool blue = false; bool green = false; bool red = false; + // dirty function to switch one of the LEDs void switchLED(int led) { int state = HIGH; @@ -43,6 +46,8 @@ void switchLED(int led) { void setup() { + plSend_.setType(payloadType::payloadData); + // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BLUE, OUTPUT); pinMode(LED_GREEN, OUTPUT); @@ -51,8 +56,7 @@ void setup() { pinMode(BTN, INPUT); // initialize comms connection - comms.beginSerial(); - data.count = 0; + comms_.beginSerial(); } void loop() { @@ -64,15 +68,25 @@ void loop() { if (currentState != HIGH) { switchLED(LED_BLUE); // counter increase on button press - data.count += 62; + data_.count += 1; + plSend_.setData(&data_); // register new data in comms - comms.registerData(dataNormal, &data); + comms_.writePayload(&plSend_); } previousState = currentState; } // per cycle sender - comms.sender(); + comms_.sender(); // per cycle receiver - comms.receiver(); + comms_.receiver(); + + // per cycle data checker - the received entry is automatically removed from the buffer + if (comms_.readPayload(&plReceive_)) { + if (plReceive_.getType() == payloadType::payloadData) { + switchLED(plReceive_.getData()->count); + plReceive_.setType(payloadType::payloadUnset); + } + } + }