External serial driver moved to a separate driver
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "intmodule_serial_driver.h"
|
||||
#endif
|
||||
|
||||
#include "extmodule_driver.h"
|
||||
|
||||
#define UPDATE_MULTI_EXT_BIN ".bin"
|
||||
|
||||
class MultiFirmwareUpdateDriver
|
||||
|
||||
@@ -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(¶ms);
|
||||
#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(¶ms);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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(¶ms);
|
||||
|
||||
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(¶ms);
|
||||
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
|
||||
|
||||
@@ -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(¶ms);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user