diff --git a/RotaxMonitor/src/isr.cpp b/RotaxMonitor/src/isr.cpp new file mode 100644 index 0000000..26a21af --- /dev/null +++ b/RotaxMonitor/src/isr.cpp @@ -0,0 +1,54 @@ +#include "isr.h" + +// ===================== +// ISR (Pass return bitmask to ISR management function) +// one function for each wake up pin conncted to a trigger +// ===================== +void trig_isr(void *arg) +{ + const int64_t time_us = esp_timer_get_time(); + + // exit if invalid args + if (!arg) + return; + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + isrParams *params = (isrParams*)arg; + ignitionBoxStatus *box = params->ign_stat; + TaskHandle_t task_handle = *params->rt_handle_ptr; + + // exit if task not running + if (!task_handle) + return; + + // reset spark flags, cannot be same time as trigger flags + box->coils12.spark_ok = false; + box->coils34.spark_ok = false; + + switch (params->flag) + { + case TRIG_FLAG_12P: + box->coils12.trig_time = time_us; + xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); + break; + case TRIG_FLAG_34P: + box->coils34.trig_time = time_us; + xTaskNotifyFromISR(task_handle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); + break; + case SPARK_FLAG_12: + box->coils12.spark_ok = true; + box->coils12.spark_time = time_us; + vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken); + break; + case SPARK_FLAG_34: + box->coils34.spark_ok = true; + box->coils34.spark_time = time_us; + vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken); + break; + default: + break; + } + + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} \ No newline at end of file diff --git a/RotaxMonitor/src/isr.h b/RotaxMonitor/src/isr.h index bd451c6..fb8bb54 100644 --- a/RotaxMonitor/src/isr.h +++ b/RotaxMonitor/src/isr.h @@ -5,7 +5,6 @@ // Arduino Libraries #include -#include #include "soc/gpio_struct.h" #ifndef TEST #include "pins.h" @@ -30,10 +29,6 @@ #define SPARK_FLAG_12 (1 << 9) #define SPARK_FLAG_34 (1 << 10) -// Task handle -TaskHandle_t trigA_TaskHandle = NULL; -TaskHandle_t trigB_TaskHandle = NULL; - // Spark Status enum sparkStatus { @@ -83,53 +78,8 @@ struct ignitionBoxStatus struct isrParams { const uint32_t flag; ignitionBoxStatus* ign_stat; + TaskHandle_t* rt_handle_ptr; }; -// ===================== -// ISR (Pass return bitmask to ISR management function) -// one function for each wake up pin conncted to a trigger -// ===================== -void IRAM_ATTR trig_isr_a(void *arg) -{ - const int64_t time_us = esp_timer_get_time(); - - // exit if task is not running - if (!trigA_TaskHandle || !arg) - return; - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - isrParams *params = (isrParams*)arg; - ignitionBoxStatus *box = box; - - // reset spark flags, cannot be same time as trigger flags - box->coils12.spark_ok = false; - box->coils34.spark_ok = false; - - switch (params->flag) - { - case TRIG_FLAG_12P: - box->coils12.trig_time = time_us; - xTaskNotifyFromISR(trigA_TaskHandle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); - break; - case TRIG_FLAG_34P: - box->coils34.trig_time = time_us; - xTaskNotifyFromISR(trigA_TaskHandle, params->flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); - break; - case SPARK_FLAG_12: - box->coils12.spark_ok = true; - box->coils12.spark_time = time_us; - vTaskNotifyGiveFromISR(trigA_TaskHandle, &xHigherPriorityTaskWoken); - break; - case SPARK_FLAG_34: - box->coils34.spark_ok = true; - box->coils34.spark_time = time_us; - vTaskNotifyGiveFromISR(trigA_TaskHandle, &xHigherPriorityTaskWoken); - break; - default: - break; - } - - if (xHigherPriorityTaskWoken) - portYIELD_FROM_ISR(); -} +void IRAM_ATTR trig_isr(void *arg); diff --git a/RotaxMonitor/src/main.cpp b/RotaxMonitor/src/main.cpp index bb84686..33519e5 100644 --- a/RotaxMonitor/src/main.cpp +++ b/RotaxMonitor/src/main.cpp @@ -51,13 +51,20 @@ void loop() // global variables bool running = true; Devices dev; + + // Task handle + TaskHandle_t trigA_TaskHandle = NULL; + TaskHandle_t trigB_TaskHandle = NULL; + QueueHandle_t rt_taskA_queue = xQueueCreate(10, sizeof(ignitionBoxStatus)); + QueueHandle_t rt_taskB_queue = xQueueCreate(10, sizeof(ignitionBoxStatus)); rtTaskParams taskA_params { .rt_running = true, .dev = &dev, + .rt_handle_ptr = &trigA_TaskHandle, .rt_queue = rt_taskA_queue, .rt_int = rtTaskInterrupts{ - .isr_ptr = trig_isr_a, + .isr_ptr = trig_isr, .trig_pin_12p = TRIG_PIN_A12P, .trig_pin_12n = TRIG_PIN_A12N, .trig_pin_34p = TRIG_PIN_A34P, @@ -76,8 +83,9 @@ void loop() .rt_running = true, .dev = &dev, .rt_queue = rt_taskB_queue, + .rt_handle_ptr = &trigB_TaskHandle, .rt_int = rtTaskInterrupts{ - .isr_ptr = trig_isr_a, + .isr_ptr = trig_isr, .trig_pin_12p = TRIG_PIN_B12P, .trig_pin_12n = TRIG_PIN_B12N, .trig_pin_34p = TRIG_PIN_B34P, diff --git a/RotaxMonitor/src/tasks.cpp b/RotaxMonitor/src/tasks.cpp new file mode 100644 index 0000000..22270a5 --- /dev/null +++ b/RotaxMonitor/src/tasks.cpp @@ -0,0 +1,250 @@ +#include "tasks.h" + +void rtIgnitionTask(void *pvParameters) +{ + + // Invalid real time rt_task_ptr parameters, exit immediate + if (!pvParameters) + { + LOG_ERROR("Null rt_task_ptr parameters"); + vTaskDelete(NULL); + } + + // Task Parameters and Devices + rtTaskParams *params = (rtTaskParams *)pvParameters; + const rtTaskInterrupts rt_int = params->rt_int; // copy to avoid external override + const rtTaskResets rt_rst = params->rt_resets; // copy to avoid external override + QueueHandle_t rt_queue = params->rt_queue; + TaskHandle_t* rt_handle_ptr = params->rt_handle_ptr; + Devices *dev = params->dev; + ADS1256 *adc = dev->adc_a; + PCA9555 *io = dev->io; + + // Variables for ISR, static to be fixed in memory locations + static ignitionBoxStatus ign_box_sts; // common for all ISR calls + static isrParams isr_params_t12p{ + .flag = TRIG_FLAG_12P, + .ign_stat = &ign_box_sts, + .rt_handle_ptr = rt_handle_ptr}; + static isrParams isr_params_t12n{ + .flag = TRIG_FLAG_12N, + .ign_stat = &ign_box_sts, + .rt_handle_ptr = rt_handle_ptr}; + static isrParams isr_params_t34p{ + .flag = TRIG_FLAG_34P, + .ign_stat = &ign_box_sts, + .rt_handle_ptr = rt_handle_ptr}; + static isrParams isr_params_t34n{ + .flag = TRIG_FLAG_34N, + .ign_stat = &ign_box_sts, + .rt_handle_ptr = rt_handle_ptr}; + static isrParams isr_params_sp12{ + .flag = SPARK_FLAG_12, + .ign_stat = &ign_box_sts, + .rt_handle_ptr = rt_handle_ptr}; + static isrParams isr_params_sp34{ + .flag = SPARK_FLAG_34, + .ign_stat = &ign_box_sts, + .rt_handle_ptr = rt_handle_ptr}; + + // Attach Pin Interrupts + attachInterruptArg(rt_int.trig_pin_12p, rt_int.isr_ptr, (void *)&isr_params_t12p, RISING); + attachInterruptArg(rt_int.trig_pin_12n, rt_int.isr_ptr, (void *)&isr_params_t12n, RISING); + attachInterruptArg(rt_int.trig_pin_34p, rt_int.isr_ptr, (void *)&isr_params_t34p, RISING); + attachInterruptArg(rt_int.trig_pin_34n, rt_int.isr_ptr, (void *)&isr_params_t34n, RISING); + attachInterruptArg(rt_int.spark_pin_12, rt_int.isr_ptr, (void *)&isr_params_sp12, RISING); + attachInterruptArg(rt_int.spark_pin_34, rt_int.isr_ptr, (void *)&isr_params_sp34, RISING); + + // Compute Reset Pin Bitmask + const uint16_t rst_bitmask = (1 << rt_rst.rst_io_12p) | + (1 << rt_rst.rst_io_12n) | + (1 << rt_rst.rst_io_34p) | + (1 << rt_rst.rst_io_34n); + + uint32_t it = 0; + uint32_t q_fail_count = 0; + while (params->rt_running) + { + // Global rt_task_ptr variables + uint32_t pickup_flag = 0; + uint32_t spark_flag = 0; + +#ifdef DEBUG + Serial.print("\033[2J"); // clear screen + Serial.print("\033[H"); // cursor home + LOG_INFO("Iteration [", it, "]"); +#endif + + // WAIT FOR PICKUP SIGNAL + xTaskNotifyWait( + 0x00, // non pulire all'ingresso + ULONG_MAX, // pulisci i primi 8 bit + &pickup_flag, // valore ricevuto + portMAX_DELAY); + +#ifdef DEBUG + LOG_INFO("Pickup Flags: ", printBits(pickup_flag).c_str()); + if (!names.contains(pickup_flag)) + { + LOG_ERROR("Wrong Pickup Flag"); + continue; + } + else + { + LOG_INFO("Pickup Trigger: ", names.at(pickup_flag)); + } +#endif + + // WAIT FOR SPARK TO HAPPEN + auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(spark_timeout_max)); + if (ign_box_sts.coils12.spark_ok || ign_box_sts.coils34.spark_ok) // otherwise timeout if none is set in the ISR + spark_flag = ign_box_sts.coils12.spark_ok ? SPARK_FLAG_12 : SPARK_FLAG_34; + + xTaskNotifyStateClear(NULL); + ulTaskNotifyValueClear(NULL, 0xFFFFFFFF); +#ifdef DEBUG + LOG_INFO("Spark Flags: ", printBits(spark_flag).c_str()); + if (!names.contains(spark_flag)) + LOG_ERROR("No Spark"); + else + LOG_INFO("Spark Trigger:", names.at(spark_flag)); +#endif + + // A trigger from pickup 12 is followed by a spark event on 34 or vice versa pickup 34 triggers spark on 12 + if ((pickup_flag == TRIG_FLAG_12P || pickup_flag == TRIG_FLAG_12N) && spark_flag != SPARK_FLAG_12) + { + ign_box_sts.coils12.spark_status = ign_box_sts.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL; + // Save error on circular buffer and skip to next cycle // + LOG_ERROR("Spark Mismatch"); + continue; + } + + coilsStatus *coils; + switch (pickup_flag) + { + case TRIG_FLAG_12P: + case TRIG_FLAG_12N: + coils = &ign_box_sts.coils12; + break; + case TRIG_FLAG_34P: + case TRIG_FLAG_34N: + coils = &ign_box_sts.coils34; + break; + } + + bool new_data = false; + switch (pickup_flag) + { + // CASES for NEGATIVE cycle triggering of pickup and sparks 12 & 34 + case TRIG_FLAG_12P: + case TRIG_FLAG_34P: + { + // Timeout not occourred, expected POSITIVE edge spark OCCOURRED + if (spark_timeout == pdPASS) + { + coils->spark_delay = coils->spark_time - coils->trig_time; + coils->sstart_status = softStartStatus::NORMAL; // because spark on positive edge + coils->spark_status = sparkStatus::SPARK_POS_OK; // do not wait for spark on negative edge +#ifdef DEBUG + LOG_INFO("Trigger Spark POSITIVE"); + LOG_INFO("Spark12 Delay Timer: ", (int)coils->spark_delay); +#endif + } + // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED + else if (spark_timeout == pdFAIL) + { + coils->spark_status = sparkStatus::SPARK_NEG_WAIT; + coils->sstart_status = softStartStatus::NORMAL; + } + new_data = false; + break; // Do nothing more on positive pulse + } + // CASES for NEGATIVE cycle triggering of pickup and sparks 12 & 34 + case TRIG_FLAG_12N: + case TRIG_FLAG_34N: + { + const bool expected_negative12 = coils->spark_status == sparkStatus::SPARK_NEG_WAIT; + // Timeout not occourred, expected NEGATIVE edge spark OCCOURRED + if (spark_timeout == pdPASS && expected_negative12) + { + coils->spark_delay = coils->spark_time - coils->trig_time; + coils->sstart_status = softStartStatus::SOFT_START; + coils->spark_status == sparkStatus::SPARK_NEG_OK; +#ifdef DEBUG + LOG_INFO("Trigger Spark NEGATIVE"); + LOG_INFO("Spark12 Delay Timer: ", (int)ign_box_sts.coils12.spark_delay); +#endif + } + // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED + else if (spark_timeout == pdFAIL && expected_negative12) + { + coils->sstart_status = softStartStatus::NORMAL; + coils->spark_status = sparkStatus::SPARK_NEG_FAIL; + } + // Timeout not occouured, unexpected negative edge spark + else if (spark_timeout == pdPASS && !expected_negative12) + { + coils->sstart_status = softStartStatus::SOFT_START; + coils->spark_status = sparkStatus::SPARK_NEG_UNEXPECTED; + } + // Wait for finish of negative pulse to save data to buffer + new_data = true; + break; + } + default: + LOG_ERROR("Invalid Interrupt"); + break; + } + + if (new_data) + { + vTaskDelay(pdMS_TO_TICKS(1)); // delay 1ms to allow peak detectors to charge for negative cycle + // read adc channels: pickup12, out12 [ pos + neg ] + if (adc) // read only if adc initialized + { + // from peak detector circuits + ign_box_sts.coils12.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_12P_IN); + ign_box_sts.coils12.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_12N_IN); + ign_box_sts.coils34.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_34P_IN); + ign_box_sts.coils34.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_34N_IN); + ign_box_sts.coils12.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_12P_OUT); + ign_box_sts.coils12.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_12N_OUT); + ign_box_sts.coils34.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_34P_OUT); + ign_box_sts.coils34.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_34N_OUT); + } + else // simulate adc read timig + vTaskDelay(pdMS_TO_TICKS(6)); + + // reset peak detectors + sample and hold + // outputs on io expander + if (io) + { + const uint16_t iostat = io->read(); + io->write(iostat | rst_bitmask); + vTaskDelay(pdMS_TO_TICKS(1)); + io->write(iostat & ~rst_bitmask); + } + else + vTaskDelay(pdMS_TO_TICKS(2)); + + // send essage to main loop with ignition info, by copy so local static variable is ok + if (rt_queue) + ign_box_sts.timestamp = esp_timer_get_time(); // update data timestamp + if (xQueueSendToBack(rt_queue, (void *)&ign_box_sts, pdMS_TO_TICKS(1)) != pdPASS) + { + q_fail_count++; + LOG_ERROR("Failed to send to rt_queue"); + } + } + } + LOG_WARN("Ending realTime Task"); + // Ignition A Interrupts DETACH + detachInterrupt(rt_int.trig_pin_12p); + detachInterrupt(rt_int.trig_pin_12n); + detachInterrupt(rt_int.trig_pin_34p); + detachInterrupt(rt_int.trig_pin_34n); + detachInterrupt(rt_int.spark_pin_12); + detachInterrupt(rt_int.spark_pin_34); + // delete present task + vTaskDelete(NULL); +} diff --git a/RotaxMonitor/src/tasks.h b/RotaxMonitor/src/tasks.h index f08f217..14b53db 100644 --- a/RotaxMonitor/src/tasks.h +++ b/RotaxMonitor/src/tasks.h @@ -1,4 +1,5 @@ #pragma once +#define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG // Serial debug flag // #define DEBUG @@ -6,7 +7,9 @@ // Arduino Libraries #include #include +#ifdef DEBUG #include "utils.h" +#endif // ISR #include "isr.h" @@ -55,249 +58,10 @@ struct rtTaskParams { bool rt_running; // run flag, false to terminate Devices *dev; + TaskHandle_t* rt_handle_ptr; const QueueHandle_t rt_queue; const rtTaskInterrupts rt_int; // interrupt pins to attach const rtTaskResets rt_resets; // reset ping for peak detectors }; -void rtIgnitionTask(void *pvParameters) -{ - - // Invalid real time task parameters, exit immediate - if (!pvParameters) - { - LOG_ERROR("Null task parameters"); - vTaskDelete(NULL); - } - - // Task Parameters and Devices - rtTaskParams *params = (rtTaskParams *)pvParameters; - const rtTaskInterrupts rt_int = params->rt_int; // copy to avoid external override - const rtTaskResets rt_rst = params->rt_resets; // copy to avoid external override - QueueHandle_t queue = params->rt_queue; - Devices *dev = params->dev; - ADS1256 *adc = dev->adc_a; - PCA9555 *io = dev->io; - - // Variables for ISR, static to be fixed in memory locations - static ignitionBoxStatus ign_box_sts; // common for all ISR calls - static isrParams isr_params_t12p{ // only call flag changes - .flag = TRIG_FLAG_12P, - .ign_stat = &ign_box_sts}; - static isrParams isr_params_t12n{ - .flag = TRIG_FLAG_12N, - .ign_stat = &ign_box_sts}; - static isrParams isr_params_t34p{ - .flag = TRIG_FLAG_34P, - .ign_stat = &ign_box_sts}; - static isrParams isr_params_t34n{ - .flag = TRIG_FLAG_34N, - .ign_stat = &ign_box_sts}; - static isrParams isr_params_sp12{ - .flag = SPARK_FLAG_12, - .ign_stat = &ign_box_sts}; - static isrParams isr_params_sp34{ - .flag = SPARK_FLAG_34, - .ign_stat = &ign_box_sts}; - - // Attach Pin Interrupts - attachInterruptArg(rt_int.trig_pin_12p, rt_int.isr_ptr, (void *)&isr_params_t12p, RISING); - attachInterruptArg(rt_int.trig_pin_12n, rt_int.isr_ptr, (void *)&isr_params_t12n, RISING); - attachInterruptArg(rt_int.trig_pin_34p, rt_int.isr_ptr, (void *)&isr_params_t34p, RISING); - attachInterruptArg(rt_int.trig_pin_34n, rt_int.isr_ptr, (void *)&isr_params_t34n, RISING); - attachInterruptArg(rt_int.spark_pin_12, rt_int.isr_ptr, (void *)&isr_params_sp12, RISING); - attachInterruptArg(rt_int.spark_pin_34, rt_int.isr_ptr, (void *)&isr_params_sp34, RISING); - - // Compute Reset Pin Bitmask - const uint16_t rst_bitmask = (1 << rt_rst.rst_io_12p) | - (1 << rt_rst.rst_io_12n) | - (1 << rt_rst.rst_io_34p) | - (1 << rt_rst.rst_io_34n); - - uint32_t it = 0; - uint32_t q_fail_count = 0; - while (params->rt_running) - { - // Global task variables - uint32_t pickup_flag = 0; - uint32_t spark_flag = 0; - -#ifdef DEBUG - Serial.print("\033[2J"); // clear screen - Serial.print("\033[H"); // cursor home - LOG_INFO("Iteration [", it, "]"); -#endif - - // WAIT FOR PICKUP SIGNAL - xTaskNotifyWait( - 0x00, // non pulire all'ingresso - ULONG_MAX, // pulisci i primi 8 bit - &pickup_flag, // valore ricevuto - portMAX_DELAY); - -#ifdef DEBUG - LOG_INFO("Pickup Flags: ", printBits(pickup_flag).c_str()); - if (!names.contains(pickup_flag)) - { - LOG_ERROR("Wrong Pickup Flag"); - continue; - } - else - { - LOG_INFO("Pickup Trigger: ", names.at(pickup_flag)); - } -#endif - - // WAIT FOR SPARK TO HAPPEN - auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(spark_timeout_max)); - if (ign_box_sts.coils12.spark_ok || ign_box_sts.coils34.spark_ok) // otherwise timeout if none is set in the ISR - spark_flag = ign_box_sts.coils12.spark_ok ? SPARK_FLAG_12 : SPARK_FLAG_34; - - xTaskNotifyStateClear(NULL); - ulTaskNotifyValueClear(NULL, 0xFFFFFFFF); -#ifdef DEBUG - LOG_INFO("Spark Flags: ", printBits(spark_flag).c_str()); - if (!names.contains(spark_flag)) - LOG_ERROR("No Spark"); - else - LOG_INFO("Spark Trigger:", names.at(spark_flag)); -#endif - - // A trigger from pickup 12 is followed by a spark event on 34 or vice versa pickup 34 triggers spark on 12 - if ((pickup_flag == TRIG_FLAG_12P || pickup_flag == TRIG_FLAG_12N) && spark_flag != SPARK_FLAG_12) - { - ign_box_sts.coils12.spark_status = ign_box_sts.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL; - // Save error on circular buffer and skip to next cycle // - LOG_ERROR("Spark Mismatch"); - continue; - } - - coilsStatus *coils; - switch (pickup_flag) - { - case TRIG_FLAG_12P: - case TRIG_FLAG_12N: - coils = &ign_box_sts.coils12; - break; - case TRIG_FLAG_34P: - case TRIG_FLAG_34N: - coils = &ign_box_sts.coils34; - break; - } - - bool new_data = false; - switch (pickup_flag) - { - // CASES for NEGATIVE cycle triggering of pickup and sparks 12 & 34 - case TRIG_FLAG_12P: - case TRIG_FLAG_34P: - { - // Timeout not occourred, expected POSITIVE edge spark OCCOURRED - if (spark_timeout == pdPASS) - { - coils->spark_delay = coils->spark_time - coils->trig_time; - coils->sstart_status = softStartStatus::NORMAL; // because spark on positive edge - coils->spark_status = sparkStatus::SPARK_POS_OK; // do not wait for spark on negative edge -#ifdef DEBUG - LOG_INFO("Trigger Spark POSITIVE"); - LOG_INFO("Spark12 Delay Timer: ", (int)coils->spark_delay); -#endif - } - // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED - else if (spark_timeout == pdFAIL) - { - coils->spark_status = sparkStatus::SPARK_NEG_WAIT; - coils->sstart_status = softStartStatus::NORMAL; - } - new_data = false; - break; // Do nothing more on positive pulse - } - // CASES for NEGATIVE cycle triggering of pickup and sparks 12 & 34 - case TRIG_FLAG_12N: - case TRIG_FLAG_34N: - { - const bool expected_negative12 = coils->spark_status == sparkStatus::SPARK_NEG_WAIT; - // Timeout not occourred, expected NEGATIVE edge spark OCCOURRED - if (spark_timeout == pdPASS && expected_negative12) - { - coils->spark_delay = coils->spark_time - coils->trig_time; - coils->sstart_status = softStartStatus::SOFT_START; - coils->spark_status == sparkStatus::SPARK_NEG_OK; -#ifdef DEBUG - LOG_INFO("Trigger Spark NEGATIVE"); - LOG_INFO("Spark12 Delay Timer: ", (int)ign_box_sts.coils12.spark_delay); -#endif - } - // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED - else if (spark_timeout == pdFAIL && expected_negative12) - { - coils->sstart_status = softStartStatus::NORMAL; - coils->spark_status = sparkStatus::SPARK_NEG_FAIL; - } - // Timeout not occouured, unexpected negative edge spark - else if (spark_timeout == pdPASS && !expected_negative12) - { - coils->sstart_status = softStartStatus::SOFT_START; - coils->spark_status = sparkStatus::SPARK_NEG_UNEXPECTED; - } - // Wait for finish of negative pulse to save data to buffer - new_data = true; - break; - } - default: - LOG_ERROR("Invalid Interrupt"); - break; - } - - if (new_data) - { - vTaskDelay(pdMS_TO_TICKS(1)); // delay 1ms to allow peak detectors to charge for negative cycle - // read adc channels: pickup12, out12 [ pos + neg ] - if (adc) // read only if adc initialized - { - // from peak detector circuits - ign_box_sts.coils12.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_12P_IN); - ign_box_sts.coils12.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_12N_IN); - ign_box_sts.coils34.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_34P_IN); - ign_box_sts.coils34.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_34N_IN); - ign_box_sts.coils12.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_12P_OUT); - ign_box_sts.coils12.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_12N_OUT); - ign_box_sts.coils34.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_34P_OUT); - ign_box_sts.coils34.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_34N_OUT); - } - else // simulate adc read timig - vTaskDelay(pdMS_TO_TICKS(6)); - - // reset peak detectors + sample and hold - // outputs on io expander - if (io) - { - const uint16_t iostat = io->read(); - io->write(iostat | rst_bitmask); - vTaskDelay(pdMS_TO_TICKS(1)); - io->write(iostat & ~rst_bitmask); - } - else - vTaskDelay(pdMS_TO_TICKS(2)); - - // send essage to main loop with ignition info, by copy so local static variable is ok - if (queue) - ign_box_sts.timestamp = esp_timer_get_time(); // update data timestamp - if (xQueueSendToBack(queue, (void *)&ign_box_sts, pdMS_TO_TICKS(1)) != pdPASS) - { - q_fail_count++; - LOG_ERROR("Failed to send to queue"); - } - } - } - LOG_WARN("Ending realTime Task"); - // Ignition A Interrupts DETACH - detachInterrupt(rt_int.trig_pin_12p); - detachInterrupt(rt_int.trig_pin_12n); - detachInterrupt(rt_int.trig_pin_34p); - detachInterrupt(rt_int.trig_pin_34n); - detachInterrupt(rt_int.spark_pin_12); - detachInterrupt(rt_int.spark_pin_34); - // delete present task - vTaskDelete(NULL); -} +void rtIgnitionTask(void *pvParameters);