External serial driver moved to a separate driver

This commit is contained in:
Raphael Coeffic
2022-03-20 16:22:12 +01:00
parent 803b472c85
commit ffefd0f6dd
17 changed files with 885 additions and 618 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ struct etx_serial_init {
void (*on_error)(); // = nullptr;
};
struct etx_hal_serial_driver_t {
struct etx_serial_driver_t {
// Init module communication
void (*init)(const etx_serial_init* params);
+2
View File
@@ -41,6 +41,8 @@
#include "intmodule_serial_driver.h"
#endif
#include "extmodule_driver.h"
#define UPDATE_MULTI_EXT_BIN ".bin"
class MultiFirmwareUpdateDriver
+75 -67
View File
@@ -21,6 +21,7 @@
#include "opentx.h"
#include "mixer_scheduler.h"
#include "hal/module_driver.h"
#if defined(INTMODULE_USART)
#include "intmodule_serial_driver.h"
@@ -99,14 +100,13 @@ static void setupPulsesCrossfire(uint8_t idx, CrossfirePulsesData* p_data,
}
}
static void setupPulsesCrossfire(uint8_t idx, int16_t* channels, uint8_t nChannels)
static void crossfireSetupMixerScheduler(uint8_t module)
{
if (idx == INTERNAL_MODULE) {
auto* p_data = &intmodulePulsesData.crossfire;
setupPulsesCrossfire(idx, p_data, 0, channels, nChannels);
} else if (telemetryProtocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
auto* p_data = &extmodulePulsesData.crossfire;
setupPulsesCrossfire(idx, p_data, TELEMETRY_ENDPOINT_SPORT, channels, nChannels);
ModuleSyncStatus& status = getModuleSyncStatus(module);
if (status.isValid()) {
mixerSchedulerSetPeriod(module, status.getAdjustedRefreshRate());
} else {
mixerSchedulerSetPeriod(module, CROSSFIRE_PERIOD);
}
}
@@ -137,83 +137,91 @@ static const etx_serial_init intmoduleCrossfireInitParams = {
.on_receive = intmoduleCRSF_rx,
.on_error = nullptr,
};
#endif
static void* crossfireInit(uint8_t module)
static void* crossfireInitInternal(uint8_t module)
{
if (module == INTERNAL_MODULE) {
#if defined(INTERNAL_MODULE_CRSF)
// serial port setup
etx_serial_init params(intmoduleCrossfireInitParams);
params.baudrate = CROSSFIRE_BAUDRATE;
(void)module;
// wakeup mixer when rx buffer is quarter full (16 bytes)
params.on_receive = intmoduleCRSF_rx;
// serial port setup
etx_serial_init params(intmoduleCrossfireInitParams);
params.baudrate = CROSSFIRE_BAUDRATE;
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&params);
#endif
} else {
// TODO: setup S.PORT
// - for now, the init is still done via telemetryWakeup()....
telemetryInit(PROTOCOL_TELEMETRY_CROSSFIRE);
}
// wakeup mixer when rx buffer is quarter full (16 bytes)
params.on_receive = intmoduleCRSF_rx;
// mixer setup
mixerSchedulerSetPeriod(module, CROSSFIRE_PERIOD);
return (void*)(ulong)module;
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&params);
return nullptr;
}
static void crossfireDeInit(void* context)
static void crossfireDeInitInternal(void* context)
{
ulong module = (ulong)context;
(void)context;
if (module == INTERNAL_MODULE) {
#if defined(INTERNAL_MODULE_CRSF)
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
intmoduleStop();
intmoduleFifo.clear();
#endif
} else {
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
}
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
intmoduleStop();
intmoduleFifo.clear();
}
static void crossfireSetupPulses(void* context, int16_t* channels, uint8_t nChannels)
static void crossfireSetupPulsesInternal(void* context, int16_t* channels, uint8_t nChannels)
{
ulong module = (ulong)context;
ModuleSyncStatus& status = getModuleSyncStatus(module);
if (status.isValid()) {
mixerSchedulerSetPeriod(module, status.getAdjustedRefreshRate());
} else {
mixerSchedulerSetPeriod(module, CROSSFIRE_PERIOD);
}
setupPulsesCrossfire(module, channels, nChannels);
auto* p_data = &intmodulePulsesData.crossfire;
crossfireSetupMixerScheduler(INTERNAL_MODULE);
setupPulsesCrossfire(INTERNAL_MODULE, p_data, 0, channels, nChannels);
}
static void crossfireSendPulses(void* context)
static void crossfireSendPulsesInternal(void* context)
{
ulong module = (ulong)context;
(void)context;
if (module == INTERNAL_MODULE) {
#if defined(INTERNAL_MODULE_CRSF)
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.crossfire.pulses,
intmodulePulsesData.crossfire.length);
#endif
} else {
sportSendBuffer(extmodulePulsesData.crossfire.pulses,
extmodulePulsesData.crossfire.length);
}
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.crossfire.pulses,
intmodulePulsesData.crossfire.length);
}
#include "hal/module_driver.h"
etx_module_driver_t CrossfireModuleDriver = {
etx_module_driver_t CrossfireInternalDriver = {
.protocol = PROTOCOL_CHANNELS_CROSSFIRE,
.init = crossfireInit,
.deinit = crossfireDeInit,
.setupPulses = crossfireSetupPulses,
.sendPulses = crossfireSendPulses
.init = crossfireInitInternal,
.deinit = crossfireDeInitInternal,
.setupPulses = crossfireSetupPulsesInternal,
.sendPulses = crossfireSendPulsesInternal,
};
#endif
static void* crossfireInitExternal(uint8_t module)
{
telemetryInit(PROTOCOL_TELEMETRY_CROSSFIRE);
mixerSchedulerSetPeriod(module, CROSSFIRE_PERIOD);
return nullptr;
}
static void crossfireDeInitExternal(void* context)
{
(void)context;
telemetryProtocol = 0xFF;
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
}
static void crossfireSetupPulsesExternal(void* context, int16_t* channels, uint8_t nChannels)
{
auto* p_data = &extmodulePulsesData.crossfire;
crossfireSetupMixerScheduler(EXTERNAL_MODULE);
setupPulsesCrossfire(EXTERNAL_MODULE, p_data, TELEMETRY_ENDPOINT_SPORT,
channels, nChannels);
}
static void crossfireSendPulsesExternal(void* context)
{
(void)context;
sportSendBuffer(extmodulePulsesData.crossfire.pulses,
extmodulePulsesData.crossfire.length);
}
etx_module_driver_t CrossfireExternalDriver = {
.protocol = PROTOCOL_CHANNELS_CROSSFIRE,
.init = crossfireInitExternal,
.deinit = crossfireDeInitExternal,
.setupPulses = crossfireSetupPulsesExternal,
.sendPulses = crossfireSendPulsesExternal
};
+2 -1
View File
@@ -23,4 +23,5 @@
#include "hal/module_driver.h"
extern etx_module_driver_t CrossfireModuleDriver;
extern etx_module_driver_t CrossfireInternalDriver;
extern etx_module_driver_t CrossfireExternalDriver;
+329 -249
View File
@@ -34,6 +34,8 @@
#include "intmodule_pulses_driver.h"
#endif
#include "extmodule_driver.h"
#if defined(CROSSFIRE)
#include "pulses/crossfire.h"
#endif
@@ -277,10 +279,255 @@ uint8_t getRequiredProtocol(uint8_t module)
return protocol;
}
#if defined(HARDWARE_INTERNAL_MODULE)
static void* internalModuleContext = nullptr;
static const etx_module_driver_t* internalModuleDriver = nullptr;
static void enablePulsesInternalModule(uint8_t protocol)
{
// start new protocol hardware here
if (internalModuleDriver) {
internalModuleDriver->deinit(internalModuleContext);
internalModuleContext = nullptr;
internalModuleDriver = nullptr;
} else {
intmoduleStop();
}
switch (protocol) {
#if defined(PXX1) && !defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_PULSES:
intmodulePxx1PulsesStart();
#if defined(INTMODULE_HEARTBEAT)
init_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
break;
#endif
#if defined(PXX1) && defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
intmodulePxx1SerialStart();
#if defined(INTMODULE_HEARTBEAT)
init_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
break;
#endif
#if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
internalModuleContext = Pxx2InternalDriver.init(INTERNAL_MODULE);
internalModuleDriver = &Pxx2InternalDriver;
break;
#endif
#if defined(INTERNAL_MODULE_MULTI)
case PROTOCOL_CHANNELS_MULTIMODULE:
// TODO: use module interface
// serial port setup
intmodulePulsesData.multi.initFrame();
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&multiSerialInitParams);
// mixer setup
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
// reset status
getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false;
getMultiModuleStatus(INTERNAL_MODULE).flags = 0;
#if defined(MULTI_PROTOLIST)
TRACE("enablePulsesInternalModule(): trigger scan");
MultiRfProtocols::instance(INTERNAL_MODULE)->triggerScan();
TRACE("counter = %d", moduleState[INTERNAL_MODULE].counter);
#endif
break;
#endif
#if defined(INTERNAL_MODULE_CRSF)
case PROTOCOL_CHANNELS_CROSSFIRE:
internalModuleContext = CrossfireInternalDriver.init(INTERNAL_MODULE);
internalModuleDriver = &CrossfireInternalDriver;
break;
#endif
#if defined(INTERNAL_MODULE_PPM)
case PROTOCOL_CHANNELS_PPM:
intmodulePpmStart();
mixerSchedulerSetPeriod(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE));
break;
#endif
#if defined(AFHDS2)
case PROTOCOL_CHANNELS_AFHDS2A:
// serial port setup
resetPulsesAFHDS2();
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&afhds2SerialInitParams)
// mixer setup
mixerSchedulerSetPeriod(INTERNAL_MODULE, AFHDS2_PERIOD);
break;
#endif
default:
// internal module stopped, use default mixer period
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
break;
}
}
bool setupPulsesInternalModule(uint8_t protocol)
{
uint8_t channelStart = g_model.moduleData[INTERNAL_MODULE].channelsStart;
int16_t* channels = &channelOutputs[channelStart];
uint8_t nChannels = 16; // TODO: MAX_CHANNELS - channelsStart
if (internalModuleDriver) {
internalModuleDriver->setupPulses(internalModuleContext,
channels, nChannels);
return true;
}
switch (protocol) {
#if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_PULSES:
intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE);
return true;
#endif
#if defined(PXX1) && defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE);
return true;
#endif
#if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM)
case PROTOCOL_CHANNELS_PPM:
setupPulsesPPMInternalModule();
return true;
#endif
#if defined(INTERNAL_MODULE_MULTI)
case PROTOCOL_CHANNELS_MULTIMODULE:
setupPulsesMultiInternalModule();
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
return true;
#endif
#if defined(AFHDS2)
case PROTOCOL_CHANNELS_AFHDS2A:
{
ModuleSyncStatus& status = getModuleSyncStatus(INTERNAL_MODULE);
mixerSchedulerSetPeriod(
INTERNAL_MODULE,
status.isValid() ? status.getAdjustedRefreshRate() : AFHDS2_PERIOD);
status.invalidate();
setupPulsesAFHDS2();
return true;
}
#endif
default:
return false;
}
}
void stopPulsesInternalModule()
{
if (moduleState[INTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
if (internalModuleDriver) {
internalModuleDriver->deinit(internalModuleContext);
internalModuleDriver = nullptr;
internalModuleContext = nullptr;
} else {
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
intmoduleStop();
}
moduleState[INTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
}
}
void intmoduleSendNextFrame()
{
if (internalModuleDriver) {
internalModuleDriver->sendPulses(internalModuleContext);
return;
}
switch (moduleState[INTERNAL_MODULE].protocol) {
#if defined(INTERNAL_MODULE_PPM)
case PROTOCOL_CHANNELS_PPM:
intmoduleSendNextFramePPM(
intmodulePulsesData.ppm.pulses,
intmodulePulsesData.ppm.ptr - intmodulePulsesData.ppm.pulses);
break;
#endif
#if defined(PXX1)
#if defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.pxx_uart.getData(),
intmodulePulsesData.pxx_uart.getSize());
break;
#else
case PROTOCOL_CHANNELS_PXX1_PULSES:
intmoduleSendNextFramePxx1(intmodulePulsesData.pxx.getData(),
intmodulePulsesData.pxx.getSize());
break;
#endif
#endif
#if defined(INTERNAL_MODULE_MULTI)
case PROTOCOL_CHANNELS_MULTIMODULE:
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.multi.getData(),
intmodulePulsesData.multi.getSize());
break;
#endif
#if defined(AFHDS2)
case PROTOCOL_CHANNELS_AFHDS2A: {
uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses;
uint16_t size = intmodulePulsesData.flysky.ptr - data;
intmoduleSendBuffer(data, size);
} break;
#endif
}
}
bool setupPulsesInternalModule()
{
uint8_t protocol = getRequiredProtocol(INTERNAL_MODULE);
heartbeat |= (HEART_TIMER_PULSES << INTERNAL_MODULE);
if (moduleState[INTERNAL_MODULE].protocol != protocol) {
enablePulsesInternalModule(protocol);
moduleState[INTERNAL_MODULE].protocol = protocol;
return false;
}
else {
return setupPulsesInternalModule(protocol);
}
}
#endif
#if defined(HARDWARE_EXTERNAL_MODULE)
static void* externalModuleContext = nullptr;
static const etx_module_driver_t* externalModuleDriver = nullptr;
void enablePulsesExternalModule(uint8_t protocol)
{
// start new protocol hardware here
if (externalModuleDriver) {
externalModuleDriver->deinit(externalModuleContext);
externalModuleDriver = nullptr;
externalModuleContext = nullptr;
} else {
extmoduleStop();
}
switch (protocol) {
#if defined(PXX1)
@@ -301,16 +548,20 @@ void enablePulsesExternalModule(uint8_t protocol)
case PROTOCOL_CHANNELS_DSM2_LP45:
case PROTOCOL_CHANNELS_DSM2_DSM2:
case PROTOCOL_CHANNELS_DSM2_DSMX:
#if defined(PCBSKY9X)
extmoduleSerialStart(DSM2_BAUDRATE, DSM2_PERIOD * 2000, false);
#else
extmoduleSerialStart();
mixerSchedulerSetPeriod(EXTERNAL_MODULE, DSM2_PERIOD);
#endif
break;
#endif
#if defined(CROSSFIRE)
case PROTOCOL_CHANNELS_CROSSFIRE:
EXTERNAL_MODULE_ON();
if (CrossfireModuleDriver.init)
CrossfireModuleDriver.init(EXTERNAL_MODULE);
externalModuleContext = CrossfireExternalDriver.init(EXTERNAL_MODULE);
externalModuleDriver = &CrossfireExternalDriver;
break;
#endif
@@ -323,18 +574,24 @@ void enablePulsesExternalModule(uint8_t protocol)
#if defined(PXX2) && defined(EXTMODULE_USART)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
Pxx2ModuleDriver.init(EXTERNAL_MODULE);
externalModuleContext = Pxx2ExternalDriver.init(EXTERNAL_MODULE);
externalModuleDriver = &Pxx2ExternalDriver;
break;
case PROTOCOL_CHANNELS_PXX2_LOWSPEED:
Pxx2LowSpeedModuleDriver.init(EXTERNAL_MODULE);
externalModuleContext = Pxx2LowSpeedExternalDriver.init(EXTERNAL_MODULE);
externalModuleDriver = &Pxx2LowSpeedExternalDriver;
break;
#endif
#if defined(MULTIMODULE)
case PROTOCOL_CHANNELS_MULTIMODULE:
#if defined(PCBSKY9X)
extmoduleSerialStart(MULTIMODULE_BAUDRATE, MULTIMODULE_PERIOD * 2000, true);
#else
extmoduleSerialStart();
mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD);
#endif
getMultiModuleStatus(EXTERNAL_MODULE).failsafeChecked = false;
getMultiModuleStatus(EXTERNAL_MODULE).flags = 0;
#if defined(MULTI_PROTOLIST)
@@ -345,8 +602,12 @@ void enablePulsesExternalModule(uint8_t protocol)
#if defined(SBUS)
case PROTOCOL_CHANNELS_SBUS:
#if defined(PCBSKY9X)
extmoduleSerialStart(SBUS_BAUDRATE, SBUS_PERIOD_HALF_US, false);
#else
extmoduleSerialStart();
mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD);
#endif
break;
#endif
@@ -374,10 +635,16 @@ void enablePulsesExternalModule(uint8_t protocol)
bool setupPulsesExternalModule(uint8_t protocol)
{
int16_t* channels =
&channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart];
uint8_t channelStart = g_model.moduleData[EXTERNAL_MODULE].channelsStart;
int16_t* channels = &channelOutputs[channelStart];
uint8_t nChannels = 16; // TODO: MAX_CHANNELS - channelsStart
if (externalModuleDriver) {
externalModuleDriver->setupPulses(externalModuleContext,
channels, nChannels);
return true;
}
switch (protocol) {
#if defined(PXX1)
@@ -392,13 +659,6 @@ bool setupPulsesExternalModule(uint8_t protocol)
return true;
#endif
#if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
case PROTOCOL_CHANNELS_PXX2_LOWSPEED:
Pxx2ModuleDriver.setupPulses((void*)EXTERNAL_MODULE, channels, nChannels);
return true;
#endif
#if defined(SBUS)
case PROTOCOL_CHANNELS_SBUS:
setupPulsesSbus();
@@ -415,15 +675,6 @@ bool setupPulsesExternalModule(uint8_t protocol)
return true;
#endif
#if defined(CROSSFIRE)
case PROTOCOL_CHANNELS_CROSSFIRE:
if (CrossfireModuleDriver.setupPulses) {
CrossfireModuleDriver.setupPulses((void*)EXTERNAL_MODULE, channels,
nChannels);
}
return true;
#endif
#if defined(GHOST)
case PROTOCOL_CHANNELS_GHOST:
{
@@ -466,255 +717,85 @@ bool setupPulsesExternalModule(uint8_t protocol)
return false;
}
}
#endif
#if defined(HARDWARE_INTERNAL_MODULE)
static void enablePulsesInternalModule(uint8_t protocol)
void extmoduleSendNextFrame()
{
// start new protocol hardware here
switch (protocol) {
#if defined(PXX1) && !defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_PULSES:
intmodulePxx1PulsesStart();
#if defined(INTMODULE_HEARTBEAT)
init_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
break;
#endif
#if defined(PXX1) && defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
intmodulePxx1SerialStart();
#if defined(INTMODULE_HEARTBEAT)
init_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
break;
#endif
#if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
Pxx2ModuleDriver.init(INTERNAL_MODULE);
break;
#endif
#if defined(INTERNAL_MODULE_MULTI)
case PROTOCOL_CHANNELS_MULTIMODULE:
// serial port setup
intmodulePulsesData.multi.initFrame();
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&multiSerialInitParams);
// mixer setup
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
// reset status
getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false;
getMultiModuleStatus(INTERNAL_MODULE).flags = 0;
#if defined(MULTI_PROTOLIST)
TRACE("enablePulsesInternalModule(): trigger scan");
MultiRfProtocols::instance(INTERNAL_MODULE)->triggerScan();
TRACE("counter = %d", moduleState[INTERNAL_MODULE].counter);
#endif
break;
#endif
#if defined(INTERNAL_MODULE_CRSF)
case PROTOCOL_CHANNELS_CROSSFIRE:
if (CrossfireModuleDriver.init) {
// TODO: save context
CrossfireModuleDriver.init(INTERNAL_MODULE);
}
break;
#endif
#if defined(INTERNAL_MODULE_PPM)
case PROTOCOL_CHANNELS_PPM:
intmodulePpmStart();
mixerSchedulerSetPeriod(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE));
break;
#endif
#if defined(AFHDS2)
case PROTOCOL_CHANNELS_AFHDS2A:
// serial port setup
resetPulsesAFHDS2();
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&afhds2SerialInitParams)
// mixer setup
mixerSchedulerSetPeriod(INTERNAL_MODULE, AFHDS2_PERIOD);
break;
#endif
default:
// internal module stopped, use default mixer period
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
break;
if (externalModuleDriver) {
externalModuleDriver->sendPulses(externalModuleContext);
return;
}
}
bool setupPulsesInternalModule(uint8_t protocol)
{
int16_t* channels =
&channelOutputs[g_model.moduleData[INTERNAL_MODULE].channelsStart];
uint8_t nChannels = 16; // TODO: MAX_CHANNELS - channelsStart
switch (moduleState[EXTERNAL_MODULE].protocol) {
switch (protocol) {
#if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_PULSES:
intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE);
return true;
#endif
#if defined(PXX1) && defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE);
return true;
#endif
#if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
Pxx2ModuleDriver.setupPulses((void*)INTERNAL_MODULE, channels, nChannels);
return true;
#endif
#if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM)
case PROTOCOL_CHANNELS_PPM:
setupPulsesPPMInternalModule();
return true;
#endif
#if defined(INTERNAL_MODULE_CRSF)
case PROTOCOL_CHANNELS_CROSSFIRE:
if (CrossfireModuleDriver.setupPulses) {
int16_t* channels =
&channelOutputs[g_model.moduleData[INTERNAL_MODULE].channelsStart];
uint8_t nChannels = 16; // TODO: MAX_CHANNELS - channelsStart
CrossfireModuleDriver.setupPulses((void*)INTERNAL_MODULE, channels,
nChannels);
}
return true;
#endif
#if defined(INTERNAL_MODULE_MULTI)
case PROTOCOL_CHANNELS_MULTIMODULE:
setupPulsesMultiInternalModule();
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
return true;
#endif
#if defined(AFHDS2)
case PROTOCOL_CHANNELS_AFHDS2A:
{
ModuleSyncStatus& status = getModuleSyncStatus(INTERNAL_MODULE);
mixerSchedulerSetPeriod(
INTERNAL_MODULE,
status.isValid() ? status.getAdjustedRefreshRate() : AFHDS2_PERIOD);
status.invalidate();
setupPulsesAFHDS2();
return true;
}
#endif
default:
return false;
}
}
void stopPulsesInternalModule()
{
if (moduleState[INTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
intmoduleStop();
moduleState[INTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
}
}
void intmoduleSendNextFrame()
{
switch (moduleState[INTERNAL_MODULE].protocol) {
#if defined(PXX2)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
Pxx2ModuleDriver.sendPulses((void*)INTERNAL_MODULE);
break;
#endif
#if defined(INTERNAL_MODULE_PPM)
case PROTOCOL_CHANNELS_PPM:
intmoduleSendNextFramePPM(
intmodulePulsesData.ppm.pulses,
intmodulePulsesData.ppm.ptr - intmodulePulsesData.ppm.pulses);
break;
#endif
// Note: this is called directly from the EXTMODULE_TIMER_IRQHandler()
// periodically (the only non-synchronous pulse driver
//
// case PROTOCOL_CHANNELS_PPM:
// extmoduleSendNextFramePpm(
// extmodulePulsesData.ppm.pulses,
// extmodulePulsesData.ppm.ptr - extmodulePulsesData.ppm.pulses,
// *(extmodulePulsesData.ppm.ptr - 1));
// break;
#if defined(PXX1)
#if defined(INTMODULE_USART)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.pxx_uart.getData(),
intmodulePulsesData.pxx_uart.getSize());
break;
#else
case PROTOCOL_CHANNELS_PXX1_PULSES:
intmoduleSendNextFramePxx1(intmodulePulsesData.pxx.getData(),
intmodulePulsesData.pxx.getSize());
extmoduleSendNextFramePxx1(extmodulePulsesData.pxx.getData(),
extmodulePulsesData.pxx.getSize());
break;
#endif
#if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
extmoduleSendBuffer(extmodulePulsesData.pxx_uart.getData(),
extmodulePulsesData.pxx_uart.getSize());
break;
#endif
#if defined(INTERNAL_MODULE_MULTI)
#if defined(AFHDS3)
case PROTOCOL_CHANNELS_AFHDS3:
#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(),
extmodulePulsesData.afhds3.getSize());
#else
extmoduleSendNextFrameAFHDS3(extmodulePulsesData.afhds3.getData(),
extmodulePulsesData.afhds3.getSize());
#endif
break;
#endif
#if defined(DSM2)
case PROTOCOL_CHANNELS_SBUS:
case PROTOCOL_CHANNELS_DSM2_LP45:
case PROTOCOL_CHANNELS_DSM2_DSM2:
case PROTOCOL_CHANNELS_DSM2_DSMX:
case PROTOCOL_CHANNELS_MULTIMODULE:
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.multi.getData(),
intmodulePulsesData.multi.getSize());
extmoduleSendNextFrameSoftSerial100kbit(
extmodulePulsesData.dsm2.pulses,
extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses);
break;
#endif
#if defined(INTERNAL_MODULE_CRSF)
case PROTOCOL_CHANNELS_CROSSFIRE:
if (CrossfireModuleDriver.sendPulses) {
CrossfireModuleDriver.sendPulses((void*)INTERNAL_MODULE);
}
#if defined(GHOST)
case PROTOCOL_CHANNELS_GHOST:
sportSendBuffer(extmodulePulsesData.ghost.pulses,
extmodulePulsesData.ghost.length);
break;
#endif
#if defined(AFHDS2)
case PROTOCOL_CHANNELS_AFHDS2A: {
uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses;
uint16_t size = intmodulePulsesData.flysky.ptr - data;
intmoduleSendBuffer(data, size);
} break;
#endif
}
}
bool setupPulsesInternalModule()
{
uint8_t protocol = getRequiredProtocol(INTERNAL_MODULE);
heartbeat |= (HEART_TIMER_PULSES << INTERNAL_MODULE);
if (moduleState[INTERNAL_MODULE].protocol != protocol) {
intmoduleStop();
enablePulsesInternalModule(protocol);
moduleState[INTERNAL_MODULE].protocol = protocol;
return false;
}
else {
return setupPulsesInternalModule(protocol);
}
}
#endif
#if defined(HARDWARE_EXTERNAL_MODULE)
void stopPulsesExternalModule()
{
if (moduleState[EXTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
extmoduleStop();
if (moduleState[EXTERNAL_MODULE].protocol !=
PROTOCOL_CHANNELS_UNINITIALIZED) {
if (externalModuleDriver) {
externalModuleDriver->deinit(externalModuleContext);
externalModuleDriver = nullptr;
externalModuleContext = nullptr;
} else {
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
extmoduleStop();
}
moduleState[EXTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
}
}
@@ -726,7 +807,6 @@ bool setupPulsesExternalModule()
heartbeat |= (HEART_TIMER_PULSES << EXTERNAL_MODULE);
if (moduleState[EXTERNAL_MODULE].protocol != protocol) {
extmoduleStop();
enablePulsesExternalModule(protocol);
moduleState[EXTERNAL_MODULE].protocol = protocol;
return false;
+1
View File
@@ -231,6 +231,7 @@ void intmoduleSendNextFrame();
#if defined(HARDWARE_EXTERNAL_MODULE)
bool setupPulsesExternalModule();
void stopPulsesExternalModule();
void extmoduleSendNextFrame();
#endif
void setupPulsesDSM2();
void setupPulsesCrossfire(uint8_t idx);
+97 -69
View File
@@ -647,50 +647,87 @@ void Pxx2OtaUpdate::flashFirmware(const char * filename, ProgressHandler progres
resumePulses();
}
static void* pxx2Init(uint8_t module)
static void* pxx2InitInternal(uint8_t moduleType)
{
if (module == INTERNAL_MODULE) {
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&pxx2SerialInitParams);
resetAccessAuthenticationCount();
intmoduleFifo.clear();
IntmoduleSerialDriver.init(&pxx2SerialInitParams);
resetAccessAuthenticationCount();
#if defined(INTMODULE_HEARTBEAT)
// use backup trigger (1 ms later)
init_intmodule_heartbeat();
// use backup trigger (1 ms later)
init_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
return nullptr;
}
static void pxx2DeInitInternal(void* context)
{
IntmoduleSerialDriver.deinit();
#if defined(INTMODULE_HEARTBEAT)
stop_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
}
static bool pxx2InternalSendNextFrame = true;
static void pxx2SetupPulsesInternal(void* context, int16_t* channels, uint8_t nChannels)
{
(void)context;
pxx2InternalSendNextFrame =
intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE, channels, nChannels);
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER ||
moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) {
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_TOOLS_PERIOD);
} else {
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
} else {
#if defined(EXTMODULE_USART)
extmoduleInvertedSerialStart(PXX2_HIGHSPEED_BAUDRATE);
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
#else
return nullptr;
#endif
}
return (void*)(uint32_t)module;
}
static void pxx2DeInit(void* context)
static void pxx2SendPulsesInternal(void* context)
{
uint32_t module = (uint32_t)context;
(void)context;
if (module == INTERNAL_MODULE) {
IntmoduleSerialDriver.deinit();
#if defined(INTMODULE_HEARTBEAT)
stop_intmodule_heartbeat();
#endif
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
} else {
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
extmoduleStop();
if (pxx2InternalSendNextFrame) {
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.pxx2.getData(),
intmodulePulsesData.pxx2.getSize());
}
}
#include "hal/module_driver.h"
const etx_module_driver_t Pxx2InternalDriver = {
.protocol = PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
.init = pxx2InitInternal,
.deinit = pxx2DeInitInternal,
.setupPulses = pxx2SetupPulsesInternal,
.sendPulses = pxx2SendPulsesInternal,
};
#if defined(EXTMODULE_USART)
#include "extmodule_serial_driver.h"
static const etx_serial_init pxx2ExtSerialInitParams = {
.baudrate = 0,
.parity = ETX_Parity_None,
.stop_bits = ETX_StopBits_One,
.word_length = ETX_WordLength_8,
.rx_enable = true,
.on_receive = extmoduleFifoReceive,
.on_error = extmoduleFifoError,
};
static void* pxx2InitLowSpeed(uint8_t module)
{
if (module == EXTERNAL_MODULE) {
extmoduleInvertedSerialStart(PXX2_LOWSPEED_BAUDRATE);
etx_serial_init params(pxx2ExtSerialInitParams);
params.baudrate = PXX2_LOWSPEED_BAUDRATE;
ExtmoduleSerialDriver.init(&params);
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
return (void*)EXTERNAL_MODULE;
}
@@ -698,59 +735,50 @@ static void* pxx2InitLowSpeed(uint8_t module)
return nullptr;
}
static bool pxx2InternalSendNextFrame = true;
static void pxx2SetupPulses(void* context, int16_t* channels, uint8_t nChannels)
static void* pxx2InitExternal(uint8_t moduleType)
{
uint32_t module = (uint32_t)context;
etx_serial_init params(pxx2ExtSerialInitParams);
params.baudrate = PXX2_HIGHSPEED_BAUDRATE;
ExtmoduleSerialDriver.init(&params);
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
if (module == INTERNAL_MODULE) {
pxx2InternalSendNextFrame = intmodulePulsesData.pxx2.setupFrame(
INTERNAL_MODULE, channels, nChannels);
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER ||
moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) {
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_TOOLS_PERIOD);
} else {
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
}
} else {
extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE, channels, nChannels);
}
return nullptr;
}
static void pxx2SendPulses(void* context)
static void pxx2DeInitExternal(void* context)
{
uint32_t module = (uint32_t)context;
(void)context;
if (module == INTERNAL_MODULE) {
if (pxx2InternalSendNextFrame) {
IntmoduleSerialDriver.sendBuffer(intmodulePulsesData.pxx2.getData(),
intmodulePulsesData.pxx2.getSize());
}
} else {
#if defined(EXTMODULE_USART)
extmoduleSendBuffer(extmodulePulsesData.pxx2.getData(),
extmodulePulsesData.pxx2.getSize());
#endif
}
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
extmoduleStop();
}
#include "hal/module_driver.h"
static void pxx2SetupPulsesExternal(void* context, int16_t* channels, uint8_t nChannels)
{
(void)context;
extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE, channels, nChannels);
}
const etx_module_driver_t Pxx2ModuleDriver = {
static void pxx2SendPulsesExternal(void* context)
{
(void)context;
ExtmoduleSerialDriver.sendBuffer(extmodulePulsesData.pxx2.getData(),
extmodulePulsesData.pxx2.getSize());
}
const etx_module_driver_t Pxx2ExternalDriver = {
.protocol = PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
.init = pxx2Init,
.deinit = pxx2DeInit,
.setupPulses = pxx2SetupPulses,
.sendPulses = pxx2SendPulses,
.init = pxx2InitExternal,
.deinit = pxx2DeInitExternal,
.setupPulses = pxx2SetupPulsesExternal,
.sendPulses = pxx2SendPulsesExternal,
};
const etx_module_driver_t Pxx2LowSpeedModuleDriver = {
const etx_module_driver_t Pxx2LowSpeedExternalDriver = {
.protocol = PROTOCOL_CHANNELS_PXX2_LOWSPEED,
.init = pxx2InitLowSpeed,
.deinit = pxx2DeInit,
.setupPulses = pxx2SetupPulses,
.sendPulses = pxx2SendPulses,
.deinit = pxx2DeInitExternal,
.setupPulses = pxx2SetupPulsesExternal,
.sendPulses = pxx2SendPulsesExternal,
};
#endif
+4 -2
View File
@@ -579,7 +579,9 @@ class Pxx2OtaUpdate {
};
extern const etx_serial_init pxx2SerialInitParams;
extern const etx_module_driver_t Pxx2ModuleDriver;
extern const etx_module_driver_t Pxx2LowSpeedModuleDriver;
extern const etx_module_driver_t Pxx2InternalDriver;
extern const etx_module_driver_t Pxx2ExternalDriver;
extern const etx_module_driver_t Pxx2LowSpeedExternalDriver;
#endif
@@ -0,0 +1,194 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* 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 "hal/serial_driver.h"
#include "board.h"
#if defined(EXTMODULE_USART)
#include "stm32_usart_driver.h"
#include "io/frsky_pxx2.h"
ModuleFifo extmoduleFifo;
struct etx_serial_callbacks_t {
void (*on_receive)(uint8_t data);
void (*on_error)();
};
static etx_serial_callbacks_t extmodule_driver = { nullptr, nullptr };
void extmoduleFifoReceive(uint8_t data)
{
extmoduleFifo.push(data);
}
void extmoduleFifoError()
{
extmoduleFifo.errors++;
}
static const etx_serial_init extmoduleSerialParams = {
.baudrate = 0,
.parity = ETX_Parity_None,
.stop_bits = ETX_StopBits_One,
.word_length = ETX_WordLength_8,
.rx_enable = true,
.on_receive = extmoduleFifoReceive,
.on_error = extmoduleFifoError,
};
static void extmoduleSerialStart(const etx_serial_init* params)
{
if (!params) return;
extmodule_driver.on_receive = params->on_receive;
extmodule_driver.on_error = params->on_error;
// TX + RX Pins
GPIO_PinAFConfig(EXTMODULE_USART_GPIO, EXTMODULE_TX_GPIO_PinSource,
EXTMODULE_USART_GPIO_AF);
GPIO_PinAFConfig(EXTMODULE_USART_GPIO, EXTMODULE_RX_GPIO_PinSource,
EXTMODULE_USART_GPIO_AF);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(EXTMODULE_USART_GPIO, &GPIO_InitStructure);
// UART config
stm32_usart_init(EXTMODULE_USART, params);
extmoduleFifo.clear();
USART_ITConfig(EXTMODULE_USART, USART_IT_RXNE, ENABLE);
NVIC_SetPriority(EXTMODULE_USART_IRQn, 6);
NVIC_EnableIRQ(EXTMODULE_USART_IRQn);
}
void extmoduleInvertedSerialStart(uint32_t baudrate)
{
EXTERNAL_MODULE_ON();
etx_serial_init params(extmoduleSerialParams);
params.baudrate = baudrate;
extmoduleSerialStart(&params);
}
void extmoduleSerialStop()
{
DMA_DeInit(EXTMODULE_USART_TX_DMA_STREAM);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(EXTMODULE_USART_GPIO, &GPIO_InitStructure);
USART_DeInit(EXTMODULE_USART);
GPIO_ResetBits(EXTMODULE_USART_GPIO, EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN);
// reset callbacks
extmodule_driver.on_receive = nullptr;
extmodule_driver.on_error = nullptr;
}
static void extmoduleSendByte(uint8_t byte)
{
while (!(EXTMODULE_USART->SR & USART_SR_TXE));
USART_SendData(EXTMODULE_USART, byte);
}
static void extmoduleSendBuffer(const uint8_t * data, uint8_t size)
{
if (size == 0)
return;
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(EXTMODULE_USART_TX_DMA_STREAM);
DMA_InitStructure.DMA_Channel = EXTMODULE_USART_TX_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&EXTMODULE_USART->DR);
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(data);
DMA_InitStructure.DMA_BufferSize = size;
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(EXTMODULE_USART_TX_DMA_STREAM, &DMA_InitStructure);
DMA_Cmd(EXTMODULE_USART_TX_DMA_STREAM, ENABLE);
USART_DMACmd(EXTMODULE_USART, USART_DMAReq_Tx, ENABLE);
}
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
extern "C" void EXTMODULE_USART_IRQHandler(void)
{
// No ISR based send loop: DMA only
// Receive
uint32_t status = EXTMODULE_USART->SR;
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
uint8_t data = EXTMODULE_USART->DR;
if (status & USART_FLAG_ERRORS) {
if (extmodule_driver.on_error)
extmodule_driver.on_error();
}
else {
if (extmodule_driver.on_receive)
extmodule_driver.on_receive(data);
}
status = EXTMODULE_USART->SR;
}
}
static void extmoduleWaitForTxCompleted()
{
#if !defined(SIMU)
// TODO: check if everything is properly initialised, this seems to block when
// the port has been initialised with a zero baudrate
if (DMA_GetCmdStatus(EXTMODULE_USART_TX_DMA_STREAM) == ENABLE) {
while (DMA_GetFlagStatus(EXTMODULE_USART_TX_DMA_STREAM,
EXTMODULE_USART_TX_DMA_FLAG_TC) == RESET)
;
DMA_ClearFlag(EXTMODULE_USART_TX_DMA_STREAM,
EXTMODULE_USART_TX_DMA_FLAG_TC);
}
#endif
}
etx_serial_driver_t ExtmoduleSerialDriver = {
.init = extmoduleSerialStart,
.deinit = extmoduleSerialStop,
.sendByte = extmoduleSendByte,
.sendBuffer = extmoduleSendBuffer,
.waitForTxCompleted = extmoduleWaitForTxCompleted,
};
#endif // defined(EXTMODULE_USART)
@@ -0,0 +1,36 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* 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.
*/
#pragma once
#include <stdint.h>
#include "hal/serial_driver.h"
// Callbacks using intmoduleFifo
void extmoduleFifoReceive(uint8_t data);
void extmoduleFifoError();
// void extmoduleSerialStart();
// void extmoduleInvertedSerialStart(uint32_t baudrate);
// void extmoduleSendBuffer(const uint8_t * data, uint8_t size);
// void extmoduleSendNextFrame();
extern etx_serial_driver_t ExtmoduleSerialDriver;
@@ -24,17 +24,18 @@
#include "stm32_usart_driver.h"
ModuleFifo intmoduleFifo;
#if !defined(INTMODULE_DMA_STREAM)
uint8_t * intmoduleTxBufferData;
volatile uint8_t intmoduleTxBufferRemaining;
#endif
struct etx_serial_driver {
struct etx_serial_callbacks_t {
void (*on_receive)(uint8_t data);
void (*on_error)();
};
static etx_serial_driver intmodule_driver = { nullptr, nullptr };
static etx_serial_callbacks_t intmodule_driver = { nullptr, nullptr };
// TODO: move this somewhere else
void intmoduleFifoReceive(uint8_t data)
@@ -47,18 +48,6 @@ void intmoduleFifoError()
intmoduleFifo.errors++;
}
// etx_serial_init::etx_serial_init():
// baudrate(0),
// parity(USART_Parity_No),
// stop_bits(USART_StopBits_1),
// word_length(USART_WordLength_8b),
// rx_enable(false),
// // TODO: this should not be needed
// on_receive(intmoduleFifoReceive),
// on_error(intmoduleFifoError)
// {
// }
void intmoduleStop()
{
#if defined(INTMODULE_DMA_STREAM)
@@ -238,7 +227,7 @@ void intmoduleWaitForTxCompleted()
#endif
}
etx_hal_serial_driver_t IntmoduleSerialDriver = {
etx_serial_driver_t IntmoduleSerialDriver = {
.init = intmoduleSerialStart,
.deinit = intmoduleStop,
.sendByte = intmoduleSendByte,
@@ -28,4 +28,4 @@
void intmoduleFifoReceive(uint8_t data);
void intmoduleFifoError();
extern etx_hal_serial_driver_t IntmoduleSerialDriver;
extern etx_serial_driver_t IntmoduleSerialDriver;
+1
View File
@@ -242,6 +242,7 @@ set(TARGET_SRC
../common/arm/stm32/mixer_scheduler_driver.cpp
../common/arm/stm32/timers_driver.cpp
../common/arm/stm32/intmodule_serial_driver.cpp
../common/arm/stm32/extmodule_serial_driver.cpp
../common/arm/stm32/stm32_usart_driver.cpp
../common/arm/stm32/rotary_encoder_driver.cpp
)
-6
View File
@@ -194,12 +194,6 @@ void SDRAM_Init();
#define IS_PXX1_INTERNAL_ENABLED() (true)
#endif
void extmoduleSerialStart();
void extmoduleInvertedSerialStart(uint32_t baudrate);
void extmoduleSendBuffer(const uint8_t * data, uint8_t size);
void extmoduleSendNextFrame();
void extmoduleSendInvertedByte(uint8_t byte);
// Trainer driver
void init_trainer_ppm();
void stop_trainer_ppm();
+93 -207
View File
@@ -20,6 +20,7 @@
*/
#include "opentx.h"
#include "extmodule_driver.h"
#if defined(CROSSFIRE)
#include "pulses/crossfire.h"
@@ -207,232 +208,114 @@ void extmoduleSerialStart()
NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn, 7);
}
#if defined(EXTMODULE_USART)
ModuleFifo extmoduleFifo;
void extmoduleInvertedSerialStart(uint32_t baudrate)
static void extmoduleSendNextFramePpm(uint32_t* pulses, uint16_t length,
uint16_t trailing_pulse)
{
EXTERNAL_MODULE_ON();
// TX + RX Pins
GPIO_PinAFConfig(EXTMODULE_USART_GPIO, EXTMODULE_TX_GPIO_PinSource, EXTMODULE_USART_GPIO_AF);
GPIO_PinAFConfig(EXTMODULE_USART_GPIO, EXTMODULE_RX_GPIO_PinSource, EXTMODULE_USART_GPIO_AF);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(EXTMODULE_USART_GPIO, &GPIO_InitStructure);
// UART config
USART_DeInit(EXTMODULE_USART);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(EXTMODULE_USART, &USART_InitStructure);
USART_Cmd(EXTMODULE_USART, ENABLE);
extmoduleFifo.clear();
USART_ITConfig(EXTMODULE_USART, USART_IT_RXNE, ENABLE);
NVIC_SetPriority(EXTMODULE_USART_IRQn, 6);
NVIC_EnableIRQ(EXTMODULE_USART_IRQn);
}
void extmoduleSendBuffer(const uint8_t * data, uint8_t size)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(EXTMODULE_USART_TX_DMA_STREAM);
DMA_InitStructure.DMA_Channel = EXTMODULE_USART_TX_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&EXTMODULE_USART->DR);
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(data);
DMA_InitStructure.DMA_BufferSize = size;
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(EXTMODULE_USART_TX_DMA_STREAM, &DMA_InitStructure);
DMA_Cmd(EXTMODULE_USART_TX_DMA_STREAM, ENABLE);
USART_DMACmd(EXTMODULE_USART, USART_DMAReq_Tx, ENABLE);
}
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
extern "C" void EXTMODULE_USART_IRQHandler(void)
{
uint32_t status = EXTMODULE_USART->SR;
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
uint8_t data = EXTMODULE_USART->DR;
if (status & USART_FLAG_ERRORS) {
extmoduleFifo.errors++;
}
else {
extmoduleFifo.push(data);
}
status = EXTMODULE_USART->SR;
}
}
#endif
void extmoduleSendNextFrame()
{
switch (moduleState[EXTERNAL_MODULE].protocol) {
case PROTOCOL_CHANNELS_PPM:
#if defined(PCBX10) || PCBREV >= 13
EXTMODULE_TIMER->CCR3 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE)*2;
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0);
EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
// Using timer channel 3
EXTMODULE_TIMER->CCR3 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE) * 2;
EXTMODULE_TIMER->CCER =
TIM_CCER_CC3E |
(GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0);
#else
EXTMODULE_TIMER->CCR1 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE)*2;
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E |
(GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ?
// Using timer channel 1
EXTMODULE_TIMER->CCR1 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE) * 2;
EXTMODULE_TIMER->CCER =
TIM_CCER_CC1E | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ?
#if defined(PCBNV14)
0 : TIM_CCER_CC1P
0
: TIM_CCER_CC1P
#else
TIM_CCER_CC1P : 0
TIM_CCER_CC1P
: 0
#endif
);
EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
);
#endif
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.ppm.pulses);
EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.ppm.ptr - extmodulePulsesData.ppm.pulses;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
break;
EXTMODULE_TIMER->CCR2 = trailing_pulse - 4000; // 2mS in advance
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |=
EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC |
EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(pulses);
EXTMODULE_TIMER_DMA_STREAM->NDTR = length;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
}
#if defined(PXX1)
case PROTOCOL_CHANNELS_PXX1_PULSES:
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN)
return;
void extmoduleSendNextFramePxx1(const uint32_t* pulses, uint16_t length)
{
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) return;
// disable timer
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData());
EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.pxx.getSize();
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
// disable timer
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
EXTMODULE_TIMER_DMA_STREAM->CR |=
EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC |
EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(pulses);
EXTMODULE_TIMER_DMA_STREAM->NDTR = length;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
// re-init timer
EXTMODULE_TIMER->EGR = 1;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
break;
// re-init timer
EXTMODULE_TIMER->EGR = 1;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
}
#endif
#if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
case PROTOCOL_CHANNELS_PXX1_SERIAL:
extmoduleSendBuffer(extmodulePulsesData.pxx_uart.getData(), extmodulePulsesData.pxx_uart.getSize());
break;
#if defined(AFHDS3) && !(defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO))
void extmoduleSendNextFrameAFHDS3(const uint16_t* dataPtr, uint16_t dataSize)
{
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) return;
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |=
EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC |
DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr);
EXTMODULE_TIMER_DMA_STREAM->NDTR = dataSize;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
// re-init timer
EXTMODULE_TIMER->EGR = TIM_PSCReloadMode_Immediate;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
}
#endif
#if defined(PXX2) && defined(EXTMODULE_USART)
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
case PROTOCOL_CHANNELS_PXX2_LOWSPEED:
Pxx2ModuleDriver.sendPulses((void*)EXTERNAL_MODULE);
break;
#endif
void extmoduleSendNextFrameSoftSerial100kbit(const uint32_t* pulses, uint16_t length)
{
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) return;
#if defined(AFHDS3)
case PROTOCOL_CHANNELS_AFHDS3:
{
#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize());
#else
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN)
return;
const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData();
uint32_t dataSize = extmodulePulsesData.afhds3.getSize();
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr);
EXTMODULE_TIMER_DMA_STREAM->NDTR = dataSize;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
// re-init timer
EXTMODULE_TIMER->EGR = TIM_PSCReloadMode_Immediate;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
#endif
}
break;
#endif
#if defined(DSM2)
case PROTOCOL_CHANNELS_SBUS:
case PROTOCOL_CHANNELS_DSM2_LP45:
case PROTOCOL_CHANNELS_DSM2_DSM2:
case PROTOCOL_CHANNELS_DSM2_DSMX:
case PROTOCOL_CHANNELS_MULTIMODULE:
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN)
return;
if (PROTOCOL_CHANNELS_SBUS == moduleState[EXTERNAL_MODULE].protocol) {
// reverse polarity for Sbus if needed
EXTMODULE_TIMER->CCER =
if (PROTOCOL_CHANNELS_SBUS == moduleState[EXTERNAL_MODULE].protocol) {
// reverse polarity for Sbus if needed
EXTMODULE_TIMER->CCER =
#if defined(PCBX10) || PCBREV >= 13
TIM_CCER_CC3E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0)
TIM_CCER_CC3E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0)
#elif defined(PCBNV14)
TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? 0 : TIM_CCER_CC1P)
TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? 0 : TIM_CCER_CC1P)
#else
TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0)
TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0)
#endif
; //
}
// disable timer
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
// send DMA request
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses);
EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
// re-init timer
EXTMODULE_TIMER->EGR = 1;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
break;
#endif
#if defined(CROSSFIRE)
case PROTOCOL_CHANNELS_CROSSFIRE:
if (CrossfireModuleDriver.sendPulses) {
CrossfireModuleDriver.sendPulses((void*)EXTERNAL_MODULE);
}
break;
#endif
#if defined(GHOST)
case PROTOCOL_CHANNELS_GHOST:
sportSendBuffer(extmodulePulsesData.ghost.pulses, extmodulePulsesData.ghost.length);
break;
#endif
default:
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
break;
; //
}
// disable timer
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
// send DMA request
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_TIMER_DMA_STREAM->CR |=
EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC |
EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(pulses);
EXTMODULE_TIMER_DMA_STREAM->NDTR = length;
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
// re-init timer
EXTMODULE_TIMER->EGR = 1;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
}
void extmoduleSendInvertedByte(uint8_t byte)
@@ -487,6 +370,9 @@ extern "C" void EXTMODULE_TIMER_IRQHandler()
EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
if (setupPulsesExternalModule())
extmoduleSendNextFrame();
setupPulsesPPMExternalModule();
extmoduleSendNextFramePpm(
extmodulePulsesData.ppm.pulses,
extmodulePulsesData.ppm.ptr - extmodulePulsesData.ppm.pulses,
*(extmodulePulsesData.ppm.ptr - 1));
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* 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.
*/
#pragma once
#include <stdint.h>
void extmoduleStop();
void extmodulePpmStart();
#if defined(PXX1)
void extmodulePxx1PulsesStart();
void extmoduleSendNextFramePxx1(const uint32_t* pulses, uint16_t length);
#endif
// Soft serial on PPM pin
void extmoduleSerialStart();
#if defined(AFHDS3) && !(defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO))
void extmoduleSendNextFrameAFHDS3(const uint16_t* dataPtr, uint16_t dataSize);
#endif
void extmoduleSendNextFrameSoftSerial100kbit(const uint32_t* pulses, uint16_t length);
// Bitbang serial
void extmoduleSendInvertedByte(uint8_t byte);
+1
View File
@@ -862,6 +862,7 @@
#define EXTMODULE_USART_IRQHandler USART3_IRQHandler
#define EXTMODULE_USART_TX_DMA_CHANNEL DMA_Channel_4
#define EXTMODULE_USART_TX_DMA_STREAM DMA1_Stream3
#define EXTMODULE_USART_TX_DMA_FLAG_TC DMA_FLAG_TCIF3
#define EXTMODULE_USART_RX_DMA_CHANNEL DMA_Channel_4
#define EXTMODULE_USART_RX_DMA_STREAM DMA1_Stream1
#elif defined(PCBX10) || PCBREV >= 13