From a380a747a0eb6ce34a4ccc720d2d1f504946f665 Mon Sep 17 00:00:00 2001 From: "Schoenberger, Philipp" Date: Thu, 28 Feb 2019 13:40:44 +0100 Subject: [PATCH] cleanup multiprotocol --- Multiprotocol/FrSkyD_cc2500.cpp | 59 ++-- Multiprotocol/FrSkyV_cc2500.cpp | 155 --------- Multiprotocol/FrSkyV_cc2500.h | 39 --- Multiprotocol/FrSkyX_cc2500.cpp | 363 -------------------- Multiprotocol/FrSkyX_cc2500.h | 37 -- Multiprotocol/Multiprotocol.h | 478 +------------------------- Multiprotocol/Multiprotocol.ino | 588 ++++---------------------------- Multiprotocol/Validate.h | 248 -------------- Multiprotocol/cc2500_spi.cpp | 14 +- Multiprotocol/cc2500_spi.h | 33 ++ Multiprotocol/common.cpp | 25 +- Multiprotocol/common.h | 14 - Multiprotocol/config.cpp | 35 +- Multiprotocol/config.h | 14 +- Multiprotocol/debug.h | 11 + Multiprotocol/input.cpp | 409 ++++++++-------------- Multiprotocol/input.h | 76 +++-- Multiprotocol/state.cpp | 47 +-- Multiprotocol/state.h | 11 +- Multiprotocol/tx_def.h | 164 --------- 20 files changed, 358 insertions(+), 2462 deletions(-) delete mode 100644 Multiprotocol/FrSkyV_cc2500.cpp delete mode 100644 Multiprotocol/FrSkyV_cc2500.h delete mode 100644 Multiprotocol/FrSkyX_cc2500.cpp delete mode 100644 Multiprotocol/FrSkyX_cc2500.h diff --git a/Multiprotocol/FrSkyD_cc2500.cpp b/Multiprotocol/FrSkyD_cc2500.cpp index b656f22..3aa90d4 100644 --- a/Multiprotocol/FrSkyD_cc2500.cpp +++ b/Multiprotocol/FrSkyD_cc2500.cpp @@ -17,6 +17,7 @@ #include "cc2500_spi.h" #include "Multiprotocol.h" +uint16_t counter; void frsky2way_init(uint8_t bind) { //debugln("frsky2way_init"); @@ -105,12 +106,10 @@ uint16_t initFrSky_2way() { frsky2way_init(1); state = FRSKY_BIND; - debugln("initFrSky_2way bind"); - } - else - { + debugln("initFrSky_2way bind"); + } else { state = FRSKY_BIND_DONE; - debugln("initFrSky_2way bind done"); + debugln("initFrSky_2way bind done"); } return 10000; } @@ -119,8 +118,7 @@ uint16_t ReadFrSky_2way() { //debugln("%s",__func__); - if (state < FRSKY_BIND_DONE) - { + if (state < FRSKY_BIND_DONE) { frsky2way_build_bind_packet(); CC2500_Strobe(CC2500_SIDLE); CC2500_WriteReg(CC2500_0A_CHANNR, 0x00); @@ -129,50 +127,43 @@ uint16_t ReadFrSky_2way() CC2500_WriteData(packet, packet[0]+1); if(IS_BIND_DONE) { state = FRSKY_BIND; - debugln("%s bind done",__func__); - } else - state++; - - if(state == FRSKY_BIND_DONE) { - debugln("%s bind done fr",__func__); - } + debugln("%s bind done",__func__); + } else { + // menu tells us to stop so do not inc state + //state++; + } + + if(state == FRSKY_BIND_DONE) { + debugln("%s bind done fr",__func__); + } return 9000; } - if (state == FRSKY_BIND_DONE) - { + if (state == FRSKY_BIND_DONE) { //debugln("%s bind done",__func__); state = FRSKY_DATA2; frsky2way_init(0); counter = 0; BIND_DONE; - } - else - if (state == FRSKY_DATA5) - { + } else if (state == FRSKY_DATA5) { CC2500_Strobe(CC2500_SRX);//0x34 RX enable state = FRSKY_DATA1; return 9200; } counter = (counter + 1) % 188; - if (state == FRSKY_DATA4) - { //telemetry receive + if (state == FRSKY_DATA4) { //telemetry receive CC2500_SetTxRxMode(RX_EN); CC2500_Strobe(CC2500_SIDLE); CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[counter % 47]); CC2500_WriteReg(CC2500_23_FSCAL3, 0x89); state++; return 1300; - } - else - { - if (state == FRSKY_DATA1) - { + } else { + if (state == FRSKY_DATA1) { len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; //debugln("%d len",len); - if (len && len<=(0x11+3))// 20bytes - { + if (len && len<=(0x11+3)) { // 20bytes CC2500_ReadData(pkt, len); //received telemetry packets #if defined(TELEMETRY) if(pkt[len-1] & 0x80) @@ -181,13 +172,10 @@ uint16_t ReadFrSky_2way() frsky_check_telemetry(pkt,len); //check if valid telemetry packets and buffer them. } #endif - } - else - { + } else { packet_count++; // restart sequence on missed packet - might need count or timeout instead of one missed - if(packet_count>100) - {//~1sec + if(packet_count > 100) {//~1sec packet_count=0; #if defined TELEMETRY telemetry_link=0;//no link frames @@ -200,8 +188,7 @@ uint16_t ReadFrSky_2way() } CC2500_Strobe(CC2500_SIDLE); CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[counter % 47]); - if ( prev_option != option ) - { + if ( prev_option != option ) { CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack prev_option = option ; } diff --git a/Multiprotocol/FrSkyV_cc2500.cpp b/Multiprotocol/FrSkyV_cc2500.cpp deleted file mode 100644 index b6c5a0a..0000000 --- a/Multiprotocol/FrSkyV_cc2500.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - 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. - - Multiprotocol 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 Multiprotocol. If not, see . - */ - -#define FRSKYV_BIND_COUNT 200 -#include "FrSkyV_cc2500.h" -#include "cc2500_spi.h" -#include "common.h" - -uint8_t FRSKYV_crc8(uint8_t result, uint8_t *data, uint8_t len) -{ - for(uint8_t i = 0; i < len; i++) - { - result = result ^ data[i]; - for(uint8_t j = 0; j < 8; j++) - if(result & 0x80) - result = (result << 1) ^ 0x07; - else - result = result << 1; - } - return result; -} - -uint8_t FRSKYV_crc8_le(uint8_t *data, uint8_t len) -{ - uint8_t result = 0xD6; - - for(uint8_t i = 0; i < len; i++) - { - result = result ^ data[i]; - for(uint8_t j = 0; j < 8; j++) - if(result & 0x01) - result = (result >> 1) ^ 0x83; - else - result = result >> 1; - } - return result; -} - -void FRSKYV_build_bind_packet() -{ - //0e 03 01 57 12 00 06 0b 10 15 1a 00 00 00 61 - packet[0] = 0x0e; //Length - packet[1] = 0x03; //Packet type - packet[2] = 0x01; //Packet type - packet[3] = rx_tx_addr[3]; - packet[4] = rx_tx_addr[2]; - packet[5] = (binding_idx % 10) * 5; - packet[6] = packet[5] * 5 + 6; - packet[7] = packet[5] * 5 + 11; - packet[8] = packet[5] * 5 + 16; - packet[9] = packet[5] * 5 + 21; - packet[10] = packet[5] * 5 + 26; - packet[11] = 0x00; - packet[12] = 0x00; - packet[13] = 0x00; - packet[14] = FRSKYV_crc8(0x93, packet, 14); -} - -uint8_t FRSKYV_calc_channel() -{ - uint32_t temp=seed; - temp = (temp * 0xaa) % 0x7673; - seed = temp; - return (seed & 0xff) % 0x32; -} - -void FRSKYV_build_data_packet() -{ - uint8_t idx = 0; // transmit lower channels - - packet[0] = 0x0e; - packet[1] = rx_tx_addr[3]; - packet[2] = rx_tx_addr[2]; - packet[3] = seed & 0xff; - packet[4] = seed >> 8; - if (phase == FRSKYV_DATA1 || phase == FRSKYV_DATA3) - packet[5] = 0x0f; - else - if(phase == FRSKYV_DATA2 || phase == FRSKYV_DATA4) - { - packet[5] = 0xf0; - idx=4; // transmit upper channels - } - else - packet[5] = 0x00; - for(uint8_t i = 0; i < 4; i++) - { - uint16_t value = convert_channel_frsky(i+idx); - packet[2*i + 6] = value & 0xff; - packet[2*i + 7] = value >> 8; - } - packet[14] = FRSKYV_crc8(crc8, packet, 14); -} - -uint16_t ReadFRSKYV() -{ - if(IS_BIND_DONE) - { // Normal operation - uint8_t chan = FRSKYV_calc_channel(); - CC2500_Strobe(CC2500_SIDLE); - if (option != prev_option) - { - CC2500_WriteReg(CC2500_0C_FSCTRL0, option); - prev_option=option; - } - CC2500_WriteReg(CC2500_0A_CHANNR, chan * 5 + 6); - FRSKYV_build_data_packet(); - - if (phase == FRSKYV_DATA5) - { - CC2500_SetPower(); - phase = FRSKYV_DATA1; - } - else - phase++; - - CC2500_WriteData(packet, packet[0]+1); - return 9006; - } - // Bind mode - FRSKYV_build_bind_packet(); - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteReg(CC2500_0A_CHANNR, 0x00); - CC2500_WriteData(packet, packet[0]+1); - binding_idx++; - if(binding_idx>=FRSKYV_BIND_COUNT) - BIND_DONE; - return 53460; -} - -uint16_t initFRSKYV() -{ - //ID is 15 bits. Using rx_tx_addr[2] and rx_tx_addr[3] since we want to use RX_Num for model match - rx_tx_addr[2]&=0x7F; - crc8 = FRSKYV_crc8_le(rx_tx_addr+2, 2); - - FRSKY_init_cc2500(FRSKYV_cc2500_conf); - seed = 1; - binding_idx=0; - phase = FRSKYV_DATA1; - return 10000; -} - diff --git a/Multiprotocol/FrSkyV_cc2500.h b/Multiprotocol/FrSkyV_cc2500.h deleted file mode 100644 index 10294a0..0000000 --- a/Multiprotocol/FrSkyV_cc2500.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - 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. - - Multiprotocol 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 Multiprotocol. If not, see . - */ - -#ifndef _FRSKYV_CC2500_H_ -#define _FRSKYV_CC2500_H_ - -#define FRSKYV_BIND_COUNT 200 -#include -#include "Multiprotocol.h" - -enum frskyv_data_e { - FRSKYV_DATA1=0, - FRSKYV_DATA2, - FRSKYV_DATA3, - FRSKYV_DATA4, - FRSKYV_DATA5 -}; - -uint8_t FRSKYV_crc8(uint8_t result, uint8_t *data, uint8_t len); - -uint8_t FRSKYV_crc8_le(uint8_t *data, uint8_t len); -void FRSKYV_build_bind_packet(void); -uint8_t FRSKYV_calc_channel(void); -void FRSKYV_build_data_packet(void); -uint16_t ReadFRSKYV(void); -uint16_t initFRSKYV(void); -#endif diff --git a/Multiprotocol/FrSkyX_cc2500.cpp b/Multiprotocol/FrSkyX_cc2500.cpp deleted file mode 100644 index 3aeb3a2..0000000 --- a/Multiprotocol/FrSkyX_cc2500.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/* ************************** - * By Midelic on RCGroups * - ************************** - 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. - - Multiprotocol 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 Multiprotocol. If not, see . -*/ - - - -#include "Arduino.h" -#include "Multiprotocol.h" -#include "FrSkyX_cc2500.h" -#include -#include "common.h" -#include "cc2500_spi.h" - -uint8_t FrX_chanskip; -uint8_t FrX_send_seq ; -uint8_t FrX_receive_seq ; - -void frskyX_set_start(uint8_t ch) -{ - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]); - CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]); -} - -void frskyX_init(void) -{ - FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC - // - for(uint8_t c=0;c < 48;c++) - {//calibrate hop channels - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]); - CC2500_Strobe(CC2500_SCAL); - delayMicroseconds(900);// - calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1); - } - //#######END INIT######## -} - -void frskyX_initialize_data(uint8_t adr) -{ - CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack - CC2500_WriteReg(CC2500_18_MCSM0, 0x8); - CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]); - CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05); -} - -//**CRC** -const uint16_t frskyX_CRC_Short[]={ - 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, - 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 }; - -uint16_t frskyX_CRCTable(uint8_t val) -{ - uint16_t word ; - word = pgm_read_word(&frskyX_CRC_Short[val&0x0F]) ; - val /= 16 ; - return word ^ (0x1081 * val) ; -} - -uint16_t frskyX_crc_x(uint8_t *data, uint8_t len) -{ - uint16_t crc = 0; - for(uint8_t i=0; i < len; i++) - crc = (crc<<8) ^ frskyX_CRCTable((uint8_t)(crc>>8) ^ *data++); - return crc; -} - -void frskyX_build_bind_packet(void) -{ - // debugln("%s:%d build bind", __func__, __LINE__); - packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC - packet[1] = 0x03; - packet[2] = 0x01; - // - packet[3] = rx_tx_addr[3]; - packet[4] = rx_tx_addr[2]; - int idx = ((state -FRSKY_BIND) % 10) * 5; - packet[5] = idx; - packet[6] = hopping_frequency[idx++]; - packet[7] = hopping_frequency[idx++]; - packet[8] = hopping_frequency[idx++]; - packet[9] = hopping_frequency[idx++]; - packet[10] = hopping_frequency[idx++]; - packet[11] = 0x02; - packet[12] = RX_num; - // - uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; - memset(&packet[13], 0, limit - 13); - uint16_t lcrc = frskyX_crc_x(&packet[3], limit-3); - // - packet[limit++] = lcrc >> 8; - packet[limit] = lcrc; - // -} - -// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182 -//64=860,1024=1500,1984=2140//Taranis 125% -uint16_t frskyX_scaleForPXX(uint8_t i) -{ //mapped 860,2140(125%) range to 64,1984(PXX values); - uint16_t chan_val=convert_channel_frsky(i)-1226; - if(i>7) chan_val|=2048; // upper channels offset - return chan_val; -} - -uint16_t frskyX_scaleForPXX_FS(uint8_t i) -{ //mapped 1,2046(125%) range to 64,1984(PXX values); - uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64; - if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES) - chan_val=FAILSAFE_CHANNEL_NOPULSES; - else if(Failsafe_data[i]==FAILSAFE_CHANNEL_HOLD) - chan_val=FAILSAFE_CHANNEL_HOLD; - if(i>7) chan_val|=2048; // upper channels offset - return chan_val; -} - -void frskyX_data_frame(void) -{ - //0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12 - // - static uint8_t chan_offset=0; - uint16_t chan_0 ; - uint16_t chan_1 ; - // - // data frames sent every 9ms; failsafe every 9 seconds - #ifdef FAILSAFE_ENABLE - static uint16_t failsafe_count=0; - static uint8_t FS_flag=0,failsafe_chan=0; - if (FS_flag == 0 && failsafe_count > FRX_FAILSAFE_TIME && chan_offset == 0 && IS_FAILSAFE_VALUES_on) - { - FS_flag = 0x10; - failsafe_chan = 0; - } else if (FS_flag & 0x10 && failsafe_chan < (sub_protocol & 0x01 ? 8-1:16-1)) - { - FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet - failsafe_chan ++; - } else if (FS_flag & 0x10) - { - FS_flag = 0; - failsafe_count = 0; - } - failsafe_count++; - #endif - - packet[0] = (sub_protocol & 0x02 ) ? 0x20 : 0x1D ; // LBT or FCC - packet[1] = rx_tx_addr[3]; - packet[2] = rx_tx_addr[2]; - packet[3] = 0x02; - // - packet[4] = (FrX_chanskip<<6)|hopping_frequency_no; - packet[5] = FrX_chanskip>>2; - packet[6] = RX_num; - //packet[7] = FLAGS 00 - standard packet - //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet - //20 - range check packet - #ifdef FAILSAFE_ENABLE - packet[7] = FS_flag; - #else - packet[7] = 0; - #endif - packet[8] = 0; - // - uint8_t startChan = chan_offset; for(uint8_t i = 0; i <12 ; i+=3) - {//12 bytes of channel data - #ifdef FAILSAFE_ENABLE - if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) ) - chan_0 = frskyX_scaleForPXX_FS(failsafe_chan); - else - #endif - chan_0 = frskyX_scaleForPXX(startChan); - startChan++; - // - #ifdef FAILSAFE_ENABLE - if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) ) - chan_1 = frskyX_scaleForPXX_FS(failsafe_chan); - else - #endif - chan_1 = frskyX_scaleForPXX(startChan); - startChan++; - // - packet[9+i] = lowByte(chan_0); //3 bytes*4 - packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4)); - packet[9+i+2]=chan_1>>4; - } - packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start - - if(sub_protocol & 0x01 ) // in X8 mode send only 8ch every 9ms - chan_offset = 0 ; - else - chan_offset^=0x08; - - uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; - for (uint8_t i=22;i>8;//high byte - packet[limit]=lcrc;//low byte -} - -uint16_t ReadFrSkyX(void) -{ - switch(state) - { - default: - frskyX_set_start(47); - CC2500_SetPower(); - CC2500_Strobe(CC2500_SFRX); - // - frskyX_build_bind_packet(); - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteData(packet, packet[0]+1); - if(IS_BIND_DONE) { - state = FRSKY_BIND_DONE; - //debugln("%s:%d bind done", __func__, __LINE__); - } - else - state++; - return 9000; - case FRSKY_BIND_DONE: - frskyX_initialize_data(0); - hopping_frequency_no=0; - BIND_DONE; - state++; - break; - case FRSKY_DATA1: - if ( prev_option != option ) - { - CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack - prev_option = option ; - } - CC2500_SetTxRxMode(TX_EN); - frskyX_set_start(hopping_frequency_no); - CC2500_SetPower(); - CC2500_Strobe(CC2500_SFRX); - hopping_frequency_no = (hopping_frequency_no+FrX_chanskip)%47; - CC2500_Strobe(CC2500_SIDLE); - CC2500_WriteData(packet, packet[0]+1); - // -// frskyX_data_frame(); - state++; - return 5200; - case FRSKY_DATA2: - CC2500_SetTxRxMode(RX_EN); - CC2500_Strobe(CC2500_SIDLE); - state++; - return 200; - case FRSKY_DATA3: - CC2500_Strobe(CC2500_SRX); - state++; - return 3100; - case FRSKY_DATA4: - len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; - if (len && (len<=(0x0E + 3))) //Telemetry frame is 17 - { - packet_count=0; - CC2500_ReadData(pkt, len); - #if defined TELEMETRY - frsky_check_telemetry(pkt,len); //check if valid telemetry packets - //parse telemetry packets here - //The same telemetry function used by FrSky(D8). - #endif - } - else - { - packet_count++; - // restart sequence on missed packet - might need count or timeout instead of one missed - if(packet_count>100) - {//~1sec -// seq_last_sent = 0; -// seq_last_rcvd = 8; - FrX_send_seq = 0x08 ; -// FrX_receive_seq = 0 ; - packet_count=0; - #if defined TELEMETRY - telemetry_lost=1; - #endif - } - CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO - } - frskyX_data_frame(); - if ( FrX_send_seq != 0x08 ) - { - FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ; - } - state = FRSKY_DATA1; - return 500; - } - return 1; -} - -uint16_t initFrSkyX(void) -{ - set_rx_tx_addr(MProtocol_id_master); - Frsky_init_hop(); - packet_count=0; - while(!FrX_chanskip) - FrX_chanskip=random(0xfefefefe)%47; - - //for test*************** - rx_tx_addr[3]=0xB3; - rx_tx_addr[2]=0xFD; - //************************ - frskyX_init(); -#if defined SPORT_POLLING -#ifdef INVERT_SERIAL - start_timer4() ; -#endif -#endif - // - if(IS_BIND_IN_PROGRESS) - { - state = FRSKY_BIND; - frskyX_initialize_data(1); - } - else - { - state = FRSKY_DATA1; - frskyX_initialize_data(0); - } -// seq_last_sent = 0; -// seq_last_rcvd = 8; - FrX_send_seq = 0x08 ; - FrX_receive_seq = 0 ; - return 10000; -} diff --git a/Multiprotocol/FrSkyX_cc2500.h b/Multiprotocol/FrSkyX_cc2500.h deleted file mode 100644 index 9bab442..0000000 --- a/Multiprotocol/FrSkyX_cc2500.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ************************** - * By Midelic on RCGroups * - ************************** - 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. - - Multiprotocol 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 Multiprotocol. If not, see . -*/ - -#ifndef _FRSKYX_CC2500_H_ -#define _FRSKYX_CC2500_H_ -#include - -#define FRX_FAILSAFE_TIMEOUT 1032 -#define FRX_FAILSAFE_TIME 1032 - -void frskyX_set_start(uint8_t ch); -void frskyX_init(void); -void frskyX_initialize_data(uint8_t adr); -uint16_t frskyX_CRCTable(uint8_t val); -uint16_t frskyX_crc_x(uint8_t *data, uint8_t len); -void frskyX_build_bind_packet(void); -uint16_t frskyX_scaleForPXX(uint8_t i); -uint16_t frskyX_scaleForPXX_FS(uint8_t i); - -void frskyX_data_frame(void); -uint16_t ReadFrSkyX(void); -uint16_t initFrSkyX(void); -#endif diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index 5c69e8d..0ae59e9 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -25,7 +25,6 @@ void set_rx_tx_addr(uint32_t id); #define MAX_PKT 29 -extern volatile uint16_t PPM_data[NUM_CHN]; extern uint8_t hopping_frequency_no; extern uint8_t sub_protocol; extern uint8_t calData[48]; @@ -34,11 +33,8 @@ extern uint8_t protocol_flags; extern uint8_t protocol_flags2; extern uint8_t pkt[MAX_PKT];//telemetry receiving packets extern uint8_t prev_option; -extern uint8_t prev_power; // unused power value -extern uint16_t counter; extern uint8_t hopping_frequency[50]; extern uint8_t crc8; -extern uint16_t Channel_data[NUM_CHN]; extern uint8_t packet_count; extern uint8_t RX_num; extern uint8_t binding_idx; @@ -67,14 +63,13 @@ enum MultiPacketTypes }; // Macros +#ifndef _BV #define _BV(i) (1<CHANNEL_SWITCH) -#define CH14_SW (Channel_data[CH14]>CHANNEL_SWITCH) -#define CH15_SW (Channel_data[CH15]>CHANNEL_SWITCH) -#define CH16_SW (Channel_data[CH16]>CHANNEL_SWITCH) - -//************************ -//*** Power settings *** -//************************ -enum { - TXPOWER_100uW, - TXPOWER_300uW, - TXPOWER_1mW, - TXPOWER_3mW, - TXPOWER_10mW, - TXPOWER_30mW, - TXPOWER_100mW, - TXPOWER_150mW -}; - -// A7105 power -// Power amp is ~+16dBm so: -enum A7105_POWER -{ - A7105_POWER_0 = 0x00<<3 | 0x00, // TXPOWER_100uW = -23dBm == PAC=0 TBG=0 - A7105_POWER_1 = 0x00<<3 | 0x01, // TXPOWER_300uW = -20dBm == PAC=0 TBG=1 - A7105_POWER_2 = 0x00<<3 | 0x02, // TXPOWER_1mW = -16dBm == PAC=0 TBG=2 - A7105_POWER_3 = 0x00<<3 | 0x04, // TXPOWER_3mW = -11dBm == PAC=0 TBG=4 - A7105_POWER_4 = 0x01<<3 | 0x05, // TXPOWER_10mW = -6dBm == PAC=1 TBG=5 - A7105_POWER_5 = 0x02<<3 | 0x07, // TXPOWER_30mW = 0dBm == PAC=2 TBG=7 - A7105_POWER_6 = 0x03<<3 | 0x07, // TXPOWER_100mW = 1dBm == PAC=3 TBG=7 - A7105_POWER_7 = 0x03<<3 | 0x07 // TXPOWER_150mW = 1dBm == PAC=3 TBG=7 -}; -#define A7105_HIGH_POWER A7105_POWER_7 -#define A7105_LOW_POWER A7105_POWER_3 -#define A7105_RANGE_POWER A7105_POWER_0 -#define A7105_BIND_POWER A7105_POWER_0 - -// NRF Power -// Power setting is 0..3 for nRF24L01 -// Claimed power amp for nRF24L01 from eBay is 20dBm. -enum NRF_POWER -{ // Raw w 20dBm PA - NRF_POWER_0 = 0x00, // 0 : -18dBm (16uW) 2dBm (1.6mW) - NRF_POWER_1 = 0x01, // 1 : -12dBm (60uW) 8dBm (6mW) - NRF_POWER_2 = 0x02, // 2 : -6dBm (250uW) 14dBm (25mW) - NRF_POWER_3 = 0x03 // 3 : 0dBm (1mW) 20dBm (100mW) -}; -#define NRF_HIGH_POWER NRF_POWER_3 -#define NRF_LOW_POWER NRF_POWER_1 -#define NRF_RANGE_POWER NRF_POWER_0 -#define NRF_BIND_POWER NRF_POWER_0 - -// CC2500 power output from the chip itself -// The numbers do not take into account any outside amplifier -enum CC2500_POWER -{ - CC2500_POWER_0 = 0x00, // -55dbm or less - CC2500_POWER_1 = 0x50, // -30dbm - CC2500_POWER_2 = 0x44, // -28dbm - CC2500_POWER_3 = 0xC0, // -26dbm - CC2500_POWER_4 = 0x84, // -24dbm - CC2500_POWER_5 = 0x81, // -22dbm - CC2500_POWER_6 = 0x46, // -20dbm - CC2500_POWER_7 = 0x93, // -18dbm - CC2500_POWER_8 = 0x55, // -16dbm - CC2500_POWER_9 = 0x8D, // -14dbm - CC2500_POWER_10 = 0xC6, // -12dbm - CC2500_POWER_11 = 0x97, // -10dbm - CC2500_POWER_12 = 0x6E, // -8dbm - CC2500_POWER_13 = 0x7F, // -6dbm - CC2500_POWER_14 = 0xA9, // -4dbm - CC2500_POWER_15 = 0xBB, // -2dbm - CC2500_POWER_16 = 0xFE, // 0dbm - CC2500_POWER_17 = 0xFF // +1dbm -}; -#define CC2500_HIGH_POWER CC2500_POWER_1 -#define CC2500_LOW_POWER CC2500_POWER_1 -#define CC2500_RANGE_POWER CC2500_POWER_1 -#define CC2500_BIND_POWER CC2500_POWER_1 - -// CYRF power -enum CYRF_POWER -{ - CYRF_POWER_0 = 0x00, // -35dbm - CYRF_POWER_1 = 0x01, // -30dbm - CYRF_POWER_2 = 0x02, // -24dbm - CYRF_POWER_3 = 0x03, // -18dbm - CYRF_POWER_4 = 0x04, // -13dbm - CYRF_POWER_5 = 0x05, // -5dbm - CYRF_POWER_6 = 0x06, // 0dbm - CYRF_POWER_7 = 0x07 // +4dbm -}; -#define CYRF_HIGH_POWER CYRF_POWER_7 -#define CYRF_LOW_POWER CYRF_POWER_3 -#define CYRF_RANGE_POWER CYRF_POWER_1 // 1/30 of the full power distance -#define CYRF_BIND_POWER CYRF_POWER_0 - -enum TXRX_State { - TXRX_OFF, - TX_EN, - RX_EN -}; - -// Packet ack status values -enum { - PKT_PENDING = 0, - PKT_ACKED, - PKT_TIMEOUT -}; - -// baudrate defines for serial -#define SPEED_100K 0 -#define SPEED_9600 1 -#define SPEED_57600 2 -#define SPEED_125K 3 - -/** EEPROM Layout */ -#define EEPROM_ID_OFFSET 10 // Module ID (4 bytes) -#define EEPROM_BANK_OFFSET 15 // Current bank number (1 byte) -#define EEPROM_ID_VALID_OFFSET 20 // 1 byte flag that ID is valid -#define MODELMODE_EEPROM_OFFSET 30 // Autobind mode, 1 byte per model, end is 30+16=46 -#define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 byte per model id, end is 50+64=114 -#define BUGS_EEPROM_OFFSET 114 // RX ID, 4 byte per model id, end is 114+64=178 -//#define CONFIG_EEPROM_OFFSET 178 // Current configuration of the multimodule - -//**************************************** -//*** MULTI protocol serial definition *** -//**************************************** -/* -************************** -16 channels serial protocol -************************** -Serial: 100000 Baud 8e2 _ xxxx xxxx p -- - Total of 26 bytes - Stream[0] = 0x55 sub_protocol values are 0..31 Stream contains channels - Stream[0] = 0x54 sub_protocol values are 32..63 Stream contains channels - Stream[0] = 0x57 sub_protocol values are 0..31 Stream contains failsafe - Stream[0] = 0x56 sub_protocol values are 32..63 Stream contains failsafe - header - Stream[1] = sub_protocol|BindBit|RangeCheckBit|AutoBindBit; - sub_protocol is 0..31 (bits 0..4), value should be added with 32 if Stream[0] = 0x54 - => Reserved 0 - Flysky 1 - Hubsan 2 - FrskyD 3 - Hisky 4 - V2x2 5 - DSM 6 - Devo 7 - YD717 8 - KN 9 - SymaX 10 - SLT 11 - CX10 12 - CG023 13 - Bayang 14 - FrskyX 15 - ESky 16 - MT99XX 17 - MJXQ 18 - SHENQI 19 - FY326 20 - SFHSS 21 - J6PRO 22 - FQ777 23 - ASSAN 24 - FrskyV 25 - HONTAI 26 - OpenLRS 27 - AFHDS2A 28 - Q2X2 29 - WK2x01 30 - Q303 31 - GW008 32 - DM002 33 - CABELL 34 - ESKY150 35 - H8_3D 36 - CORONA 37 - CFlie 38 - Hitec 39 - WFLY 40 - BUGS 41 - BindBit=> 0x80 1=Bind/0=No - AutoBindBit=> 0x40 1=Yes /0=No - RangeCheck=> 0x20 1=Yes /0=No - Stream[2] = RxNum | Power | Type; - RxNum value is 0..15 (bits 0..3) - Type is 0..7 <<4 (bit 4..6) - sub_protocol==Flysky - Flysky 0 - V9x9 1 - V6x6 2 - V912 3 - CX20 4 - sub_protocol==Hubsan - H107 0 - H301 1 - H501 2 - sub_protocol==Hisky - Hisky 0 - HK310 1 - sub_protocol==DSM - DSM2_22 0 - DSM2_11 1 - DSMX_22 2 - DSMX_11 3 - DSM_AUTO 4 - sub_protocol==YD717 - YD717 0 - SKYWLKR 1 - SYMAX4 2 - XINXUN 3 - NIHUI 4 - sub_protocol==KN - WLTOYS 0 - FEILUN 1 - sub_protocol==SYMAX - SYMAX 0 - SYMAX5C 1 - sub_protocol==CX10 - CX10_GREEN 0 - CX10_BLUE 1 // also compatible with CX10-A, CX12 - DM007 2 - --- 3 - JC3015_1 4 - JC3015_2 5 - MK33041 6 - sub_protocol==Q2X2 - Q222 0 - Q242 1 - Q282 2 - sub_protocol==CG023 - CG023 0 - YD829 1 - sub_protocol==BAYANG - BAYANG 0 - H8S3D 1 - X16_AH 2 - IRDRONE 3 - sub_protocol==MT99XX - MT99 0 - H7 1 - YZ 2 - LS 3 - FY805 4 - sub_protocol==MJXQ - WLH08 0 - X600 1 - X800 2 - H26D 3 - E010 4 - H26WH 5 - sub_protocol==FRSKYX - CH_16 0 - CH_8 1 - EU_16 2 - EU_8 3 - sub_protocol==HONTAI - HONTAI 0 - JJRCX1 1 - X5C1 2 - FQ777_951 3 - sub_protocol==AFHDS2A - PWM_IBUS 0 - PPM_IBUS 1 - PWM_SBUS 2 - PPM_SBUS 3 - sub_protocol==V2X2 - V2X2 0 - JXD506 1 - sub_protocol==FY326 - FY326 0 - FY319 1 - sub_protocol==WK2x01 - WK2801 0 - WK2401 1 - W6_5_1 2 - W6_6_1 3 - W6_HEL 4 - W6_HEL_I 5 - sub_protocol==Q303 - Q303 0 - CX35 1 - CX10D 2 - CX10WD 3 - sub_protocol==CABELL - CABELL_V3 0 - CABELL_V3_TELEMETRY 1 - CABELL_SET_FAIL_SAFE 6 - CABELL_UNBIND 7 - sub_protocol==H8_3D - H8_3D 0 - H20H 1 - H20MINI 2 - H30MINI 3 - sub_protocol==CORONA - COR_V1 0 - COR_V2 1 - FD_V3 2 - sub_protocol==HITEC - OPT_FW 0 - OPT_HUB 1 - MINIMA 2 - sub_protocol==SLT - SLT_V1 0 - SLT_V2 1 - Q100 2 - Q200 3 - MR100 4 - - Power value => 0x80 0=High/1=Low - Stream[3] = option_protocol; - option_protocol value is -128..127 - Stream[4] to [25] = Channels or failsafe depending on Steam[0] - 16 Channels on 11 bits (0..2047) - 0 -125% - 204 -100% - 1024 0% - 1843 +100% - 2047 +125% - Values are concatenated to fit in 22 bytes like in SBUS protocol. - Failsafe values have exactly the same range/values than normal channels except the extremes where - 0=hold, 2047=no pulse. If failsafe is not set or RX then failsafe packets should not be sent. -*/ -/* - Multimodule Status - Based on #define MULTI_STATUS - - Serial: 100000 Baud 8e2 (same as input) - - Format: header (2 bytes) + data (variable) - [0] = 'M' (0x4d) - [1] Length (excluding the 2 header bytes) - [2-xx] data - - Type = 0x01 Multimodule Status: - [2] Flags - 0x01 = Input signal detected - 0x02 = Serial mode enabled - 0x04 = Protocol is valid - 0x08 = Module is in binding mode - 0x10 = Module waits a bind event to load the protocol - 0x20 = Failsafe supported by currently running protocol - [3] major - [4] minor - [5] revision - [6] patchlevel, - version of multi code, should be displayed as major.minor.revision.patchlevel -*/ -/* - Multiprotocol telemetry/command definition for OpenTX - Based on #define MULTI_TELEMETRY enables OpenTX to get the multimodule status and select the correct telemetry type automatically. - - Serial: 100000 Baud 8e2 (same as input) - - TLV Protocol (type, length, value), allows a TX to ignore unknown messages - - Format: header (4 byte) + data (variable) - [0] = 'M' (0x4d) - [1] = 'P' (0x50) - - The first byte is deliberatly chosen to be different from other telemetry protocols - (e.g. 0xAA for DSM/Multi, 0xAA for FlySky and 0x7e for Frsky) to allow a TX to detect - the telemetry format of older versions - - [2] Type (see below) - [3] Length (excluding the 4 header bytes) - - [4-xx] data#define EEPROM_BANK_OFFSET 15 // Current bank number (1 byte) - - - Commands from TX to multi cannot be longer than 22 bytes (RXLen -4byte header) - - Type = 0x01 Multimodule Status: - [4] Flags - 0x01 = Input signal detected - 0x02 = Serial mode enabled - 0x04 = protocol is valid - 0x08 = module is in binding mode - 0x10 = module waits a bind event to load the protocol - [5] major - [6] minor - [7] revision - [8] patchlevel, - version of multi code, should be displayed as major.minor.revision.patchlevel - - more information can be added by specifing a longer length of the type, the TX will just ignore these bytes - - - Type 0x02 Frksy S.port telemetry - Type 0x03 Frsky Hub telemetry - - *No* usual frsky byte stuffing and without start/stop byte (0x7e) - - - Type 0x04 Spektrum telemetry data - data[0] TX RSSI - data[1-15] telemetry data - - Type 0x05 DSM bind data - data[0-16] DSM bind data - - technically DSM bind data is only 10 bytes but multi sends 16 - like with telemtery, check length field) - - Type 0x06 Flysky AFHDS2 telemetry data - length: 29 - data[0] = RSSI value - data[1-28] telemetry data - - Type 0x0A Hitec telemetry data - length: 8 - data[0] = TX RSSI value - data[1] = TX LQI value - data[2] = frame number - data[3-7] telemetry data - Full description at the bottom of Hitec_cc2500.ino - -*/ #endif diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index d1ea344..af1e8c1 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -22,18 +22,13 @@ */ -//#define DEBUG_PIN // Use pin TX for AVR and SPI_CS for STM32 => DEBUG_PIN_on, DEBUG_PIN_off, DEBUG_PIN_toggle #define DEBUG_SERIAL // Only for STM32_BOARD compiled with Upload method "Serial"->usart1, "STM32duino bootloader"->USB serial -#if defined (ARDUINO_AVR_XMEGA32D4) || defined (ARDUINO_MULTI_ORANGERX) - #include "MultiOrange.h" -#endif #include "config.h" #include "tx_def.h" #include "Multiprotocol.h" -//Multiprotocol module configuration file #include "pins.h" #include "Validate.h" @@ -42,8 +37,8 @@ #include "input.h" #include "cc2500_spi.h" -#include "FrSkyX_cc2500.h" -#include "FrSkyV_cc2500.h" +//#include "FrSkyX_cc2500.h" +//#include "FrSkyV_cc2500.h" #include "FrSkyD_cc2500.h" //Global constants/variables @@ -52,13 +47,11 @@ uint32_t MProtocol_id_master; uint32_t blink=0,last_signal=0; uint8_t protocol_flags=0,protocol_flags2=0; // -uint16_t counter; uint8_t channel; uint8_t packet[40]; -// Servo data -uint16_t Channel_data[NUM_CHN]; -uint8_t Channel_AUX; + +uint16_t seed; // Protocol variables uint8_t cyrfmfg_id[6];//for dsm2 and devo @@ -80,7 +73,6 @@ uint8_t throttle, rudder, elevator, aileron; uint8_t flags; uint16_t crc; uint8_t crc8; -uint16_t seed; uint16_t failsafe_count; uint16_t state; uint8_t len; @@ -89,18 +81,12 @@ uint8_t len; uint8_t calData[48]; #endif -//Channel mapping for protocols -const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; -const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; -const uint8_t CH_RETA[]={RUDDER, ELEVATOR, THROTTLE, AILERON, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; -const uint8_t CH_EATR[]={ELEVATOR, AILERON, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9, CH10, CH11, CH12, CH13, CH14, CH15, CH16}; // Mode_select variables uint8_t mode_select; #ifdef ENABLE_PPM // PPM variable -volatile uint16_t PPM_data[NUM_CHN]; volatile uint8_t PPM_chan_max=0; #endif @@ -115,7 +101,6 @@ uint8_t protocol; uint8_t option; uint8_t cur_protocol[3]; uint8_t prev_option; -uint8_t prev_power=0xFD; // unused power value uint8_t RX_num; //Serial RX variables @@ -136,36 +121,24 @@ void_function_t remote_callback = 0; void setup() { // Setup diagnostic uart before anything else - #ifdef DEBUG_SERIAL + #ifdef ENABLE_DBEUG Serial.begin(115200,SERIAL_8N1); while (!Serial); // Wait for ever for the serial port to connect... debugln("Multiprotocol startup"); debugln("time %s ", __TIME__); #endif - // General pinout - //ATMEGA328p // all inputs // outputs SDI_output; SCLK_output; CC25_CSN_output; - // Timer1 config - #ifdef TCCR1A - TCCR1A = 0; - TCCR1B = (1 << CS11); //prescaler8, set timer1 to increment every 0.5us(16Mhz) and start timer - #endif // Random //random_init(); CC25_CSN_on; - // Set SPI lines - #ifdef STM32_BOARD - initSPI2(); - #else SDI_on; SCLK_off; - #endif //Wait for every component to start delay(100); @@ -217,13 +190,6 @@ void setup() } debugln("Protocol selection switch reads as %d", mode_select); - #ifdef ENABLE_PPM - uint8_t bank=bank_switch(); - #endif - - // Set default channels' value - InitChannel(); - InitPPM(); // Update LED LED_off; LED_output; @@ -231,18 +197,20 @@ void setup() //Init RF modules modules_reset(); - randomSeed(42); + { + seed = analogRead(PA0); + randomSeed(seed); + } // Read or create protocol id - MProtocol_id_master=random_id(10,false); + MProtocol_id_master=random_id(false); debugln("Module Id: %lx", MProtocol_id_master); #ifdef ENABLE_PPM //Protocol and interrupts initialization - if(mode_select != MODE_SERIAL) - { // PPM - uint8_t line=bank*14+mode_select-1; + { + uint8_t line=curr_bank*14+mode_select-1; protocol = PPM_prot[line].protocol; cur_protocol[1] = protocol; sub_protocol = PPM_prot[line].sub_proto; @@ -265,8 +233,7 @@ void setup() debugln("freq offset: %d", option); if(PPM_prot[line].power) POWER_FLAG_on; - if(PPM_prot[line].autobind) - { + if(PPM_prot[line].autobind) { AUTOBIND_FLAG_on; BIND_IN_PROGRESS; // Force a bind at protocol startup } @@ -274,11 +241,7 @@ void setup() protocol_init(); - #if defined(TELEMETRY) - PPM_Telemetry_serial_init();// Configure serial for telemetry - #endif } - else #endif //ENABLE_PPM debugln("Init complete"); input.init(); @@ -310,8 +273,15 @@ void loop() next_callback = remote_callback(); if (next_callback > 4000) { + uint32_t s; + + s =micros(); input.update(); - //update_state(); + debugln("input took %lu", (micros()-s)); + + s =micros(); + update_state(); + debugln("state took %lu", (micros()-s)); } uint32_t wait_until = start + next_callback; @@ -328,47 +298,21 @@ void loop() } uint8_t Update_All() { - #ifdef ENABLE_SERIAL - if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received - { - update_serial_data(); // Update protocol and data - update_channels_aux(); - last_signal=millis(); - } - #endif //ENABLE_SERIAL - #ifdef ENABLE_PPM - if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received - { - debugln("%s:%d",__func__, __LINE__); - for(uint8_t i=0;iCHANNEL_MAX_125) val=CHANNEL_MAX_125; - //Channel_data[i]=val; - } - PPM_FLAG_off; // wait for next frame before update - update_channels_aux(); - last_signal=millis(); - } - #endif //ENABLE_PPM - - + #ifdef ENABLE_BIND_CH - if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && Channel_data[BIND_CH-1]>CHANNEL_MAX_COMMAND && Channel_data[THROTTLE]<(CHANNEL_MIN_100+50)) - { // Autobind is on and BIND_CH went up and Throttle is low + if(IS_AUTOBIND_FLAG_on && + IS_BIND_CH_PREV_off && + Channel_data[BIND_CH-1] > CHANNEL_MAX_COMMAND && + Channel_data[Input::CH_THROTTLE] < (CHANNEL_MIN_100+50) + ) { // Autobind is on and BIND_CH went up and Throttle is low CHANGE_PROTOCOL_FLAG_on; //reload protocol BIND_IN_PROGRESS; //enable bind - debugln("%s:%d set bind prog",__func__, __LINE__); + debugln("%s:%d set bind prog",__func__, __LINE__); BIND_CH_PREV_on; } - if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_on && Channel_data[BIND_CH-1]CHANNEL_SWITCH) - Channel_AUX|=1<=NBR_BANKS) - { // Wrong number of bank - curr_bank = 0; // set bank to 0 - bank=0; - } - debugln("Using bank %d", bank); - - phase=3; - uint32_t check=millis(); - blink=millis(); - while(mode_select==15) - { //loop here if the dial is on position 15 for user to select the bank - if(blink>2) >= bank) - { - phase=0; - blink+=BLINK_BANK_REPEAT; - } - else - phase+=2; - break; - case 3: - blink+=BLINK_BANK_TIME_LOW; - phase=0; - break; - } - } - if(check=NBR_BANKS) - bank=0; - curr_bank = bank; - debugln("Using bank %d", bank); - phase=3; - blink+=BLINK_BANK_REPEAT; - check+=2*BLINK_BANK_REPEAT; - } - check+=1; - } - } - return bank; -} -#endif - -inline void tx_pause() -{ - #ifdef TELEMETRY - // Pause telemetry by disabling transmitter interrupt - #ifdef ORANGE_TX - USARTC0.CTRLA &= ~0x03 ; - #else - #ifndef BASH_SERIAL - #ifdef STM32_BOARD - USART3_BASE->CR1 &= ~ USART_CR1_TXEIE; - #else - UCSR0B &= ~_BV(UDRIE0); - #endif - #endif - #endif - #endif -} - -inline void tx_resume() -{ - #ifdef TELEMETRY - // Resume telemetry by enabling transmitter interrupt - #ifndef SPORT_POLLING - if(!IS_TX_PAUSE_on) - #endif - { - #ifdef ORANGE_TX - cli() ; - USARTC0.CTRLA = (USARTC0.CTRLA & 0xFC) | 0x01 ; - sei() ; - #else - #ifndef BASH_SERIAL - #ifdef STM32_BOARD - USART3_BASE->CR1 |= USART_CR1_TXEIE; - #else - UCSR0B |= _BV(UDRIE0); - #endif - #else - resumeBashSerial(); - #endif - #endif - } - #endif -} - // Protocol start static void protocol_init() { static uint16_t next_callback; @@ -536,10 +348,6 @@ static void protocol_init() { MProtocol_id = RX_num + MProtocol_id_master; set_rx_tx_addr(MProtocol_id); - #ifdef FAILSAFE_ENABLE - InitFailsafe(); - #endif - blink=millis(); debugln("Protocol selected: %d, sub proto %d, rxnum %d, option %d", protocol, sub_protocol, RX_num, option); @@ -550,20 +358,12 @@ static void protocol_init() { next_callback = initFrSky_2way(); remote_callback = ReadFrSky_2way; break; - case PROTO_FRSKYV: - next_callback = initFRSKYV(); - remote_callback = ReadFRSKYV; - break; - case PROTO_FRSKYX: - next_callback = initFrSkyX(); - remote_callback = ReadFrSkyX; - break; } } #if defined(WAIT_FOR_BIND) && defined(ENABLE_BIND_CH) - if( IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && (cur_protocol[1]&0x80)==0 && mode_select == MODE_SERIAL) - { // Autobind is active but no bind requested by either BIND_CH or BIND. But do not wait if in PPM mode... + if( IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && (cur_protocol[1]&0x80)==0 && mode_select == MODE_SERIAL) { + // Autobind is active but no bind requested by either BIND_CH or BIND. But do not wait if in PPM mode... WAIT_BIND_on; return; } @@ -577,74 +377,36 @@ static void protocol_init() { void update_serial_data() { - RX_DONOTUPDATE_on; - RX_FLAG_off; //data is being processed - #ifdef SAMSON // Extremely dangerous, do not enable this unless you know what you are doing... - if( rx_ok_buff[0]==0x55 && (rx_ok_buff[1]&0x1F)==PROTO_FRSKYD && rx_ok_buff[2]==0x7F && rx_ok_buff[24]==217 && rx_ok_buff[25]==202 ) - {//proto==FRSKYD+sub==7+rx_num==7+CH15==73%+CH16==73% - rx_ok_buff[1]=(rx_ok_buff[1]&0xE0) | PROTO_FLYSKY; // change the protocol to Flysky - memcpy((void*)(rx_ok_buff+4),(void*)(rx_ok_buff+4+11),11); // reassign channels 9-16 to 1-8 - } - #endif if(rx_ok_buff[1]&0x20) //check range RANGE_FLAG_on; else RANGE_FLAG_off; + if(rx_ok_buff[1]&0x40) //check autobind AUTOBIND_FLAG_on; else AUTOBIND_FLAG_off; + if(rx_ok_buff[2]&0x80) //if rx_ok_buff[2] ==1,power is low ,0-power high POWER_FLAG_off; //power low else POWER_FLAG_on; //power high //Forced frequency tuning values for CC2500 protocols - #if defined(FORCE_FRSKYD_TUNING) && defined(FRSKYD_CC2500_INO) + #if defined(FORCE_FRSKYD_TUNING) if(protocol==PROTO_FRSKYD) option=FORCE_FRSKYD_TUNING; // Use config-defined tuning value for FrSkyD else - #endif - #if defined(FORCE_FRSKYV_TUNING) && defined(FRSKYV_CC2500_INO) - if(protocol==PROTO_FRSKYV) - option=FORCE_FRSKYV_TUNING; // Use config-defined tuning value for FrSkyV - else - #endif - #if defined(FORCE_FRSKYX_TUNING) && defined(FRSKYX_CC2500_INO) - if(protocol==PROTO_FRSKYX) - option=FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX - else - #endif - #if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO) - if (protocol==PROTO_SFHSS) - option=FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS - else - #endif - #if defined(FORCE_CORONA_TUNING) && defined(CORONA_CC2500_INO) - if (protocol==PROTO_CORONA) - option=FORCE_CORONA_TUNING; // Use config-defined tuning value for CORONA - else - #endif - #if defined(FORCE_HITEC_TUNING) && defined(HITEC_CC2500_INO) - if (protocol==PROTO_HITEC) - option=FORCE_HITEC_TUNING; // Use config-defined tuning value for HITEC - else #endif option=rx_ok_buff[3]; // Use radio-defined option value #ifdef FAILSAFE_ENABLE bool failsafe=false; - if(rx_ok_buff[0]&0x02) - { // Packet contains failsafe instead of channels + if(rx_ok_buff[0]&0x02) { // Packet contains failsafe instead of channels failsafe=true; rx_ok_buff[0]&=0xFD; //remove the failsafe flag - FAILSAFE_VALUES_on; //failsafe data has been received } #endif - #ifdef BONI - if(CH14_SW) - rx_ok_buff[2]=(rx_ok_buff[2]&0xF0)|((rx_ok_buff[2]+1)&0x0F); // Extremely dangerous, do not enable this!!! This is really for a special case... - #endif if( (rx_ok_buff[0] != cur_protocol[0]) || ((rx_ok_buff[1]&0x5F) != (cur_protocol[1]&0x5F)) || ( (rx_ok_buff[2]&0x7F) != (cur_protocol[2]&0x7F) ) ) { // New model has been selected CHANGE_PROTOCOL_FLAG_on; //change protocol @@ -656,14 +418,11 @@ void update_serial_data() protocol=(rx_ok_buff[0]==0x55?0:32) + (rx_ok_buff[1]&0x1F); //protocol no (0-63) bits 4-6 of buff[1] and bit 0 of buf[0] sub_protocol=(rx_ok_buff[2]>>4)& 0x07; //subprotocol no (0-7) bits 4-6 RX_num=rx_ok_buff[2]& 0x0F; // rx_num bits 0---3 - } - else - if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set + } else if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set { // Restart protocol with bind CHANGE_PROTOCOL_FLAG_on; BIND_IN_PROGRESS; - } - else + } else { if( ((rx_ok_buff[1]&0x80)==0) && ((cur_protocol[1]&0x80)!=0) ) // Bind flag has been reset { // Request protocol to end bind #if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) @@ -674,6 +433,7 @@ void update_serial_data() if(bind_counter>2) bind_counter=2; } + } //store current protocol values for(uint8_t i=0;i<3;i++) @@ -682,104 +442,35 @@ void update_serial_data() // decode channel/failsafe values volatile uint8_t *p=rx_ok_buff+3; uint8_t dec=-3; - for(uint8_t i=0;i=8) - { + if(dec>=8) { dec-=8; p++; } p++; uint16_t temp=((*((uint32_t *)p))>>dec)&0x7FF; - #ifdef FAILSAFE_ENABLE if(failsafe) Failsafe_data[i]=temp; //value range 0..2047, 0=no pulses, 2047=hold else - #endif Channel_data[i]=temp; //value range 0..2047, 0=-125%, 2047=+125% } - RX_DONOTUPDATE_off; cli(); if(IS_RX_MISSED_BUFF_on) // If the buffer is still valid { memcpy((void*)rx_ok_buff,(const void*)rx_buff,RXBUFFER_SIZE);// Duplicate the buffer - RX_FLAG_on; // data to be processed next time... RX_MISSED_BUFF_off; } sei(); - #ifdef FAILSAFE_ENABLE - if(failsafe) - debugln("RX_FS:%d,%d,%d,%d",Failsafe_data[0],Failsafe_data[1],Failsafe_data[2],Failsafe_data[3]); - #endif } void modules_reset() { - #ifdef CC2500_INSTALLED - CC2500_Reset(); - #endif - #ifdef A7105_INSTALLED - A7105_Reset(); - #endif - #ifdef CYRF6936_INSTALLED - CYRF_Reset(); - #endif - #ifdef NRF24L01_INSTALLED - NRF24L01_Reset(); - #endif + CC2500_Reset(); //Wait for every component to reset delay(100); - prev_power=0xFD; // unused power value } -#ifdef STM32_BOARD - void usart2_begin(uint32_t baud,uint32_t config ) - { - usart_init(USART2); - usart_config_gpios_async(USART2,GPIOA,PIN_MAP[PA3].gpio_bit,GPIOA,PIN_MAP[PA2].gpio_bit,config); - LED2_output; - usart_set_baud_rate(USART2, STM32_PCLK1, baud); - usart_enable(USART2); - } - void usart3_begin(uint32_t baud,uint32_t config ) - { - usart_init(USART3); - usart_config_gpios_async(USART3,GPIOB,PIN_MAP[PB11].gpio_bit,GPIOB,PIN_MAP[PB10].gpio_bit,config); - usart_set_baud_rate(USART3, STM32_PCLK1, baud); - usart_enable(USART3); - } - void init_HWTimer() - { - HWTimer2.pause(); // Pause the timer2 while we're configuring it - - TIMER2_BASE->PSC = 35; // 36-1;for 72 MHZ /0.5sec/(35+1) - TIMER2_BASE->ARR = 0xFFFF; // Count until 0xFFFF - - HWTimer2.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE); // Main scheduler - HWTimer2.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE); // Serial check - - TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC2IF; // Clear Timer2/Comp2 interrupt flag - HWTimer2.attachInterrupt(TIMER_CH2,ISR_COMPB); // Assign function to Timer2/Comp2 interrupt - TIMER2_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer2/Comp2 interrupt - - HWTimer2.refresh(); // Refresh the timer's count, prescale, and overflow - HWTimer2.resume(); - } -#endif - -#if defined(TELEMETRY) -void PPM_Telemetry_serial_init() -{ - if( (protocol==PROTO_FRSKYD)) - initTXSerial( SPEED_9600 ) ; - if(protocol==PROTO_FRSKYX) - initTXSerial( SPEED_57600 ) ; - if(protocol==PROTO_DSM) - initTXSerial( SPEED_125K ) ; -} -#endif - // Convert 32b id to rx_tx_addr void set_rx_tx_addr(uint32_t id) { // Used by almost all protocols @@ -790,18 +481,19 @@ void set_rx_tx_addr(uint32_t id) rx_tx_addr[4] = (rx_tx_addr[2]&0xF0)|(rx_tx_addr[3]&0x0F); } -uint32_t random_id(uint16_t address, uint8_t create_new) +uint32_t random_id(bool create_new) { - #ifndef FORCE_GLOBAL_ID + #ifdef FORCE_GLOBAL_ID + (void)create_new; + return FORCE_GLOBAL_ID; + #else uint32_t id=0; - #if 0 - //(eeprom_read_byte((EE_ADDR)(address+10))==0xf0 && !create_new) - { // TXID exists in EEPROM - for(uint8_t i=4;i>0;i--) - { + if (eeprom_read_byte((EE_ADDR)(10))==0xf0 && !create_new) { + // TXID exists in EEPROM + for(uint8_t i=4;i>0;i--) { id<<=8; - id|=eeprom_read_byte((EE_ADDR)address+i-1); + id|=eeprom_read_byte((EE_ADDR)i-1); } if(id!=0x2AD141A7) //ID with seed=0 { @@ -809,18 +501,14 @@ uint32_t random_id(uint16_t address, uint8_t create_new) return id; } } - // Generate a random ID - #if defined STM32_BOARD + // Generate a random ID from UUID #define STM32_UUID ((uint32_t *)0x1FFFF7E8) - if (!create_new) - { + if (!create_new) { id = STM32_UUID[0] ^ STM32_UUID[1] ^ STM32_UUID[2]; - debugln("Generated ID from STM32 UUID"); + debugln("Generated ID from STM32 UUID %x", id); + } else { + id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); } - else - #endif - #endif - id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); #if 0 for(uint8_t i=0;i<4;i++) @@ -828,166 +516,6 @@ uint32_t random_id(uint16_t address, uint8_t create_new) eeprom_write_byte((EE_ADDR)(address+10),0xf0);//write bind flag in eeprom. #endif return id; - #else - (void)address; - (void)create_new; - return FORCE_GLOBAL_ID; - #endif -} - -/**************************/ -/**************************/ -/** Interrupt routines **/ -/**************************/ -/**************************/ - -//PPM -#ifdef blubber // ENABLE_PPM - #ifdef ORANGE_TX - #if PPM_pin == 2 - ISR(PORTD_INT0_vect) - #else - ISR(PORTD_INT1_vect) - #endif - #elif defined STM32_BOARD - void PPM_decode() - #else - #if PPM_pin == 2 - ISR(INT0_vect, ISR_NOBLOCK) - #else - ISR(INT1_vect, ISR_NOBLOCK) - #endif - #endif - { // Interrupt on PPM pin - static int8_t chan=0,bad_frame=1; - static uint16_t Prev_TCNT1=0; - uint16_t Cur_TCNT1; - - Cur_TCNT1 = TCNT1 - Prev_TCNT1 ; // Capture current Timer1 value - if(Cur_TCNT1<1600) - bad_frame=1; // bad frame - else - if(Cur_TCNT1>4400) - { //start of frame - if(chan>=MIN_PPM_CHANNELS) - { - PPM_FLAG_on; // good frame received if at least 4 channels have been seen - if(chan>PPM_chan_max) PPM_chan_max=chan; // Saving the number of channels received - } - chan=0; // reset channel counter - bad_frame=0; - } - else - if(bad_frame==0) // need to wait for start of frame - { //servo values between 800us and 2200us will end up here - PPM_data[chan]=Cur_TCNT1; - if(chan++>=MAX_PPM_CHANNELS) - bad_frame=1; // don't accept any new channels - } - Prev_TCNT1+=Cur_TCNT1; - } -#endif //ENABLE_PPM - -//Serial RX -#ifdef ENABLE_SERIAL - #ifdef ORANGE_TX - ISR(USARTC0_RXC_vect) - #elif defined STM32_BOARD - void __irq_usart2() - #else - ISR(USART_RX_vect) #endif - { // RX interrupt - static uint8_t idx=0; - #ifdef ORANGE_TX - if((USARTC0.STATUS & 0x1C)==0) // Check frame error, data overrun and parity error - #elif defined STM32_BOARD - if((USART2_BASE->SR & USART_SR_RXNE) && (USART2_BASE->SR &0x0F)==0) - #else - UCSR0B &= ~_BV(RXCIE0) ; // RX interrupt disable - sei() ; - if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error - #endif - { // received byte is ok to process - if(idx==0||discard_frame==1) - { // Let's try to sync at this point - idx=0;discard_frame=0; - RX_MISSED_BUFF_off; // If rx_buff was good it's not anymore... - rx_buff[0]=UDR0; - #ifdef FAILSAFE_ENABLE - if((rx_buff[0]&0xFC)==0x54) // If 1st byte is 0x54, 0x55, 0x56 or 0x57 it looks ok - #else - if((rx_buff[0]&0xFE)==0x54) // If 1st byte is 0x54 or 0x55 it looks ok - #endif - { - TX_RX_PAUSE_on; - tx_pause(); - #if defined STM32_BOARD - TIMER2_BASE->CCR2=TIMER2_BASE->CNT+(6500L); // Full message should be received within timer of 3250us - TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC2IF; // Clear Timer2/Comp2 interrupt flag - TIMER2_BASE->DIER |= TIMER_DIER_CC2IE; // Enable Timer2/Comp2 interrupt - #else - OCR1B = TCNT1+(6500L) ; // Full message should be received within timer of 3250us - TIFR1 = OCF1B_bm ; // clear OCR1B match flag - SET_TIMSK1_OCIE1B ; // enable interrupt on compare B match - #endif - idx++; - } - } - else - { - rx_buff[idx++]=UDR0; // Store received byte - if(idx>=RXBUFFER_SIZE) - { // A full frame has been received - if(!IS_RX_DONOTUPDATE_on) - { //Good frame received and main is not working on the buffer - memcpy((void*)rx_ok_buff,(const void*)rx_buff,RXBUFFER_SIZE);// Duplicate the buffer - RX_FLAG_on; // flag for main to process servo data - } - else - RX_MISSED_BUFF_on; // notify that rx_buff is good - discard_frame=1; // start again - } - } - } - else - { - idx=UDR0; // Dummy read - discard_frame=1; // Error encountered discard full frame... - debugln("Bad frame RX"); - } - if(discard_frame==1) - { - #ifdef STM32_BOARD - TIMER2_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer2/Comp2 interrupt - #else - CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match - #endif - TX_RX_PAUSE_off; - tx_resume(); - } - #if not defined (ORANGE_TX) && not defined (STM32_BOARD) - cli() ; - UCSR0B |= _BV(RXCIE0) ; // RX interrupt enable - #endif - } - //Serial timer - #ifdef ORANGE_TX - ISR(TCC1_CCB_vect) - #elif defined STM32_BOARD - void ISR_COMPB() - #else - ISR(TIMER1_COMPB_vect, ISR_NOBLOCK ) - #endif - { // Timer1 compare B interrupt - discard_frame=1; - #ifdef STM32_BOARD - TIMER2_BASE->DIER &= ~TIMER_DIER_CC2IE; // Disable Timer2/Comp2 interrupt - debugln("Bad frame timer"); - #else - CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match - #endif - tx_resume(); - } -#endif //ENABLE_SERIAL +} diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index 6699eb3..6969b55 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -3,69 +3,6 @@ #include "config.h" #include "tx_def.h" -// Check selected board type -#if defined (STM32_BOARD) && defined (ORANGE_TX) - #error You must comment the board type STM32_BOARD in _Config.h to compile ORANGE_TX -#endif -#if not defined (ORANGE_TX) && not defined (STM32_BOARD) - //Atmega328p - #if (not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_AVR_LEONARDO) )&& not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO) - #warning You must select one of these boards: "Multi 4-in-1", "Arduino Pro or Pro Mini" or "Arduino Mini" - #endif - #if F_CPU != 16000000L || not defined(__AVR_ATmega328P__) || not defined(__AVR_ATmega32U4__) - #warning You must select the processor type "ATmega328(5V, 16MHz)" - #endif -#endif -#if defined (STM32_BOARD) && not defined (ORANGE_TX) - //STM32 - #if not defined(ARDUINO_GENERIC_STM32F103C) && not defined(ARDUINO_MULTI_STM32_FLASH_FROM_TX) && not defined(ARDUINO_MULTI_STM32_NO_BOOT) && not defined(ARDUINO_MULTI_STM32_WITH_BOOT) - #error You must select one of these boards: "Multi 4-in-1 (STM32F103CB)" or "Generic STM32F103C series" - #endif -#endif - -// Check for minimum version of multi-module boards -#define MIN_AVR_BOARD 103 -#define MIN_ORX_BOARD 103 -#define MIN_STM32_BOARD 104 -//AVR -#if (defined(ARDUINO_MULTI_NO_BOOT) && ARDUINO_MULTI_NO_BOOT < MIN_AVR_BOARD) || (defined(ARDUINO_MULTI_FLASH_FROM_TX) && ARDUINO_MULTI_FLASH_FROM_TX < MIN_AVR_BOARD) - #error You need to update your Multi 4-in-1 board definition. Open Boards Manager and update to the latest version of the Multi 4-in-1 AVR Boards. -#endif -//OrangeRX -#if (defined(ARDUINO_MULTI_ORANGERX) && ARDUINO_MULTI_ORANGERX < MIN_ORX_BOARD) - #error You need to update your Multi 4-in-1 board definition. Open Boards Manager and update to the latest version of the Multi 4-in-1 AVR Boards. -#endif -//STM32 -#if (defined(ARDUINO_MULTI_STM32_NO_BOOT) && ARDUINO_MULTI_STM32_NO_BOOT < MIN_STM32_BOARD) || (defined(ARDUINO_MULTI_STM32_FLASH_FROM_TX) && ARDUINO_MULTI_STM32_FLASH_FROM_TX < MIN_STM32_BOARD) || (defined(ARDUINO_MULTI_STM32_WITH_BOOT) && ARDUINO_MULTI_STM32_WITH_BOOT < MIN_STM32_BOARD) - #error You need to update your Multi 4-in-1 board definition. Open Boards Manager and update to the latest version of the Multi 4-in-1 STM32 Board. -#endif - -// Error if CHECK_FOR_BOOTLOADER is not enabled but a FLASH_FROM_TX board is selected -#if (defined(ARDUINO_MULTI_FLASH_FROM_TX) || defined(ARDUINO_MULTI_STM32_FLASH_FROM_TX)) &! defined(CHECK_FOR_BOOTLOADER) - #if defined(STM32_BOARD) - #error "You have selected the 'Flash from TX' upload method but not enabled CHECK_FOR_BOOTLOADER." - #else - #error "You have selected the 'Flash from TX' bootloader but not enabled CHECK_FOR_BOOTLOADER." - #endif -#endif - -// Error if CHECK_FOR_BOOTLOADER is enabled but the 'Flash from TX' bootloader -#if defined(ARDUINO_MULTI_NO_BOOT) && defined(CHECK_FOR_BOOTLOADER) - #error "You have enabled CHECK_FOR_BOOTLOADER but not selected the 'Flash from TX' bootloader." -#endif - -//Check number of banks -#if NBR_BANKS < 1 || NBR_BANKS > 5 - #error "You need to select a number of banks between 1 and 5." -#endif - -//Check failsafe throttle value -#ifdef FAILSAFE_ENABLE - #if ( FAILSAFE_THROTTLE_LOW < -125 ) || ( FAILSAFE_THROTTLE_LOW > 125 ) - #error "The failsafe value for throttle is outside of the range -125..125." - #endif -#endif - // Check forced tuning values are valid #ifdef FORCE_FRSKYD_TUNING #if ( FORCE_FRSKYD_TUNING < -127 ) || ( FORCE_FRSKYD_TUNING > 127 ) @@ -82,179 +19,7 @@ #error "The FrSkyX forced frequency tuning value is outside of the range -127..127." #endif #endif -#ifdef FORCE_SFHSS_TUNING - #if ( FORCE_SFHSS_TUNING < -127 ) || ( FORCE_SFHSS_TUNING > 127 ) - #error "The SFHSS forced frequency tuning value is outside of the range -127..127." - #endif -#endif -#ifdef FORCE_CORONA_TUNING - #if ( FORCE_CORONA_TUNING < -127 ) || ( FORCE_CORONA_TUNING > 127 ) - #error "The CORONA forced frequency tuning value is outside of the range -127..127." - #endif -#endif -#ifdef FORCE_HITEC_TUNING - #if ( FORCE_HITEC_TUNING < -127 ) || ( FORCE_HITEC_TUNING > 127 ) - #error "The HITEC forced frequency tuning value is outside of the range -127..127." - #endif -#endif -#ifdef FORCE_FLYSKY_TUNING - #if ( FORCE_FLYSKY_TUNING < -300 ) || ( FORCE_FLYSKY_TUNING > 300 ) - #error "The Flysky forced frequency tuning value is outside of the range -300..300." - #endif -#endif -#ifdef FORCE_HUBSAN_TUNING - #if ( FORCE_HUBSAN_TUNING < -300 ) || ( FORCE_HUBSAN_TUNING > 300 ) - #error "The Hubsan forced frequency tuning value is outside of the range -300..300." - #endif -#endif -#ifdef FORCE_AFHDS2A_TUNING - #if ( FORCE_AFHDS2A_TUNING < -300 ) || ( FORCE_AFHDS2A_TUNING > 300 ) - #error "The AFHDS2A forced frequency tuning value is outside of the range -300..300." - #endif -#endif -#ifndef USE_A7105_CH15_TUNING - #ifndef FORCE_FLYSKY_TUNING - #define FORCE_FLYSKY_TUNING 0 - #endif - #ifndef FORCE_HUBSAN_TUNING - #define FORCE_HUBSAN_TUNING 0 - #endif - #ifndef FORCE_AFHDS2A_TUNING - #define FORCE_AFHDS2A_TUNING 0 - #endif -#endif - -//Change/Force configuration if OrangeTX -#ifdef ORANGE_TX - #undef ENABLE_PPM // Disable PPM for OrangeTX module - #undef A7105_INSTALLED // Disable A7105 for OrangeTX module - #undef A7105_CSN_pin - #undef CC2500_INSTALLED // Disable CC2500 for OrangeTX module - #undef CC25_CSN_pin - #undef NRF24L01_INSTALLED // Disable NRF for OrangeTX module - #undef NRF_CSN_pin - #define TELEMETRY // Enable telemetry - #define INVERT_TELEMETRY // Enable invert telemetry - #define DSM_TELEMETRY // Enable DSM telemetry -#endif - -//Make sure protocols are selected correctly -#ifndef A7105_INSTALLED - #undef FLYSKY_A7105_INO - #undef HUBSAN_A7105_INO - #undef AFHDS2A_A7105_INO - #undef BUGS_A7105_INO -#endif -#ifndef CYRF6936_INSTALLED - #undef DEVO_CYRF6936_INO - #undef DSM_CYRF6936_INO - #undef J6PRO_CYRF6936_INO - #undef WFLY_CYRF6936_INO - #undef WK2x01_CYRF6936_INO -#endif -#ifndef CC2500_INSTALLED - #undef FRSKYD_CC2500_INO - #undef FRSKYV_CC2500_INO - #undef FRSKYX_CC2500_INO - #undef SFHSS_CC2500_INO - #undef CORONA_CC2500_INO - #undef HITEC_CC2500_INO -#endif -#ifndef NRF24L01_INSTALLED - #undef BAYANG_NRF24L01_INO - #undef CG023_NRF24L01_INO - #undef CX10_NRF24L01_INO - #undef ESKY_NRF24L01_INO - #undef HISKY_NRF24L01_INO - #undef KN_NRF24L01_INO - #undef SLT_NRF24L01_INO - #undef SYMAX_NRF24L01_INO - #undef V2X2_NRF24L01_INO - #undef YD717_NRF24L01_INO - #undef MT99XX_NRF24L01_INO - #undef MJXQ_NRF24L01_INO - #undef SHENQI_NRF24L01_INO - #undef FY326_NRF24L01_INO - #undef FQ777_NRF24L01_INO - #undef ASSAN_NRF24L01_INO - #undef HONTAI_NRF24L01_INO - #undef Q303_NRF24L01_INO - #undef GW008_NRF24L01_INO - #undef DM002_NRF24L01_INO - #undef CABELL_NRF24L01_INO - #undef ESKY150_NRF24L01_INO - #undef H8_3D_NRF24L01_INO - #undef CFLIE_NRF24L01_INO -#endif - -//Make sure telemetry is selected correctly -#ifndef TELEMETRY - #undef INVERT_TELEMETRY - #undef AFHDS2A_FW_TELEMETRY - #undef AFHDS2A_HUB_TELEMETRY - #undef HITEC_FW_TELEMETRY - #undef HITEC_HUB_TELEMETRY - #undef BAYANG_HUB_TELEMETRY - #undef CABELL_HUB_TELEMETRY - #undef HUBSAN_HUB_TELEMETRY - #undef BUGS_HUB_TELEMETRY - #undef HUB_TELEMETRY - #undef SPORT_TELEMETRY - #undef SPORT_POLLING - #undef DSM_TELEMETRY - #undef MULTI_STATUS - #undef MULTI_TELEMETRY -#else - #if defined MULTI_TELEMETRY && not defined INVERT_TELEMETRY - #warning MULTI_TELEMETRY has been defined but not INVERT_TELEMETRY. They should be both enabled for OpenTX telemetry and status to work. - #endif - #if not defined(BAYANG_NRF24L01_INO) - #undef BAYANG_HUB_TELEMETRY - #endif - #if not defined(CABELL_NRF24L01_INO) - #undef CABELL_HUB_TELEMETRY - #endif - #if not defined(HUBSAN_A7105_INO) - #undef HUBSAN_HUB_TELEMETRY - #endif - #if not defined(AFHDS2A_A7105_INO) - #undef AFHDS2A_HUB_TELEMETRY - #undef AFHDS2A_FW_TELEMETRY - #endif - #if not defined(HITEC_CC2500_INO) - #undef HITEC_HUB_TELEMETRY - #undef HITEC_FW_TELEMETRY - #endif - #if not defined(FRSKYD_CC2500_INO) - #undef HUB_TELEMETRY - #endif - #if not defined(FRSKYX_CC2500_INO) - #undef SPORT_TELEMETRY - #undef SPORT_POLLING - #endif - #if not defined (SPORT_TELEMETRY) || not defined (STM32_BOARD) - #undef SPORT_POLLING - #endif - #if defined SPORT_POLLING && not defined INVERT_TELEMETRY - #error SPORT_POLLING has been defined but not INVERT_TELEMETRY. They should be both enabled to work. - #endif - #if not defined(DSM_CYRF6936_INO) - #undef DSM_TELEMETRY - #endif - #if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) - #undef TELEMETRY - #undef INVERT_TELEMETRY - #undef SPORT_POLLING - #endif -#endif -//Make sure TX is defined correctly -#ifndef AILERON - #error You must select a correct channel order. -#endif -#if not defined(PPM_MAX_100) || not defined(PPM_MIN_100) - #error You must set correct PPM end points for your TX. -#endif #if defined(ENABLE_BIND_CH) #if BIND_CH<4 @@ -265,17 +30,4 @@ #endif #endif -#if MIN_PPM_CHANNELS>16 - #error MIN_PPM_CHANNELS must be below or equal to 16. The default for this value is 4. -#endif -#if MIN_PPM_CHANNELS<2 - #error MIN_PPM_CHANNELS must be larger than 1. The default for this value is 4. -#endif -#if MAX_PPM_CHANNELS16 - #error MAX_PPM_CHANNELS must be below or equal to 16. The default for this value is 16. -#endif - #endif diff --git a/Multiprotocol/cc2500_spi.cpp b/Multiprotocol/cc2500_spi.cpp index f72df9a..35fa423 100644 --- a/Multiprotocol/cc2500_spi.cpp +++ b/Multiprotocol/cc2500_spi.cpp @@ -23,6 +23,7 @@ #include "cc2500_spi.h" #include "spi.h" +uint8_t prev_power=0xFD; // unused power value void CC2500_WriteReg(uint8_t address, uint8_t data) { CC25_CSN_off; @@ -85,14 +86,12 @@ void CC2500_SetTxRxMode(uint8_t mode) //from deviation firmware CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F); CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F | 0x40); - } else { - if (mode == RX_EN) { + } else if (mode == RX_EN) { CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F); CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F | 0x40); - } else { + } else { CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F); CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F); - } } } uint8_t CC2500_Reset() @@ -100,21 +99,22 @@ uint8_t CC2500_Reset() CC2500_Strobe(CC2500_SRES); delay(1); CC2500_SetTxRxMode(TXRX_OFF); + prev_power=0xFD; // unused power value return CC2500_ReadReg(CC2500_0E_FREQ1) == 0xC4;//check if reset } void CC2500_SetPower() { uint8_t power=CC2500_BIND_POWER; - if(IS_BIND_DONE) + if(IS_BIND_DONE) { #ifdef CC2500_ENABLE_LOW_POWER power=IS_POWER_FLAG_on?CC2500_HIGH_POWER:CC2500_LOW_POWER; #else power=CC2500_HIGH_POWER; #endif + } if(IS_RANGE_FLAG_on) power=CC2500_RANGE_POWER; - if(prev_power != power) - { + if(prev_power != power) { CC2500_WriteReg(CC2500_3E_PATABLE, power); prev_power=power; } diff --git a/Multiprotocol/cc2500_spi.h b/Multiprotocol/cc2500_spi.h index 8123e87..0d452b7 100644 --- a/Multiprotocol/cc2500_spi.h +++ b/Multiprotocol/cc2500_spi.h @@ -160,4 +160,37 @@ enum { #define CC2500_LQI_CRC_OK_BM 0x80 #define CC2500_LQI_EST_BM 0x7F +// CC2500 power output from the chip itself +// The numbers do not take into account any outside amplifier +enum CC2500_POWER +{ + CC2500_POWER_0 = 0x00, // -55dbm or less + CC2500_POWER_1 = 0x50, // -30dbm + CC2500_POWER_2 = 0x44, // -28dbm + CC2500_POWER_3 = 0xC0, // -26dbm + CC2500_POWER_4 = 0x84, // -24dbm + CC2500_POWER_5 = 0x81, // -22dbm + CC2500_POWER_6 = 0x46, // -20dbm + CC2500_POWER_7 = 0x93, // -18dbm + CC2500_POWER_8 = 0x55, // -16dbm + CC2500_POWER_9 = 0x8D, // -14dbm + CC2500_POWER_10 = 0xC6, // -12dbm + CC2500_POWER_11 = 0x97, // -10dbm + CC2500_POWER_12 = 0x6E, // -8dbm + CC2500_POWER_13 = 0x7F, // -6dbm + CC2500_POWER_14 = 0xA9, // -4dbm + CC2500_POWER_15 = 0xBB, // -2dbm + CC2500_POWER_16 = 0xFE, // 0dbm + CC2500_POWER_17 = 0xFF // +1dbm +}; +#define CC2500_HIGH_POWER CC2500_POWER_1 +#define CC2500_LOW_POWER CC2500_POWER_1 +#define CC2500_RANGE_POWER CC2500_POWER_1 +#define CC2500_BIND_POWER CC2500_POWER_1 + +enum TXRX_State { + TXRX_OFF, + TX_EN, + RX_EN +}; #endif diff --git a/Multiprotocol/common.cpp b/Multiprotocol/common.cpp index d24416d..88606a7 100644 --- a/Multiprotocol/common.cpp +++ b/Multiprotocol/common.cpp @@ -18,32 +18,9 @@ #include "Multiprotocol.h" #include "cc2500_spi.h" -#ifdef FAILSAFE_ENABLE - uint16_t Failsafe_data[NUM_CHN]; -#endif +#include "input.h" -void InitFailsafe(void) -{ - for (uint8_t i = 0; i < NUM_CHN; i++) - Failsafe_data[i] = 1024; - Failsafe_data[THROTTLE] = (uint16_t)204; //1=-125%, 204=-100% - FAILSAFE_VALUES_on; -} - -void InitPPM(void) -{ - for(uint8_t i=0;icurr = &(this->input[0]); this->old = &(this->input[1]); memset(this->input,0, sizeof(this->input)); + //InitFailsafe + for (uint8_t i = 0; i < NUM_TX_CHN; i++) + Failsafe_data[i] = (CHANNEL_MAX_100 - CHANNEL_MIN_100) / 2 + CHANNEL_MIN_100; + Failsafe_data[CH_THROTTLE] = CHANNEL_MIN_100; //1=-125%, 204=-100% + + // init channel + + for (uint8_t i = 0; i < NUM_TX_CHN; i++) + Channel_data[i] = 1024; + Channel_data[CH_THROTTLE] = 204; } void Input::mark_processed(void) { struct data* temp = this->old; @@ -28,40 +55,63 @@ struct Input::data* Input::get_old_input(void) { } void Input::init() { - analogReadResolution(16); - - pinMode(Throttle_pin,INPUT); - pinMode(Yaw_pin,INPUT); - pinMode(Roll_pin,INPUT); - pinMode(Aux1_pin,INPUT); - pinMode(Aux2_pin,INPUT); - pinMode(Aux3_pin,INPUT); - pinMode(Aux4_pin,INPUT); - pinMode(Aux5_pin,INPUT); - pinMode(Aux6_pin,INPUT); + this->pins[CH_THROTTLE] = Throttle_pin; + this->ch_config[CH_THROTTLE].is_analog = true; + + this->pins[CH_YAW] = Yaw_pin; + this->ch_config[CH_YAW].is_analog = true; + + this->pins[CH_PITCH] = Pitch_pin; + this->ch_config[CH_PITCH].is_analog = true; + + this->pins[CH_ROLL] = Roll_pin; + this->ch_config[CH_ROLL].is_analog = true; + + this->pins[CH_AUX1] = Aux1_pin; + this->ch_config[CH_AUX1].is_analog = false; + + this->pins[CH_AUX2] = Aux2_pin; + this->ch_config[CH_AUX2].is_analog = false; + + this->pins[CH_AUX3] = Aux3_pin; + this->ch_config[CH_AUX3].is_analog = false; + + this->pins[CH_AUX4] = Aux4_pin; + this->ch_config[CH_AUX4].is_analog = false; + + this->pins[CH_AUX5] = Aux5_pin; + this->ch_config[CH_AUX5].is_analog = false; + + this->pins[CH_AUX6] = Aux6_pin; + this->ch_config[CH_AUX6].is_analog = false; + + for (uint8_t i = 0; i < CH_COUNT; ++i) { + pinMode(this->pins[i], INPUT); + } pinMode(Menu_pin,INPUT); - this->throttle.inverted = true; - this->yaw.inverted = false; - this->roll.inverted = false; - this->pitch.inverted = false; - this->aux[0].inverted = false; - this->aux[1].inverted = false; - this->aux[2].inverted = false; - this->aux[3].inverted = false; - this->aux[4].inverted = false; - this->aux[5].inverted = false; - - - this->throttle.min = 500; - this->yaw.min = 500; - this->roll.min = 500; - this->pitch.min = 500; - - this->throttle.max = 500; - this->yaw.max = 500; - this->roll.max = 500; - this->pitch.max = 500; + //analogReadResolution(16); + + // move this to eeprom later + this->ch_config[CH_THROTTLE].inverted = false; + this->ch_config[CH_YAW].inverted = false; + this->ch_config[CH_ROLL].inverted = false; + this->ch_config[CH_PITCH].inverted = false; + this->ch_config[CH_AUX1].inverted = false; + this->ch_config[CH_AUX2].inverted = false; + this->ch_config[CH_AUX3].inverted = false; + this->ch_config[CH_AUX4].inverted = false; + this->ch_config[CH_AUX5].inverted = false; + + this->ch_config[CH_THROTTLE].min = 0; + this->ch_config[CH_YAW].min = 0; + this->ch_config[CH_ROLL].min = 0; + this->ch_config[CH_PITCH].min = 0; + + this->ch_config[CH_THROTTLE].max = 4096; + this->ch_config[CH_YAW].max = 4096; + this->ch_config[CH_ROLL].max = 4096; + this->ch_config[CH_PITCH].max = 4096; } void Input::do_calibration(void) { int8_t turns = 50; @@ -71,24 +121,19 @@ void Input::do_calibration(void) { i = turns; while(i > 0) { this->update(); - if (true == this->save_calibration()) { + if (true == this->calibration_update()) { i = turns; debugln("new values t %d-%d r %d-%d p %d-%d y %d-%d", - this->throttle.min,this->throttle.max, - this->roll.min, this->roll.max, - this->pitch.min, this->pitch.max, - this->yaw.min, this->yaw.max); + this->ch_config[CH_THROTTLE].min, this->ch_config[CH_THROTTLE].max, + this->ch_config[CH_ROLL].min, this->ch_config[CH_ROLL].max, + this->ch_config[CH_PITCH].min, this->ch_config[CH_PITCH].max, + this->ch_config[CH_YAW].min, this->ch_config[CH_YAW].max); }else { i -= 1; } delay(100); } - debugln("end values t %d-%d r %d-%d p %d-%d y %d-%d", - this->throttle.min,this->throttle.max, - this->roll.min, this->roll.max, - this->pitch.min, this->pitch.max, - this->yaw.min, this->yaw.max); // center debugln("now center all sticks"); @@ -104,199 +149,64 @@ void Input::do_calibration(void) { } - debugln("now Move throttle to max"); + for (int ch = 0; ch < 4 ; ++ch) { + debugln("now Move %s to max", ch_name[ch]); i = turns; while(i>0) { - delay(100); + delay(50); this->update(); - if (true == this->is_throttle_up()) { + if (true == this->is_high((enum input_channels)ch)) { + debug("u"); i--; continue; } - if (true == this->is_throttle_down()) { - this->throttle.inverted = ! this->throttle.inverted; - i = turns; - continue; - } - } - debugln("throttle invert is %d", this->throttle.inverted); - - - debugln("now Move yaw to max"); - i = turns; - while(i>0) { - delay(100); - this->update(); - - if (true == this->is_yaw_up()) { - i--; - continue; - } - if (true == this->is_yaw_down()) { - this->yaw.inverted = ! this->yaw.inverted; - i = turns; - continue; - } - } - debugln("yaw invert is %d", this->yaw.inverted); - debugln("now Move pitch to max"); - i = turns; - while(i>0) { - delay(100); - this->update(); - if (true == this->is_pitch_up()) { - i--; - continue; - } - if (true == this->is_pitch_down()) { - this->pitch.inverted = ! this->pitch.inverted; - i = turns; - continue; - } - } - debugln("pitch invert is %d", this->pitch.inverted); - - debugln("now Move roll to max"); + if (true == this->is_low((enum input_channels)ch)) { + debug("dI"); + this->ch_config[CH_THROTTLE].inverted = !this->ch_config[CH_THROTTLE].inverted; i = turns; - while(i>0) { - delay(100); - this->update(); - - if (true == this->is_roll_up()) { - i--; continue; } - if (true == this->is_roll_down()) { - this->roll.inverted = ! this->roll.inverted; - i = turns; - continue; } } - debugln("roll invert is %d", this->roll.inverted); } bool Input::is_centered(void) { - return this->is_centered_left() && this->is_centered_right(); + return + this->is_centered(CH_ROLL) && + this->is_centered(CH_PITCH) && + this->is_centered(CH_THROTTLE) && + this->is_centered(CH_YAW); } -bool Input::is_centered_left(void) { - uint16_t range; - uint16_t delta; - - range = this->throttle.max - this->throttle.min; - delta = range >>4; - if ( this->curr->throttle < this->throttle.min + range/2 - delta || - this->curr->throttle > this->throttle.min + range/2 + delta - ) { - // throttle is not centered - return false; - } - +bool Input::is_centered(enum Input::input_channels ch) { + uint16_t range = this->ch_config[ch].max - this->ch_config[ch].min; + uint16_t delta = range / 5; - range = this->yaw.max - this->yaw.min; - delta = range >>4; - if ( this->curr->yaw < this->yaw.min + range/2 - delta || - this->curr->yaw > this->yaw.min + range/2 + delta - ) { - // yaw is not centered - return false; - } - return true; -} -bool Input::is_centered_right(void) { - uint16_t range; - uint16_t delta; - - range = this->pitch.max - this->pitch.min; - delta = range >>4; - if ( this->curr->pitch < this->pitch.min + range/2 - delta || - this->curr->pitch > this->pitch.min + range/2 + delta + if ( this->curr->ch_data[ch] < this->ch_config[ch].min + range / 2 - delta || + this->curr->ch_data[ch] > this->ch_config[ch].min + range / 2 + delta ) { // pitch is not centered return false; } - - range = this->roll.max - this->roll.min; - delta = range >>4; - if ( this->curr->roll < this->roll.min + range/2 - delta || - this->curr->roll > this->roll.min + range/2 + delta - ) { - // roll is not centered - return false; - } return true; } -bool Input::is_menu_left(void) { - return this->is_roll_down(); -} -bool Input::is_menu_right(void) { - return this->is_roll_up(); -} -bool Input::is_menu_down(void) { - return this->is_pitch_down(); -} -bool Input::is_menu_up(void) { - return this->is_pitch_up(); -} -bool Input::is_throttle_down(void) { - uint16_t delta = (this->throttle.max - this->throttle.min)/3; - if ( this->curr->throttle < this->throttle.min + delta) { +bool Input::is_high(enum Input::input_channels ch) { + uint16_t range = this->ch_config[ch].max - this->ch_config[ch].min; + uint16_t delta = range / 3; + if ( this->curr->ch_data[ch] < this->ch_config[ch].max - delta) { return true; } return false; } -bool Input::is_throttle_up(void) { - uint16_t delta = (this->throttle.max - this->throttle.min)/3; - if ( this->curr->throttle > this->throttle.max - delta) { - return true; - } - return false; -} -bool Input::is_yaw_up(void) { - uint16_t delta = (this->yaw.max - this->yaw.min)/3; - if ( this->curr->yaw > this->yaw.max - delta) { - return true; - } - return false; -} -bool Input::is_yaw_down(void) { - uint16_t delta = (this->yaw.max - this->yaw.min)/3; - if ( this->curr->yaw > this->yaw.min + delta) { - return true; - } - return false; -} - -bool Input::is_roll_down(void) { - uint16_t delta = (this->roll.max - this->roll.min)/3; - if ( this->curr->roll < this->roll.min + delta) { - return true; - } - return false; - -} -bool Input::is_roll_up(void) { - uint16_t delta = (this->roll.max - this->roll.min)/3; - if ( this->curr->roll > this->roll.max - delta) { - return true; - } - return false; -} -bool Input::is_pitch_up(void) { - uint16_t delta = (this->pitch.max - this->pitch.min)/3; - if ( this->curr->pitch > this->pitch.max - delta) { - return true; - } - return false; -} -bool Input::is_pitch_down(void) { - uint16_t delta = (this->pitch.max - this->pitch.min)/3; - if ( this->curr->pitch > this->pitch.min + delta) { +bool Input::is_low(enum Input::input_channels ch) { + uint16_t range = this->ch_config[ch].max - this->ch_config[ch].min; + uint16_t delta = range / 3; + if ( this->curr->ch_data[ch] < this->ch_config[ch].min + delta) { return true; } return false; @@ -306,56 +216,48 @@ bool Input::is_menu_triggered(void) { return this->curr->menu; } -bool Input::save_calibration(void) { +bool Input::calibration_update(void) { bool changed = false; - if (this->throttle.min > this->curr->throttle){ - changed = true; - this->throttle.min = this->curr->throttle; - } else if (this->throttle.max < this->curr->throttle) { - changed = true; - this->throttle.max = this->curr->throttle; - } - if (this->yaw.min > this->curr->yaw){ + for (uint8_t ch = 0; ch < CH_COUNT; ch++) { + if (this->ch_config[ch].min > this->ch_raw[ch]) { + this->ch_config[ch].min = this->ch_raw[ch]; changed = true; - this->yaw.min = this->curr->yaw; - } else if (this->yaw.max < this->curr->yaw) { + } else if (this->ch_config[ch].max < this->ch_raw[ch]) { changed = true; - this->yaw.max = this->curr->yaw; + this->ch_config[ch].max = this->ch_raw[ch]; } - if (this->roll.min > this->curr->roll){ - changed = true; - this->roll.min = this->curr->roll; - } else if (this->roll.max < this->curr->roll) { - changed = true; - this->roll.max = this->curr->roll; } - if (this->pitch.min > this->curr->pitch){ - changed = true; - this->pitch.min = this->curr->pitch; - } else if (this->roll.max < this->curr->pitch) { - changed = true; - this->pitch.max = this->curr->pitch; - } + // TODO save in eeprom return changed; } void Input::update(void) { - this->curr->throttle = analogRead(Throttle_pin); - this->curr->yaw = analogRead(Yaw_pin); - this->curr->roll = analogRead(Roll_pin); - this->curr->pitch = analogRead(Pitch_pin); - this->curr->aux[0] = digitalRead(Aux1_pin); - this->curr->aux[1] = digitalRead(Aux2_pin); - this->curr->aux[2] = digitalRead(Aux3_pin); - this->curr->aux[3] = digitalRead(Aux4_pin); - this->curr->aux[4] = digitalRead(Aux5_pin); - this->curr->aux[5] = digitalRead(Aux6_pin); + for (uint8_t ch = 0; ch < CH_MAX; ch ++) { + + if (this->ch_config[ch].is_analog) + this->ch_raw[ch] = analogRead(this->pins[ch]); + else + this->ch_raw[ch] = digitalRead(this->pins[ch]) == HIGH; - this->curr->menu = digitalRead(Menu_pin); + // do inverting + if (this->ch_config[ch].inverted) + this->curr->ch_data[ch] = this->ch_config[ch].max - this->ch_raw[ch]; + else + this->curr->ch_data[ch] = this->ch_raw[ch]; + + // cap on max + + if (this->ch_config[ch].min > this->curr->ch_data[ch]) { + this->curr->ch_data[ch] = this->ch_config[ch].min; + } else if (this->ch_config[ch].max < this->curr->ch_data[ch]) { + this->curr->ch_data[ch] = this->ch_config[ch].max; + } + } + this->curr->menu = digitalRead(Menu_pin) == HIGH; /*debug_input("t%d y%d r%d p%d a1_%d a2_%d a3_%d a4_%d a5_%d m%d", @@ -368,32 +270,7 @@ void Input::update(void) { if (curr_state != s_fly) return; - if(this->throttle.inverted) - Channel_data[THROTTLE] = map(this->curr->throttle, this->throttle.min, this->throttle.max, CHANNEL_MAX_100, CHANNEL_MIN_100); - else - Channel_data[THROTTLE] = map(this->curr->throttle, this->throttle.min, this->throttle.max, CHANNEL_MIN_100, CHANNEL_MAX_100); - - - if(this->yaw.inverted) - Channel_data[RUDDER] = map(this->curr->yaw, this->yaw.min, this->yaw.max, CHANNEL_MAX_100, CHANNEL_MIN_100); - else - Channel_data[RUDDER] = map(this->curr->yaw, this->yaw.min, this->yaw.max, CHANNEL_MIN_100, CHANNEL_MAX_100); - - if(this->roll.inverted) - Channel_data[AILERON] = map(this->curr->roll, this->roll.min, this->roll.max, CHANNEL_MAX_100, CHANNEL_MIN_100); - else - Channel_data[AILERON] = map(this->curr->roll, this->roll.min, this->roll.max, CHANNEL_MIN_100, CHANNEL_MAX_100); - - - if(this->pitch.inverted) - Channel_data[ELEVATOR] = map(this->curr->pitch, this->pitch.min, this->pitch.max, CHANNEL_MAX_100, CHANNEL_MIN_100); - else - Channel_data[ELEVATOR] = map(this->curr->pitch, this->pitch.min, this->pitch.max, CHANNEL_MIN_100, CHANNEL_MAX_100); - - for (uint8_t i = 0; i<6; ++i) { - if(this->aux[i].inverted) - Channel_data[CH5+i] = (this->curr->aux[i]) ? CHANNEL_MIN_100 : CHANNEL_MAX_100; - else - Channel_data[CH5+i] = (this->curr->aux[i]) ? CHANNEL_MAX_100 : CHANNEL_MIN_100; + for (uint8_t ch = 0; ch < CH_COUNT; ++ch) { + Channel_data[ch] = map(this->curr->ch_data[ch], this->ch_config[ch].min, this->ch_config[ch].max, CHANNEL_MAX_100, CHANNEL_MIN_100); } } diff --git a/Multiprotocol/input.h b/Multiprotocol/input.h index 43787f1..910904d 100644 --- a/Multiprotocol/input.h +++ b/Multiprotocol/input.h @@ -3,31 +3,37 @@ #include #include "tx_def.h" +#define NUM_TX_CHN 16 + +extern uint16_t Channel_data[NUM_TX_CHN]; +extern uint16_t Failsafe_data[NUM_TX_CHN]; class Input { - private: - struct data { - uint16_t throttle; - uint16_t yaw; - uint16_t roll; - uint16_t pitch; + public: + enum input_channels { + CH_ROLL = 0, + CH_PITCH = 1, + CH_THROTTLE = 2, + CH_YAW = 3, - bool aux[6]; + CH_AUX1 = 4, + CH_AUX2 = 5, + CH_AUX3 = 6, + CH_AUX4 = 7, + CH_AUX5 = 8, + CH_AUX6 = 8, - bool menu; + CH_MAX = 8, + CH_COUNT = 9, + MENU_UP_DOWN = CH_PITCH, + MENU_LEFT_RIGHT = CH_ROLL, }; - struct data input[2]; - struct data* curr; - struct data* old; - struct { - uint16_t max; - uint16_t min; - uint8_t inverted; - } throttle, yaw, roll, pitch, aux[5]; + struct data { + uint16_t ch_data[CH_COUNT]; + bool menu; + }; - bool save_calibration(void); - public: Input(void); void init(void); @@ -40,27 +46,31 @@ class Input { void mark_processed(void); bool is_centered(void); - bool is_centered_left(void); - bool is_centered_right(void); + bool is_centered(enum input_channels ch); + bool is_low(enum input_channels ch); + bool is_high(enum input_channels ch); // menu inputs bool is_menu_triggered(void); - bool is_menu_left(void); - bool is_menu_right(void); - bool is_menu_down(void); - bool is_menu_up(void); + private: + struct data input[2]; + struct data* curr; + struct data* old; + + uint16_t ch_raw[CH_COUNT]; + + struct { + uint16_t max; + uint16_t min; + bool inverted; + bool is_analog; + } ch_config[CH_COUNT]; - bool is_throttle_up(void); - bool is_throttle_down(void); - bool is_yaw_up(void); - bool is_yaw_down(void); + uint32_t pins[CH_COUNT]; - bool is_roll_up(void); - bool is_roll_down(void); - bool is_pitch_up(void); - bool is_pitch_down(void); + bool calibration_update(void); }; -extern uint16_t Channel_data[NUM_CHN]; +extern uint16_t Channel_data[NUM_TX_CHN]; extern Input input; #endif diff --git a/Multiprotocol/state.cpp b/Multiprotocol/state.cpp index 6c7a8e9..d6e61d3 100644 --- a/Multiprotocol/state.cpp +++ b/Multiprotocol/state.cpp @@ -10,10 +10,11 @@ LiquidCrystal_I2C lcd(0x27,16,2); State *curr_state = NULL; State *new_state = NULL; -State *s_init = new LCD_state_init(); -State *s_bind = new LCD_state_bind(); -State *s_fly = new LCD_state_fly(); -State *s_menu = new LCD_state_menu(); +State *s_init = NULL; +State *s_bind = NULL; +State *s_fly = NULL; +State *s_joy = NULL; +State *s_menu = NULL; enum lcd_special_chars { @@ -58,11 +59,17 @@ void install_special_caracters(void) } void init_state(void) { + #if 0 Wire.setSDA(PB9); Wire.setSCL(PB8); + #endif Wire.begin(); lcd.init(); + s_init = new LCD_state_init(); + s_bind = new LCD_state_bind(); + s_fly = new LCD_state_fly(); + s_menu = new LCD_state_menu(); lcd.backlight(); curr_state = NULL; new_state = s_init; @@ -89,14 +96,12 @@ void update_state(void) { //LCD_state_init LCD_state_init::LCD_state_init(void) { - snprintf(this->line[0],sizeof(this->line[0])," wellcome "); - snprintf(this->line[1],sizeof(this->line[1])," phschoen "); } void LCD_state_init::enter(void) { lcd.setCursor(0,0); - lcd.print(this->line[0]); + lcd.print(" wellcome "); lcd.setCursor(0,1); - lcd.print(this->line[1]); + lcd.print(" phschoen "); this->time_enter = millis(); } void LCD_state_init::update(void) @@ -113,28 +118,29 @@ void LCD_state_init::leave(void) } //LCD_state_bind LCD_state_bind::LCD_state_bind(void) { - snprintf(this->line[0],sizeof(this->line[0]),"bind mode "); - snprintf(this->line[1],sizeof(this->line[1])," "); this->bind_time = 20; } void LCD_state_bind::enter(void) { lcd.setCursor(0,0); - lcd.print(this->line[0]); + lcd.print("bind mode "); lcd.setCursor(0,1); - lcd.print(this->line[1]); + lcd.print(" "); this->time_enter = millis(); } void LCD_state_bind::update(void) { debugln("blubber\n"); + char line[17]; unsigned long time_in_ms = millis() - this->time_enter; unsigned long time_in_s = time_in_ms/1000; // to sec unsigned long remain_s = this->bind_time - time_in_s; - snprintf(this->line[0],sizeof(this->line[1]),"remaining sec %02d",remain_s); + snprintf(line,sizeof(line),"remaining sec %02d",remain_s); lcd.setCursor(0,1); - lcd.print(this->line[0]); + lcd.print(line); + + // cange to menu when done if (time_in_s >= this->bind_time) new_state = s_menu; } @@ -146,15 +152,12 @@ void LCD_state_bind::leave(void) // LCD_state_menu LCD_state_menu::LCD_state_menu(void) { - snprintf(this->line[0],sizeof(this->line[0]),"Menubind mode "); - snprintf(this->line[1],sizeof(this->line[1])," "); - this->curr_selected = 0; } void LCD_state_menu::enter(void) { lcd.setCursor(0,0); - lcd.print(this->line[0]); + lcd.print("menu mode "); lcd.setCursor(0,1); - lcd.print(this->line[1]); + lcd.print(" "); this->time_enter = millis(); } @@ -169,15 +172,13 @@ void LCD_state_menu::leave(void) // LCD_state_fly LCD_state_fly::LCD_state_fly(void) { - snprintf(this->line[0],sizeof(this->line[0]),"fly mode "); - snprintf(this->line[1],sizeof(this->line[1])," "); } void LCD_state_fly::enter(void) { lcd.setCursor(0,0); - lcd.print(this->line[0]); + lcd.print("fly mode "); lcd.setCursor(0,1); - lcd.print(this->line[1]); + lcd.print(" "); this->time_enter = millis(); } diff --git a/Multiprotocol/state.h b/Multiprotocol/state.h index 0a79e9f..99a631b 100644 --- a/Multiprotocol/state.h +++ b/Multiprotocol/state.h @@ -12,7 +12,6 @@ void update_state(void); class State { protected: - char line[2][17]; public: virtual void enter(void) { @@ -73,11 +72,21 @@ public: void leave(void); }; +class LCD_state_calibration: public State { +private: + unsigned long time_enter; +public: + LCD_state_calibration(void); + void enter(void); + void update(void); + void leave(void); +}; extern State *curr_state; extern State *new_state; extern State *s_init; extern State *s_bind; extern State *s_fly; +extern State *s_joy; extern State *s_menu; #endif /*_STATE_H_*/ diff --git a/Multiprotocol/tx_def.h b/Multiprotocol/tx_def.h index ec33aad..0887996 100644 --- a/Multiprotocol/tx_def.h +++ b/Multiprotocol/tx_def.h @@ -48,170 +48,6 @@ #define CHANNEL_MAX_COMMAND 1424 // 1750us //Channel definitions -#ifdef AETR - #define AILERON 0 - #define ELEVATOR 1 - #define THROTTLE 2 - #define RUDDER 3 -#endif -#ifdef AERT - #define AILERON 0 - #define ELEVATOR 1 - #define THROTTLE 3 - #define RUDDER 2 -#endif -#ifdef ARET - #define AILERON 0 - #define ELEVATOR 2 - #define THROTTLE 3 - #define RUDDER 1 -#endif -#ifdef ARTE - #define AILERON 0 - #define ELEVATOR 3 - #define THROTTLE 2 - #define RUDDER 1 -#endif -#ifdef ATRE - #define AILERON 0 - #define ELEVATOR 3 - #define THROTTLE 1 - #define RUDDER 2 -#endif -#ifdef ATER - #define AILERON 0 - #define ELEVATOR 2 - #define THROTTLE 1 - #define RUDDER 3 -#endif - -#ifdef EATR - #define AILERON 1 - #define ELEVATOR 0 - #define THROTTLE 2 - #define RUDDER 3 -#endif -#ifdef EART - #define AILERON 1 - #define ELEVATOR 0 - #define THROTTLE 3 - #define RUDDER 2 -#endif -#ifdef ERAT - #define AILERON 2 - #define ELEVATOR 0 - #define THROTTLE 3 - #define RUDDER 1 -#endif -#ifdef ERTA - #define AILERON 3 - #define ELEVATOR 0 - #define THROTTLE 2 - #define RUDDER 1 -#endif -#ifdef ETRA - #define AILERON 3 - #define ELEVATOR 0 - #define THROTTLE 1 - #define RUDDER 2 -#endif -#ifdef ETAR - #define AILERON 2 - #define ELEVATOR 0 - #define THROTTLE 1 - #define RUDDER 3 -#endif - -#ifdef TEAR - #define AILERON 2 - #define ELEVATOR 1 - #define THROTTLE 0 - #define RUDDER 3 -#endif -#ifdef TERA - #define AILERON 3 - #define ELEVATOR 1 - #define THROTTLE 0 - #define RUDDER 2 -#endif -#ifdef TREA - #define AILERON 3 - #define ELEVATOR 2 - #define THROTTLE 0 - #define RUDDER 1 -#endif -#ifdef TRAE - #define AILERON 2 - #define ELEVATOR 3 - #define THROTTLE 0 - #define RUDDER 1 -#endif -#ifdef TARE - #define AILERON 1 - #define ELEVATOR 3 - #define THROTTLE 0 - #define RUDDER 2 -#endif -#ifdef TAER - #define AILERON 1 - #define ELEVATOR 2 - #define THROTTLE 0 - #define RUDDER 3 -#endif - -#ifdef RETA - #define AILERON 3 - #define ELEVATOR 1 - #define THROTTLE 2 - #define RUDDER 0 -#endif -#ifdef REAT - #define AILERON 2 - #define ELEVATOR 1 - #define THROTTLE 3 - #define RUDDER 0 -#endif -#ifdef RAET - #define AILERON 1 - #define ELEVATOR 2 - #define THROTTLE 3 - #define RUDDER 0 -#endif -#ifdef RATE - #define AILERON 1 - #define ELEVATOR 3 - #define THROTTLE 2 - #define RUDDER 0 -#endif -#ifdef RTAE - #define AILERON 2 - #define ELEVATOR 3 - #define THROTTLE 1 - #define RUDDER 0 -#endif -#ifdef RTEA - #define AILERON 3 - #define ELEVATOR 2 - #define THROTTLE 1 - #define RUDDER 0 -#endif -#define CH1 0 -#define CH2 1 -#define CH3 2 -#define CH4 3 -#define CH5 4 -#define CH6 5 -#define CH7 6 -#define CH8 7 -#define CH9 8 -#define CH10 9 -#define CH11 10 -#define CH12 11 -#define CH13 12 -#define CH14 13 -#define CH15 14 -#define CH16 15 -#define NUM_CHN 16 #endif /* _TX_DEV_H_ */