2015-12-30 01:41:12 +01:00
|
|
|
/*********************************************************
|
|
|
|
Multiprotocol Tx code
|
|
|
|
by Midelic and Pascal Langer(hpnuts)
|
|
|
|
http://www.rcgroups.com/forums/showthread.php?t=2165676
|
|
|
|
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/edit/master/README.md
|
|
|
|
|
2016-04-06 12:57:42 +02:00
|
|
|
Thanks to PhracturedBlue, Hexfet, Goebish, Victzh and all protocol developers
|
2015-12-30 01:41:12 +01:00
|
|
|
Ported from deviation firmware
|
|
|
|
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <avr/pgmspace.h>
|
2016-04-06 12:57:42 +02:00
|
|
|
//#define DEBUG_TX
|
2016-08-31 10:26:27 +02:00
|
|
|
#include "Multiprotocol.h"
|
2016-04-06 12:57:42 +02:00
|
|
|
|
2016-01-22 16:23:39 +01:00
|
|
|
//Multiprotocol module configuration file
|
|
|
|
#include "_Config.h"
|
2016-10-16 19:51:42 +02:00
|
|
|
#include "Pins.h"
|
2016-08-24 14:52:47 +02:00
|
|
|
#include "TX_Def.h"
|
2016-10-16 19:51:42 +02:00
|
|
|
#include "Validate.h"
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
#include <avr/eeprom.h>
|
|
|
|
#else
|
2016-10-16 23:25:52 +02:00
|
|
|
#include <arduino.h>
|
2016-10-16 19:51:42 +02:00
|
|
|
#include <libmaple/usart.h>
|
|
|
|
#include <libmaple/timer.h>
|
|
|
|
#include <SPI.h>
|
|
|
|
#include <EEPROM.h>
|
|
|
|
HardwareTimer timer(2);
|
2016-10-17 08:37:09 +02:00
|
|
|
void PPM_decode();
|
|
|
|
void ISR_COMPB();
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
void __irq_usart2(void);
|
|
|
|
void __irq_usart3(void);
|
|
|
|
}
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
|
|
|
|
2015-12-30 01:41:12 +01:00
|
|
|
//Global constants/variables
|
|
|
|
uint32_t MProtocol_id;//tx id,
|
|
|
|
uint32_t MProtocol_id_master;
|
2016-11-17 12:08:44 +01:00
|
|
|
uint32_t blink=0,last_signal=0;
|
2015-12-30 01:41:12 +01:00
|
|
|
//
|
|
|
|
uint16_t counter;
|
2016-02-01 11:41:36 +01:00
|
|
|
uint8_t channel;
|
|
|
|
uint8_t packet[40];
|
2015-12-30 01:41:12 +01:00
|
|
|
|
|
|
|
#define NUM_CHN 16
|
|
|
|
// Servo data
|
|
|
|
uint16_t Servo_data[NUM_CHN];
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
uint8_t Servo_AUX;
|
2016-08-24 14:52:47 +02:00
|
|
|
uint16_t servo_max_100,servo_min_100,servo_max_125,servo_min_125;
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-02-05 17:27:51 +01:00
|
|
|
// Protocol variables
|
2016-08-25 14:48:48 +02:00
|
|
|
uint8_t cyrfmfg_id[6];//for dsm2 and devo
|
2016-02-01 11:41:36 +01:00
|
|
|
uint8_t rx_tx_addr[5];
|
2016-10-20 19:29:46 +02:00
|
|
|
uint8_t rx_id[4];
|
2016-02-01 11:41:36 +01:00
|
|
|
uint8_t phase;
|
2015-12-30 01:41:12 +01:00
|
|
|
uint16_t bind_counter;
|
2016-02-01 11:41:36 +01:00
|
|
|
uint8_t bind_phase;
|
|
|
|
uint8_t binding_idx;
|
2015-12-30 01:41:12 +01:00
|
|
|
uint16_t packet_period;
|
2016-02-01 11:41:36 +01:00
|
|
|
uint8_t packet_count;
|
|
|
|
uint8_t packet_sent;
|
|
|
|
uint8_t packet_length;
|
|
|
|
uint8_t hopping_frequency[23];
|
|
|
|
uint8_t *hopping_frequency_ptr;
|
|
|
|
uint8_t hopping_frequency_no=0;
|
|
|
|
uint8_t rf_ch_num;
|
|
|
|
uint8_t throttle, rudder, elevator, aileron;
|
|
|
|
uint8_t flags;
|
2016-02-05 17:27:51 +01:00
|
|
|
uint16_t crc;
|
2016-08-31 15:43:45 +02:00
|
|
|
uint8_t crc8;
|
|
|
|
uint16_t seed;
|
2016-01-26 13:46:22 +01:00
|
|
|
//
|
2016-08-01 21:57:18 +02:00
|
|
|
uint16_t state;
|
2016-02-01 11:41:36 +01:00
|
|
|
uint8_t len;
|
|
|
|
uint8_t RX_num;
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-04-06 12:57:42 +02:00
|
|
|
#if defined(FRSKYX_CC2500_INO) || defined(SFHSS_CC2500_INO)
|
2016-09-01 17:41:24 +02:00
|
|
|
uint8_t calData[48];
|
2016-04-06 12:57:42 +02:00
|
|
|
#endif
|
|
|
|
|
2016-07-28 20:58:12 +02:00
|
|
|
//Channel mapping for protocols
|
2016-10-20 19:29:46 +02:00
|
|
|
const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8, AUX9, AUX10};
|
2016-08-26 16:18:50 +02:00
|
|
|
const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8};
|
|
|
|
const uint8_t CH_RETA[]={RUDDER, ELEVATOR, THROTTLE, AILERON, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8};
|
2016-08-25 15:44:02 +02:00
|
|
|
const uint8_t CH_EATR[]={ELEVATOR, AILERON, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8};
|
2016-07-28 20:58:12 +02:00
|
|
|
|
2015-12-30 01:41:12 +01:00
|
|
|
// Mode_select variables
|
|
|
|
uint8_t mode_select;
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
uint8_t protocol_flags=0,protocol_flags2=0;
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-02-15 21:15:09 +01:00
|
|
|
// PPM variable
|
|
|
|
volatile uint16_t PPM_data[NUM_CHN];
|
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef ORANGE_TX
|
2016-09-12 16:41:40 +02:00
|
|
|
//Random variable
|
|
|
|
volatile uint32_t gWDT_entropy=0;
|
2016-09-12 21:44:30 +02:00
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
|
|
|
|
//Serial protocol
|
|
|
|
uint8_t sub_protocol;
|
2016-09-15 12:38:49 +02:00
|
|
|
uint8_t protocol;
|
2015-12-30 01:41:12 +01:00
|
|
|
uint8_t option;
|
2016-09-15 12:38:49 +02:00
|
|
|
uint8_t cur_protocol[3];
|
|
|
|
uint8_t prev_option;
|
|
|
|
uint8_t prev_power=0xFD; // unused power value
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-09-20 18:27:09 +02:00
|
|
|
//Serial RX variables
|
|
|
|
#define BAUD 100000
|
|
|
|
#define RXBUFFER_SIZE 26
|
|
|
|
volatile uint8_t rx_buff[RXBUFFER_SIZE];
|
|
|
|
volatile uint8_t rx_ok_buff[RXBUFFER_SIZE];
|
|
|
|
volatile uint8_t discard_frame = 0;
|
|
|
|
|
2015-12-30 01:41:12 +01:00
|
|
|
// Telemetry
|
2016-11-04 20:45:56 +01:00
|
|
|
#define MAX_PKT 29
|
2016-01-26 22:33:17 +01:00
|
|
|
uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
2016-01-27 17:57:33 +01:00
|
|
|
#if defined(TELEMETRY)
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifdef INVERT_TELEMETRY
|
2016-10-16 19:51:42 +02:00
|
|
|
#if not defined(ORANGE_TX) && not defined(STM32_BOARD)
|
|
|
|
// enable bit bash for serial
|
2016-09-20 18:27:09 +02:00
|
|
|
#define BASH_SERIAL 1
|
|
|
|
#endif
|
|
|
|
#define INVERT_SERIAL 1
|
|
|
|
#endif
|
2016-08-31 10:26:27 +02:00
|
|
|
uint8_t pass = 0;
|
2016-02-05 17:27:51 +01:00
|
|
|
uint8_t pktt[MAX_PKT];//telemetry receiving packets
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifndef BASH_SERIAL
|
|
|
|
#define TXBUFFER_SIZE 32
|
|
|
|
volatile uint8_t tx_buff[TXBUFFER_SIZE];
|
|
|
|
volatile uint8_t tx_head=0;
|
|
|
|
volatile uint8_t tx_tail=0;
|
|
|
|
#endif // BASH_SERIAL
|
2016-02-05 17:27:51 +01:00
|
|
|
uint8_t v_lipo;
|
|
|
|
int16_t RSSI_dBm;
|
2016-10-26 13:51:54 +02:00
|
|
|
uint8_t TX_RSSI;
|
2016-02-05 17:27:51 +01:00
|
|
|
uint8_t telemetry_link=0;
|
|
|
|
uint8_t telemetry_counter=0;
|
2016-10-16 19:51:42 +02:00
|
|
|
uint8_t telemetry_lost;
|
2015-12-30 01:41:12 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Callback
|
|
|
|
typedef uint16_t (*void_function_t) (void);//pointer to a function with no parameters which return an uint16_t integer
|
|
|
|
void_function_t remote_callback = 0;
|
|
|
|
|
|
|
|
// Init
|
|
|
|
void setup()
|
|
|
|
{
|
2016-10-16 19:51:42 +02:00
|
|
|
// General pinout
|
|
|
|
#ifdef ORANGE_TX
|
|
|
|
//XMEGA
|
2016-09-01 17:41:24 +02:00
|
|
|
PORTD.OUTSET = 0x17 ;
|
|
|
|
PORTD.DIRSET = 0xB2 ;
|
|
|
|
PORTD.DIRCLR = 0x4D ;
|
|
|
|
PORTD.PIN0CTRL = 0x18 ;
|
|
|
|
PORTD.PIN2CTRL = 0x18 ;
|
|
|
|
PORTE.DIRSET = 0x01 ;
|
|
|
|
PORTE.DIRCLR = 0x02 ;
|
|
|
|
// Timer1 config
|
|
|
|
// TCC1 16-bit timer, clocked at 0.5uS
|
|
|
|
EVSYS.CH3MUX = 0x80 + 0x04 ; // Prescaler of 16
|
|
|
|
TCC1.CTRLB = 0; TCC1.CTRLC = 0; TCC1.CTRLD = 0; TCC1.CTRLE = 0;
|
|
|
|
TCC1.INTCTRLA = 0; TIMSK1 = 0;
|
|
|
|
TCC1.PER = 0xFFFF ;
|
|
|
|
TCNT1 = 0 ;
|
|
|
|
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
|
|
|
//STM32
|
|
|
|
pinMode(A7105_CSN_pin,OUTPUT);
|
|
|
|
pinMode(CC25_CSN_pin,OUTPUT);
|
|
|
|
pinMode(NRF_CSN_pin,OUTPUT);
|
|
|
|
pinMode(CYRF_CSN_pin,OUTPUT);
|
|
|
|
pinMode(CYRF_RST_pin,OUTPUT);
|
|
|
|
pinMode(PE1_pin,OUTPUT);
|
|
|
|
pinMode(PE2_pin,OUTPUT);
|
|
|
|
#if defined TELEMETRY
|
|
|
|
pinMode(TX_INV_pin,OUTPUT);
|
|
|
|
pinMode(RX_INV_pin,OUTPUT);
|
|
|
|
#if defined INVERT_SERIAL
|
|
|
|
TX_INV_on;//activated inverter for both serial TX and RX signals
|
|
|
|
RX_INV_on;
|
|
|
|
#else
|
|
|
|
TX_INV_off;
|
|
|
|
RX_INV_off;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
pinMode(BIND_pin,INPUT_PULLUP);
|
|
|
|
pinMode(PPM_pin,INPUT);
|
|
|
|
pinMode(S1_pin,INPUT_PULLUP);//dial switch
|
|
|
|
pinMode(S2_pin,INPUT_PULLUP);
|
|
|
|
pinMode(S3_pin,INPUT_PULLUP);
|
|
|
|
pinMode(S4_pin,INPUT_PULLUP);
|
|
|
|
//Random pins
|
|
|
|
pinMode(PB0, INPUT_ANALOG); // set up pin for analog input
|
|
|
|
pinMode(PB1, INPUT_ANALOG); // set up pin for analog input
|
|
|
|
|
|
|
|
//select the counter clock.
|
|
|
|
start_timer2();//0.5us
|
|
|
|
#else
|
|
|
|
//ATMEGA328p
|
2016-09-19 23:43:14 +02:00
|
|
|
// all inputs
|
2016-09-20 18:27:09 +02:00
|
|
|
DDRB=0x00;DDRC=0x00;DDRD=0x00;
|
2016-09-19 23:43:14 +02:00
|
|
|
// outputs
|
|
|
|
SDI_output;
|
|
|
|
SCLK_output;
|
|
|
|
#ifdef A7105_INSTALLED
|
|
|
|
A7105_CSN_output;
|
|
|
|
#endif
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
CC25_CSN_output;
|
|
|
|
#endif
|
|
|
|
#ifdef CYRF6936_INSTALLED
|
|
|
|
CYRF_RST_output;
|
|
|
|
CYRF_CSN_output;
|
|
|
|
#endif
|
|
|
|
#ifdef NRF24L01_INSTALLED
|
|
|
|
NRF_CSN_output;
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2016-09-19 23:43:14 +02:00
|
|
|
PE1_output;
|
|
|
|
PE2_output;
|
2016-09-21 14:28:37 +02:00
|
|
|
SERIAL_TX_output;
|
2016-09-19 23:43:14 +02:00
|
|
|
|
|
|
|
// pullups
|
|
|
|
MODE_DIAL1_port |= _BV(MODE_DIAL1_pin);
|
|
|
|
MODE_DIAL2_port |= _BV(MODE_DIAL2_pin);
|
|
|
|
MODE_DIAL3_port |= _BV(MODE_DIAL3_pin);
|
|
|
|
MODE_DIAL4_port |= _BV(MODE_DIAL4_pin);
|
|
|
|
BIND_port |= _BV(BIND_pin);
|
2016-09-01 17:41:24 +02:00
|
|
|
|
|
|
|
// Timer1 config
|
|
|
|
TCCR1A = 0;
|
|
|
|
TCCR1B = (1 << CS11); //prescaler8, set timer1 to increment every 0.5us(16Mhz) and start timer
|
2016-09-19 23:43:14 +02:00
|
|
|
|
|
|
|
// Random
|
2016-09-12 21:44:30 +02:00
|
|
|
random_init();
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
|
|
|
|
// Set Chip selects
|
2016-09-19 23:43:14 +02:00
|
|
|
#ifdef A7105_INSTALLED
|
|
|
|
A7105_CSN_on;
|
|
|
|
#endif
|
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
CC25_CSN_on;
|
|
|
|
#endif
|
|
|
|
#ifdef CYRF6936_INSTALLED
|
|
|
|
CYRF_CSN_on;
|
|
|
|
#endif
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifdef NRF24L01_INSTALLED
|
|
|
|
NRF_CSN_on;
|
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
// Set SPI lines
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef STM32_BOARD
|
|
|
|
initSPI2();
|
|
|
|
#else
|
|
|
|
SDI_on;
|
|
|
|
SCLK_off;
|
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
|
|
|
|
// Set servos positions
|
|
|
|
for(uint8_t i=0;i<NUM_CHN;i++)
|
|
|
|
Servo_data[i]=1500;
|
2016-08-24 14:52:47 +02:00
|
|
|
Servo_data[THROTTLE]=servo_min_100;
|
2016-09-01 17:41:24 +02:00
|
|
|
#ifdef ENABLE_PPM
|
|
|
|
memcpy((void *)PPM_data,Servo_data, sizeof(Servo_data));
|
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-03-03 16:26:17 +01:00
|
|
|
//Wait for every component to start
|
2016-08-22 18:17:14 +02:00
|
|
|
delayMilliseconds(100);
|
2016-03-03 16:26:17 +01:00
|
|
|
|
2015-12-30 01:41:12 +01:00
|
|
|
// Read status of bind button
|
2016-08-26 18:33:05 +02:00
|
|
|
if( IS_BIND_BUTTON_on )
|
2015-12-30 01:41:12 +01:00
|
|
|
BIND_BUTTON_FLAG_on; // If bind button pressed save the status for protocol id reset under hubsan
|
|
|
|
|
|
|
|
// Read status of mode select binary switch
|
|
|
|
// after this mode_select will be one of {0000, 0001, ..., 1111}
|
2016-09-01 17:41:24 +02:00
|
|
|
#ifndef ENABLE_PPM
|
|
|
|
mode_select = MODE_SERIAL ; // force serial mode
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
|
|
|
mode_select= 0x0F -(uint8_t)(((GPIOA->regs->IDR)>>4)&0x0F);
|
2016-09-01 17:41:24 +02:00
|
|
|
#else
|
2016-09-20 18:27:09 +02:00
|
|
|
mode_select =
|
|
|
|
((MODE_DIAL1_ipr & _BV(MODE_DIAL1_pin)) ? 0 : 1) +
|
|
|
|
((MODE_DIAL2_ipr & _BV(MODE_DIAL2_pin)) ? 0 : 2) +
|
|
|
|
((MODE_DIAL3_ipr & _BV(MODE_DIAL3_pin)) ? 0 : 4) +
|
|
|
|
((MODE_DIAL4_ipr & _BV(MODE_DIAL4_pin)) ? 0 : 8);
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
|
|
|
|
// Update LED
|
2016-09-19 23:43:14 +02:00
|
|
|
LED_off;
|
|
|
|
LED_output;
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-01-25 17:22:47 +01:00
|
|
|
//Init RF modules
|
2016-08-31 10:26:27 +02:00
|
|
|
modules_reset();
|
2016-09-12 16:41:40 +02:00
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef ORANGE_TX
|
2016-09-12 16:41:40 +02:00
|
|
|
//Init the seed with a random value created from watchdog timer for all protocols requiring random values
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef STM32_BOARD
|
|
|
|
randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1));
|
|
|
|
#else
|
|
|
|
randomSeed(random_value());
|
|
|
|
#endif
|
2016-09-12 21:44:30 +02:00
|
|
|
#endif
|
2016-09-12 16:41:40 +02:00
|
|
|
|
|
|
|
// Read or create protocol id
|
|
|
|
MProtocol_id_master=random_id(10,false);
|
2016-08-31 10:26:27 +02:00
|
|
|
|
2016-08-24 14:52:47 +02:00
|
|
|
#ifdef ENABLE_PPM
|
2015-12-30 01:41:12 +01:00
|
|
|
//Protocol and interrupts initialization
|
|
|
|
if(mode_select != MODE_SERIAL)
|
|
|
|
{ // PPM
|
2016-01-22 16:23:39 +01:00
|
|
|
mode_select--;
|
2016-09-15 12:38:49 +02:00
|
|
|
protocol = PPM_prot[mode_select].protocol;
|
2016-09-16 16:56:46 +02:00
|
|
|
cur_protocol[1] = protocol;
|
2016-01-22 16:23:39 +01:00
|
|
|
sub_protocol = PPM_prot[mode_select].sub_proto;
|
2016-01-26 13:46:22 +01:00
|
|
|
RX_num = PPM_prot[mode_select].rx_num;
|
|
|
|
MProtocol_id = RX_num + MProtocol_id_master;
|
2016-01-22 16:23:39 +01:00
|
|
|
option = PPM_prot[mode_select].option;
|
|
|
|
if(PPM_prot[mode_select].power) POWER_FLAG_on;
|
|
|
|
if(PPM_prot[mode_select].autobind) AUTOBIND_FLAG_on;
|
|
|
|
mode_select++;
|
2016-08-24 14:52:47 +02:00
|
|
|
servo_max_100=PPM_MAX_100; servo_min_100=PPM_MIN_100;
|
|
|
|
servo_max_125=PPM_MAX_125; servo_min_125=PPM_MIN_125;
|
2016-01-22 16:23:39 +01:00
|
|
|
|
|
|
|
protocol_init();
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
//Configure PPM interrupt
|
|
|
|
#if PPM_pin == 2
|
|
|
|
EICRA |= _BV(ISC01); // The rising edge of INT0 pin D2 generates an interrupt request
|
|
|
|
EIMSK |= _BV(INT0); // INT0 interrupt enable
|
|
|
|
#elif PPM_pin == 3
|
|
|
|
EICRA |= _BV(ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
|
|
|
|
EIMSK |= _BV(INT1); // INT1 interrupt enable
|
|
|
|
#else
|
|
|
|
#error PPM pin can only be 2 or 3
|
|
|
|
#endif
|
2016-09-19 23:43:14 +02:00
|
|
|
#else
|
2016-10-16 19:51:42 +02:00
|
|
|
attachInterrupt(PPM_pin,PPM_decode,FALLING);
|
2016-09-19 23:43:14 +02:00
|
|
|
#endif
|
2016-04-06 12:57:42 +02:00
|
|
|
|
2016-09-01 17:41:24 +02:00
|
|
|
#if defined(TELEMETRY)
|
|
|
|
PPM_Telemetry_serial_init(); // Configure serial for telemetry
|
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
else
|
2016-08-24 14:52:47 +02:00
|
|
|
#endif //ENABLE_PPM
|
2015-12-30 01:41:12 +01:00
|
|
|
{ // Serial
|
2016-09-01 17:41:24 +02:00
|
|
|
#ifdef ENABLE_SERIAL
|
2016-09-15 16:02:36 +02:00
|
|
|
for(uint8_t i=0;i<3;i++)
|
2016-09-15 12:38:49 +02:00
|
|
|
cur_protocol[i]=0;
|
|
|
|
protocol=0;
|
2016-09-01 17:41:24 +02:00
|
|
|
servo_max_100=SERIAL_MAX_100; servo_min_100=SERIAL_MIN_100;
|
|
|
|
servo_max_125=SERIAL_MAX_125; servo_min_125=SERIAL_MIN_125;
|
|
|
|
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
|
|
|
#endif //ENABLE_SERIAL
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Main
|
2016-08-31 10:26:27 +02:00
|
|
|
// Protocol scheduler
|
2015-12-30 01:41:12 +01:00
|
|
|
void loop()
|
2016-08-31 10:26:27 +02:00
|
|
|
{
|
|
|
|
uint16_t next_callback,diff=0xFFFF;
|
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
if(remote_callback==0 || diff>2*200)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Update_All();
|
|
|
|
}
|
|
|
|
while(remote_callback==0);
|
|
|
|
}
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
if( (TIFR1 & OCF1A_bm) != 0)
|
|
|
|
{
|
|
|
|
cli(); // Disable global int due to RW of 16 bits registers
|
|
|
|
OCR1A=TCNT1; // Callback should already have been called... Use "now" as new sync point.
|
|
|
|
sei(); // Enable global int
|
|
|
|
}
|
|
|
|
else
|
|
|
|
while((TIFR1 & OCF1A_bm) == 0); // Wait before callback
|
|
|
|
#else
|
|
|
|
if((TIMER2_BASE->SR & TIMER_SR_CC1IF)!=0)
|
|
|
|
{
|
|
|
|
cli();
|
|
|
|
OCR1A = TCNT1;
|
|
|
|
sei();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
while((TIMER2_BASE->SR & TIMER_SR_CC1IF )==0); // Wait before callback
|
|
|
|
#endif
|
2016-08-31 10:26:27 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
TX_MAIN_PAUSE_on;
|
|
|
|
tx_pause();
|
|
|
|
next_callback=remote_callback();
|
|
|
|
TX_MAIN_PAUSE_off;
|
|
|
|
tx_resume();
|
|
|
|
while(next_callback>4000)
|
|
|
|
{ // start to wait here as much as we can...
|
|
|
|
next_callback-=2000; // We will wait below for 2ms
|
2016-09-01 17:41:24 +02:00
|
|
|
cli(); // Disable global int due to RW of 16 bits registers
|
|
|
|
OCR1A += 2000*2 ; // set compare A for callback
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
TIFR1=OCF1A_bm; // clear compare A=callback flag
|
|
|
|
#else
|
|
|
|
TIMER2_BASE->SR &= ~TIMER_SR_CC1IF; //clear compare Flag
|
|
|
|
#endif
|
2016-09-01 17:41:24 +02:00
|
|
|
sei(); // enable global int
|
|
|
|
Update_All();
|
|
|
|
if(IS_CHANGE_PROTOCOL_FLAG_on)
|
|
|
|
break; // Protocol has been changed
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
while((TIFR1 & OCF1A_bm) == 0); // wait 2ms...
|
|
|
|
#else
|
|
|
|
while((TIMER2_BASE->SR & TIMER_SR_CC1IF)==0);//2ms wait
|
|
|
|
#endif
|
2016-08-31 10:26:27 +02:00
|
|
|
}
|
|
|
|
// at this point we have a maximum of 4ms in next_callback
|
|
|
|
next_callback *= 2 ;
|
2016-09-01 17:41:24 +02:00
|
|
|
cli(); // Disable global int due to RW of 16 bits registers
|
|
|
|
OCR1A+= next_callback ; // set compare A for callback
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
TIFR1=OCF1A_bm; // clear compare A=callback flag
|
|
|
|
#else
|
|
|
|
TIMER2_BASE->SR &= ~TIMER_SR_CC1IF; //clear compare Flag write zero
|
|
|
|
#endif
|
2016-09-01 17:41:24 +02:00
|
|
|
diff=OCR1A-TCNT1; // compare timer and comparator
|
|
|
|
sei(); // enable global int
|
2016-08-31 10:26:27 +02:00
|
|
|
}
|
|
|
|
while(diff&0x8000); // Callback did not took more than requested time for next callback
|
|
|
|
// so we can launch Update_All before next callback
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Update_All()
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-09-01 17:41:24 +02:00
|
|
|
#ifdef ENABLE_SERIAL
|
2016-11-17 12:08:44 +01:00
|
|
|
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
|
2016-09-01 17:41:24 +02:00
|
|
|
{
|
2016-11-17 12:08:44 +01:00
|
|
|
update_serial_data(); // Update protocol and data
|
2016-09-01 17:41:24 +02:00
|
|
|
update_aux_flags();
|
|
|
|
if(IS_CHANGE_PROTOCOL_FLAG_on)
|
|
|
|
{ // Protocol needs to be changed
|
2016-09-19 23:43:14 +02:00
|
|
|
LED_off; //led off during protocol init
|
2016-09-01 17:41:24 +02:00
|
|
|
modules_reset(); //reset all modules
|
|
|
|
protocol_init(); //init new protocol
|
|
|
|
}
|
2016-11-17 12:08:44 +01:00
|
|
|
|
|
|
|
INPUT_SIGNAL_on; //valid signal received
|
|
|
|
last_signal=millis();
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif //ENABLE_SERIAL
|
|
|
|
#ifdef ENABLE_PPM
|
2016-11-17 12:08:44 +01:00
|
|
|
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
2016-09-01 17:41:24 +02:00
|
|
|
{
|
|
|
|
for(uint8_t i=0;i<NUM_CHN;i++)
|
|
|
|
{ // update servo data without interrupts to prevent bad read in protocols
|
|
|
|
uint16_t temp_ppm ;
|
2016-11-17 12:08:44 +01:00
|
|
|
cli(); // disable global int
|
2016-09-01 17:41:24 +02:00
|
|
|
temp_ppm = PPM_data[i] ;
|
2016-11-17 12:08:44 +01:00
|
|
|
sei(); // enable global int
|
2016-09-01 17:41:24 +02:00
|
|
|
if(temp_ppm<PPM_MIN_125) temp_ppm=PPM_MIN_125;
|
|
|
|
else if(temp_ppm>PPM_MAX_125) temp_ppm=PPM_MAX_125;
|
|
|
|
Servo_data[i]= temp_ppm ;
|
|
|
|
}
|
|
|
|
update_aux_flags();
|
2016-11-17 12:08:44 +01:00
|
|
|
PPM_FLAG_off; // wait for next frame before update
|
|
|
|
INPUT_SIGNAL_on; //valid signal received
|
|
|
|
last_signal=millis();
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif //ENABLE_PPM
|
2015-12-30 01:41:12 +01:00
|
|
|
#if defined(TELEMETRY)
|
2016-10-20 19:29:46 +02:00
|
|
|
if((protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) )
|
2016-09-01 17:41:24 +02:00
|
|
|
TelemetryUpdate();
|
2016-08-31 10:26:27 +02:00
|
|
|
#endif
|
2016-11-17 12:08:44 +01:00
|
|
|
update_led_status();
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
// Update Servo_AUX flags based on servo AUX positions
|
|
|
|
static void update_aux_flags(void)
|
|
|
|
{
|
|
|
|
Servo_AUX=0;
|
|
|
|
for(uint8_t i=0;i<8;i++)
|
|
|
|
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
|
|
|
Servo_AUX|=1<<i;
|
|
|
|
}
|
|
|
|
|
2015-12-30 01:41:12 +01:00
|
|
|
// Update led status based on binding and serial
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
static void update_led_status(void)
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-11-17 12:08:44 +01:00
|
|
|
if(IS_INPUT_SIGNAL_on)
|
|
|
|
if(millis()-last_signal>50)
|
|
|
|
INPUT_SIGNAL_off; //no valid signal (PPM or Serial) received for 50ms
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
if(blink<millis())
|
|
|
|
{
|
2016-11-17 12:08:44 +01:00
|
|
|
if(IS_INPUT_SIGNAL_off)
|
|
|
|
{
|
|
|
|
if(mode_select==MODE_SERIAL)
|
|
|
|
blink+=BLINK_SERIAL_TIME; //blink slowly if no valid serial input
|
|
|
|
else
|
|
|
|
blink+=BLINK_PPM_TIME; //blink more slowly if no valid PPM input
|
|
|
|
}
|
2015-12-30 01:41:12 +01:00
|
|
|
else
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
if(remote_callback == 0)
|
|
|
|
{ // Invalid protocol
|
|
|
|
if(IS_LED_on) //flash to indicate invalid protocol
|
|
|
|
blink+=BLINK_BAD_PROTO_TIME_LOW;
|
|
|
|
else
|
|
|
|
blink+=BLINK_BAD_PROTO_TIME_HIGH;
|
|
|
|
}
|
2015-12-30 01:41:12 +01:00
|
|
|
else
|
2016-11-17 12:08:44 +01:00
|
|
|
{
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
if(IS_BIND_DONE_on)
|
2016-11-17 12:08:44 +01:00
|
|
|
LED_off; //bind completed force led on
|
|
|
|
blink+=BLINK_BIND_TIME; //blink fastly during binding
|
|
|
|
}
|
2016-09-19 23:43:14 +02:00
|
|
|
LED_toggle;
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
}
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
2016-08-31 10:26:27 +02:00
|
|
|
inline void tx_pause()
|
|
|
|
{
|
2016-10-27 11:15:25 +02:00
|
|
|
#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);
|
2016-10-16 19:51:42 +02:00
|
|
|
#endif
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2016-08-31 10:26:27 +02:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void tx_resume()
|
|
|
|
{
|
2016-10-27 11:15:25 +02:00
|
|
|
#ifdef TELEMETRY
|
|
|
|
// Resume telemetry by enabling transmitter interrupt
|
|
|
|
if(!IS_TX_PAUSE_on)
|
|
|
|
{
|
|
|
|
#ifdef ORANGE_TX
|
|
|
|
cli() ;
|
|
|
|
USARTC0.CTRLA = (USARTC0.CTRLA & 0xFC) | 0x01 ;
|
|
|
|
sei() ;
|
|
|
|
#else
|
|
|
|
#ifndef BASH_SERIAL
|
|
|
|
#ifdef STM32_BOARD
|
|
|
|
USART3_BASE->CR1 |= USART_CR1_TXEIE;
|
2016-10-16 19:51:42 +02:00
|
|
|
#else
|
2016-10-27 11:15:25 +02:00
|
|
|
UCSR0B |= _BV(UDRIE0);
|
2016-10-16 19:51:42 +02:00
|
|
|
#endif
|
2016-10-27 11:15:25 +02:00
|
|
|
#else
|
|
|
|
resumeBashSerial();
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2016-10-27 11:15:25 +02:00
|
|
|
#endif
|
|
|
|
}
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef STM32_BOARD
|
|
|
|
void start_timer2()
|
|
|
|
{
|
|
|
|
// Pause the timer while we're configuring it
|
|
|
|
timer.pause();
|
|
|
|
TIMER2_BASE->PSC = 35; //36-1;for 72 MHZ /0.5sec/(35+1)
|
|
|
|
TIMER2_BASE->ARR = 0xFFFF; //count till max
|
|
|
|
timer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
|
|
|
|
timer.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE);
|
|
|
|
// Refresh the timer's count, prescale, and overflow
|
|
|
|
timer.refresh();
|
|
|
|
timer.resume();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-01-22 16:23:39 +01:00
|
|
|
// Protocol start
|
|
|
|
static void protocol_init()
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
uint16_t next_callback=0; // Default is immediate call back
|
2015-12-30 01:41:12 +01:00
|
|
|
remote_callback = 0;
|
|
|
|
|
2016-08-31 10:26:27 +02:00
|
|
|
// reset telemetry
|
|
|
|
#ifdef TELEMETRY
|
|
|
|
tx_pause();
|
|
|
|
pass=0;
|
|
|
|
telemetry_link=0;
|
2016-10-16 19:51:42 +02:00
|
|
|
telemetry_lost=1;
|
2016-09-01 20:12:17 +02:00
|
|
|
#ifndef BASH_SERIAL
|
|
|
|
tx_tail=0;
|
|
|
|
tx_head=0;
|
|
|
|
#endif
|
2016-10-27 11:15:25 +02:00
|
|
|
TX_RX_PAUSE_off;
|
|
|
|
TX_MAIN_PAUSE_off;
|
2016-08-31 10:26:27 +02:00
|
|
|
#endif
|
|
|
|
|
Core and all protocols have been updated
Lot of changes in this new master
ChangeLog:
- Core: LED flashing when an invalid protocol has been selected
- Core: Channels 5 to 12 available as switches for all protocols: code
and size optimization
- Documentation (readme.md): fully updated, all protocols/sub
protocols/channels described, models example, many improvements
- All protocols have been updated in some way, here are some highlights:
* Bayang: added picture, video and inverted channels
* CG023->H8_3D: added light and calibration channels
* CX10: added sub protocols Q282, JC3015_1, JC3015_2, MK33041
* ESky: added new protocol - untested
* Hubsan: added compatibility with the new Hubsan Plus protocol
* KN: fully rewritten protocol: added sub protocols WLTOYS and FEILUN,
11 channels support
New version successfully tested on all my models: Flysky RX/F939/V911
protocol Flysky, Frsky RX protocol Frsky, Hubsan X4 protocol Hubsan,
Hisky HCP100/HCP80 protocol Hisky, HK-3000/HK3100 RX protocol
Hisky/HK310, XINXUN X39 protocol YD717/XINXUN, Symax X5C-1 protocol
SymaX/SYMAX, Cheerson CX-10A protocol CX10/BLUE, Eachine 3D-X4 protocol
CG023.
To access new protocols from er9x/ersky9x, you need to build a version
from this github repository https://github.com/pascallanger/mbtx based
on the latest er9x r820 and ersky9x r218.
2016-01-20 10:50:56 +01:00
|
|
|
blink=millis();
|
2015-12-30 01:41:12 +01:00
|
|
|
if(IS_BIND_BUTTON_FLAG_on)
|
|
|
|
AUTOBIND_FLAG_on;
|
|
|
|
if(IS_AUTOBIND_FLAG_on)
|
|
|
|
BIND_IN_PROGRESS; // Indicates bind in progress for blinking bind led
|
|
|
|
else
|
|
|
|
BIND_DONE;
|
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
PE1_on; //NRF24L01 antenna RF3 by default
|
2016-09-19 23:43:14 +02:00
|
|
|
PE2_off; //NRF24L01 antenna RF3 by default
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-09-15 12:38:49 +02:00
|
|
|
switch(protocol) // Init the requested protocol
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifdef A7105_INSTALLED
|
|
|
|
#if defined(FLYSKY_A7105_INO)
|
|
|
|
case MODE_FLYSKY:
|
|
|
|
PE1_off; //antenna RF1
|
|
|
|
next_callback = initFlySky();
|
|
|
|
remote_callback = ReadFlySky;
|
|
|
|
break;
|
|
|
|
#endif
|
2016-10-20 19:29:46 +02:00
|
|
|
#if defined(AFHDS2A_A7105_INO)
|
|
|
|
case MODE_AFHDS2A:
|
|
|
|
PE1_off; //antenna RF1
|
|
|
|
next_callback = initAFHDS2A();
|
|
|
|
remote_callback = ReadAFHDS2A;
|
|
|
|
break;
|
|
|
|
#endif
|
2016-09-20 18:27:09 +02:00
|
|
|
#if defined(HUBSAN_A7105_INO)
|
|
|
|
case MODE_HUBSAN:
|
|
|
|
PE1_off; //antenna RF1
|
|
|
|
if(IS_BIND_BUTTON_FLAG_on) random_id(10,true); // Generate new ID if bind button is pressed.
|
|
|
|
next_callback = initHubsan();
|
|
|
|
remote_callback = ReadHubsan;
|
|
|
|
break;
|
|
|
|
#endif
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
#if defined(FRSKYD_CC2500_INO)
|
|
|
|
case MODE_FRSKYD:
|
|
|
|
PE1_off; //antenna RF2
|
|
|
|
PE2_on;
|
|
|
|
next_callback = initFrSky_2way();
|
|
|
|
remote_callback = ReadFrSky_2way;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(FRSKYV_CC2500_INO)
|
|
|
|
case MODE_FRSKYV:
|
|
|
|
PE1_off; //antenna RF2
|
|
|
|
PE2_on;
|
|
|
|
next_callback = initFRSKYV();
|
|
|
|
remote_callback = ReadFRSKYV;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(FRSKYX_CC2500_INO)
|
|
|
|
case MODE_FRSKYX:
|
|
|
|
PE1_off; //antenna RF2
|
|
|
|
PE2_on;
|
|
|
|
next_callback = initFrSkyX();
|
|
|
|
remote_callback = ReadFrSkyX;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(SFHSS_CC2500_INO)
|
|
|
|
case MODE_SFHSS:
|
|
|
|
PE1_off; //antenna RF2
|
|
|
|
PE2_on;
|
|
|
|
next_callback = initSFHSS();
|
|
|
|
remote_callback = ReadSFHSS;
|
|
|
|
break;
|
|
|
|
#endif
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifdef CYRF6936_INSTALLED
|
|
|
|
#if defined(DSM_CYRF6936_INO)
|
|
|
|
case MODE_DSM:
|
|
|
|
PE2_on; //antenna RF4
|
|
|
|
next_callback = initDsm();
|
|
|
|
//Servo_data[2]=1500;//before binding
|
|
|
|
remote_callback = ReadDsm;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(DEVO_CYRF6936_INO)
|
|
|
|
case MODE_DEVO:
|
|
|
|
#ifdef ENABLE_PPM
|
|
|
|
if(mode_select) //PPM mode
|
2016-09-01 17:41:24 +02:00
|
|
|
{
|
2016-09-20 18:27:09 +02:00
|
|
|
if(IS_BIND_BUTTON_FLAG_on)
|
|
|
|
{
|
2016-10-16 19:51:42 +02:00
|
|
|
eeprom_write_byte((EE_ADDR)(30+mode_select),0x00); // reset to autobind mode for the current model
|
2016-09-20 18:27:09 +02:00
|
|
|
option=0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-16 19:51:42 +02:00
|
|
|
option=eeprom_read_byte((EE_ADDR)(30+mode_select)); // load previous mode: autobind or fixed id
|
|
|
|
if(option!=1) option=0; // if not fixed id mode then it should be autobind
|
2016-09-20 18:27:09 +02:00
|
|
|
}
|
2016-09-01 17:41:24 +02:00
|
|
|
}
|
2016-09-20 18:27:09 +02:00
|
|
|
#endif //ENABLE_PPM
|
|
|
|
PE2_on; //antenna RF4
|
|
|
|
next_callback = DevoInit();
|
|
|
|
remote_callback = devo_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(J6PRO_CYRF6936_INO)
|
|
|
|
case MODE_J6PRO:
|
|
|
|
PE2_on; //antenna RF4
|
|
|
|
next_callback = initJ6Pro();
|
|
|
|
remote_callback = ReadJ6Pro;
|
|
|
|
break;
|
|
|
|
#endif
|
2016-09-01 17:41:24 +02:00
|
|
|
#endif
|
2016-09-20 18:27:09 +02:00
|
|
|
#ifdef NRF24L01_INSTALLED
|
|
|
|
#if defined(HISKY_NRF24L01_INO)
|
|
|
|
case MODE_HISKY:
|
|
|
|
next_callback=initHiSky();
|
|
|
|
remote_callback = hisky_cb;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(V2X2_NRF24L01_INO)
|
|
|
|
case MODE_V2X2:
|
|
|
|
next_callback = initV2x2();
|
|
|
|
remote_callback = ReadV2x2;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(YD717_NRF24L01_INO)
|
|
|
|
case MODE_YD717:
|
|
|
|
next_callback=initYD717();
|
|
|
|
remote_callback = yd717_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(KN_NRF24L01_INO)
|
|
|
|
case MODE_KN:
|
|
|
|
next_callback = initKN();
|
|
|
|
remote_callback = kn_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(SYMAX_NRF24L01_INO)
|
|
|
|
case MODE_SYMAX:
|
|
|
|
next_callback = initSymax();
|
|
|
|
remote_callback = symax_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(SLT_NRF24L01_INO)
|
|
|
|
case MODE_SLT:
|
|
|
|
next_callback=initSLT();
|
|
|
|
remote_callback = SLT_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(CX10_NRF24L01_INO)
|
2016-11-23 21:56:00 +01:00
|
|
|
case MODE_Q2X2:
|
|
|
|
sub_protocol|=0x08; // Increase the number of sub_protocols for CX-10
|
2016-09-20 18:27:09 +02:00
|
|
|
case MODE_CX10:
|
|
|
|
next_callback=initCX10();
|
|
|
|
remote_callback = CX10_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(CG023_NRF24L01_INO)
|
|
|
|
case MODE_CG023:
|
|
|
|
next_callback=initCG023();
|
|
|
|
remote_callback = CG023_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(BAYANG_NRF24L01_INO)
|
|
|
|
case MODE_BAYANG:
|
|
|
|
next_callback=initBAYANG();
|
|
|
|
remote_callback = BAYANG_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(ESKY_NRF24L01_INO)
|
|
|
|
case MODE_ESKY:
|
|
|
|
next_callback=initESKY();
|
|
|
|
remote_callback = ESKY_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(MT99XX_NRF24L01_INO)
|
|
|
|
case MODE_MT99XX:
|
|
|
|
next_callback=initMT99XX();
|
|
|
|
remote_callback = MT99XX_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(MJXQ_NRF24L01_INO)
|
|
|
|
case MODE_MJXQ:
|
|
|
|
next_callback=initMJXQ();
|
|
|
|
remote_callback = MJXQ_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(SHENQI_NRF24L01_INO)
|
|
|
|
case MODE_SHENQI:
|
|
|
|
next_callback=initSHENQI();
|
|
|
|
remote_callback = SHENQI_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(FY326_NRF24L01_INO)
|
|
|
|
case MODE_FY326:
|
|
|
|
next_callback=initFY326();
|
|
|
|
remote_callback = FY326_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(FQ777_NRF24L01_INO)
|
|
|
|
case MODE_FQ777:
|
|
|
|
next_callback=initFQ777();
|
|
|
|
remote_callback = FQ777_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(ASSAN_NRF24L01_INO)
|
|
|
|
case MODE_ASSAN:
|
|
|
|
next_callback=initASSAN();
|
|
|
|
remote_callback = ASSAN_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if defined(HONTAI_NRF24L01_INO)
|
|
|
|
case MODE_HONTAI:
|
|
|
|
next_callback=initHONTAI();
|
|
|
|
remote_callback = HONTAI_callback;
|
|
|
|
break;
|
|
|
|
#endif
|
2016-09-09 18:34:20 +02:00
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(next_callback>32000)
|
|
|
|
{ // next_callback should not be more than 32767 so we will wait here...
|
2016-08-24 14:52:47 +02:00
|
|
|
uint16_t temp=(next_callback>>10)-2;
|
2016-08-22 18:17:14 +02:00
|
|
|
delayMilliseconds(temp);
|
2016-09-15 12:38:49 +02:00
|
|
|
next_callback-=temp<<10; // between 2-3ms left at this stage
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-15 12:38:49 +02:00
|
|
|
cli(); // disable global int
|
|
|
|
OCR1A = TCNT1 + next_callback*2; // set compare A for callback
|
|
|
|
sei(); // enable global int
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifndef STM32_BOARD
|
|
|
|
TIFR1 = OCF1A_bm ; // clear compare A flag
|
|
|
|
#else
|
|
|
|
TIMER2_BASE->SR &= ~TIMER_SR_CC1IF; //clear compare Flag write zero
|
|
|
|
#endif
|
2016-09-15 12:38:49 +02:00
|
|
|
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
2016-08-24 14:52:47 +02:00
|
|
|
void update_serial_data()
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-08-29 17:32:21 +02:00
|
|
|
RX_DONOTUPDTAE_on;
|
2016-09-15 12:38:49 +02:00
|
|
|
RX_FLAG_off; //data is being processed
|
|
|
|
if(rx_ok_buff[1]&0x20) //check range
|
2016-08-29 17:32:21 +02:00
|
|
|
RANGE_FLAG_on;
|
|
|
|
else
|
|
|
|
RANGE_FLAG_off;
|
2016-09-15 12:38:49 +02:00
|
|
|
if(rx_ok_buff[1]&0xC0) //check autobind(0x40) & bind(0x80) together
|
2016-08-29 17:32:21 +02:00
|
|
|
AUTOBIND_FLAG_on;
|
|
|
|
else
|
|
|
|
AUTOBIND_FLAG_off;
|
2016-09-15 12:38:49 +02:00
|
|
|
if(rx_ok_buff[2]&0x80) //if rx_ok_buff[2] ==1,power is low ,0-power high
|
|
|
|
POWER_FLAG_off; //power low
|
2016-08-29 17:32:21 +02:00
|
|
|
else
|
2016-09-15 12:38:49 +02:00
|
|
|
POWER_FLAG_on; //power high
|
|
|
|
|
|
|
|
option=rx_ok_buff[3];
|
2016-08-29 17:32:21 +02:00
|
|
|
|
2016-09-15 12:38:49 +02:00
|
|
|
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) ) )
|
2016-08-29 17:32:21 +02:00
|
|
|
{ // New model has been selected
|
|
|
|
CHANGE_PROTOCOL_FLAG_on; //change protocol
|
2016-09-15 12:38:49 +02:00
|
|
|
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
|
|
|
|
MProtocol_id=MProtocol_id_master+RX_num;//personalized RX bind + rx num
|
|
|
|
set_rx_tx_addr(MProtocol_id); //set rx_tx_addr
|
2016-08-29 17:32:21 +02:00
|
|
|
}
|
|
|
|
else
|
2016-09-15 12:38:49 +02:00
|
|
|
if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set
|
2016-08-29 17:32:21 +02:00
|
|
|
CHANGE_PROTOCOL_FLAG_on; //restart protocol with bind
|
2016-08-31 10:26:27 +02:00
|
|
|
else
|
|
|
|
CHANGE_PROTOCOL_FLAG_off; //no need to restart
|
2016-09-15 12:38:49 +02:00
|
|
|
//store current protocol values
|
|
|
|
for(uint8_t i=0;i<3;i++)
|
|
|
|
cur_protocol[i] = rx_ok_buff[i];
|
|
|
|
|
2016-08-29 17:32:21 +02:00
|
|
|
// decode channel values
|
2016-09-15 12:38:49 +02:00
|
|
|
volatile uint8_t *p=rx_ok_buff+3;
|
2016-08-29 17:32:21 +02:00
|
|
|
uint8_t dec=-3;
|
|
|
|
for(uint8_t i=0;i<NUM_CHN;i++)
|
|
|
|
{
|
|
|
|
dec+=3;
|
|
|
|
if(dec>=8)
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-08-29 17:32:21 +02:00
|
|
|
dec-=8;
|
2015-12-30 01:41:12 +01:00
|
|
|
p++;
|
|
|
|
}
|
2016-08-29 17:32:21 +02:00
|
|
|
p++;
|
|
|
|
Servo_data[i]=((((*((uint32_t *)p))>>dec)&0x7FF)*5)/8+860; //value range 860<->2140 -125%<->+125%
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-08-29 17:32:21 +02:00
|
|
|
RX_DONOTUPDTAE_off;
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-08-29 17:32:21 +02:00
|
|
|
cli();
|
|
|
|
#else
|
2016-09-15 12:38:49 +02:00
|
|
|
UCSR0B &= ~_BV(RXCIE0); // RX interrupt disable
|
2016-08-29 17:32:21 +02:00
|
|
|
#endif
|
2016-09-15 12:38:49 +02:00
|
|
|
if(IS_RX_MISSED_BUFF_on) // If the buffer is still valid
|
2016-08-31 10:26:27 +02:00
|
|
|
{ memcpy((void*)rx_ok_buff,(const void*)rx_buff,RXBUFFER_SIZE);// Duplicate the buffer
|
2016-09-15 12:38:49 +02:00
|
|
|
RX_FLAG_on; // data to be processed next time...
|
2016-08-31 10:26:27 +02:00
|
|
|
RX_MISSED_BUFF_off;
|
|
|
|
}
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-08-29 17:32:21 +02:00
|
|
|
sei();
|
|
|
|
#else
|
2016-09-15 12:38:49 +02:00
|
|
|
UCSR0B |= _BV(RXCIE0) ; // RX interrupt enable
|
2016-08-29 17:32:21 +02:00
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
2016-08-31 10:26:27 +02:00
|
|
|
void modules_reset()
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-08-31 10:26:27 +02:00
|
|
|
#ifdef CC2500_INSTALLED
|
|
|
|
CC2500_Reset();
|
|
|
|
#endif
|
|
|
|
#ifdef A7105_INSTALLED
|
|
|
|
A7105_Reset();
|
|
|
|
#endif
|
|
|
|
#ifdef CYRF6936_INSTALLED
|
|
|
|
CYRF_Reset();
|
|
|
|
#endif
|
2016-09-19 23:43:14 +02:00
|
|
|
#ifdef NRF24L01_INSTALLED
|
2016-08-31 10:26:27 +02:00
|
|
|
NRF24L01_Reset();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//Wait for every component to reset
|
|
|
|
delayMilliseconds(100);
|
|
|
|
prev_power=0xFD; // unused power value
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
2016-08-24 14:52:47 +02:00
|
|
|
void Mprotocol_serial_init()
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-09-01 17:41:24 +02:00
|
|
|
PORTC.OUTSET = 0x08 ;
|
|
|
|
PORTC.DIRSET = 0x08 ;
|
|
|
|
|
|
|
|
USARTC0.BAUDCTRLA = 19 ;
|
|
|
|
USARTC0.BAUDCTRLB = 0 ;
|
|
|
|
|
|
|
|
USARTC0.CTRLB = 0x18 ;
|
|
|
|
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
|
|
|
|
USARTC0.CTRLC = 0x2B ;
|
|
|
|
UDR0 ;
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef INVERT_SERIAL
|
2016-09-01 17:41:24 +02:00
|
|
|
PORTC.PIN3CTRL |= 0x40 ;
|
|
|
|
#endif
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
2016-11-06 16:34:40 +01:00
|
|
|
usart2_begin(100000,SERIAL_8E2);
|
|
|
|
usart3_begin(100000,SERIAL_8E2);
|
2016-10-16 19:51:42 +02:00
|
|
|
USART2_BASE->CR1 |= USART_CR1_PCE_BIT;
|
|
|
|
USART3_BASE->CR1 &= ~ USART_CR1_RE;//disable
|
|
|
|
USART2_BASE->CR1 &= ~ USART_CR1_TE;//disable transmit
|
2016-09-01 17:41:24 +02:00
|
|
|
#else
|
2016-10-16 19:51:42 +02:00
|
|
|
//ATMEGA328p
|
2016-09-01 17:41:24 +02:00
|
|
|
#include <util/setbaud.h>
|
|
|
|
UBRR0H = UBRRH_VALUE;
|
|
|
|
UBRR0L = UBRRL_VALUE;
|
|
|
|
UCSR0A = 0 ; // Clear X2 bit
|
|
|
|
//Set frame format to 8 data bits, even parity, 2 stop bits
|
|
|
|
UCSR0C = _BV(UPM01)|_BV(USBS0)|_BV(UCSZ01)|_BV(UCSZ00);
|
|
|
|
while ( UCSR0A & (1 << RXC0) )//flush receive buffer
|
|
|
|
UDR0;
|
|
|
|
//enable reception and RC complete interrupt
|
|
|
|
UCSR0B = _BV(RXEN0)|_BV(RXCIE0);//rx enable and interrupt
|
|
|
|
#ifndef DEBUG_TX
|
|
|
|
#if defined(TELEMETRY)
|
|
|
|
initTXSerial( SPEED_100K ) ;
|
|
|
|
#endif //TELEMETRY
|
|
|
|
#endif //DEBUG_TX
|
2016-10-16 19:51:42 +02:00
|
|
|
#endif //ORANGE_TX
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 10:50:52 +01:00
|
|
|
#if defined(TELEMETRY)
|
2016-08-24 14:52:47 +02:00
|
|
|
void PPM_Telemetry_serial_init()
|
2016-01-27 17:57:33 +01:00
|
|
|
{
|
2016-10-27 11:15:25 +02:00
|
|
|
if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) )
|
2016-09-16 10:39:44 +02:00
|
|
|
initTXSerial( SPEED_9600 ) ;
|
|
|
|
if(protocol==MODE_FRSKYX)
|
|
|
|
initTXSerial( SPEED_57600 ) ;
|
|
|
|
if(protocol==MODE_DSM)
|
|
|
|
initTXSerial( SPEED_125K ) ;
|
2016-01-27 17:57:33 +01:00
|
|
|
}
|
2016-01-28 10:50:52 +01:00
|
|
|
#endif
|
2016-01-27 17:57:33 +01:00
|
|
|
|
2016-01-22 16:23:39 +01:00
|
|
|
// Convert 32b id to rx_tx_addr
|
|
|
|
static void set_rx_tx_addr(uint32_t id)
|
|
|
|
{ // Used by almost all protocols
|
|
|
|
rx_tx_addr[0] = (id >> 24) & 0xFF;
|
|
|
|
rx_tx_addr[1] = (id >> 16) & 0xFF;
|
|
|
|
rx_tx_addr[2] = (id >> 8) & 0xFF;
|
|
|
|
rx_tx_addr[3] = (id >> 0) & 0xFF;
|
2016-09-21 14:28:37 +02:00
|
|
|
rx_tx_addr[4] = (rx_tx_addr[2]&0xF0)|(rx_tx_addr[3]&0x0F);
|
2016-01-22 16:23:39 +01:00
|
|
|
}
|
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
|
2016-09-12 16:41:40 +02:00
|
|
|
static void random_init(void)
|
|
|
|
{
|
|
|
|
cli(); // Temporarily turn off interrupts, until WDT configured
|
|
|
|
MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
|
|
|
|
WDTCSR |= _BV(WDCE); // WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the prescaler
|
|
|
|
WDTCSR = _BV(WDIE); // Watchdog interrupt enable (WDIE)
|
|
|
|
sei(); // Turn interupts on
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t random_value(void)
|
|
|
|
{
|
|
|
|
while (!gWDT_entropy);
|
|
|
|
return gWDT_entropy;
|
|
|
|
}
|
2016-09-12 21:44:30 +02:00
|
|
|
#endif
|
2016-09-12 16:41:40 +02:00
|
|
|
|
2015-12-30 01:41:12 +01:00
|
|
|
static uint32_t random_id(uint16_t adress, uint8_t create_new)
|
|
|
|
{
|
2016-10-16 19:51:42 +02:00
|
|
|
uint32_t id=0;
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
if(eeprom_read_byte((EE_ADDR)(adress+10))==0xf0 && !create_new)
|
2015-12-30 01:41:12 +01:00
|
|
|
{ // TXID exists in EEPROM
|
2016-10-16 19:51:42 +02:00
|
|
|
for(uint8_t i=4;i>0;i--)
|
|
|
|
{
|
|
|
|
id<<=8;
|
|
|
|
id|=eeprom_read_byte((EE_ADDR)adress+i-1);
|
|
|
|
}
|
2016-09-12 16:41:40 +02:00
|
|
|
if(id!=0x2AD141A7) //ID with seed=0
|
|
|
|
return id;
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-12 16:41:40 +02:00
|
|
|
// Generate a random ID
|
|
|
|
id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
|
2016-10-16 19:51:42 +02:00
|
|
|
for(uint8_t i=0;i<4;i++)
|
|
|
|
{
|
|
|
|
eeprom_write_byte((EE_ADDR)adress+i,id);
|
|
|
|
id>>=8;
|
|
|
|
}
|
|
|
|
eeprom_write_byte((EE_ADDR)(adress+10),0xf0);//write bind flag in eeprom.
|
2015-12-30 01:41:12 +01:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************/
|
|
|
|
/**************************/
|
|
|
|
/** Interrupt routines **/
|
|
|
|
/**************************/
|
|
|
|
/**************************/
|
|
|
|
|
2016-01-22 16:23:39 +01:00
|
|
|
//PPM
|
2016-08-24 14:52:47 +02:00
|
|
|
#ifdef ENABLE_PPM
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-09-19 23:43:14 +02:00
|
|
|
#if PPM_pin == 2
|
|
|
|
ISR(PORTD_INT0_vect)
|
|
|
|
#else
|
|
|
|
ISR(PORTD_INT1_vect)
|
|
|
|
#endif
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
|
|
|
void PPM_decode()
|
2016-09-19 23:43:14 +02:00
|
|
|
#else
|
|
|
|
#if PPM_pin == 2
|
|
|
|
ISR(INT0_vect, ISR_NOBLOCK)
|
|
|
|
#else
|
|
|
|
ISR(INT1_vect, ISR_NOBLOCK)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
{ // Interrupt on PPM pin
|
2016-11-17 12:08:44 +01:00
|
|
|
static int8_t chan=0,bad_frame=1;
|
2016-09-19 23:43:14 +02:00
|
|
|
static uint16_t Prev_TCNT1=0;
|
|
|
|
uint16_t Cur_TCNT1;
|
|
|
|
|
|
|
|
Cur_TCNT1 = TCNT1 - Prev_TCNT1 ; // Capture current Timer1 value
|
|
|
|
if(Cur_TCNT1<1000)
|
2016-11-17 12:08:44 +01:00
|
|
|
bad_frame=1; // bad frame
|
2015-12-30 01:41:12 +01:00
|
|
|
else
|
2016-09-19 23:43:14 +02:00
|
|
|
if(Cur_TCNT1>4840)
|
2016-11-17 12:08:44 +01:00
|
|
|
{ //start of frame
|
|
|
|
if(chan>3)
|
|
|
|
PPM_FLAG_on; // good frame received if at least 4 channels have been seen
|
|
|
|
chan=0; // reset channel counter
|
|
|
|
bad_frame=0;
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-19 23:43:14 +02:00
|
|
|
else
|
2016-11-17 12:08:44 +01:00
|
|
|
if(bad_frame==0) // need to wait for start of frame
|
2016-09-19 23:43:14 +02:00
|
|
|
{ //servo values between 500us and 2420us will end up here
|
|
|
|
PPM_data[chan]= Cur_TCNT1>>1;;
|
|
|
|
if(chan++>=NUM_CHN)
|
2016-11-17 12:08:44 +01:00
|
|
|
bad_frame=1; // don't accept any new channels
|
2016-09-19 23:43:14 +02:00
|
|
|
}
|
|
|
|
Prev_TCNT1+=Cur_TCNT1;
|
|
|
|
}
|
2016-08-24 14:52:47 +02:00
|
|
|
#endif //ENABLE_PPM
|
2015-12-30 01:41:12 +01:00
|
|
|
|
2016-01-22 16:23:39 +01:00
|
|
|
//Serial RX
|
2016-08-24 14:52:47 +02:00
|
|
|
#ifdef ENABLE_SERIAL
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-09-19 23:43:14 +02:00
|
|
|
ISR(USARTC0_RXC_vect)
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
|
|
|
void __irq_usart2()
|
2016-08-31 10:26:27 +02:00
|
|
|
#else
|
2016-09-19 23:43:14 +02:00
|
|
|
ISR(USART_RX_vect)
|
2016-08-31 10:26:27 +02:00
|
|
|
#endif
|
2016-09-19 23:43:14 +02:00
|
|
|
{ // RX interrupt
|
|
|
|
static uint8_t idx=0;
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-09-19 23:43:14 +02:00
|
|
|
if((USARTC0.STATUS & 0x1C)==0) // Check frame error, data overrun and parity error
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
|
|
|
if((USART2_BASE->SR & USART_SR_RXNE) && (USART2_BASE->SR &0x0F)==0)
|
2016-09-19 23:43:14 +02:00
|
|
|
#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;
|
|
|
|
if((rx_buff[0]&0xFE)==0x54) // If 1st byte is 0x54 or 0x55 it looks ok
|
|
|
|
{
|
2016-10-27 11:15:25 +02:00
|
|
|
TX_RX_PAUSE_on;
|
|
|
|
tx_pause();
|
2016-10-16 19:51:42 +02:00
|
|
|
#if defined STM32_BOARD
|
|
|
|
uint16_t OCR1B;
|
|
|
|
OCR1B =TCNT1+(6500L);
|
|
|
|
timer.setCompare(TIMER_CH2,OCR1B);
|
|
|
|
timer.attachCompare2Interrupt(ISR_COMPB);
|
|
|
|
#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
|
2016-09-19 23:43:14 +02:00
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2015-12-30 01:41:12 +01:00
|
|
|
{
|
2016-09-19 23:43:14 +02:00
|
|
|
rx_buff[idx++]=UDR0; // Store received byte
|
|
|
|
if(idx>=RXBUFFER_SIZE)
|
|
|
|
{ // A full frame has been received
|
|
|
|
if(!IS_RX_DONOTUPDTAE_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
|
|
|
|
}
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-19 23:43:14 +02:00
|
|
|
idx=UDR0; // Dummy read
|
|
|
|
discard_frame=1; // Error encountered discard full frame...
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-19 23:43:14 +02:00
|
|
|
if(discard_frame==1)
|
|
|
|
{
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef STM32_BOARD
|
|
|
|
detachInterrupt(2); // Disable interrupt on ch2
|
|
|
|
#else
|
|
|
|
CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match
|
|
|
|
#endif
|
2016-10-27 11:15:25 +02:00
|
|
|
TX_RX_PAUSE_off;
|
|
|
|
tx_resume();
|
2016-09-19 23:43:14 +02:00
|
|
|
}
|
2016-10-16 19:51:42 +02:00
|
|
|
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
|
2016-09-19 23:43:14 +02:00
|
|
|
cli() ;
|
|
|
|
UCSR0B |= _BV(RXCIE0) ; // RX interrupt enable
|
|
|
|
#endif
|
2015-12-30 01:41:12 +01:00
|
|
|
}
|
2016-09-19 23:43:14 +02:00
|
|
|
|
|
|
|
//Serial timer
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef ORANGE_TX
|
2016-09-19 23:43:14 +02:00
|
|
|
ISR(TCC1_CCB_vect)
|
2016-10-16 19:51:42 +02:00
|
|
|
#elif defined STM32_BOARD
|
|
|
|
void ISR_COMPB()
|
2016-09-19 23:43:14 +02:00
|
|
|
#else
|
|
|
|
ISR(TIMER1_COMPB_vect, ISR_NOBLOCK )
|
|
|
|
#endif
|
|
|
|
{ // Timer1 compare B interrupt
|
|
|
|
discard_frame=1;
|
2016-10-16 19:51:42 +02:00
|
|
|
#ifdef STM32_BOARD
|
|
|
|
detachInterrupt(2); // Disable interrupt on ch2
|
|
|
|
#else
|
|
|
|
CLR_TIMSK1_OCIE1B; // Disable interrupt on compare B match
|
|
|
|
#endif
|
2016-10-27 11:15:25 +02:00
|
|
|
tx_resume();
|
2016-08-31 10:26:27 +02:00
|
|
|
}
|
2016-09-12 16:41:40 +02:00
|
|
|
#endif //ENABLE_SERIAL
|
|
|
|
|
2016-10-16 19:51:42 +02:00
|
|
|
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
|
2016-09-19 23:43:14 +02:00
|
|
|
// Random interrupt service routine called every time the WDT interrupt is triggered.
|
|
|
|
// It is only enabled at startup to generate a seed.
|
|
|
|
ISR(WDT_vect)
|
2016-09-12 16:41:40 +02:00
|
|
|
{
|
2016-09-19 23:43:14 +02:00
|
|
|
static uint8_t gWDT_buffer_position=0;
|
|
|
|
#define gWDT_buffer_SIZE 32
|
|
|
|
static uint8_t gWDT_buffer[gWDT_buffer_SIZE];
|
|
|
|
gWDT_buffer[gWDT_buffer_position] = TCNT1L; // Record the Timer 1 low byte (only one needed)
|
|
|
|
gWDT_buffer_position++; // every time the WDT interrupt is triggered
|
|
|
|
if (gWDT_buffer_position >= gWDT_buffer_SIZE)
|
2016-09-12 16:41:40 +02:00
|
|
|
{
|
2016-09-19 23:43:14 +02:00
|
|
|
// The following code is an implementation of Jenkin's one at a time hash
|
|
|
|
for(uint8_t gWDT_loop_counter = 0; gWDT_loop_counter < gWDT_buffer_SIZE; ++gWDT_loop_counter)
|
|
|
|
{
|
|
|
|
gWDT_entropy += gWDT_buffer[gWDT_loop_counter];
|
|
|
|
gWDT_entropy += (gWDT_entropy << 10);
|
|
|
|
gWDT_entropy ^= (gWDT_entropy >> 6);
|
|
|
|
}
|
|
|
|
gWDT_entropy += (gWDT_entropy << 3);
|
|
|
|
gWDT_entropy ^= (gWDT_entropy >> 11);
|
|
|
|
gWDT_entropy += (gWDT_entropy << 15);
|
|
|
|
WDTCSR = 0; // Disable Watchdog interrupt
|
2016-09-12 16:41:40 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-12 21:44:30 +02:00
|
|
|
#endif
|