diff --git a/Multiprotocol/CABELL_nrf224l01.ino b/Multiprotocol/CABELL_nrf224l01.ino index a1f4027..965f550 100644 --- a/Multiprotocol/CABELL_nrf224l01.ino +++ b/Multiprotocol/CABELL_nrf224l01.ino @@ -48,10 +48,12 @@ Multiprotocol is distributed in the hope that it will be useful, typedef struct { enum RxMode_t : uint8_t { // Note bit 8 is used to indicate if the packet is the first of 2 on the channel. Mask out this bit before using the enum - normal = 0, - bind = 1, - setFailSafe = 2, - unBind = 127 + normal = 0, + bind = 1, + setFailSafe = 2, + normalWithTelemetry = 3, + telemetryResponse = 4, + unBind = 127 } RxMode; uint8_t reserved = 0; uint8_t option; @@ -94,9 +96,58 @@ static uint8_t __attribute__((unused)) CABELL_getNextChannel (uint8_t seqArray[] return (seqArraySize * nextBand) + seqArray[nextChannalSeqArrayPosition] + CABELL_RADIO_MIN_CHANNEL_NUM; // Add CABELL_RADIO_MIN_CHANNEL_NUM so we dont use channel 0 as it may bleed below 2.400 GHz } +//----------------------------------------------------------------------------------------- +#if defined(TELEMETRY) && defined(HUB_TELEMETRY) +static void __attribute__((unused)) CABELL_get_telemetry() +{ + static unsigned long telemetryProcessingTime = 50; // initial guess. This will get adjusted below once telemetry packts are recieved + + // calculate TX rssi based on telemetry packets recieved per half second. Cannot use full second count because telemetry_counter is not large enough + state++; + if (state > (500000 / CABELL_PACKET_PERIOD)) + { + //calculate telemetry reception RSSI - based on packet rape per 1000ms where 255 is 100% + state--; //This is the number of packets expected + TX_RSSI = constrain(((uint16_t)(((float)telemetry_counter / (float)state * (float)255))),0,255); + telemetry_counter = 0; + state = 0; + telemetry_lost=0; +// Serial.print(TX_RSSI); +// Serial.print(" "); +// Serial.println(RX_RSSI); + } + + // Process incomming telementry packet of it was recieved + if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) { // data received from model + unsigned long telemetryProcessingStart = micros(); + NRF24L01_ReadPayload(packet, 2); + if ((packet[0] & 0x7F) == CABELL_RxTxPacket_t::RxMode_t::telemetryResponse) // ignore first bit in compare becasue it toggles with each packet + { + RX_RSSI = packet[1]; + telemetry_counter++; + if(telemetry_lost==0) telemetry_link=1; + telemetryProcessingTime = micros() - telemetryProcessingStart; + } + } else { + // If no telemetry packet was recieved then delay by the typical telemetry packet processing time + // This is done to try to keep the sendPacket process timing more consistent. Since the SPI payload read takes some time + delayMicroseconds(telemetryProcessingTime); + } + + NRF24L01_SetTxRxMode(TX_EN); + NRF24L01_FlushRx(); +} +#endif + //----------------------------------------------------------------------------------------- static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode) { + #if defined(TELEMETRY) && defined(HUB_TELEMETRY) + if (sub_protocol == CABELL_V3_TELEMETRY) { // check for incommimg packet and switch radio back to TX mode if we were listening for telemetry + CABELL_get_telemetry(); + } + #endif + CABELL_RxTxPacket_t TxPacket; uint8_t channelReduction = constrain((option & CABELL_OPTION_MASK_CHANNEL_REDUCTION),0,CABELL_NUM_CHANNELS-CABELL_MIN_CHANNELS); // Max 12 - cannot reduce below 4 channels @@ -113,7 +164,17 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode) if (sub_protocol == CABELL_SET_FAIL_SAFE && !bindMode) { TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::setFailSafe; } else { - TxPacket.RxMode = (bindMode) ? CABELL_RxTxPacket_t::RxMode_t::bind : CABELL_RxTxPacket_t::RxMode_t::normal; + if (bindMode) { + TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::bind; + } else { + switch (sub_protocol) { + case CABELL_V3_TELEMETRY : TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normalWithTelemetry; + break; + + default : TxPacket.RxMode = CABELL_RxTxPacket_t::RxMode_t::normal; + break; + } + } } TxPacket.option = (bindMode) ? (option & (~CABELL_OPTION_MASK_CHANNEL_REDUCTION)) : option; //remove channel reduction if in bind mode } @@ -143,11 +204,6 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode) case 13 : holdValue = 1000 + rx_tx_addr[2]; break; case 14 : holdValue = 1000 + rx_tx_addr[3]; break; case 15 : holdValue = 1000 + rx_tx_addr[4]; break; -// case 11 : holdValue = 1000 + ((((uint64_t)CABELL_normal_addr)>>32) & 0x00000000000000FF); break; -// case 12 : holdValue = 1000 + ((((uint64_t)CABELL_normal_addr)>>24) & 0x00000000000000FF); break; -// case 13 : holdValue = 1000 + ((((uint64_t)CABELL_normal_addr)>>16) & 0x00000000000000FF); break; -// case 14 : holdValue = 1000 + ((((uint64_t)CABELL_normal_addr)>>8) & 0x00000000000000FF); break; -// case 15 : holdValue = 1000 + ((((uint64_t)CABELL_normal_addr)) & 0x00000000000000FF); break; } } @@ -181,6 +237,22 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode) // This is a work around for a reported bug in clone NRF24L01 chips that mis-took this case for a re-transmit of the same packet. NRF24L01_WritePayload((uint8_t*)&TxPacket, packetSize); + + #if defined(TELEMETRY) && defined(HUB_TELEMETRY) + if (sub_protocol == CABELL_V3_TELEMETRY) { // switch radio to rx as soon as packet is sent + // calculate transmit time based on packet size and data rate of 1MB per sec + // This is done becasue polling the status register during xmit casued issues. + // The status register will still be chaecked after the delay to be sure xmit is complete + // bits = packstsize * 8 + 73 bits overhead + // at 1 MB per sec, one bit is 1 uS + // then add 150 uS which is 130 uS to begin the xmit and 10 uS fudge factor + delayMicroseconds(((unsigned long)packetSize * 8ul) + 73ul + 150ul) ; + while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))) delayMicroseconds(5); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // RX mode with 16 bit CRC + } + #endif + + CABELL_SetPower(); } //----------------------------------------------------------------------------------------- @@ -263,7 +335,11 @@ static void __attribute__((unused)) CABELL_init() { NRF24L01_Initialize(); CABELL_SetPower(); - NRF24L01_SetBitrate(NRF24L01_BR_250K); + if (sub_protocol == CABELL_V3_TELEMETRY) { + NRF24L01_SetBitrate(NRF24L01_BR_1M); // telemeetry needs higfher data rate for there to be time for the round trip in teh 3ms interval + } else { + NRF24L01_SetBitrate(NRF24L01_BR_250K); // slower data rate when not in telemetry mode gives better range/reliability + } NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement on all data pipes NRF24L01_SetTxRxMode(TX_EN); //Power up and 16 bit CRC @@ -272,7 +348,7 @@ static void __attribute__((unused)) CABELL_init() NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); NRF24L01_FlushTx(); NRF24L01_FlushRx(); - NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x02); + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 32 byte packet length NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, 0x20); // 32 byte packet length NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); @@ -334,6 +410,11 @@ uint16_t initCABELL(void) bind_counter = CABELL_BIND_COUNT; } CABELL_init(); + #if defined(TELEMETRY) && defined(HUB_TELEMETRY) + init_frskyd_link_telemetry(); + telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message... + #endif + return CABELL_PACKET_PERIOD; } diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index e7d2cf6..e694f05 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -198,6 +198,7 @@ enum Q303 enum CABELL { CABELL_V3 = 0, + CABELL_V3_TELEMETRY = 1, CABELL_SET_FAIL_SAFE = 6, CABELL_UNBIND = 7 }; @@ -590,9 +591,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- CX10D 2 CX10WD 3 sub_protocol==CABELL - CABELL_V3 0, + CABELL_V3 0, + CABELL_V3_TELEMETRY 1, CABELL_SET_FAIL_SAFE 6, - CABELL_UNBIND 7 + CABELL_UNBIND 7 Power value => 0x80 0=High/1=Low Stream[3] = option_protocol; @@ -688,4 +690,4 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- data[0] = RSSI value data[1-28] telemetry data -*/ \ No newline at end of file +*/ diff --git a/Multiprotocol/Pins.h b/Multiprotocol/Pins.h index 9850055..ff47296 100644 --- a/Multiprotocol/Pins.h +++ b/Multiprotocol/Pins.h @@ -34,28 +34,28 @@ #endif // Dial - #define MODE_DIAL1_pin 2 - #define MODE_DIAL1_port PORTB - #define MODE_DIAL1_ipr PINB - #define MODE_DIAL2_pin 3 - #define MODE_DIAL2_port PORTB - #define MODE_DIAL2_ipr PINB - #define MODE_DIAL3_pin 4 - #define MODE_DIAL3_port PORTB - #define MODE_DIAL3_ipr PINB - #define MODE_DIAL4_pin 0 - #define MODE_DIAL4_port PORTC - #define MODE_DIAL4_ipr PINC + #define MODE_DIAL1_pin 4 //D4 = PD4 + #define MODE_DIAL1_port PORTD + #define MODE_DIAL1_ipr PIND + #define MODE_DIAL2_pin 5 //D5 = PD5 + #define MODE_DIAL2_port PORTD + #define MODE_DIAL2_ipr PIND + #define MODE_DIAL3_pin 6 //D6 = PD6 + #define MODE_DIAL3_port PORTD + #define MODE_DIAL3_ipr PIND + #define MODE_DIAL4_pin 7 //D7 = PD7 + #define MODE_DIAL4_port PORTD + #define MODE_DIAL4_ipr PIND // PPM #define PPM_pin 3 //D3 = PD3 #define PPM_port PORTD // SDIO - #define SDI_pin 5 //D5 = PD5 - #define SDI_port PORTD - #define SDI_ipr PIND - #define SDI_ddr DDRD + #define SDI_pin 3 //D11 = PB3 = MOSI + #define SDI_port PORTB + #define SDI_ipr PINB + #define SDI_ddr DDRB #ifdef ORANGE_TX #define SDI_on SDI_port.OUTSET = _BV(SDI_pin) #define SDI_off SDI_port.OUTCLR = _BV(SDI_pin) @@ -69,9 +69,9 @@ #define SDI_output SDI_ddr |= _BV(SDI_pin) //SDO - #define SDO_pin 6 //D6 = PD6 - #define SDO_port PORTD - #define SDO_ipr PIND + #define SDO_pin 4 //D12 = PB4 = MISO + #define SDO_port PORTB + #define SDO_ipr PINB #ifdef ORANGE_TX #define SDO_1 (SDO_port.IN & _BV(SDO_pin)) #define SDO_0 (SDO_port.IN & _BV(SDO_pin)) == 0x00 @@ -81,14 +81,14 @@ #endif // SCLK - #define SCLK_port PORTD - #define SCLK_ddr DDRD + #define SCLK_port PORTB + #define SCLK_ddr DDRB #ifdef ORANGE_TX - #define SCLK_pin 7 //PD7 + #define SCLK_pin 7 //PD7 #define SCLK_on SCLK_port.OUTSET = _BV(SCLK_pin) #define SCLK_off SCLK_port.OUTCLR = _BV(SCLK_pin) #else - #define SCLK_pin 4 //D4 = PD4 + #define SCLK_pin 5 //D13 = PB5 = SCLK #define SCLK_output SCLK_ddr |= _BV(SCLK_pin) #define SCLK_on SCLK_port |= _BV(SCLK_pin) #define SCLK_off SCLK_port &= ~_BV(SCLK_pin) @@ -103,22 +103,28 @@ #define A7105_CSN_off A7105_CSN_port &= ~_BV(A7105_CSN_pin) // CC2500 - #define CC25_CSN_pin 7 //D7 = PD7 - #define CC25_CSN_port PORTD - #define CC25_CSN_ddr DDRD + #define CC25_CSN_pin 3 //A3 = PC3 = CSN + #define CC25_CSN_port PORTC + #define CC25_CSN_ddr DDRC #define CC25_CSN_output CC25_CSN_ddr |= _BV(CC25_CSN_pin) #define CC25_CSN_on CC25_CSN_port |= _BV(CC25_CSN_pin) #define CC25_CSN_off CC25_CSN_port &= ~_BV(CC25_CSN_pin) // NRF24L01 - #define NRF_CSN_pin 0 //D8 = PB0 - #define NRF_CSN_port PORTB - #define NRF_CSN_ddr DDRB - #define NRF_CSN_output NRF_CSN_ddr |= _BV(NRF_CSN_pin) - #define NRF_CSN_on NRF_CSN_port |= _BV(NRF_CSN_pin) + // pin D10 is CE which is set to HIGH in setup. In normal multi module not use as CE is hard wired + #define NRF_CE_pin 2 //D10 = PB2 = CE + #define NRF_CE_port PORTB + #define NRF_CE_ddr DDRB + #define NRF_CE_output NRF_CE_ddr |= _BV(NRF_CE_pin) + #define NRF_CE_on NRF_CE_port |= _BV(NRF_CE_pin) + #define NRF_CE_off NRF_CE_port &= ~_BV(NRF_CE_pin) + + #define NRF_CSN_pin 0 //A0 = PC0 = CSN + #define NRF_CSN_port PORTC + #define NRF_CSN_ddr DDRC + #define NRF_CSN_output NRF_CSN_ddr |= _BV(NRF_CSN_pin) ; NRF_CE_output ; NRF_CE_on // Turn CE on so it stays on becasue it is not hard wired like the normal MULTI board + #define NRF_CSN_on NRF_CSN_port |= _BV(NRF_CSN_pin) #define NRF_CSN_off NRF_CSN_port &= ~_BV(NRF_CSN_pin) - #define NRF_CE_on - #define NRF_CE_off // CYRF6936 #ifdef ORANGE_TX @@ -156,7 +162,7 @@ #define PE2_on #define PE2_off #else - #define PE1_pin 1 //A1 = PC1 + #define PE1_pin 4 //A4 = PC4 #define PE1_port PORTC #define PE1_ddr DDRC #define PE1_output PE1_ddr |= _BV(PE1_pin) @@ -182,9 +188,9 @@ #define LED_output LED_port.DIRSET = _BV(LED_pin) #define IS_LED_on (LED_port.OUT & _BV(LED_pin)) #else - #define LED_pin 5 //D13 = PB5 - #define LED_port PORTB - #define LED_ddr DDRB + #define LED_pin 1 //A1 = PC1 + #define LED_port PORTC + #define LED_ddr DDRC #define LED_on LED_port |= _BV(LED_pin) #define LED_off LED_port &= ~_BV(LED_pin) #define LED_toggle LED_port ^= _BV(LED_pin) @@ -198,10 +204,10 @@ #define BIND_port PORTD #define IS_BIND_BUTTON_on ( (BIND_port.IN & _BV(BIND_pin)) == 0x00 ) #else - #define BIND_pin 5 //D13 = PB5 - #define BIND_port PORTB - #define BIND_ipr PINB - #define BIND_ddr DDRB + #define BIND_pin 1 //A1 = PC1 + #define BIND_port PORTC + #define BIND_ipr PINC + #define BIND_ddr DDRC #define BIND_SET_INPUT BIND_ddr &= ~_BV(BIND_pin) #define BIND_SET_OUTPUT BIND_ddr |= _BV(BIND_pin) #define BIND_SET_PULLUP BIND_port |= _BV(BIND_pin) diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index fad0f50..41d8633 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -342,6 +342,7 @@ const PPM_Parameters PPM_prot[15]= { NONE MODE_CABELL CABELL_V3 + CABELL_V3_TELEMETRY CABELL_SET_FAIL_SAFE CABELL_UNBIND */