From 7ef9992349cefcf086718a2e18c13b49d4cf34db Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 5 Jun 2016 22:34:16 +0200 Subject: [PATCH] Bsongis/horus xjt external module (#3566) * [Horus] PXX and DSM2 in external module * [Taranis] Pulses driver refactoring (uses DMA also for PPM in external module and saves 800bytes RAM) * Cosmetics (Pulses driver splitted) --- radio/src/CMakeLists.txt | 24 +- radio/src/pulses/dsm2_arm.cpp | 57 +- radio/src/pulses/multi_arm.cpp | 26 +- radio/src/pulses/ppm_arm.cpp | 20 +- radio/src/pulses/pulses_arm.cpp | 11 +- radio/src/pulses/pulses_arm.h | 81 ++- radio/src/pulses/pxx_arm.cpp | 238 ++++--- radio/src/targets/horus/board_horus.cpp | 3 +- radio/src/targets/horus/board_horus.h | 5 + radio/src/targets/horus/extmodule_driver.cpp | 276 ++++++++ radio/src/targets/horus/hal.h | 18 +- radio/src/targets/horus/pulses_driver.cpp | 598 ++++-------------- radio/src/targets/horus/telemetry_driver.cpp | 2 - radio/src/targets/simu/simpgmspace.cpp | 8 +- radio/src/targets/simu/simpgmspace.h | 11 +- radio/src/targets/taranis/board_taranis.h | 11 +- .../src/targets/taranis/extmodule_driver.cpp | 265 ++++++++ radio/src/targets/taranis/hal.h | 22 +- radio/src/targets/taranis/pulses_driver.cpp | 580 ++++------------- 19 files changed, 1138 insertions(+), 1118 deletions(-) create mode 100644 radio/src/targets/horus/extmodule_driver.cpp create mode 100644 radio/src/targets/taranis/extmodule_driver.cpp diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index ac52a0a0a..1aafe6fd8 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -79,7 +79,7 @@ if(PCB STREQUAL HORUS) set(VIRTUAL_INPUTS YES) set(RAMBACKUP YES) option(DISK_CACHE "Enable SD card disk cache" YES) - add_definitions(-DPCBHORUS -DCOLORLCD -DSTM32F429_439xx -DPPM_PIN_HW_SERIAL) + add_definitions(-DPCBHORUS -DCOLORLCD -DSTM32F429_439xx -DPPM_PIN_UART -DPPM_PIN_TIMER) add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK) add_definitions(-DLUAINPUTS -DXCURVES -DVARIO) include_directories(${RADIO_SRC_DIRECTORY}/fonts/horus gui/${GUI_DIR} gui/${GUI_DIR}/layouts) @@ -111,7 +111,11 @@ if(PCB STREQUAL HORUS) set(SRC ${SRC} disk_cache.cpp) add_definitions(-DDISK_CACHE) endif() - set(TARGET_SRC ${TARGET_SRC} board_horus.cpp) + set(TARGET_SRC + ${TARGET_SRC} + board_horus.cpp + extmodule_driver.cpp + ) set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} sdio_sd.c @@ -181,12 +185,20 @@ elseif(PCB STREQUAL TARANIS) set(TARGET_DIR taranis) set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} taranis_bitmaps) set(VIRTUAL_INPUTS YES) - add_definitions(-DPCBTARANIS) + add_definitions(-DPCBTARANIS -DPPM_PIN_TIMER) add_definitions(-DAUDIO -DVOICE -DRTCLOCK) add_definitions(-DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DVARIO) set(GUI_SRC ${GUI_SRC} bmp.cpp menu_model_inputs.cpp menu_model_mixes.cpp menu_model_display.cpp menu_general_diagkeys.cpp menu_general_diaganas.cpp menu_general_hardware.cpp view_channels.cpp view_telemetry.cpp view_text.cpp view_about.cpp) - set(TARGET_SRC ${TARGET_SRC} board_taranis.cpp rtc_driver.cpp) - set(FIRMWARE_SRC ${FIRMWARE_SRC} loadboot.cpp) + set(TARGET_SRC + ${TARGET_SRC} + board_taranis.cpp + extmodule_driver.cpp + rtc_driver.cpp + ) + set(FIRMWARE_SRC + ${FIRMWARE_SRC} + loadboot.cpp + ) set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} lcd_driver.cpp @@ -244,7 +256,7 @@ elseif(PCB STREQUAL SKY9X OR PCB STREQUAL 9XRPRO OR PCB STREQUAL AR9X) set(GUI_DIR 9x) set(TARGET_DIR sky9x) set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps) - add_definitions(-DPCBSKY9X) + add_definitions(-DPCBSKY9X -DPPM_PIN_SERIAL) add_definitions(-DAUDIO -DVOICE -DRTCLOCK -DVARIO) add_definitions(-DEEPROM_VARIANT=0) set(GUI_SRC ${GUI_SRC} ${9X_GUI_SRC} menu_general_hardware.cpp view_telemetry.cpp view_text.cpp view_about.cpp) diff --git a/radio/src/pulses/dsm2_arm.cpp b/radio/src/pulses/dsm2_arm.cpp index aa6698615..263a06e9d 100644 --- a/radio/src/pulses/dsm2_arm.cpp +++ b/radio/src/pulses/dsm2_arm.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../opentx.h" +#include "opentx.h" #define DSM2_SEND_BIND (1 << 7) #define DSM2_SEND_RANGECHECK (1 << 5) @@ -35,17 +35,17 @@ uint8_t dsm2BindTimer = DSM2_BIND_TIMEOUT; #define BITLEN_DSM2 (8*2) //125000 Baud => 8uS per bit -#if !defined(PPM_PIN_HW_SERIAL) +#if !defined(PPM_PIN_SERIAL) void _send_1(uint8_t v) { - if (modulePulsesData[EXTERNAL_MODULE].dsm2.index == 0) - v -= 2; - else + if (modulePulsesData[EXTERNAL_MODULE].dsm2.index & 1) v += 2; + else + v -= 2; - modulePulsesData[EXTERNAL_MODULE].dsm2.value += v; - *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.value; - modulePulsesData[EXTERNAL_MODULE].dsm2.index = (modulePulsesData[EXTERNAL_MODULE].dsm2.index+1) % 2; + *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = v; + modulePulsesData[EXTERNAL_MODULE].dsm2.index += 1; + modulePulsesData[EXTERNAL_MODULE].dsm2.rest -= v; } void sendByteDsm2(uint8_t b) //max 10 changes 0 10 10 10 10 1 @@ -69,8 +69,10 @@ void sendByteDsm2(uint8_t b) //max 10 changes 0 10 10 10 10 1 void putDsm2Flush() { - modulePulsesData[EXTERNAL_MODULE].dsm2.ptr--; //remove last stopbits and - *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = 44010; // Past the 44000 of the ARR + if (modulePulsesData[EXTERNAL_MODULE].dsm2.index & 1) + *(modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - 1) = modulePulsesData[EXTERNAL_MODULE].dsm2.rest; + else + *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.rest; } #else void putDsm2SerialBit(uint8_t bit) @@ -108,26 +110,20 @@ void putDsm2Flush() // This is the data stream to send, prepare after 19.5 mS // Send after 22.5 mS -//static uint8_t *Dsm2_pulsePtr = pulses2MHz.pbyte ; -void setupPulsesDSM2(unsigned int port) +void setupPulsesDSM2(uint8_t port) { - static uint8_t dsmDat[2+6*2]={0xFF,0x00, 0x00,0xAA, 0x05,0xFF, 0x09,0xFF, 0x0D,0xFF, 0x13,0x54, 0x14,0xAA}; + uint8_t dsmDat[14]; -#if defined(PPM_PIN_HW_SERIAL) +#if defined(PPM_PIN_SERIAL) modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0 ; modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0 ; #else - modulePulsesData[EXTERNAL_MODULE].dsm2.value = 0; modulePulsesData[EXTERNAL_MODULE].dsm2.index = 1; + modulePulsesData[EXTERNAL_MODULE].dsm2.rest = 44000; #endif modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses; -#if !defined(PPM_PIN_HW_SERIAL) - modulePulsesData[EXTERNAL_MODULE].dsm2.value = 100; - *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.value; -#endif - switch (s_current_protocol[port]) { case PROTO_DSM2_LP45: dsmDat[0] = 0x00; @@ -140,13 +136,7 @@ void setupPulsesDSM2(unsigned int port) break; } -#if !defined(PPM_PIN_HW_SERIAL) - if (moduleFlag[port] == MODULE_BIND) - dsmDat[0] |= DSM2_SEND_BIND; - else if (moduleFlag[port] == MODULE_RANGECHECK) - dsmDat[0] |= DSM2_SEND_RANGECHECK; -#else -#if defined(PCBSKY9X) // TODO needed? +#if defined(PCBSKY9X) if (dsm2BindTimer > 0) { dsm2BindTimer--; if (switchState(SW_DSM2_BIND)) { @@ -154,14 +144,19 @@ void setupPulsesDSM2(unsigned int port) dsmDat[0] |= DSM2_SEND_BIND; } } - else -#endif - if (moduleFlag[port] == MODULE_RANGECHECK) { + else if (moduleFlag[port] == MODULE_RANGECHECK) { dsmDat[0] |= DSM2_SEND_RANGECHECK; } else { moduleFlag[port] = 0; } +#else + if (moduleFlag[port] == MODULE_BIND) { + dsmDat[0] |= DSM2_SEND_BIND; + } + else if (moduleFlag[port] == MODULE_RANGECHECK) { + dsmDat[0] |= DSM2_SEND_RANGECHECK; + } #endif dsmDat[1] = g_model.header.modelId[port]; // DSM2 Header second byte for model match diff --git a/radio/src/pulses/multi_arm.cpp b/radio/src/pulses/multi_arm.cpp index a16c32172..9dee80bc0 100644 --- a/radio/src/pulses/multi_arm.cpp +++ b/radio/src/pulses/multi_arm.cpp @@ -35,7 +35,7 @@ #define BITLEN_MULTI (10*2) //100000 Baud => 10uS per bit -#if defined(PPM_PIN_HW_SERIAL) +#if defined(PPM_PIN_SERIAL) static void sendByteMulti(uint8_t b) { uint8_t parity = 1; @@ -56,14 +56,14 @@ static void _send_level(uint8_t v) { /* Copied over from DSM, this looks doubious and in my logic analyzer output the low->high is about 2 ns late */ - if (modulePulsesData[EXTERNAL_MODULE].dsm2.index == 0) - v -= 2; - else + if (modulePulsesData[EXTERNAL_MODULE].dsm2.index & 1) v += 2; + else + v -= 2; - modulePulsesData[EXTERNAL_MODULE].dsm2.value += v; - *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.value; - modulePulsesData[EXTERNAL_MODULE].dsm2.index = (modulePulsesData[EXTERNAL_MODULE].dsm2.index+1) % 2; + *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = v; + modulePulsesData[EXTERNAL_MODULE].dsm2.index+=1; + modulePulsesData[EXTERNAL_MODULE].dsm2.rest -=v; } static void sendByteMulti(uint8_t b) //max 11 changes 0 10 10 10 10 P 1 @@ -99,24 +99,18 @@ static void sendByteMulti(uint8_t b) //max 11 changes 0 10 10 10 10 P 1 #define MULTI_CHANS 16 #define MULTI_CHAN_BITS 11 -void setupPulsesMultimodule(unsigned int port) +void setupPulsesMultimodule(uint8_t port) { - -#if defined(PPM_PIN_HW_SERIAL) +#if defined(PPM_PIN_SERIAL) modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0 ; modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0 ; #else - modulePulsesData[EXTERNAL_MODULE].dsm2.value = 0; + modulePulsesData[EXTERNAL_MODULE].dsm2.rest = 44000; modulePulsesData[EXTERNAL_MODULE].dsm2.index = 1; #endif modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses; -#if defined(PCBTARANIS) - modulePulsesData[EXTERNAL_MODULE].dsm2.value = 100; - *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.value; -#endif - // header, byte 0, always 0x55 sendByteMulti(0x55); diff --git a/radio/src/pulses/ppm_arm.cpp b/radio/src/pulses/ppm_arm.cpp index 30b85084c..9fb84668f 100644 --- a/radio/src/pulses/ppm_arm.cpp +++ b/radio/src/pulses/ppm_arm.cpp @@ -18,9 +18,9 @@ * GNU General Public License for more details. */ -#include "../opentx.h" +#include "opentx.h" -void setupPulsesPPM(unsigned int port) // Don't enable interrupts through here +void setupPulsesPPM(uint8_t port) // Don't enable interrupts through here { int16_t PPM_range = g_model.extendedLimits ? (512*LIMIT_EXT_PERCENT/100) * 2 : 512 * 2; //range of 0.7..1.7msec @@ -43,23 +43,35 @@ void setupPulsesPPM(unsigned int port) // Don't enable interru #endif PpmPulsesData * ppmPulsesData = (port == TRAINER_MODULE ? &trainerPulsesData.ppm : &modulePulsesData[port].ppm); - uint16_t * ptr = ppmPulsesData->pulses; +#if defined(CPUSTM32) + ppmPulsesData->ptr = ppmPulsesData->pulses; +#else + uint16_t * ptr = ppmPulsesData->pulses; ppmPulsesData->ptr = ptr; +#endif int32_t rest = 22500u * 2; rest += (int32_t(g_model.moduleData[port].ppm.frameLength)) * 1000; for (uint32_t i=firstCh; iptr++ = v; /* as Pat MacKenzie suggests */ +#else *ptr++ = v; /* as Pat MacKenzie suggests */ +#endif } if (rest > 65535) rest = 65535; /* prevents overflows */ if (rest < 9000) rest = 9000; /* avoids that CCR2 is bigger than ARR which would cause reboot */ +#if defined(CPUSTM32) + *ppmPulsesData->ptr++ = rest; +#else *ptr = rest; *(ptr + 1) = 0; +#endif -#if !defined(PCBSKY9X) +#if defined(CPUSTM32) rest -= 1000; uint32_t ppmDelay = (g_model.moduleData[port].ppm.delay * 50 + 300) * 2; // set idle time, ppm delay and ppm polarity diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index cb1fe955c..e5519e5dd 100644 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../opentx.h" +#include "opentx.h" uint8_t s_pulses_paused = 0; uint8_t s_current_protocol[NUM_MODULES] = { MODULES_INIT(255) }; @@ -28,7 +28,7 @@ uint8_t moduleFlag[NUM_MODULES] = { 0 }; ModulePulsesData modulePulsesData[NUM_MODULES] __DMA; TrainerPulsesData trainerPulsesData __DMA; -void setupPulses(unsigned int port) +void setupPulses(uint8_t port) { uint8_t required_protocol; @@ -202,9 +202,10 @@ void setupPulses(unsigned int port) } #endif #if defined(MULTIMODULE) - case PROTO_MULTIMODULE: - setupPulsesMultimodule(port); - break; + case PROTO_MULTIMODULE: + setupPulsesMultimodule(port); + scheduleNextMixerCalculation(port, 11); + break; #endif case PROTO_PPM: setupPulsesPPM(port); diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index d835ef0c7..182457d4b 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -27,17 +27,23 @@ #define MODULES_INIT(...) __VA_ARGS__ #endif +#if defined(PCBHORUS) + #define pulse_duration_t uint32_t +#else + #define 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]; PACK(struct PpmPulsesData { - uint16_t pulses[20]; - uint16_t * ptr; + pulse_duration_t pulses[20]; + pulse_duration_t * ptr; }); -#if defined(PPM_PIN_HW_SERIAL) -PACK(struct PxxPulsesData { +#if defined(PPM_PIN_SERIAL) +PACK(struct PxxSerialPulsesData { uint8_t pulses[64]; uint8_t *ptr; uint16_t pcmValue; @@ -46,26 +52,49 @@ PACK(struct PxxPulsesData { uint16_t serialByte; uint16_t serialBitCount; }); -PACK(struct Dsm2PulsesData { + +PACK(struct Dsm2SerialPulsesData { uint8_t pulses[64]; uint8_t *ptr; uint8_t serialByte ; uint8_t serialBitCount; }); +#endif + +#if defined(PPM_PIN_UART) +PACK(struct PxxUartPulsesData { + uint8_t pulses[64]; + uint8_t * ptr; + uint16_t pcmCrc; +}); +#endif + +#if defined(PPM_PIN_TIMER) +/* 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 */ +#if defined(MULTIMODULE) +#define NUM_TIMER_PULSES 300 #else -PACK(struct PxxPulsesData { - uint16_t pulses[400]; - uint16_t *ptr; - uint16_t pcmValue; +#define NUM_TIMER_PULSES 200 +#endif + +PACK(struct PxxTimerPulsesData { + pulse_duration_t pulses[NUM_TIMER_PULSES]; + pulse_duration_t * ptr; + uint16_t rest; uint16_t pcmCrc; uint32_t pcmOnesCount; }); -PACK(struct Dsm2PulsesData { - uint16_t pulses[400]; - uint16_t *ptr; - uint16_t value; - uint16_t index; + +PACK(struct Dsm2TimerPulsesData { + pulse_duration_t pulses[NUM_TIMER_PULSES]; + pulse_duration_t * ptr; + uint16_t rest; + uint8_t index; }); +#undef NUM_TIMER_PULSES #endif #define CROSSFIRE_BAUDRATE 400000 @@ -77,8 +106,16 @@ PACK(struct CrossfirePulsesData { }); union ModulePulsesData { - PxxPulsesData pxx; - Dsm2PulsesData dsm2; +#if defined(PPM_PIN_SERIAL) + PxxSerialPulsesData pxx; + Dsm2SerialPulsesData dsm2; +#else + PxxTimerPulsesData pxx; + Dsm2TimerPulsesData dsm2; +#endif +#if defined(PPM_PIN_UART) + PxxUartPulsesData pxx_uart; +#endif PpmPulsesData ppm; CrossfirePulsesData crossfire; }; @@ -91,11 +128,11 @@ extern ModulePulsesData modulePulsesData[NUM_MODULES]; extern TrainerPulsesData trainerPulsesData; extern const uint16_t CRCTable[]; -void setupPulses(unsigned int port); -void setupPulsesDSM2(unsigned int port); -void setupPulsesMultimodule(unsigned int port); -void setupPulsesPXX(unsigned int port); -void setupPulsesPPM(unsigned int port); +void setupPulses(uint8_t port); +void setupPulsesDSM2(uint8_t port); +void setupPulsesMultimodule(uint8_t port); +void setupPulsesPXX(uint8_t port); +void setupPulsesPPM(uint8_t port); void sendByteDsm2(uint8_t b); void putDsm2Flush(); void putDsm2SerialBit(uint8_t bit); diff --git a/radio/src/pulses/pxx_arm.cpp b/radio/src/pulses/pxx_arm.cpp index f66c47a38..35b445fe4 100644 --- a/radio/src/pulses/pxx_arm.cpp +++ b/radio/src/pulses/pxx_arm.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -60,44 +60,50 @@ const uint16_t CRCTable[]= 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; -void crc(uint8_t data, unsigned int port) -{ - modulePulsesData[port].pxx.pcmCrc = (modulePulsesData[port].pxx.pcmCrc<<8) ^ (CRCTable[((modulePulsesData[port].pxx.pcmCrc>>8)^data) & 0xFF]); -} - -#if defined(PCBHORUS) -void putPcmPart(uint8_t byte, unsigned int port) +#if defined(PPM_PIN_UART) +inline void uartPutPcmPart(uint8_t port, uint8_t byte) { if (0x7E == byte) { - *modulePulsesData[port].pxx.ptr++ = 0x7D; - *modulePulsesData[port].pxx.ptr++ = 0x5E; + *modulePulsesData[port].pxx_uart.ptr++ = 0x7D; + *modulePulsesData[port].pxx_uart.ptr++ = 0x5E; } else if (0x7D == byte) { - *modulePulsesData[port].pxx.ptr++ = 0x7D; - *modulePulsesData[port].pxx.ptr++ = 0x5D; + *modulePulsesData[port].pxx_uart.ptr++ = 0x7D; + *modulePulsesData[port].pxx_uart.ptr++ = 0x5D; } else { - *modulePulsesData[port].pxx.ptr++ = byte; + *modulePulsesData[port].pxx_uart.ptr++ = byte; } } -void putPcmByte(uint8_t byte, unsigned int port) +void uartPutPcmByte(uint8_t port, uint8_t byte) { - crc(byte, port); - putPcmPart(byte, port); + modulePulsesData[port].pxx_uart.pcmCrc = (modulePulsesData[port].pxx_uart.pcmCrc<<8) ^ (CRCTable[((modulePulsesData[port].pxx_uart.pcmCrc>>8)^byte) & 0xFF]); + uartPutPcmPart(port, byte); } -void putPcmHead(unsigned int port) +void uartInitPcmArray(uint8_t port) +{ + modulePulsesData[port].pxx_uart.ptr = modulePulsesData[port].pxx_uart.pulses; + modulePulsesData[port].pxx_uart.pcmCrc = 0; +} + +void uartPutPcmHead(uint8_t port) { // send 7E, do not CRC - *modulePulsesData[port].pxx.ptr++ = 0x7E; + *modulePulsesData[port].pxx_uart.ptr++ = 0x7E; } -#define putPcmFlush(port) -#define putPcmPreamble(port) -#else -#if defined(PPM_PIN_HW_SERIAL) -void putPcmSerialBit(uint8_t bit, unsigned int port) +void uartPutPcmCrc(uint8_t port) +{ + uint16_t pulseValue = modulePulsesData[port].pxx_uart.pcmCrc; + uartPutPcmByte(port, pulseValue >> 8); + uartPutPcmByte(port, pulseValue); +} +#endif + +#if defined(PPM_PIN_SERIAL) +void pxxPutPcmSerialBit(uint8_t port, uint8_t bit) { modulePulsesData[port].pxx.serialByte >>= 1; if (bit & 1) { @@ -110,103 +116,169 @@ void putPcmSerialBit(uint8_t bit, unsigned int port) } // 8uS/bit 01 = 0, 001 = 1 -void putPcmPart(uint8_t value, unsigned int port) +void pxxPutPcmPart(uint8_t port, uint8_t value) { - putPcmSerialBit(0, port); + pxxPutPcmSerialBit(port, 0); if (value) { - putPcmSerialBit(0, port); + pxxPutPcmSerialBit(port, 0); } - putPcmSerialBit(1, port); + pxxPutPcmSerialBit(port, 1); } -void putPcmFlush(unsigned int port) +void pxxPutPcmTail(uint8_t port) { while (modulePulsesData[port].pxx.serialBitCount != 0) { - putPcmSerialBit(1, port); + pxxPutPcmSerialBit(port, 1); } } #else -void putPcmPart(uint8_t value, unsigned int port) +void pxxPutPcmPart(uint8_t port, uint8_t value) { - modulePulsesData[port].pxx.pcmValue += 18 ; // Output 1 for this time - *modulePulsesData[port].pxx.ptr++ = modulePulsesData[port].pxx.pcmValue ; - modulePulsesData[port].pxx.pcmValue += 14 ; - if (value) { - modulePulsesData[port].pxx.pcmValue += 16 ; - } - *modulePulsesData[port].pxx.ptr++ = modulePulsesData[port].pxx.pcmValue ; // Output 0 for this time + pulse_duration_t duration = value ? 48 : 32; + *modulePulsesData[port].pxx.ptr++ = duration; + modulePulsesData[port].pxx.rest -= duration + 1; } -void putPcmFlush(unsigned int port) +void pxxPutPcmTail(uint8_t port) { - *modulePulsesData[port].pxx.ptr++ = 18010 ; // Past the 18000 of the ARR + *(modulePulsesData[port].pxx.ptr-1) += modulePulsesData[port].pxx.rest; } #endif -void putPcmBit(uint8_t bit, unsigned int port) +void pxxPutPcmBit(uint8_t port, uint8_t bit) { if (bit) { - modulePulsesData[port].pxx.pcmOnesCount += 1; - putPcmPart(1, port); + 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; - putPcmPart(0, port); - } - if (modulePulsesData[port].pxx.pcmOnesCount >= 5) { - putPcmBit(0, port); // Stuff a 0 bit in } + } -void putPcmByte(uint8_t byte, unsigned int port) +void pxxPutPcmByte(uint8_t port, uint8_t byte) { - crc(byte, port); + 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++) { - putPcmBit(byte & 0x80, port); + pxxPutPcmBit(port, byte & 0x80); byte <<= 1; } } -void putPcmHead(unsigned int port) +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 = 18000; +#endif + modulePulsesData[port].pxx.pcmCrc = 0; + modulePulsesData[port].pxx.pcmOnesCount = 0; +} + +void pxxPutPcmHead(uint8_t port) { // send 7E, do not CRC // 01111110 - putPcmPart(0, port); - putPcmPart(1, port); - putPcmPart(1, port); - putPcmPart(1, port); - putPcmPart(1, port); - putPcmPart(1, port); - putPcmPart(1, port); - putPcmPart(0, port); + 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 putPcmPreamble(unsigned int port) +void pxxPutPcmCrc(uint8_t port) { - putPcmPart(0, port); - putPcmPart(0, port); - putPcmPart(0, port); - putPcmPart(0, port); + uint16_t pulseValue = modulePulsesData[port].pxx.pcmCrc; + pxxPutPcmByte(port, pulseValue >> 8); + pxxPutPcmByte(port, pulseValue); +} + +#if defined(PPM_PIN_UART) +inline void initPcmArray(uint8_t port) +{ + if (IS_UART_MODULE(port)) + uartInitPcmArray(port); + else + pxxInitPcmArray(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 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 -void setupPulsesPXX(unsigned int port) +void setupPulsesPXX(uint8_t port) { uint16_t pulseValue=0, pulseValueLow=0; - modulePulsesData[port].pxx.ptr = modulePulsesData[port].pxx.pulses; - modulePulsesData[port].pxx.pcmValue = 0 ; - modulePulsesData[port].pxx.pcmCrc = 0; - modulePulsesData[port].pxx.pcmOnesCount = 0; - - /* Preamble */ - putPcmPreamble(port); + initPcmArray(port); /* Sync */ putPcmHead(port); /* Rx Number */ - putPcmByte(g_model.header.modelId[port], port); + putPcmByte(port, g_model.header.modelId[port]); /* FLAG1 */ uint8_t flag1 = (g_model.moduleData[port].rfProtocol << 6); @@ -226,10 +298,10 @@ void setupPulsesPXX(unsigned int port) } } - putPcmByte(flag1, port); + putPcmByte(port, flag1); /* FLAG2 */ - putPcmByte(0, port); + putPcmByte(port, 0); /* PPM */ static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) }; @@ -291,9 +363,9 @@ void setupPulsesPXX(unsigned int port) } if (i & 1) { - putPcmByte(pulseValueLow, port); // Low byte of channel - putPcmByte(((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4), port); // 4 bits each from 2 channels - putPcmByte(pulseValue >> 4, port); // High byte of channel + 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; @@ -306,18 +378,16 @@ void setupPulsesPXX(unsigned int port) if (port == INTERNAL_MODULE) { antenna = g_model.moduleData[INTERNAL_MODULE].ppm.pulsePol; } - putPcmByte (antenna, port); + putPcmByte(port, antenna); #else - putPcmByte(0, port); + putPcmByte(port, 0); #endif - /* CRC16 */ - pulseValue = modulePulsesData[port].pxx.pcmCrc; - putPcmByte(pulseValue >> 8, port); - putPcmByte(pulseValue, port); + /* CRC */ + putPcmCrc(port); /* Sync */ putPcmHead(port); - putPcmFlush(port); + putPcmTail(port); } diff --git a/radio/src/targets/horus/board_horus.cpp b/radio/src/targets/horus/board_horus.cpp index 89fe39533..2db387527 100644 --- a/radio/src/targets/horus/board_horus.cpp +++ b/radio/src/targets/horus/board_horus.cpp @@ -138,8 +138,7 @@ void boardInit() RCC_APB2PeriphClockCmd(LCD_RCC_APB2Periph | ADC_RCC_APB2Periph | HAPTIC_RCC_APB2Periph | - INTMODULE_RCC_APB2Periph | - EXTMODULE_RCC_APB2Periph, ENABLE); + INTMODULE_RCC_APB2Periph, ENABLE); pwrInit(); delaysInit(); diff --git a/radio/src/targets/horus/board_horus.h b/radio/src/targets/horus/board_horus.h index d9a16812e..dab27e230 100644 --- a/radio/src/targets/horus/board_horus.h +++ b/radio/src/targets/horus/board_horus.h @@ -164,6 +164,11 @@ void SDRAM_Init(void); #define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) #define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET) #define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET) +#define IS_UART_MODULE(port) (port == INTERNAL_MODULE) + +// void setupPulses(uint8_t port); +// void setupPulsesPPM(uint8_t port); +// void setupPulsesPXX(uint8_t port); void init_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port); void init_ppm( uint32_t module_index ); diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp new file mode 100644 index 000000000..0cee6b65a --- /dev/null +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -0,0 +1,276 @@ +/* + * 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" + +void extmoduleSendNextFrame(); + +void extmoduleStop() +{ + NVIC_DisableIRQ(EXTMODULE_DMA_IRQn); + NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn); + + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + EXTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE); + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } +} + +void extmoduleNoneStart() +{ + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); + GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high + + 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->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 extmodulePpmStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + + // PPM generation principle: + // + // Hardware timer in PWM mode is used for PPM generation + // Output is OFF if CNTCR1 &= ~TIM_CR1_CEN; // Stop timer + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + EXTMODULE_TIMER->ARR = 41000; + // CH1 PWM mode 1, CH1 out is OFF if CNTCCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 + EXTMODULE_TIMER->EGR = 1; // Reloads register vales now + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer + + setupPulsesPPM(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + + NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); + NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); + NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); +} + +void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) +{ + EXTMODULE_TIMER->CCR2 = idleTime; + EXTMODULE_TIMER->CCR1 = delay; + EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (positive ? 0 : TIM_CCER_CC1P); +} + +void extmodulePxxStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + EXTMODULE_TIMER->ARR = 18000; + EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP; // TIM_CCER_CC1E | TIM_CCER_CC1P; + EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs + EXTMODULE_TIMER->CCR1 = 18; + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high + EXTMODULE_TIMER->EGR = 1; // Restart + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + setupPulsesPXX(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + + NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); + NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); + NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); +} + +#if defined(DSM2) +void extmoduleDsm2Start() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + EXTMODULE_TIMER->ARR = 44000; // 22mS + EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P; + EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs + EXTMODULE_TIMER->CCR1 = 0; + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high + EXTMODULE_TIMER->EGR = 1; // Restart + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + setupPulsesDSM2(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + + NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); + NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); + NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); +} +#endif + +void extmoduleCrossfireStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); + GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_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_FRAME_PERIOD); + EXTMODULE_TIMER->CCR2 = (2000 * CROSSFIRE_FRAME_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) { + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + 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; + EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); + EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].ppm.pulses); + EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].ppm.ptr - modulePulsesData[EXTERNAL_MODULE].ppm.pulses; + EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + } + else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) { + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + 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; + 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->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + } + else if (s_current_protocol[EXTERNAL_MODULE] >= PROTO_DSM2_LP45 && s_current_protocol[EXTERNAL_MODULE] <= PROTO_DSM2_DSMX) { + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + 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; + EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); + EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses); + EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - modulePulsesData[EXTERNAL_MODULE].dsm2.pulses; + EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + } + else { + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; + } +} + +extern "C" void EXTMODULE_DMA_IRQHandler() +{ + if (!DMA_GetITStatus(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC)) + return; + + DMA_ClearITPendingBit(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC); + + uint32_t arr = EXTMODULE_TIMER->ARR; + if (arr > 4000) { + EXTMODULE_TIMER->CCR2 = arr - 4000; // 2mS in advance + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + } + else { + setupPulses(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + } +} + +extern "C" void EXTMODULE_TIMER_IRQHandler() +{ + EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; + setupPulses(EXTERNAL_MODULE); + extmoduleSendNextFrame(); +} diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index f6209f3c9..864c5e021 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -261,7 +261,7 @@ #define HAPTIC_GPIO_PinSource GPIO_PinSource2 // Internal Module -#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB) +#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2) #define INTMODULE_RCC_APB2Periph (RCC_APB2Periph_TIM1 | RCC_APB2Periph_USART1) #define INTMODULE_PWR_GPIO GPIOA #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PA.08 @@ -276,15 +276,17 @@ #define INTMODULE_USART_IRQn USART1_IRQn #define INTMODULE_DMA_STREAM DMA2_Stream7 #define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn +#define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler +#define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF7 #define INTMODULE_DMA_CHANNEL DMA_Channel_4 #define INTMODULE_TIMER TIM1 -#define INTMODULE_TIMER_IRQn TIM1_CC_IRQn +#define INTMODULE_TIMER_CC_IRQn TIM1_CC_IRQn +#define INTMODULE_TIMER_CC_IRQHandler TIM1_CC_IRQHandler #define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) // External Module -#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB) +#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1) #define EXTMODULE_RCC_APB1Periph RCC_APB1Periph_TIM2 -#define EXTMODULE_RCC_APB2Periph 0 #define EXTMODULE_PWR_GPIO GPIOB #define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_3 // PB.03 #define EXTMODULE_PPM_GPIO GPIOA @@ -292,8 +294,14 @@ #define EXTMODULE_PPM_GPIO_PinSource GPIO_PinSource15 #define EXTMODULE_TIMER TIM2 #define EXTMODULE_PPM_GPIO_AF GPIO_AF_TIM2 -#define EXTMODULE_PPM_GPIO_PinSource GPIO_PinSource15 +#define EXTMODULE_DMA DMA1 +#define EXTMODULE_DMA_CHANNEL DMA_Channel_3 +#define EXTMODULE_DMA_STREAM DMA1_Stream7 +#define EXTMODULE_DMA_IRQn DMA1_Stream7_IRQn +#define EXTMODULE_DMA_IRQHandler DMA1_Stream7_IRQHandler +#define EXTMODULE_DMA_FLAG_TC DMA_IT_TCIF7 #define EXTMODULE_TIMER_IRQn TIM2_IRQn +#define EXTMODULE_TIMER_IRQHandler TIM2_IRQHandler #define EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) // Trainer Port diff --git a/radio/src/targets/horus/pulses_driver.cpp b/radio/src/targets/horus/pulses_driver.cpp index 031d1cf1b..8b971cc53 100644 --- a/radio/src/targets/horus/pulses_driver.cpp +++ b/radio/src/targets/horus/pulses_driver.cpp @@ -20,41 +20,64 @@ #include "opentx.h" -void setupPulses(unsigned int port); -void setupPulsesPPM(unsigned int port); -void setupPulsesPXX(unsigned int port); +void intmoduleStop(void); +void extmoduleStop(void); -static void intmodulePxxStart( void ) ; -static void intmodulePxxStop( void ) ; -static void extmodulePxxStart( void ) ; -static void extmodulePxxStop( void ) ; +void intmoduleNoneStart(void); +void intmodulePxxStart(void); + +void extmoduleNoneStart(void); +void extmodulePpmStart(void); +void extmodulePxxStart(void); #if defined(DSM2) -static void extmoduleDsm2Start( void ) ; -static void extmoduleDsm2Stop( void ) ; +void extmoduleDsm2Start(void); #endif -static void extmodulePpmStart( void ) ; -static void extmodulePpmStop( void ) ; -static void intmoduleNoneStart( void ) ; -static void intmoduleNoneStop( void ) ; -static void extmoduleNoneStart( void ) ; -static void extmoduleNoneStop( void ) ; -static void extmoduleCrossfireStart( void ) ; -static void extmoduleCrossfireStop( void ) ; +void extmoduleCrossfireStart(void); + +void init_no_pulses(uint32_t port) +{ + if (port == INTERNAL_MODULE) + intmoduleNoneStart(); + else + extmoduleNoneStart(); +} + +void disable_no_pulses(uint32_t port) +{ + if (port == INTERNAL_MODULE) + intmoduleStop(); + else + extmoduleStop(); +} + +void init_ppm(uint32_t port) +{ + if (port == EXTERNAL_MODULE) { + extmodulePpmStart(); + } +} + +void disable_ppm(uint32_t port) +{ + if (port == EXTERNAL_MODULE) { + extmoduleStop(); + } +} void init_pxx(uint32_t port) { if (port == INTERNAL_MODULE) - intmodulePxxStart() ; + intmodulePxxStart(); else - extmodulePxxStart() ; + extmodulePxxStart(); } void disable_pxx(uint32_t port) { if (port == INTERNAL_MODULE) - intmodulePxxStop() ; + intmoduleStop(); else - extmodulePxxStop() ; + extmoduleStop(); } #if defined(DSM2) @@ -68,48 +91,11 @@ void init_dsm2(uint32_t port) void disable_dsm2(uint32_t port) { if (port == EXTERNAL_MODULE) { - extmoduleDsm2Stop(); + extmoduleStop(); } } #endif -void init_ppm(uint32_t port) -{ - if (port == EXTERNAL_MODULE) { - extmodulePpmStart(); - } -} - -void disable_ppm(uint32_t port) -{ - if (port == EXTERNAL_MODULE) { - extmodulePpmStop(); - } -} - -void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - EXTMODULE_TIMER->CCR2 = idleTime; - EXTMODULE_TIMER->CCR1 = delay; - EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (positive ? 0 : TIM_CCER_CC1P); -} - -void init_no_pulses(uint32_t port) -{ - if (port == INTERNAL_MODULE) - intmoduleNoneStart(); - else - extmoduleNoneStart(); -} - -void disable_no_pulses(uint32_t port) -{ - if (port == INTERNAL_MODULE) - intmoduleNoneStop(); - else - extmoduleNoneStop(); -} - void init_crossfire(uint32_t port) { if (port == EXTERNAL_MODULE) { @@ -119,184 +105,51 @@ void init_crossfire(uint32_t port) void disable_crossfire(uint32_t port) { - if (port == EXTERNAL_MODULE) - extmoduleCrossfireStop(); + if (port == EXTERNAL_MODULE) { + extmoduleStop(); + } } -static void intmoduleNoneStart() +void intmoduleStop() +{ + INTERNAL_MODULE_OFF(); + + NVIC_DisableIRQ(INTMODULE_TIMER_CC_IRQn); + + INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; +} + +void intmoduleNoneStart() { INTERNAL_MODULE_OFF(); // Timer1, channel 3 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ; + 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(INTMODULE_TX_GPIO, &GPIO_InitStructure); - GPIO_SetBits(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PIN) ; // Set high + GPIO_SetBits(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PIN); // Set high - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - INTMODULE_TIMER->ARR = 36000 ; // 18mS - INTMODULE_TIMER->CCR2 = 32000 ; // Update time - INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz) + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + INTMODULE_TIMER->ARR = 36000; // 18mS + INTMODULE_TIMER->CCR2 = 32000; // Update time + INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - INTMODULE_TIMER->CCER = TIM_CCER_CC3E ; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - INTMODULE_TIMER->CCMR2 = 0 ; - INTMODULE_TIMER->EGR = 1 ; // Restart + INTMODULE_TIMER->CCMR2 = 0; + INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 ; // Toggle CC1 o/p - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt - INTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; - NVIC_EnableIRQ(INTMODULE_TIMER_IRQn) ; - NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); -} - -static void intmoduleNoneStop() -{ - NVIC_DisableIRQ(INTMODULE_TIMER_IRQn) ; - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE ; - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; -} - -#if !defined(SIMU) -extern "C" void DMA2_Stream7_IRQHandler(void) -{ - DEBUG_INTERRUPT(INT_DMA2S7); - if(DMA_GetITStatus(INTMODULE_DMA_STREAM, DMA_IT_TCIF7)) { - // TODO we could send the 8 next channels here (when needed) - DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, DMA_IT_TCIF7); - } -} - -extern "C" void TIM1_CC_IRQHandler() -{ - DEBUG_INTERRUPT(INT_TIM1CC); - DEBUG_TIMER_SAMPLE(debugTimerIntPulses); - DEBUG_TIMER_START(debugTimerIntPulsesDuration); - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // stop this interrupt - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag - - setupPulses(INTERNAL_MODULE); - - if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) { - DMA_InitTypeDef DMA_InitStructure; - DMA_DeInit(INTMODULE_DMA_STREAM); - DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL; - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&INTMODULE_USART->DR); - DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; - DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)modulePulsesData[INTERNAL_MODULE].pxx.pulses; - DMA_InitStructure.DMA_BufferSize = (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx.ptr - (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx.pulses; - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; - DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; - DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; - DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; - DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; - DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; - DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure); - - DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE); - USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE); - // DMA_ITConfig(INTMODULE_DMA_STREAM, DMA_IT_TC, ENABLE); - } - - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; - DEBUG_TIMER_STOP(debugTimerIntPulsesDuration); -} -#endif - -static void extmoduleNoneStart() -{ - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } - - GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0); // TODO : check if needed - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); - GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN) ; // Set high - - TIM_DeInit(EXTMODULE_TIMER); - - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_TimeBaseStructure.TIM_Prescaler = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = 36000; // 18mS - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; - TIM_TimeBaseInit(EXTMODULE_TIMER, &TIM_TimeBaseStructure); - - // set CC2 compare to fire slightly before the Update - TIM_SetCompare2(EXTMODULE_TIMER, 32000); // 16ms - - // enable CC2 interrupt - TIM_ClearFlag(EXTMODULE_TIMER, TIM_FLAG_CC2); - TIM_ITConfig(EXTMODULE_TIMER, TIM_IT_CC2, ENABLE); - - // start timer - TIM_Cmd(EXTMODULE_TIMER, ENABLE); - - // enable interrupt and set it's priority - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn) ; - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmoduleNoneStop() -{ - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn) ; - TIM_DeInit(EXTMODULE_TIMER); -} - -static void extmoduleCrossfireStart() -{ - EXTERNAL_MODULE_ON(); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); - GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - EXTMODULE_TIMER->ARR = 5000 ; // 2.5mS - EXTMODULE_TIMER->CCR2 = 32000 ; // Update time - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz) - - EXTMODULE_TIMER->CCMR2 = 0 ; - EXTMODULE_TIMER->EGR = 1 ; // Restart - - EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 ; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn) ; - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmoduleCrossfireStop() -{ - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn) ; - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE ; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); } void intmodulePxxStart() @@ -306,7 +159,7 @@ void intmodulePxxStart() INTERNAL_MODULE_ON(); - setupPulsesPXX(INTERNAL_MODULE) ; // TODO not here! + setupPulsesPXX(INTERNAL_MODULE); NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; @@ -340,270 +193,69 @@ void intmodulePxxStart() USART_Init(INTMODULE_USART, &USART_InitStructure); USART_Cmd(INTMODULE_USART, ENABLE); - // open DMA------------------------------ - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // Enable DMA1 clock - // Timer - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - INTMODULE_TIMER->ARR = 18000 ; // 9mS - INTMODULE_TIMER->CCR2 = 15000 ; // Update time - INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz) - INTMODULE_TIMER->CCER = TIM_CCER_CC3E ; - INTMODULE_TIMER->CCER = TIM_CCER_CC3E ; + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + INTMODULE_TIMER->ARR = 18000; // 9mS + INTMODULE_TIMER->CCR2 = 15000; // Update time + INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + INTMODULE_TIMER->CCER = TIM_CCER_CC3E; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - INTMODULE_TIMER->CCMR2 = 0 ; - INTMODULE_TIMER->EGR = 1 ; // Restart + INTMODULE_TIMER->CCMR2 = 0; + INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 ; // Toggle CC1 o/p - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt - INTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; - NVIC_EnableIRQ(INTMODULE_TIMER_IRQn) ; - NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); } -static void intmodulePxxStop() +extern "C" void INTMODULE_DMA_STREAM_IRQHandler(void) { - INTERNAL_MODULE_OFF(); -} - -void extmodulePxxStart() -{ - EXTERNAL_MODULE_ON(); - - setupPulsesPXX(EXTERNAL_MODULE); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - EXTMODULE_TIMER->ARR = 18000 ; // 9mS - EXTMODULE_TIMER->CCR2 = 15000 ; // Update time - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz) - EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE ; - EXTMODULE_TIMER->CR2 = TIM_CR2_OIS1 ; // O/P idle high - EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE ; // Enable outputs - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].pxx.pulses[0]; - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0 ; // Force O/P high - EXTMODULE_TIMER->EGR = 1 ; // Restart - - EXTMODULE_TIMER->DIER |= TIM_DIER_CC1DE ; // Enable DMA on CC1 match - EXTMODULE_TIMER->DCR = 13; - - // Enable the DMA channel here, DMA1 stream 5, channel 3 (TIM2_CH1) - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 - | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL ; - DMA1_Stream5->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->DMAR); - DMA1_Stream5->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].pxx.pulses[1]); -// DMA1_Stream5->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; -// DMA1_Stream5->NDTR = 100 ; - DMA1_Stream5->CR |= DMA_SxCR_EN ; // Enable DMA - - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 ; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmodulePxxStop() -{ - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn) ; - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE ; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); + DEBUG_INTERRUPT(INT_DMA2S7); + if (DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC)) { + // TODO we could send the 8 next channels here (when needed) + DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC); } } -#if defined(DSM2) -static void extmoduleDsm2Start() +extern "C" void INTMODULE_TIMER_CC_IRQHandler() { - EXTERNAL_MODULE_ON(); + DEBUG_INTERRUPT(INT_TIM1CC); + DEBUG_TIMER_SAMPLE(debugTimerIntPulses); + DEBUG_TIMER_START(debugTimerIntPulsesDuration); + INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // stop this interrupt + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag - setupPulsesDSM2(EXTERNAL_MODULE); + setupPulses(INTERNAL_MODULE); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) { + DMA_InitTypeDef DMA_InitStructure; + DMA_DeInit(INTMODULE_DMA_STREAM); + 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 = (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx_uart.ptr - (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure); - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - EXTMODULE_TIMER->ARR = 44000 ; // 22mS - EXTMODULE_TIMER->CCR2 = 40000 ; // Update time - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz) - EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | TIM_CCER_CC1NP ; - EXTMODULE_TIMER->CR2 = TIM_CR2_OIS1 ; // O/P idle high - EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE ; // Enable outputs - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[0]; - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0 ; // Force O/P high - EXTMODULE_TIMER->EGR = 1 ; // Restart - - EXTMODULE_TIMER->DIER |= TIM_DIER_CC1DE ; // Enable DMA on CC1 match - EXTMODULE_TIMER->DCR = 13 ; // DMA to CC1 - - // Enable the DMA channel here, DMA1 stream 5, channel 3 (TIM2_CH1) - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 - | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL ; - DMA1_Stream5->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->DMAR); - DMA1_Stream5->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[1]); -// DMA1_Stream5->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; -// DMA1_Stream5->NDTR = 100 ; - DMA1_Stream5->CR |= DMA_SxCR_EN ; // Enable DMA - - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 ; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn) ; - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmoduleDsm2Stop() -{ - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn) ; - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE ; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } -} -#endif - -static void extmodulePpmStart() -{ - EXTERNAL_MODULE_ON(); - - GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); - - // PPM generation principle: - // - // Hardware timer in PWM mode is used for PPM generation - // Output is OFF if CNTCR1 &= ~TIM_CR1_CEN ; - - // setupPulsesPPM() is also configuring registers, - // so it has to be called after the peripheral is enabled - setupPulsesPPM(EXTERNAL_MODULE) ; - - EXTMODULE_TIMER->ARR = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++ ; - EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz) - - // CH1 PWM mode 1, CH1 out is OFF if CNTCCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 - - // Reloads register vales now - EXTMODULE_TIMER->EGR = 1 ; - - // Update DMA request enabled. WHY????? - EXTMODULE_TIMER->DIER = TIM_DIER_UDE ; - - // clear interrupt flags and enable Update and - // CC2 interrupts (this one is enabled now to trigger pulse setup) - EXTMODULE_TIMER->SR &= ~TIM_SR_UIF ; // Clear flag - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; - EXTMODULE_TIMER->DIER |= TIM_DIER_UIE ; - - // enable timer and global interrupts - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN ; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn) ; - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmodulePpmStop() -{ - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn) ; - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE & ~TIM_DIER_UIE ; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear all flags - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } -} - -extern "C" void TIM2_IRQHandler() -{ - DEBUG_INTERRUPT(INT_TIM2); - //determine if its CC or UP interrupt - uint16_t sr = EXTMODULE_TIMER->SR; - uint16_t dier = EXTMODULE_TIMER->DIER; - - if (sr & TIM_SR_CC2IF && dier & TIM_DIER_CC2IE) { // Capture/Compare 2 interrupt enabled and fired - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag - - setupPulses(EXTERNAL_MODULE); - - if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) { - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].pxx.pulses[1]); - DMA1_Stream5->CR |= DMA_SxCR_EN ; // Enable DMA - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].pxx.pulses[0]; - } -#if defined(DSM2) - else if (s_current_protocol[EXTERNAL_MODULE] >= PROTO_DSM2_LP45 && s_current_protocol[EXTERNAL_MODULE] <= PROTO_DSM2_DSMX) { - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[1]); - DMA1_Stream5->CR |= DMA_SxCR_EN ; // Enable DMA - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[0]; - } -#endif - else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { - // Stop CC2 interrupt, the pulse train period ended - // the new PPM values were set, we begin new pulse train - // generation with Update interrupt - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE ; // stop CC2 interrupt - EXTMODULE_TIMER->DIER |= TIM_DIER_UDE ; - EXTMODULE_TIMER->SR &= ~TIM_SR_UIF ; // Clear Update interrupt flag - EXTMODULE_TIMER->DIER |= TIM_DIER_UIE ; // Enable Update interrupt - } + DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE); + USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE); } - if (sr & TIM_SR_UIF && dier & TIM_DIER_UIE) { // Update interrupt enabled and fired - EXTMODULE_TIMER->SR &= ~TIM_SR_UIF ; // Clear flag - if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { - EXTMODULE_TIMER->ARR = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++ ; - if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) { - // we reached the end of PPM pulses - // enable CC2 interrupt (which comes before Update in any case) - // to start new PPM cycle and setup pulses - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear CC1 flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable CC1 interrupt - } - } - } + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; + DEBUG_TIMER_STOP(debugTimerIntPulsesDuration); } diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index 2a749c519..1a2457d71 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -103,7 +103,6 @@ void telemetryPortSetDirectionInput() void sportSendBuffer(uint8_t * buffer, uint32_t count) { - #if 0 telemetryPortSetDirectionOutput(); DMA_InitTypeDef DMA_InitStructure; @@ -131,7 +130,6 @@ void sportSendBuffer(uint8_t * buffer, uint32_t count) // enable interrupt and set it's priority NVIC_EnableIRQ(TELEMETRY_DMA_TX_Stream_IRQ) ; NVIC_SetPriority(TELEMETRY_DMA_TX_Stream_IRQ, 7); - #endif } extern "C" void TELEMETRY_DMA_TX_IRQHandler(void) diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 3154225bb..6654843e5 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -57,7 +57,7 @@ uint32_t Peri1_frequency, Peri2_frequency; GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpioi, gpioj; TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10; RCC_TypeDef rcc; -DMA_Stream_TypeDef dma2_stream2, dma2_stream6, dma1_stream5; +DMA_Stream_TypeDef dma1_stream5, dma1_stream7, dma2_stream1, dma2_stream2, dma2_stream5, dma2_stream6; DMA_TypeDef dma2; USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4; #elif defined(CPUARM) @@ -1355,6 +1355,11 @@ void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) { } void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) { } void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState) { } void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) { } +void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) { } +void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) { } +void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength) { } +void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState) { } +void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState) { } void RCC_PLLI2SConfig(uint32_t PLLI2SN, uint32_t PLLI2SR) { } void RCC_PLLI2SCmd(FunctionalState NewState) { } void RCC_I2SCLKConfig(uint32_t RCC_I2SCLKSource) { } @@ -1363,6 +1368,7 @@ void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct) { } void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) { } void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState) { } void RCC_LSEConfig(uint8_t RCC_LSE) { } +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) { }; FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) { return SET; } ErrorStatus RTC_WaitForSynchro(void) { return SUCCESS; } void unlockFlash() { } diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index 8add4e711..b6f49d241 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -93,7 +93,7 @@ extern GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpio extern TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10; extern USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4; extern RCC_TypeDef rcc; -extern DMA_Stream_TypeDef dma2_stream2, dma2_stream6, dma1_stream5; +extern DMA_Stream_TypeDef dma1_stream5, dma1_stream7, dma2_stream1, dma2_stream2, dma2_stream5, dma2_stream6; extern DMA_TypeDef dma2; #undef GPIOA #undef GPIOB @@ -146,10 +146,16 @@ extern DMA_TypeDef dma2; #undef RCC #define RCC (&rcc) #undef DMA1_Stream5 +#undef DMA1_Stream7 +#undef DMA2_Stream1 #undef DMA2_Stream2 +#undef DMA2_Stream5 #undef DMA2_Stream6 #define DMA1_Stream5 (&dma1_stream5) +#define DMA1_Stream7 (&dma1_stream7) +#define DMA2_Stream1 (&dma2_stream1) #define DMA2_Stream2 (&dma2_stream2) +#define DMA2_Stream5 (&dma2_stream5) #define DMA2_Stream6 (&dma2_stream6) #undef DMA2 #define DMA2 (&dma2) @@ -439,9 +445,6 @@ OS_TID CoCreateTask(FUNCPtr task, void *argv, uint32_t parameter, void * stk, ui #if defined(CPUSTM32) inline void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { } #define TIM_DeInit(...) -#if defined(PCBHORUS) -inline void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) { } -#endif #define TIM_SetCompare2(...) #define TIM_ClearFlag(...) #define TIM_Cmd(...) diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 05555b8ef..66390b053 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -31,6 +31,7 @@ extern "C" { #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h" #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_rcc.h" #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_gpio.h" + #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_tim.h" #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_adc.h" #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_spi.h" #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_i2c.h" @@ -45,6 +46,7 @@ extern "C" { #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Include/stm32f2xx.h" #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc/stm32f2xx_rcc.h" #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc/stm32f2xx_gpio.h" + #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc/stm32f2xx_tim.h" #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc/stm32f2xx_adc.h" #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc/stm32f2xx_spi.h" #include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc/stm32f2xx_i2c.h" @@ -231,10 +233,15 @@ void checkRotaryEncoder(void); // WDT driver #if !defined(SIMU) +#if defined(WATCHDOG_DISABLED) + #define wdt_enable(x) + #define wdt_reset() +#else + #define wdt_enable(x) watchdogInit(x) + #define wdt_reset() IWDG->KR = 0xAAAA +#endif #define wdt_disable() void watchdogInit(unsigned int duration); -#define wdt_enable(x) watchdogInit(x) -#define wdt_reset() IWDG->KR = 0xAAAA #define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) #define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) #define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_SFTRSTF)) diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp new file mode 100644 index 000000000..1a5be7bc4 --- /dev/null +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -0,0 +1,265 @@ +/* + * 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" + +void extmoduleSendNextFrame(); + +void extmoduleStop() +{ + NVIC_DisableIRQ(EXTMODULE_DMA_IRQn); + NVIC_DisableIRQ(EXTMODULE_TIMER_CC_IRQn); + + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + EXTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE); + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } +} + +void extmoduleNoneStart() +{ + if (!IS_TRAINER_EXTERNAL_MODULE()) { + EXTERNAL_MODULE_OFF(); + } + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); + GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_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 = 36000; // 18mS + EXTMODULE_TIMER->CCR2 = 32000; // Update time + 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 extmodulePpmStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz + EXTMODULE_TIMER->ARR = 41000; + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 + EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; + EXTMODULE_TIMER->EGR = 1; + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + setupPulsesPPM(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + + NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); + NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); +} + +void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) +{ + EXTMODULE_TIMER->CCR2 = idleTime; + EXTMODULE_TIMER->CCR1 = delay; + // we are using complementary output so logic has to be reversed here + EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | (positive ? 0 : TIM_CCER_CC1NP); +} + +void extmodulePxxStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + EXTMODULE_TIMER->ARR = 18000; + EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE; + EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs + EXTMODULE_TIMER->CCR1 = 18; + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high + EXTMODULE_TIMER->EGR = 1; // Restart + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + setupPulsesPXX(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + + NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); + NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); +} + +#if defined(DSM2) || defined(MULTIMODULE) +void extmoduleDsm2Start() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); + + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz + EXTMODULE_TIMER->ARR = 44000; // 22mS + EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | TIM_CCER_CC1NP; + EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs + EXTMODULE_TIMER->CCR1 = 0; + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high + EXTMODULE_TIMER->EGR = 1; // Restart + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update + EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + setupPulsesDSM2(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + + NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); + NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); +} +#endif + +void extmoduleCrossfireStart() +{ + EXTERNAL_MODULE_ON(); + + GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); + GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_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_FRAME_PERIOD); + EXTMODULE_TIMER->CCR2 = (2000 * CROSSFIRE_FRAME_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) { + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + 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; + EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); + EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].ppm.pulses); + EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].ppm.ptr - modulePulsesData[EXTERNAL_MODULE].ppm.pulses; + EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + } + else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) { + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + 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; + 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->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + } + else if (s_current_protocol[EXTERNAL_MODULE] >= PROTO_DSM2_LP45 && s_current_protocol[EXTERNAL_MODULE] <= PROTO_DSM2_DSMX) { + EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + 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; + EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); + EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses); + EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - modulePulsesData[EXTERNAL_MODULE].dsm2.pulses; + EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + } + else { + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; + } +} + +extern "C" void EXTMODULE_DMA_IRQHandler() +{ + if (!DMA_GetITStatus(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC)) + return; + + DMA_ClearITPendingBit(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC); + + uint32_t arr = EXTMODULE_TIMER->ARR; + if (arr > 4000) { + EXTMODULE_TIMER->CCR2 = arr - 4000; // 2mS in advance + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + } + else { + setupPulses(EXTERNAL_MODULE); + extmoduleSendNextFrame(); + } +} + +extern "C" void EXTMODULE_TIMER_CC_IRQHandler() +{ + EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt + EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; + setupPulses(EXTERNAL_MODULE); + extmoduleSendNextFrame(); +} diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index f623ce386..f715e9b4f 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -334,9 +334,16 @@ #define INTMODULE_PPM_GPIO GPIOA #define INTMODULE_PPM_GPIO_PIN GPIO_Pin_10 // PA.10 #define INTMODULE_PPM_GPIO_PinSource GPIO_PinSource10 -#define INTMODULE_PPM_GPIO_AF GPIO_AF_TIM1 #define INTMODULE_TIMER TIM1 -#define INTMODULE_TIMER_IRQn TIM1_CC_IRQn +#define INTMODULE_TIMER_CC_IRQn TIM1_CC_IRQn +#define INTMODULE_TIMER_CC_IRQHandler TIM1_CC_IRQHandler +#define INTMODULE_PPM_GPIO_AF GPIO_AF_TIM1 +#define INTMODULE_DMA_CHANNEL DMA_Channel_6 +#define INTMODULE_DMA_STREAM DMA2_Stream5 +#define INTMODULE_DMA_IRQn DMA2_Stream5_IRQn +#define INTMODULE_DMA_IRQHandler DMA2_Stream5_IRQHandler +#define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF5 +#define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) // External Module #define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2) @@ -345,10 +352,17 @@ #define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PD.08 #define EXTMODULE_PPM_GPIO GPIOA #define EXTMODULE_PPM_GPIO_PIN GPIO_Pin_7 // PA.07 +#define EXTMODULE_PPM_GPIO_PinSource GPIO_PinSource7 #define EXTMODULE_TIMER TIM8 #define EXTMODULE_PPM_GPIO_AF GPIO_AF_TIM8 -#define EXTMODULE_PPM_GPIO_PinSource GPIO_PinSource7 -#define EXTMODULE_TIMER_IRQn TIM8_CC_IRQn +#define EXTMODULE_TIMER_CC_IRQn TIM8_CC_IRQn +#define EXTMODULE_TIMER_CC_IRQHandler TIM8_CC_IRQHandler +#define EXTMODULE_DMA_CHANNEL DMA_Channel_7 +#define EXTMODULE_DMA_STREAM DMA2_Stream1 +#define EXTMODULE_DMA_IRQn DMA2_Stream1_IRQn +#define EXTMODULE_DMA_IRQHandler DMA2_Stream1_IRQHandler +#define EXTMODULE_DMA_FLAG_TC DMA_IT_TCIF1 +#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) // Trainer Port #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC) diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index 2c004398e..4d4c6b979 100644 --- a/radio/src/targets/taranis/pulses_driver.cpp +++ b/radio/src/targets/taranis/pulses_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,32 +18,26 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" -void setupPulses(unsigned int port); -void setupPulsesPPM(unsigned int port); -void setupPulsesPXX(unsigned int port); +void intmoduleStop(void); +void extmoduleStop(void); -static void intmodulePxxStart(void); -static void intmodulePxxStop(void); +void intmoduleNoneStart(void); +void intmodulePxxStart(void); #if defined(TARANIS_INTERNAL_PPM) - static void intmodulePpmStart(void); - static void intmodulePpmStop(void); +void intmodulePpmStart(void); #endif -static void extmodulePxxStart(void); -static void extmodulePxxStop(void); + +void extmoduleNoneStart(void); +void extmodulePpmStart(void); +void extmodulePxxStart(void); #if defined(DSM2) || defined(MULTIMODULE) -static void extmoduleDsm2Start(void); -static void extmoduleDsm2Stop(void); +void extmoduleDsm2Start(void); #endif -static void extmodulePpmStart(void); -static void extmodulePpmStop(void); -static void intmoduleNoneStart(void); -static void intmoduleNoneStop(void); -static void extmoduleNoneStart(void); -static void extmoduleNoneStop(void); -static void extmoduleCrossfireStart(void); -static void extmoduleCrossfireStop(void); +void extmoduleCrossfireStart(void); + +void intmoduleSendNextFrame(); void init_pxx(uint32_t port) { @@ -56,9 +50,9 @@ void init_pxx(uint32_t port) void disable_pxx(uint32_t port) { if (port == INTERNAL_MODULE) - intmodulePxxStop(); + intmoduleStop(); else - extmodulePxxStop(); + extmoduleStop(); } #if defined(DSM2) || defined(MULTIMODULE) @@ -72,7 +66,7 @@ void init_dsm2(uint32_t port) void disable_dsm2(uint32_t port) { if (port == EXTERNAL_MODULE) { - extmoduleDsm2Stop(); + extmoduleStop(); } } #endif @@ -92,32 +86,15 @@ void init_ppm(uint32_t port) void disable_ppm(uint32_t port) { if (port == EXTERNAL_MODULE) { - extmodulePpmStop(); + extmoduleStop(); } #if defined(TARANIS_INTERNAL_PPM) else if (port == INTERNAL_MODULE) { - intmodulePpmStop(); + intmoduleStop(); } #endif } -void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - EXTMODULE_TIMER->CCR2 = idleTime; - EXTMODULE_TIMER->CCR1 = delay; - // we are using complementary output so logic has to be reversed here - EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | (positive ? 0 : TIM_CCER_CC1NP); -} - -#if defined(TARANIS_INTERNAL_PPM) -void set_internal_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - INTMODULE_TIMER->CCR2 = idleTime; - INTMODULE_TIMER->CCR3 = delay; - INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (positive ? TIM_CCER_CC3P : 0); -} -#endif - void init_no_pulses(uint32_t port) { if (port == INTERNAL_MODULE) @@ -129,9 +106,9 @@ void init_no_pulses(uint32_t port) void disable_no_pulses(uint32_t port) { if (port == INTERNAL_MODULE) - intmoduleNoneStop(); + intmoduleStop(); else - extmoduleNoneStop(); + extmoduleStop(); } void init_crossfire(uint32_t port) @@ -143,15 +120,27 @@ void init_crossfire(uint32_t port) void disable_crossfire(uint32_t port) { - if (port == EXTERNAL_MODULE) - extmoduleCrossfireStop(); + if (port == EXTERNAL_MODULE) { + extmoduleStop(); + } } -static void intmoduleNoneStart() +void intmoduleStop() +{ + INTERNAL_MODULE_OFF(); + + NVIC_DisableIRQ(INTMODULE_DMA_IRQn); + NVIC_DisableIRQ(INTMODULE_TIMER_CC_IRQn); + + INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + INTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE); + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; +} + +void intmoduleNoneStart() { INTERNAL_MODULE_OFF(); - // Timer1, channel 3 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = INTMODULE_PPM_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; @@ -159,241 +148,115 @@ static void intmoduleNoneStart() GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(INTMODULE_PPM_GPIO, &GPIO_InitStructure); - GPIO_SetBits(INTMODULE_PPM_GPIO, INTMODULE_PPM_GPIO_PIN); // Set high - - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTMODULE_TIMER->ARR = 36000; // 18mS - INTMODULE_TIMER->CCR2 = 32000; // Update time - INTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - - INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - - INTMODULE_TIMER->CCMR2 = 0; - INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz + INTMODULE_TIMER->ARR = 36000; // 18mS + INTMODULE_TIMER->CCR2 = 32000; // Update time + INTMODULE_TIMER->EGR = 1; // Restart + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(INTMODULE_TIMER_IRQn); - NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); + + NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); } -static void intmoduleNoneStop() -{ - NVIC_DisableIRQ(INTMODULE_TIMER_IRQn); - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; -} - -static void extmoduleNoneStart() -{ - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); - GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->ARR = 36000; // 18mS - EXTMODULE_TIMER->CCR2 = 32000; // Update time - EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - - EXTMODULE_TIMER->CCMR2 = 0; - EXTMODULE_TIMER->EGR = 1; // Restart - - EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmoduleNoneStop() -{ - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn); - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; -} - -static void extmoduleCrossfireStart() -{ - EXTERNAL_MODULE_ON(); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_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_PPM_GPIO, &GPIO_InitStructure); - GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->ARR = (2000 * CROSSFIRE_FRAME_PERIOD); - EXTMODULE_TIMER->CCR2 = 32000; // Update time - EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - - EXTMODULE_TIMER->CCMR2 = 0; - EXTMODULE_TIMER->EGR = 1; // Restart - - EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmoduleCrossfireStop() -{ - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn); - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } -} - -static void intmodulePxxStart() +void intmodulePxxStart() { INTERNAL_MODULE_ON(); - // Timer1, channel 3 - setupPulsesPXX(INTERNAL_MODULE); // TODO not here! + GPIO_PinAFConfig(INTMODULE_PPM_GPIO, INTMODULE_PPM_GPIO_PinSource, INTMODULE_PPM_GPIO_AF); GPIO_InitTypeDef GPIO_InitStructure; - - GPIO_PinAFConfig(INTMODULE_PPM_GPIO, INTMODULE_PPM_GPIO_PinSource, INTMODULE_PPM_GPIO_AF); GPIO_InitStructure.GPIO_Pin = INTMODULE_PPM_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(INTMODULE_PPM_GPIO, &GPIO_InitStructure); - + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTMODULE_TIMER->ARR = 18000; // 9mS - INTMODULE_TIMER->CCR2 = 15000; // Update time - INTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - INTMODULE_TIMER->CR2 = TIM_CR2_OIS3; // O/P idle high - INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs - INTMODULE_TIMER->CCR3 = modulePulsesData[INTERNAL_MODULE].pxx.pulses[0]; - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high - INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->DIER |= TIM_DIER_CC3DE; // Enable DMA on CC3 match - INTMODULE_TIMER->DCR = 15; // DMA to CC1 - - // Enable the DMA channel here, DMA2 stream 6, channel 6 - DMA2_Stream6->CR &= ~DMA_SxCR_EN; // Disable DMA - DMA2->HIFCR = DMA_HIFCR_CTCIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 | DMA_HIFCR_CFEIF6; // Write ones to clear bits - DMA2_Stream6->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 - | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL; - DMA2_Stream6->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->DMAR); - DMA2_Stream6->M0AR = CONVERT_PTR_UINT(&modulePulsesData[INTERNAL_MODULE].pxx.pulses[1]); - DMA2_Stream6->CR |= DMA_SxCR_EN; // Enable DMA - - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + INTMODULE_TIMER->ARR = 18000; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE; + INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs + INTMODULE_TIMER->CCR3 = 16; + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high + INTMODULE_TIMER->EGR = 1; // Restart + INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(INTMODULE_TIMER_IRQn); - NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); -} -static void intmodulePxxStop() -{ - DMA2_Stream6->CR &= ~DMA_SxCR_EN; // Disable DMA - NVIC_DisableIRQ(INTMODULE_TIMER_IRQn); - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTERNAL_MODULE_OFF(); + setupPulsesPXX(INTERNAL_MODULE); + intmoduleSendNextFrame(); + + NVIC_EnableIRQ(INTMODULE_DMA_IRQn); + NVIC_SetPriority(INTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); } #if defined(TARANIS_INTERNAL_PPM) -// PPM output -// Timer 1, channel 1 on PA8 for prototype -// Pin is AF1 function for timer 1 -static void intmodulePpmStart() +void intmodulePpmStart() { INTERNAL_MODULE_ON(); - // Timer1 - configure_pins(INTMODULE_PPM_GPIO_PIN, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25); - + GPIO_PinAFConfig(INTMODULE_PPM_GPIO, INTMODULE_PPM_GPIO_PinSource, INTMODULE_PPM_GPIO_AF); + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = INTMODULE_PPM_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(INTMODULE_PPM_GPIO, &GPIO_InitStructure); + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - - // setupPulsesPPM() is also configuring registers, - // so it has to be called after the peripheral is enabled - setupPulsesPPM(INTERNAL_MODULE); - - INTMODULE_TIMER->ARR = *modulePulsesData[INTERNAL_MODULE].ppm.ptr++; - INTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - - INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1 - INTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC2PE; // PWM mode 1 + INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz + INTMODULE_TIMER->ARR = 41000; + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1 INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; INTMODULE_TIMER->EGR = 1; INTMODULE_TIMER->DIER = TIM_DIER_UDE; - - INTMODULE_TIMER->SR &= ~TIM_SR_UIF; // Clear flag - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; - INTMODULE_TIMER->DIER |= TIM_DIER_UIE; - INTMODULE_TIMER->CR1 = TIM_CR1_CEN; - NVIC_EnableIRQ(INTMODULE_TIMER_IRQn); - NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); - NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); - NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 7); + + setupPulsesPPM(INTERNAL_MODULE); + intmoduleSendNextFrame(); + + NVIC_EnableIRQ(INTMODULE_DMA_IRQn); + NVIC_SetPriority(INTMODULE_DMA_IRQn, 7); + NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); + NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); } -static void intmodulePpmStop() +void set_internal_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) { - NVIC_DisableIRQ(INTMODULE_TIMER_IRQn); - NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn); - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE & ~TIM_DIER_UIE; - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - - INTERNAL_MODULE_OFF(); + INTMODULE_TIMER->CCR2 = idleTime; + INTMODULE_TIMER->CCR3 = delay; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (positive ? TIM_CCER_CC3P : 0); } -#endif // #if defined(TARANIS_INTERNAL_PPM) +#endif // defined(TARANIS_INTERNAL_PPM) -#if !defined(SIMU) -extern "C" void TIM1_CC_IRQHandler() +void intmoduleSendNextFrame() { - DEBUG_INTERRUPT(INT_TIM1CC); - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // stop this interrupt - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag - DMA2_Stream6->CR &= ~DMA_SxCR_EN; // disable DMA, it will have the whole of the execution time of setupPulses() to actually stop - - setupPulses(INTERNAL_MODULE); - if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) { - DMA2->HIFCR = DMA_HIFCR_CTCIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 | DMA_HIFCR_CFEIF6; - DMA2_Stream6->M0AR = CONVERT_PTR_UINT(&modulePulsesData[INTERNAL_MODULE].pxx.pulses[1]); - DMA2_Stream6->CR |= DMA_SxCR_EN; // enable DMA - INTMODULE_TIMER->CCR3 = modulePulsesData[INTERNAL_MODULE].pxx.pulses[0]; - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // enable this interrupt + 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->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA } #if defined(TARANIS_INTERNAL_PPM) else if (s_current_protocol[INTERNAL_MODULE] == PROTO_PPM) { - INTMODULE_TIMER->DIER |= TIM_DIER_UDE; - INTMODULE_TIMER->SR &= ~TIM_SR_UIF; - INTMODULE_TIMER->DIER |= TIM_DIER_UIE; + 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].ppm.pulses); + INTMODULE_DMA_STREAM->NDTR = modulePulsesData[INTERNAL_MODULE].ppm.ptr - modulePulsesData[INTERNAL_MODULE].ppm.pulses; + INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA } #endif else { @@ -401,226 +264,29 @@ extern "C" void TIM1_CC_IRQHandler() } } -extern "C" void TIM1_UP_TIM10_IRQHandler() +extern "C" void INTMODULE_DMA_IRQHandler() { - DEBUG_INTERRUPT(INT_TIM1); - INTMODULE_TIMER->SR &= ~TIM_SR_UIF; // Clear flag + if (!DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC)) + return; - INTMODULE_TIMER->ARR = *modulePulsesData[INTERNAL_MODULE].ppm.ptr++; - if (*modulePulsesData[INTERNAL_MODULE].ppm.ptr == 0) { - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear this flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - } -} -#endif + DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC); -void extmodulePxxStart() -{ - EXTERNAL_MODULE_ON(); - - setupPulsesPXX(EXTERNAL_MODULE); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->ARR = 18000; // 9mS - EXTMODULE_TIMER->CCR2 = 15000; // Update time - EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE; - EXTMODULE_TIMER->CR2 = TIM_CR2_OIS1; // O/P idle high - EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].pxx.pulses[0]; - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high - EXTMODULE_TIMER->EGR = 1; // Restart - - EXTMODULE_TIMER->DIER |= TIM_DIER_CC1DE; // Enable DMA on CC1 match - EXTMODULE_TIMER->DCR = 13; // DMA to CC1 - - // Enable the DMA channel here, DMA2 stream 2, channel 7 - DMA2_Stream2->CR &= ~DMA_SxCR_EN; // Disable DMA - DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2; // Write ones to clear bits - DMA2_Stream2->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 - | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL; - DMA2_Stream2->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->DMAR); - DMA2_Stream2->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].pxx.pulses[1]); - DMA2_Stream2->CR |= DMA_SxCR_EN; // Enable DMA - - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmodulePxxStop() -{ - DMA2_Stream2->CR &= ~DMA_SxCR_EN; // Disable DMA - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn); - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } -} - -#if defined(DSM2) || defined(MULTIMODULE) -static void extmoduleDsm2Start() -{ - EXTERNAL_MODULE_ON(); - - setupPulsesDSM2(EXTERNAL_MODULE); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF); - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure); - - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER->ARR = 44000; // 22mS - EXTMODULE_TIMER->CCR2 = 40000; // Update time - EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | TIM_CCER_CC1NP; - EXTMODULE_TIMER->CR2 = TIM_CR2_OIS1; // O/P idle high - EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[0]; - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high - EXTMODULE_TIMER->EGR = 1; // Restart - - EXTMODULE_TIMER->DIER |= TIM_DIER_CC1DE; // Enable DMA on CC1 match - EXTMODULE_TIMER->DCR = 13; // DMA to CC1 - - // Enable the DMA channel here, DMA2 stream 2, channel 7 - DMA2_Stream2->CR &= ~DMA_SxCR_EN; // Disable DMA - DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2; // Write ones to clear bits - DMA2_Stream2->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 - | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_PFCTRL; - DMA2_Stream2->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->DMAR); - DMA2_Stream2->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[1]); -// DMA2_Stream2->FCR = 0x05; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0; -// DMA2_Stream2->NDTR = 100; - DMA2_Stream2->CR |= DMA_SxCR_EN; // Enable DMA - - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; // Toggle CC1 o/p - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); -} - -static void extmoduleDsm2Stop() -{ - DMA2_Stream2->CR &= ~DMA_SxCR_EN; // Disable DMA - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn); - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } -} -#endif - -static void extmodulePpmStart() -{ - EXTERNAL_MODULE_ON(); - - configure_pins(EXTMODULE_PPM_GPIO_PIN, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_3 | PIN_OS25); - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - - // setupPulsesPPM() is also configuring registers, - // so it has to be called after the peripheral is enabled - setupPulsesPPM(EXTERNAL_MODULE); - - EXTMODULE_TIMER->ARR = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++; - EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS from 30MHz - - EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 - EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; - EXTMODULE_TIMER->EGR = 1; - EXTMODULE_TIMER->DIER = TIM_DIER_UDE; - - EXTMODULE_TIMER->SR &= ~TIM_SR_UIF; // Clear flag - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; - EXTMODULE_TIMER->DIER |= TIM_DIER_UIE; - - EXTMODULE_TIMER->CR1 = TIM_CR1_CEN; - NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); - NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn); - NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 7); -} - -static void extmodulePpmStop() -{ - NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn); - NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn); - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE & ~TIM_DIER_UIE; - EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - if (!IS_TRAINER_EXTERNAL_MODULE()) { - EXTERNAL_MODULE_OFF(); - } -} - -#if !defined(SIMU) -extern "C" void TIM8_CC_IRQHandler() -{ - EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // stop this interrupt - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - - setupPulses(EXTERNAL_MODULE); - - if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) { - DMA2_Stream2->CR &= ~DMA_SxCR_EN; // Disable DMA - DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2; // Write ones to clear bits - DMA2_Stream2->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].pxx.pulses[1]); - DMA2_Stream2->CR |= DMA_SxCR_EN; // Enable DMA - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].pxx.pulses[0]; - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - } -#if defined(DSM2) - else if ((s_current_protocol[EXTERNAL_MODULE] >= PROTO_DSM2_LP45 && s_current_protocol[EXTERNAL_MODULE] <= PROTO_DSM2_DSMX) || IS_MULTIMODULE_PROTOCOL (s_current_protocol[EXTERNAL_MODULE])) - -{ - DMA2_Stream2->CR &= ~DMA_SxCR_EN; // Disable DMA - DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTEIF2 | DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2; // Write ones to clear bits - DMA2_Stream2->M0AR = CONVERT_PTR_UINT(&modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[1]); - DMA2_Stream2->CR |= DMA_SxCR_EN; // Enable DMA - EXTMODULE_TIMER->CCR1 = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses[0]; - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - } -#endif - else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { - EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; - EXTMODULE_TIMER->SR &= ~TIM_SR_UIF; // Clear this flag - EXTMODULE_TIMER->DIER |= TIM_DIER_UIE; // Enable this interrupt + uint32_t arr = INTMODULE_TIMER->ARR; + if (arr > 5000) { + INTMODULE_TIMER->CCR2 = arr - 4000; // 2mS in advance + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt } else { - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + setupPulses(INTERNAL_MODULE); + intmoduleSendNextFrame(); } } -extern "C" void TIM8_UP_TIM13_IRQHandler() +extern "C" void INTMODULE_TIMER_CC_IRQHandler() { - DEBUG_INTERRUPT(INT_TIM8); - EXTMODULE_TIMER->SR &= ~TIM_SR_UIF; // Clear flag - - EXTMODULE_TIMER->ARR = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++; - if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) { - EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear this flag - EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - } + INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; + setupPulses(INTERNAL_MODULE); + intmoduleSendNextFrame(); } -#endif