From 713402b572f7972267ebce155624bbe0eb2b00c7 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 8 Oct 2018 00:12:53 +0200 Subject: [PATCH 1/9] PXX2 first draft --- radio/src/CMakeLists.txt | 7 +- radio/src/io/pxx2.h | 27 +++ radio/src/myeeprom.h | 8 +- radio/src/pulses/pulses_arm.cpp | 24 ++- radio/src/pulses/pulses_arm.h | 4 +- radio/src/pulses/pxx.h | 23 +++ radio/src/pulses/pxx2.cpp | 184 ++++++++++++++++++ radio/src/pulses/pxx2.h | 21 ++ radio/src/pulses/pxx_arm.cpp | 5 +- .../targets/common/arm/stm32/CMakeLists.txt | 10 + radio/src/targets/taranis/board.h | 18 +- radio/src/targets/taranis/pulses_driver.cpp | 9 + 12 files changed, 322 insertions(+), 18 deletions(-) create mode 100644 radio/src/io/pxx2.h create mode 100644 radio/src/pulses/pxx.h create mode 100644 radio/src/pulses/pxx2.cpp create mode 100644 radio/src/pulses/pxx2.h 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 c8a2d9af0..30767b1cb 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..14543ebd7 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; @@ -146,6 +150,12 @@ void setupPulses(uint8_t port) break; #endif +#if defined(PXX2) + case PROTO_PXX2: + disable_pxx2(port); + break; +#endif + #if defined(MULTIMODULE) case PROTO_MULTIMODULE: #endif @@ -208,6 +218,16 @@ void setupPulses(uint8_t port) break; #endif +#if defined(PXX2) + case PROTO_PXX2: + if (telemetryProtocol == PROTOCOL_FRSKY_SPORT && !init_needed) { + createPXX2ChannelsFrame(port); + sportSendBuffer(modulePulsesData[port].pxx_uart.pulses, modulePulsesData[port].pxx_uart.ptr - modulePulsesData[port].pxx_uart.pulses); + } + scheduleNextMixerCalculation(port, PXX2_PERIOD); + break; +#endif + #if defined(MULTIMODULE) case PROTO_MULTIMODULE: setupPulsesMultimodule(port); diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index e726f8e63..92841f311 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -86,7 +86,7 @@ PACK(struct Dsm2TimerPulsesData { }); #endif -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) +#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) || defined(PXX2) PACK(struct PxxUartPulsesData { uint8_t pulses[64]; uint8_t * ptr; @@ -131,7 +131,7 @@ PACK(struct CrossfirePulsesData { }); union ModulePulsesData { -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) +#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) || defined(PXX2) PxxUartPulsesData pxx_uart; #endif #if defined(PPM_PIN_SERIAL) diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h new file mode 100644 index 000000000..15ac96784 --- /dev/null +++ b/radio/src/pulses/pxx.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +#define PXX_SEND_BIND 0x01 +#define PXX_SEND_FAILSAFE (1 << 4) +#define PXX_SEND_RANGECHECK (1 << 5) diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp new file mode 100644 index 000000000..93df83ec1 --- /dev/null +++ b/radio/src/pulses/pxx2.cpp @@ -0,0 +1,184 @@ +/* + * 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/pxx.h" + +void uartInitPcmArray(uint8_t port) +{ + modulePulsesData[port].pxx_uart.pcmCrc = 0; + modulePulsesData[port].pxx_uart.ptr = modulePulsesData[port].pxx_uart.pulses; +} + +void putPXX2Byte(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]); + *modulePulsesData[port].pxx_uart.ptr++ = byte; +} + +void createPXX2ChannelsFrame(uint8_t port) +{ + uint16_t pulseValue=0, pulseValueLow=0; + + static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) }; + uint8_t sendUpperChannels = 0; + if (pass[port]++ & 0x01) { + sendUpperChannels = g_model.moduleData[port].channelsCount; + } + + uartInitPcmArray(port); + + // Model ID + putPXX2Byte(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; + } + } + putPXX2Byte(port, flag1); + + // Flag2 + putPXX2Byte(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) { + putPXX2Byte(port, pulseValueLow); // Low byte of channel + putPXX2Byte(port, ((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels + putPXX2Byte(port, pulseValue >> 4); // High byte of channel + } + else { + pulseValueLow = pulseValue; + } + } + + // 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); + } + putPXX2Byte(port, extra_flags); + + // Flag3, reserved + putPXX2Byte(port, 0); + +#if defined(LUA) + if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) { + // CMD/Resp + putPXX2Byte(port, 1); + // primID (1 byte) + dataID (2 bytes) + value (4 bytes) + for (uint8_t i=0; i<7; i++) { + putPXX2Byte(port, outputTelemetryBuffer[i]); + } + outputTelemetryBufferTrigger = 0x00; + outputTelemetryBufferSize = 0; + } + else { + // CMD/Resp + putPXX2Byte(port, 0); + } +#else + // CMD/Resp + putPXX2Byte(port, 0); +#endif + + // CRC + putPXX2Byte(port, modulePulsesData[port].pxx_uart.pcmCrc); // 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..fc5f8116a --- /dev/null +++ b/radio/src/pulses/pxx2.h @@ -0,0 +1,21 @@ +/* + * 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. + */ + +void createPXX2ChannelsFrame(uint8_t port); diff --git a/radio/src/pulses/pxx_arm.cpp b/radio/src/pulses/pxx_arm.cpp index 1418df9a4..8d19a1642 100644 --- a/radio/src/pulses/pxx_arm.cpp +++ b/radio/src/pulses/pxx_arm.cpp @@ -19,10 +19,7 @@ */ #include "opentx.h" - -#define PXX_SEND_BIND 0x01 -#define PXX_SEND_FAILSAFE (1 << 4) -#define PXX_SEND_RANGECHECK (1 << 5) +#include "pulses/pxx.h" const uint16_t CRCTable[]= { diff --git a/radio/src/targets/common/arm/stm32/CMakeLists.txt b/radio/src/targets/common/arm/stm32/CMakeLists.txt index ad2dca3d2..feedb073f 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,12 +91,21 @@ 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 ) + +if(PXX2) + set(PULSES_SRC + ${PULSES_SRC} + pxx2.cpp + ) +endif() diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 87fabf59b..235afc1d4 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -182,14 +182,16 @@ 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_crossfire( uint32_t module_index); +void disable_crossfire( uint32_t module_index); +void init_pxx2( uint32_t module_index); +void disable_pxx2( uint32_t module_index); // Trainer driver #define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE) diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index f70a241ed..ad7931bc1 100644 --- a/radio/src/targets/taranis/pulses_driver.cpp +++ b/radio/src/targets/taranis/pulses_driver.cpp @@ -120,3 +120,12 @@ void disable_crossfire(uint32_t port) extmoduleStop(); } } + +void disable_pxx2(uint32_t port) +{ + if (port == EXTERNAL_MODULE) { + extmoduleStop(); + } +} + + From f798bbfcc7c362891f4e807d060503bcc048eafb Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 8 Oct 2018 08:22:20 +0200 Subject: [PATCH 2/9] Wrong baudrate chosen for PXX2 on setup --- radio/src/telemetry/frsky.h | 6 ++++++ 1 file changed, 6 insertions(+) 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 From 946f66b1286f935f58a71e9576f14ef4bcf31eab Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 9 Oct 2018 07:57:58 +0200 Subject: [PATCH 3/9] Pulses refactoring ... WIP --- radio/src/pulses/pulses_arm.cpp | 4 +- radio/src/pulses/pulses_arm.h | 12 +- radio/src/pulses/pxx.cpp | 230 +++++++++ radio/src/pulses/pxx.h | 221 +++++++++ radio/src/pulses/pxx2.cpp | 141 +----- radio/src/pulses/pxx2.h | 54 ++- radio/src/pulses/pxx_arm.cpp | 450 ------------------ radio/src/targets/common/arm/CMakeLists.txt | 2 +- radio/src/targets/horus/board.h | 2 +- radio/src/targets/horus/telemetry_driver.cpp | 2 +- radio/src/targets/taranis/board.h | 2 +- .../src/targets/taranis/telemetry_driver.cpp | 2 +- 12 files changed, 536 insertions(+), 586 deletions(-) create mode 100644 radio/src/pulses/pxx.cpp delete mode 100644 radio/src/pulses/pxx_arm.cpp diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index 14543ebd7..6ade90621 100755 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -221,8 +221,8 @@ void setupPulses(uint8_t port) #if defined(PXX2) case PROTO_PXX2: if (telemetryProtocol == PROTOCOL_FRSKY_SPORT && !init_needed) { - createPXX2ChannelsFrame(port); - sportSendBuffer(modulePulsesData[port].pxx_uart.pulses, modulePulsesData[port].pxx_uart.ptr - modulePulsesData[port].pxx_uart.pulses); + modulePulsesData[port].pxx2.setupFrame(port); + sportSendBuffer(modulePulsesData[port].pxx2.getData(), modulePulsesData[port].pxx2.getSize()); } scheduleNextMixerCalculation(port, PXX2_PERIOD); break; diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index 92841f311..aab6832bb 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -54,8 +54,6 @@ template struct PpmPulsesData { #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]; @@ -125,13 +123,17 @@ PACK(struct PxxTimerPulsesData { }); #endif +#if !defined(BOOT) +#include "pulses/pxx2.h" +#endif + #define CROSSFIRE_FRAME_MAXLEN 64 PACK(struct CrossfirePulsesData { uint8_t pulses[CROSSFIRE_FRAME_MAXLEN]; }); union ModulePulsesData { -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) || defined(PXX2) +#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) PxxUartPulsesData pxx_uart; #endif #if defined(PPM_PIN_SERIAL) @@ -140,6 +142,10 @@ union ModulePulsesData { PxxTimerPulsesData pxx; #endif +#if defined(PXX2) && !defined(BOOT) + Pxx2Pulses pxx2; +#endif + #if defined(PPM_PIN_SERIAL) Dsm2SerialPulsesData dsm2; #else diff --git a/radio/src/pulses/pxx.cpp b/radio/src/pulses/pxx.cpp new file mode 100644 index 000000000..5d491c5dd --- /dev/null +++ b/radio/src/pulses/pxx.cpp @@ -0,0 +1,230 @@ +/* + * 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/pxx.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 StandardPxxPulses::setup8ChannelsFrame(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(); + + // CRC + addCrc(); + + // Sync = HEAD + addHead(); + + // Tail + PxxTransport::addTail(); +} + +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 +void StandardPxxPulses::setupFrame(uint8_t port) +{ + PxxPulses::initFrame(); + +#if defined(PXX_FREQUENCY_HIGH) + setup8ChannelsFrame(port, 0); + if (sentModuleChannels(port) > 8) { + setup8ChannelsFrame(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; + } + setup8ChannelsFrame(port, sendUpperChannels); +#endif +} diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index 15ac96784..5f6362e2d 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -18,6 +18,227 @@ * GNU General Public License for more details. */ +#ifndef _PULSES_PXX_H_ +#define _PULSES_PXX_H_ + +#include + #define PXX_SEND_BIND 0x01 #define PXX_SEND_FAILSAFE (1 << 4) #define PXX_SEND_RANGECHECK (1 << 5) + +class PxxCrcMixin { + protected: + void initCrc() + { + crc = 0; + } + + void addToCrc(uint8_t byte) + { + crc = (crc << 8) ^ (CRCTable[((crc >> 8) ^ byte) & 0xFF]); + } + + uint8_t crc; + static const uint16_t CRCTable[]; +}; + + +class SerialPxxBitTransport { + protected: + uint8_t data[64]; + uint8_t * ptr; + uint8_t byte; + uint8_t bits_count; + uint8_t padding[2]; + + void initFrame() + { + ptr = data; + 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); + } + } +}; + +// TODO elsewhere !!! + +#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 + +#define PXX_PERIOD_HALF_US (PXX_PERIOD * 2000) + +class PwmPxxBitTransport { + protected: + pulse_duration_t pulses[200]; + pulse_duration_t * ptr; + uint16_t rest; + uint8_t padding[2]; + + void initFrame() + { + ptr = pulses; + rest = PXX_PERIOD_HALF_US; + } + + void addPart(uint8_t value) + { + pulse_duration_t duration = value ? 47 : 31; + *ptr++ = duration; + rest -= duration + 1; + } + + void addTail(uint8_t port) + { + // rest min value is 18000 - 200 * 48 = 8400 (4.2ms) + *(ptr - 1) += rest; + } +}; + +template +class StandardPxxTransport: public PxxCrcMixin, public BitTransport { + protected: + uint8_t ones_count; + uint8_t padding[3]; + + 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; + } + } + + void initFrame() + { + ones_count = 0; + } +}; + +class UartPxxTransport: public PxxCrcMixin { + protected: + uint8_t data[64]; + uint8_t * ptr; + + void initFrame() + { + ptr = data; + } + + void addByte(uint8_t byte) + { + PxxCrcMixin::addToCrc(byte); + addWithByteStuffing(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); +}; + +typedef PxxPulses UartPxxPulses; + +template +class StandardPxxPulses: public PxxPulses +{ + public: + void setupFrame(uint8_t port); + + protected: + void addHead() + { + // send 7E, do not CRC + PxxTransport::addByteWithoutCrc(0x7E); + } + + void addCrc() + { + addByteWithoutCrc(PxxCrcMixin::crc >> 8); + addByteWithoutCrc(PxxCrcMixin::crc); + } + + void setup8ChannelsFrame(uint8_t port, uint8_t sendUpperChannels); +}; + +typedef StandardPxxPulses> PwmPxxPxxPulses; + + +#endif diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index 93df83ec1..d7d32b588 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -19,23 +19,12 @@ */ #include "opentx.h" -#include "pulses/pxx.h" +#include "pulses/pxx2.h" -void uartInitPcmArray(uint8_t port) +void Pxx2Pulses::setupFrame(uint8_t port) { - modulePulsesData[port].pxx_uart.pcmCrc = 0; - modulePulsesData[port].pxx_uart.ptr = modulePulsesData[port].pxx_uart.pulses; -} - -void putPXX2Byte(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]); - *modulePulsesData[port].pxx_uart.ptr++ = byte; -} - -void createPXX2ChannelsFrame(uint8_t port) -{ - uint16_t pulseValue=0, pulseValueLow=0; + initFrame(); + initCrc(); static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) }; uint8_t sendUpperChannels = 0; @@ -43,142 +32,44 @@ void createPXX2ChannelsFrame(uint8_t port) sendUpperChannels = g_model.moduleData[port].channelsCount; } - uartInitPcmArray(port); - // Model ID - putPXX2Byte(port, g_model.header.modelId[port]); + addByte(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; - } - } - putPXX2Byte(port, flag1); + uint8_t flag1 = addFlag1(port); // Flag2 - putPXX2Byte(port, 0); + addByte(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; - } - } + addChannels(port, flag1 & PXX_SEND_FAILSAFE, sendUpperChannels); - if (i & 1) { - putPXX2Byte(port, pulseValueLow); // Low byte of channel - putPXX2Byte(port, ((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels - putPXX2Byte(port, pulseValue >> 4); // High byte of channel - } - else { - pulseValueLow = pulseValue; - } - } - - // 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); - } - putPXX2Byte(port, extra_flags); + // Extra flags + addExtraFlags(port); // Flag3, reserved - putPXX2Byte(port, 0); + addByte(0); #if defined(LUA) if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) { // CMD/Resp - putPXX2Byte(port, 1); + addByte(1); // primID (1 byte) + dataID (2 bytes) + value (4 bytes) for (uint8_t i=0; i<7; i++) { - putPXX2Byte(port, outputTelemetryBuffer[i]); + addByte(outputTelemetryBuffer[i]); } outputTelemetryBufferTrigger = 0x00; outputTelemetryBufferSize = 0; } else { // CMD/Resp - putPXX2Byte(port, 0); + addByte(0); } #else // CMD/Resp - putPXX2Byte(port, 0); + addByte(0); #endif // CRC - putPXX2Byte(port, modulePulsesData[port].pxx_uart.pcmCrc); // TODO need to check the CRC chosen algorithm + addByte(crc); // TODO need to check the CRC chosen algorithm } - diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index fc5f8116a..ce2a83f2e 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -18,4 +18,56 @@ * GNU General Public License for more details. */ -void createPXX2ChannelsFrame(uint8_t port); +#ifndef _PULSES_PXX2_H_ +#define _PULSES_PXX2_H_ + +#include "pulses/pxx.h" + +class Pxx2Transport: public PxxCrcMixin { + protected: + uint8_t data[64]; + uint8_t * ptr; + + void initFrame() + { + ptr = data; + } + + void addByte(uint8_t byte) + { + PxxCrcMixin::addToCrc(byte); + *ptr++ = byte; + } + + void addTail() + { + // nothing + } +}; + + +class Pxx2Pulses: public PxxPulses { + public: + void setupFrame(uint8_t port); + + const uint8_t * getData() + { + return data; + } + + uint8_t getSize() + { + return ptr - data; + } + + protected: + uint8_t data[64]; + uint8_t * ptr; + + void initFrame() + { + ptr = data; + } +}; + +#endif diff --git a/radio/src/pulses/pxx_arm.cpp b/radio/src/pulses/pxx_arm.cpp deleted file mode 100644 index 8d19a1642..000000000 --- a/radio/src/pulses/pxx_arm.cpp +++ /dev/null @@ -1,450 +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" -#include "pulses/pxx.h" - -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..0d552c781 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -129,7 +129,7 @@ set(PULSES_SRC ${PULSES_SRC} pulses_arm.cpp ppm_arm.cpp - pxx_arm.cpp + pxx.cpp dsm2_arm.cpp sbus_arm.cpp ) \ No newline at end of file diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 0818657da..cc513c449 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -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/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/taranis/board.h b/radio/src/targets/taranis/board.h index 235afc1d4..004f55648 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -567,7 +567,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/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(); From 62dcd6ac5e2e56fc14e736d28bb61a3ea3eaa831 Mon Sep 17 00:00:00 2001 From: bsongis Date: Tue, 9 Oct 2018 12:47:22 +0200 Subject: [PATCH 4/9] Refactoring continued --- radio/src/pulses/pulses_arm.cpp | 2 +- radio/src/pulses/pulses_arm.h | 22 ++--- radio/src/pulses/pulses_common.h | 65 ++++++++++++++ radio/src/pulses/pxx.cpp | 57 +----------- radio/src/pulses/pxx.h | 90 ++++++------------- radio/src/pulses/pxx1.cpp | 77 ++++++++++++++++ radio/src/pulses/pxx1.h | 52 +++++++++++ radio/src/pulses/pxx2.h | 23 +---- .../targets/common/arm/stm32/CMakeLists.txt | 6 ++ .../src/targets/taranis/extmodule_driver.cpp | 6 +- .../taranis/intmodule_pulses_driver.cpp | 6 +- 11 files changed, 246 insertions(+), 160 deletions(-) create mode 100644 radio/src/pulses/pulses_common.h create mode 100644 radio/src/pulses/pxx1.cpp create mode 100644 radio/src/pulses/pxx1.h diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index 6ade90621..f88bf37ab 100755 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -177,7 +177,7 @@ void setupPulses(uint8_t port) // Set up output data here switch (required_protocol) { case PROTO_PXX: - setupPulsesPXX(port); + modulePulsesData[port].pxx.setupFrame(port); scheduleNextMixerCalculation(port, PXX_PERIOD); break; diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index aab6832bb..5fd2619a8 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -44,16 +44,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 - #if defined(PPM_PIN_SERIAL) PACK(struct PxxSerialPulsesData { uint8_t pulses[64]; @@ -125,6 +115,7 @@ PACK(struct PxxTimerPulsesData { #if !defined(BOOT) #include "pulses/pxx2.h" +#include "pulses/pxx1.h" #endif #define CROSSFIRE_FRAME_MAXLEN 64 @@ -133,13 +124,14 @@ PACK(struct CrossfirePulsesData { }); union ModulePulsesData { -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) - PxxUartPulsesData pxx_uart; +#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) && !defined(BOOT) + UartPxxPulses pxx_uart; #endif -#if defined(PPM_PIN_SERIAL) - PxxSerialPulsesData pxx; +#if defined(BOOT) +#elif defined(PPM_PIN_SERIAL) + SerialPxxPulses pxx; #elif !defined(INTMODULE_USART) || !defined(EXTMODULE_USART) - PxxTimerPulsesData pxx; + PwmPxxPulses pxx; #endif #if defined(PXX2) && !defined(BOOT) 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 index 5d491c5dd..69257831a 100644 --- a/radio/src/pulses/pxx.cpp +++ b/radio/src/pulses/pxx.cpp @@ -19,7 +19,8 @@ */ #include "opentx.h" -#include "pulses/pxx.h" +#include "pulses/pxx1.h" +#include "pulses/pxx2.h" const uint16_t PxxCrcMixin::CRCTable[] = { 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, @@ -56,39 +57,6 @@ const uint16_t PxxCrcMixin::CRCTable[] = { 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; -template -void StandardPxxPulses::setup8ChannelsFrame(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(); - - // CRC - addCrc(); - - // Sync = HEAD - addHead(); - - // Tail - PxxTransport::addTail(); -} - template void PxxPulses::addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels) { @@ -209,22 +177,5 @@ void PxxPulses::addExtraFlags(uint8_t port) PxxTransport::addByte(extra_flags); } -template -void StandardPxxPulses::setupFrame(uint8_t port) -{ - PxxPulses::initFrame(); - -#if defined(PXX_FREQUENCY_HIGH) - setup8ChannelsFrame(port, 0); - if (sentModuleChannels(port) > 8) { - setup8ChannelsFrame(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; - } - setup8ChannelsFrame(port, sendUpperChannels); -#endif -} +template class PxxPulses >; +template class PxxPulses; diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index 5f6362e2d..ce96cf5d6 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -21,12 +21,24 @@ #ifndef _PULSES_PXX_H_ #define _PULSES_PXX_H_ -#include +#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 + +#define PXX_PERIOD_HALF_US (PXX_PERIOD * 2000) + class PxxCrcMixin { protected: void initCrc() @@ -43,18 +55,16 @@ class PxxCrcMixin { static const uint16_t CRCTable[]; }; - -class SerialPxxBitTransport { +// Used by the Sky9x family boards +class SerialPxxBitTransport: public DataBuffer { protected: - uint8_t data[64]; - uint8_t * ptr; uint8_t byte; uint8_t bits_count; uint8_t padding[2]; void initFrame() { - ptr = data; + initBuffer(); byte = 0; bits_count = 0; } @@ -89,28 +99,14 @@ class SerialPxxBitTransport { } }; -// TODO elsewhere !!! - -#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 - -#define PXX_PERIOD_HALF_US (PXX_PERIOD * 2000) - -class PwmPxxBitTransport { +class PwmPxxBitTransport: public PulsesBuffer { protected: - pulse_duration_t pulses[200]; - pulse_duration_t * ptr; uint16_t rest; uint8_t padding[2]; void initFrame() { - ptr = pulses; + initBuffer(); rest = PXX_PERIOD_HALF_US; } @@ -121,7 +117,7 @@ class PwmPxxBitTransport { rest -= duration + 1; } - void addTail(uint8_t port) + void addTail() { // rest min value is 18000 - 200 * 48 = 8400 (4.2ms) *(ptr - 1) += rest; @@ -134,6 +130,12 @@ class StandardPxxTransport: public PxxCrcMixin, public BitTransport { uint8_t ones_count; uint8_t padding[3]; + void initFrame() + { + BitTransport::initBuffer(); + ones_count = 0; + } + void addByte(uint8_t byte) { PxxCrcMixin::addToCrc(byte); @@ -162,23 +164,10 @@ class StandardPxxTransport: public PxxCrcMixin, public BitTransport { ones_count = 0; } } - - void initFrame() - { - ones_count = 0; - } }; -class UartPxxTransport: public PxxCrcMixin { +class UartPxxTransport: public DataBuffer, public PxxCrcMixin { protected: - uint8_t data[64]; - uint8_t * ptr; - - void initFrame() - { - ptr = data; - } - void addByte(uint8_t byte) { PxxCrcMixin::addToCrc(byte); @@ -214,31 +203,4 @@ class PxxPulses: public PxxTransport { void addExtraFlags(uint8_t port); }; -typedef PxxPulses UartPxxPulses; - -template -class StandardPxxPulses: public PxxPulses -{ - public: - void setupFrame(uint8_t port); - - protected: - void addHead() - { - // send 7E, do not CRC - PxxTransport::addByteWithoutCrc(0x7E); - } - - void addCrc() - { - addByteWithoutCrc(PxxCrcMixin::crc >> 8); - addByteWithoutCrc(PxxCrcMixin::crc); - } - - void setup8ChannelsFrame(uint8_t port, uint8_t sendUpperChannels); -}; - -typedef StandardPxxPulses> PwmPxxPxxPulses; - - #endif diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp new file mode 100644 index 000000000..7dbebe84f --- /dev/null +++ b/radio/src/pulses/pxx1.cpp @@ -0,0 +1,77 @@ +/* + * 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) +{ + PxxPulses::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 >; 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.h b/radio/src/pulses/pxx2.h index ce2a83f2e..bef2eea98 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -21,18 +21,10 @@ #ifndef _PULSES_PXX2_H_ #define _PULSES_PXX2_H_ -#include "pulses/pxx.h" +#include "./pxx.h" -class Pxx2Transport: public PxxCrcMixin { +class Pxx2Transport: public DataBuffer, public PxxCrcMixin { protected: - uint8_t data[64]; - uint8_t * ptr; - - void initFrame() - { - ptr = data; - } - void addByte(uint8_t byte) { PxxCrcMixin::addToCrc(byte); @@ -45,21 +37,10 @@ class Pxx2Transport: public PxxCrcMixin { } }; - class Pxx2Pulses: public PxxPulses { public: void setupFrame(uint8_t port); - const uint8_t * getData() - { - return data; - } - - uint8_t getSize() - { - return ptr - data; - } - protected: uint8_t data[64]; uint8_t * ptr; diff --git a/radio/src/targets/common/arm/stm32/CMakeLists.txt b/radio/src/targets/common/arm/stm32/CMakeLists.txt index feedb073f..9dbabfc41 100644 --- a/radio/src/targets/common/arm/stm32/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/CMakeLists.txt @@ -103,6 +103,12 @@ set(PULSES_SRC crossfire.cpp ) +set(PULSES_SRC + ${PULSES_SRC} + pxx1.cpp + ) + + if(PXX2) set(PULSES_SRC ${PULSES_SRC} diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index c18b86e12..6cf69c54d 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -300,12 +300,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) From 67b145b22e0398688c7c62b2859952598e8a1779 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 9 Oct 2018 22:56:51 +0200 Subject: [PATCH 5/9] Compilation fixes --- radio/src/pulses/pulses_arm.cpp | 16 ++++- radio/src/pulses/pulses_arm.h | 64 ++----------------- radio/src/pulses/pxx.cpp | 2 + radio/src/pulses/pxx.h | 21 ++++-- radio/src/pulses/pxx1.cpp | 4 +- radio/src/pulses/pxx2.h | 2 +- radio/src/targets/common/arm/CMakeLists.txt | 11 +++- .../targets/common/arm/stm32/CMakeLists.txt | 13 ---- .../arm/stm32/intmodule_serial_driver.cpp | 4 +- radio/src/targets/horus/board.h | 1 + radio/src/targets/horus/extmodule_driver.cpp | 6 +- radio/src/targets/horus/pulses_driver.cpp | 8 +++ radio/src/targets/sky9x/pulses_driver.cpp | 4 +- .../src/targets/taranis/extmodule_driver.cpp | 4 +- 14 files changed, 72 insertions(+), 88 deletions(-) diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index f88bf37ab..0b226ce20 100755 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -122,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; @@ -177,7 +191,7 @@ void setupPulses(uint8_t port) // Set up output data here switch (required_protocol) { case PROTO_PXX: - modulePulsesData[port].pxx.setupFrame(port); + setupPulsesPXX(port); scheduleNextMixerCalculation(port, PXX_PERIOD); break; diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index 5fd2619a8..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,18 +39,6 @@ template struct PpmPulsesData { T * ptr; }; -#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]; @@ -74,15 +57,6 @@ PACK(struct Dsm2TimerPulsesData { }); #endif -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) || defined(PXX2) -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 @@ -93,48 +67,22 @@ 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 - -#if !defined(BOOT) -#include "pulses/pxx2.h" -#include "pulses/pxx1.h" -#endif - #define CROSSFIRE_FRAME_MAXLEN 64 PACK(struct CrossfirePulsesData { uint8_t pulses[CROSSFIRE_FRAME_MAXLEN]; }); union ModulePulsesData { -#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) && !defined(BOOT) +#if defined(INTMODULE_USART) || defined(EXTMODULE_USART) UartPxxPulses pxx_uart; #endif -#if defined(BOOT) -#elif defined(PPM_PIN_SERIAL) +#if defined(PPM_PIN_SERIAL) SerialPxxPulses pxx; #elif !defined(INTMODULE_USART) || !defined(EXTMODULE_USART) PwmPxxPulses pxx; #endif -#if defined(PXX2) && !defined(BOOT) +#if defined(PXX2) Pxx2Pulses pxx2; #endif diff --git a/radio/src/pulses/pxx.cpp b/radio/src/pulses/pxx.cpp index 69257831a..19a547ac7 100644 --- a/radio/src/pulses/pxx.cpp +++ b/radio/src/pulses/pxx.cpp @@ -178,4 +178,6 @@ void PxxPulses::addExtraFlags(uint8_t port) } 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 index ce96cf5d6..c9c0a3fca 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -37,6 +37,17 @@ #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 { @@ -60,7 +71,6 @@ class SerialPxxBitTransport: public DataBuffer { protected: uint8_t byte; uint8_t bits_count; - uint8_t padding[2]; void initFrame() { @@ -102,7 +112,6 @@ class SerialPxxBitTransport: public DataBuffer { class PwmPxxBitTransport: public PulsesBuffer { protected: uint16_t rest; - uint8_t padding[2]; void initFrame() { @@ -125,10 +134,9 @@ class PwmPxxBitTransport: public PulsesBuffer { }; template -class StandardPxxTransport: public PxxCrcMixin, public BitTransport { +class StandardPxxTransport: public BitTransport, public PxxCrcMixin { protected: uint8_t ones_count; - uint8_t padding[3]; void initFrame() { @@ -174,6 +182,11 @@ class UartPxxTransport: public DataBuffer, public PxxCrcMixin { addWithByteStuffing(byte); } + void addByteWithoutCrc(uint8_t byte) + { + *ptr++ = byte; + } + void addWithByteStuffing(uint8_t byte) { if (0x7E == byte) { diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp index 7dbebe84f..0981184f3 100644 --- a/radio/src/pulses/pxx1.cpp +++ b/radio/src/pulses/pxx1.cpp @@ -57,7 +57,7 @@ void Pxx1Pulses::add8ChannelsFrame(uint8_t port, uint8_t sendUpper template void Pxx1Pulses::setupFrame(uint8_t port) { - PxxPulses::initFrame(); + PxxTransport::initBuffer(); #if defined(PXX_FREQUENCY_HIGH) add8ChannelsFrame(port, 0); @@ -75,3 +75,5 @@ void Pxx1Pulses::setupFrame(uint8_t port) } template class Pxx1Pulses >; +template class Pxx1Pulses >; +template class Pxx1Pulses; diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index bef2eea98..1f1384a62 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -47,7 +47,7 @@ class Pxx2Pulses: public PxxPulses { void initFrame() { - ptr = data; + Pxx2Transport::initBuffer(); } }; diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 0d552c781..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.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 9dbabfc41..0398e2f74 100644 --- a/radio/src/targets/common/arm/stm32/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/CMakeLists.txt @@ -102,16 +102,3 @@ set(PULSES_SRC ${PULSES_SRC} crossfire.cpp ) - -set(PULSES_SRC - ${PULSES_SRC} - pxx1.cpp - ) - - -if(PXX2) - set(PULSES_SRC - ${PULSES_SRC} - pxx2.cpp - ) -endif() 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 cc513c449..b793280cf 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -197,6 +197,7 @@ void init_serial(uint32_t module_index, uint32_t baudrate, uint32_t period_half_ void disable_serial(uint32_t module_index); void init_crossfire(uint32_t module_index); void disable_crossfire(uint32_t module_index); +void disable_pxx2(uint32_t module_index); // Trainer driver void init_trainer_ppm(void); diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 10e86cf58..4b0240763 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -259,7 +259,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 +267,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..f3e8e7a66 100644 --- a/radio/src/targets/horus/pulses_driver.cpp +++ b/radio/src/targets/horus/pulses_driver.cpp @@ -107,3 +107,11 @@ void disable_crossfire(uint32_t port) extmoduleStop(); } } + + +void disable_pxx2(uint32_t port) +{ + if (port == EXTERNAL_MODULE) { + extmoduleStop(); + } +} 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/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 6cf69c54d..4d1799ce6 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -283,8 +283,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; From 2823fe9a12d3680aeab5c1285039bd46378dc959 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 10 Oct 2018 08:49:58 +0200 Subject: [PATCH 6/9] PXX2 init was not called --- radio/src/pulses/pulses_arm.cpp | 12 ++++-- radio/src/targets/horus/board.h | 5 +-- radio/src/targets/horus/extmodule_driver.cpp | 40 ++++--------------- radio/src/targets/horus/pulses_driver.cpp | 18 +++------ radio/src/targets/taranis/board.h | 6 +-- .../src/targets/taranis/extmodule_driver.cpp | 39 +++--------------- radio/src/targets/taranis/pulses_driver.cpp | 21 +++------- 7 files changed, 38 insertions(+), 103 deletions(-) diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index 0b226ce20..f91a36194 100755 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -160,13 +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_pxx2(port); + disable_module_timer(port); break; #endif @@ -277,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/targets/horus/board.h b/radio/src/targets/horus/board.h index b793280cf..d14f2f706 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -195,9 +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 disable_pxx2(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); diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 4b0240763..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) { diff --git a/radio/src/targets/horus/pulses_driver.cpp b/radio/src/targets/horus/pulses_driver.cpp index f3e8e7a66..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,24 +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(); } } - -void disable_pxx2(uint32_t port) -{ - if (port == EXTERNAL_MODULE) { - extmoduleStop(); - } -} diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 004f55648..be890a8ad 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -188,10 +188,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); void disable_serial( uint32_t module_index); -void init_crossfire( uint32_t module_index); -void disable_crossfire( uint32_t module_index); -void init_pxx2( uint32_t module_index); -void disable_pxx2( 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) diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 4d1799ce6..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) { diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index ad7931bc1..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,25 +107,16 @@ 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(); } } - -void disable_pxx2(uint32_t port) -{ - if (port == EXTERNAL_MODULE) { - extmoduleStop(); - } -} - - From fd4b309e0b98ffe1f73ce51bc687e46ca854f9b2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 10 Oct 2018 09:47:34 +0200 Subject: [PATCH 7/9] PXX2 uses S.PORT CRC algorithm --- radio/src/pulses/pxx2.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index 1f1384a62..939d0204d 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -23,11 +23,29 @@ #include "./pxx.h" -class Pxx2Transport: public DataBuffer, public PxxCrcMixin { +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) { - PxxCrcMixin::addToCrc(byte); + SportCrcMixin::addToCrc(byte); *ptr++ = byte; } From bbfa94151f6bfc143b914fee0d73f7a008d6f928 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 10 Oct 2018 09:49:25 +0200 Subject: [PATCH 8/9] Regular PXX will need to be checked --- radio/src/pulses/pxx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index c9c0a3fca..aa381c9a9 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -62,7 +62,7 @@ class PxxCrcMixin { crc = (crc << 8) ^ (CRCTable[((crc >> 8) ^ byte) & 0xFF]); } - uint8_t crc; + uint16_t crc; static const uint16_t CRCTable[]; }; From 9d93d88a665a164ae1265c034dbf6badba560d10 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 3 Nov 2018 16:28:57 +0100 Subject: [PATCH 9/9] PXX seems now OK on X7. More tests needed --- radio/src/pulses/pxx.h | 7 ++++++- radio/src/pulses/pxx1.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index aa381c9a9..02296bbe5 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -140,7 +140,7 @@ class StandardPxxTransport: public BitTransport, public PxxCrcMixin { void initFrame() { - BitTransport::initBuffer(); + BitTransport::initFrame(); ones_count = 0; } @@ -176,6 +176,11 @@ class StandardPxxTransport: public BitTransport, public PxxCrcMixin { class UartPxxTransport: public DataBuffer, public PxxCrcMixin { protected: + void initFrame() + { + initBuffer(); + } + void addByte(uint8_t byte) { PxxCrcMixin::addToCrc(byte); diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp index 0981184f3..3ab3963d8 100644 --- a/radio/src/pulses/pxx1.cpp +++ b/radio/src/pulses/pxx1.cpp @@ -57,7 +57,7 @@ void Pxx1Pulses::add8ChannelsFrame(uint8_t port, uint8_t sendUpper template void Pxx1Pulses::setupFrame(uint8_t port) { - PxxTransport::initBuffer(); + PxxTransport::initFrame(); #if defined(PXX_FREQUENCY_HIGH) add8ChannelsFrame(port, 0);