1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-18 22:05:10 +03:00

#2894 - Crossfire (inverted serial) sent on S.PORT pin in the module bay

16 channels sent every 2.5ms now @ 200KBauds with CRC
This commit is contained in:
Bertrand Songis 2015-09-24 20:49:19 +02:00
parent a4869cdb8a
commit f7044a20ec
31 changed files with 435 additions and 92 deletions

View file

@ -926,7 +926,7 @@ ifeq ($(PCB), TARANIS)
PPM_LIMITS_SYMETRICAL = YES
PPM_CENTER_ADJUSTABLE = YES
DSM2 = PPM
CPPDEFS += -DPCBTARANIS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM_RLC -DAUDIO -DPXX
CPPDEFS += -DPCBTARANIS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM_RLC -DAUDIO -DPXX -DSBUS -DCROSSFIRE
INCDIRS += targets/taranis $(THIRDPARTY) $(COOSDIR) $(COOSDIR)/kernel $(COOSDIR)/portable
CPPDEFS += -DHSE_VALUE=12000000
ifeq ($(PCBREV), REV9E)
@ -952,7 +952,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 = eeprom_common.cpp eeprom_rlc.cpp 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
@ -1297,6 +1297,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

80
radio/src/crc16.cpp Normal file
View file

@ -0,0 +1,80 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - 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<len; counter++) {
crc = (crc<<8) ^ crc16tab[ ((crc>>8) ^ *buf++ ) & 0x00FF];
}
return crc;
}

View file

@ -207,7 +207,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)

View file

@ -2020,6 +2020,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,
@ -2061,6 +2064,9 @@ enum ModuleTypes {
MODULE_TYPE_XJT,
#if defined(DSM2)
MODULE_TYPE_DSM2,
#endif
#if defined(CROSSFIRE)
MODULE_TYPE_CROSSFIRE,
#endif
MODULE_TYPE_COUNT
};
@ -2127,7 +2133,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

View file

@ -2511,7 +2511,7 @@ int main(void)
sei(); // interrupts needed for telemetryInit and eeReadAll.
#if defined(FRSKY) && !defined(DSM2_SERIAL)
#if !defined(CPUARM) && defined(FRSKY) && !defined(DSM2_SERIAL)
telemetryInit();
#endif

View file

@ -480,7 +480,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)
@ -499,6 +499,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
@ -977,8 +982,8 @@ void checkAll();
void getADC();
#endif
#if defined(PCBTARANIS)
void processSbusInput();
#if defined(SBUS)
#include "sbus.h"
#endif
extern void backlightOn();
@ -1375,6 +1380,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

View file

@ -0,0 +1,62 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - 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<NUM_TRAINER; i++) {
bits |= (CROSSFIRE_CH_CENTER + (((pulses[i]) * 4) / 5)) << bitsavailable;
bitsavailable += CROSSFIRE_CH_BITS;
while (bitsavailable >= 8) {
*buf++ = bits;
bits >>= 8;
bitsavailable -= 8;
}
}
*buf++ = 0;
*buf++ = crc16(frame, 24);
}

View file

@ -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);

View file

@ -87,10 +87,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 {
@ -105,6 +112,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

View file

@ -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<<SBUS_CH_BITS)-1)
#define SBUS_CH_MASK ((1<<SBUS_CH_BITS)-1)
#define SBUS_CH_CENTER 0x3E0
#define SBUS_CH_CENTER 0x3E0
Fifo<32> 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;

47
radio/src/sbus.h Normal file
View file

@ -0,0 +1,47 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - 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_

View file

@ -1233,6 +1233,10 @@ void lcdRefresh()
lcd_refresh = true;
}
void telemetryPortInit()
{
}
#if defined(PCBTARANIS)
void pwrInit() { }
void pwrOff() { }

View file

@ -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

View file

@ -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();

View file

@ -105,7 +105,7 @@ void serial2Putc(char c)
void serial2SbusInit()
{
uart3Setup(100000);
uart3Setup(SBUS_BAUDRATE);
SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ;
}

View file

@ -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 ;
}

View file

@ -284,8 +284,8 @@ void telemetryWakeup()
#if defined(CPUARM)
uint8_t requiredTelemetryProtocol = MODEL_TELEMETRY_PROTOCOL();
if (telemetryProtocol != requiredTelemetryProtocol) {
telemetryInit(requiredTelemetryProtocol);
telemetryProtocol = requiredTelemetryProtocol;
telemetryInit();
}
#endif
@ -609,25 +609,33 @@ 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);
}
else {
telemetryPortInit(FRSKY_SPORT_BAUDRATE);
}
#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)

View file

@ -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

View file

@ -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<len; counter++) {
crc = (crc<<8) ^ crc16tab[ ((crc>>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;

View file

@ -0,0 +1,55 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - 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<NUM_TRAINER; i++) {
pulsesStart[i] = -1024 + (2048 / NUM_TRAINER) * i;
}
createCrossfireFrame(crossfire, pulsesStart);
// TODO check
}
#endif

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "Amerika\0""Japonsko""Evropa\0 ")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "Vyp\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "Vyp\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "Vyp\0""D16\0""D8\0 ""LR12"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "Amerika""Japan\0 ""Europa\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "AUS\0""PPM\0""XJT\0""DSM?"
#define TR_TARANIS_PROTOCOLS "AUS\0""PPM\0""XJT\0""DSM?""CRSF"
#if defined(MODULE_D16_EU_ONLY_SUPPORT)
#define LEN_XJT_PROTOCOLS "\006"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europe\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japon\0 ""Europa\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "Amerikk""Japani\0""Euroopp")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "USA\0 ""Japon\0""Europe")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -107,7 +107,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europa\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -107,7 +107,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "Amerika""Japan\0 ""Europa\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "UIT\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "UIT\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -107,7 +107,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "Ameryka""Japonia""Europa\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europe\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "OFF\0""D16\0""D8\0 ""LR12"

View file

@ -104,7 +104,7 @@
#define TR_COUNTRYCODES TR("US""JP""EU", "Amerika""Japan\0 ""Europa\0")
#define LEN_TARANIS_PROTOCOLS "\004"
#define TR_TARANIS_PROTOCOLS "Av\0 ""PPM\0""XJT\0""DSM2"
#define TR_TARANIS_PROTOCOLS "Av\0 ""PPM\0""XJT\0""DSM2""CRSF"
#define LEN_XJT_PROTOCOLS "\004"
#define TR_XJT_PROTOCOLS "Av\0 ""D16\0""D8\0 ""LR12"