From e0af350b893ff092fee629c03270336c3955f2a0 Mon Sep 17 00:00:00 2001 From: Emanuele Trabattoni Date: Mon, 30 Mar 2026 12:36:31 +0200 Subject: [PATCH] refactored real time task to general with configuration structure --- RotaxMonitor/src/devices.h | 4 +- RotaxMonitor/src/isr.h | 188 ++++++---------- RotaxMonitor/src/tasks.h | 426 +++++++++++++++++++++---------------- 3 files changed, 300 insertions(+), 318 deletions(-) diff --git a/RotaxMonitor/src/devices.h b/RotaxMonitor/src/devices.h index d683561..d87a2a0 100644 --- a/RotaxMonitor/src/devices.h +++ b/RotaxMonitor/src/devices.h @@ -33,14 +33,12 @@ struct Devices { PCA9555* io = NULL; }; -inline float adcReadChannel(ADS1256* adc, const uint32_t drdy_pin, const uint32_t ch){ +inline float adcReadChannel(ADS1256* adc, const uint8_t ch){ adc->setMUX(ch); // scarta 3 conversioni for (int i = 0; i < 3; i++) { - while (digitalRead(drdy_pin)); adc->readSingle(); } // ora lettura valida a 30kSPS → ~100 µs di settling - while (digitalRead(drdy_pin)); return adc->convertToVoltage(adc->readSingle()); } diff --git a/RotaxMonitor/src/isr.h b/RotaxMonitor/src/isr.h index 1c643bf..3f08d17 100644 --- a/RotaxMonitor/src/isr.h +++ b/RotaxMonitor/src/isr.h @@ -1,50 +1,34 @@ #pragma once +// Test device Flag #define TEST +// Arduino Libraries #include #include #include "soc/gpio_struct.h" #ifndef TEST - #include "pins.h" +#include "pins.h" #else - #include "pins_test.h" +#include "pins_test.h" #endif #define CORE_0 0 #define CORE_1 1 -#define TASK_STACK 4096 // in words -#define TASK_PRIORITY 2 // priorità leggermente più alta +#define TASK_STACK 4096 // in words +#define TASK_PRIORITY (configMAX_PRIORITIES - 4) // highest priority after wifi tasks // ===================== // Event Flags (bitmask) // ===================== -#define TRIG_FLAG_A12P (1 << 0) -#define TRIG_FLAG_A12N (1 << 2) -#define TRIG_FLAG_A34P (1 << 1) -#define TRIG_FLAG_A34N (1 << 3) -#ifndef TEST -#define TRIG_FLAG_B12P (1 << 4) -#define TRIG_FLAG_B12N (1 << 6) -#define TRIG_FLAG_B34P (1 << 5) -#define TRIG_FLAG_B34N (1 << 7) -#endif +#define TRIG_FLAG_12P (1 << 0) +#define TRIG_FLAG_12N (1 << 2) +#define TRIG_FLAG_34P (1 << 1) +#define TRIG_FLAG_34N (1 << 3) -#define SPARK_FLAG_A12 (1 << 8) -#define SPARK_FLAG_A34 (1 << 9) -#ifndef TEST -#define SPARK_FLAG_B12 (1 << 10) -#define SPARK_FLAG_B34 (1 << 11) -#endif - -static const std::map names = { - {TRIG_FLAG_A12P, "TRIG_FLAG_A12P"}, - {TRIG_FLAG_A12N, "TRIG_FLAG_A12N"}, - {TRIG_FLAG_A34P, "TRIG_FLAG_A34P"}, - {TRIG_FLAG_A34N, "TRIG_FLAG_A34N"}, - {SPARK_FLAG_A12, "SPARK_FLAG_A12"}, - {SPARK_FLAG_A34, "SPARK_FLAG_A34"}, -}; +#define SPARK_FLAG_NIL (1 << 8) +#define SPARK_FLAG_12 (1 << 9) +#define SPARK_FLAG_34 (1 << 10) // Task handle TaskHandle_t trigA_TaskHandle = NULL; @@ -78,20 +62,22 @@ struct coilsStatus int64_t spark_time; int64_t spark_delay; sparkStatus spark_status; - softStartStatus soft_start_status; - float pickup_volts; - float output_volts; + softStartStatus sstart_status; + float peak_p_in, peak_n_in; + float peak_p_out, peak_n_out; + float trigger_spark; }; // Task internal Status struct ignitionBoxStatus { + int64_t timestamp; // coils pairs for each ignition coilsStatus coils12; coilsStatus coils34; // voltage from generator float volts_gen = 0.0; - + // spark flags bool spark12 = false; bool spark34 = false; }; @@ -103,126 +89,72 @@ ignitionBoxStatus ignB_status; static uint32_t pin2trig[49] = {0}; void initTriggerPinMapping() { - pin2trig[TRIG_A12P] = TRIG_FLAG_A12P; - pin2trig[TRIG_A12N] = TRIG_FLAG_A12N; - pin2trig[TRIG_A34P] = TRIG_FLAG_A34P; - pin2trig[TRIG_A34N] = TRIG_FLAG_A34N; - #ifndef TEST - pin2trig[TRIG_B12P] = TRIG_FLAG_B12P; - pin2trig[TRIG_B12N] = TRIG_FLAG_B12N; - pin2trig[TRIG_B34P] = TRIG_FLAG_B34P; - pin2trig[TRIG_B34N] = TRIG_FLAG_B34N; - #endif + pin2trig[TRIG_A12P] = TRIG_FLAG_12P; + pin2trig[TRIG_A12N] = TRIG_FLAG_12N; + pin2trig[TRIG_A34P] = TRIG_FLAG_34P; + pin2trig[TRIG_A34N] = TRIG_FLAG_34N; +#ifndef TEST + pin2trig[TRIG_B12P] = TRIG_FLAG_12P; + pin2trig[TRIG_B12N] = TRIG_FLAG_12N; + pin2trig[TRIG_B34P] = TRIG_FLAG_34P; + pin2trig[TRIG_B34N] = TRIG_FLAG_34N; +#endif }; static uint32_t pin2spark[49] = {0}; void initSparkPinMapping() { - pin2spark[SPARK_A12] = SPARK_FLAG_A12; - pin2spark[SPARK_A34] = SPARK_FLAG_A34; - #ifndef TEST - pin2spark[SPARK_B12] = SPARK_FLAG_B12; - pin2spark[SPARK_B34] = SPARK_FLAG_B34; - #endif + pin2spark[SPARK_A12] = SPARK_FLAG_12; + pin2spark[SPARK_A34] = SPARK_FLAG_34; +#ifndef TEST + pin2spark[SPARK_B12] = SPARK_FLAG_12; + pin2spark[SPARK_B34] = SPARK_FLAG_34; +#endif }; // ===================== // 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) +void IRAM_ATTR trig_isr_a(void *arg) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; volatile const int64_t time_us = esp_timer_get_time(); - if (!trigA_TaskHandle) - return; // exit if task is not running - uint32_t flag = (uint32_t)arg; + // exit if task is not running + if (!trigA_TaskHandle) + return; + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + volatile const uint32_t flag = (uint32_t)arg; + + // reset spark flags, cannot be same time as trigger flags ignA_status.spark12 = false; ignA_status.spark34 = false; - if (flag & TRIG_FLAG_A12P) { + switch (flag) + { + case TRIG_FLAG_12P: ignA_status.coils12.trig_time = time_us; xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); - } - if (flag & TRIG_FLAG_A34P) { + break; + case TRIG_FLAG_34P: ignA_status.coils34.trig_time = time_us; xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); - } - - if (flag & SPARK_FLAG_A12) { + break; + case SPARK_FLAG_12: ignA_status.spark12 = true; ignA_status.coils12.spark_time = time_us; - xTaskNotifyGive(trigA_TaskHandle); - } - if (flag & SPARK_FLAG_A34) { - ignA_status.spark12 = false; + vTaskNotifyGiveFromISR(trigA_TaskHandle, &xHigherPriorityTaskWoken); + break; + case SPARK_FLAG_34: + ignA_status.spark34 = true; ignA_status.coils34.spark_time = time_us; - xTaskNotifyGive(trigA_TaskHandle); + vTaskNotifyGiveFromISR(trigA_TaskHandle, &xHigherPriorityTaskWoken); + break; + default: + break; } - //xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken); - if (xHigherPriorityTaskWoken) { + if (xHigherPriorityTaskWoken) portYIELD_FROM_ISR(); - } } - -// void IRAM_ATTR spark_a(void* arg) -// { -// BaseType_t xHigherPriorityTaskWoken = pdFALSE; -// volatile const int64_t time_us = esp_timer_get_time(); -// if (!trigA_TaskHandle) -// return; - -// uint32_t flag = (uint32_t) arg; - -// xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetBits, &xHigherPriorityTaskWoken); -// portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -// } - -#ifndef TEST -void IRAM_ATTR trig_isr_b() -{ - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - volatile const int64_t time_us = esp_timer_get_time(); - if (!trigB_TaskHandle) - return; // exit if task is not running - - #ifndef TEST - uint32_t status = GPIO.status; - #else - uint32_t status = GPIO.status1.val; - #endif - uint32_t pickup_flags = 0; - - while (status) - { - uint32_t pin = __builtin_ctz(status); // trova primo bit attivo - status &= ~(1 << pin); // clear bit - pickup_flags |= pin2trig[pin]; - } - - if (pickup_flags & TRIG_FLAG_B12P) - ignB_status.coils12.trig_time = time_us; - if (pickup_flags & TRIG_FLAG_B34P) - ignB_status.coils34.trig_time = time_us; - - xTaskNotifyFromISR(trigB_TaskHandle, pickup_flags, eSetBits, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -void IRAM_ATTR spark_b() -{ - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - volatile const int64_t time_us = esp_timer_get_time(); - if (!trigB_TaskHandle) - return; - uint32_t spark_flag = GPIO.status1.val & SPARK_B12 ? SPARK_FLAG_B12 : SPARK_FLAG_B34; - if (spark_flag & SPARK_FLAG_B12) - ignB_status.coils12.spark_time = time_us; - if (spark_flag & SPARK_FLAG_B34) - ignB_status.coils34.spark_time = time_us; - xTaskNotifyFromISR(trigB_TaskHandle, spark_flag, eSetBits, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} -#endif diff --git a/RotaxMonitor/src/tasks.h b/RotaxMonitor/src/tasks.h index dd965aa..b46299d 100644 --- a/RotaxMonitor/src/tasks.h +++ b/RotaxMonitor/src/tasks.h @@ -1,5 +1,8 @@ #pragma once +// Serial debug flag +// #define DEBUG + // Arduino Libraries #include #include @@ -11,241 +14,290 @@ // DEVICES #include "devices.h" -//Global Variables and Flags +// Global Variables and Flags static bool rt_task_running = true; -const auto spark_timeout_max = 1000; // convert to microsecond timer +const auto spark_timeout_max = 2; // in milliseconds -// RT task parameters -struct rtTaskParams { - bool rt_running; - Devices *dev; +// Debug Variables +#ifdef DEBUG +static const std::map names = { + {TRIG_FLAG_A12P, "TRIG_FLAG_A12P"}, + {TRIG_FLAG_A12N, "TRIG_FLAG_A12N"}, + {TRIG_FLAG_A34P, "TRIG_FLAG_A34P"}, + {TRIG_FLAG_A34N, "TRIG_FLAG_A34N"}, + {SPARK_FLAG_A12, "SPARK_FLAG_A12"}, + {SPARK_FLAG_A34, "SPARK_FLAG_A34"}, +}; +#endif + +// RT task Interrupt parameters +struct rtTaskInterrupts +{ + void (*isr_ptr)(void *); + const uint8_t trig_pin_12p; + const uint8_t trig_pin_12n; + const uint8_t trig_pin_34p; + const uint8_t trig_pin_34n; + const uint8_t spark_pin_12; + const uint8_t spark_pin_34; }; -void ignitionA_task(void *pvParameters) { +// RT Task Peak Detector Reset pins +struct rtTaskResets +{ + const uint8_t rst_io_12p; + const uint8_t rst_io_12n; + const uint8_t rst_io_34p; + const uint8_t rst_io_34n; +}; - if (!pvParameters) { +// RT Task Adc channels +struct rtTaskAdChannels +{ + const uint8_t adc_gen; + const uint8_t adc_spark_12; + const uint8_t adc_spark_34; + const uint8_t adc_peak_12p_in; + const uint8_t adc_peak_12n_in; + const uint8_t adc_peak_34p_in; + const uint8_t adc_peak_34n_in; + const uint8_t adc_peak_12p_out; + const uint8_t adc_peak_12n_out; + const uint8_t adc_peak_34p_out; + const uint8_t adc_peak_34n_out; +}; + +// RT task parameters +struct rtTaskParams +{ + bool rt_running; // run flag, false to terminate + Devices *dev; + QueueHandle_t rt_queue; + const rtTaskInterrupts rt_int; // interrupt pins to attach + const rtTaskResets rt_resets; // reset ping for peak detectors + const rtTaskAdChannels rt_adcch; // adc channels +}; + +void ignitionA_task(void *pvParameters) +{ + + if (!pvParameters) + { LOG_ERROR("Null task parameters"); vTaskDelete(NULL); } // Task Parameters and Devices - rtTaskParams* params = (rtTaskParams*) pvParameters; - Devices* dev = (Devices*) params->dev; - ADS1256* adc = dev->adc_a; + const rtTaskParams *params = (const 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 + const rtTaskAdChannels rt_adcch = params->rt_adcch; // copy to avoid external override + QueueHandle_t queue = params->rt_queue; + Devices *dev = params->dev; + ADS1256 *adc = dev->adc_a; + PCA9555 *io = dev->io; - // Ignition A Interrupts - attachInterruptArg(TRIG_A12P, trig_isr_a, (void*)TRIG_FLAG_A12P, RISING); - attachInterruptArg(TRIG_A12N, trig_isr_a, (void*)TRIG_FLAG_A12N, RISING); - attachInterruptArg(TRIG_A34P, trig_isr_a, (void*)TRIG_FLAG_A34P, RISING); - attachInterruptArg(TRIG_A34N, trig_isr_a, (void*)TRIG_FLAG_A34N, RISING); - attachInterruptArg(SPARK_A12, trig_isr_a, (void*)SPARK_FLAG_A12, RISING); - attachInterruptArg(SPARK_A34, trig_isr_a, (void*)SPARK_FLAG_A34, RISING); + // Attach Pin Interrupts + attachInterruptArg(rt_int.trig_pin_12p, rt_int.isr_ptr, (void *)TRIG_FLAG_12P, RISING); + attachInterruptArg(rt_int.trig_pin_12n, rt_int.isr_ptr, (void *)TRIG_FLAG_12N, RISING); + attachInterruptArg(rt_int.trig_pin_34p, rt_int.isr_ptr, (void *)TRIG_FLAG_34P, RISING); + attachInterruptArg(rt_int.trig_pin_34n, rt_int.isr_ptr, (void *)TRIG_FLAG_34N, RISING); + attachInterruptArg(rt_int.spark_pin_12, rt_int.isr_ptr, (void *)SPARK_FLAG_12, RISING); + attachInterruptArg(rt_int.spark_pin_34, rt_int.isr_ptr, (void *)SPARK_FLAG_34, RISING); - uint32_t it=0; - while (rt_task_running) { + // 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 (rt_task_running) + { // Global task variables uint32_t pickup_flag = 0; uint32_t spark_flag = 0; - - // 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 Serial.print("\033[2J"); // clear screen Serial.print("\033[H"); // cursor home LOG_INFO("Iteration [", it, "]"); +#endif - //LOG_INFO("Pickup Flags: ", printBits(pickup_flag).c_str()); - if (!names.contains(pickup_flag)) { + // 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 { + } + else + { LOG_INFO("Pickup Trigger: ", names.at(pickup_flag)); } +#endif // WAIT FOR SPARK TO HAPPEN - auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(5)); - //auto spark_timeout = xTaskNotifyWait( - // 0x00, // non pulire all'ingresso - // ULONG_MAX, // pulisci gli 8 bit successivi - // &spark_flag, // valore ricevuto - // spark_timeout_max - //); - - digitalWrite(POT_A_CS, HIGH); - if (ignA_status.spark12 || ignA_status.spark34) { //otherwise timeout - //LOG_INFO("Spark Flags: ", printBits(spark_flag).c_str()); - spark_flag = ignA_status.spark12 ? SPARK_FLAG_A12 : SPARK_FLAG_A34; - if (!names.contains(spark_flag)) { - LOG_ERROR("Wrong Spark Flag"); - } else { - LOG_INFO("Spark Trigger:", names.at(spark_flag)); - } - } else { - LOG_INFO("Spark Timeout"); - } + auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(spark_timeout_max)); + if (ignA_status.spark12 || ignA_status.spark34) // otherwise timeout if none is set in the ISR + spark_flag = ignA_status.spark12 ? 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_A12P || pickup_flag == TRIG_FLAG_A12N) && spark_flag != SPARK_FLAG_A12) { + if ((pickup_flag == TRIG_FLAG_12P || pickup_flag == TRIG_FLAG_12N) && spark_flag != SPARK_FLAG_12) + { ignA_status.coils12.spark_status = ignA_status.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL; // Save error on circular buffer and skip to next cycle // LOG_ERROR("Spark Mismatch"); continue; } - coilsStatus* c; - switch (pickup_flag) + coilsStatus *c; + switch (pickup_flag) { - case TRIG_FLAG_A12P: - case TRIG_FLAG_A12N: - //case SPARK_FLAG_A12: - c = &ignA_status.coils12; - break; - case TRIG_FLAG_A34P: - case TRIG_FLAG_A34N: - //case SPARK_FLAG_A34: - c = &ignA_status.coils34; - break; + case TRIG_FLAG_12P: + case TRIG_FLAG_12N: + c = &ignA_status.coils12; + break; + case TRIG_FLAG_34P: + case TRIG_FLAG_34N: + c = &ignA_status.coils34; + break; } - - bool new_data = false; - - switch (pickup_flag) { - // CASES for NEGATIVE cycle triggering of pickup and sparks 12 & 34 - case TRIG_FLAG_A12P: - case TRIG_FLAG_A34P: - { - LOG_INFO("Trigger Pickup POSITIVE"); - // Timeout not occourred, expected POSITIVE edge spark OCCOURRED - if (spark_timeout == pdPASS) { - c->spark_delay = c->spark_time - c->trig_time; - c->soft_start_status = softStartStatus::NORMAL; // because spark on positive edge - c->spark_status = sparkStatus::SPARK_POS_OK; // do not wait for spark on negative edge - LOG_INFO("Trigger Spark POSITIVE"); - LOG_INFO("Spark12 Delay Timer: ", (int)c->spark_delay); - } - // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED - else if (spark_timeout == pdFAIL) { - c->spark_status = sparkStatus::SPARK_NEG_WAIT; - c->soft_start_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_A12N: - case TRIG_FLAG_A34N: - { - const bool expected_negative12 = c->spark_status == sparkStatus::SPARK_NEG_WAIT; - LOG_INFO("Trigger Pickup NEGATIVE"); - // Timeout not occourred, expected NEGATIVE edge spark OCCOURRED - if (spark_timeout == pdPASS && expected_negative12) { - c->spark_delay = c->spark_time - c->trig_time; - c->soft_start_status = softStartStatus::SOFT_START; - c->spark_status == sparkStatus::SPARK_NEG_OK; - LOG_INFO("Trigger Spark NEGATIVE"); - LOG_INFO("Spark12 Delay Timer: ", (int)ignA_status.coils12.spark_delay); - } - // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED - else if (spark_timeout == pdFAIL && expected_negative12) { - c->soft_start_status = softStartStatus::NORMAL; - c->spark_status = sparkStatus::SPARK_NEG_FAIL; - } - // Timeout not occouured, unexpected negative edge spark - else if (spark_timeout == pdPASS && !expected_negative12) { - c->soft_start_status = softStartStatus::SOFT_START; - c->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 A Interrupt"); - break; - } - it++; - digitalWrite(POT_A_CS, LOW); - continue; - if (new_data) { + 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) + { + c->spark_delay = c->spark_time - c->trig_time; + c->sstart_status = softStartStatus::NORMAL; // because spark on positive edge + c->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)c->spark_delay); +#endif + } + // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED + else if (spark_timeout == pdFAIL) + { + c->spark_status = sparkStatus::SPARK_NEG_WAIT; + c->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 = c->spark_status == sparkStatus::SPARK_NEG_WAIT; + // Timeout not occourred, expected NEGATIVE edge spark OCCOURRED + if (spark_timeout == pdPASS && expected_negative12) + { + c->spark_delay = c->spark_time - c->trig_time; + c->sstart_status = softStartStatus::SOFT_START; + c->spark_status == sparkStatus::SPARK_NEG_OK; +#ifdef DEBUG + LOG_INFO("Trigger Spark NEGATIVE"); + LOG_INFO("Spark12 Delay Timer: ", (int)ignA_status.coils12.spark_delay); +#endif + } + // Timeout occourred, expected POSITIVE edge spark NOT OCCOURRED + else if (spark_timeout == pdFAIL && expected_negative12) + { + c->sstart_status = softStartStatus::NORMAL; + c->spark_status = sparkStatus::SPARK_NEG_FAIL; + } + // Timeout not occouured, unexpected negative edge spark + else if (spark_timeout == pdPASS && !expected_negative12) + { + c->sstart_status = softStartStatus::SOFT_START; + c->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 ] + // read adc channels: pickup12, out12 [ pos + neg ] if (adc) // read only if adc initialized { - ignA_status.coils12.pickup_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A12_P); - ignA_status.coils12.output_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A12_N); - ignA_status.coils34.pickup_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A34_P); - ignA_status.coils34.output_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A34_N); - } else { - LOG_WARN("ADC not initialized, skipping conversion"); + ignA_status.volts_gen = adcReadChannel(adc, rt_adcch.adc_gen); + // from peak detector circuits + ignA_status.coils12.peak_p_in = adcReadChannel(adc, rt_adcch.adc_peak_12p_in); + ignA_status.coils12.peak_n_in = adcReadChannel(adc, rt_adcch.adc_peak_12n_in); + ignA_status.coils34.peak_p_in = adcReadChannel(adc, rt_adcch.adc_peak_34p_in); + ignA_status.coils34.peak_n_in = adcReadChannel(adc, rt_adcch.adc_peak_34n_in); + ignA_status.coils12.peak_p_out = adcReadChannel(adc, rt_adcch.adc_peak_12p_out); + ignA_status.coils12.peak_n_out = adcReadChannel(adc, rt_adcch.adc_peak_12n_out); + ignA_status.coils34.peak_p_out = adcReadChannel(adc, rt_adcch.adc_peak_34p_out); + ignA_status.coils34.peak_n_out = adcReadChannel(adc, rt_adcch.adc_peak_34n_out); + // from sample and hold triggered from spark interrupt + ignA_status.coils12.trigger_spark = adcReadChannel(adc, rt_adcch.adc_spark_12); + ignA_status.coils34.trigger_spark = adcReadChannel(adc, rt_adcch.adc_spark_34); } - // reset peak detectors -> gli output sono sull'expander, temporaneo uso il PC del pot non collegato - digitalWrite(POT_A_CS, HIGH); - // digitalWrite(RST_A12P, HIGH); - // digitalWrite(RST_A12N, HIGH); - // digitalWrite(RST_A34P, HIGH); - // digitalWrite(RST_A34N, HIGH); - vTaskDelay(1); - digitalWrite(POT_A_CS, HIGH); - // digitalWrite(RST_A12P, LOW); - // digitalWrite(RST_A12N, LOW); - // digitalWrite(RST_A34P, LOW); - // digitalWrite(RST_A34N, LOW); - // save on circluar buffer 12 - } + 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 + if (queue) + ignA_status.timestamp = esp_timer_get_time(); // update data timestamp + if (xQueueSendToBack(queue, (void*)&ignA_status, 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(TRIG_A12P); - detachInterrupt(TRIG_A12N); - detachInterrupt(TRIG_A34P); - detachInterrupt(TRIG_A34N); - detachInterrupt(SPARK_A12); - detachInterrupt(SPARK_A34); + 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); } - -#ifndef TEST -void ignitionB_task(void *pvParameters) { - uint32_t notifiedValue; - // Ignition B Interrupts - attachInterrupt(TRIG_B12P, trig_isr_b, RISING); - attachInterrupt(TRIG_B34P, trig_isr_b, RISING); - attachInterrupt(TRIG_B12N, trig_isr_b, RISING); - attachInterrupt(TRIG_B34N, trig_isr_b, RISING); - attachInterrupt(SPARK_B12, spark_b, RISING); - attachInterrupt(SPARK_B34, spark_b, RISING); - while (true) { - // attende eventi - xTaskNotifyWait( - 0x00, // non pulire all'ingresso - 0xFFFFFFFF, // pulisci tutti i bit all'uscita - ¬ifiedValue, // valore ricevuto - portMAX_DELAY - ); - - switch (notifiedValue) { - case TRIG_FLAG_B12P: - break; - case TRIG_FLAG_B34P: - break; - case TRIG_FLAG_B12N: - break; - case TRIG_FLAG_B34N: - break; - default: - LOG_ERROR("Invalid B Interrupt: ", notifiedValue); - } - } -} -#endif