diff --git a/Multiprotocol/FrSkyX_cc2500.ino b/Multiprotocol/FrSkyX_cc2500.ino index 84594b4..52b3b46 100644 --- a/Multiprotocol/FrSkyX_cc2500.ino +++ b/Multiprotocol/FrSkyX_cc2500.ino @@ -21,8 +21,11 @@ #include "iface_cc2500.h" uint8_t chanskip; -uint8_t seq_last_sent; -uint8_t seq_last_rcvd; +//uint8_t seq_last_sent; +//uint8_t seq_last_rcvd; + +uint8_t FrX_send_seq ; +uint8_t FrX_receive_seq ; static void __attribute__((unused)) set_start(uint8_t ch ) { @@ -151,13 +154,7 @@ static void __attribute__((unused)) frskyX_data_frame() packet[9+i+2]=chan_1>>4; } - packet[21] = seq_last_sent << 4 | seq_last_rcvd;//8 at start - if (seq_last_sent < 0x08 && seq_last_rcvd < 8) - seq_last_sent = (seq_last_sent + 1) % 4; - else if (seq_last_rcvd == 0x00) - seq_last_sent = 1; - else - seq_last_rcvd = 8; + packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms lpass = 0 ; @@ -210,7 +207,7 @@ uint16_t ReadFrSkyX() CC2500_Strobe(CC2500_SIDLE); CC2500_WriteData(packet, packet[0]+1); // - frskyX_data_frame(); +// frskyX_data_frame(); state++; return 5500; case FRSKY_DATA2: @@ -221,7 +218,7 @@ uint16_t ReadFrSkyX() case FRSKY_DATA3: CC2500_Strobe(CC2500_SRX); state++; - return 3000; + return 2800; case FRSKY_DATA4: len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (len && (len<=(0x0E + 3))) //Telemetry frame is 17 @@ -240,8 +237,10 @@ uint16_t ReadFrSkyX() // restart sequence on missed packet - might need count or timeout instead of one missed if(packet_count>100) {//~1sec - seq_last_sent = 0; - seq_last_rcvd = 8; +// seq_last_sent = 0; +// seq_last_rcvd = 8; + FrX_send_seq = 0x08 ; + FrX_receive_seq = 0 ; packet_count=0; #if defined TELEMETRY telemetry_lost=1; @@ -249,8 +248,13 @@ uint16_t ReadFrSkyX() } CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO } + frskyX_data_frame(); + if ( FrX_send_seq != 0x08 ) + { + FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ; + } state = FRSKY_DATA1; - return 300; + return 500; } return 1; } @@ -279,8 +283,10 @@ uint16_t initFrSkyX() state = FRSKY_DATA1; initialize_data(0); } - seq_last_sent = 0; - seq_last_rcvd = 8; +// seq_last_sent = 0; +// seq_last_rcvd = 8; + uint8_t FrX_send_seq = 0x08 ; + uint8_t FrX_receive_seq = 0 ; return 10000; } #endif \ No newline at end of file diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index c7173e4..df5fc78 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -393,7 +393,7 @@ enum CC2500_POWER CC2500_POWER_16 = 0xFE, // 0dbm CC2500_POWER_17 = 0xFF // +1dbm }; -#define CC2500_HIGH_POWER CC2500_POWER_16 +#define CC2500_HIGH_POWER CC2500_POWER_17 #define CC2500_LOW_POWER CC2500_POWER_13 #define CC2500_RANGE_POWER CC2500_POWER_1 #define CC2500_BIND_POWER CC2500_POWER_1 diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 83f0d8d..caf8545 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -106,6 +106,19 @@ uint8_t RX_num; uint8_t calData[48]; #endif +#ifdef CHECK_FOR_BOOTLOADER +uint8_t BootTimer ; +uint8_t BootState ; +uint8_t NotBootChecking ; +uint8_t BootCount ; + +#define BOOT_WAIT_30_IDLE 0 +#define BOOT_WAIT_30_DATA 1 +#define BOOT_WAIT_20 2 +#define BOOT_READY 3 + +#endif + //Channel mapping for protocols const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8, AUX9, AUX10}; const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8}; @@ -392,12 +405,91 @@ void setup() protocol=0; servo_max_100=SERIAL_MAX_100; servo_min_100=SERIAL_MIN_100; servo_max_125=SERIAL_MAX_125; servo_min_125=SERIAL_MIN_125; +#ifdef CHECK_FOR_BOOTLOADER + Mprotocol_serial_init(1); // Configure serial and enable RX interrupt +#else Mprotocol_serial_init(); // Configure serial and enable RX interrupt +#endif #endif //ENABLE_SERIAL } servo_mid=servo_min_100+servo_max_100; //In fact 2* mid_value } + + +#ifdef CHECK_FOR_BOOTLOADER +void pollBoot() +{ + uint8_t rxchar ; + uint8_t lState = BootState ; + uint8_t millisTime = millis() ; // Call this once only +#ifdef ORANGE_TX + if ( USARTC0.STATUS & USART_RXCIF_bm ) +#else + if ( UCSR0A & ( 1 << RXC0 ) ) +#endif + { + rxchar = UDR0 ; + BootCount += 1 ; + if ( ( lState == BOOT_WAIT_30_IDLE ) || ( lState == BOOT_WAIT_30_DATA ) ) + { + if ( lState == BOOT_WAIT_30_IDLE ) // Waiting for 0x30 + { + BootTimer = millisTime ; // Start timeout + } + if ( rxchar == 0x30 ) + { + lState = BOOT_WAIT_20 ; + } + else + { + lState = BOOT_WAIT_30_DATA ; + } + } + else if ( lState == BOOT_WAIT_20 ) // Waiting for 0x20 + { + if ( rxchar == 0x20 ) + { + lState = BOOT_READY ; + } + } + } + else // No byte received + { + if ( lState != BOOT_WAIT_30_IDLE ) // Something received + { + uint8_t time = millisTime - BootTimer ; + if ( time > 5 ) + { + if ( BootCount > 2 ) + { // Run normally + NotBootChecking = 0xFF ; + Mprotocol_serial_init( 0 ) ; + } + else if ( lState == BOOT_READY ) + { + cli(); // Disable global int due to RW of 16 bits registers + void (*p)() ; +#ifndef ORANGE_TX + p = (void (*)())0x3F00 ; // Word address (0x7E00 byte) +#else + p = (void (*)())0x4000 ; // Word address (0x8000 byte) +#endif + (*p)() ; + // go to boot + } + else + { + lState = BOOT_WAIT_30_IDLE ; + BootCount = 0 ; + } + } + } + } + BootState = lState ; +} +#endif + // Main // Protocol scheduler void loop() @@ -485,6 +577,13 @@ void loop() uint8_t Update_All() { #ifdef ENABLE_SERIAL +#ifdef CHECK_FOR_BOOTLOADER + if ( (mode_select==MODE_SERIAL) && (NotBootChecking == 0) ) + { + pollBoot() ; + } + else +#endif if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received { update_serial_data(); // Update protocol and data @@ -1093,7 +1192,11 @@ void modules_reset() prev_power=0xFD; // unused power value } +#ifdef CHECK_FOR_BOOTLOADER +void Mprotocol_serial_init( uint8_t boot ) +#else void Mprotocol_serial_init() +#endif { #ifdef ORANGE_TX PORTC.OUTSET = 0x08 ; @@ -1103,12 +1206,23 @@ void Mprotocol_serial_init() USARTC0.BAUDCTRLB = 0 ; USARTC0.CTRLB = 0x18 ; - USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ; + USARTC0.CTRLA = (USARTC0.CTRLA & 0xCC) | 0x11 ; USARTC0.CTRLC = 0x2B ; UDR0 ; #ifdef INVERT_SERIAL PORTC.PIN3CTRL |= 0x40 ; #endif +#ifdef CHECK_FOR_BOOTLOADER + if ( boot ) + { + USARTC0.BAUDCTRLB = 0 ; + USARTC0.BAUDCTRLA = 33 ; // 57600 + USARTC0.CTRLA = (USARTC0.CTRLA & 0xC0) ; + USARTC0.CTRLC = 0x03 ; // 8 bit, no parity, 1 stop + USARTC0.CTRLB = 0x18 ; // Enable Tx and Rx + PORTC.PIN3CTRL &= ~0x40 ; + } +#endif // CHECK_FOR_BOOTLOADER #elif defined STM32_BOARD usart2_begin(100000,SERIAL_8E2); usart3_begin(100000,SERIAL_8E2); @@ -1132,6 +1246,16 @@ void Mprotocol_serial_init() initTXSerial( SPEED_100K ) ; #endif //TELEMETRY #endif //DEBUG_TX +#ifdef CHECK_FOR_BOOTLOADER + if ( boot ) + { + UBRR0H = 0 ; + UBRR0L = 33 ; // 57600 + UCSR0C &= ~_BV(UPM01) ; // No parity + UCSR0B &= ~_BV(RXCIE0);// No rx interrupt + UCSR0A |= _BV(U2X0); //Double speed mode USART0 + } +#endif // CHECK_FOR_BOOTLOADER #endif //ORANGE_TX } diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 947b118..d8b55b2 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -31,6 +31,18 @@ uint8_t RetrySequence ; uint8_t sport_counter=0; uint8_t RxBt = 0; uint8_t sport = 0; + +struct t_fx_rx_packet +{ + uint8_t validSequence ; + uint8_t count ; + uint8_t payload[6] ; +} ; + +// Store for out of sequence packet +struct t_fx_rx_packet FrskyxRxTelemetry ; + + #endif #if defined HUB_TELEMETRY #define USER_MAX_BYTES 6 @@ -205,19 +217,73 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len) telemetry_lost=0; if (protocol==MODE_FRSKYX) { - if ((pktt[5] >> 4 & 0x0f) == 0x08) - { - seq_last_sent = 8; - seq_last_rcvd = 0; - pass=0; - } - else + uint16_t lcrc = crc_x(&pkt[3], len-7) ; + if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) ) { - if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4) - seq_last_rcvd = (seq_last_rcvd + 1) % 4; + // Check if in sequence + if ( (pkt[5] & 0x0F) == 0x08 ) + { + FrX_receive_seq = 0x08 ; + } + else if ( (pkt[5] & 0x03) == (FrX_receive_seq & 0x03 ) ) + { + // OK to process + FrX_receive_seq = ( FrX_receive_seq + 1 ) & 0x03 ; + if ( FrskyxRxTelemetry.validSequence & 0x80 ) + { + FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ; + } + } else - pass=0;//reset if sequence wrong + { + // Save and request correct packet + struct t_fx_rx_packet *p ; + uint8_t count ; + // pkt[4] RSSI + // pkt[5] sequence control + // pkt[6] payload count + // pkt[7-12] payload + pktt[6] = 0 ; // Don't process + p = &FrskyxRxTelemetry ; + count = pkt[6] ; + if ( count <= 6 ) + { + p->count = count ; + for ( uint8_t i = 0 ; i < count ; i += 1 ) + { + p->payload[i] = pkt[i+7] ; + } + p->validSequence = 0x80 | ( pkt[5] & 0x03 ) ; + } + FrX_receive_seq = ( FrX_receive_seq & 0x03 ) | 0x04 ; // Request re-transmission + } + + if (((pktt[5] >> 4) & 0x0f) == 0x08) + { + FrX_send_seq = 0 ; +// FrX_receive_seq = 0x08 ; + } } + +// packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start +// if ( FrX_send_seq != 0x08 ) +// { +// FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ; +// } + +// if ((pktt[5] >> 4 & 0x0f) == 0x08) +// { +// seq_last_sent = 8; +// seq_last_rcvd = 0; +// pass=0; +// } +// else +// { +// if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4) +// seq_last_rcvd = (seq_last_rcvd + 1) % 4; +// else +// pass=0;//reset if sequence wrong +// } } #endif } @@ -573,8 +639,20 @@ void TelemetryUpdate() else RxBt = (pktt[4]<<1) + 1 ; if(pktt[6] && pktt[6]<=6) + { for (uint8_t i=0; i < pktt[6]; i++) proces_sport_data(pktt[7+i]); + if ( FrskyxRxTelemetry.validSequence & 0x80 ) + { + // Process out of sequence packet + for (uint8_t i=0; i < FrskyxRxTelemetry.count ; i++) + { + proces_sport_data( FrskyxRxTelemetry.payload[i] ) ; + } +// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ; + FrskyxRxTelemetry.validSequence = 0 ; + } + } telemetry_link=0; } uint32_t now = micros(); diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 513ca8b..5c53159 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -49,6 +49,15 @@ //The goal is to prevent binding other people's model when powering up the TX, changing model or scanning through protocols. #define WAIT_FOR_BIND +/*************************/ +/*** BOOTLOADER USE ***/ +/*************************/ +#define CHECK_FOR_BOOTLOADER +//Allow flashing multimodule directly with TX(erky9x or opentx modified firmwares) +//1. Start ersky9x in bootloader mode and copy the multi.hex file into the firmware directory on the SD card. +//2. Disconnect the USB, then press EXIT LONG while holding the horizontal trims APART to enter "maintenance mode". +//3. Select "Update Multi", then HEX mode, then select the file and start the flash. +//4. When finished, EXIT back to reboot in normal mode. /****************/ /*** RF CHIPS ***/