diff --git a/README.md b/README.md index b2f59f2..1f6d2c5 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ Development, not yet functional | 0010 | 0x2 | Request receiver configuration | TX -> RX | | 0011 | 0x3 | Receiver configuration | RX -> TX | | 0100 | 0x4 | Set receiver configuration | TX -> RX | -| 0101 | 0x5 | PING frame | TX -> RX | -| 0110 | 0x6 | PONG frame | RX -> TX | +| 0101 | 0x5 | PING frame, uses 9 byte payload | TX -> RX | +| 0110 | 0x6 | PONG frame, the same payload as PING | RX -> TX | ### `RC_DATA` frame format diff --git a/crossbow.ino b/crossbow.ino index 162f232..8653739 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -1,11 +1,11 @@ #define LORA_HARDWARE_SPI -#define DEVICE_MODE_TX -// #define DEVICE_MODE_RX +// #define DEVICE_MODE_TX +#define DEVICE_MODE_RX #define FEATURE_TX_OLED -#define DEBUG_SERIAL +// #define DEBUG_SERIAL // #define DEBUG_PING_PONG // #define DEBUG_LED // #define WAIT_FOR_SERIAL @@ -63,7 +63,7 @@ uint8_t getRadioRssi(void) return map(constrain(LoRa.packetRssi() * -1, 0, 164), 0, 164, 255, 0); } -float getRadioSnr(void) +uint8_t getRadioSnr(void) { return (uint8_t) constrain(LoRa.packetSnr(), 0, 255); } @@ -209,7 +209,7 @@ int8_t rxSendSequence[16] = { -1, -1, -1, - -1, + QSP_FRAME_RX_HEALTH, -1, -1, -1, @@ -217,7 +217,7 @@ int8_t rxSendSequence[16] = { -1, -1, -1, - -1, + QSP_FRAME_RX_HEALTH, -1, -1, -1 @@ -236,9 +236,15 @@ void updateRxDeviceState(RxDeviceState_t *rxDeviceState) { rxDeviceState->snr = getRadioSnr(); } -int8_t getFrameToTransmit() { - int8_t retVal = rxSendSequence[currentSequenceIndex]; +int8_t getFrameToTransmit(QspConfiguration_t *qsp) { + + if (qsp->forcePongFrame) { + qsp->forcePongFrame = false; + return QSP_FRAME_PONG; + } + int8_t retVal = rxSendSequence[currentSequenceIndex]; + currentSequenceIndex++; if (currentSequenceIndex >= TRANSMIT_SEQUENCE_COUNT) { currentSequenceIndex = 0; @@ -250,7 +256,7 @@ int8_t getFrameToTransmit() { #endif #ifdef DEVICE_MODE_TX -int8_t getFrameToTransmit() { +int8_t getFrameToTransmit(QspConfiguration_t *qsp) { int8_t retVal = txSendSequence[currentSequenceIndex]; currentSequenceIndex++; @@ -284,7 +290,7 @@ void loop(void) qsp.protocolState == QSP_STATE_IDLE ) { - int8_t frameToSend = getFrameToTransmit(); + int8_t frameToSend = getFrameToTransmit(&qsp); if (frameToSend == QSP_FRAME_RC_DATA && !ppmReader.isReceiving()) { frameToSend = -1; @@ -313,17 +319,70 @@ void loop(void) #endif - // if ( - // qsp.forcePongFrame && - // !transmitPayload && - // qsp.protocolState == QSP_STATE_IDLE - // ) - // { - // qsp.forcePongFrame = false; - // qsp.frameToSend = QSP_FRAME_PONG; - // transmitPayload = true; - // } +#ifdef DEVICE_MODE_RX + /* + * This routine updates RX device state and updates one of radio channels with RSSI value + */ + if (abs(currentMillis - lastRxStateTaskTime) > RX_TASK_HEALTH) { + lastRxStateTaskTime = currentMillis; + updateRxDeviceState(&rxDeviceState); + ppm[RSSI_CHANNEL - 1] = map(rxDeviceState.rssi, 0, 255, 1000, 2000); + + if (qsp.deviceState == DEVICE_STATE_FAILSAFE) { + digitalWrite(LED_BUILTIN, HIGH); + } else { + digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + } + } + + /* + * Main routine to answer to TX module + */ + if (qsp.transmitWindowOpen && qsp.protocolState == QSP_STATE_IDLE) { + + qsp.transmitWindowOpen = false; + + int8_t frameToSend = getFrameToTransmit(&qsp); + + if (frameToSend > -1) { + + qsp.frameToSend = frameToSend; + + if (frameToSend != QSP_FRAME_PONG) { + qspClearPayload(&qsp); + } + + switch (qsp.frameToSend) { + case QSP_FRAME_PONG: + /* + * Pong frame just responses with received payload + */ + break; + + case QSP_FRAME_RX_HEALTH: + encodeRxHealthPayload(&qsp, &rxDeviceState); + break; + } + + transmitPayload = true; + } + + } + + if (currentMillis > sbusTime) { + sbusPreparePacket(sbusPacket, ppm, false, (qsp.deviceState == DEVICE_STATE_FAILSAFE)); + Serial1.write(sbusPacket, SBUS_PACKET_LENGTH); + sbusTime = currentMillis + SBUS_UPDATE_RATE; + } + + if (abs(currentMillis - qsp.lastFrameReceivedAt[QSP_FRAME_RC_DATA]) > RX_FAILSAFE_DELAY) { + qsp.deviceState = DEVICE_STATE_FAILSAFE; + } else { + qsp.deviceState = DEVICE_STATE_OK; + } + +#endif #ifdef DEVICE_MODE_TX @@ -363,48 +422,6 @@ void loop(void) #endif -// #ifdef DEVICE_MODE_RX - -// if (currentMillis > sbusTime) { -// sbusPreparePacket(sbusPacket, ppm, false, (qsp.deviceState == DEVICE_STATE_FAILSAFE)); -// Serial1.write(sbusPacket, SBUS_PACKET_LENGTH); - -// sbusTime = currentMillis + SBUS_UPDATE_RATE; -// } - -// /* -// * This routine updates RX device state and updates one of radio channels with RSSI value -// */ -// if (currentMillis - lastRxStateTaskTime > RX_TASK_HEALTH) { -// lastRxStateTaskTime = currentMillis; -// updateRxDeviceState(&rxDeviceState); -// ppm[RSSI_CHANNEL - 1] = map(rxDeviceState.rssi, 0, 255, 1000, 2000); - -// if (qsp.deviceState == DEVICE_STATE_FAILSAFE) { -// digitalWrite(LED_BUILTIN, HIGH); -// } else { -// digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); -// } - -// } - -// /* -// * RX_HEALTH QSP frame -// */ -// if ( -// currentMillis - qsp.lastFrameTransmitedAt[QSP_FRAME_RX_HEALTH] > RX_RX_HEALTH_FRAME_RATE && -// !transmitPayload && -// qsp.protocolState == QSP_STATE_IDLE -// ) -// { -// qspClearPayload(&qsp); -// encodeRxHealthPayload(&qsp, &rxDeviceState); -// qsp.frameToSend = QSP_FRAME_RX_HEALTH; - -// transmitPayload = true; -// } -// #endif - if (qsp.canTransmit && transmitPayload) { radioPacketStart(); @@ -413,16 +430,6 @@ void loop(void) transmitPayload = false; } - /* - * Here we do state handling and similar operations - */ -#ifdef DEVICE_MODE_RX - if (abs(currentMillis - qsp.lastFrameReceivedAt[QSP_FRAME_RC_DATA]) > RX_FAILSAFE_DELAY) { - qsp.deviceState = DEVICE_STATE_FAILSAFE; - } else { - qsp.deviceState = DEVICE_STATE_OK; - } -#endif } #ifdef LORA_HARDWARE_SPI diff --git a/qsp.cpp b/qsp.cpp index 07a0978..98d961c 100644 --- a/qsp.cpp +++ b/qsp.cpp @@ -204,19 +204,6 @@ void qspDecodeIncomingFrame(QspConfiguration_t *qsp, uint8_t incomingByte, int p qsp->lastFrameReceivedAt[frameId] = millis(); } - if (qsp->debugConfig & DEBUG_FLAG_SERIAL) { - Serial.print("Frame "); - Serial.print(frameId); - Serial.println(" received"); - } - - if (qsp->debugConfig & DEBUG_FLAG_LED) { - digitalWrite(LED_BUILTIN, HIGH); - delay(10); - digitalWrite(LED_BUILTIN, LOW); - delay(100); - } - switch (frameId) { case QSP_FRAME_RC_DATA: qspDecodeRcDataFrame(qsp, ppm); @@ -224,12 +211,6 @@ void qspDecodeIncomingFrame(QspConfiguration_t *qsp, uint8_t incomingByte, int p case QSP_FRAME_RX_HEALTH: decodeRxHealthPayload(qsp, rxDeviceState); - if (qsp->debugConfig & DEBUG_FLAG_SERIAL) { - Serial.print("RX RSSI: "); - Serial.println(rxDeviceState->rssi); - Serial.print("RX SNR: "); - Serial.println(rxDeviceState->snr); - } break; case QSP_FRAME_PING: @@ -251,6 +232,8 @@ void qspDecodeIncomingFrame(QspConfiguration_t *qsp, uint8_t incomingByte, int p //TODO do something in this case break; } + + qsp->transmitWindowOpen = true; } else { diff --git a/variables.h b/variables.h index d7e80d2..126194d 100644 --- a/variables.h +++ b/variables.h @@ -11,12 +11,9 @@ #define RX_TASK_HEALTH 200 //5Hz should be enough #define RSSI_CHANNEL 11 -#define RX_RX_HEALTH_FRAME_RATE 503 #define TX_TRANSMIT_SLOT_RATE 57 //ms #define RX_FAILSAFE_DELAY (TX_TRANSMIT_SLOT_RATE * 8) -#define TX_PING_RATE 2007 - #define CHANNEL_ID 0x01 #define QSP_PREAMBLE 0x51 #define QSP_PAYLOAD_LENGTH 32 @@ -82,6 +79,7 @@ struct QspConfiguration_t { uint8_t debugConfig = 0; uint32_t frameDecodingStartedAt = 0; uint32_t lastTxSlotTimestamp = 0; + bool transmitWindowOpen = false; }; struct RxDeviceState_t {