diff --git a/src/Afterburner.cpp b/src/Afterburner.cpp index ae5eb18..d47a492 100644 --- a/src/Afterburner.cpp +++ b/src/Afterburner.cpp @@ -128,8 +128,8 @@ const int FirmwareRevision = 32; const int FirmwareSubRevision = 0; -const int FirmwareMinorRevision = 0; -const char* FirmwareDate = "30 Mar 2020"; +const int FirmwareMinorRevision = 3; +const char* FirmwareDate = "9 Apr 2020"; #ifdef ESP32 diff --git a/src/Protocol/TxManage.cpp b/src/Protocol/TxManage.cpp index 49ad8c6..4b321ab 100644 --- a/src/Protocol/TxManage.cpp +++ b/src/Protocol/TxManage.cpp @@ -22,6 +22,7 @@ #include "TxManage.h" #include "../Utility/NVStorage.h" #include "../Utility/helpers.h" +#include "freertos/queue.h" //#define DEBUG_THERMOSTAT @@ -51,6 +52,31 @@ extern void DebugReportFrame(const char* hdr, const CProtocol&, const char* ftr) unsigned long CTxManage::m_nStartTime = 0; int CTxManage::m_nTxGatePin = 0; +// Timer callback operates at ISRL +// this means we should avoid any function NOT in IRAM. +// Sadly digitalWrite falls into this category, so use a FreeRTOS queue +// to push the end event handling into a non ISRL task + +static QueueHandle_t txGate_queue = NULL; +static int lclTxGatePin = 0; + +// static function used for the tx gate termination +static void IRAM_ATTR GateTerminateCallback() +{ + uint32_t gpio_num = lclTxGatePin; + xQueueSendFromISR(txGate_queue, &gpio_num, NULL); +} + +static void TxGateConclude(void* arg) +{ + uint32_t io_num; + for(;;) { + if(xQueueReceive(txGate_queue, &io_num, portMAX_DELAY)) { + digitalWrite(io_num, LOW); // terminate Tx Gate + } + } +} + CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) : m_BlueWireSerial(serial), m_TxFrame(CProtocol::CtrlMode) @@ -61,6 +87,7 @@ CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) : m_bTxPending = false; m_nStartTime = 0; m_nTxGatePin = TxGatePin; + lclTxGatePin = TxGatePin; _rawCommand = 0; m_HWTimer = NULL; } @@ -68,7 +95,9 @@ CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) : // static function used for the tx gate termination void CTxManage::GateTerminate() { - digitalWrite(m_nTxGatePin, LOW); // default to receive mode + uint32_t gpio_num = m_nTxGatePin; + xQueueSendFromISR(txGate_queue, &gpio_num, NULL); +// digitalWrite(m_nTxGatePin, LOW); // default to receive mode m_nStartTime = 0; // cancel, we are DONE } @@ -78,12 +107,19 @@ void CTxManage::begin() pinMode(m_nTxGatePin, OUTPUT); digitalWrite(m_nTxGatePin, LOW); // default to receive mode +//create a queue to handle gpio event from isr + txGate_queue = xQueueCreate(10, sizeof(uint32_t)); + //start gpio task + xTaskCreate(TxGateConclude, "Tx Gate Conclude", 2048, NULL, configMAX_PRIORITIES-2, NULL); + // use a hardware timer to terminate the Tx gate shortly after the completion of the 24 byte transmit packet m_HWTimer = timerBegin(2, 80, true); //set time in uS of Tx gate from when actual tx data bytes are loaded // 240 bits @ 25000bps is 9.6ms, we'll use 9.7ms for a bit of tolerance timerAlarmWrite(m_HWTimer, 10000-300, false); - timerAttachInterrupt(m_HWTimer, &GateTerminate, true); + // timerAttachInterrupt(m_HWTimer, &GateTerminate, true); + timerAttachInterrupt(m_HWTimer, &GateTerminateCallback, true); + timerAlarmDisable(m_HWTimer); //disable interrupt for now timerSetAutoReload(m_HWTimer, false); } @@ -299,6 +335,7 @@ CTxManage::CheckTx(unsigned long timenow) // Tx gate remains held high // it is then brought low by the timer alarm callback, which also cancels m_nStartTime m_bTxPending = false; + m_nStartTime = 0; m_BlueWireSerial.write(m_TxFrame.Data, 24); // write native binary values timerWrite(m_HWTimer, 0); //reset tx gate timeout timerAlarmEnable(m_HWTimer); // timeout will cause cessation of the Tx gate