diff --git a/radio/src/Makefile b/radio/src/Makefile index 3e9caf631..dfd87b3d3 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -934,7 +934,7 @@ ifeq ($(PCB), TARANIS) PPM_LIMITS_SYMETRICAL = YES PPM_CENTER_ADJUSTABLE = YES DSM2 = PPM - CPPDEFS += -DPCBTARANIS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM -DEEPROM_RLC -DAUDIO -DPXX + CPPDEFS += -DPCBTARANIS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM -DEEPROM_RLC -DAUDIO -DPXX -DSBUS -DCROSSFIRE INCDIRS += targets/taranis $(THIRDPARTY) $(COOSDIR) $(COOSDIR)/kernel $(COOSDIR)/portable CPPDEFS += -DHSE_VALUE=12000000 ifeq ($(PCBREV), REV9E) @@ -960,7 +960,7 @@ ifeq ($(PCB), TARANIS) SRC += $(COOSDIR)/kernel/core.c $(COOSDIR)/kernel/hook.c $(COOSDIR)/kernel/task.c $(COOSDIR)/kernel/event.c $(COOSDIR)/kernel/time.c $(COOSDIR)/kernel/timer.c $(COOSDIR)/kernel/flag.c $(COOSDIR)/kernel/mutex.c $(COOSDIR)/kernel/serviceReq.c $(COOSDIR)/portable/GCC/port.c $(COOSDIR)/portable/arch.c SRC += targets/taranis/pwr_driver.c targets/taranis/usb_driver.c EEPROMSRC = storage/storage_common.cpp storage/eeprom_common.cpp storage/eeprom_rlc.cpp storage/eeprom_conversions.cpp - PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp + PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp pulses/crossfire.cpp CPPSRC += tasks_arm.cpp audio_arm.cpp sbus.cpp telemetry/telemetry.cpp CPPSRC += targets/taranis/pulses_driver.cpp targets/taranis/keys_driver.cpp targets/taranis/adc_driver.cpp targets/taranis/trainer_driver.cpp targets/taranis/audio_driver.cpp targets/taranis/serial2_driver.cpp targets/taranis/telemetry_driver.cpp CPPSRC += bmp.cpp gui/$(GUIDIRECTORY)/view_channels.cpp gui/$(GUIDIRECTORY)/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp debug.cpp @@ -1554,6 +1554,7 @@ ifeq ($(EXT), $(filter $(EXT), FRSKY FRSKY_SPORT TELEMETREZ)) ifeq ($(EXT), FRSKY_SPORT) CPPSRC += telemetry/frsky_sport.cpp + CPPSRC += crc16.cpp CPPDEFS += -DFRSKY_SPORT endif diff --git a/radio/src/crc16.cpp b/radio/src/crc16.cpp new file mode 100644 index 000000000..301b45760 --- /dev/null +++ b/radio/src/crc16.cpp @@ -0,0 +1,80 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program 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. + * + */ + +/* CRC16 implementation according to CCITT standards */ +static const unsigned short crc16tab[256]= { + 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, + 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, + 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, + 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, + 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, + 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, + 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, + 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, + 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, + 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, + 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, + 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, + 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, + 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, + 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, + 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, + 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, + 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, + 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, + 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, + 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, + 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, + 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, + 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, + 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, + 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, + 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, + 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, + 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, + 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, + 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, + 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 +}; + +uint16_t crc16(uint8_t * buf, uint32_t len) +{ + uint16_t crc = 0; + for (uint32_t counter=0; counter>8) ^ *buf++ ) & 0x00FF]; + } + return crc; +} diff --git a/radio/src/gui/taranis/menu_model_setup.cpp b/radio/src/gui/taranis/menu_model_setup.cpp index 8805545e5..dcd60a7a8 100644 --- a/radio/src/gui/taranis/menu_model_setup.cpp +++ b/radio/src/gui/taranis/menu_model_setup.cpp @@ -205,7 +205,7 @@ int getSwitchWarningsCount() #define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) #define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW) #define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1) -#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1) +#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON((IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_CROSSFIRE(EXTERNAL_MODULE)) ? (uint8_t)0 : (uint8_t)1) #define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) #define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : TRAINER_CHANNELS_ROWS())) #define FAILSAFE_ROWS(x) (HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 1071549f1..9507d3801 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -2183,6 +2183,9 @@ enum Protocols { PROTO_DSM2_DSM2, PROTO_DSM2_DSMX, #endif +#if defined(CROSSFIRE) + PROTO_CROSSFIRE, +#endif #if defined(IRPROTOS) // we will need 4 bytes for proto :( PROTO_SILV, @@ -2216,6 +2219,9 @@ enum ModuleTypes { MODULE_TYPE_XJT, #if defined(DSM2) MODULE_TYPE_DSM2, +#endif +#if defined(CROSSFIRE) + MODULE_TYPE_CROSSFIRE, #endif MODULE_TYPE_COUNT }; @@ -2286,7 +2292,8 @@ enum TelemetryType PROTOCOL_TELEMETRY_FIRST, PROTOCOL_FRSKY_SPORT = PROTOCOL_TELEMETRY_FIRST, PROTOCOL_FRSKY_D, - PROTOCOL_FRSKY_D_SECONDARY + PROTOCOL_FRSKY_D_SECONDARY, + PROTOCOL_PULSES_CROSSFIRE }; enum DisplayTrims diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 6b4f18d69..4b2199ffb 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2547,7 +2547,7 @@ int main(void) sei(); // interrupts needed now -#if defined(FRSKY) && !defined(DSM2_SERIAL) +#if !defined(CPUARM) && defined(FRSKY) && !defined(DSM2_SERIAL) telemetryInit(); #endif diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 99f74fe42..0dede6f62 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -464,7 +464,7 @@ #endif #if defined(CPUARM) - static const int8_t maxChannelsModules[] = { 0, 8, 8, -2 }; // relative to 8! + static const int8_t maxChannelsModules[] = { 0, 8, 8, -2, 8 }; // relative to 8! static const int8_t maxChannelsXJT[] = { 0, 8, 0, 4 }; // relative to 8! #define NUM_CHANNELS(idx) (8+g_model.moduleData[idx].channelsCount) #define MAX_TRAINER_CHANNELS() (8) @@ -483,6 +483,11 @@ #else #define IS_MODULE_DSM2(idx) (false) #endif + #if defined(CROSSFIRE) + #define IS_MODULE_CROSSFIRE(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_CROSSFIRE) + #else + #define IS_MODULE_CROSSFIRE(idx) (false) + #endif #if defined(TARANIS_INTERNAL_PPM) #define MAX_INTERNAL_MODULE_CHANNELS() ((g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[0].rfProtocol] : maxChannelsModules[g_model.moduleData[INTERNAL_MODULE].type]) #else @@ -964,8 +969,8 @@ void checkAll(); void getADC(); #endif -#if defined(PCBTARANIS) -void processSbusInput(); +#if defined(SBUS) +#include "sbus.h" #endif extern void backlightOn(); @@ -1385,6 +1390,10 @@ void evalFunctions(); #include "telemetry/mavlink.h" #endif +#if defined(CPUARM) +uint16_t crc16(uint8_t * buf, uint32_t len); +#endif + #define PLAY_REPEAT(x) (x) /* Range 0 to 15 */ #define PLAY_NOW 0x10 #define PLAY_BACKGROUND 0x20 diff --git a/radio/src/pulses/crossfire.cpp b/radio/src/pulses/crossfire.cpp new file mode 100644 index 000000000..d3b65b543 --- /dev/null +++ b/radio/src/pulses/crossfire.cpp @@ -0,0 +1,62 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program 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. + * + */ + +#include "../opentx.h" + +#define CROSSFIRE_START_BYTE 0x0F +#define CROSSFIRE_CH_CENTER 0x3E0 +#define CROSSFIRE_CH_BITS 11 + +// Range for pulses (channels output) is [-1024:+1024] +void createCrossfireFrame(uint8_t * frame, int16_t * pulses) +{ + uint8_t * buf = frame; + *buf++ = CROSSFIRE_START_BYTE; + + uint32_t bits = 0; + uint8_t bitsavailable = 0; + for (int i=0; i= 8) { + *buf++ = bits; + bits >>= 8; + bitsavailable -= 8; + } + } + *buf++ = 0; + *buf++ = crc16(frame, 24); +} diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index 6870ee7d7..ae2d109df 100644 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -98,6 +98,11 @@ void setupPulses(unsigned int port) } } break; +#endif +#if defined(PCBTARANIS) && defined(CROSSFIRE) + case MODULE_TYPE_CROSSFIRE: + required_protocol = PROTO_CROSSFIRE; + break; #endif default: required_protocol = PROTO_NONE; @@ -129,6 +134,11 @@ void setupPulses(unsigned int port) case PROTO_DSM2_DSMX: disable_dsm2(port); break; +#endif +#if defined(CROSSFIRE) + case PROTO_CROSSFIRE: + disable_crossfire(port); + break; #endif case PROTO_PPM: disable_ppm(port); @@ -150,10 +160,16 @@ void setupPulses(unsigned int port) case PROTO_DSM2_DSMX: init_dsm2(port); break; +#endif +#if defined(CROSSFIRE) + case PROTO_CROSSFIRE: + init_crossfire(port); + break; #endif case PROTO_PPM: init_ppm(port); break; + default: init_no_pulses(port); break; @@ -171,6 +187,17 @@ void setupPulses(unsigned int port) case PROTO_DSM2_DSMX: setupPulsesDSM2(port); break; +#endif +#if defined(CROSSFIRE) + case PROTO_CROSSFIRE: + { + if (telemetryProtocol == PROTOCOL_PULSES_CROSSFIRE) { + uint8_t * crossfire = modulePulsesData[port].crossfire.pulses; + createCrossfireFrame(crossfire, &channelOutputs[g_model.moduleData[port].channelsStart]); + sportSendBuffer(crossfire, CROSSFIRE_FRAME_LEN); + } + break; + } #endif case PROTO_PPM: setupPulsesPPM(port); diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index 1484c0f0d..58cbda991 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -84,10 +84,17 @@ PACK(struct Dsm2PulsesData { }); #endif +#define CROSSFIRE_BAUDRATE 200000 +#define CROSSFIRE_FRAME_LEN 25 +PACK(struct CrossfirePulsesData { + uint8_t pulses[CROSSFIRE_FRAME_LEN]; +}); + union ModulePulsesData { PxxPulsesData pxx; Dsm2PulsesData dsm2; PpmPulsesData ppm; + CrossfirePulsesData crossfire; }; union TrainerPulsesData { @@ -102,6 +109,8 @@ void setupPulsesDSM2(unsigned int port); void setupPulsesPXX(unsigned int port); void setupPulsesPPM(unsigned int port); +void createCrossfireFrame(uint8_t * frame, int16_t * pulses); + #if defined(HUBSAN) void Hubsan_Init(); #endif diff --git a/radio/src/sbus.cpp b/radio/src/sbus.cpp index ca2fdafa6..1111dd7f9 100644 --- a/radio/src/sbus.cpp +++ b/radio/src/sbus.cpp @@ -35,28 +35,27 @@ */ #include "opentx.h" +#include "sbus.h" -#define SBUS_MIN_FRAME_SIZE 23 -#define SBUS_MAX_FRAME_SIZE 28 +#define SBUS_FRAME_GAP_DELAY 1000 // 500uS -#define SBUS_FRAME_GAP_DELAY 1000 // 500uS - -#define SBUS_START_BYTE 0x0F -#define SBUS_FLAGS_IDX 23 +#define SBUS_START_BYTE 0x0F +#define SBUS_FLAGS_IDX 23 #define SBUS_FRAMELOST_BIT 2 #define SBUS_FAILSAFE_BIT 3 #define SBUS_CH_BITS 11 -#define SBUS_CH_MASK ((1< sbusFifo; uint8_t SbusFrame[SBUS_MAX_FRAME_SIZE]; uint16_t SbusTimer ; uint8_t SbusIndex = 0 ; -void processSbusFrame(uint8_t *sbus, int16_t *pulses, uint32_t size) +// Range for pulses (ppm input) is [-512:+512] +void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size) { uint32_t inputbitsavailable = 0; uint32_t inputbits = 0; diff --git a/radio/src/sbus.h b/radio/src/sbus.h new file mode 100644 index 000000000..f7c3575a7 --- /dev/null +++ b/radio/src/sbus.h @@ -0,0 +1,47 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program 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. + * + */ + +#ifndef _SBUS_H_ +#define _SBUS_H_ + +#define SBUS_BAUDRATE 100000 +#define SBUS_MIN_FRAME_SIZE 23 +#define SBUS_MAX_FRAME_SIZE 28 + +void processSbusInput(); +void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size); + +#endif // _SBUS_H_ diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index e4653e59f..6f9e8bef4 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -1277,6 +1277,10 @@ void lcdRefresh() simuLcdRefresh = true; } +void telemetryPortInit() +{ +} + #if !defined(PCBFLAMENCO) display_t simuLcdBackupBuf[DISPLAY_BUFFER_SIZE]; void lcdStoreBackupBuffer() diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 4063701bf..2cea55c5f 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -210,6 +210,8 @@ void init_pxx( uint32_t module_index ); void disable_pxx( uint32_t module_index ); void init_dsm2( uint32_t module_index ); void disable_dsm2( uint32_t module_index ); +void init_crossfire( uint32_t module_index ); +void disable_crossfire( uint32_t module_index ); // Trainer driver void init_trainer_ppm(void); @@ -305,6 +307,7 @@ void debugPutc(const char c); // Telemetry driver void telemetryPortInit(uint32_t baudrate); +void telemetryPortSetDirectionOutput(void); void sportSendBuffer(uint8_t *buffer, uint32_t count); // Audio driver diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index 98226adf0..c67d95cff 100644 --- a/radio/src/targets/taranis/pulses_driver.cpp +++ b/radio/src/targets/taranis/pulses_driver.cpp @@ -58,6 +58,8 @@ static void intmoduleNoneStart( void ) ; static void intmoduleNoneStop( void ) ; static void extmoduleNoneStart( void ) ; static void extmoduleNoneStop( void ) ; +static void extmoduleCrossfireStart( void ) ; +static void extmoduleCrossfireStop( void ) ; void init_pxx(uint32_t port) { @@ -148,6 +150,19 @@ void disable_no_pulses(uint32_t port) extmoduleNoneStop(); } +void init_crossfire(uint32_t port) +{ + if (port == EXTERNAL_MODULE) { + extmoduleCrossfireStart(); + } +} + +void disable_crossfire(uint32_t port) +{ + if (port == EXTERNAL_MODULE) + extmoduleCrossfireStop(); +} + static void intmoduleNoneStart() { INTERNAL_MODULE_OFF(); @@ -226,6 +241,46 @@ static void extmoduleNoneStop() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; } +static void extmoduleCrossfireStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_GPIO, &GPIO_InitStructure); + GPIO_SetBits(EXTMODULE_GPIO, EXTMODULE_GPIO_PIN); // Set high + + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; + EXTMODULE_TIMER->ARR = 5000 ; // 2.5mS + EXTMODULE_TIMER->CCR2 = 32000 ; // Update time + EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz + + EXTMODULE_TIMER->CCMR2 = 0 ; + EXTMODULE_TIMER->EGR = 1 ; // Restart + + EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 ; // Toggle CC1 o/p + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; + NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn) ; + NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); +} + +static void extmoduleCrossfireStop() +{ + NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn) ; + EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE ; + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; + + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } +} + static void intmodulePxxStart() { INTERNAL_MODULE_ON(); diff --git a/radio/src/targets/taranis/serial2_driver.cpp b/radio/src/targets/taranis/serial2_driver.cpp index 2369a1c96..80e467344 100644 --- a/radio/src/targets/taranis/serial2_driver.cpp +++ b/radio/src/targets/taranis/serial2_driver.cpp @@ -105,7 +105,7 @@ void serial2Putc(char c) void serial2SbusInit() { - uart3Setup(100000); + uart3Setup(SBUS_BAUDRATE); SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ; } diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index 93612af6f..25bf4111b 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -85,12 +85,17 @@ struct SportTxBuffer uint32_t count; } sportTxBuffer; +void telemetryPortSetDirectionOutput() +{ + TELEMETRY_GPIO_DIR->BSRRL = TELEMETRY_GPIO_PIN_DIR; // output enable + TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver +} + void sportSendBuffer(uint8_t *buffer, uint32_t count) { - sportTxBuffer.ptr = buffer ; - sportTxBuffer.count = count ; - TELEMETRY_GPIO_DIR->BSRRL = TELEMETRY_GPIO_PIN_DIR ; // output enable - TELEMETRY_USART->CR1 &= ~USART_CR1_RE ; // turn off receiver + sportTxBuffer.ptr = buffer; + sportTxBuffer.count = count; + telemetryPortSetDirectionOutput(); TELEMETRY_USART->CR1 |= USART_CR1_TXEIE ; } diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp index 75dee9522..88a746c16 100644 --- a/radio/src/telemetry/frsky.cpp +++ b/radio/src/telemetry/frsky.cpp @@ -293,8 +293,8 @@ void telemetryWakeup() #else if (telemetryProtocol != requiredTelemetryProtocol) { #endif + telemetryInit(requiredTelemetryProtocol); telemetryProtocol = requiredTelemetryProtocol; - telemetryInit(); } #endif @@ -618,13 +618,20 @@ void telemetryReset() #endif } -void telemetryInit(void) -{ #if defined(CPUARM) - if (telemetryProtocol == PROTOCOL_FRSKY_D) { +// we don't reset the telemetry here as we would also reset the consumption after model load +void telemetryInit(uint8_t protocol) +{ + if (protocol == PROTOCOL_FRSKY_D) { telemetryPortInit(FRSKY_D_BAUDRATE); } - else if (telemetryProtocol==PROTOCOL_FRSKY_D_SECONDARY) { +#if defined(PCBTARANIS) + else if (protocol == PROTOCOL_PULSES_CROSSFIRE) { + telemetryPortInit(CROSSFIRE_BAUDRATE); + telemetryPortSetDirectionOutput(); + } +#endif + else if (protocol == PROTOCOL_FRSKY_D_SECONDARY) { telemetryPortInit(0); serial2TelemetryInit(PROTOCOL_FRSKY_D_SECONDARY); } @@ -640,12 +647,13 @@ void telemetryInit(void) clearMFP(); } #endif -#elif !defined(SIMU) - telemetryPortInit(); -#endif - - // we don't reset the telemetry here as we would also reset the consumption after model load } +#else +void telemetryInit() +{ + telemetryPortInit(); +} +#endif #if defined(CPUARM) #elif defined(FRSKY_HUB) diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h index 07c9a5c2b..0e494a078 100644 --- a/radio/src/telemetry/frsky.h +++ b/radio/src/telemetry/frsky.h @@ -528,7 +528,14 @@ void sportFirmwareUpdate(ModuleIndex module, const char *filename); #endif void telemetryWakeup(void); void telemetryReset(); + +#if defined(CPUARM) +extern uint8_t telemetryProtocol; +void telemetryInit(uint8_t protocol); +#else void telemetryInit(void); +#endif + void telemetryInterrupt10ms(void); #if defined(CPUARM) @@ -544,7 +551,18 @@ void frskyUpdateCells(void); #endif #if defined(PCBTARANIS) - #define MODEL_TELEMETRY_PROTOCOL() ((g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) ? g_model.telemetryProtocol : PROTOCOL_FRSKY_SPORT) + inline uint8_t modelTelemetryProtocol() + { +#if defined(CROSSFIRE) + if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) + return PROTOCOL_PULSES_CROSSFIRE; +#endif + if (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) + return g_model.telemetryProtocol; + else + return PROTOCOL_FRSKY_SPORT; + } + #define MODEL_TELEMETRY_PROTOCOL() modelTelemetryProtocol() #elif defined(CPUARM) #define MODEL_TELEMETRY_PROTOCOL() g_model.telemetryProtocol #endif diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index f349b6b64..e58092704 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -326,60 +326,14 @@ void blankPacket(uint8_t *packet) memset(packet+2, 0, 6); } -/* CRC16 implementation acording to CCITT standards */ - -static const unsigned short crc16tab[256]= { - 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, - 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, - 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, - 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, - 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, - 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, - 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, - 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, - 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, - 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, - 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, - 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, - 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, - 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, - 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, - 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, - 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, - 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, - 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, - 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, - 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, - 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, - 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, - 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, - 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, - 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, - 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, - 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, - 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, - 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, - 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, - 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 -}; - -uint16_t crc16_ccitt(uint8_t *buf, uint32_t len) -{ - uint16_t crc = 0; - for (uint32_t counter=0; counter>8) ^ *buf++ ) &0x00FF]; - } - return crc; -} - uint8_t sportUpdatePacket[16]; -void writePacket(uint8_t *packet) +void writePacket(uint8_t * packet) { uint8_t *ptr = sportUpdatePacket; *ptr++ = 0x7E; *ptr++ = 0xFF; - packet[7] = crc16_ccitt(packet, 7); + packet[7] = crc16(packet, 7); for (int i=0; i<8; i++) { if (packet[i] == 0x7E || packet[i] == 0x7D) { *ptr++ = 0x7D; diff --git a/radio/src/tests/crossfire.cpp b/radio/src/tests/crossfire.cpp new file mode 100644 index 000000000..8862c0683 --- /dev/null +++ b/radio/src/tests/crossfire.cpp @@ -0,0 +1,55 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program 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. + * + */ + +#include "gtests.h" + +#if defined(CROSSFIRE) +TEST(Crossfire, createCrossfireFrame) +{ + int16_t pulsesStart[NUM_TRAINER]; + uint8_t crossfire[CROSSFIRE_FRAME_LEN]; + + memset(crossfire, 0, sizeof(crossfire)); + for (int i=0; i