Browse Source

- first try to port frsky from multi protocol

master
philipp schoenberger 7 years ago
parent
commit
36b5481c47
  1. 11
      remote/src/cc2500.cpp
  2. 9
      remote/src/cc2500.h
  3. 69
      remote/src/config.h
  4. 306
      remote/src/frskyd.cpp
  5. 81
      remote/src/frskyd.h
  6. 3
      remote/src/io_data.cpp
  7. 3
      remote/src/io_data.h
  8. 32
      remote/src/main.cpp
  9. 14
      remote/src/pins.h
  10. 11
      remote/src/spi.cpp
  11. 3
      remote/src/spi.h

11
remote/src/cc2500.cpp

@ -7,6 +7,12 @@ CC2500::CC2500(SPI* spi)
{ {
this->spi = spi; this->spi = spi;
this->bind_done = false; this->bind_done = false;
CC2500_CS_OUTPUT;
CC2500_CS_ON;
LOW_NOISE_AMP_OUTPUT;
LOW_NOISE_AMP_OFF;
} }
void CC2500::write_register(uint8_t address, uint8_t data) void CC2500::write_register(uint8_t address, uint8_t data)
@ -93,10 +99,12 @@ void CC2500::set_wireless_mode(enum wireless_mode mode )
this->write_register(CC2500_00_IOCFG2, 0x2F); this->write_register(CC2500_00_IOCFG2, 0x2F);
this->write_register(CC2500_02_IOCFG0, 0x2F | 0x40); this->write_register(CC2500_02_IOCFG0, 0x2F | 0x40);
break; break;
case wireless_rx: case wireless_rx:
this->write_register(CC2500_02_IOCFG0, 0x2F); this->write_register(CC2500_02_IOCFG0, 0x2F);
this->write_register(CC2500_00_IOCFG2, 0x2F | 0x40); this->write_register(CC2500_00_IOCFG2, 0x2F | 0x40);
break; break;
case wireless_off: case wireless_off:
this->write_register(CC2500_02_IOCFG0, 0x2F); this->write_register(CC2500_02_IOCFG0, 0x2F);
this->write_register(CC2500_00_IOCFG2, 0x2F); this->write_register(CC2500_00_IOCFG2, 0x2F);
@ -148,6 +156,8 @@ void CC2500::resetChip(void)
this->strobe(CC2500_SRES); this->strobe(CC2500_SRES);
_delay_ms(100); _delay_ms(100);
this->prev_power = 0xfd;
} }
void CC2500::set_power_value(uint8_t power) void CC2500::set_power_value(uint8_t power)
@ -162,6 +172,7 @@ void CC2500::set_power_value(uint8_t power)
0xFE, // 0dbm 0xFE, // 0dbm
0xFF // 1.5dbm 0xFF // 1.5dbm
}; };
if (power > 7) if (power > 7)
power = 7; power = 7;

9
remote/src/cc2500.h

@ -14,12 +14,14 @@
*/ */
#ifndef CC2500_H #ifndef CC2500_H
#define CC2500_H
#include "Arduino.h" #include "Arduino.h"
#include "spi.h" #include "spi.h"
#include "iface_cc2500.h" #include "iface_cc2500.h"
class CC2500 {
class CC2500
{
private: private:
SPI *spi; SPI *spi;
bool bind_done; bool bind_done;
@ -34,8 +36,7 @@ class CC2500 {
}; };
// CC2500 power output from the chip itself // CC2500 power output from the chip itself
// The numbers do not take into account any outside amplifier // The numbers do not take into account any outside amplifier
enum CC2500_POWER
{
enum CC2500_POWER {
CC2500_POWER_0 = 0x00, // -55dbm or less CC2500_POWER_0 = 0x00, // -55dbm or less
CC2500_POWER_1 = 0x50, // -30dbm CC2500_POWER_1 = 0x50, // -30dbm
CC2500_POWER_2 = 0x44, // -28dbm CC2500_POWER_2 = 0x44, // -28dbm
@ -81,4 +82,4 @@ class CC2500 {
void resetChip(void); void resetChip(void);
}; };
#endif
#endif /* CC2500_H */

69
remote/src/config.h

@ -1,4 +1,73 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
const uint8_t FRSKYD_cc2500_conf[] = {
/*02_IOCFG0*/ 0x06,
/*00_IOCFG2*/ 0x06,
/*17_MCSM1*/ 0x0c,
/*18_MCSM0*/ 0x18,
/*06_PKTLEN*/ 0x19,
/*07_PKTCTRL1*/ 0x04,
/*08_PKTCTRL0*/ 0x05,
/*3E_PATABLE*/ 0xff,
/*0B_FSCTRL1*/ 0x08,
/*0C_FSCTRL0*/ 0x00,
/*0D_FREQ2*/ 0x5c,
/*0E_FREQ1*/ 0x76,
/*0F_FREQ0*/ 0x27,
/*10_MDMCFG4*/ 0xAA,
/*11_MDMCFG3*/ 0x39,
/*12_MDMCFG2*/ 0x11,
/*13_MDMCFG1*/ 0x23,
/*14_MDMCFG0*/ 0x7a,
/*15_DEVIATN*/ 0x42
};
const uint8_t FRSKY_common_end_cc2500_conf[][2] = {
{ CC2500_19_FOCCFG, 0x16 },
{ CC2500_1A_BSCFG, 0x6c },
{ CC2500_1B_AGCCTRL2, 0x43 },
{ CC2500_1C_AGCCTRL1, 0x40 },
{ CC2500_1D_AGCCTRL0, 0x91 },
{ CC2500_21_FREND1, 0x56 },
{ CC2500_22_FREND0, 0x10 },
{ CC2500_23_FSCAL3, 0xa9 },
{ CC2500_24_FSCAL2, 0x0A },
{ CC2500_25_FSCAL1, 0x00 },
{ CC2500_26_FSCAL0, 0x11 },
{ CC2500_29_FSTEST, 0x59 },
{ CC2500_2C_TEST2, 0x88 },
{ CC2500_2D_TEST1, 0x31 },
{ CC2500_2E_TEST0, 0x0B },
{ CC2500_03_FIFOTHR, 0x07 },
{ CC2500_09_ADDR, 0x00 }
};
const uint8_t FRSKY_common_startreg_cc2500_conf[] = {
CC2500_02_IOCFG0,
CC2500_00_IOCFG2,
CC2500_17_MCSM1,
CC2500_18_MCSM0,
CC2500_06_PKTLEN,
CC2500_07_PKTCTRL1,
CC2500_08_PKTCTRL0,
CC2500_3E_PATABLE,
CC2500_0B_FSCTRL1,
CC2500_0C_FSCTRL0, // replaced by option value
CC2500_0D_FREQ2,
CC2500_0E_FREQ1,
CC2500_0F_FREQ0,
CC2500_10_MDMCFG4,
CC2500_11_MDMCFG3,
CC2500_12_MDMCFG2,
CC2500_13_MDMCFG1,
CC2500_14_MDMCFG0,
CC2500_15_DEVIATN
};
//AETR
#define AILERON 0
#define ELEVATOR 1
#define THROTTLE 2
#define RUDDER 3
#endif #endif

306
remote/src/frskyd.cpp

@ -0,0 +1,306 @@
/*
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 "iface_cc2500.h"
#include "frskyd.h"
#include "config.h"
#include "Arduino.h"
Frsky_d::Frsky_d(CC2500 *cc2500)
{
this->calibration = 0x89;
this->state = FRSKY_BIND;
this->cc2500 = cc2500;
this->packet_count = 0;
// TODO real random randomSeed(analogRead(0));
randomSeed(42);
this->MProtocol_id_master = random(10);
this->MProtocol_id = this->MProtocol_id_master;
this->init_channel();
this->init_failsafe();
Serial.print(" multiprotocl id : ");
Serial.print(this->MProtocol_id);
Serial.print("\n");
}
void Frsky_d::init(bool bind)
{
this->init_cc2500(FRSKYD_cc2500_conf);
cc2500->write_register(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
cc2500->write_register(CC2500_07_PKTCTRL1, 0x05);
cc2500->strobe(CC2500_SIDLE); // Go to idle...
//
cc2500->write_register(CC2500_0A_CHANNR, 0x00);
cc2500->write_register(CC2500_23_FSCAL3, 0x89);
cc2500->strobe(CC2500_SFRX);
//#######END INIT########
}
void Frsky_d::init_cc2500(const uint8_t *ptr)
{
for (uint8_t i = 0; i < 19; i++) {
uint8_t reg = FRSKY_common_startreg_cc2500_conf[i];
uint8_t val = ptr[i];
if (reg == CC2500_0C_FSCTRL0)
val = option;
cc2500->write_register(reg, val);
}
prev_option = option ; // Save option to monitor FSCTRL0 change
for (uint8_t i = 0; i < 17; i++) {
uint8_t reg = FRSKY_common_end_cc2500_conf[i][0];
uint8_t val = FRSKY_common_end_cc2500_conf[i][1];
cc2500->write_register(reg, val);
}
cc2500->set_wireless_mode(CC2500::wireless_tx);
cc2500->set_power();
cc2500->strobe(CC2500_SIDLE); // Go to idle...
}
void Frsky_d::build_bind_packet(void)
{
//11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
//11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
packet[0] = 0x11;
packet[1] = 0x03;
packet[2] = 0x01;
packet[3] = rx_tx_addr[3];
packet[4] = rx_tx_addr[2];
uint16_t 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] = 0x00;
packet[12] = 0x00;
packet[13] = 0x00;
packet[14] = 0x00;
packet[15] = 0x00;
packet[16] = 0x00;
packet[17] = 0x01;
}
void Frsky_d::frsky2way_data_frame()
{
//pachet[4] is telemetry user frame counter(hub)
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
//11 57 12 00 00 01 f2 f2 f2 f2 06 06 ca ca ca ca 18 18
packet[0] = 0x11; //Length
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = counter;//
#if defined TELEMETRY
packet[4] = telemetry_counter;
#else
packet[4] = 0x00;
#endif
packet[5] = 0x01;
//
packet[10] = 0;
packet[11] = 0;
packet[16] = 0;
packet[17] = 0;
for (uint8_t i = 0; i < 8; i++) {
uint16_t value;
value = convert_channel_frsky(i);
if (i < 4) {
packet[6 + i] = value & 0xff;
packet[10 + (i >> 1)] |= ((value >> 8) & 0x0f) << (4 * (i & 0x01));
} else {
packet[8 + i] = value & 0xff;
packet[16 + ((i - 4) >> 1)] |= ((value >> 8) & 0x0f) << (4 * ((i - 4) & 0x01));
}
}
}
uint16_t Frsky_d::init_frsky_2way(void)
{
Serial.print("init hop");
init_hop();
packet_count = 0;
#if defined TELEMETRY
init_frskyd_link_telemetry();
#endif
if (IS_BIND_IN_PROGRESS) {
init(true);
state = FRSKY_BIND;
} else {
state = FRSKY_BIND_DONE;
}
return 10000;
}
uint16_t Frsky_d::read_frsky_2way(void)
{
if (state < FRSKY_BIND_DONE) {
Serial.print("bind mode\n");
build_bind_packet();
cc2500->strobe(CC2500_SIDLE);
cc2500->write_register(CC2500_0A_CHANNR, 0x00);
cc2500->write_register(CC2500_23_FSCAL3, 0x89);
cc2500->strobe(CC2500_SFRX);//0x3A
cc2500->write_data(packet, packet[0] + 1);
if (IS_BIND_DONE) {
Serial.print("bind finished \n");
state = FRSKY_BIND_DONE;
} else {
//state += 1;
Serial.print("bind not done\n");
Serial.print("state :");
Serial.print(state);
Serial.print("\n");
}
return 9000;
}
if (state == FRSKY_BIND_DONE) {
Serial.print("bind done \n");
state = FRSKY_DATA2;
init(false);
counter = 0;
BIND_DONE;
} else if (state == FRSKY_DATA5) {
Serial.print("data 5 \n");
cc2500->strobe(CC2500_SRX);//0x34 RX enable
state = FRSKY_DATA1;
return 9200;
}
counter = (counter + 1) % 188;
if (state == FRSKY_DATA4) {
Serial.print("data 4 \n");
//telemetry receive
cc2500->set_wireless_mode(CC2500::wireless_rx);
cc2500->strobe(CC2500_SIDLE);
cc2500->write_register(CC2500_0A_CHANNR, hopping_frequency[counter % 47]);
cc2500->write_register(CC2500_23_FSCAL3, 0x89);
state++;
return 1300;
} else {
if (state == FRSKY_DATA1) {
Serial.print("data 1 \n");
len = cc2500->read_register(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && len <= (0x11 + 3)) { // 20bytes
cc2500->read_data(pkt, len); //received telemetry packets
#if defined(TELEMETRY)
if (pkt[len - 1] & 0x80) {
//with valid crc
packet_count = 0;
frsky_check_telemetry(pkt, len); //check if valid telemetry packets and buffer them.
}
#endif
} else {
packet_count++;
// restart sequence on missed packet - might need count or timeout instead of one missed
if (packet_count > 100) {
//~1sec
packet_count = 0;
#if defined TELEMETRY
telemetry_link = 0; //no link frames
pkt[6] = 0; //no user frames.
#endif
}
}
cc2500->set_wireless_mode(CC2500::wireless_tx);
cc2500->set_power(); // Set tx_power
}
cc2500->strobe(CC2500_SIDLE);
cc2500->write_register(CC2500_0A_CHANNR, hopping_frequency[counter % 47]);
if (prev_option != option) {
cc2500->write_register(CC2500_0C_FSCTRL0, option); // Frequency offset hack
prev_option = option ;
}
cc2500->write_register(CC2500_23_FSCAL3, 0x89);
cc2500->strobe(CC2500_SFRX);
frsky2way_data_frame();
cc2500->write_data(packet, packet[0] + 1);
state++;
}
return state == FRSKY_DATA4 ? 7500 : 9000;
}
uint16_t Frsky_d::convert_channel_frsky(uint8_t num)
{
// Channel value for FrSky (PPM is multiplied by 1.5)
uint16_t val = Channel_data[num];
return ((val*15)>>4)+1290;
}
void Frsky_d::init_hop(void)
{
uint8_t val;
uint8_t channel = rx_tx_addr[0]&0x07;
uint8_t channel_spacing = rx_tx_addr[1];
//Filter bad tables
if(channel_spacing<0x02)
channel_spacing+=0x02;
if(channel_spacing>0xE9)
channel_spacing-=0xE7;
if(channel_spacing%0x2F==0)
channel_spacing++;
hopping_frequency[0]=channel;
for(uint8_t i=1;i<50;i++) {
channel=(channel+channel_spacing) % 0xEB;
val=channel;
if((val==0x00) || (val==0x5A) || (val==0xDC))
val++;
hopping_frequency[i]=i>46?0:val;
}
}
void Frsky_d::init_channel(void)
{
for(uint8_t i=0;i<NUM_CHN;i++)
Channel_data[i]=1024;
Channel_data[THROTTLE]=204;
}
void Frsky_d::init_failsafe()
{
for(uint8_t i=0;i<NUM_CHN;i++)
failsafe_data[i]=1024;
failsafe_data[THROTTLE]=204;
fail_save = true;
}

81
remote/src/frskyd.h

@ -0,0 +1,81 @@
#include <Arduino.h>
#ifndef FRSKYD_H
#define FRSKYD_H
#include <cc2500.h>
#define BIND_IN_PROGRESS protocol_flags &= ~_BV(7)
#define BIND_DONE protocol_flags |= _BV(7)
#define IS_BIND_DONE ( ( protocol_flags & _BV(7) ) !=0 )
#define IS_BIND_IN_PROGRESS ( ( protocol_flags & _BV(7) ) ==0 )
class Frsky_d
{
private:
uint8_t hopping_frequency[50];
uint8_t calibration;
enum frsky_d_state {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5
};
int state;
CC2500 * cc2500;
uint16_t packet_count;
uint8_t packet[40];
uint8_t len;
uint8_t rx_tx_addr[5];
uint8_t option;
uint8_t prev_option;
uint16_t counter;
uint8_t pkt[29];
#define NUM_CHN 16
// Servo data
uint8_t Channel_AUX;
uint16_t Channel_data[NUM_CHN];
uint16_t failsafe_data[NUM_CHN];
uint8_t protocol_flags=0,protocol_flags2=0;
volatile uint32_t gWDT_entropy = 0;
uint32_t MProtocol_id_master;
uint32_t MProtocol_id;
bool fail_save = false;
public:
Frsky_d(CC2500 *cc2500);
void init(bool bind);
void build_bind_packet(void);
uint16_t init_frsky_2way(void);
uint16_t read_frsky_2way(void);
void frsky2way_init(bool bind);
void frsky_init_hop(void);
void init_cc2500(const uint8_t *ptr);
void frsky2way_data_frame();
uint16_t convert_channel_frsky(uint8_t num);
void init_hop(void);
void init_channel(void);
void init_failsafe(void);
};
#endif /*FRSKYD_H*/

3
remote/src/io_data.cpp

@ -34,6 +34,7 @@ uint16_t IO_DATA::adc_read(uint8_t ch)
/* Clear Mux5 */ /* Clear Mux5 */
ADCSRB &= ~_BV(MUX5); ADCSRB &= ~_BV(MUX5);
} }
ch = ch & 0b00000111; ch = ch & 0b00000111;
Serial.print("ch"); Serial.print("ch");
Serial.print(ch); Serial.print(ch);
@ -44,7 +45,9 @@ uint16_t IO_DATA::adc_read(uint8_t ch)
// wait for conversion to complete // wait for conversion to complete
delay(50); delay(50);
while (ADCSRA & (1 << ADSC)); // wait for conversion to complete while (ADCSRA & (1 << ADSC)); // wait for conversion to complete
/* while(!(ADCSRA & (1<<ADIF))) { */ /* while(!(ADCSRA & (1<<ADIF))) { */
/* /1* nothing *1/ */ /* /1* nothing *1/ */
/* } */ /* } */

3
remote/src/io_data.h

@ -2,7 +2,8 @@
#define INPUT_HPP #define INPUT_HPP
#include "Arduino.h" #include "Arduino.h"
class IO_DATA {
class IO_DATA
{
private: private:
void adc_init(void); void adc_init(void);
uint16_t adc_read(uint8_t ch); uint16_t adc_read(uint8_t ch);

32
remote/src/main.cpp

@ -17,16 +17,20 @@
#include "spi.h" #include "spi.h"
#include "cc2500.h" #include "cc2500.h"
#include "frskyd.h"
#include "io_data.h" #include "io_data.h"
SPI *spi = NULL; SPI *spi = NULL;
IO_DATA *io_data = NULL; IO_DATA *io_data = NULL;
CC2500 *cc2500 = NULL; CC2500 *cc2500 = NULL;
Frsky_d *frskyd = NULL;
void setup() {
void setup()
{
while (!Serial) { while (!Serial) {
delay(500); delay(500);
} }
Serial.begin(115200); Serial.begin(115200);
spi = new SPI(); spi = new SPI();
@ -34,14 +38,26 @@ void setup() {
cc2500 = new CC2500(spi); cc2500 = new CC2500(spi);
frskyd = new Frsky_d(cc2500);
io_data = new IO_DATA(); io_data = new IO_DATA();
io_data->init(); io_data->init();
Serial.println("Remote ON!"); Serial.println("Remote ON!");
delay (500);
cc2500->reset();
Serial.print(" init\n");
frskyd->init(false);
delay (500);
Serial.print(" init 2way\n");
frskyd->init_frsky_2way();
} }
void loop() {
void loop()
{
Serial.println("loop!"); Serial.println("loop!");
io_data->update(); io_data->update();
@ -68,5 +84,15 @@ void loop() {
Serial.print(io_data->l_sw); Serial.print(io_data->l_sw);
Serial.print("\n"); Serial.print("\n");
delay(500);
//TODO needed ? PE1_off;
//TODO needed ? PE2_on;
Serial.print(" read 2 way\n");
int rt = frskyd->read_frsky_2way();
Serial.print(" read :");
Serial.print(rt);
Serial.print("\n");
delayMicroseconds(rt);
} }

14
remote/src/pins.h

@ -248,3 +248,17 @@
#define SPI_MOSI_IS_LOW ((SPI_MOSI_IPR & _BV(SPI_MOSI_PIN) == 0x00) #define SPI_MOSI_IS_LOW ((SPI_MOSI_IPR & _BV(SPI_MOSI_PIN) == 0x00)
#define NOP __asm__("nop"); #define NOP __asm__("nop");
#define PE1_pin 1 //A1 = PC1
#define PE1_port PORTC
#define PE1_ddr DDRC
#define PE1_output PE1_ddr |= _BV(PE1_pin)
#define PE1_on PE1_port |= _BV(PE1_pin)
#define PE1_off PE1_port &= ~_BV(PE1_pin)
#define PE2_pin 2 //A2 = PC2
#define PE2_port PORTC
#define PE2_ddr DDRC
#define PE2_output PE2_ddr |= _BV(PE2_pin)
#define PE2_on PE2_port |= _BV(PE2_pin)
#define PE2_off PE2_port &= ~_BV(PE2_pin)

11
remote/src/spi.cpp

@ -17,6 +17,8 @@
/********************/ /********************/
#include "spi.h" #include "spi.h"
#include "pins.h" #include "pins.h"
#include "Arduino.h"
SPI::SPI() SPI::SPI()
{ {
} }
@ -25,6 +27,12 @@ void SPI::init(void)
SPI_SCLK_OUTPUT; SPI_SCLK_OUTPUT;
SPI_MOSI_OUTPUT; SPI_MOSI_OUTPUT;
SPI_MISO_INPUT; SPI_MISO_INPUT;
SPI_MOSI_ON;
SPI_SCLK_OFF;
// wait for the components
delay(100);
} }
void SPI::write(const uint8_t command) void SPI::write(const uint8_t command)
@ -50,6 +58,7 @@ void SPI::write(const uint8_t command)
// reset clock // reset clock
SPI_SCLK_OFF; SPI_SCLK_OFF;
} }
SPI_MOSI_ON; SPI_MOSI_ON;
} }
@ -60,6 +69,7 @@ uint8_t SPI::read(void)
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
result = result << 1; result = result << 1;
if (SPI_MISO_IS_HIGH) { if (SPI_MISO_IS_HIGH) {
result |= 0x01; result |= 0x01;
} }
@ -71,5 +81,6 @@ uint8_t SPI::read(void)
// reset clock // reset clock
SPI_SCLK_OFF; SPI_SCLK_OFF;
} }
return result; return result;
} }

3
remote/src/spi.h

@ -15,7 +15,8 @@
#ifndef SPI_H #ifndef SPI_H
#define SPI_H #define SPI_H
#include <Arduino.h> #include <Arduino.h>
class SPI {
class SPI
{
private: private:
public: public:

Loading…
Cancel
Save