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)
This commit is contained in:
Bertrand Songis
2016-06-05 22:34:16 +02:00
parent 5767be27b6
commit 7ef9992349
19 changed files with 1138 additions and 1118 deletions
+18 -6
View File
@@ -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)
+26 -31
View File
@@ -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
+10 -16
View File
@@ -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);
+16 -4
View File
@@ -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; i<lastCh; i++) {
int16_t v = limit((int16_t)-PPM_range, channelOutputs[i], (int16_t)PPM_range) + 2*PPM_CH_CENTER(i);
rest -= v;
#if defined(CPUSTM32)
*ppmPulsesData->ptr++ = 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
+6 -5
View File
@@ -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);
+59 -22
View File
@@ -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);
+154 -84
View File
@@ -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);
}
+1 -2
View File
@@ -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();
+5
View File
@@ -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 );
@@ -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 CNT<CCR1(delay) and ON if bigger
// CCR1 register defines duration of pulse length and is constant
// AAR register defines duration of each pulse, it is
// updated after every pulse in Update interrupt handler.
// CCR2 register defines duration of no pulses (time between two pulse trains)
// it is calculated every round to have PPM period constant.
// CC2 interrupt is then used to setup new PPM values for the
// next PPM pulses train.
EXTMODULE_TIMER->CR1 &= ~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 CNT<CCR1(delay) and ON if bigger (up to AAR,which is pulse length)
EXTMODULE_TIMER->CCMR1 = 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();
}
+13 -5
View File
@@ -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
+125 -473
View File
@@ -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 CNT<CCR1(delay) and ON if bigger
// CCR1 register defines duration of pulse length and is constant
// AAR register defines duration of each pulse, it is
// updated after every pulse in Update interrupt handler.
// CCR2 register defines duration of no pulses (time between two pulse trains)
// it is calculated every round to have PPM period constant.
// CC2 interrupt is then used to setup new PPM values for the
// next PPM pulses train.
// stop timer
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 = EXTMODULE_TIMER_FREQ / 2000000 - 1 ; // 0.5uS (2Mhz)
// CH1 PWM mode 1, CH1 out is OFF if CNT<CCR1(delay) and ON if bigger (up to AAR,which is pulse length)
EXTMODULE_TIMER->CCMR1 = 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);
}
@@ -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)
+7 -1
View File
@@ -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() { }
+7 -4
View File
@@ -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(...)
+9 -2
View File
@@ -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))
@@ -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();
}
+18 -4
View File
@@ -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)
+123 -457
View File
@@ -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