diff --git a/.vscode/arduino.json b/.vscode/arduino.json index e8e6b14..0ca9fe3 100644 --- a/.vscode/arduino.json +++ b/.vscode/arduino.json @@ -1,6 +1,6 @@ { "board": "bsfrance:avr:lora32u4", "sketch": "crossbow/crossbow.ino", - "port": "COM7", + "port": "COM5", "output": "../build" } \ No newline at end of file diff --git a/README.md b/README.md index 6d7e4da..6adae86 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,31 @@ _QuadMeUp Crossbow_ is a DIY project that gives 5km (at least) of RC link for UA # Current state -Development, ready for testing +Works: +* Getting data from OpenTX radio using SBUS protocol +* Transmitting 10 channels to RX modules +* Frequency hopping +* Getting basic telemetry from RX module +* Sending 10 channels using SBUS to flight controller + +Needs implementation: +* Binding +* TX module configuration +* Allowing to use OLED on TX to get basic data +* RX configuration from TX module +* Sending telemetry from TX to OpenTX radio # Protocol | Byte | Description | Notes | | ---- | ---- | ---- | -| 1 | Channel ID | channel used for comunication between TX and RX | -| 2 | Frame type & Length | bits 7-5 defines frame, bits 4-0 current radio channel | -| 3 - 34 | Payload | lenghth defined by frame type | -| payload length + 3 | CRC | using crc8_dvb_s2 method | +| 1 | Frame type & used radio channel | bits 7-5 defines frame, bits 4-0 current radio channel | +| 2 - 33 | Payload | lenghth defined by frame type | +| payload length + 2 | CRC | using crc8_dvb_s2 method | + +## CRC + +CRC is computed using `crc8_dvb_s2` method. Initial CRC value for each frame CRC is equal to CRC of 4 bind bytes (unique for transmitter module). ## Frame types diff --git a/crossbow/config.h b/crossbow/config.h index 9706f06..cfb4482 100644 --- a/crossbow/config.h +++ b/crossbow/config.h @@ -5,16 +5,18 @@ * Hardware type. Available types: * ARDUINO_AVR_FEATHER32U4 * ARDUINO_SAMD_FEATHER_M0 + * + * Leave commented for autodetect */ -#define ARDUINO_AVR_FEATHER32U4 +// #define ARDUINO_AVR_FEATHER32U4 /* * TX or RX mode for hardware. Available types: * DEVICE_MODE_TX * DEVICE_MODE_RX */ -// #define DEVICE_MODE_TX -#define DEVICE_MODE_RX +#define DEVICE_MODE_TX +// #define DEVICE_MODE_RX // #define FEATURE_TX_OLED // #define FORCE_TX_WITHOUT_INPUT diff --git a/crossbow/crossbow.ino b/crossbow/crossbow.ino index 6bc9d68..faaacd0 100644 --- a/crossbow/crossbow.ino +++ b/crossbow/crossbow.ino @@ -274,6 +274,14 @@ void setup(void) qsp.debugConfig |= DEBUG_FLAG_LED; #endif + /* + * Setup salt bind key + */ + qsp.bindKey[0] = 0x12; + qsp.bindKey[1] = 0x0a; + qsp.bindKey[2] = 0x36; + qsp.bindKey[3] = 0xa7; + } uint8_t currentSequenceIndex = 0; diff --git a/crossbow/qsp.cpp b/crossbow/qsp.cpp index 5106778..90a8186 100644 --- a/crossbow/qsp.cpp +++ b/crossbow/qsp.cpp @@ -151,6 +151,16 @@ void qspClearPayload(QspConfiguration_t *qsp) qsp->payloadLength = 0; } +/** + * Init CRC with salt based on 4 byte bind key + */ +void qspInitCrc(QspConfiguration_t *qsp) { + qsp->crc = 0; + for (uint8_t i = 0; i < 4; i++) { + qspComputeCrc(qsp, qsp->bindKey[i]); + } +} + void qspDecodeIncomingFrame( QspConfiguration_t *qsp, uint8_t incomingByte, @@ -165,24 +175,11 @@ void qspDecodeIncomingFrame( if (qsp->protocolState == QSP_STATE_IDLE) { - // Check if incomming channel ID is the same as receiver - if (incomingByte == CHANNEL_ID) - { - qsp->frameDecodingStartedAt = millis(); - qsp->protocolState = QSP_STATE_CHANNEL_RECEIVED; - qsp->crc = 0; - qspComputeCrc(qsp, incomingByte); - qspClearPayload(qsp); + qspInitCrc(qsp); + qspClearPayload(qsp); + receivedPayload = 0; + qsp->frameDecodingStartedAt = millis(); - receivedPayload = 0; - } - else - { - qsp->protocolState = QSP_STATE_IDLE; - } - } - else if (qsp->protocolState == QSP_STATE_CHANNEL_RECEIVED) - { //Frame ID and payload length qspComputeCrc(qsp, incomingByte); @@ -228,11 +225,8 @@ void qspDecodeIncomingFrame( * Encode frame is corrent format and write to hardware */ void qspEncodeFrame(QspConfiguration_t *qsp, volatile RadioState_t *radioState, uint8_t buffer[], uint8_t *size) { - //Zero CRC - qsp->crc = 0; - - qspComputeCrc(qsp, CHANNEL_ID); - buffer[0] = CHANNEL_ID; + //Salt CRC with bind key + qspInitCrc(qsp); //Write frame type and length // We are no longer sending payload length, so 4 bits are now free for other usages @@ -240,16 +234,16 @@ void qspEncodeFrame(QspConfiguration_t *qsp, volatile RadioState_t *radioState, uint8_t data = radioState->channel; data |= (qsp->frameToSend << 4) & 0xf0; qspComputeCrc(qsp, data); - buffer[1] = data; + buffer[0] = data; for (uint8_t i = 0; i < qsp->payloadLength; i++) { qspComputeCrc(qsp, qsp->payload[i]); - buffer[i + 2] = qsp->payload[i]; + buffer[i + 1] = qsp->payload[i]; } - buffer[qsp->payloadLength + 2] = qsp->crc; - *size = qsp->payloadLength + 3; //Total length of QSP frame + buffer[qsp->payloadLength + 1] = qsp->crc; + *size = qsp->payloadLength + 2; //Total length of QSP frame } void encodePingPayload(QspConfiguration_t *qsp, uint32_t currentMicros) { diff --git a/crossbow/variables.h b/crossbow/variables.h index b1c25bc..f0dcb7e 100644 --- a/crossbow/variables.h +++ b/crossbow/variables.h @@ -48,7 +48,6 @@ static const uint8_t qspFrameLengths[QSP_FRAME_COUNT] = { enum dataStates { QSP_STATE_IDLE, - QSP_STATE_CHANNEL_RECEIVED, QSP_STATE_FRAME_TYPE_RECEIVED, QSP_STATE_PAYLOAD_RECEIVED, QSP_STATE_CRC_RECEIVED @@ -130,6 +129,7 @@ struct RxDeviceState_t { }; struct QspConfiguration_t { + uint8_t bindKey[4] = {0, 0, 0, 0}; uint8_t protocolState = QSP_STATE_IDLE; uint8_t crc = 0; uint8_t payload[QSP_PAYLOAD_LENGTH] = {0};