diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index b620c7f86..713655f44 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -47,6 +47,7 @@ option(FRSKY_STICKS "Reverse sticks for FrSky sticks" OFF) option(NANO "Use nano newlib and binalloc") option(NIGHTLY_BUILD_WARNING "Warn this is a nightly build" OFF) option(MODULE_R9M_FLEX_FW "Add R9M options for non certified firmwwares" OFF) +option(PXX2 "Enable PXX v2 support" OFF) # since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags. set(FIRMWARE_C_FLAGS "" CACHE STRING "Additional flags for firmware target c compiler (note: all CMAKE_C_FLAGS[_*] are ignored for firmware/bootloader).") @@ -313,7 +314,11 @@ if(NIGHTLY_BUILD_WARNING) endif(NIGHTLY_BUILD_WARNING) if(MODULE_R9M_FLEX_FW) - add_definitions(-DMODULE_R9M_FLEX_FW) + add_definitions(-DMODULE_R9M_FLEX_FW) +endif() + +if(PXX2) + add_definitions(-DPXX2) endif() set(SRC diff --git a/radio/src/io/pxx2.h b/radio/src/io/pxx2.h new file mode 100644 index 000000000..3a1506a67 --- /dev/null +++ b/radio/src/io/pxx2.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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 _IO_PXX2_H_ +#define _IO_PXX2_H_ + +#define PXX2_BAUDRATE 230400 +#define PXX2_PERIOD 4 // 4ms + +#endif diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index a8bc908d5..3024536b5 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -342,10 +342,16 @@ enum Protocols { #endif PROTO_MULTIMODULE, PROTO_SBUS, - PROTO_MAX, + PROTO_PXX2, PROTO_NONE }; +#if defined(PXX2) +#define PROTO_PXX_EXTERNAL_MODULE PROTO_PXX2 +#else +#define PROTO_PXX_EXTERNAL_MODULE PROTO_PXX +#endif + enum XJTRFProtocols { RF_PROTO_OFF = -1, RF_PROTO_X16, diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index f9e613682..f91a36194 100755 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -20,6 +20,11 @@ #include "opentx.h" +#if defined(PXX2) +#include "io/pxx2.h" +#include "pulses/pxx2.h" +#endif + uint8_t s_pulses_paused = 0; uint8_t s_current_protocol[NUM_MODULES] = { MODULES_INIT(255) }; uint16_t failsafeCounter[NUM_MODULES] = { MODULES_INIT(100) }; @@ -56,14 +61,13 @@ uint8_t getRequiredProtocol(uint8_t port) #endif default: - port = EXTERNAL_MODULE; // ensure it's external module only switch (g_model.moduleData[EXTERNAL_MODULE].type) { case MODULE_TYPE_PPM: required_protocol = PROTO_PPM; break; case MODULE_TYPE_XJT: case MODULE_TYPE_R9M: - required_protocol = PROTO_PXX; + required_protocol = PROTO_PXX_EXTERNAL_MODULE; // either PXX or PXX2 depending on compilation options break; case MODULE_TYPE_SBUS: required_protocol = PROTO_SBUS; @@ -118,6 +122,20 @@ uint8_t getRequiredProtocol(uint8_t port) return required_protocol; } +void setupPulsesPXX(uint8_t port) +{ +#if defined(INTMODULE_USART) && defined(EXTMODULE_USART) + modulePulsesData[port].pxx_uart.setupFrame(port); +#elif !defined(INTMODULE_USART) && !defined(EXTMODULE_USART) + modulePulsesData[port].pxx.setupFrame(port); +#else + if (IS_UART_MODULE(port)) + modulePulsesData[port].pxx_uart.setupFrame(port); + else + modulePulsesData[port].pxx.setupFrame(port); +#endif +} + void setupPulses(uint8_t port) { bool init_needed = false; @@ -142,7 +160,13 @@ void setupPulses(uint8_t port) #if defined(CROSSFIRE) case PROTO_CROSSFIRE: - disable_crossfire(port); + disable_module_timer(port); + break; +#endif + +#if defined(PXX2) + case PROTO_PXX2: + disable_module_timer(port); break; #endif @@ -208,6 +232,16 @@ void setupPulses(uint8_t port) break; #endif +#if defined(PXX2) + case PROTO_PXX2: + if (telemetryProtocol == PROTOCOL_FRSKY_SPORT && !init_needed) { + modulePulsesData[port].pxx2.setupFrame(port); + sportSendBuffer(modulePulsesData[port].pxx2.getData(), modulePulsesData[port].pxx2.getSize()); + } + scheduleNextMixerCalculation(port, PXX2_PERIOD); + break; +#endif + #if defined(MULTIMODULE) case PROTO_MULTIMODULE: setupPulsesMultimodule(port); @@ -243,7 +277,13 @@ void setupPulses(uint8_t port) #if defined(CROSSFIRE) case PROTO_CROSSFIRE: - init_crossfire(port); + init_module_timer(port, CROSSFIRE_PERIOD, true); + break; +#endif + +#if defined(PXX2) + case PROTO_PXX2: + init_module_timer(port, PXX2_PERIOD, true); break; #endif diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index e726f8e63..744abb07b 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -21,20 +21,15 @@ #ifndef _PULSES_ARM_H_ #define _PULSES_ARM_H_ +#include "pulses/pxx2.h" +#include "pulses/pxx1.h" + #if NUM_MODULES == 2 #define MODULES_INIT(...) __VA_ARGS__, __VA_ARGS__ #else #define MODULES_INIT(...) __VA_ARGS__ #endif -#if defined(PCBX12S) && PCBREV < 13 - #define pulse_duration_t uint32_t - #define trainer_pulse_duration_t uint16_t -#else - #define pulse_duration_t uint16_t - #define trainer_pulse_duration_t uint16_t -#endif - extern uint8_t s_current_protocol[NUM_MODULES]; extern uint8_t s_pulses_paused; extern uint16_t failsafeCounter[NUM_MODULES]; @@ -44,30 +39,6 @@ template struct PpmPulsesData { T * ptr; }; -#if defined(PXX_FREQUENCY_HIGH) -#define EXTMODULE_USART_PXX_BAUDRATE 420000 -#define INTMODULE_USART_PXX_BAUDRATE 450000 -#define PXX_PERIOD 4/*ms*/ -#else -#define EXTMODULE_USART_PXX_BAUDRATE 115200 -#define INTMODULE_USART_PXX_BAUDRATE 115200 -#define PXX_PERIOD 9/*ms*/ -#endif - -#define PXX_PERIOD_HALF_US (PXX_PERIOD * 2000) - -#if defined(PPM_PIN_SERIAL) -PACK(struct PxxSerialPulsesData { - uint8_t pulses[64]; - uint8_t * ptr; - uint16_t pcmValue; - uint16_t pcmCrc; - uint32_t pcmOnesCount; - uint16_t serialByte; - uint16_t serialBitCount; -}); -#endif - #if defined(PPM_PIN_SERIAL) PACK(struct Dsm2SerialPulsesData { uint8_t pulses[64]; @@ -86,15 +57,6 @@ PACK(struct Dsm2TimerPulsesData { }); #endif -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) -PACK(struct PxxUartPulsesData { - uint8_t pulses[64]; - uint8_t * ptr; - uint16_t pcmCrc; - uint16_t _alignment; -}); -#endif - #define PPM_PERIOD_HALF_US(module) ((g_model.moduleData[module].ppm.frameLength * 5 + 225) * 200) /*half us*/ #define PPM_PERIOD(module) (PPM_PERIOD_HALF_US(module) / 2000) /*ms*/ #define DSM2_BAUDRATE 125000 @@ -105,26 +67,6 @@ PACK(struct PxxUartPulsesData { #define MULTIMODULE_BAUDRATE 100000 #define MULTIMODULE_PERIOD 7 /*ms*/ -#if !defined(INTMODULE_USART) || !defined(EXTMODULE_USART) -/* PXX uses 20 bytes (as of Rev 1.1 document) with 8 changes per byte + stop bit ~= 162 max pulses */ -/* DSM2 uses 2 header + 12 channel bytes, with max 10 changes (8n2) per byte + 16 bits trailer ~= 156 max pulses */ -/* Multimodule uses 3 bytes header + 22 channel bytes with max 11 changes per byte (8e2) + 16 bits trailer ~= 291 max pulses */ -/* Multimodule reuses some of the DSM2 function and structs since the protocols are similar enough */ -/* sbus is 1 byte header, 22 channel bytes (11bit * 16ch) + 1 byte flags */ - -#if defined(PXX_FREQUENCY_HIGH) -#error "Pulses array needs to be increased (PXX_FREQUENCY=HIGH)" -#endif - -PACK(struct PxxTimerPulsesData { - pulse_duration_t pulses[200]; - pulse_duration_t * ptr; - uint16_t rest; - uint16_t pcmCrc; - uint32_t pcmOnesCount; -}); -#endif - #define CROSSFIRE_FRAME_MAXLEN 64 PACK(struct CrossfirePulsesData { uint8_t pulses[CROSSFIRE_FRAME_MAXLEN]; @@ -132,12 +74,16 @@ PACK(struct CrossfirePulsesData { union ModulePulsesData { #if defined(INTMODULE_USART) || defined(EXTMODULE_USART) - PxxUartPulsesData pxx_uart; + UartPxxPulses pxx_uart; #endif #if defined(PPM_PIN_SERIAL) - PxxSerialPulsesData pxx; + SerialPxxPulses pxx; #elif !defined(INTMODULE_USART) || !defined(EXTMODULE_USART) - PxxTimerPulsesData pxx; + PwmPxxPulses pxx; +#endif + +#if defined(PXX2) + Pxx2Pulses pxx2; #endif #if defined(PPM_PIN_SERIAL) diff --git a/radio/src/pulses/pulses_common.h b/radio/src/pulses/pulses_common.h new file mode 100644 index 000000000..da70a13c0 --- /dev/null +++ b/radio/src/pulses/pulses_common.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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 _PULSES_COMMON_H_ +#define _PULSES_COMMON_H_ + +#include + +#if defined(PCBX12S) && PCBREV < 13 + #define pulse_duration_t uint32_t + #define trainer_pulse_duration_t uint16_t +#else + #define pulse_duration_t uint16_t + #define trainer_pulse_duration_t uint16_t +#endif + +template +class DataBuffer { + public: + const T * getData() + { + return data; + } + + uint8_t getSize() + { + return ptr - data; + } + + protected: + T data[SIZE]; + T * ptr; + + void initBuffer() + { + ptr = data; + } +}; + +template +class PulsesBuffer: public DataBuffer { + public: + T getLast() { + return *(DataBuffer::ptr - 1); + }; +}; + +#endif diff --git a/radio/src/pulses/pxx.cpp b/radio/src/pulses/pxx.cpp new file mode 100644 index 000000000..19a547ac7 --- /dev/null +++ b/radio/src/pulses/pxx.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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" +#include "pulses/pxx1.h" +#include "pulses/pxx2.h" + +const uint16_t PxxCrcMixin::CRCTable[] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +}; + +template +void PxxPulses::addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels) +{ + uint16_t pulseValue = 0; + uint16_t pulseValueLow = 0; + + for (int8_t i=0; i<8; i++) { + if (sendFailsafe) { + if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) { + pulseValue = (i < sendUpperChannels ? 4095 : 2047); + } + else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) { + pulseValue = (i < sendUpperChannels ? 2048 : 0); + } + else { + if (i < sendUpperChannels) { + int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[8+i]; + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { + pulseValue = 4095; + } + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + pulseValue = 2048; + } + else { + failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER; + pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094); + } + } + else { + int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[i]; + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { + pulseValue = 2047; + } + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + pulseValue = 0; + } + else { + failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER; + pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046); + } + } + } + } + else { + if (i < sendUpperChannels) { + int channel = 8 + g_model.moduleData[port].channelsStart + i; + int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; + pulseValue = limit(2049, (value * 512 / 682) + 3072, 4094); + } + else if (i < sentModuleChannels(port)) { + int channel = g_model.moduleData[port].channelsStart + i; + int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; + pulseValue = limit(1, (value * 512 / 682) + 1024, 2046); + } + else { + pulseValue = 1024; + } + } + + if (i & 1) { + PxxTransport::addByte(pulseValueLow); // Low byte of channel + PxxTransport::addByte(((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels + PxxTransport::addByte(pulseValue >> 4); // High byte of channel + } + else { + pulseValueLow = pulseValue; + } + } +} + +template +uint8_t PxxPulses::addFlag1(uint8_t port) +{ + uint8_t flag1 = (g_model.moduleData[port].rfProtocol << 6); + if (moduleFlag[port] == MODULE_BIND) { + flag1 |= (g_eeGeneral.countryCode << 1) | PXX_SEND_BIND; + } + else if (moduleFlag[port] == MODULE_RANGECHECK) { + flag1 |= PXX_SEND_RANGECHECK; + } + else if (g_model.moduleData[port].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[port].failsafeMode != FAILSAFE_RECEIVER) { + if (failsafeCounter[port]-- == 0) { + failsafeCounter[port] = 1000; + flag1 |= PXX_SEND_FAILSAFE; + } + if (failsafeCounter[port] == 0 && g_model.moduleData[port].channelsCount > 0) { + flag1 |= PXX_SEND_FAILSAFE; + } + } + PxxTransport::addByte(flag1); + return flag1; +} + +template +void PxxPulses::addExtraFlags(uint8_t port) +{ + // Ext. flag (holds antenna selection on Horus internal module, 0x00 otherwise) + uint8_t extra_flags = 0; + +#if defined(PCBHORUS) || defined(PCBXLITE) + if (port == INTERNAL_MODULE) { + extra_flags |= (g_model.moduleData[port].pxx.external_antenna << 0); + } +#endif + + extra_flags |= (g_model.moduleData[port].pxx.receiver_telem_off << 1); + extra_flags |= (g_model.moduleData[port].pxx.receiver_channel_9_16 << 2); + if (isModuleR9M(port)) { + extra_flags |= (min(g_model.moduleData[port].pxx.power, isModuleR9M_FCC_VARIANT(port) ? (uint8_t)R9M_FCC_POWER_MAX : (uint8_t)R9M_LBT_POWER_MAX) << 3); + if(isModuleR9M_EUPLUS(port)) + extra_flags |= (1 << 6); + } + + // Disable S.PORT if internal module is active + if (IS_TELEMETRY_INTERNAL_MODULE()) { + extra_flags |= (1 << 5); + } + PxxTransport::addByte(extra_flags); +} + +template class PxxPulses >; +template class PxxPulses >; +template class PxxPulses; +template class PxxPulses; diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h new file mode 100644 index 000000000..02296bbe5 --- /dev/null +++ b/radio/src/pulses/pxx.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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 _PULSES_PXX_H_ +#define _PULSES_PXX_H_ + +#include "pulses_common.h" + +#define PXX_SEND_BIND 0x01 +#define PXX_SEND_FAILSAFE (1 << 4) +#define PXX_SEND_RANGECHECK (1 << 5) + +#if defined(PXX_FREQUENCY_HIGH) + #define EXTMODULE_USART_PXX_BAUDRATE 420000 + #define INTMODULE_USART_PXX_BAUDRATE 450000 + #define PXX_PERIOD 4/*ms*/ +#else + #define EXTMODULE_USART_PXX_BAUDRATE 115200 + #define INTMODULE_USART_PXX_BAUDRATE 115200 + #define PXX_PERIOD 9/*ms*/ +#endif + +#if defined(PXX_FREQUENCY_HIGH) && (!defined(INTMODULE_USART) || !defined(EXTMODULE_USART)) +/* PXX uses 20 bytes (as of Rev 1.1 document) with 8 changes per byte + stop bit ~= 162 max pulses */ +/* DSM2 uses 2 header + 12 channel bytes, with max 10 changes (8n2) per byte + 16 bits trailer ~= 156 max pulses */ +/* Multimodule uses 3 bytes header + 22 channel bytes with max 11 changes per byte (8e2) + 16 bits trailer ~= 291 max pulses */ +/* Multimodule reuses some of the DSM2 function and structs since the protocols are similar enough */ +/* sbus is 1 byte header, 22 channel bytes (11bit * 16ch) + 1 byte flags */ + +#error "Pulses array needs to be increased (PXX_FREQUENCY=HIGH)" +#endif + + +#define PXX_PERIOD_HALF_US (PXX_PERIOD * 2000) + +class PxxCrcMixin { + protected: + void initCrc() + { + crc = 0; + } + + void addToCrc(uint8_t byte) + { + crc = (crc << 8) ^ (CRCTable[((crc >> 8) ^ byte) & 0xFF]); + } + + uint16_t crc; + static const uint16_t CRCTable[]; +}; + +// Used by the Sky9x family boards +class SerialPxxBitTransport: public DataBuffer { + protected: + uint8_t byte; + uint8_t bits_count; + + void initFrame() + { + initBuffer(); + byte = 0; + bits_count = 0; + } + + void addSerialBit(uint8_t bit) + { + byte >>= 1; + if (bit & 1) { + byte |= 0x80; + } + if (++bits_count >= 8) { + *ptr++ = byte; + bits_count = 0; + } + } + + // 8uS/bit 01 = 0, 001 = 1 + void addPart(uint8_t value) + { + addSerialBit(0); + if (value) { + addSerialBit(0); + } + addSerialBit(1); + } + + void addTail() + { + while (bits_count != 0) { + addSerialBit(1); + } + } +}; + +class PwmPxxBitTransport: public PulsesBuffer { + protected: + uint16_t rest; + + void initFrame() + { + initBuffer(); + rest = PXX_PERIOD_HALF_US; + } + + void addPart(uint8_t value) + { + pulse_duration_t duration = value ? 47 : 31; + *ptr++ = duration; + rest -= duration + 1; + } + + void addTail() + { + // rest min value is 18000 - 200 * 48 = 8400 (4.2ms) + *(ptr - 1) += rest; + } +}; + +template +class StandardPxxTransport: public BitTransport, public PxxCrcMixin { + protected: + uint8_t ones_count; + + void initFrame() + { + BitTransport::initFrame(); + ones_count = 0; + } + + void addByte(uint8_t byte) + { + PxxCrcMixin::addToCrc(byte); + addByteWithoutCrc(byte); + }; + + void addByteWithoutCrc(uint8_t byte) + { + for (uint8_t i = 0; i < 8; i++) { + addBit(byte & 0x80); + byte <<= 1; + } + } + + void addBit(uint8_t bit) + { + if (bit) { + BitTransport::addPart(1); + if (++ones_count == 5) { + ones_count = 0; + BitTransport::addPart(0); // Stuff a 0 bit in + } + } + else { + BitTransport::addPart(0); + ones_count = 0; + } + } +}; + +class UartPxxTransport: public DataBuffer, public PxxCrcMixin { + protected: + void initFrame() + { + initBuffer(); + } + + void addByte(uint8_t byte) + { + PxxCrcMixin::addToCrc(byte); + addWithByteStuffing(byte); + } + + void addByteWithoutCrc(uint8_t byte) + { + *ptr++ = byte; + } + + void addWithByteStuffing(uint8_t byte) + { + if (0x7E == byte) { + *ptr++ = 0x7D; + *ptr++ = 0x5E; + } + else if (0x7D == byte) { + *ptr++ = 0x7D; + *ptr++ = 0x5D; + } + else { + *ptr++ = byte; + } + } + + void addTail() + { + // nothing + } +}; + +template +class PxxPulses: public PxxTransport { + protected: + uint8_t addFlag1(uint8_t port); + void addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels); + void addExtraFlags(uint8_t port); +}; + +#endif diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp new file mode 100644 index 000000000..3ab3963d8 --- /dev/null +++ b/radio/src/pulses/pxx1.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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" +#include "pulses/pxx1.h" + +template +void Pxx1Pulses::add8ChannelsFrame(uint8_t port, uint8_t sendUpperChannels) +{ + PxxTransport::initCrc(); + + // Sync + addHead(); + + // RX Number + PxxTransport::addByte(g_model.header.modelId[port]); + + // Flag1 + uint8_t flag1 = PxxPulses::addFlag1(port); + + // Flag2 + PxxTransport::addByte(0); + + // Channels + PxxPulses::addChannels(port, flag1 & PXX_SEND_FAILSAFE, sendUpperChannels); + + // Extra flags + PxxPulses::addExtraFlags(port); + + // CRC + addCrc(); + + // Sync = HEAD + addHead(); + + // Tail + PxxTransport::addTail(); +} + +template +void Pxx1Pulses::setupFrame(uint8_t port) +{ + PxxTransport::initFrame(); + +#if defined(PXX_FREQUENCY_HIGH) + add8ChannelsFrame(port, 0); + if (sentModuleChannels(port) > 8) { + add8ChannelsFrame(port, 8); + } +#else + static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) }; + uint8_t sendUpperChannels = 0; + if (pass[port]++ & 0x01) { + sendUpperChannels = g_model.moduleData[port].channelsCount; + } + add8ChannelsFrame(port, sendUpperChannels); +#endif +} + +template class Pxx1Pulses >; +template class Pxx1Pulses >; +template class Pxx1Pulses; diff --git a/radio/src/pulses/pxx1.h b/radio/src/pulses/pxx1.h new file mode 100644 index 000000000..444202d26 --- /dev/null +++ b/radio/src/pulses/pxx1.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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 _PULSES_PXX1_H_ +#define _PULSES_PXX1_H_ + +#include "pxx.h" + +template +class Pxx1Pulses: public PxxPulses +{ + public: + void setupFrame(uint8_t port); + + protected: + void addHead() + { + // send 7E, do not CRC + PxxTransport::addByteWithoutCrc(0x7E); + } + + void addCrc() + { + PxxTransport::addByteWithoutCrc(PxxCrcMixin::crc >> 8); + PxxTransport::addByteWithoutCrc(PxxCrcMixin::crc); + } + + void add8ChannelsFrame(uint8_t port, uint8_t sendUpperChannels); +}; + +typedef Pxx1Pulses UartPxxPulses; +typedef Pxx1Pulses> PwmPxxPulses; +typedef Pxx1Pulses> SerialPxxPulses; + +#endif diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp new file mode 100644 index 000000000..d7d32b588 --- /dev/null +++ b/radio/src/pulses/pxx2.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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" +#include "pulses/pxx2.h" + +void Pxx2Pulses::setupFrame(uint8_t port) +{ + initFrame(); + initCrc(); + + static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) }; + uint8_t sendUpperChannels = 0; + if (pass[port]++ & 0x01) { + sendUpperChannels = g_model.moduleData[port].channelsCount; + } + + // Model ID + addByte(g_model.header.modelId[port]); + + // Flag1 + uint8_t flag1 = addFlag1(port); + + // Flag2 + addByte(0); + + // Channels + addChannels(port, flag1 & PXX_SEND_FAILSAFE, sendUpperChannels); + + // Extra flags + addExtraFlags(port); + + // Flag3, reserved + addByte(0); + +#if defined(LUA) + if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) { + // CMD/Resp + addByte(1); + // primID (1 byte) + dataID (2 bytes) + value (4 bytes) + for (uint8_t i=0; i<7; i++) { + addByte(outputTelemetryBuffer[i]); + } + outputTelemetryBufferTrigger = 0x00; + outputTelemetryBufferSize = 0; + } + else { + // CMD/Resp + addByte(0); + } +#else + // CMD/Resp + addByte(0); +#endif + + // CRC + addByte(crc); // TODO need to check the CRC chosen algorithm +} diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h new file mode 100644 index 000000000..939d0204d --- /dev/null +++ b/radio/src/pulses/pxx2.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * 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 _PULSES_PXX2_H_ +#define _PULSES_PXX2_H_ + +#include "./pxx.h" + +class SportCrcMixin { + protected: + void initCrc() + { + crc = 0; + } + + void addToCrc(uint8_t byte) + { + crc += byte; // 0-1FF + crc += crc >> 8; // 0-100 + crc &= 0x00ff; + } + + uint16_t crc; +}; + + +class Pxx2Transport: public DataBuffer, public SportCrcMixin { + protected: + void addByte(uint8_t byte) + { + SportCrcMixin::addToCrc(byte); + *ptr++ = byte; + } + + void addTail() + { + // nothing + } +}; + +class Pxx2Pulses: public PxxPulses { + public: + void setupFrame(uint8_t port); + + protected: + uint8_t data[64]; + uint8_t * ptr; + + void initFrame() + { + Pxx2Transport::initBuffer(); + } +}; + +#endif diff --git a/radio/src/pulses/pxx_arm.cpp b/radio/src/pulses/pxx_arm.cpp deleted file mode 100644 index 1418df9a4..000000000 --- a/radio/src/pulses/pxx_arm.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * 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 PXX_SEND_BIND 0x01 -#define PXX_SEND_FAILSAFE (1 << 4) -#define PXX_SEND_RANGECHECK (1 << 5) - -const uint16_t CRCTable[]= -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 -}; - -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) -inline void uartPutPcmPart(uint8_t port, uint8_t byte) -{ - if (0x7E == byte) { - *modulePulsesData[port].pxx_uart.ptr++ = 0x7D; - *modulePulsesData[port].pxx_uart.ptr++ = 0x5E; - } - else if (0x7D == byte) { - *modulePulsesData[port].pxx_uart.ptr++ = 0x7D; - *modulePulsesData[port].pxx_uart.ptr++ = 0x5D; - } - else { - *modulePulsesData[port].pxx_uart.ptr++ = byte; - } -} - -void uartPutPcmByte(uint8_t port, uint8_t byte) -{ - modulePulsesData[port].pxx_uart.pcmCrc = (modulePulsesData[port].pxx_uart.pcmCrc<<8) ^ (CRCTable[((modulePulsesData[port].pxx_uart.pcmCrc>>8)^byte) & 0xFF]); - uartPutPcmPart(port, byte); -} - -void uartInitPcmArray(uint8_t port) -{ - modulePulsesData[port].pxx_uart.ptr = modulePulsesData[port].pxx_uart.pulses; -} - -void uartInitPcmCrc(uint8_t port) -{ - modulePulsesData[port].pxx_uart.pcmCrc = 0; -} - -void uartPutPcmHead(uint8_t port) -{ - // send 7E, do not CRC - *modulePulsesData[port].pxx_uart.ptr++ = 0x7E; -} - -void uartPutPcmCrc(uint8_t port) -{ - uint16_t pulseValue = modulePulsesData[port].pxx_uart.pcmCrc; - uartPutPcmByte(port, pulseValue >> 8); - uartPutPcmByte(port, pulseValue); -} -#endif - -#if !defined(INTMODULE_USART) || !defined(EXTMODULE_USART) - -#if defined(PPM_PIN_SERIAL) -void pxxPutPcmSerialBit(uint8_t port, uint8_t bit) -{ - modulePulsesData[port].pxx.serialByte >>= 1; - if (bit & 1) { - modulePulsesData[port].pxx.serialByte |= 0x80; - } - if (++modulePulsesData[port].pxx.serialBitCount >= 8) { - *modulePulsesData[port].pxx.ptr++ = modulePulsesData[port].pxx.serialByte; - modulePulsesData[port].pxx.serialBitCount = 0; - } -} - -// 8uS/bit 01 = 0, 001 = 1 -void pxxPutPcmPart(uint8_t port, uint8_t value) -{ - pxxPutPcmSerialBit(port, 0); - if (value) { - pxxPutPcmSerialBit(port, 0); - } - pxxPutPcmSerialBit(port, 1); -} - -void pxxPutPcmTail(uint8_t port) -{ - while (modulePulsesData[port].pxx.serialBitCount != 0) { - pxxPutPcmSerialBit(port, 1); - } -} -#else -void pxxPutPcmPart(uint8_t port, uint8_t value) -{ - pulse_duration_t duration = value ? 47 : 31; - *modulePulsesData[port].pxx.ptr++ = duration; - modulePulsesData[port].pxx.rest -= duration + 1; -} - -void pxxPutPcmTail(uint8_t port) -{ - // rest min value is 18000 - 200 * 48 = 8400 (4.2ms) - *(modulePulsesData[port].pxx.ptr-1) += modulePulsesData[port].pxx.rest; -} -#endif - -void pxxPutPcmBit(uint8_t port, uint8_t bit) -{ - if (bit) { - pxxPutPcmPart(port, 1); - if (++modulePulsesData[port].pxx.pcmOnesCount == 5) { - modulePulsesData[port].pxx.pcmOnesCount = 0; - pxxPutPcmPart(port, 0); // Stuff a 0 bit in - } - } - else { - pxxPutPcmPart(port, 0); - modulePulsesData[port].pxx.pcmOnesCount = 0; - } -} - -void pxxPutPcmByte(uint8_t port, uint8_t byte) -{ - modulePulsesData[port].pxx.pcmCrc = (modulePulsesData[port].pxx.pcmCrc<<8) ^ (CRCTable[((modulePulsesData[port].pxx.pcmCrc>>8)^byte) & 0xFF]); - for (uint8_t i=0; i<8; i++) { - pxxPutPcmBit(port, byte & 0x80); - byte <<= 1; - } -} - -void pxxInitPcmArray(uint8_t port) -{ - modulePulsesData[port].pxx.ptr = modulePulsesData[port].pxx.pulses; -#if defined(PPM_PIN_SERIAL) - modulePulsesData[port].pxx.pcmValue = 0; -#else - modulePulsesData[port].pxx.rest = PXX_PERIOD_HALF_US; -#endif - - modulePulsesData[port].pxx.pcmOnesCount = 0; -} - -void pxxInitPcmCrc(uint8_t port) -{ - modulePulsesData[port].pxx.pcmCrc = 0; -} - -void pxxPutPcmHead(uint8_t port) -{ - // send 7E, do not CRC - // 01111110 - pxxPutPcmPart(port, 0); - pxxPutPcmPart(port, 1); - pxxPutPcmPart(port, 1); - pxxPutPcmPart(port, 1); - pxxPutPcmPart(port, 1); - pxxPutPcmPart(port, 1); - pxxPutPcmPart(port, 1); - pxxPutPcmPart(port, 0); -} - -void pxxPutPcmCrc(uint8_t port) -{ - uint16_t pulseValue = modulePulsesData[port].pxx.pcmCrc; - pxxPutPcmByte(port, pulseValue >> 8); - pxxPutPcmByte(port, pulseValue); -} -#else - // those functions should not be used, a link error will occur if wrong - void pxxInitPcmArray(uint8_t port); - void pxxInitPcmCrc(uint8_t port); - void pxxPutPcmByte(uint8_t port, uint8_t byte); - void pxxPutPcmHead(uint8_t port); - void pxxPutPcmTail(uint8_t port); - void pxxPutPcmCrc(uint8_t port); -#endif - -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) -inline void initPcmArray(uint8_t port) -{ - if (IS_UART_MODULE(port)) - uartInitPcmArray(port); - else - pxxInitPcmArray(port); -} - -inline void initPcmCrc(uint8_t port) -{ - if (IS_UART_MODULE(port)) - uartInitPcmCrc(port); - else - pxxInitPcmCrc(port); -} - -inline void putPcmHead(uint8_t port) -{ - if (IS_UART_MODULE(port)) - uartPutPcmHead(port); - else - pxxPutPcmHead(port); -} - -inline void putPcmByte(uint8_t port, uint8_t byte) -{ - if (IS_UART_MODULE(port)) - uartPutPcmByte(port, byte); - else - pxxPutPcmByte(port, byte); -} - -inline void putPcmCrc(uint8_t port) -{ - if (IS_UART_MODULE(port)) - uartPutPcmCrc(port); - else - pxxPutPcmCrc(port); -} - -inline void putPcmTail(uint8_t port) -{ - if (!IS_UART_MODULE(port)) - pxxPutPcmTail(port); -} -#else -inline void initPcmArray(uint8_t port) -{ - pxxInitPcmArray(port); -} - -inline void initPcmCrc(uint8_t port) -{ - pxxInitPcmCrc(port); -} - -inline void putPcmHead(uint8_t port) -{ - pxxPutPcmHead(port); -} - -inline void putPcmByte(uint8_t port, uint8_t byte) -{ - pxxPutPcmByte(port, byte); -} - -inline void putPcmCrc(uint8_t port) -{ - pxxPutPcmCrc(port); -} - -inline void putPcmTail(uint8_t port) -{ - pxxPutPcmTail(port); -} -#endif - -inline void setupFramePXX(uint8_t port, uint8_t sendUpperChannels) -{ - uint16_t pulseValue=0, pulseValueLow=0; - - initPcmCrc(port); - - /* Sync */ - putPcmHead(port); - - /* Rx Number */ - putPcmByte(port, g_model.header.modelId[port]); - - /* FLAG1 */ - uint8_t flag1 = (g_model.moduleData[port].rfProtocol << 6); - if (moduleFlag[port] == MODULE_BIND) { - flag1 |= (g_eeGeneral.countryCode << 1) | PXX_SEND_BIND; - } - else if (moduleFlag[port] == MODULE_RANGECHECK) { - flag1 |= PXX_SEND_RANGECHECK; - } - else if (g_model.moduleData[port].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[port].failsafeMode != FAILSAFE_RECEIVER) { - if (failsafeCounter[port]-- == 0) { - failsafeCounter[port] = 1000; - flag1 |= PXX_SEND_FAILSAFE; - } - if (failsafeCounter[port] == 0 && g_model.moduleData[port].channelsCount > 0) { - flag1 |= PXX_SEND_FAILSAFE; - } - } - - putPcmByte(port, flag1); - - /* FLAG2 */ - putPcmByte(port, 0); - - /* CHANNELS */ - for (int i=0; i<8; i++) { - if (flag1 & PXX_SEND_FAILSAFE) { - if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) { - pulseValue = (i < sendUpperChannels ? 4095 : 2047); - } - else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) { - pulseValue = (i < sendUpperChannels ? 2048 : 0); - } - else { - if (i < sendUpperChannels) { - int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[8+i]; - if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { - pulseValue = 4095; - } - else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { - pulseValue = 2048; - } - else { - failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER; - pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094); - } - } - else { - int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[i]; - if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { - pulseValue = 2047; - } - else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { - pulseValue = 0; - } - else { - failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER; - pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046); - } - } - } - } - else { - if (i < sendUpperChannels) { - int channel = 8 + g_model.moduleData[port].channelsStart + i; - int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; - pulseValue = limit(2049, (value * 512 / 682) + 3072, 4094); - } - else if (i < sentModuleChannels(port)) { - int channel = g_model.moduleData[port].channelsStart + i; - int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; - pulseValue = limit(1, (value * 512 / 682) + 1024, 2046); - } - else { - pulseValue = 1024; - } - } - - if (i & 1) { - putPcmByte(port, pulseValueLow); // Low byte of channel - putPcmByte(port, ((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels - putPcmByte(port, pulseValue >> 4); // High byte of channel - } - else { - pulseValueLow = pulseValue; - } - } - - uint8_t extra_flags = 0; - -/* Ext. flag (holds antenna selection on Horus internal module, 0x00 otherwise) */ -#if defined(PCBHORUS) || defined(PCBXLITE) - if (port == INTERNAL_MODULE) { - extra_flags |= (g_model.moduleData[port].pxx.external_antenna << 0); - } -#endif - - extra_flags |= (g_model.moduleData[port].pxx.receiver_telem_off << 1); - extra_flags |= (g_model.moduleData[port].pxx.receiver_channel_9_16 << 2); - if (isModuleR9M(port)) { - extra_flags |= (min(g_model.moduleData[port].pxx.power, isModuleR9M_FCC_VARIANT(port) ? (uint8_t)R9M_FCC_POWER_MAX : (uint8_t)R9M_LBT_POWER_MAX) << 3); - if(isModuleR9M_EUPLUS(port)) - extra_flags |= (1 << 6); - } - - // Disable S.PORT if internal module is active - if (IS_TELEMETRY_INTERNAL_MODULE()) { - extra_flags |= (1 << 5); - } - - putPcmByte(port, extra_flags); - - /* CRC */ - putPcmCrc(port); - - /* Sync */ - putPcmHead(port); - - putPcmTail(port); -} - -void setupPulsesPXX(uint8_t port) -{ - initPcmArray(port); - -#if defined(PXX_FREQUENCY_HIGH) - setupFramePXX(port, 0); - if (sentModuleChannels(port) > 8) { - setupFramePXX(port, 8); - } -#else - static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) }; - uint8_t sendUpperChannels = 0; - if (pass[port]++ & 0x01) { - sendUpperChannels = g_model.moduleData[port].channelsCount; - } - setupFramePXX(port, sendUpperChannels); -#endif -} diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 8099d6d56..51110e88b 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -125,11 +125,20 @@ set(FIRMWARE_SRC ${COOS_DIR}/portable/GCC/port.c ${COOS_DIR}/portable/arch.c ) + set(PULSES_SRC ${PULSES_SRC} pulses_arm.cpp ppm_arm.cpp - pxx_arm.cpp + pxx.cpp + pxx1.cpp dsm2_arm.cpp sbus_arm.cpp - ) \ No newline at end of file + ) + +if(PXX2) + set(PULSES_SRC + ${PULSES_SRC} + pxx2.cpp + ) +endif() diff --git a/radio/src/targets/common/arm/stm32/CMakeLists.txt b/radio/src/targets/common/arm/stm32/CMakeLists.txt index ad2dca3d2..0398e2f74 100644 --- a/radio/src/targets/common/arm/stm32/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/CMakeLists.txt @@ -9,6 +9,7 @@ option(USB_SERIAL "Enable USB serial (CDC)" OFF) set(ARCH ARM) set(STM32USB_DIR ${THIRDPARTY_DIR}/STM32_USB-Host-Device_Lib_V2.2.0/Libraries) add_definitions(-DSTM32 -DLUA_INPUTS -DVARIO -DCROSSFIRE) + include_directories(${RADIO_SRC_DIRECTORY}/targets/common/arm/stm32) include_directories(${STM32USB_DIR}/STM32_USB_OTG_Driver/inc) include_directories(${STM32USB_DIR}/STM32_USB_Device_Library/Core/inc) @@ -90,11 +91,13 @@ foreach(FILE ${STM32USB_SRC}) ${STM32USB_DIR}/${FILE} ) endforeach() + set(SRC ${SRC} telemetry/crossfire.cpp io/bootloader_flash.cpp ) + set(PULSES_SRC ${PULSES_SRC} crossfire.cpp diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp index dbefcf170..a930fd227 100755 --- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp @@ -130,8 +130,8 @@ void intmoduleSendNextFrame() DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL; DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR); DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; - DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses); - DMA_InitStructure.DMA_BufferSize = modulePulsesData[INTERNAL_MODULE].pxx_uart.ptr - modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses; + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.getData()); + DMA_InitStructure.DMA_BufferSize = modulePulsesData[INTERNAL_MODULE].pxx_uart.getSize(); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 0818657da..d14f2f706 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -195,8 +195,8 @@ void init_pxx(uint32_t module_index); void disable_pxx(uint32_t module_index); void init_serial(uint32_t module_index, uint32_t baudrate, uint32_t period_half_us); void disable_serial(uint32_t module_index); -void init_crossfire(uint32_t module_index); -void disable_crossfire(uint32_t module_index); +void init_module_timer( uint32_t module_index, uint32_t period, uint8_t state); +void disable_module_timer( uint32_t module_index); // Trainer driver void init_trainer_ppm(void); @@ -526,7 +526,7 @@ int32_t getVolume(void); #define TELEMETRY_FIFO_SIZE 512 void telemetryPortInit(uint32_t baudrate, uint8_t mode); void telemetryPortSetDirectionOutput(void); -void sportSendBuffer(uint8_t * buffer, uint32_t count); +void sportSendBuffer(const uint8_t * buffer, uint32_t count); uint8_t telemetryGetByte(uint8_t * byte); extern uint32_t telemetryErrors; diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 10e86cf58..724c16837 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -34,9 +34,12 @@ void extmoduleStop() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; } -void extmoduleNoneStart() +void extmoduleTimerStart(uint32_t period, uint8_t state) { - EXTERNAL_MODULE_OFF(); + if (state) + EXTERNAL_MODULE_ON(); + else + EXTERNAL_MODULE_OFF(); GPIO_PinAFConfig(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PinSource, 0); @@ -51,8 +54,8 @@ void extmoduleNoneStart() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - EXTMODULE_TIMER->ARR = 36000; // 18mS - EXTMODULE_TIMER->CCR2 = 32000; // Update time + EXTMODULE_TIMER->ARR = (2000 * period); + EXTMODULE_TIMER->CCR2 = (2000 * period) - 1000; EXTMODULE_TIMER->EGR = 1; // Restart EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt @@ -62,6 +65,7 @@ void extmoduleNoneStart() NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); } + void extmodulePpmStart() { EXTERNAL_MODULE_ON(); @@ -209,34 +213,6 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us) } #endif -void extmoduleCrossfireStart() -{ - EXTERNAL_MODULE_ON(); - - GPIO_PinAFConfig(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PinSource, 0); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_TX_GPIO, &GPIO_InitStructure); - GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); // Set high - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - EXTMODULE_TIMER->ARR = (2000 * CROSSFIRE_PERIOD); - EXTMODULE_TIMER->CCR2 = (2000 * CROSSFIRE_PERIOD) - 1000; - EXTMODULE_TIMER->EGR = 1; // Restart - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; - 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); -} - void extmoduleSendNextFrame() { if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { @@ -259,7 +235,7 @@ void extmoduleSendNextFrame() EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA } else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) { - EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].pxx.ptr - 1) - 4000; // 2mS in advance + EXTMODULE_TIMER->CCR2 = modulePulsesData[EXTERNAL_MODULE].pxx.getLast() - 4000; // 2mS in advance EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA #if defined(PCBX10) || PCBREV >= 13 EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; @@ -267,8 +243,8 @@ void extmoduleSendNextFrame() EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; #endif EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); - EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses); - EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.ptr - modulePulsesData[EXTERNAL_MODULE].pxx.pulses; + EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.getData()); + EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.getSize(); EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA } else if (IS_DSM2_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_MULTIMODULE_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_SBUS_PROTOCOL(s_current_protocol[EXTERNAL_MODULE])) { diff --git a/radio/src/targets/horus/pulses_driver.cpp b/radio/src/targets/horus/pulses_driver.cpp index be46b31b8..97305df0b 100644 --- a/radio/src/targets/horus/pulses_driver.cpp +++ b/radio/src/targets/horus/pulses_driver.cpp @@ -26,18 +26,17 @@ void extmoduleStop(void); void intmoduleNoneStart(void); void intmodulePxxStart(void); -void extmoduleNoneStart(void); +void extmoduleTimerStart(uint32_t period, uint8_t state); void extmodulePpmStart(void); void extmodulePxxStart(void); void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us); -void extmoduleCrossfireStart(void); void init_no_pulses(uint32_t port) { if (port == INTERNAL_MODULE) intmoduleNoneStart(); else - extmoduleNoneStart(); + extmoduleTimerStart(18, false); } void disable_no_pulses(uint32_t port) @@ -94,16 +93,17 @@ void disable_serial(uint32_t port) } #endif -void init_crossfire(uint32_t port) +void init_module_timer(uint32_t port, uint32_t period, uint8_t state) { if (port == EXTERNAL_MODULE) { - extmoduleCrossfireStart(); + extmoduleTimerStart(period, state); } } -void disable_crossfire(uint32_t port) +void disable_module_timer(uint32_t port) { if (port == EXTERNAL_MODULE) { extmoduleStop(); } } + diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index 75e31cb81..8541c0742 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -138,7 +138,7 @@ void telemetryPortSetDirectionInput() TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver } -void sportSendBuffer(uint8_t * buffer, uint32_t count) +void sportSendBuffer(const uint8_t * buffer, uint32_t count) { telemetryPortSetDirectionOutput(); diff --git a/radio/src/targets/sky9x/pulses_driver.cpp b/radio/src/targets/sky9x/pulses_driver.cpp index 299684489..02f8d5cf5 100644 --- a/radio/src/targets/sky9x/pulses_driver.cpp +++ b/radio/src/targets/sky9x/pulses_driver.cpp @@ -278,8 +278,8 @@ extern "C" void PWM_IRQHandler(void) else { // Kick off serial output here Ssc * sscptr = SSC; - sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses); - sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.pulses; + sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.getData()); + sscptr->SSC_TCR = modulePulsesData[EXTERNAL_MODULE].pxx.getSize(); sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers } break; diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 87fabf59b..be890a8ad 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -182,14 +182,14 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #endif void init_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port); -void init_ppm( uint32_t module_index ); -void disable_ppm( uint32_t module_index ); -void init_pxx( uint32_t module_index ); -void disable_pxx( uint32_t module_index ); -void init_serial( uint32_t module_index, uint32_t baudrate, uint32_t period ); -void disable_serial( uint32_t module_index ); -void init_crossfire( uint32_t module_index ); -void disable_crossfire( uint32_t module_index ); +void init_ppm( uint32_t module_index); +void disable_ppm( uint32_t module_index); +void init_pxx( uint32_t module_index); +void disable_pxx( uint32_t module_index); +void init_serial( uint32_t module_index, uint32_t baudrate, uint32_t period); +void disable_serial( uint32_t module_index); +void init_module_timer( uint32_t module_index, uint32_t period, uint8_t state); +void disable_module_timer( uint32_t module_index); // Trainer driver #define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE) @@ -565,7 +565,7 @@ void debugPutc(const char c); // Telemetry driver void telemetryPortInit(uint32_t baudrate, uint8_t mode); void telemetryPortSetDirectionOutput(void); -void sportSendBuffer(uint8_t * buffer, uint32_t count); +void sportSendBuffer(const uint8_t * buffer, uint32_t count); uint8_t telemetryGetByte(uint8_t * byte); extern uint32_t telemetryErrors; diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index c18b86e12..522ae7ba0 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -41,11 +41,12 @@ void extmoduleStop() } } -void extmoduleNoneStart() +void extmoduleTimerStart(uint32_t period, uint8_t state) { - if (!IS_TRAINER_EXTERNAL_MODULE()) { + if (state) + EXTERNAL_MODULE_ON(); + else if (!IS_TRAINER_EXTERNAL_MODULE()) EXTERNAL_MODULE_OFF(); - } GPIO_PinAFConfig(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PinSource, 0); @@ -60,8 +61,8 @@ void extmoduleNoneStart() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz - EXTMODULE_TIMER->ARR = 36000; // 18mS - EXTMODULE_TIMER->CCR2 = 32000; // Update time + EXTMODULE_TIMER->ARR = (2000 * period); + EXTMODULE_TIMER->CCR2 = (2000 * period) - 1000; EXTMODULE_TIMER->EGR = 1; // Restart EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt @@ -235,34 +236,6 @@ void extmodulePxxStart() } #endif -void extmoduleCrossfireStart() -{ - EXTERNAL_MODULE_ON(); - - GPIO_PinAFConfig(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PinSource, 0); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_TX_GPIO, &GPIO_InitStructure); - GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); // Set high - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz - EXTMODULE_TIMER->ARR = (2000 * CROSSFIRE_PERIOD); - EXTMODULE_TIMER->CCR2 = (2000 * CROSSFIRE_PERIOD) - 1000; - EXTMODULE_TIMER->EGR = 1; // Restart - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - - NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); -} - void extmoduleSendNextFrame() { if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { @@ -283,8 +256,8 @@ void extmoduleSendNextFrame() DMA_InitStructure.DMA_Channel = EXTMODULE_USART_DMA_CHANNEL; DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&EXTMODULE_USART->DR); DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; - DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx_uart.pulses); - DMA_InitStructure.DMA_BufferSize = modulePulsesData[EXTERNAL_MODULE].pxx_uart.ptr - modulePulsesData[EXTERNAL_MODULE].pxx_uart.pulses; + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx_uart.getData()); + DMA_InitStructure.DMA_BufferSize = modulePulsesData[EXTERNAL_MODULE].pxx_uart.getSize(); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; @@ -300,12 +273,12 @@ void extmoduleSendNextFrame() USART_DMACmd(EXTMODULE_USART, USART_DMAReq_Tx, ENABLE); EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; #else - EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].pxx.ptr - 1) - 4000; // 2mS in advance + EXTMODULE_TIMER->CCR2 = modulePulsesData[EXTERNAL_MODULE].pxx.getLast() - 4000; // 2mS in advance EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); - EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses); - EXTMODULE_TIMER_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.ptr - modulePulsesData[EXTERNAL_MODULE].pxx.pulses; + EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.getData()); + EXTMODULE_TIMER_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.getSize(); EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA #endif } diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index 0f8cf3e43..1999dc796 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -61,12 +61,12 @@ void intmoduleNoneStart() void intmoduleSendNextFrame() { if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) { - INTMODULE_TIMER->CCR2 = *(modulePulsesData[INTERNAL_MODULE].pxx.ptr - 1) - 4000; // 2mS in advance + INTMODULE_TIMER->CCR2 = modulePulsesData[INTERNAL_MODULE].pxx.getLast() - 4000; // 2mS in advance INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR); - INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx.pulses); - INTMODULE_DMA_STREAM->NDTR = modulePulsesData[INTERNAL_MODULE].pxx.ptr - modulePulsesData[INTERNAL_MODULE].pxx.pulses; + INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx.getData()); + INTMODULE_DMA_STREAM->NDTR = modulePulsesData[INTERNAL_MODULE].pxx.getSize(); INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA } #if defined(TARANIS_INTERNAL_PPM) diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index f70a241ed..9b7cfea4d 100644 --- a/radio/src/targets/taranis/pulses_driver.cpp +++ b/radio/src/targets/taranis/pulses_driver.cpp @@ -29,11 +29,11 @@ void intmodulePxxStart(void); void intmodulePpmStart(void); #endif -void extmoduleNoneStart(void); +void extmoduleTimerStart(uint32_t period, uint8_t state); void extmodulePpmStart(void); void extmodulePxxStart(void); void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us); -void extmoduleCrossfireStart(void); + void init_pxx(uint32_t port) { @@ -96,7 +96,7 @@ void init_no_pulses(uint32_t port) if (port == INTERNAL_MODULE) intmoduleNoneStart(); else - extmoduleNoneStart(); + extmoduleTimerStart(18, false); } void disable_no_pulses(uint32_t port) @@ -107,14 +107,14 @@ void disable_no_pulses(uint32_t port) extmoduleStop(); } -void init_crossfire(uint32_t port) +void init_module_timer(uint32_t port, uint32_t period, uint8_t state) { if (port == EXTERNAL_MODULE) { - extmoduleCrossfireStart(); + extmoduleTimerStart(period, state); } } -void disable_crossfire(uint32_t port) +void disable_module_timer(uint32_t port) { if (port == EXTERNAL_MODULE) { extmoduleStop(); diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index fbcfdbd56..f3b58159e 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -89,7 +89,7 @@ void telemetryPortSetDirectionInput() TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver } -void sportSendBuffer(uint8_t * buffer, uint32_t count) +void sportSendBuffer(const uint8_t * buffer, uint32_t count) { telemetryPortSetDirectionOutput(); diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h index bf4e15d6a..e138dcf62 100644 --- a/radio/src/telemetry/frsky.h +++ b/radio/src/telemetry/frsky.h @@ -32,7 +32,13 @@ enum FrSkyDataState { STATE_DATA_XOR, }; +#if defined(PXX2) +#include "io/pxx2.h" +#define FRSKY_SPORT_BAUDRATE PXX2_BAUDRATE +#else #define FRSKY_SPORT_BAUDRATE 57600 +#endif + #define FRSKY_D_BAUDRATE 9600 #define FRSKY_SPORT_PACKET_SIZE 9