From 99c99fd66230c1307818e96ccd4a5b6aa42fabef Mon Sep 17 00:00:00 2001 From: Goebish Date: Wed, 10 Apr 2019 00:58:21 +0200 Subject: [PATCH 01/31] Add V2 sub-format --- src/protocol/gd00x_nrf24l01.c | 215 ++++++++++++++++++++++++++-------- 1 file changed, 164 insertions(+), 51 deletions(-) diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_nrf24l01.c index e55cc84383..a4413e7546 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_nrf24l01.c @@ -41,13 +41,35 @@ #define GD00X_RF_BIND_CHANNEL 2 #define GD00X_PAYLOAD_SIZE 15 +#define GD00X_V2_BIND_PACKET_PERIOD 1700 +#define GD00X_V2_RF_BIND_CHANNEL 0x43 +#define GD00X_V2_PAYLOAD_SIZE 6 + +static const char * const gd00x_opts[] = { + _tr_noop("Format"), "V1", "V2", NULL, + NULL +}; +enum { + PROTOOPTS_FORMAT = 0, + LAST_PROTO_OPT, +}; +enum { + FORMAT_V1 = 0, + FORMAT_V2, +}; +ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts); + static u8 tx_power; static u8 packet[GD00X_PAYLOAD_SIZE]; static u8 hopping_frequency_no; static u8 rx_tx_addr[5]; static u8 hopping_frequency[4]; static u16 bind_counter; +static u16 packet_period; +static u8 packet_count; +static u8 packet_length; static u8 phase; +static u8 len; enum{ GD00X_BIND, @@ -58,6 +80,10 @@ enum{ #define GD00X_FLAG_DR 0x08 #define GD00X_FLAG_LIGHT 0x04 +// flags going to packet[4] +#define GD00X_V2_FLAG_DR 0x40 +#define GD00X_V2_FLAG_LIGHT 0x80 + // For code readability enum { CHANNEL1 = 0, @@ -89,27 +115,89 @@ static u16 scale_channel(u8 ch, u16 destMin, u16 destMax) #define GET_FLAG(ch, mask) (Channels[ch] > 0 ? mask : 0) static void GD00X_send_packet() { - packet[0] = (phase == GD00X_BIND) ? 0xAA : 0x55; - memcpy(packet+1,rx_tx_addr,4); - u16 channel=scale_channel(CHANNEL1, 2000, 1000); // aileron - packet[5 ] = channel; - packet[6 ] = channel>>8; - channel=scale_channel(CHANNEL3, 1000, 2000); // throttle - packet[7 ] = channel; - packet[8 ] = channel>>8; - // dynamically driven aileron trim - channel=scale_channel(CHANNEL1, 1000, 2000); // aileron - packet[9 ] = channel; - packet[10] = channel>>8; - packet[11] = GD00X_FLAG_DR // Force high rate - | GET_FLAG(CHANNEL5, GD00X_FLAG_LIGHT); - packet[12] = 0x00; - packet[13] = 0x00; - packet[14] = 0x00; + static u8 prev_CH6=0; + switch (Model.proto_opts[PROTOOPTS_FORMAT]) { + case FORMAT_V1: + packet[0] = (phase == GD00X_BIND) ? 0xAA : 0x55; + memcpy(packet+1,rx_tx_addr,4); + u16 channel=scale_channel(CHANNEL1, 2000, 1000); // aileron + packet[5 ] = channel; + packet[6 ] = channel>>8; + channel=scale_channel(CHANNEL3, 1000, 2000); // throttle + packet[7 ] = channel; + packet[8 ] = channel>>8; + // dynamically driven aileron trim + channel=scale_channel(CHANNEL1, 1000, 2000); // aileron + packet[9 ] = channel; + packet[10] = channel>>8; + packet[11] = GD00X_FLAG_DR // Force high rate + | GET_FLAG(CHANNEL5, GD00X_FLAG_LIGHT); + packet[12] = 0x00; + packet[13] = 0x00; + packet[14] = 0x00; + break; + case FORMAT_V2: + if (phase == GD00X_BIND) { + for(u8 i=0; i<5;i++) + packet[i]=rx_tx_addr[i]; + } + else { + packet[0]=scale_channel(CHANNEL3,0,100); // throttle 0..100 + + #define CHANNEL_MAX_100 1844 + #define CHANNEL_MIN_100 204 + #define GD00X_V2_DB_MIN 1024-40 + #define GD00X_V2_DB_MAX 1024+40 + // Deadband is needed on aileron + u16 aileron=scale_channel(CHANNEL1, CHANNEL_MAX_100, CHANNEL_MIN_100); + if (aileron>GD00X_V2_DB_MIN && aileronGD00X_V2_DB_MAX) + packet[1]=0x1F-((aileron-GD00X_V2_DB_MAX)*(0x20)/(CHANNEL_MAX_100+1-GD00X_V2_DB_MAX)); // 1F..00 + else + packet[1]=0x3F-((aileron-CHANNEL_MIN_100)*(0x1F)/(GD00X_V2_DB_MIN-CHANNEL_MIN_100)); // 3F..21 + + // Trims must be in a seperate channel for this model + packet[2]=0x3F-(scale_channel(CHANNEL5,0,255)>>2); // Trim: 0x3F..0x20..0x00 + + u8 seq=((packet_count*3)/7)%5; + packet[4]=seq | GD00X_V2_FLAG_DR; + + if (GET_FLAG(CHANNEL6,1) != prev_CH6) + { // LED switch is temporary + len=43; + prev_CH6=GET_FLAG(CHANNEL6,1); + } + if (len) + { // Send the light flag for a couple of packets + packet[4] |= GD00X_V2_FLAG_LIGHT; + len--; + } + + packet[3]=(packet[0]+packet[1]+packet[2]+packet[4])^0x65; + + if ((packet_count%12) == 0 ) + hopping_frequency_no ^= 1; // Toggle between the 2 frequencies + packet_count++; + if (packet_count>34) packet_count=0; // Full period + if ( seq == (((packet_count*3)/7)%5) ) + { + if (packet_period==2700) + packet_period=3000; + else + packet_period=2700; + } + else + packet_period=4300; + } + packet[5]='D'; + break; + } // Power on, TX mode, CRC enabled XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); - if(phase == GD00X_DATA) + if (phase == GD00X_DATA) { NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); hopping_frequency_no &= 3; // 4 RF channels @@ -117,7 +205,7 @@ static void GD00X_send_packet() NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); NRF24L01_FlushTx(); - XN297_WritePayload(packet, GD00X_PAYLOAD_SIZE); + XN297_WritePayload(packet, packet_length); if (tx_power != Model.tx_power) { @@ -131,14 +219,21 @@ static void GD00X_init() { NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); - XN297_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); - NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_RF_BIND_CHANNEL); // Bind channel + switch (Model.proto_opts[PROTOOPTS_FORMAT]) { + case FORMAT_V1: + XN297_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); + break; + case FORMAT_V2: + XN297_SetTXAddr((u8*)"GDKNx", 5); + break; + } + NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_RF_BIND_CHANNEL); // Bind channel NRF24L01_FlushTx(); NRF24L01_FlushRx(); - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit - NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only + NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps NRF24L01_SetPower(tx_power); } @@ -165,49 +260,67 @@ static void GD00X_initialize_txid() // Pump zero bytes for LFSR to diverge more for (i = 0; i < sizeof(lfsr); ++i) rand32_r(&lfsr, 0); - // tx address - for(i=0; i<2; i++) - rx_tx_addr[i] = (lfsr >> (i*8)) & 0xff; - - rx_tx_addr[2]=0x12; - rx_tx_addr[3]=0x13; - - u8 start=76+(rx_tx_addr[0]&0x03); - for(i=0; i<4;i++) - hopping_frequency[i]=start-(i<<1); - - #ifdef FORCE_GD00X_ORIGINAL_ID - rx_tx_addr[0]=0x1F; - rx_tx_addr[1]=0x39; - rx_tx_addr[2]=0x12; - rx_tx_addr[3]=0x13; - for(i=0; i<4;i++) - hopping_frequency[i]=79-(i<<1); - #endif + switch (Model.proto_opts[PROTOOPTS_FORMAT]) { + case FORMAT_V1: + // tx address + for (i=0; i<2; i++) + rx_tx_addr[i] = (lfsr >> (i*8)) & 0xff; + + rx_tx_addr[2]=0x12; + rx_tx_addr[3]=0x13; + + u8 start=76+(rx_tx_addr[0]&0x03); + for (i=0; i<4;i++) + hopping_frequency[i]=start-(i<<1); + + #ifdef FORCE_GD00X_ORIGINAL_ID + rx_tx_addr[0]=0x1F; + rx_tx_addr[1]=0x39; + rx_tx_addr[2]=0x12; + rx_tx_addr[3]=0x13; + for(i=0; i<4;i++) + hopping_frequency[i]=79-(i<<1); + #endif + break; + case FORMAT_V2: + //Only 1 ID for now... + rx_tx_addr[0]=0x65; + rx_tx_addr[1]=0x00; + rx_tx_addr[2]=0x00; + rx_tx_addr[3]=0x95; + rx_tx_addr[4]=0x47; //'G' + hopping_frequency[0]=0x05; + hopping_frequency[1]=0x25; + break; + } } static u16 GD00X_callback() { - if(phase == GD00X_BIND) { - if(--bind_counter==0) { + if (phase == GD00X_BIND) { + if (--bind_counter==0) { PROTOCOL_SetBindState(0); phase = GD00X_DATA; } } GD00X_send_packet(); - return GD00X_PACKET_PERIOD; + return packet_period; } static void initialize() { CLOCK_StopTimer(); tx_power = Model.tx_power; - PROTOCOL_SetBindState((GD00X_BIND_COUNT * GD00X_PACKET_PERIOD)/1000); - GD00X_initialize_txid(); - GD00X_init(); + packet_period=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD; + packet_length=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; + packet_count=0; + len=0; hopping_frequency_no = 0; bind_counter=GD00X_BIND_COUNT; phase = GD00X_BIND; + PROTOCOL_SetBindState((GD00X_BIND_COUNT * packet_period)/1000); + GD00X_initialize_txid(); + GD00X_init(); CLOCK_StartTimer(GD00X_INITIAL_WAIT, GD00X_callback); } @@ -224,7 +337,7 @@ uintptr_t GD00X_Cmds(enum ProtoCmds cmd) case PROTOCMD_NUMCHAN: return 5; case PROTOCMD_DEFAULT_NUMCHAN: return 5; case PROTOCMD_CURRENT_ID: return Model.fixed_id; - case PROTOCMD_GETOPTIONS: return 0; + case PROTOCMD_GETOPTIONS: return (uintptr_t)gd00x_opts; case PROTOCMD_TELEMETRYSTATE: return PROTO_TELEM_UNSUPPORTED; case PROTOCMD_CHANNELMAP: return AETRG; default: break; From 5ec6a4ba70fda57e7b9f54c719433c0efdd6a210 Mon Sep 17 00:00:00 2001 From: Goebish Date: Wed, 10 Apr 2019 21:39:03 +0200 Subject: [PATCH 02/31] Fix bind and hopping --- src/protocol/gd00x_nrf24l01.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_nrf24l01.c index a4413e7546..e0029d9400 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_nrf24l01.c @@ -197,10 +197,12 @@ static void GD00X_send_packet() // Power on, TX mode, CRC enabled XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); - if (phase == GD00X_DATA) - { - NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]); - hopping_frequency_no &= 3; // 4 RF channels + if (phase == GD00X_DATA) { + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); + if(Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1) { + hopping_frequency_no++; + hopping_frequency_no &= 3; // 4 RF channels + } } NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); @@ -222,12 +224,13 @@ static void GD00X_init() switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_V1: XN297_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); + NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_RF_BIND_CHANNEL); break; case FORMAT_V2: XN297_SetTXAddr((u8*)"GDKNx", 5); + NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_V2_RF_BIND_CHANNEL); break; } - NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_RF_BIND_CHANNEL); // Bind channel NRF24L01_FlushTx(); NRF24L01_FlushRx(); NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit From 04a8c7310967e1b887af4539feb29b0cef5c1860 Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 11 Apr 2019 16:11:05 +0200 Subject: [PATCH 03/31] Fix typo --- src/protocol/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/protocol.c b/src/protocol/protocol.c index addad87c2e..60a16f0b95 100644 --- a/src/protocol/protocol.c +++ b/src/protocol/protocol.c @@ -165,7 +165,7 @@ void PROTOCOL_Load(int no_dlg) //printf("Loading %s: %08lx\n", file, fh); if(! fh) { if(! no_dlg) { - sprintf(tempstring, "Misisng protocol:\n%s", file); + sprintf(tempstring, "Missing protocol:\n%s", file); PAGE_ShowWarning(NULL, tempstring); } return; From 9dae018aac1f648df7a76a9ddfb570e4a6b540cf Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 11 Apr 2019 23:06:10 +0200 Subject: [PATCH 04/31] Add arbitrary Tx ID --- src/protocol/gd00x_nrf24l01.c | 46 ++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_nrf24l01.c index e0029d9400..c568627282 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_nrf24l01.c @@ -175,7 +175,7 @@ static void GD00X_send_packet() len--; } - packet[3]=(packet[0]+packet[1]+packet[2]+packet[4])^0x65; + packet[3]=(packet[0]+packet[1]+packet[2]+packet[4])^(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]); if ((packet_count%12) == 0 ) hopping_frequency_no ^= 1; // Toggle between the 2 frequencies @@ -286,14 +286,48 @@ static void GD00X_initialize_txid() #endif break; case FORMAT_V2: - //Only 1 ID for now... - rx_tx_addr[0]=0x65; + //Generate 64 different IDs rx_tx_addr[1]=0x00; rx_tx_addr[2]=0x00; + rx_tx_addr[1+((lfsr&0x10)>>4)]=lfsr&0x8F; + rx_tx_addr[0]=0x65; rx_tx_addr[3]=0x95; - rx_tx_addr[4]=0x47; //'G' - hopping_frequency[0]=0x05; - hopping_frequency[1]=0x25; + rx_tx_addr[4]=0x47; //'G' + + //hopping calculation + hopping_frequency[0]=(0x15+(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3]))&0x1F; + if( hopping_frequency[0] == 0x0F ) + hopping_frequency[0]=0x0E; + else if( (hopping_frequency[0]&0xFE) == 0x10 ) + hopping_frequency[0]+=2; + hopping_frequency[1]=0x20+hopping_frequency[0]; + + #ifdef FORCE_GD00X_ORIGINAL_ID + //ID 1 + rx_tx_addr[0]=0x65; + rx_tx_addr[1]=0x00; + rx_tx_addr[2]=0x00; + rx_tx_addr[3]=0x95; + rx_tx_addr[4]=0x47; //'G' + hopping_frequency[0]=0x05; + hopping_frequency[1]=0x25; + //ID 2 + rx_tx_addr[0]=0xFD; + rx_tx_addr[1]=0x09; + rx_tx_addr[2]=0x00; + rx_tx_addr[3]=0x65; + rx_tx_addr[4]=0x47; //'G' + hopping_frequency[0]=0x06; + hopping_frequency[1]=0x26; + //ID 3 + rx_tx_addr[0]=0x67; + rx_tx_addr[1]=0x0F; + rx_tx_addr[2]=0x00; + rx_tx_addr[3]=0x69; + rx_tx_addr[4]=0x47; //'G' + hopping_frequency[0]=0x16; + hopping_frequency[1]=0x36; + #endif break; } } From cfdb8b3c11089babd3c21e0bc7cde26b5ab9333e Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 11 Apr 2019 23:30:25 +0200 Subject: [PATCH 05/31] Fix lint --- src/protocol/gd00x_nrf24l01.c | 169 +++++++++++++++++----------------- 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_nrf24l01.c index c568627282..cba8a60da2 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_nrf24l01.c @@ -17,7 +17,7 @@ #include "interface.h" #include "mixer.h" #include "config/model.h" -#include "config/tx.h" // for Transmitter +#include "config/tx.h" // for Transmitter #ifdef PROTO_HAS_NRF24L01 @@ -27,8 +27,8 @@ #define GD00X_PACKET_PERIOD 100 #define dbgprintf printf #else -#define GD00X_BIND_COUNT 857 //3sec -#define GD00X_PACKET_PERIOD 3500 // Timeout for callback in uSec +#define GD00X_BIND_COUNT 857 //3sec +#define GD00X_PACKET_PERIOD 3500 // Timeout for callback in uSec //printf inside an interrupt handler is really dangerous //this shouldn't be enabled even in debug builds without explicitly //turning it on @@ -41,9 +41,9 @@ #define GD00X_RF_BIND_CHANNEL 2 #define GD00X_PAYLOAD_SIZE 15 -#define GD00X_V2_BIND_PACKET_PERIOD 1700 -#define GD00X_V2_RF_BIND_CHANNEL 0x43 -#define GD00X_V2_PAYLOAD_SIZE 6 +#define GD00X_V2_BIND_PACKET_PERIOD 1700 +#define GD00X_V2_RF_BIND_CHANNEL 0x43 +#define GD00X_V2_PAYLOAD_SIZE 6 static const char * const gd00x_opts[] = { _tr_noop("Format"), "V1", "V2", NULL, @@ -81,8 +81,8 @@ enum{ #define GD00X_FLAG_LIGHT 0x04 // flags going to packet[4] -#define GD00X_V2_FLAG_DR 0x40 -#define GD00X_V2_FLAG_LIGHT 0x80 +#define GD00X_V2_FLAG_DR 0x40 +#define GD00X_V2_FLAG_LIGHT 0x80 // For code readability enum { @@ -115,19 +115,19 @@ static u16 scale_channel(u8 ch, u16 destMin, u16 destMax) #define GET_FLAG(ch, mask) (Channels[ch] > 0 ? mask : 0) static void GD00X_send_packet() { - static u8 prev_CH6=0; + static u8 prev_CH6 = 0; switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_V1: packet[0] = (phase == GD00X_BIND) ? 0xAA : 0x55; - memcpy(packet+1,rx_tx_addr,4); - u16 channel=scale_channel(CHANNEL1, 2000, 1000); // aileron + memcpy(packet+1, rx_tx_addr, 4); + u16 channel = scale_channel(CHANNEL1, 2000, 1000); // aileron packet[5 ] = channel; packet[6 ] = channel>>8; - channel=scale_channel(CHANNEL3, 1000, 2000); // throttle + channel = scale_channel(CHANNEL3, 1000, 2000); // throttle packet[7 ] = channel; packet[8 ] = channel>>8; // dynamically driven aileron trim - channel=scale_channel(CHANNEL1, 1000, 2000); // aileron + channel = scale_channel(CHANNEL1, 1000, 2000); // aileron packet[9 ] = channel; packet[10] = channel>>8; packet[11] = GD00X_FLAG_DR // Force high rate @@ -138,36 +138,37 @@ static void GD00X_send_packet() break; case FORMAT_V2: if (phase == GD00X_BIND) { - for(u8 i=0; i<5;i++) - packet[i]=rx_tx_addr[i]; + for (u8 i = 0; i < 5; i++) + packet[i] = rx_tx_addr[i]; } - else { - packet[0]=scale_channel(CHANNEL3,0,100); // throttle 0..100 + else + { + packet[0] = scale_channel(CHANNEL3, 0, 100); // throttle 0..100 - #define CHANNEL_MAX_100 1844 - #define CHANNEL_MIN_100 204 + #define CHANNEL_MAX_100 1844 + #define CHANNEL_MIN_100 204 #define GD00X_V2_DB_MIN 1024-40 #define GD00X_V2_DB_MAX 1024+40 // Deadband is needed on aileron u16 aileron=scale_channel(CHANNEL1, CHANNEL_MAX_100, CHANNEL_MIN_100); - if (aileron>GD00X_V2_DB_MIN && aileron GD00X_V2_DB_MIN && aileron < GD00X_V2_DB_MAX) + packet[1] = 0x20; // Send the channel centered else // Ail: 0x3F..0x20..0x00 - if (aileron>GD00X_V2_DB_MAX) - packet[1]=0x1F-((aileron-GD00X_V2_DB_MAX)*(0x20)/(CHANNEL_MAX_100+1-GD00X_V2_DB_MAX)); // 1F..00 + if (aileron > GD00X_V2_DB_MAX) + packet[1] = 0x1F-((aileron-GD00X_V2_DB_MAX)*(0x20)/(CHANNEL_MAX_100+1-GD00X_V2_DB_MAX)); // 1F..00 else - packet[1]=0x3F-((aileron-CHANNEL_MIN_100)*(0x1F)/(GD00X_V2_DB_MIN-CHANNEL_MIN_100)); // 3F..21 + packet[1] = 0x3F-((aileron-CHANNEL_MIN_100)*(0x1F)/(GD00X_V2_DB_MIN-CHANNEL_MIN_100)); // 3F..21 // Trims must be in a seperate channel for this model - packet[2]=0x3F-(scale_channel(CHANNEL5,0,255)>>2); // Trim: 0x3F..0x20..0x00 + packet[2] = 0x3F-(scale_channel(CHANNEL5, 0, 255)>>2); // Trim: 0x3F..0x20..0x00 - u8 seq=((packet_count*3)/7)%5; - packet[4]=seq | GD00X_V2_FLAG_DR; + u8 seq = ((packet_count*3)/7)%5; + packet[4] = seq | GD00X_V2_FLAG_DR; - if (GET_FLAG(CHANNEL6,1) != prev_CH6) + if (GET_FLAG(CHANNEL6, 1) != prev_CH6) { // LED switch is temporary - len=43; - prev_CH6=GET_FLAG(CHANNEL6,1); + len = 43; + prev_CH6 = GET_FLAG(CHANNEL6, 1); } if (len) { // Send the light flag for a couple of packets @@ -175,23 +176,23 @@ static void GD00X_send_packet() len--; } - packet[3]=(packet[0]+packet[1]+packet[2]+packet[4])^(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]); + packet[3] = (packet[0]+packet[1]+packet[2]+packet[4])^(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]); if ((packet_count%12) == 0 ) - hopping_frequency_no ^= 1; // Toggle between the 2 frequencies + hopping_frequency_no ^= 1; // Toggle between the 2 frequencies packet_count++; - if (packet_count>34) packet_count=0; // Full period + if (packet_count > 34) packet_count = 0; // Full period if ( seq == (((packet_count*3)/7)%5) ) { - if (packet_period==2700) - packet_period=3000; + if (packet_period == 2700) + packet_period = 3000; else - packet_period=2700; + packet_period = 2700; } else - packet_period=4300; + packet_period = 4300; } - packet[5]='D'; + packet[5] = 'D'; break; } @@ -201,7 +202,7 @@ static void GD00X_send_packet() NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); if(Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1) { hopping_frequency_no++; - hopping_frequency_no &= 3; // 4 RF channels + hopping_frequency_no &= 3; // 4 RF channels } } @@ -266,67 +267,67 @@ static void GD00X_initialize_txid() switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_V1: // tx address - for (i=0; i<2; i++) + for (i = 0; i < 2; i++) rx_tx_addr[i] = (lfsr >> (i*8)) & 0xff; - rx_tx_addr[2]=0x12; - rx_tx_addr[3]=0x13; + rx_tx_addr[2] = 0x12; + rx_tx_addr[3] = 0x13; - u8 start=76+(rx_tx_addr[0]&0x03); - for (i=0; i<4;i++) - hopping_frequency[i]=start-(i<<1); + u8 start = 76+(rx_tx_addr[0]&0x03); + for (i = 0; i < 4; i++) + hopping_frequency[i] = start-(i<<1); #ifdef FORCE_GD00X_ORIGINAL_ID - rx_tx_addr[0]=0x1F; - rx_tx_addr[1]=0x39; - rx_tx_addr[2]=0x12; - rx_tx_addr[3]=0x13; - for(i=0; i<4;i++) + rx_tx_addr[0] = 0x1F; + rx_tx_addr[1] = 0x39; + rx_tx_addr[2] = 0x12; + rx_tx_addr[3] = 0x13; + for(i = 0; i < 4; i++) hopping_frequency[i]=79-(i<<1); #endif break; case FORMAT_V2: //Generate 64 different IDs - rx_tx_addr[1]=0x00; - rx_tx_addr[2]=0x00; - rx_tx_addr[1+((lfsr&0x10)>>4)]=lfsr&0x8F; - rx_tx_addr[0]=0x65; - rx_tx_addr[3]=0x95; - rx_tx_addr[4]=0x47; //'G' + rx_tx_addr[1] = 0x00; + rx_tx_addr[2] = 0x00; + rx_tx_addr[1+((lfsr&0x10)>>4)] = lfsr&0x8F; + rx_tx_addr[0] = 0x65; + rx_tx_addr[3] = 0x95; + rx_tx_addr[4] = 0x47; //'G' //hopping calculation - hopping_frequency[0]=(0x15+(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3]))&0x1F; + hopping_frequency[0] = (0x15+(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3]))&0x1F; if( hopping_frequency[0] == 0x0F ) - hopping_frequency[0]=0x0E; + hopping_frequency[0] = 0x0E; else if( (hopping_frequency[0]&0xFE) == 0x10 ) - hopping_frequency[0]+=2; - hopping_frequency[1]=0x20+hopping_frequency[0]; + hopping_frequency[0] += 2; + hopping_frequency[1] = 0x20+hopping_frequency[0]; #ifdef FORCE_GD00X_ORIGINAL_ID //ID 1 - rx_tx_addr[0]=0x65; - rx_tx_addr[1]=0x00; - rx_tx_addr[2]=0x00; - rx_tx_addr[3]=0x95; - rx_tx_addr[4]=0x47; //'G' - hopping_frequency[0]=0x05; - hopping_frequency[1]=0x25; + rx_tx_addr[0] = 0x65; + rx_tx_addr[1] = 0x00; + rx_tx_addr[2] = 0x00; + rx_tx_addr[3] = 0x95; + rx_tx_addr[4] = 0x47; //'G' + hopping_frequency[0] = 0x05; + hopping_frequency[1] = 0x25; //ID 2 - rx_tx_addr[0]=0xFD; - rx_tx_addr[1]=0x09; - rx_tx_addr[2]=0x00; - rx_tx_addr[3]=0x65; - rx_tx_addr[4]=0x47; //'G' - hopping_frequency[0]=0x06; - hopping_frequency[1]=0x26; + rx_tx_addr[0] = 0xFD; + rx_tx_addr[1] = 0x09; + rx_tx_addr[2] = 0x00; + rx_tx_addr[3] = 0x65; + rx_tx_addr[4] = 0x47; //'G' + hopping_frequency[0] = 0x06; + hopping_frequency[1] = 0x26; //ID 3 - rx_tx_addr[0]=0x67; - rx_tx_addr[1]=0x0F; - rx_tx_addr[2]=0x00; - rx_tx_addr[3]=0x69; - rx_tx_addr[4]=0x47; //'G' - hopping_frequency[0]=0x16; - hopping_frequency[1]=0x36; + rx_tx_addr[0] = 0x67; + rx_tx_addr[1] = 0x0F; + rx_tx_addr[2] = 0x00; + rx_tx_addr[3] = 0x69; + rx_tx_addr[4] = 0x47; //'G' + hopping_frequency[0] = 0x16; + hopping_frequency[1] = 0x36; #endif break; } @@ -335,7 +336,7 @@ static void GD00X_initialize_txid() static u16 GD00X_callback() { if (phase == GD00X_BIND) { - if (--bind_counter==0) { + if (--bind_counter == 0) { PROTOCOL_SetBindState(0); phase = GD00X_DATA; } @@ -349,8 +350,8 @@ static void initialize() CLOCK_StopTimer(); tx_power = Model.tx_power; packet_period=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD; - packet_length=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; - packet_count=0; + packet_length=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; + packet_count=0; len=0; hopping_frequency_no = 0; bind_counter=GD00X_BIND_COUNT; From c4d7cdc2b58ebac5f2a15b7f16f0cc15e6106d29 Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 11 Apr 2019 23:37:41 +0200 Subject: [PATCH 06/31] Fix lint --- src/protocol/gd00x_nrf24l01.c | 64 ++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_nrf24l01.c index cba8a60da2..3873bc08f0 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_nrf24l01.c @@ -27,15 +27,15 @@ #define GD00X_PACKET_PERIOD 100 #define dbgprintf printf #else -#define GD00X_BIND_COUNT 857 //3sec +#define GD00X_BIND_COUNT 857 // 3sec #define GD00X_PACKET_PERIOD 3500 // Timeout for callback in uSec -//printf inside an interrupt handler is really dangerous -//this shouldn't be enabled even in debug builds without explicitly -//turning it on +// printf inside an interrupt handler is really dangerous +// this shouldn't be enabled even in debug builds without explicitly +// turning it on #define dbgprintf if(0) printf #endif -//#define FORCE_GD00X_ORIGINAL_ID +// #define FORCE_GD00X_ORIGINAL_ID #define GD00X_INITIAL_WAIT 500 #define GD00X_RF_BIND_CHANNEL 2 @@ -150,15 +150,17 @@ static void GD00X_send_packet() #define GD00X_V2_DB_MIN 1024-40 #define GD00X_V2_DB_MAX 1024+40 // Deadband is needed on aileron - u16 aileron=scale_channel(CHANNEL1, CHANNEL_MAX_100, CHANNEL_MIN_100); - if (aileron > GD00X_V2_DB_MIN && aileron < GD00X_V2_DB_MAX) + u16 aileron = scale_channel(CHANNEL1, CHANNEL_MAX_100, CHANNEL_MIN_100); + if (aileron > GD00X_V2_DB_MIN && aileron < GD00X_V2_DB_MAX) { packet[1] = 0x20; // Send the channel centered + } else // Ail: 0x3F..0x20..0x00 + { if (aileron > GD00X_V2_DB_MAX) packet[1] = 0x1F-((aileron-GD00X_V2_DB_MAX)*(0x20)/(CHANNEL_MAX_100+1-GD00X_V2_DB_MAX)); // 1F..00 else packet[1] = 0x3F-((aileron-CHANNEL_MIN_100)*(0x1F)/(GD00X_V2_DB_MIN-CHANNEL_MIN_100)); // 3F..21 - + } // Trims must be in a seperate channel for this model packet[2] = 0x3F-(scale_channel(CHANNEL5, 0, 255)>>2); // Trim: 0x3F..0x20..0x00 @@ -200,7 +202,7 @@ static void GD00X_send_packet() XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); if (phase == GD00X_DATA) { NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); - if(Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1) { + if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1) { hopping_frequency_no++; hopping_frequency_no &= 3; // 4 RF channels } @@ -212,7 +214,7 @@ static void GD00X_send_packet() if (tx_power != Model.tx_power) { - //Keep transmit power updated + // Keep transmit power updated tx_power = Model.tx_power; NRF24L01_SetPower(tx_power); } @@ -269,63 +271,63 @@ static void GD00X_initialize_txid() // tx address for (i = 0; i < 2; i++) rx_tx_addr[i] = (lfsr >> (i*8)) & 0xff; - + rx_tx_addr[2] = 0x12; rx_tx_addr[3] = 0x13; - + u8 start = 76+(rx_tx_addr[0]&0x03); for (i = 0; i < 4; i++) - hopping_frequency[i] = start-(i<<1); - + hopping_frequency[i] = start-(i << 1); + #ifdef FORCE_GD00X_ORIGINAL_ID rx_tx_addr[0] = 0x1F; rx_tx_addr[1] = 0x39; rx_tx_addr[2] = 0x12; rx_tx_addr[3] = 0x13; - for(i = 0; i < 4; i++) - hopping_frequency[i]=79-(i<<1); + for (i = 0; i < 4; i++) + hopping_frequency[i] = 79-(i << 1); #endif break; case FORMAT_V2: - //Generate 64 different IDs + // Generate 64 different IDs rx_tx_addr[1] = 0x00; rx_tx_addr[2] = 0x00; rx_tx_addr[1+((lfsr&0x10)>>4)] = lfsr&0x8F; rx_tx_addr[0] = 0x65; rx_tx_addr[3] = 0x95; - rx_tx_addr[4] = 0x47; //'G' + rx_tx_addr[4] = 0x47; // 'G' - //hopping calculation + // hopping calculation hopping_frequency[0] = (0x15+(rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3]))&0x1F; - if( hopping_frequency[0] == 0x0F ) + if (hopping_frequency[0] == 0x0F) hopping_frequency[0] = 0x0E; - else if( (hopping_frequency[0]&0xFE) == 0x10 ) + else if ((hopping_frequency[0]&0xFE) == 0x10) hopping_frequency[0] += 2; hopping_frequency[1] = 0x20+hopping_frequency[0]; #ifdef FORCE_GD00X_ORIGINAL_ID - //ID 1 + // ID 1 rx_tx_addr[0] = 0x65; rx_tx_addr[1] = 0x00; rx_tx_addr[2] = 0x00; rx_tx_addr[3] = 0x95; - rx_tx_addr[4] = 0x47; //'G' + rx_tx_addr[4] = 0x47; // 'G' hopping_frequency[0] = 0x05; hopping_frequency[1] = 0x25; - //ID 2 + // ID 2 rx_tx_addr[0] = 0xFD; rx_tx_addr[1] = 0x09; rx_tx_addr[2] = 0x00; rx_tx_addr[3] = 0x65; - rx_tx_addr[4] = 0x47; //'G' + rx_tx_addr[4] = 0x47; // 'G' hopping_frequency[0] = 0x06; hopping_frequency[1] = 0x26; - //ID 3 + // ID 3 rx_tx_addr[0] = 0x67; rx_tx_addr[1] = 0x0F; rx_tx_addr[2] = 0x00; rx_tx_addr[3] = 0x69; - rx_tx_addr[4] = 0x47; //'G' + rx_tx_addr[4] = 0x47; // 'G' hopping_frequency[0] = 0x16; hopping_frequency[1] = 0x36; #endif @@ -349,10 +351,10 @@ static void initialize() { CLOCK_StopTimer(); tx_power = Model.tx_power; - packet_period=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD; - packet_length=Model.proto_opts[PROTOOPTS_FORMAT]==FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; - packet_count=0; - len=0; + packet_period = Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD; + packet_length = Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; + packet_count = 0; + len = 0; hopping_frequency_no = 0; bind_counter=GD00X_BIND_COUNT; phase = GD00X_BIND; From ff1a962f08bb35ee0d3a0e3f92549b3b746f6b31 Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 15:45:12 +0200 Subject: [PATCH 07/31] Add E010 protocol for CC2500 --- src/protocol/Makefile.inc | 6 + src/protocol/e010_cc2500.c | 424 +++++++++++++++++++++++++++++++++++++ src/protocol/protocol.h | 1 + 3 files changed, 431 insertions(+) create mode 100644 src/protocol/e010_cc2500.c diff --git a/src/protocol/Makefile.inc b/src/protocol/Makefile.inc index c9d32d23dd..d8cf83f0e2 100644 --- a/src/protocol/Makefile.inc +++ b/src/protocol/Makefile.inc @@ -61,6 +61,7 @@ PROTO_MODULES += $(ODIR)/protocol/loli.mod PROTO_MODULES += $(ODIR)/protocol/e016h.mod PROTO_MODULES += $(ODIR)/protocol/sumd.mod PROTO_MODULES += $(ODIR)/protocol/scancyrf.mod +PROTO_MODULES += $(ODIR)/protocol/e010.mod ALL += $(PROTO_MODULES) else #BUILD_TARGET @@ -307,4 +308,9 @@ $(ODIR)/protocol/sumd.mod : $(ODIR)/sumd_uart.bin $(ODIR)/protocol/scancyrf.mod : $(ODIR)/scanner_cyrf6936.bin @echo Building 'scancyrf' module /bin/mkdir -p $(ODIR)/protocol/ 2>/dev/null; /bin/cp $< $@ + +$(ODIR)/protocol/e010.mod : $(ODIR)/e010_cc2500.bin + @echo Building 'e010' module + /bin/mkdir -p $(ODIR)/protocol/ 2>/dev/null; /bin/cp $< $@ + endif #BUILD_TARGET diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c new file mode 100644 index 0000000000..2c102b0dc5 --- /dev/null +++ b/src/protocol/e010_cc2500.c @@ -0,0 +1,424 @@ +/* + This project is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Deviation is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Deviation. If not, see . + */ + +#include "common.h" +#include "interface.h" +#include "mixer.h" +#include "config/model.h" +#include "config/tx.h" + +#ifdef PROTO_HAS_CC2500 + +#ifdef EMULATOR + #define USE_FIXED_MFGID + #define BIND_COUNT 20 + #define PACKET_PERIOD 150 + #define dbgprintf printf +#else + #define BIND_COUNT 150 + #define PACKET_PERIOD 4000 // Timeout for callback in uSec + // printf inside an interrupt handler is really dangerous + // this shouldn't be enabled even in debug builds without explicitly + // turning it on + #define dbgprintf if(0) printf +#endif + +#define INITIAL_WAIT 500 +#define PACKET_SIZE 16 +#define RF_NUM_CHANNELS 4 +#define ADDRESS_LENGTH 5 + +const char * const e010_opts[] = { + _tr_noop("Format"), "E010", "Phoenix", NULL, + _tr_noop("Freq-Fine"), "-127", "127", NULL, + NULL +}; + +enum { + PROTOOPTS_FORMAT = 0, + PROTOOPTS_FREQFINE, + LAST_PROTO_OPT +}; +ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts); + +enum { + FORMAT_E010, + FORMAT_PHOENIX, +}; + +// For code readability +enum { + CHANNEL1 = 0, // Aileron + CHANNEL2, // Elevator + CHANNEL3, // Throttle + CHANNEL4, // Rudder + CHANNEL5, // Leds / Arm + CHANNEL6, // Flip + CHANNEL7, // Still camera + CHANNEL8, // Video camera + CHANNEL9, // Headless + CHANNEL10, // Return To Home +}; + +#define CHANNEL_LED CHANNEL5 +#define CHANNEL_ARM CHANNEL5 // TDR Phoenix mini +#define CHANNEL_FLIP CHANNEL6 +#define CHANNEL_PICTURE CHANNEL7 +#define CHANNEL_VIDEO CHANNEL8 +#define CHANNEL_HEADLESS CHANNEL9 +#define CHANNEL_RTH CHANNEL10 + +enum { + MJXq_INIT1 = 0, + MJXq_BIND1, + MJXq_DATA +}; + +static u8 tx_power; +static s8 fine; +static u16 counter; +static u8 phase; +static u8 tx_power; +static u8 rf_chan; +static u8 txid[3]; +static u8 packet[PACKET_SIZE]; +static u8 rf_channels[RF_NUM_CHANNELS]; + +// dumped from E010 and H36 stock transmitters +static const struct { + u8 txid[2]; + u8 rfchan[RF_NUM_CHANNELS]; +} +e010_tx_rf_map[] = {{{0x4F, 0x1C}, {0x3A, 0x35, 0x4A, 0x45}}, + {{0x90, 0x1C}, {0x2E, 0x36, 0x3E, 0x46}}, + {{0x24, 0x36}, {0x32, 0x3E, 0x42, 0x4E}}, + {{0x7A, 0x40}, {0x2E, 0x3C, 0x3E, 0x4C}}, + {{0x61, 0x31}, {0x2F, 0x3B, 0x3F, 0x4B}}, + {{0x5D, 0x37}, {0x33, 0x3B, 0x43, 0x4B}}, + {{0xFD, 0x4F}, {0x33, 0x3B, 0x43, 0x4B}}, + {{0x86, 0x3C}, {0x34, 0x3E, 0x44, 0x4E}}}; + +// xn297 emulation +//////////////////// +static u8 xn297_addr_len; +static u8 xn297_tx_addr[5]; +static const u8 xn297_crc = 1; + +static const u8 xn297_scramble[] = { + 0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66, + 0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f, + 0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc, + 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, + 0x8e, 0xc5, 0x2f}; + +static const u16 xn297_crc_xorout[] = { + 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, + 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, + 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, + 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, + 0x2138, 0x129F, 0xB3A0, 0x2988}; + +static void XN297L_init() +{ + CC2500_Reset(); + CC2500_Strobe(CC2500_SIDLE); + + // Address Config = No address check + // Base Frequency = 2399.999268 + // CRC Autoflush = false + // CRC Enable = true + // Carrier Frequency = 2399.999268 + // Channel Number = 0 + // Channel Spacing = 333.251953 + // Data Format = Normal mode + // Data Rate = 249.939 + // Deviation = 126.953125 + // Device Address = 0 + // Manchester Enable = false + // Modulated = true + // Modulation Format = GFSK + // Packet Length = 255 + // Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word + // Preamble Count = 4 + // RX Filter BW = 203.125000 + // Sync Word Qualifier Mode = 30/32 sync word bits detected + // TX Power = 0 + // Whitening = false + // CC2500_WriteReg(CC2500_0002_IOCFG0,0x06); // GDO0Output Pin Configuration + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Packet Automation Control + CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte + CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x13); // Modem Configuration + CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration + CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration + CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting + CC2500_WriteReg(CC2500_18_MCSM0, 0x18); // Main Radio Control State Machine Configuration + CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration + CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration + CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control + CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control + CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control + CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration + CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration + + CC2500_SetTxRxMode(TX_EN); +} + +static u8 bit_reverse(uint8_t b_in) +{ + uint8_t b_out = 0; + for (u8 i = 0; i < 8; ++i) { + b_out = (b_out << 1) | (b_in & 1); + b_in >>= 1; + } + return b_out; +} + +static const u16 initial = 0xb5d2; + +static void XN297L_SetTXAddr(const u8* addr, u8 len) +{ + if (len > 5) len = 5; + if (len < 3) len = 3; + xn297_addr_len = len; + memcpy(xn297_tx_addr, addr, len); +} + + +static void XN297L_WritePayload(const u8* msg, u8 len) +{ + u8 buf[32]; + u8 last = 0; + u8 i; + + for (i = 0; i < xn297_addr_len; ++i) { + buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; + } + + for (i = 0; i < len; ++i) { + // bit-reverse bytes in packet + u8 b_out = bit_reverse(msg[i]); + buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; + } + if (xn297_crc) { + u8 offset = xn297_addr_len < 4 ? 1 : 0; + u16 crc = initial; + for (u8 i = offset; i < last; ++i) { + crc = crc16_update(crc, buf[i], 8); + } + crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len]; + buf[last++] = crc >> 8; + buf[last++] = crc & 0xff; + } + + // stop TX/RX + CC2500_Strobe(CC2500_SIDLE); + // flush tx FIFO + CC2500_Strobe(CC2500_SFTX); + // xn297L preamble + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); + // xn297 packet + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); + // transmit + CC2500_Strobe(CC2500_STX); +} + +// end of xn297 emulation +/////////////////////////// + +// Bit vector from bit position +#define BV(bit) (1 << bit) + +static u8 checksum() +{ + u8 sum = packet[0]; + for (int i=1; i < PACKET_SIZE-1; i++) sum += packet[i]; + return sum; +} + +#define BABS(X) (((X) < 0) ? -(u8)(X) : (X)) +#define LIMIT_CHAN(X) (X < CHAN_MIN_VALUE ? CHAN_MIN_VALUE : (X > CHAN_MAX_VALUE ? CHAN_MAX_VALUE : X)) +// Channel values are sign + magnitude 8bit values +static u8 convert_channel(u8 num) +{ + s32 ch = LIMIT_CHAN(Channels[num]); + return (u8) ((ch < 0 ? 0x80 : 0) | BABS(ch * 127 / CHAN_MAX_VALUE)); +} + +#define GET_FLAG(ch, mask) (Channels[ch] > 0 ? mask : 0) +#define GET_FLAG_INV(ch, mask) (Channels[ch] < 0 ? mask : 0) +#define CHAN2TRIM(X) (((X) & 0x80 ? (X) : 0x7f - (X)) >> 1) +static void send_packet(u8 bind) +{ + packet[0] = convert_channel(CHANNEL3); // throttle + packet[0] = packet[0] & 0x80 ? 0xff - packet[0] : 0x80 + packet[0]; + packet[1] = convert_channel(CHANNEL4); // rudder + packet[4] = 0x40; // rudder does not work well with dyntrim + packet[2] = 0x80 ^ convert_channel(CHANNEL2); // elevator + // driven trims cause issues when headless is enabled + packet[5] = GET_FLAG(CHANNEL_HEADLESS, 1) ? 0x40 : CHAN2TRIM(packet[2]); // trim elevator + packet[3] = convert_channel(CHANNEL1); // aileron + packet[6] = GET_FLAG(CHANNEL_HEADLESS, 1) ? 0x40 : CHAN2TRIM(packet[3]); // trim aileron + packet[7] = txid[0]; + packet[8] = txid[1]; + packet[9] = txid[2]; + packet[10] = 0; // overwritten below for feature bits + packet[11] = 0; + packet[12] = 0; + packet[13] = 0; + packet[14] = 0xc0; // bind value + + packet[10] += GET_FLAG(CHANNEL_RTH, 0x02) + | GET_FLAG(CHANNEL_HEADLESS, 0x01); + if (!bind) { + packet[14] = 0x04 + | GET_FLAG(CHANNEL_FLIP, 0x01) + | GET_FLAG(CHANNEL_PICTURE, 0x08) + | GET_FLAG(CHANNEL_VIDEO, 0x10) + | GET_FLAG_INV(CHANNEL_LED, 0x20); // air/ground mode + if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_PHOENIX) { + packet[10] |= 0x20 // high rate + | GET_FLAG(CHANNEL_ARM, 0x80); + packet[14] &= ~0x24; + } + } + + packet[15] = checksum(); + + // NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channels[rf_chan++ / 2]); + + // spacing is 333.25 Mhz, must multiply xn297 channel by 3 + CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[rf_chan++ / 2] * 3); + rf_chan %= 2 * sizeof(rf_channels); // channels repeated + + // NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); + // NRF24L01_FlushTx(); + + // Make sure that the radio is in IDLE state before flushing the FIFO + CC2500_Strobe(CC2500_SIDLE); + // Flush TX FIFO + CC2500_Strobe(CC2500_SFTX); + + // Power on, TX mode, 2byte CRC + // XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); + XN297L_WritePayload(packet, PACKET_SIZE); + + // Check and adjust transmission power. We do this after + // transmission to not bother with timeout after power + // settings change - we have plenty of time until next + // packet. + if (tx_power != Model.tx_power) { + //Keep transmit power updated + tx_power = Model.tx_power; + CC2500_SetPower(tx_power); + } +} + +static void mjxq_init() +{ + u8 rx_tx_addr[ADDRESS_LENGTH]; + + XN297L_init(); // setup cc2500 for xn297L@250kbps emulation + CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); + memcpy(rx_tx_addr, "\x6d\x6a\x77\x77\x77", sizeof(rx_tx_addr)); + memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); + XN297L_SetTXAddr(rx_tx_addr, sizeof(rx_tx_addr)); + CC2500_SetPower(tx_power); +} + +static void mjxq_init2() +{ + memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); +} + +static u16 e010_callback() +{ + switch (phase) { + case MJXq_INIT1: + phase = MJXq_BIND1; + break; + + case MJXq_BIND1: + if (counter == 0) { + mjxq_init2(); + phase = MJXq_DATA; + PROTOCOL_SetBindState(0); + } else { + send_packet(1); + counter -= 1; + } + break; + + case MJXq_DATA: + if (fine != (s8)Model.proto_opts[PROTOOPTS_FREQFINE]) { + fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; + CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); + } + send_packet(0); + break; + } + return PACKET_PERIOD; +} + +static void initialize_txid() +{ + memcpy(txid, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].txid, 2); + txid[2] = 0x00; +} + +static void initialize() +{ + CLOCK_StopTimer(); + tx_power = Model.tx_power; + fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; + counter = BIND_COUNT; + initialize_txid(); + mjxq_init(); + phase = MJXq_INIT1; + + PROTOCOL_SetBindState(BIND_COUNT * PACKET_PERIOD / 1000); + + CLOCK_StartTimer(INITIAL_WAIT, e010_callback); +} + +uintptr_t E010_Cmds(enum ProtoCmds cmd) +{ + switch(cmd) { + case PROTOCMD_INIT: initialize(0); return 0; + case PROTOCMD_DEINIT: + case PROTOCMD_RESET: + CLOCK_StopTimer(); + return (CC2500_Reset() ? 1 : -1); + case PROTOCMD_CHECK_AUTOBIND: return 0; //Never Autobind + case PROTOCMD_BIND: initialize(1); return 0; + case PROTOCMD_NUMCHAN: return 8; + case PROTOCMD_DEFAULT_NUMCHAN: return 8; + case PROTOCMD_CURRENT_ID: return Model.fixed_id; + case PROTOCMD_GETOPTIONS: return (uintptr_t)e010_opts; + case PROTOCMD_TELEMETRYSTATE: return PROTO_TELEM_UNSUPPORTED; + case PROTOCMD_CHANNELMAP: return AETRG; + default: break; + } + return 0; +} + +#endif diff --git a/src/protocol/protocol.h b/src/protocol/protocol.h index e7a089cc98..bffd0c075a 100644 --- a/src/protocol/protocol.h +++ b/src/protocol/protocol.h @@ -28,6 +28,7 @@ PROTODEF(PROTOCOL_SKYARTEC, CC2500, AETRG, SKYARTEC_Cmds, "Skyartec") PROTODEF(PROTOCOL_SFHSS, CC2500, AETRG, SFHSS_Cmds, "S-FHSS") PROTODEF(PROTOCOL_CORONA, CC2500, AETRG, Corona_Cmds, "Corona") PROTODEF(PROTOCOL_HITEC, CC2500, AETRG, Hitec_Cmds, "Hitec") +PROTODEF(PROTOCOL_E010, CC2500, AETRG, E010_Cmds, "E010") #endif //PROTO_HAS_CC2500 #ifdef PROTO_HAS_NRF24L01 PROTODEF(PROTOCOL_V202, NRF24L01, AETRG, V202_Cmds, "V202") From 00001c264acad0e63b2398e6a9aee5b778d1e26b Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 15:52:08 +0200 Subject: [PATCH 08/31] Fix lint --- src/protocol/e010_cc2500.c | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 2c102b0dc5..9ea1b7de8c 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -32,7 +32,7 @@ // printf inside an interrupt handler is really dangerous // this shouldn't be enabled even in debug builds without explicitly // turning it on - #define dbgprintf if(0) printf + #define dbgprintf if (0) printf #endif #define INITIAL_WAIT 500 @@ -91,7 +91,7 @@ static s8 fine; static u16 counter; static u8 phase; static u8 tx_power; -static u8 rf_chan; +static u8 rf_chan; static u8 txid[3]; static u8 packet[PACKET_SIZE]; static u8 rf_channels[RF_NUM_CHANNELS]; @@ -102,12 +102,12 @@ static const struct { u8 rfchan[RF_NUM_CHANNELS]; } e010_tx_rf_map[] = {{{0x4F, 0x1C}, {0x3A, 0x35, 0x4A, 0x45}}, - {{0x90, 0x1C}, {0x2E, 0x36, 0x3E, 0x46}}, + {{0x90, 0x1C}, {0x2E, 0x36, 0x3E, 0x46}}, {{0x24, 0x36}, {0x32, 0x3E, 0x42, 0x4E}}, {{0x7A, 0x40}, {0x2E, 0x3C, 0x3E, 0x4C}}, {{0x61, 0x31}, {0x2F, 0x3B, 0x3F, 0x4B}}, {{0x5D, 0x37}, {0x33, 0x3B, 0x43, 0x4B}}, - {{0xFD, 0x4F}, {0x33, 0x3B, 0x43, 0x4B}}, + {{0xFD, 0x4F}, {0x33, 0x3B, 0x43, 0x4B}}, {{0x86, 0x3C}, {0x34, 0x3E, 0x44, 0x4E}}}; // xn297 emulation @@ -122,12 +122,12 @@ static const u8 xn297_scramble[] = { 0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc, 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, 0x8e, 0xc5, 0x2f}; - + static const u16 xn297_crc_xorout[] = { - 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, + 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, - 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, + 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, 0x2138, 0x129F, 0xB3A0, 0x2988}; static void XN297L_init() @@ -179,7 +179,7 @@ static void XN297L_init() CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration - + CC2500_SetTxRxMode(TX_EN); } @@ -209,7 +209,7 @@ static void XN297L_WritePayload(const u8* msg, u8 len) u8 buf[32]; u8 last = 0; u8 i; - + for (i = 0; i < xn297_addr_len; ++i) { buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; } @@ -229,7 +229,7 @@ static void XN297L_WritePayload(const u8* msg, u8 len) buf[last++] = crc >> 8; buf[last++] = crc & 0xff; } - + // stop TX/RX CC2500_Strobe(CC2500_SIDLE); // flush tx FIFO @@ -275,9 +275,9 @@ static void send_packet(u8 bind) packet[4] = 0x40; // rudder does not work well with dyntrim packet[2] = 0x80 ^ convert_channel(CHANNEL2); // elevator // driven trims cause issues when headless is enabled - packet[5] = GET_FLAG(CHANNEL_HEADLESS, 1) ? 0x40 : CHAN2TRIM(packet[2]); // trim elevator + packet[5] = GET_FLAG(CHANNEL_HEADLESS, 1) ? 0x40 : CHAN2TRIM(packet[2]); // trim elevator packet[3] = convert_channel(CHANNEL1); // aileron - packet[6] = GET_FLAG(CHANNEL_HEADLESS, 1) ? 0x40 : CHAN2TRIM(packet[3]); // trim aileron + packet[6] = GET_FLAG(CHANNEL_HEADLESS, 1) ? 0x40 : CHAN2TRIM(packet[3]); // trim aileron packet[7] = txid[0]; packet[8] = txid[1]; packet[9] = txid[2]; @@ -286,7 +286,7 @@ static void send_packet(u8 bind) packet[12] = 0; packet[13] = 0; packet[14] = 0xc0; // bind value - + packet[10] += GET_FLAG(CHANNEL_RTH, 0x02) | GET_FLAG(CHANNEL_HEADLESS, 0x01); if (!bind) { @@ -294,30 +294,30 @@ static void send_packet(u8 bind) | GET_FLAG(CHANNEL_FLIP, 0x01) | GET_FLAG(CHANNEL_PICTURE, 0x08) | GET_FLAG(CHANNEL_VIDEO, 0x10) - | GET_FLAG_INV(CHANNEL_LED, 0x20); // air/ground mode + | GET_FLAG_INV(CHANNEL_LED, 0x20); // air/ground mode if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_PHOENIX) { packet[10] |= 0x20 // high rate | GET_FLAG(CHANNEL_ARM, 0x80); packet[14] &= ~0x24; } } - + packet[15] = checksum(); // NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channels[rf_chan++ / 2]); - + // spacing is 333.25 Mhz, must multiply xn297 channel by 3 CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[rf_chan++ / 2] * 3); rf_chan %= 2 * sizeof(rf_channels); // channels repeated // NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // NRF24L01_FlushTx(); - + // Make sure that the radio is in IDLE state before flushing the FIFO CC2500_Strobe(CC2500_SIDLE); // Flush TX FIFO CC2500_Strobe(CC2500_SFTX); - + // Power on, TX mode, 2byte CRC // XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); XN297L_WritePayload(packet, PACKET_SIZE); @@ -327,7 +327,7 @@ static void send_packet(u8 bind) // settings change - we have plenty of time until next // packet. if (tx_power != Model.tx_power) { - //Keep transmit power updated + // Keep transmit power updated tx_power = Model.tx_power; CC2500_SetPower(tx_power); } @@ -346,7 +346,7 @@ static void mjxq_init() } static void mjxq_init2() -{ +{ memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); } @@ -396,19 +396,19 @@ static void initialize() phase = MJXq_INIT1; PROTOCOL_SetBindState(BIND_COUNT * PACKET_PERIOD / 1000); - + CLOCK_StartTimer(INITIAL_WAIT, e010_callback); } uintptr_t E010_Cmds(enum ProtoCmds cmd) { - switch(cmd) { + switch (cmd) { case PROTOCMD_INIT: initialize(0); return 0; case PROTOCMD_DEINIT: case PROTOCMD_RESET: CLOCK_StopTimer(); return (CC2500_Reset() ? 1 : -1); - case PROTOCMD_CHECK_AUTOBIND: return 0; //Never Autobind + case PROTOCMD_CHECK_AUTOBIND: return 1; case PROTOCMD_BIND: initialize(1); return 0; case PROTOCMD_NUMCHAN: return 8; case PROTOCMD_DEFAULT_NUMCHAN: return 8; From eee9559e2758cb81705855b071a99ac0f0791553 Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 16:50:54 +0200 Subject: [PATCH 09/31] Remove MJXq references --- src/protocol/e010_cc2500.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 9ea1b7de8c..9525cd4896 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -81,9 +81,9 @@ enum { #define CHANNEL_RTH CHANNEL10 enum { - MJXq_INIT1 = 0, - MJXq_BIND1, - MJXq_DATA + E010_INIT1 = 0, + E010_BIND1, + E010_DATA }; static u8 tx_power; @@ -333,7 +333,7 @@ static void send_packet(u8 bind) } } -static void mjxq_init() +static void e010_init() { u8 rx_tx_addr[ADDRESS_LENGTH]; @@ -345,7 +345,7 @@ static void mjxq_init() CC2500_SetPower(tx_power); } -static void mjxq_init2() +static void e010_init2() { memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); } @@ -353,14 +353,14 @@ static void mjxq_init2() static u16 e010_callback() { switch (phase) { - case MJXq_INIT1: - phase = MJXq_BIND1; + case E010_INIT1: + phase = E010_BIND1; break; - case MJXq_BIND1: + case E010_BIND1: if (counter == 0) { - mjxq_init2(); - phase = MJXq_DATA; + e010_init2(); + phase = E010_DATA; PROTOCOL_SetBindState(0); } else { send_packet(1); @@ -368,7 +368,7 @@ static u16 e010_callback() } break; - case MJXq_DATA: + case E010_DATA: if (fine != (s8)Model.proto_opts[PROTOOPTS_FREQFINE]) { fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); @@ -392,8 +392,8 @@ static void initialize() fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; counter = BIND_COUNT; initialize_txid(); - mjxq_init(); - phase = MJXq_INIT1; + e010_init(); + phase = E010_INIT1; PROTOCOL_SetBindState(BIND_COUNT * PACKET_PERIOD / 1000); From 0f234ec209952e33be39affff698707e6f2219ad Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 17:00:31 +0200 Subject: [PATCH 10/31] Cleanup --- src/protocol/e010_cc2500.c | 47 ++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 9525cd4896..dadf541640 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -156,29 +156,29 @@ static void XN297L_init() // Sync Word Qualifier Mode = 30/32 sync word bits detected // TX Power = 0 // Whitening = false - // CC2500_WriteReg(CC2500_0002_IOCFG0,0x06); // GDO0Output Pin Configuration + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Packet Automation Control - CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control - CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control - CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte - CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte - CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte - CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration - CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration - CC2500_WriteReg(CC2500_12_MDMCFG2, 0x13); // Modem Configuration - CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration - CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration - CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting - CC2500_WriteReg(CC2500_18_MCSM0, 0x18); // Main Radio Control State Machine Configuration - CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration - CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration + CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte + CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x13); // Modem Configuration + CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration + CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration + CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting + CC2500_WriteReg(CC2500_18_MCSM0, 0x18); // Main Radio Control State Machine Configuration + CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration + CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control - CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration - CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration - CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration - CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration + CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration CC2500_SetTxRxMode(TX_EN); } @@ -304,22 +304,15 @@ static void send_packet(u8 bind) packet[15] = checksum(); - // NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channels[rf_chan++ / 2]); - - // spacing is 333.25 Mhz, must multiply xn297 channel by 3 + // spacing is 333.25 kHz, must multiply xn297 channel by 3 CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[rf_chan++ / 2] * 3); rf_chan %= 2 * sizeof(rf_channels); // channels repeated - // NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); - // NRF24L01_FlushTx(); - // Make sure that the radio is in IDLE state before flushing the FIFO CC2500_Strobe(CC2500_SIDLE); // Flush TX FIFO CC2500_Strobe(CC2500_SFTX); - // Power on, TX mode, 2byte CRC - // XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); XN297L_WritePayload(packet, PACKET_SIZE); // Check and adjust transmission power. We do this after From 58ed1a83af0dec715360c255f13f81a8eda24472 Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 21:08:29 +0200 Subject: [PATCH 11/31] Disable cc2500 crc --- src/protocol/e010_cc2500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index dadf541640..e928aae50a 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -138,7 +138,7 @@ static void XN297L_init() // Address Config = No address check // Base Frequency = 2399.999268 // CRC Autoflush = false - // CRC Enable = true + // CRC Enable = false // Carrier Frequency = 2399.999268 // Channel Number = 0 // Channel Spacing = 333.251953 @@ -157,7 +157,7 @@ static void XN297L_init() // TX Power = 0 // Whitening = false - CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Packet Automation Control + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte From aa8744b684105f8bf62d529034f4fbd39b50babf Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 21:11:47 +0200 Subject: [PATCH 12/31] Set cc2500 packet length --- src/protocol/e010_cc2500.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index e928aae50a..fabaee4c37 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -234,6 +234,8 @@ static void XN297L_WritePayload(const u8* msg, u8 len) CC2500_Strobe(CC2500_SIDLE); // flush tx FIFO CC2500_Strobe(CC2500_SFTX); + // packet length + CC2500_WriteRegister(CC2500_3F_TXFIFO, last + 4); // xn297L preamble CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); // xn297 packet From 86994217f496af73435a2294dc2d6010a75471d8 Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 21:15:43 +0200 Subject: [PATCH 13/31] Fix typo --- src/protocol/e010_cc2500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index fabaee4c37..53661fa496 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -235,7 +235,7 @@ static void XN297L_WritePayload(const u8* msg, u8 len) // flush tx FIFO CC2500_Strobe(CC2500_SFTX); // packet length - CC2500_WriteRegister(CC2500_3F_TXFIFO, last + 4); + CC2500_WriteReg(CC2500_3F_TXFIFO, last + 4); // xn297L preamble CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); // xn297 packet From 770772448a6238f3a64c530b456fdf1372f42c57 Mon Sep 17 00:00:00 2001 From: Goebish Date: Tue, 16 Apr 2019 22:43:38 +0200 Subject: [PATCH 14/31] Disable cc2500 preamble and syncword --- src/protocol/e010_cc2500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 53661fa496..5218301f84 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -153,7 +153,7 @@ static void XN297L_init() // Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word // Preamble Count = 4 // RX Filter BW = 203.125000 - // Sync Word Qualifier Mode = 30/32 sync word bits detected + // Sync Word Qualifier Mode = No preamble/sync // TX Power = 0 // Whitening = false @@ -165,7 +165,7 @@ static void XN297L_init() CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration - CC2500_WriteReg(CC2500_12_MDMCFG2, 0x13); // Modem Configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x11); // Modem Configuration CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting From 013d92fdceba9f42178bff2277e183c6c4ae3721 Mon Sep 17 00:00:00 2001 From: Goebish Date: Wed, 17 Apr 2019 00:17:12 +0200 Subject: [PATCH 15/31] Calibrate cc2500 rf channels for faster hopping --- src/protocol/e010_cc2500.c | 78 ++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 5218301f84..6bf31ed708 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -81,8 +81,7 @@ enum { #define CHANNEL_RTH CHANNEL10 enum { - E010_INIT1 = 0, - E010_BIND1, + E010_BIND = 0, E010_DATA }; @@ -95,6 +94,9 @@ static u8 rf_chan; static u8 txid[3]; static u8 packet[PACKET_SIZE]; static u8 rf_channels[RF_NUM_CHANNELS]; +static u8 calibration[RF_NUM_CHANNELS]; +static u8 calibration_fscal2; +static u8 calibration_fscal3; // dumped from E010 and H36 stock transmitters static const struct { @@ -306,8 +308,12 @@ static void send_packet(u8 bind) packet[15] = checksum(); + rf_chan++; + CC2500_WriteReg(CC2500_23_FSCAL3, calibration_fscal3); + CC2500_WriteReg(CC2500_24_FSCAL2, calibration_fscal2); + CC2500_WriteReg(CC2500_25_FSCAL1, calibration[rf_chan / 2]); // spacing is 333.25 kHz, must multiply xn297 channel by 3 - CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[rf_chan++ / 2] * 3); + CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[rf_chan / 2] * 3); rf_chan %= 2 * sizeof(rf_channels); // channels repeated // Make sure that the radio is in IDLE state before flushing the FIFO @@ -328,48 +334,56 @@ static void send_packet(u8 bind) } } +static void calibrate_rf_chans() +{ + for (int c = 0; c < RF_NUM_CHANNELS; c++) { + CLOCK_ResetWatchdog(); + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[c] * 3); + CC2500_Strobe(CC2500_SCAL); + usleep(900); + calibration[c] = CC2500_ReadReg(CC2500_25_FSCAL1); + } + calibration_fscal3 = CC2500_ReadReg(CC2500_23_FSCAL3); // only needs to be done once + calibration_fscal2 = CC2500_ReadReg(CC2500_24_FSCAL2); // only needs to be done once + CC2500_Strobe(CC2500_SIDLE); +} + + static void e010_init() { u8 rx_tx_addr[ADDRESS_LENGTH]; - XN297L_init(); // setup cc2500 for xn297L@250kbps emulation CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); memcpy(rx_tx_addr, "\x6d\x6a\x77\x77\x77", sizeof(rx_tx_addr)); memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); XN297L_SetTXAddr(rx_tx_addr, sizeof(rx_tx_addr)); CC2500_SetPower(tx_power); -} - -static void e010_init2() -{ - memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); + calibrate_rf_chans(); } static u16 e010_callback() { switch (phase) { - case E010_INIT1: - phase = E010_BIND1; - break; - - case E010_BIND1: - if (counter == 0) { - e010_init2(); - phase = E010_DATA; - PROTOCOL_SetBindState(0); - } else { - send_packet(1); - counter -= 1; - } - break; - - case E010_DATA: - if (fine != (s8)Model.proto_opts[PROTOOPTS_FREQFINE]) { - fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; - CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); - } - send_packet(0); - break; + case E010_BIND: + if (counter == 0) { + memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); + calibrate_rf_chans(); + phase = E010_DATA; + PROTOCOL_SetBindState(0); + } else { + send_packet(1); + counter -= 1; + } + break; + + case E010_DATA: + if (fine != (s8)Model.proto_opts[PROTOOPTS_FREQFINE]) { + fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; + CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); + } + send_packet(0); + break; } return PACKET_PERIOD; } @@ -388,7 +402,7 @@ static void initialize() counter = BIND_COUNT; initialize_txid(); e010_init(); - phase = E010_INIT1; + phase = E010_BIND; PROTOCOL_SetBindState(BIND_COUNT * PACKET_PERIOD / 1000); From e47d502eaf11f1d6f2934208ce70773c3cc917a5 Mon Sep 17 00:00:00 2001 From: Goebish Date: Wed, 17 Apr 2019 03:06:35 +0200 Subject: [PATCH 16/31] Adjust packet size --- src/protocol/e010_cc2500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 6bf31ed708..18b45e7c0d 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -237,7 +237,7 @@ static void XN297L_WritePayload(const u8* msg, u8 len) // flush tx FIFO CC2500_Strobe(CC2500_SFTX); // packet length - CC2500_WriteReg(CC2500_3F_TXFIFO, last + 4); + CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); // xn297L preamble CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); // xn297 packet From 9b173247155bbbb03a8c70e5a33c4faa387f442e Mon Sep 17 00:00:00 2001 From: Goebish Date: Wed, 17 Apr 2019 12:07:22 +0200 Subject: [PATCH 17/31] Disable cc2500 preamble / syncword --- src/protocol/e010_cc2500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 18b45e7c0d..0bc90feed8 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -167,7 +167,7 @@ static void XN297L_init() CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration - CC2500_WriteReg(CC2500_12_MDMCFG2, 0x11); // Modem Configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting From eb2844d6e14a18b7aae5e2e94e8874cccd30f0a3 Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 18 Apr 2019 20:55:57 +0200 Subject: [PATCH 18/31] Start moving xn297 emulation logic --- src/protocol/e010_cc2500.c | 84 ++------------------------------- src/protocol/iface_cc2500.h | 6 +++ src/protocol/iface_nrf24l01.h | 7 +++ src/protocol/spi/cc2500.c | 59 ++++++++++++++++++++++++ src/protocol/spi/nrf24l01.c | 70 +--------------------------- src/protocol/spi/xn297_emu.c | 87 +++++++++++++++++++++++++++++++++++ 6 files changed, 164 insertions(+), 149 deletions(-) create mode 100644 src/protocol/spi/xn297_emu.c diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 0bc90feed8..da149a0502 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -116,84 +116,7 @@ e010_tx_rf_map[] = {{{0x4F, 0x1C}, {0x3A, 0x35, 0x4A, 0x45}}, //////////////////// static u8 xn297_addr_len; static u8 xn297_tx_addr[5]; -static const u8 xn297_crc = 1; - -static const u8 xn297_scramble[] = { - 0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66, - 0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f, - 0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc, - 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, - 0x8e, 0xc5, 0x2f}; - -static const u16 xn297_crc_xorout[] = { - 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, - 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, - 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, - 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, - 0x2138, 0x129F, 0xB3A0, 0x2988}; - -static void XN297L_init() -{ - CC2500_Reset(); - CC2500_Strobe(CC2500_SIDLE); - - // Address Config = No address check - // Base Frequency = 2399.999268 - // CRC Autoflush = false - // CRC Enable = false - // Carrier Frequency = 2399.999268 - // Channel Number = 0 - // Channel Spacing = 333.251953 - // Data Format = Normal mode - // Data Rate = 249.939 - // Deviation = 126.953125 - // Device Address = 0 - // Manchester Enable = false - // Modulated = true - // Modulation Format = GFSK - // Packet Length = 255 - // Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word - // Preamble Count = 4 - // RX Filter BW = 203.125000 - // Sync Word Qualifier Mode = No preamble/sync - // TX Power = 0 - // Whitening = false - - CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control - CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control - CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control - CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte - CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte - CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte - CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration - CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration - CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration - CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration - CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration - CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting - CC2500_WriteReg(CC2500_18_MCSM0, 0x18); // Main Radio Control State Machine Configuration - CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration - CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration - CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control - CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control - CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control - CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration - CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration - CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration - CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration - - CC2500_SetTxRxMode(TX_EN); -} - -static u8 bit_reverse(uint8_t b_in) -{ - uint8_t b_out = 0; - for (u8 i = 0; i < 8; ++i) { - b_out = (b_out << 1) | (b_in & 1); - b_in >>= 1; - } - return b_out; -} +//static const u8 xn297_crc = 1; static const u16 initial = 0xb5d2; @@ -205,7 +128,6 @@ static void XN297L_SetTXAddr(const u8* addr, u8 len) memcpy(xn297_tx_addr, addr, len); } - static void XN297L_WritePayload(const u8* msg, u8 len) { u8 buf[32]; @@ -227,7 +149,7 @@ static void XN297L_WritePayload(const u8* msg, u8 len) for (u8 i = offset; i < last; ++i) { crc = crc16_update(crc, buf[i], 8); } - crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len]; + crc ^= xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]; buf[last++] = crc >> 8; buf[last++] = crc & 0xff; } @@ -353,7 +275,7 @@ static void calibrate_rf_chans() static void e010_init() { u8 rx_tx_addr[ADDRESS_LENGTH]; - XN297L_init(); // setup cc2500 for xn297L@250kbps emulation + XN297L_init(1,1); // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); memcpy(rx_tx_addr, "\x6d\x6a\x77\x77\x77", sizeof(rx_tx_addr)); memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); diff --git a/src/protocol/iface_cc2500.h b/src/protocol/iface_cc2500.h index 4e8f645671..c925aabf97 100644 --- a/src/protocol/iface_cc2500.h +++ b/src/protocol/iface_cc2500.h @@ -135,4 +135,10 @@ void CC2500_WriteData(u8 *packet, u8 length); void CC2500_ReadData(u8 *dpbuffer, int len); void CC2500_SetTxRxMode(enum TXRX_State); void CC2500_SetPower(int power); + +//---------------------------------------------------------------------------------- +// XN297L emulation +//---------------------------------------------------------------------------------- +void XN297L_init(u8 scramble_en, u8 crc_en); + #endif diff --git a/src/protocol/iface_nrf24l01.h b/src/protocol/iface_nrf24l01.h index d7e500eb9f..3976cd9e2d 100644 --- a/src/protocol/iface_nrf24l01.h +++ b/src/protocol/iface_nrf24l01.h @@ -142,6 +142,13 @@ enum { XN297_SCRAMBLED }; +extern const u8 xn297_scramble[]; +extern const u16 xn297_crc_xorout_scrambled[]; +extern const u16 xn297_crc_xorout[]; +extern u8 xn297_crc; +extern u8 xn297_scramble_enabled; +uint8_t bit_reverse(uint8_t b_in); + void XN297_SetTXAddr(const u8* addr, int len); void XN297_SetRXAddr(const u8* addr, int len); void XN297_Configure(u8 flags); diff --git a/src/protocol/spi/cc2500.c b/src/protocol/spi/cc2500.c index 9d0028d16a..78bc05568a 100644 --- a/src/protocol/spi/cc2500.c +++ b/src/protocol/spi/cc2500.c @@ -140,4 +140,63 @@ int CC2500_Reset() CC2500_SetTxRxMode(TXRX_OFF); return CC2500_ReadReg(CC2500_0E_FREQ1) == 0xC4; } + +// xn297 emulation + +// setup CC2500 for XN297L @ 250 kbps emulation +void XN297L_init(u8 scramble_en, u8 crc_en) +{ + // Address Config = No address check + // Base Frequency = 2399.999268 + // CRC Autoflush = false + // CRC Enable = false + // Carrier Frequency = 2399.999268 + // Channel Number = 0 + // Channel Spacing = 333.251953 + // Data Format = Normal mode + // Data Rate = 249.939 + // Deviation = 126.953125 + // Device Address = 0 + // Manchester Enable = false + // Modulated = true + // Modulation Format = GFSK + // Packet Length = 255 + // Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word + // Preamble Count = 4 + // RX Filter BW = 203.125000 + // Sync Word Qualifier Mode = No preamble/sync + // TX Power = 0 + // Whitening = false + + CC2500_Reset(); + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control + CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control + CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte + CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration + CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration + CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration + CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting + CC2500_WriteReg(CC2500_18_MCSM0, 0x18); // Main Radio Control State Machine Configuration + CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration + CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration + CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control + CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control + CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control + CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration + CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration + + CC2500_SetTxRxMode(TX_EN); + + XN297_SetScrambledMode(scramble_en); + xn297_crc = crc_en; +} + #endif diff --git a/src/protocol/spi/nrf24l01.c b/src/protocol/spi/nrf24l01.c index a590a095e0..fe1f3eb3d1 100644 --- a/src/protocol/spi/nrf24l01.c +++ b/src/protocol/spi/nrf24l01.c @@ -272,76 +272,15 @@ int NRF24L01_Reset() // // XN297 emulation layer ////////////////////////// -static u8 xn297_scramble_enabled; +//static u8 xn297_scramble_enabled; static int xn297_addr_len; static u8 xn297_tx_addr[5]; static u8 xn297_rx_addr[5]; -static u8 xn297_crc = 0; - -static const uint8_t xn297_scramble[] = { - 0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66, - 0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f, - 0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc, - 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, - 0x8e, 0xc5, 0x2f}; - -FLASHWORDTABLE xn297_crc_xorout_scrambled[] = { - 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, - 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, - 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, - 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, - 0x2138, 0x129F, 0xB3A0, 0x2988}; - -FLASHWORDTABLE xn297_crc_xorout[] = { - 0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf, - 0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15, - 0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9, - 0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7, - 0xb798, 0x5133, 0x67db, 0xd94e}; - - -#if defined(__GNUC__) && defined(__ARM_ARCH_ISA_THUMB) && (__ARM_ARCH_ISA_THUMB==2) -// rbit instruction works on cortex m3 -uint32_t __RBIT_(uint32_t in) -{ - uint32_t out=0; - __asm volatile ("rbit %0, %1" : "=r" (out) : "r" (in) ); - return(out); -} +//static u8 xn297_crc = 0; -static uint8_t bit_reverse(uint8_t a) -{ - return __RBIT_( (unsigned int) a)>>24; -} -#else -static uint8_t bit_reverse(uint8_t b_in) -{ - uint8_t b_out = 0; - for (int i = 0; i < 8; ++i) { - b_out = (b_out << 1) | (b_in & 1); - b_in >>= 1; - } - return b_out; -} -#endif -static const uint16_t polynomial = 0x1021; static const uint16_t initial = 0xb5d2; -u16 crc16_update(u16 crc, u8 a, u8 bits) -{ - crc ^= a << 8; - while (bits--) { - if (crc & 0x8000) { - crc = (crc << 1) ^ polynomial; - } else { - crc = crc << 1; - } - } - return crc; -} - - void XN297_SetTXAddr(const u8* addr, int len) { if (len > 5) len = 5; @@ -389,11 +328,6 @@ void XN297_Configure(u8 flags) NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xff); } -void XN297_SetScrambledMode(const u8 mode) -{ - xn297_scramble_enabled = mode; -} - u8 XN297_WritePayload(u8* msg, int len) { u8 packet[32]; diff --git a/src/protocol/spi/xn297_emu.c b/src/protocol/spi/xn297_emu.c new file mode 100644 index 0000000000..92c553c931 --- /dev/null +++ b/src/protocol/spi/xn297_emu.c @@ -0,0 +1,87 @@ +/* + This project is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Deviation is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Deviation. If not, see . +*/ + +#include "common.h" + +//static u8 packet[32]; + +u8 xn297_crc; +u8 xn297_scramble_enabled; // should be 1 by default ... but can't init static in modular + +const u8 xn297_scramble[] = { + 0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66, + 0x0d, 0xae, 0x8c, 0x88, 0x12, 0x69, 0xee, 0x1f, + 0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc, + 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, + 0x8e, 0xc5, 0x2f}; + +const u16 xn297_crc_xorout_scrambled[] = { + 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, + 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, + 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, + 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, + 0x2138, 0x129F, 0xB3A0, 0x2988}; + +const u16 xn297_crc_xorout[] = { + 0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf, + 0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15, + 0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9, + 0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7, + 0xb798, 0x5133, 0x67db, 0xd94e}; + +#if defined(__GNUC__) && defined(__ARM_ARCH_ISA_THUMB) && (__ARM_ARCH_ISA_THUMB==2) +// rbit instruction works on cortex m3 +static u32 __RBIT_(u32 in) +{ + u32 out=0; + __asm volatile ("rbit %0, %1" : "=r" (out) : "r" (in) ); + return(out); +} + +u8 bit_reverse(u8 b_in) +{ + return __RBIT_( (unsigned int) b_in)>>24; +} +#else +u8 bit_reverse(u8 b_in) +{ + u8 b_out = 0; + for (int i = 0; i < 8; ++i) { + b_out = (b_out << 1) | (b_in & 1); + b_in >>= 1; + } + return b_out; +} +#endif + +static const uint16_t polynomial = 0x1021; + +u16 crc16_update(u16 crc, u8 a, u8 bits) +{ + crc ^= a << 8; + while (bits--) { + if (crc & 0x8000) { + crc = (crc << 1) ^ polynomial; + } else { + crc = crc << 1; + } + } + return crc; +} + +void XN297_SetScrambledMode(const u8 mode) +{ + xn297_scramble_enabled = mode; +} From 78e85a24e18a9376d2f819e85c2c1c6e8cb7fdc8 Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 18 Apr 2019 21:37:40 +0200 Subject: [PATCH 19/31] Explicit XN297 scramble mode --- src/protocol/bayang_nrf24l01.c | 1 + src/protocol/bugs3mini_nrf24l01.c | 1 + src/protocol/cg023_nrf24l01.c | 1 + src/protocol/cx10_nrf24l01.c | 1 + src/protocol/dm002_nrf24l01.c | 1 + src/protocol/e010_cc2500.c | 2 +- src/protocol/e016h_nrf24l01.c | 1 + src/protocol/gd00x_nrf24l01.c | 1 + src/protocol/gw008_nrf24l01.c | 1 + src/protocol/h8_3d_nrf24l01.c | 1 + src/protocol/hontai_nrf24l01.c | 1 + src/protocol/iface_nrf24l01.h | 8 ++++---- src/protocol/mjxq_nrf24l01.c | 1 + src/protocol/mt99xx_nrf24l01.c | 2 ++ src/protocol/v911s_nrf24l01.c | 1 + 15 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/protocol/bayang_nrf24l01.c b/src/protocol/bayang_nrf24l01.c index cd2abc36f7..6822774e88 100644 --- a/src/protocol/bayang_nrf24l01.c +++ b/src/protocol/bayang_nrf24l01.c @@ -350,6 +350,7 @@ static int check_rx(void) static void bay_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); u8 bind_address[] = { 0, 0, 0, 0, 0 }; switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_REGULAR: diff --git a/src/protocol/bugs3mini_nrf24l01.c b/src/protocol/bugs3mini_nrf24l01.c index f282eec56d..f78dad60d1 100644 --- a/src/protocol/bugs3mini_nrf24l01.c +++ b/src/protocol/bugs3mini_nrf24l01.c @@ -138,6 +138,7 @@ static u8 checksum() static void bugs3mini_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); tx_power = Model.tx_power; NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); diff --git a/src/protocol/cg023_nrf24l01.c b/src/protocol/cg023_nrf24l01.c index 7521746b9f..81d98a0a58 100644 --- a/src/protocol/cg023_nrf24l01.c +++ b/src/protocol/cg023_nrf24l01.c @@ -219,6 +219,7 @@ static void send_packet(u8 bind) static void cg023_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); diff --git a/src/protocol/cx10_nrf24l01.c b/src/protocol/cx10_nrf24l01.c index 859186f3d3..8afdef829f 100644 --- a/src/protocol/cx10_nrf24l01.c +++ b/src/protocol/cx10_nrf24l01.c @@ -293,6 +293,7 @@ static void send_packet(u8 bind) static void cx10_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); diff --git a/src/protocol/dm002_nrf24l01.c b/src/protocol/dm002_nrf24l01.c index 2fa552291e..72d8d8e697 100644 --- a/src/protocol/dm002_nrf24l01.c +++ b/src/protocol/dm002_nrf24l01.c @@ -175,6 +175,7 @@ static void DM002_send_packet(u8 bind) static void DM002_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", DM002_ADDRESS_SIZE); diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index da149a0502..6944d1b81d 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -275,7 +275,7 @@ static void calibrate_rf_chans() static void e010_init() { u8 rx_tx_addr[ADDRESS_LENGTH]; - XN297L_init(1,1); // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled + XN297L_init(XN297_SCRAMBLED, XN297_CRC); // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); memcpy(rx_tx_addr, "\x6d\x6a\x77\x77\x77", sizeof(rx_tx_addr)); memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); diff --git a/src/protocol/e016h_nrf24l01.c b/src/protocol/e016h_nrf24l01.c index 2a4bf0b558..ff3dcf2b18 100644 --- a/src/protocol/e016h_nrf24l01.c +++ b/src/protocol/e016h_nrf24l01.c @@ -101,6 +101,7 @@ static u16 scale_channel(s32 chanval, s32 inMin, s32 inMax, u16 destMin, u16 des static void init_e016h() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_FlushTx(); NRF24L01_FlushRx(); diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_nrf24l01.c index e55cc84383..d174caaa4f 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_nrf24l01.c @@ -129,6 +129,7 @@ static void GD00X_send_packet() static void GD00X_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); XN297_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); diff --git a/src/protocol/gw008_nrf24l01.c b/src/protocol/gw008_nrf24l01.c index aaf7bb7599..c25f731410 100644 --- a/src/protocol/gw008_nrf24l01.c +++ b/src/protocol/gw008_nrf24l01.c @@ -127,6 +127,7 @@ static void send_packet(u8 bind) static void gw008_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); XN297_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); diff --git a/src/protocol/h8_3d_nrf24l01.c b/src/protocol/h8_3d_nrf24l01.c index 0149c223df..225b6d6112 100644 --- a/src/protocol/h8_3d_nrf24l01.c +++ b/src/protocol/h8_3d_nrf24l01.c @@ -357,6 +357,7 @@ static void send_packet(u8 bind) static void h8_3d_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); diff --git a/src/protocol/hontai_nrf24l01.c b/src/protocol/hontai_nrf24l01.c index 7e1b6fadce..9e64fc95d1 100644 --- a/src/protocol/hontai_nrf24l01.c +++ b/src/protocol/hontai_nrf24l01.c @@ -274,6 +274,7 @@ static void send_packet(u8 bind) static void ht_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); diff --git a/src/protocol/iface_nrf24l01.h b/src/protocol/iface_nrf24l01.h index 3976cd9e2d..e87bcadf7e 100644 --- a/src/protocol/iface_nrf24l01.h +++ b/src/protocol/iface_nrf24l01.h @@ -137,10 +137,10 @@ int NRF24L01_Reset(); //void NRF24L01_PulseCE(); // XN297 emulation layer -enum { - XN297_UNSCRAMBLED = 0, - XN297_SCRAMBLED -}; +#define XN297_UNSCRAMBLED 0 +#define XN297_SCRAMBLED 1 +#define XN297_NOCRC 0 +#define XN297_CRC 1 extern const u8 xn297_scramble[]; extern const u16 xn297_crc_xorout_scrambled[]; diff --git a/src/protocol/mjxq_nrf24l01.c b/src/protocol/mjxq_nrf24l01.c index 628801ffa1..d65db2c532 100644 --- a/src/protocol/mjxq_nrf24l01.c +++ b/src/protocol/mjxq_nrf24l01.c @@ -297,6 +297,7 @@ static void send_packet(u8 bind) static void mjxq_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); u8 rx_tx_addr[ADDRESS_LENGTH]; NRF24L01_Initialize(); diff --git a/src/protocol/mt99xx_nrf24l01.c b/src/protocol/mt99xx_nrf24l01.c index 3873fed14e..8c16d597cf 100644 --- a/src/protocol/mt99xx_nrf24l01.c +++ b/src/protocol/mt99xx_nrf24l01.c @@ -287,6 +287,8 @@ static void mt99xx_init() NRF24L01_Initialize(); if( Model.proto_opts[PROTOOPTS_FORMAT] == PROTOOPTS_FORMAT_YZ) XN297_SetScrambledMode(XN297_UNSCRAMBLED); + else + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_SetTxRxMode(TX_EN); NRF24L01_FlushTx(); for(u8 i=0; i<5; i++) diff --git a/src/protocol/v911s_nrf24l01.c b/src/protocol/v911s_nrf24l01.c index 99ce8fa54b..ccd6bd8ede 100644 --- a/src/protocol/v911s_nrf24l01.c +++ b/src/protocol/v911s_nrf24l01.c @@ -155,6 +155,7 @@ static void V911S_send_packet(u8 bind) static void V911S_init() { + XN297_SetScrambledMode(XN297_SCRAMBLED); NRF24L01_Initialize(); NRF24L01_SetTxRxMode(TX_EN); XN297_SetTXAddr((u8 *)"\x4B\x4E\x42\x4E\x44", 5); // Bind address From e6dac7ac92a46f02f4f9a29c886ff5f272604c34 Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 18 Apr 2019 22:29:37 +0200 Subject: [PATCH 20/31] Add XN297L functions to CC2500 interface --- src/protocol/e010_cc2500.c | 72 +++-------------------------------- src/protocol/iface_cc2500.h | 5 ++- src/protocol/iface_nrf24l01.h | 3 ++ src/protocol/spi/cc2500.c | 59 +++++++++++++++++++++++++++- src/protocol/spi/nrf24l01.c | 11 ------ src/protocol/spi/xn297_emu.c | 5 ++- 6 files changed, 73 insertions(+), 82 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 6944d1b81d..7035799179 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -112,65 +112,6 @@ e010_tx_rf_map[] = {{{0x4F, 0x1C}, {0x3A, 0x35, 0x4A, 0x45}}, {{0xFD, 0x4F}, {0x33, 0x3B, 0x43, 0x4B}}, {{0x86, 0x3C}, {0x34, 0x3E, 0x44, 0x4E}}}; -// xn297 emulation -//////////////////// -static u8 xn297_addr_len; -static u8 xn297_tx_addr[5]; -//static const u8 xn297_crc = 1; - -static const u16 initial = 0xb5d2; - -static void XN297L_SetTXAddr(const u8* addr, u8 len) -{ - if (len > 5) len = 5; - if (len < 3) len = 3; - xn297_addr_len = len; - memcpy(xn297_tx_addr, addr, len); -} - -static void XN297L_WritePayload(const u8* msg, u8 len) -{ - u8 buf[32]; - u8 last = 0; - u8 i; - - for (i = 0; i < xn297_addr_len; ++i) { - buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; - } - - for (i = 0; i < len; ++i) { - // bit-reverse bytes in packet - u8 b_out = bit_reverse(msg[i]); - buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; - } - if (xn297_crc) { - u8 offset = xn297_addr_len < 4 ? 1 : 0; - u16 crc = initial; - for (u8 i = offset; i < last; ++i) { - crc = crc16_update(crc, buf[i], 8); - } - crc ^= xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]; - buf[last++] = crc >> 8; - buf[last++] = crc & 0xff; - } - - // stop TX/RX - CC2500_Strobe(CC2500_SIDLE); - // flush tx FIFO - CC2500_Strobe(CC2500_SFTX); - // packet length - CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); - // xn297L preamble - CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); - // xn297 packet - CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); - // transmit - CC2500_Strobe(CC2500_STX); -} - -// end of xn297 emulation -/////////////////////////// - // Bit vector from bit position #define BV(bit) (1 << bit) @@ -230,19 +171,14 @@ static void send_packet(u8 bind) packet[15] = checksum(); + // channel hopping rf_chan++; CC2500_WriteReg(CC2500_23_FSCAL3, calibration_fscal3); CC2500_WriteReg(CC2500_24_FSCAL2, calibration_fscal2); CC2500_WriteReg(CC2500_25_FSCAL1, calibration[rf_chan / 2]); - // spacing is 333.25 kHz, must multiply xn297 channel by 3 - CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[rf_chan / 2] * 3); + XN297L_SetChannel(rf_channels[rf_chan / 2]); rf_chan %= 2 * sizeof(rf_channels); // channels repeated - // Make sure that the radio is in IDLE state before flushing the FIFO - CC2500_Strobe(CC2500_SIDLE); - // Flush TX FIFO - CC2500_Strobe(CC2500_SFTX); - XN297L_WritePayload(packet, PACKET_SIZE); // Check and adjust transmission power. We do this after @@ -256,12 +192,13 @@ static void send_packet(u8 bind) } } +// calibrate used RF channels for faster hopping static void calibrate_rf_chans() { for (int c = 0; c < RF_NUM_CHANNELS; c++) { CLOCK_ResetWatchdog(); CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteReg(CC2500_0A_CHANNR, rf_channels[c] * 3); + XN297L_SetChannel(rf_channels[c]); CC2500_Strobe(CC2500_SCAL); usleep(900); calibration[c] = CC2500_ReadReg(CC2500_25_FSCAL1); @@ -282,6 +219,7 @@ static void e010_init() XN297L_SetTXAddr(rx_tx_addr, sizeof(rx_tx_addr)); CC2500_SetPower(tx_power); calibrate_rf_chans(); + CC2500_SetTxRxMode(TX_EN); } static u16 e010_callback() diff --git a/src/protocol/iface_cc2500.h b/src/protocol/iface_cc2500.h index c925aabf97..dfb6f0a3b7 100644 --- a/src/protocol/iface_cc2500.h +++ b/src/protocol/iface_cc2500.h @@ -137,8 +137,11 @@ void CC2500_SetTxRxMode(enum TXRX_State); void CC2500_SetPower(int power); //---------------------------------------------------------------------------------- -// XN297L emulation +// XN297L emulation, used for XN297@250kbps, TX only for now //---------------------------------------------------------------------------------- void XN297L_init(u8 scramble_en, u8 crc_en); +void XN297L_SetTXAddr(const u8* addr, u8 len); +void XN297L_WritePayload(const u8* msg, u8 len); +void XN297L_SetChannel(u8 ch); #endif diff --git a/src/protocol/iface_nrf24l01.h b/src/protocol/iface_nrf24l01.h index e87bcadf7e..06a9d679ec 100644 --- a/src/protocol/iface_nrf24l01.h +++ b/src/protocol/iface_nrf24l01.h @@ -147,6 +147,9 @@ extern const u16 xn297_crc_xorout_scrambled[]; extern const u16 xn297_crc_xorout[]; extern u8 xn297_crc; extern u8 xn297_scramble_enabled; +extern u8 xn297_addr_len; +extern u8 xn297_tx_addr[5]; +extern u8 xn297_rx_addr[5]; uint8_t bit_reverse(uint8_t b_in); void XN297_SetTXAddr(const u8* addr, int len); diff --git a/src/protocol/spi/cc2500.c b/src/protocol/spi/cc2500.c index 78bc05568a..54bd142c2e 100644 --- a/src/protocol/spi/cc2500.c +++ b/src/protocol/spi/cc2500.c @@ -193,10 +193,65 @@ void XN297L_init(u8 scramble_en, u8 crc_en) CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration - CC2500_SetTxRxMode(TX_EN); - XN297_SetScrambledMode(scramble_en); xn297_crc = crc_en; } +void XN297L_SetTXAddr(const u8* addr, u8 len) +{ + if (len > 5) len = 5; + if (len < 3) len = 3; + xn297_addr_len = len; + memcpy(xn297_tx_addr, addr, len); +} + +void XN297L_WritePayload(const u8* msg, u8 len) +{ + u8 buf[32]; + u8 last = 0; + u8 i; + static const u16 initial = 0xb5d2; + + for (i = 0; i < xn297_addr_len; ++i) { + buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; + } + + for (i = 0; i < len; ++i) { + // bit-reverse bytes in packet + u8 b_out = bit_reverse(msg[i]); + buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; + } + if (xn297_crc) { + u8 offset = xn297_addr_len < 4 ? 1 : 0; + u16 crc = initial; + for (u8 i = offset; i < last; ++i) { + crc = crc16_update(crc, buf[i], 8); + } + crc ^= xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]; + buf[last++] = crc >> 8; + buf[last++] = crc & 0xff; + } + + // stop TX/RX + CC2500_Strobe(CC2500_SIDLE); + // flush tx FIFO + CC2500_Strobe(CC2500_SFTX); + // packet length + CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); + // xn297L preamble + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); + // xn297 packet + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); + // transmit + CC2500_Strobe(CC2500_STX); +} + +void XN297L_SetChannel(u8 ch) +{ + // channel spacing is 333.25 MHz, need to multiply XN297 channel by 3 + if (ch > 85) + ch = 85; + CC2500_WriteReg(CC2500_0A_CHANNR, ch * 3); +} + #endif diff --git a/src/protocol/spi/nrf24l01.c b/src/protocol/spi/nrf24l01.c index fe1f3eb3d1..15d8e858bf 100644 --- a/src/protocol/spi/nrf24l01.c +++ b/src/protocol/spi/nrf24l01.c @@ -272,12 +272,6 @@ int NRF24L01_Reset() // // XN297 emulation layer ////////////////////////// -//static u8 xn297_scramble_enabled; -static int xn297_addr_len; -static u8 xn297_tx_addr[5]; -static u8 xn297_rx_addr[5]; -//static u8 xn297_crc = 0; - static const uint16_t initial = 0xb5d2; @@ -294,11 +288,6 @@ void XN297_SetTXAddr(const u8* addr, int len) } NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5); - // Receive address is complicated. We need to use scrambled actual address as a receive address - // but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it - // first. Also, if the scrambled address begings with 1 nRF24 will look for preamble byte 0xAA - // instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment - // with receiving signals. memcpy(xn297_tx_addr, addr, len); } diff --git a/src/protocol/spi/xn297_emu.c b/src/protocol/spi/xn297_emu.c index 92c553c931..c19436dbf3 100644 --- a/src/protocol/spi/xn297_emu.c +++ b/src/protocol/spi/xn297_emu.c @@ -18,7 +18,10 @@ //static u8 packet[32]; u8 xn297_crc; -u8 xn297_scramble_enabled; // should be 1 by default ... but can't init static in modular +u8 xn297_scramble_enabled; +u8 xn297_addr_len; +u8 xn297_tx_addr[5]; +u8 xn297_rx_addr[5]; const u8 xn297_scramble[] = { 0xe3, 0xb1, 0x4b, 0xea, 0x85, 0xbc, 0xe5, 0x66, From 6548c67639bd006fc9bd1628c09a67792f21214b Mon Sep 17 00:00:00 2001 From: Goebish Date: Thu, 18 Apr 2019 23:35:51 +0200 Subject: [PATCH 21/31] Remove duplicated code --- src/protocol/e010_cc2500.c | 3 +- src/protocol/iface_cc2500.h | 4 +- src/protocol/iface_nrf24l01.h | 3 +- src/protocol/spi/cc2500.c | 45 +++++------------- src/protocol/spi/nrf24l01.c | 86 ++++++++++++----------------------- src/protocol/spi/xn297_emu.c | 47 ++++++++++++++++--- 6 files changed, 86 insertions(+), 102 deletions(-) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 7035799179..58921e9b3a 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -212,7 +212,8 @@ static void calibrate_rf_chans() static void e010_init() { u8 rx_tx_addr[ADDRESS_LENGTH]; - XN297L_init(XN297_SCRAMBLED, XN297_CRC); // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled + // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled + XN297L_Configure(XN297_SCRAMBLED, XN297_CRC); CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); memcpy(rx_tx_addr, "\x6d\x6a\x77\x77\x77", sizeof(rx_tx_addr)); memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); diff --git a/src/protocol/iface_cc2500.h b/src/protocol/iface_cc2500.h index dfb6f0a3b7..082d62a24b 100644 --- a/src/protocol/iface_cc2500.h +++ b/src/protocol/iface_cc2500.h @@ -139,9 +139,9 @@ void CC2500_SetPower(int power); //---------------------------------------------------------------------------------- // XN297L emulation, used for XN297@250kbps, TX only for now //---------------------------------------------------------------------------------- -void XN297L_init(u8 scramble_en, u8 crc_en); +void XN297L_Configure(u8 scramble_en, u8 crc_en); void XN297L_SetTXAddr(const u8* addr, u8 len); -void XN297L_WritePayload(const u8* msg, u8 len); +void XN297L_WritePayload(u8* msg, u8 len); void XN297L_SetChannel(u8 ch); #endif diff --git a/src/protocol/iface_nrf24l01.h b/src/protocol/iface_nrf24l01.h index 06a9d679ec..ce0b6398ae 100644 --- a/src/protocol/iface_nrf24l01.h +++ b/src/protocol/iface_nrf24l01.h @@ -150,7 +150,8 @@ extern u8 xn297_scramble_enabled; extern u8 xn297_addr_len; extern u8 xn297_tx_addr[5]; extern u8 xn297_rx_addr[5]; -uint8_t bit_reverse(uint8_t b_in); +u8 bit_reverse(u8 b_in); +u8 _xn297_write_payload(u8* msg, u8 len, u8* out); void XN297_SetTXAddr(const u8* addr, int len); void XN297_SetRXAddr(const u8* addr, int len); diff --git a/src/protocol/spi/cc2500.c b/src/protocol/spi/cc2500.c index 54bd142c2e..65d0fff600 100644 --- a/src/protocol/spi/cc2500.c +++ b/src/protocol/spi/cc2500.c @@ -144,7 +144,7 @@ int CC2500_Reset() // xn297 emulation // setup CC2500 for XN297L @ 250 kbps emulation -void XN297L_init(u8 scramble_en, u8 crc_en) +void XN297L_Configure(u8 scramble_en, u8 crc_en) { // Address Config = No address check // Base Frequency = 2399.999268 @@ -205,52 +205,29 @@ void XN297L_SetTXAddr(const u8* addr, u8 len) memcpy(xn297_tx_addr, addr, len); } -void XN297L_WritePayload(const u8* msg, u8 len) +void XN297L_WritePayload(u8* msg, u8 len) { - u8 buf[32]; - u8 last = 0; - u8 i; - static const u16 initial = 0xb5d2; - - for (i = 0; i < xn297_addr_len; ++i) { - buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; - } - - for (i = 0; i < len; ++i) { - // bit-reverse bytes in packet - u8 b_out = bit_reverse(msg[i]); - buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; - } - if (xn297_crc) { - u8 offset = xn297_addr_len < 4 ? 1 : 0; - u16 crc = initial; - for (u8 i = offset; i < last; ++i) { - crc = crc16_update(crc, buf[i], 8); - } - crc ^= xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]; - buf[last++] = crc >> 8; - buf[last++] = crc & 0xff; - } - - // stop TX/RX + u8 buf[36]; + u8 count = _xn297_write_payload(msg, len, buf); + // halt Tx/Rx CC2500_Strobe(CC2500_SIDLE); // flush tx FIFO CC2500_Strobe(CC2500_SFTX); - // packet length - CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3); - // xn297L preamble + // set cc2500 packet length + CC2500_WriteReg(CC2500_3F_TXFIFO, count + 3); + // XN297L preamble CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (u8*)"\x71\x0f\x55", 3); - // xn297 packet - CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); + // packet + CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, count); // transmit CC2500_Strobe(CC2500_STX); } void XN297L_SetChannel(u8 ch) { - // channel spacing is 333.25 MHz, need to multiply XN297 channel by 3 if (ch > 85) ch = 85; + // channel spacing is 333.25 MHz CC2500_WriteReg(CC2500_0A_CHANNR, ch * 3); } diff --git a/src/protocol/spi/nrf24l01.c b/src/protocol/spi/nrf24l01.c index 15d8e858bf..63867ed51e 100644 --- a/src/protocol/spi/nrf24l01.c +++ b/src/protocol/spi/nrf24l01.c @@ -272,8 +272,7 @@ int NRF24L01_Reset() // // XN297 emulation layer ////////////////////////// - -static const uint16_t initial = 0xb5d2; +static u8 xn297_packet[32]; void XN297_SetTXAddr(const u8* addr, int len) { @@ -319,109 +318,80 @@ void XN297_Configure(u8 flags) u8 XN297_WritePayload(u8* msg, int len) { - u8 packet[32]; u8 res; - int last = 0; if (xn297_addr_len < 4) { // If address length (which is defined by receive address length) // is less than 4 the TX address can't fit the preamble, so the last // byte goes here - packet[last++] = 0x55; - } - for (int i = 0; i < xn297_addr_len; ++i) { - packet[last] = xn297_tx_addr[xn297_addr_len-i-1]; - if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[i]; - last++; - } - - for (int i = 0; i < len; ++i) { - // bit-reverse bytes in packet - u8 b_out = bit_reverse(msg[i]); - packet[last] = b_out; - if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[xn297_addr_len+i]; - last++; + xn297_packet[last++] = 0x55; } - if (xn297_crc) { - int offset = xn297_addr_len < 4 ? 1 : 0; - u16 crc = initial; - for (int i = offset; i < last; ++i) { - crc = crc16_update(crc, packet[i], 8); - } - if(xn297_scramble_enabled) - crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]); - else - crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]); - packet[last++] = crc >> 8; - packet[last++] = crc & 0xff; - } - res = NRF24L01_WritePayload(packet, last); + last += _xn297_write_payload(msg, len, &xn297_packet[last]); + res = NRF24L01_WritePayload(xn297_packet, last); return res; } u8 XN297_WriteEnhancedPayload(u8* msg, int len, int noack, u16 crc_xorout) { - u8 packet[32]; u8 scramble_index=0; u8 res; int last = 0; static int pid=0; + uint16_t initial = 0xb5d2; // address if (xn297_addr_len < 4) { // If address length (which is defined by receive address length) // is less than 4 the TX address can't fit the preamble, so the last // byte goes here - packet[last++] = 0x55; + xn297_packet[last++] = 0x55; } for (int i = 0; i < xn297_addr_len; ++i) { - packet[last] = xn297_tx_addr[xn297_addr_len-i-1]; - if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[scramble_index++]; + xn297_packet[last] = xn297_tx_addr[xn297_addr_len-i-1]; + if (xn297_scramble_enabled) + xn297_packet[last] ^= xn297_scramble[scramble_index++]; last++; } // pcf - packet[last] = (len << 1) | (pid>>1); + xn297_packet[last] = (len << 1) | (pid>>1); if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[scramble_index++]; + xn297_packet[last] ^= xn297_scramble[scramble_index++]; last++; - packet[last] = (pid << 7) | (noack << 6); + xn297_packet[last] = (pid << 7) | (noack << 6); // payload - packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload + xn297_packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[scramble_index++]; + xn297_packet[last] ^= xn297_scramble[scramble_index++]; for (int i = 0; i < len-1; ++i) { last++; - packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2); + xn297_packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2); if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[scramble_index++]; + xn297_packet[last] ^= xn297_scramble[scramble_index++]; } last++; - packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload + xn297_packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload if(xn297_scramble_enabled) - packet[last] ^= xn297_scramble[scramble_index++] & 0xc0; + xn297_packet[last] ^= xn297_scramble[scramble_index++] & 0xc0; // crc if (xn297_crc) { int offset = xn297_addr_len < 4 ? 1 : 0; u16 crc = initial; for (int i = offset; i < last; ++i) { - crc = crc16_update(crc, packet[i], 8); + crc = crc16_update(crc, xn297_packet[i], 8); } - crc = crc16_update(crc, packet[last] & 0xc0, 2); + crc = crc16_update(crc, xn297_packet[last] & 0xc0, 2); crc ^= crc_xorout; - packet[last++] |= (crc >> 8) >> 2; - packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2); - packet[last++] = (crc & 0xff) << 6; + xn297_packet[last++] |= (crc >> 8) >> 2; + xn297_packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2); + xn297_packet[last++] = (crc & 0xff) << 6; } - res = NRF24L01_WritePayload(packet, last); + res = NRF24L01_WritePayload(xn297_packet, last); pid++; if(pid>3) @@ -444,8 +414,8 @@ u8 XN297_ReadPayload(u8* msg, int len) u8 XN297_ReadEnhancedPayload(u8* msg, int len) { u8 buffer[32]; - u8 pcf_size; // pcf payload size - NRF24L01_ReadPayload(buffer, len+2); // pcf + payload + u8 pcf_size; // pcf payload size + NRF24L01_ReadPayload(buffer, len+2); // pcf + payload pcf_size = buffer[0]; if(xn297_scramble_enabled) pcf_size ^= xn297_scramble[xn297_addr_len]; @@ -471,8 +441,8 @@ static u8 hs6200_tx_addr[5]; static u8 hs6200_address_length; static const u8 hs6200_scramble[] = { - 0x80,0xf5,0x3b,0x0d,0x6d,0x2a,0xf9,0xbc, - 0x51,0x8e,0x4c,0xfd,0xc1,0x65,0xd0}; // todo: find all 32 bytes ... + 0x80, 0xf5, 0x3b, 0x0d, 0x6d, 0x2a, 0xf9, 0xbc, + 0x51, 0x8e, 0x4c, 0xfd, 0xc1, 0x65, 0xd0}; // todo: find all 32 bytes ... void HS6200_SetTXAddr(const u8* addr, u8 len) { diff --git a/src/protocol/spi/xn297_emu.c b/src/protocol/spi/xn297_emu.c index c19436dbf3..6f2461ebd7 100644 --- a/src/protocol/spi/xn297_emu.c +++ b/src/protocol/spi/xn297_emu.c @@ -15,8 +15,6 @@ #include "common.h" -//static u8 packet[32]; - u8 xn297_crc; u8 xn297_scramble_enabled; u8 xn297_addr_len; @@ -29,14 +27,14 @@ const u8 xn297_scramble[] = { 0xc7, 0x62, 0x97, 0xd5, 0x0b, 0x79, 0xca, 0xcc, 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, 0x8e, 0xc5, 0x2f}; - + const u16 xn297_crc_xorout_scrambled[] = { 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, 0x2138, 0x129F, 0xB3A0, 0x2988}; - + const u16 xn297_crc_xorout[] = { 0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf, 0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15, @@ -44,11 +42,11 @@ const u16 xn297_crc_xorout[] = { 0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7, 0xb798, 0x5133, 0x67db, 0xd94e}; -#if defined(__GNUC__) && defined(__ARM_ARCH_ISA_THUMB) && (__ARM_ARCH_ISA_THUMB==2) +#if defined(__GNUC__) && defined(__ARM_ARCH_ISA_THUMB) && (__ARM_ARCH_ISA_THUMB == 2) // rbit instruction works on cortex m3 static u32 __RBIT_(u32 in) { - u32 out=0; + u32 out = 0; __asm volatile ("rbit %0, %1" : "=r" (out) : "r" (in) ); return(out); } @@ -88,3 +86,40 @@ void XN297_SetScrambledMode(const u8 mode) { xn297_scramble_enabled = mode; } + +u8 _xn297_write_payload(const u8* msg, u8 len, u8* out) +{ + u8 last = 0; + const uint16_t initial = 0xb5d2; + + for (int i = 0; i < xn297_addr_len; ++i) { + out[last] = xn297_tx_addr[xn297_addr_len-i-1]; + if (xn297_scramble_enabled) + out[last] ^= xn297_scramble[i]; + last++; + } + + for (int i = 0; i < len; ++i) { + // bit-reverse bytes in packet + u8 b_out = bit_reverse(msg[i]); + out[last] = b_out; + if (xn297_scramble_enabled) + out[last] ^= xn297_scramble[xn297_addr_len+i]; + last++; + } + + if (xn297_crc) { + int offset = xn297_addr_len < 4 ? 1 : 0; + u16 crc = initial; + for (int i = offset; i < last; ++i) { + crc = crc16_update(crc, out[i], 8); + } + if (xn297_scramble_enabled) + crc ^= xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]; + else + crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len]; + out[last++] = crc >> 8; + out[last++] = crc & 0xff; + } + return last; +} From 4278789cb2dc4aee394c1e725e1842ba840c5348 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 00:20:27 +0200 Subject: [PATCH 22/31] Fix crc for 3 byte address --- src/protocol/spi/xn297_emu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocol/spi/xn297_emu.c b/src/protocol/spi/xn297_emu.c index 6f2461ebd7..26ac721f53 100644 --- a/src/protocol/spi/xn297_emu.c +++ b/src/protocol/spi/xn297_emu.c @@ -90,16 +90,17 @@ void XN297_SetScrambledMode(const u8 mode) u8 _xn297_write_payload(const u8* msg, u8 len, u8* out) { u8 last = 0; + u8 i; const uint16_t initial = 0xb5d2; - for (int i = 0; i < xn297_addr_len; ++i) { + for (i = 0; i < xn297_addr_len; ++i) { out[last] = xn297_tx_addr[xn297_addr_len-i-1]; if (xn297_scramble_enabled) out[last] ^= xn297_scramble[i]; last++; } - for (int i = 0; i < len; ++i) { + for (i = 0; i < len; ++i) { // bit-reverse bytes in packet u8 b_out = bit_reverse(msg[i]); out[last] = b_out; @@ -109,9 +110,8 @@ u8 _xn297_write_payload(const u8* msg, u8 len, u8* out) } if (xn297_crc) { - int offset = xn297_addr_len < 4 ? 1 : 0; u16 crc = initial; - for (int i = offset; i < last; ++i) { + for (i = 0; i < last; ++i) { crc = crc16_update(crc, out[i], 8); } if (xn297_scramble_enabled) From ce6c21512cdd72b2fe45aecb719a9abc1de0b327 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 00:38:20 +0200 Subject: [PATCH 23/31] Remove E010 and Phoenix formats from MJXq protocol --- src/protocol/mjxq_nrf24l01.c | 44 +++--------------------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/src/protocol/mjxq_nrf24l01.c b/src/protocol/mjxq_nrf24l01.c index d65db2c532..47f0fe77f7 100644 --- a/src/protocol/mjxq_nrf24l01.c +++ b/src/protocol/mjxq_nrf24l01.c @@ -55,7 +55,7 @@ #define ADDRESS_LENGTH 5 static const char * const mjxq_opts[] = { - _tr_noop("Format"), "WLH08", "X600", "X800", "H26D", "H26WH", "E010", "Phoenix", NULL, + _tr_noop("Format"), "WLH08", "X600", "X800", "H26D", "H26WH", NULL, NULL }; enum { @@ -68,8 +68,6 @@ enum { FORMAT_X800, FORMAT_H26D, FORMAT_H26WH, - FORMAT_E010, - FORMAT_PHOENIX, }; ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts); @@ -90,7 +88,7 @@ enum { CHANNEL12, // Camera tilt }; #define CHANNEL_LED CHANNEL5 -#define CHANNEL_ARM CHANNEL5 // H26WH - TDR Phoenix mini +#define CHANNEL_ARM CHANNEL5 // H26WH #define CHANNEL_FLIP CHANNEL6 #define CHANNEL_PICTURE CHANNEL7 #define CHANNEL_VIDEO CHANNEL8 @@ -123,20 +121,6 @@ static const struct { {{0xC8, 0x6E, 0x02}, {0x0A, 0x3C, 0x36, 0x3F}}, {{0x48, 0x6A, 0x40}, {0x0A, 0x43, 0x36, 0x3F}}}; -// captured from E010 and H36 stock transmitters -static const struct { - u8 txid[2]; - u8 rfchan[RF_NUM_CHANNELS]; -} -e010_tx_rf_map[] = {{{0x4F, 0x1C}, {0x3A, 0x35, 0x4A, 0x45}}, - {{0x90, 0x1C}, {0x2E, 0x36, 0x3E, 0x46}}, - {{0x24, 0x36}, {0x32, 0x3E, 0x42, 0x4E}}, - {{0x7A, 0x40}, {0x2E, 0x3C, 0x3E, 0x4C}}, - {{0x61, 0x31}, {0x2F, 0x3B, 0x3F, 0x4B}}, - {{0x5D, 0x37}, {0x33, 0x3B, 0x43, 0x4B}}, - {{0xFD, 0x4F}, {0x33, 0x3B, 0x43, 0x4B}}, - {{0x86, 0x3C}, {0x34, 0x3E, 0x44, 0x4E}}}; - // Bit vector from bit position #define BV(bit) (1 << bit) @@ -212,8 +196,6 @@ static void send_packet(u8 bind) packet[10] = pan_tilt_value(); /* FALLTHROUGH */ case FORMAT_WLH08: - case FORMAT_E010: - case FORMAT_PHOENIX: packet[10] += GET_FLAG(CHANNEL_RTH, 0x02) | GET_FLAG(CHANNEL_HEADLESS, 0x01); if (!bind) { @@ -222,11 +204,6 @@ static void send_packet(u8 bind) | GET_FLAG(CHANNEL_PICTURE, 0x08) | GET_FLAG(CHANNEL_VIDEO, 0x10) | GET_FLAG_INV(CHANNEL_LED, 0x20); // air/ground mode - if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_PHOENIX) { - packet[10] |= 0x20 // high rate - | GET_FLAG(CHANNEL_ARM, 0x80); - packet[14] &= ~0x24; - } if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_H26WH) { packet[10] |= 0x40; // high rate packet[14] &= ~0x24; // unset air/ground & arm flags @@ -310,8 +287,6 @@ static void mjxq_init() break; case FORMAT_H26D: case FORMAT_H26WH: - case FORMAT_E010: - case FORMAT_PHOENIX: memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); break; default: @@ -343,11 +318,7 @@ static void mjxq_init() NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, PACKET_SIZE); - if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_E010 - || Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_PHOENIX) - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250kbps - else - NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps + NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetPower(Model.tx_power); NRF24L01_Activate(0x73); // Activate feature register NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes @@ -361,10 +332,6 @@ static void mjxq_init2() case FORMAT_H26WH: memcpy(rf_channels, "\x47\x42\x37\x32", sizeof(rf_channels)); break; - case FORMAT_E010: - case FORMAT_PHOENIX: - memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); - break; case FORMAT_H26D: memcpy(rf_channels, "\x32\x3e\x42\x4e", sizeof(rf_channels)); break; @@ -429,11 +396,6 @@ static void initialize_txid() case FORMAT_H26WH: memcpy(txid, "\xa4\x03\x00", sizeof(txid)); break; - case FORMAT_E010: - case FORMAT_PHOENIX: - memcpy(txid, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].txid, 2); - txid[2] = 0x00; - break; case FORMAT_WLH08: // txid must be multiple of 8 txid[0] = (lfsr >> 16) & 0xf8; From c52e9e81a6a4c97dd4cbe711950b1e7cb4573e92 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 01:32:22 +0200 Subject: [PATCH 24/31] Convert GD00X protocol to CC2500 --- src/protocol/e010_cc2500.c | 13 ++-- .../{gd00x_nrf24l01.c => gd00x_cc2500.c} | 74 ++++++++++++------- src/protocol/protocol.h | 2 +- 3 files changed, 56 insertions(+), 33 deletions(-) rename src/protocol/{gd00x_nrf24l01.c => gd00x_cc2500.c} (85%) diff --git a/src/protocol/e010_cc2500.c b/src/protocol/e010_cc2500.c index 58921e9b3a..efefdf0b00 100644 --- a/src/protocol/e010_cc2500.c +++ b/src/protocol/e010_cc2500.c @@ -93,7 +93,7 @@ static u8 tx_power; static u8 rf_chan; static u8 txid[3]; static u8 packet[PACKET_SIZE]; -static u8 rf_channels[RF_NUM_CHANNELS]; +static u8 hopping_frequency[RF_NUM_CHANNELS]; static u8 calibration[RF_NUM_CHANNELS]; static u8 calibration_fscal2; static u8 calibration_fscal3; @@ -176,8 +176,8 @@ static void send_packet(u8 bind) CC2500_WriteReg(CC2500_23_FSCAL3, calibration_fscal3); CC2500_WriteReg(CC2500_24_FSCAL2, calibration_fscal2); CC2500_WriteReg(CC2500_25_FSCAL1, calibration[rf_chan / 2]); - XN297L_SetChannel(rf_channels[rf_chan / 2]); - rf_chan %= 2 * sizeof(rf_channels); // channels repeated + XN297L_SetChannel(hopping_frequency[rf_chan / 2]); + rf_chan %= 2 * sizeof(hopping_frequency); // channels repeated XN297L_WritePayload(packet, PACKET_SIZE); @@ -198,7 +198,7 @@ static void calibrate_rf_chans() for (int c = 0; c < RF_NUM_CHANNELS; c++) { CLOCK_ResetWatchdog(); CC2500_Strobe(CC2500_SIDLE); - XN297L_SetChannel(rf_channels[c]); + XN297L_SetChannel(hopping_frequency[c]); CC2500_Strobe(CC2500_SCAL); usleep(900); calibration[c] = CC2500_ReadReg(CC2500_25_FSCAL1); @@ -208,7 +208,6 @@ static void calibrate_rf_chans() CC2500_Strobe(CC2500_SIDLE); } - static void e010_init() { u8 rx_tx_addr[ADDRESS_LENGTH]; @@ -216,7 +215,7 @@ static void e010_init() XN297L_Configure(XN297_SCRAMBLED, XN297_CRC); CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); memcpy(rx_tx_addr, "\x6d\x6a\x77\x77\x77", sizeof(rx_tx_addr)); - memcpy(rf_channels, "\x36\x3e\x46\x2e", sizeof(rf_channels)); + memcpy(hopping_frequency, "\x36\x3e\x46\x2e", sizeof(hopping_frequency)); XN297L_SetTXAddr(rx_tx_addr, sizeof(rx_tx_addr)); CC2500_SetPower(tx_power); calibrate_rf_chans(); @@ -228,7 +227,7 @@ static u16 e010_callback() switch (phase) { case E010_BIND: if (counter == 0) { - memcpy(rf_channels, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(rf_channels)); + memcpy(hopping_frequency, e010_tx_rf_map[Model.fixed_id % (sizeof(e010_tx_rf_map)/sizeof(e010_tx_rf_map[0]))].rfchan, sizeof(hopping_frequency)); calibrate_rf_chans(); phase = E010_DATA; PROTOCOL_SetBindState(0); diff --git a/src/protocol/gd00x_nrf24l01.c b/src/protocol/gd00x_cc2500.c similarity index 85% rename from src/protocol/gd00x_nrf24l01.c rename to src/protocol/gd00x_cc2500.c index 43e8715e42..8f493d62f3 100644 --- a/src/protocol/gd00x_nrf24l01.c +++ b/src/protocol/gd00x_cc2500.c @@ -19,7 +19,7 @@ #include "config/model.h" #include "config/tx.h" // for Transmitter -#ifdef PROTO_HAS_NRF24L01 +#ifdef PROTO_HAS_CC2500 #ifdef EMULATOR #define USE_FIXED_MFGID @@ -40,17 +40,21 @@ #define GD00X_INITIAL_WAIT 500 #define GD00X_RF_BIND_CHANNEL 2 #define GD00X_PAYLOAD_SIZE 15 +#define GD00X_NUM_CHANNEL 4 #define GD00X_V2_BIND_PACKET_PERIOD 1700 #define GD00X_V2_RF_BIND_CHANNEL 0x43 #define GD00X_V2_PAYLOAD_SIZE 6 + static const char * const gd00x_opts[] = { _tr_noop("Format"), "V1", "V2", NULL, + _tr_noop("Freq-Fine"), "-127", "127", NULL, NULL }; enum { PROTOOPTS_FORMAT = 0, + PROTOOPTS_FREQFINE, LAST_PROTO_OPT, }; enum { @@ -63,13 +67,17 @@ static u8 tx_power; static u8 packet[GD00X_PAYLOAD_SIZE]; static u8 hopping_frequency_no; static u8 rx_tx_addr[5]; -static u8 hopping_frequency[4]; +static u8 hopping_frequency[GD00X_NUM_CHANNEL]; static u16 bind_counter; static u16 packet_period; static u8 packet_count; static u8 packet_length; static u8 phase; static u8 len; +static s8 fine; +static u8 calibration[GD00X_NUM_CHANNEL]; +static u8 calibration_fscal2; +static u8 calibration_fscal3; enum{ GD00X_BIND, @@ -198,50 +206,61 @@ static void GD00X_send_packet() break; } - // Power on, TX mode, CRC enabled - XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); + // channel hopping if (phase == GD00X_DATA) { - NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); + CC2500_WriteReg(CC2500_23_FSCAL3, calibration_fscal3); + CC2500_WriteReg(CC2500_24_FSCAL2, calibration_fscal2); + CC2500_WriteReg(CC2500_25_FSCAL1, calibration[hopping_frequency_no]); + XN297L_SetChannel(hopping_frequency[hopping_frequency_no]); if (Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1) { hopping_frequency_no++; hopping_frequency_no &= 3; // 4 RF channels } } - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); - NRF24L01_FlushTx(); - XN297_WritePayload(packet, packet_length); - + XN297L_WritePayload(packet, packet_length); if (tx_power != Model.tx_power) { // Keep transmit power updated tx_power = Model.tx_power; - NRF24L01_SetPower(tx_power); + CC2500_SetPower(tx_power); } } +// calibrate used RF channels for faster hopping +static void calibrate_rf_chans() +{ + for (int c = 0; c < GD00X_NUM_CHANNEL; c++) { + CLOCK_ResetWatchdog(); + CC2500_Strobe(CC2500_SIDLE); + XN297L_SetChannel(hopping_frequency[c]); + CC2500_Strobe(CC2500_SCAL); + usleep(900); + calibration[c] = CC2500_ReadReg(CC2500_25_FSCAL1); + } + calibration_fscal3 = CC2500_ReadReg(CC2500_23_FSCAL3); // only needs to be done once + calibration_fscal2 = CC2500_ReadReg(CC2500_24_FSCAL2); // only needs to be done once + CC2500_Strobe(CC2500_SIDLE); +} + static void GD00X_init() { - XN297_SetScrambledMode(XN297_SCRAMBLED); - NRF24L01_Initialize(); - NRF24L01_SetTxRxMode(TX_EN); + // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled + XN297L_Configure(XN297_SCRAMBLED, XN297_CRC); + CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_V1: - XN297_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); - NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_RF_BIND_CHANNEL); + XN297L_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); + XN297L_SetChannel(GD00X_RF_BIND_CHANNEL); break; case FORMAT_V2: - XN297_SetTXAddr((u8*)"GDKNx", 5); - NRF24L01_WriteReg(NRF24L01_05_RF_CH, GD00X_V2_RF_BIND_CHANNEL); + XN297L_SetTXAddr((u8*)"GDKNx", 5); + XN297L_SetChannel(GD00X_V2_RF_BIND_CHANNEL); break; } - NRF24L01_FlushTx(); - NRF24L01_FlushRx(); - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit - NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps - NRF24L01_SetPower(tx_power); + CC2500_SetPower(tx_power); + calibrate_rf_chans(); + CC2500_SetTxRxMode(TX_EN); } static void GD00X_initialize_txid() @@ -338,6 +357,10 @@ static void GD00X_initialize_txid() static u16 GD00X_callback() { + if (fine != (s8)Model.proto_opts[PROTOOPTS_FREQFINE]) { + fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; + CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); + } if (phase == GD00X_BIND) { if (--bind_counter == 0) { PROTOCOL_SetBindState(0); @@ -352,6 +375,7 @@ static void initialize() { CLOCK_StopTimer(); tx_power = Model.tx_power; + fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; packet_period = Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD; packet_length = Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; packet_count = 0; @@ -372,7 +396,7 @@ uintptr_t GD00X_Cmds(enum ProtoCmds cmd) case PROTOCMD_DEINIT: case PROTOCMD_RESET: CLOCK_StopTimer(); - return (NRF24L01_Reset() ? 1 : -1); + return (CC2500_Reset() ? 1 : -1); case PROTOCMD_CHECK_AUTOBIND: return 1; case PROTOCMD_BIND: initialize(); return 0; case PROTOCMD_NUMCHAN: return 5; diff --git a/src/protocol/protocol.h b/src/protocol/protocol.h index bffd0c075a..4af9a4ff81 100644 --- a/src/protocol/protocol.h +++ b/src/protocol/protocol.h @@ -29,6 +29,7 @@ PROTODEF(PROTOCOL_SFHSS, CC2500, AETRG, SFHSS_Cmds, "S-FHSS") PROTODEF(PROTOCOL_CORONA, CC2500, AETRG, Corona_Cmds, "Corona") PROTODEF(PROTOCOL_HITEC, CC2500, AETRG, Hitec_Cmds, "Hitec") PROTODEF(PROTOCOL_E010, CC2500, AETRG, E010_Cmds, "E010") +PROTODEF(PROTOCOL_GD00X, CC2500, AETRG, GD00X_Cmds, "GD00X") #endif //PROTO_HAS_CC2500 #ifdef PROTO_HAS_NRF24L01 PROTODEF(PROTOCOL_V202, NRF24L01, AETRG, V202_Cmds, "V202") @@ -63,7 +64,6 @@ PROTODEF(PROTOCOL_E012, NRF24L01, AETRG, E012_Cmds, "E012") PROTODEF(PROTOCOL_E015, NRF24L01, AETRG, E015_Cmds, "E015") PROTODEF(PROTOCOL_NCC1701, NRF24L01, AETRG, NCC1701_Cmds, "NCC1701") PROTODEF(PROTOCOL_V911S, NRF24L01, AETRG, V911S_Cmds, "V911S") -PROTODEF(PROTOCOL_GD00X, NRF24L01, AETRG, GD00X_Cmds, "GD00X") PROTODEF(PROTOCOL_LOLI, NRF24L01, AETRG, LOLI_Cmds, "LOLI") PROTODEF(PROTOCOL_E016H, NRF24L01, AETRG, E016H_Cmds, "E016H") #endif //PROTO_HAS_NRF24L01 From 3cbea89aafc2670b0e0b40b23db8bb59e31ce000 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 01:41:46 +0200 Subject: [PATCH 25/31] Fix modular build --- src/protocol/Makefile.inc | 2 +- src/protocol/gd00x_cc2500.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocol/Makefile.inc b/src/protocol/Makefile.inc index d8cf83f0e2..4d356899f0 100644 --- a/src/protocol/Makefile.inc +++ b/src/protocol/Makefile.inc @@ -281,7 +281,7 @@ $(ODIR)/protocol/v911s.mod : $(ODIR)/v911s_nrf24l01.bin @echo Building 'v911s' module /bin/mkdir -p $(ODIR)/protocol/ 2>/dev/null; /bin/cp $< $@ -$(ODIR)/protocol/gd00x.mod : $(ODIR)/gd00x_nrf24l01.bin +$(ODIR)/protocol/gd00x.mod : $(ODIR)/gd00x_cc2500.bin @echo Building 'gd00x' module /bin/mkdir -p $(ODIR)/protocol/ 2>/dev/null; /bin/cp $< $@ diff --git a/src/protocol/gd00x_cc2500.c b/src/protocol/gd00x_cc2500.c index 8f493d62f3..1b8390c21e 100644 --- a/src/protocol/gd00x_cc2500.c +++ b/src/protocol/gd00x_cc2500.c @@ -32,7 +32,7 @@ // printf inside an interrupt handler is really dangerous // this shouldn't be enabled even in debug builds without explicitly // turning it on -#define dbgprintf if(0) printf +#define dbgprintf if (0) printf #endif // #define FORCE_GD00X_ORIGINAL_ID @@ -219,7 +219,7 @@ static void GD00X_send_packet() } XN297L_WritePayload(packet, packet_length); - + if (tx_power != Model.tx_power) { // Keep transmit power updated tx_power = Model.tx_power; @@ -266,8 +266,8 @@ static void GD00X_init() static void GD00X_initialize_txid() { u32 lfsr = 0xb2c54a2ful; - u8 i,j; - + u8 i, j; + #ifndef USE_FIXED_MFGID u8 var[12]; MCU_SerialNumber(var, 12); @@ -381,7 +381,7 @@ static void initialize() packet_count = 0; len = 0; hopping_frequency_no = 0; - bind_counter=GD00X_BIND_COUNT; + bind_counter = GD00X_BIND_COUNT; phase = GD00X_BIND; PROTOCOL_SetBindState((GD00X_BIND_COUNT * packet_period)/1000); GD00X_initialize_txid(); @@ -391,7 +391,7 @@ static void initialize() uintptr_t GD00X_Cmds(enum ProtoCmds cmd) { - switch(cmd) { + switch (cmd) { case PROTOCMD_INIT: initialize(); return 0; case PROTOCMD_DEINIT: case PROTOCMD_RESET: From 28a182f4759770fe6a73bf06dbc135f6140a174e Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 13:29:07 +0200 Subject: [PATCH 26/31] Convert V911S protocol to CC2500 --- src/protocol/v911s_nrf24l01.c | 77 +++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/src/protocol/v911s_nrf24l01.c b/src/protocol/v911s_nrf24l01.c index ccd6bd8ede..a970dd899f 100644 --- a/src/protocol/v911s_nrf24l01.c +++ b/src/protocol/v911s_nrf24l01.c @@ -19,7 +19,7 @@ #include "config/model.h" #include "config/tx.h" // for Transmitter -#ifdef PROTO_HAS_NRF24L01 +#ifdef PROTO_HAS_CC2500 #ifdef EMULATOR #define USE_FIXED_MFGID @@ -44,6 +44,16 @@ #define V911S_RF_BIND_CHANNEL 35 #define V911S_NUM_RF_CHANNELS 8 +static const char * const v911s_opts[] = { + _tr_noop("Freq-Fine"), "-127", "127", NULL, + NULL +}; +enum { + PROTOOPTS_FREQFINE = 0, + LAST_PROTO_OPT, +}; +ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts); + static u8 tx_power; static u8 packet[V911S_PACKET_SIZE]; static u8 rf_ch_num; @@ -53,6 +63,9 @@ static u8 hopping_frequency[V911S_NUM_RF_CHANNELS]; static u16 bind_counter; static u16 packet_period; static u8 phase; +static u8 calibration[V911S_NUM_RF_CHANNELS]; +static u8 calibration_fscal2; +static u8 calibration_fscal3; enum{ V911S_BIND, @@ -132,41 +145,54 @@ static void V911S_send_packet(u8 bind) packet[11]|= ch<<3; packet[12] = ch>>5; } - - // Power on, TX mode, 2byte CRC - XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); + if (!bind) { - NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[channel]); + // channel hopping + CC2500_WriteReg(CC2500_23_FSCAL3, calibration_fscal3); + CC2500_WriteReg(CC2500_24_FSCAL2, calibration_fscal2); + CC2500_WriteReg(CC2500_25_FSCAL1, calibration[channel]); + XN297L_SetChannel(hopping_frequency[channel]); hopping_frequency_no++; hopping_frequency_no&=7; // 8 RF channels } - // clear packet status bits and TX FIFO - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); - NRF24L01_FlushTx(); - XN297_WritePayload(packet, V911S_PACKET_SIZE); + + XN297L_WritePayload(packet, V911S_PACKET_SIZE); if (tx_power != Model.tx_power) { //Keep transmit power updated tx_power = Model.tx_power; - NRF24L01_SetPower(tx_power); + CC2500_SetPower(tx_power); + } +} + +// calibrate used RF channels for faster hopping +static void calibrate_rf_chans() +{ + for (int c = 0; c < V911S_NUM_RF_CHANNELS; c++) { + CLOCK_ResetWatchdog(); + CC2500_Strobe(CC2500_SIDLE); + XN297L_SetChannel(hopping_frequency[c]); + CC2500_Strobe(CC2500_SCAL); + usleep(900); + calibration[c] = CC2500_ReadReg(CC2500_25_FSCAL1); } + calibration_fscal3 = CC2500_ReadReg(CC2500_23_FSCAL3); // only needs to be done once + calibration_fscal2 = CC2500_ReadReg(CC2500_24_FSCAL2); // only needs to be done once + CC2500_Strobe(CC2500_SIDLE); } static void V911S_init() { - XN297_SetScrambledMode(XN297_SCRAMBLED); - NRF24L01_Initialize(); - NRF24L01_SetTxRxMode(TX_EN); - XN297_SetTXAddr((u8 *)"\x4B\x4E\x42\x4E\x44", 5); // Bind address - NRF24L01_WriteReg(NRF24L01_05_RF_CH, V911S_RF_BIND_CHANNEL); // Bind channel - NRF24L01_FlushTx(); - NRF24L01_FlushRx(); - NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit - NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only - NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps - NRF24L01_SetPower(tx_power); + // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled + XN297L_Configure(XN297_SCRAMBLED, XN297_CRC); + // Bind address + XN297L_SetTXAddr((u8 *)"\x4B\x4E\x42\x4E\x44", 5); + // Bind channel + XN297L_SetChannel(V911S_RF_BIND_CHANNEL); + CC2500_SetPower(tx_power); + calibrate_rf_chans(); + CC2500_SetTxRxMode(TX_EN); } static void V911S_initialize_txid() @@ -215,7 +241,7 @@ static u16 V911S_callback() if (bind_counter == 0) { PROTOCOL_SetBindState(0); - XN297_SetTXAddr(rx_tx_addr, 5); + XN297L_SetTXAddr(rx_tx_addr, 5); packet_period=V911S_PACKET_PERIOD; phase = V911S_DATA; } @@ -263,7 +289,7 @@ static void initialize(u8 bind) } else { - XN297_SetTXAddr(rx_tx_addr, 5); + XN297L_SetTXAddr(rx_tx_addr, 5); packet_period= V911S_PACKET_PERIOD; phase = V911S_DATA; } @@ -279,12 +305,13 @@ uintptr_t V911S_Cmds(enum ProtoCmds cmd) case PROTOCMD_DEINIT: case PROTOCMD_RESET: CLOCK_StopTimer(); - return (NRF24L01_Reset() ? 1 : -1); + return (CC2500_Reset() ? 1 : -1); case PROTOCMD_CHECK_AUTOBIND: return 0; case PROTOCMD_BIND: initialize(1); return 0; case PROTOCMD_NUMCHAN: return 5; case PROTOCMD_DEFAULT_NUMCHAN: return 5; case PROTOCMD_CURRENT_ID: return Model.fixed_id; + case PROTOCMD_GETOPTIONS: return (uintptr_t)v911s_opts; case PROTOCMD_TELEMETRYSTATE: return PROTO_TELEM_UNSUPPORTED; case PROTOCMD_CHANNELMAP: return AETRG; default: break; From 4c42266b21a34641b243c779e0e947e7bc9f2c3c Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 13:33:49 +0200 Subject: [PATCH 27/31] Rename protocol file --- src/protocol/Makefile.inc | 2 +- src/protocol/protocol.h | 2 +- src/protocol/{v911s_nrf24l01.c => v911s_cc2500.c} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/protocol/{v911s_nrf24l01.c => v911s_cc2500.c} (100%) diff --git a/src/protocol/Makefile.inc b/src/protocol/Makefile.inc index 4d356899f0..0cd9450179 100644 --- a/src/protocol/Makefile.inc +++ b/src/protocol/Makefile.inc @@ -277,7 +277,7 @@ $(ODIR)/protocol/ncc1701.mod : $(ODIR)/ncc1701_nrf24l01.bin @echo Building 'ncc1701' module /bin/mkdir -p $(ODIR)/protocol/ 2>/dev/null; /bin/cp $< $@ -$(ODIR)/protocol/v911s.mod : $(ODIR)/v911s_nrf24l01.bin +$(ODIR)/protocol/v911s.mod : $(ODIR)/v911s_cc2500.bin @echo Building 'v911s' module /bin/mkdir -p $(ODIR)/protocol/ 2>/dev/null; /bin/cp $< $@ diff --git a/src/protocol/protocol.h b/src/protocol/protocol.h index 4af9a4ff81..71ce120bca 100644 --- a/src/protocol/protocol.h +++ b/src/protocol/protocol.h @@ -30,6 +30,7 @@ PROTODEF(PROTOCOL_CORONA, CC2500, AETRG, Corona_Cmds, "Corona") PROTODEF(PROTOCOL_HITEC, CC2500, AETRG, Hitec_Cmds, "Hitec") PROTODEF(PROTOCOL_E010, CC2500, AETRG, E010_Cmds, "E010") PROTODEF(PROTOCOL_GD00X, CC2500, AETRG, GD00X_Cmds, "GD00X") +PROTODEF(PROTOCOL_V911S, NRF24L01, AETRG, V911S_Cmds, "V911S") #endif //PROTO_HAS_CC2500 #ifdef PROTO_HAS_NRF24L01 PROTODEF(PROTOCOL_V202, NRF24L01, AETRG, V202_Cmds, "V202") @@ -63,7 +64,6 @@ PROTODEF(PROTOCOL_BUGS3MINI, NRF24L01, AETRG, BUGS3MINI_Cmds, "Bugs3Mini") PROTODEF(PROTOCOL_E012, NRF24L01, AETRG, E012_Cmds, "E012") PROTODEF(PROTOCOL_E015, NRF24L01, AETRG, E015_Cmds, "E015") PROTODEF(PROTOCOL_NCC1701, NRF24L01, AETRG, NCC1701_Cmds, "NCC1701") -PROTODEF(PROTOCOL_V911S, NRF24L01, AETRG, V911S_Cmds, "V911S") PROTODEF(PROTOCOL_LOLI, NRF24L01, AETRG, LOLI_Cmds, "LOLI") PROTODEF(PROTOCOL_E016H, NRF24L01, AETRG, E016H_Cmds, "E016H") #endif //PROTO_HAS_NRF24L01 diff --git a/src/protocol/v911s_nrf24l01.c b/src/protocol/v911s_cc2500.c similarity index 100% rename from src/protocol/v911s_nrf24l01.c rename to src/protocol/v911s_cc2500.c From ee7176eceb2f3e75175ffe7f92a031fd111fb7c7 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 13:35:48 +0200 Subject: [PATCH 28/31] Fix modular build --- src/protocol/protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/protocol.h b/src/protocol/protocol.h index 71ce120bca..ed7a3fc850 100644 --- a/src/protocol/protocol.h +++ b/src/protocol/protocol.h @@ -30,7 +30,7 @@ PROTODEF(PROTOCOL_CORONA, CC2500, AETRG, Corona_Cmds, "Corona") PROTODEF(PROTOCOL_HITEC, CC2500, AETRG, Hitec_Cmds, "Hitec") PROTODEF(PROTOCOL_E010, CC2500, AETRG, E010_Cmds, "E010") PROTODEF(PROTOCOL_GD00X, CC2500, AETRG, GD00X_Cmds, "GD00X") -PROTODEF(PROTOCOL_V911S, NRF24L01, AETRG, V911S_Cmds, "V911S") +PROTODEF(PROTOCOL_V911S, CC2500, AETRG, V911S_Cmds, "V911S") #endif //PROTO_HAS_CC2500 #ifdef PROTO_HAS_NRF24L01 PROTODEF(PROTOCOL_V202, NRF24L01, AETRG, V202_Cmds, "V202") From 6647eab4cfab55082ef4dc0fa7d6d7c3cb975204 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 16:55:18 +0200 Subject: [PATCH 29/31] Add Freq-Coarse setting to gd00x --- src/protocol/gd00x_cc2500.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/protocol/gd00x_cc2500.c b/src/protocol/gd00x_cc2500.c index 1b8390c21e..8794b91316 100644 --- a/src/protocol/gd00x_cc2500.c +++ b/src/protocol/gd00x_cc2500.c @@ -35,7 +35,7 @@ #define dbgprintf if (0) printf #endif -// #define FORCE_GD00X_ORIGINAL_ID +#define FORCE_GD00X_ORIGINAL_ID #define GD00X_INITIAL_WAIT 500 #define GD00X_RF_BIND_CHANNEL 2 @@ -50,11 +50,13 @@ static const char * const gd00x_opts[] = { _tr_noop("Format"), "V1", "V2", NULL, _tr_noop("Freq-Fine"), "-127", "127", NULL, + _tr_noop("Freq-Coarse"), "-127", "127", NULL, NULL }; enum { PROTOOPTS_FORMAT = 0, PROTOOPTS_FREQFINE, + PROTOOPTS_FREQCOARSE, LAST_PROTO_OPT, }; enum { @@ -75,6 +77,7 @@ static u8 packet_length; static u8 phase; static u8 len; static s8 fine; +static s8 coarse; static u8 calibration[GD00X_NUM_CHANNEL]; static u8 calibration_fscal2; static u8 calibration_fscal3; @@ -248,6 +251,7 @@ static void GD00X_init() // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled XN297L_Configure(XN297_SCRAMBLED, XN297_CRC); CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); + CC2500_WriteReg(CC2500_0F_FREQ0, 0xc3 + coarse); switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_V1: XN297L_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); @@ -361,6 +365,10 @@ static u16 GD00X_callback() fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); } + if (coarse != (s8)Model.proto_opts[PROTOOPTS_FREQCOARSE]) { + coarse = (s8)Model.proto_opts[PROTOOPTS_FREQCOARSE]; + CC2500_WriteReg(CC2500_0F_FREQ0, 0xc3 + coarse); + } if (phase == GD00X_BIND) { if (--bind_counter == 0) { PROTOCOL_SetBindState(0); @@ -376,6 +384,7 @@ static void initialize() CLOCK_StopTimer(); tx_power = Model.tx_power; fine = (s8)Model.proto_opts[PROTOOPTS_FREQFINE]; + coarse = (s8)Model.proto_opts[PROTOOPTS_FREQCOARSE]; packet_period = Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD; packet_length = Model.proto_opts[PROTOOPTS_FORMAT] == FORMAT_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE; packet_count = 0; From cd87637c5415f6205e5b42a813608767076fff9c Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 17:45:23 +0200 Subject: [PATCH 30/31] Set base frequency to 2400 MHz instead of 2399.999268 --- src/protocol/spi/cc2500.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocol/spi/cc2500.c b/src/protocol/spi/cc2500.c index 65d0fff600..131159bfd4 100644 --- a/src/protocol/spi/cc2500.c +++ b/src/protocol/spi/cc2500.c @@ -147,10 +147,10 @@ int CC2500_Reset() void XN297L_Configure(u8 scramble_en, u8 crc_en) { // Address Config = No address check - // Base Frequency = 2399.999268 + // Base Frequency = 2400 // CRC Autoflush = false // CRC Enable = false - // Carrier Frequency = 2399.999268 + // Carrier Frequency = 2400 // Channel Number = 0 // Channel Spacing = 333.251953 // Data Format = Normal mode @@ -175,7 +175,7 @@ void XN297L_Configure(u8 scramble_en, u8 crc_en) CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte - CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xC5); // Frequency Control Word, Low Byte CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration From 231bb33b340e56dcf41739fdee801046b3c2ad85 Mon Sep 17 00:00:00 2001 From: Goebish Date: Fri, 19 Apr 2019 18:29:21 +0200 Subject: [PATCH 31/31] Set freq coarse step to 100 kHz --- src/protocol/gd00x_cc2500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocol/gd00x_cc2500.c b/src/protocol/gd00x_cc2500.c index 8794b91316..30c17280c8 100644 --- a/src/protocol/gd00x_cc2500.c +++ b/src/protocol/gd00x_cc2500.c @@ -251,7 +251,7 @@ static void GD00X_init() // setup cc2500 for xn297L@250kbps emulation, scrambled, crc enabled XN297L_Configure(XN297_SCRAMBLED, XN297_CRC); CC2500_WriteReg(CC2500_0C_FSCTRL0, fine); - CC2500_WriteReg(CC2500_0F_FREQ0, 0xc3 + coarse); + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4e + coarse); switch (Model.proto_opts[PROTOOPTS_FORMAT]) { case FORMAT_V1: XN297L_SetTXAddr((u8*)"\xcc\xcc\xcc\xcc\xcc", 5); @@ -367,7 +367,7 @@ static u16 GD00X_callback() } if (coarse != (s8)Model.proto_opts[PROTOOPTS_FREQCOARSE]) { coarse = (s8)Model.proto_opts[PROTOOPTS_FREQCOARSE]; - CC2500_WriteReg(CC2500_0F_FREQ0, 0xc3 + coarse); + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4e + coarse); } if (phase == GD00X_BIND) { if (--bind_counter == 0) {