diff --git a/RotaxMonitor/src/isr.h b/RotaxMonitor/src/isr.h index b16cfb7..8a9b77a 100644 --- a/RotaxMonitor/src/isr.h +++ b/RotaxMonitor/src/isr.h @@ -1,40 +1,106 @@ #include +#include "soc/gpio_struct.h" +#include "pins.h" + + +#define CORE_0 0 +#define CORE_1 1 +#define TASK_STACK 4096 // in words +#define TASK_PRIORITY 2 // priorità leggermente più alta // ===================== // Event Flags (bitmask) // ===================== -#define PKDT_FLAG_AP (1 << 0) -#define PKDT_FLAG_AN (1 << 1) -#define PKDT_FLAG_BP (1 << 2) -#define PKDT_FLAG_BN (1 << 3) +#define TRIG_FLAG_A12P (1 << 0) +#define TRIG_FLAG_A12N (1 << 2) +#define TRIG_FLAG_A34P (1 << 1) +#define TRIG_FLAG_A34N (1 << 3) +#define TRIG_FLAG_B12P (1 << 4) +#define TRIG_FLAG_B12N (1 << 6) +#define TRIG_FLAG_B34P (1 << 5) +#define TRIG_FLAG_B34N (1 << 7) // Task handle -TaskHandle_t pkdtTaskHandle = NULL; +TaskHandle_t trigA_TaskHandle = NULL; +TaskHandle_t trigB_TaskHandle = NULL; + +// Task internal Status +struct taskStatus { + int64_t trig12_start; + int64_t trig34_start; + + int64_t trig12_time; + int64_t trig34_time; + + bool trig12_complete = false; + bool trig34_complete = false; + + bool soft12 = false; + bool soft34 = false; + + bool error12 = false; + bool error34 = false; +}; + +taskStatus ignA_status; +taskStatus ignB_status; + +// Pin to flag Map +static const uint32_t int2flag[] = { + [TRIG_A12P] = TRIG_FLAG_A12P, + [TRIG_A12N] = TRIG_FLAG_A34P, + [TRIG_A34P] = TRIG_FLAG_A12N, + [TRIG_A34N] = TRIG_FLAG_A34N, + [TRIG_B12P] = TRIG_FLAG_B12P, + [TRIG_B12N] = TRIG_FLAG_B34P, + [TRIG_B34P] = TRIG_FLAG_B12N, + [TRIG_B34N] = TRIG_FLAG_B34N, +}; // ===================== // ISR (Pass return bitmask to ISR management function) // one function for each wake up pin conncted to a trigger // ===================== -void IRAM_ATTR pkdt_isr_ap() { +void IRAM_ATTR trig_isr_a() { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_AP, eSetBits, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + auto startTime = esp_timer_get_time(); + + uint32_t status = GPIO.status; + uint32_t flags = 0; + + while (status) { + uint32_t pin = __builtin_ctz(status); // trova primo bit attivo + status &= ~(1 << pin); // clear bit + + flags |= int2flag[pin]; + } + + if (flags & (TRIG_FLAG_A12P | TRIG_FLAG_A12N)) + ignA_status.trig12_start = startTime; + else + ignA_status.trig12_start = startTime; + + if (trigA_TaskHandle) { + xTaskNotifyFromISR(trigA_TaskHandle, flags, eSetBits, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } } -void IRAM_ATTR pkdt_isr_an() { +void IRAM_ATTR trig_isr_b() { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_AN, eSetBits, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} -void IRAM_ATTR pkdt_isr_bp() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_BP, eSetBits, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} + uint32_t status = GPIO.status; + uint32_t flags = 0; -void IRAM_ATTR pkdt_isr_bn() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR(pkdtTaskHandle, PKDT_FLAG_BN, eSetBits, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + while (status) { + uint32_t pin = __builtin_ctz(status); // trova primo bit attivo + status &= ~(1 << pin); // clear bit + + flags |= int2flag[pin]; + } + + if (trigB_TaskHandle) { + xTaskNotifyFromISR(trigB_TaskHandle, flags, eSetBits, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } } diff --git a/RotaxMonitor/src/main.cpp b/RotaxMonitor/src/main.cpp index 0919746..cecd668 100644 --- a/RotaxMonitor/src/main.cpp +++ b/RotaxMonitor/src/main.cpp @@ -10,38 +10,21 @@ #include #include #include +#include // Device Libraries #include #include -void pkdtTask(void *pvParameters) { - uint32_t notifiedValue; - - while (true) { - // attende eventi - xTaskNotifyWait( - 0x00, // non pulire all'ingresso - 0xFFFFFFFF, // pulisci tutti i bit all'uscita - ¬ifiedValue, // valore ricevuto - portMAX_DELAY - ); - - // 🔥 QUI GIRA SU CORE 0 - switch (notifiedValue) - case PKDT_FLAG_AP: { - handlePKDT(PKDT_AP); - break; - } - default: - LOG_ERROR("Invalid Interrupt: ", notifiedValue); - } -} - void setup() { - Serial.begin(9600); + delay(250); + Serial.begin(115200); + + // Setup Logger LOG_ATTACH_SERIAL(Serial); LOG_SET_LEVEL(DebugLogLevel::LVL_INFO); + + // Print Processor Info LOG_INFO("ESP32 Chip:", ESP.getChipModel()); LOG_INFO("ESP32 PSram:", ESP.getPsramSize()); LOG_INFO("ESP32 Flash:", ESP.getFlashChipSize()); @@ -49,40 +32,72 @@ void setup() { LOG_INFO("ESP32 Sketch:", ESP.getFreeSketchSpace()); // Initialize Interrupt pins on peak detectors - pinMode(PKDT_AP, INPUT_PULLDOWN); - pinMode(PKDT_AN, INPUT_PULLDOWN); - pinMode(PKDT_BP, INPUT_PULLDOWN); - pinMode(PKDT_BN, INPUT_PULLDOWN); - // interrupt - attachInterrupt(PKDT_AP, pkdt_isr_ap, RISING); - attachInterrupt(PKDT_AN, pkdt_isr_an, RISING); - attachInterrupt(PKDT_BP, pkdt_isr_bp, RISING); - attachInterrupt(PKDT_BN, pkdt_isr_bn, RISING); + pinMode(TRIG_A12P, INPUT_PULLDOWN); + pinMode(TRIG_A12N, INPUT_PULLDOWN); + pinMode(TRIG_A34P, INPUT_PULLDOWN); + pinMode(TRIG_A34N, INPUT_PULLDOWN); + pinMode(TRIG_B12P, INPUT_PULLDOWN); + pinMode(TRIG_B12N, INPUT_PULLDOWN); + pinMode(TRIG_B34P, INPUT_PULLDOWN); + pinMode(TRIG_B34N, INPUT_PULLDOWN); + + // Ignition A Interrupts + attachInterrupt(TRIG_A12P, trig_isr_a, RISING); + attachInterrupt(TRIG_A34P, trig_isr_a, RISING); + attachInterrupt(TRIG_A12N, trig_isr_a, RISING); + attachInterrupt(TRIG_A34N, trig_isr_a, RISING); + // 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); // Init SPI interface SPI.begin(); - - // Init ADC - auto adc = ADS1256(ADC_DRDY, ADC_RST, ADC_SYNC, ADC_CS, 0.0, SPI); - ADS1256. } void loop() { - // task su core 0 - auto isrTask = xTaskCreatePinnedToCore( - pkdtTask, - "pkdtTask", - 4096, + // global variables + bool running = true; + + // Ignition A on Core 0 + auto ignA_task_success = xTaskCreatePinnedToCore( + ignitionA_task, + "ignitionA_task", + TASK_STACK, NULL, - 2, // priorità leggermente più alta - &pkdtTaskHandle, - 0 + TASK_PRIORITY, + &trigA_TaskHandle, + CORE_0 ); - if (isrTask != pdPASS){ + // Ignition A on Core 1 + auto ignB_task_success = xTaskCreatePinnedToCore( + ignitionB_task, + "ignitionB_task", + TASK_STACK, + NULL, + TASK_PRIORITY, // priorità leggermente più alta + &trigA_TaskHandle, + CORE_1 + ); + + if ((ignA_task_success && ignB_task_success) != pdPASS){ LOG_ERROR("Unble to initialize ISR task"); } + LOG_INFO("Real Time Tasks A&B initialized"); + + ////////////////////// MAIN LOOP ////////////////////// + while (running) { + + } + + if (trigA_TaskHandle) + vTaskDelete(trigA_TaskHandle); + if (trigB_TaskHandle) + vTaskDelete(trigB_TaskHandle); + ////////////////////// MAIN LOOP ////////////////////// } diff --git a/RotaxMonitor/src/pins.h b/RotaxMonitor/src/pins.h index 540e64c..30e5491 100644 --- a/RotaxMonitor/src/pins.h +++ b/RotaxMonitor/src/pins.h @@ -6,14 +6,15 @@ #define SPI_SCK 12 // ===================== -// CHIP SELECT +// I2C BUS // ===================== -#define ADC_CS 10 -#define POT_CS 9 +#define SDA 8 +#define SCL 9 // ===================== // ADC CONTROL // ===================== +#define ADC_CS 10 #define ADC_DRDY 4 #define ADC_RST 5 #define ADC_SYNC 6 @@ -21,47 +22,63 @@ // ===================== // DIGITAL POT // ===================== -#define POT_DRDY 7 +#define POT_CS 7 +#define POT_DRDY 18 // ===================== -// RELAY +// RELAY OUT // ===================== -#define PICK_RELAY 8 +#define PICK_RELAY 21 // ===================== -// PEAK DETECTORS (DIGITAL INPUT) +// TRIGGER INPUT INTERRUPTS // ===================== -#define PKDT_AP 1 -#define PKDT_AN 2 -#define PKDT_BP 3 -#define PKDT_BN 14 +#define TRIG_A12P 1 +#define TRIG_A12N 2 +#define TRIG_A34P 3 +#define TRIG_A34N 14 +#define TRIG_B12P 15 +#define TRIG_B12N 16 +#define TRIG_B34P 17 +#define TRIG_B34N 18 // ===================== -// TRIGGER INPUTS +// PEAK DETECTOR RESET OUTPUTS // ===================== -#define TRIG_AP 15 -#define TRIG_AN 16 -#define TRIG_BP 17 -#define TRIG_BN 18 +#define RST_A12P 39 +#define RST_A12N 40 +#define RST_A34P 41 +#define RST_A34N 42 +#define RST_B12P 35 +#define RST_B12N 36 +#define RST_B34P 37 +#define RST_B34N 38 // ===================== -// SOFT START DETECT +// SPARK DETECT INPUTS // ===================== -#define SOFT_A 21 -#define SOFT_B 47 +#define SPARK_A12 45 // input only +#define SPARK_A34 46 // input only +#define SPARK_B12 47 +#define SPARK_B34 48 // ===================== -// STATUS OUTPUT +// STATUS & BUTTON su PCA9555 (I2C) // ===================== -#define STA_1 35 -#define STA_2 36 -#define STA_3 37 -#define STA_4 38 +#define STA_1 0 +#define STA_2 1 +#define STA_3 2 +#define STA_4 3 +#define STA_5 4 +#define STA_6 5 +#define STA_7 6 +#define STA_8 7 -// ===================== -// BUTTON INPUT -// ===================== -#define BTN_1 39 -#define BTN_2 40 -#define BTN_3 41 -#define BTN_4 42 +#define BTN_1 8 +#define BTN_2 9 +#define BTN_3 10 +#define BTN_4 11 +#define BTN_5 12 +#define BTN_6 13 +#define BTN_7 14 +#define BTN_8 15 diff --git a/RotaxMonitor/src/tasks.h b/RotaxMonitor/src/tasks.h new file mode 100644 index 0000000..52454b6 --- /dev/null +++ b/RotaxMonitor/src/tasks.h @@ -0,0 +1,98 @@ +// Arduino Libraries +#include +#include + +// ISR +#include "isr.h" + +const uint16_t spark_delay_us = 500; + +void ignitionA_task(void *pvParameters) { + uint32_t notifiedValue; + + while (true) { + // attende eventi + xTaskNotifyWait( + 0x00, // non pulire all'ingresso + ULONG_MAX, // pulisci tutti i bit all'uscita + ¬ifiedValue, // valore ricevuto + portMAX_DELAY + ); + + uint64_t wait_time=0; + switch (notifiedValue) { + case TRIG_FLAG_A12P: + case TRIG_FLAG_A12N: + bool spark12_timeout = false; + if (ignA_status.trig12_complete) { + // read peak adc values from sample and hold + } else { + while(!digitalRead(SPARK_A12)) { + wait_time = ignA_status.trig12_start - esp_timer_get_time(); + if (wait_time >= spark_delay_us) { + spark12_timeout = true; + break; + } + } + if (spark12_timeout) { // spark did not happen, timeout + ignA_status.trig12_complete = false; + } else { // spark did happen + ignA_status.trig12_complete = true; + ignA_status.trig12_time = wait_time; + } + } + break; + + case TRIG_FLAG_A34P: + case TRIG_FLAG_A34N: + bool spark34_timeout = false; + if (ignA_status.trig12_complete) { + // read peak adc values from sample and hold + } else { + while(!digitalRead(SPARK_A34)) { + wait_time = ignA_status.trig34_start - esp_timer_get_time(); + if (wait_time >= spark_delay_us) { + spark12_timeout = true; + break; + } + } + if (spark34_timeout) { // spark did not happen, timeout + ignA_status.trig34_complete = false; + } else { // spark did happen + ignA_status.trig34_complete = true; + ignA_status.trig34_time = wait_time; + } + } + break; + default: + LOG_ERROR("Invalid A Interrupt: ", notifiedValue); + } + + } +} + +void ignitionB_task(void *pvParameters) { + uint32_t notifiedValue; + 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); + } + } +} \ No newline at end of file