refactored real time task to general with configuration structure
This commit is contained in:
@@ -33,14 +33,12 @@ struct Devices {
|
|||||||
PCA9555* io = NULL;
|
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);
|
adc->setMUX(ch);
|
||||||
// scarta 3 conversioni
|
// scarta 3 conversioni
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
while (digitalRead(drdy_pin));
|
|
||||||
adc->readSingle();
|
adc->readSingle();
|
||||||
}
|
}
|
||||||
// ora lettura valida a 30kSPS → ~100 µs di settling
|
// ora lettura valida a 30kSPS → ~100 µs di settling
|
||||||
while (digitalRead(drdy_pin));
|
|
||||||
return adc->convertToVoltage(adc->readSingle());
|
return adc->convertToVoltage(adc->readSingle());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// Test device Flag
|
||||||
#define TEST
|
#define TEST
|
||||||
|
|
||||||
|
// Arduino Libraries
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "soc/gpio_struct.h"
|
#include "soc/gpio_struct.h"
|
||||||
#ifndef TEST
|
#ifndef TEST
|
||||||
#include "pins.h"
|
#include "pins.h"
|
||||||
#else
|
#else
|
||||||
#include "pins_test.h"
|
#include "pins_test.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CORE_0 0
|
#define CORE_0 0
|
||||||
#define CORE_1 1
|
#define CORE_1 1
|
||||||
#define TASK_STACK 4096 // in words
|
#define TASK_STACK 4096 // in words
|
||||||
#define TASK_PRIORITY 2 // priorità leggermente più alta
|
#define TASK_PRIORITY (configMAX_PRIORITIES - 4) // highest priority after wifi tasks
|
||||||
|
|
||||||
// =====================
|
// =====================
|
||||||
// Event Flags (bitmask)
|
// Event Flags (bitmask)
|
||||||
// =====================
|
// =====================
|
||||||
#define TRIG_FLAG_A12P (1 << 0)
|
#define TRIG_FLAG_12P (1 << 0)
|
||||||
#define TRIG_FLAG_A12N (1 << 2)
|
#define TRIG_FLAG_12N (1 << 2)
|
||||||
#define TRIG_FLAG_A34P (1 << 1)
|
#define TRIG_FLAG_34P (1 << 1)
|
||||||
#define TRIG_FLAG_A34N (1 << 3)
|
#define TRIG_FLAG_34N (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 SPARK_FLAG_A12 (1 << 8)
|
#define SPARK_FLAG_NIL (1 << 8)
|
||||||
#define SPARK_FLAG_A34 (1 << 9)
|
#define SPARK_FLAG_12 (1 << 9)
|
||||||
#ifndef TEST
|
#define SPARK_FLAG_34 (1 << 10)
|
||||||
#define SPARK_FLAG_B12 (1 << 10)
|
|
||||||
#define SPARK_FLAG_B34 (1 << 11)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const std::map<const uint32_t, const char*> 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"},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Task handle
|
// Task handle
|
||||||
TaskHandle_t trigA_TaskHandle = NULL;
|
TaskHandle_t trigA_TaskHandle = NULL;
|
||||||
@@ -78,20 +62,22 @@ struct coilsStatus
|
|||||||
int64_t spark_time;
|
int64_t spark_time;
|
||||||
int64_t spark_delay;
|
int64_t spark_delay;
|
||||||
sparkStatus spark_status;
|
sparkStatus spark_status;
|
||||||
softStartStatus soft_start_status;
|
softStartStatus sstart_status;
|
||||||
float pickup_volts;
|
float peak_p_in, peak_n_in;
|
||||||
float output_volts;
|
float peak_p_out, peak_n_out;
|
||||||
|
float trigger_spark;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Task internal Status
|
// Task internal Status
|
||||||
struct ignitionBoxStatus
|
struct ignitionBoxStatus
|
||||||
{
|
{
|
||||||
|
int64_t timestamp;
|
||||||
// coils pairs for each ignition
|
// coils pairs for each ignition
|
||||||
coilsStatus coils12;
|
coilsStatus coils12;
|
||||||
coilsStatus coils34;
|
coilsStatus coils34;
|
||||||
// voltage from generator
|
// voltage from generator
|
||||||
float volts_gen = 0.0;
|
float volts_gen = 0.0;
|
||||||
|
// spark flags
|
||||||
bool spark12 = false;
|
bool spark12 = false;
|
||||||
bool spark34 = false;
|
bool spark34 = false;
|
||||||
};
|
};
|
||||||
@@ -103,126 +89,72 @@ ignitionBoxStatus ignB_status;
|
|||||||
static uint32_t pin2trig[49] = {0};
|
static uint32_t pin2trig[49] = {0};
|
||||||
void initTriggerPinMapping()
|
void initTriggerPinMapping()
|
||||||
{
|
{
|
||||||
pin2trig[TRIG_A12P] = TRIG_FLAG_A12P;
|
pin2trig[TRIG_A12P] = TRIG_FLAG_12P;
|
||||||
pin2trig[TRIG_A12N] = TRIG_FLAG_A12N;
|
pin2trig[TRIG_A12N] = TRIG_FLAG_12N;
|
||||||
pin2trig[TRIG_A34P] = TRIG_FLAG_A34P;
|
pin2trig[TRIG_A34P] = TRIG_FLAG_34P;
|
||||||
pin2trig[TRIG_A34N] = TRIG_FLAG_A34N;
|
pin2trig[TRIG_A34N] = TRIG_FLAG_34N;
|
||||||
#ifndef TEST
|
#ifndef TEST
|
||||||
pin2trig[TRIG_B12P] = TRIG_FLAG_B12P;
|
pin2trig[TRIG_B12P] = TRIG_FLAG_12P;
|
||||||
pin2trig[TRIG_B12N] = TRIG_FLAG_B12N;
|
pin2trig[TRIG_B12N] = TRIG_FLAG_12N;
|
||||||
pin2trig[TRIG_B34P] = TRIG_FLAG_B34P;
|
pin2trig[TRIG_B34P] = TRIG_FLAG_34P;
|
||||||
pin2trig[TRIG_B34N] = TRIG_FLAG_B34N;
|
pin2trig[TRIG_B34N] = TRIG_FLAG_34N;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t pin2spark[49] = {0};
|
static uint32_t pin2spark[49] = {0};
|
||||||
void initSparkPinMapping()
|
void initSparkPinMapping()
|
||||||
{
|
{
|
||||||
pin2spark[SPARK_A12] = SPARK_FLAG_A12;
|
pin2spark[SPARK_A12] = SPARK_FLAG_12;
|
||||||
pin2spark[SPARK_A34] = SPARK_FLAG_A34;
|
pin2spark[SPARK_A34] = SPARK_FLAG_34;
|
||||||
#ifndef TEST
|
#ifndef TEST
|
||||||
pin2spark[SPARK_B12] = SPARK_FLAG_B12;
|
pin2spark[SPARK_B12] = SPARK_FLAG_12;
|
||||||
pin2spark[SPARK_B34] = SPARK_FLAG_B34;
|
pin2spark[SPARK_B34] = SPARK_FLAG_34;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================
|
// =====================
|
||||||
// ISR (Pass return bitmask to ISR management function)
|
// ISR (Pass return bitmask to ISR management function)
|
||||||
// one function for each wake up pin conncted to a trigger
|
// 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();
|
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.spark12 = false;
|
||||||
ignA_status.spark34 = false;
|
ignA_status.spark34 = false;
|
||||||
|
|
||||||
if (flag & TRIG_FLAG_A12P) {
|
switch (flag)
|
||||||
|
{
|
||||||
|
case TRIG_FLAG_12P:
|
||||||
ignA_status.coils12.trig_time = time_us;
|
ignA_status.coils12.trig_time = time_us;
|
||||||
xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
|
xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
|
||||||
}
|
break;
|
||||||
if (flag & TRIG_FLAG_A34P) {
|
case TRIG_FLAG_34P:
|
||||||
ignA_status.coils34.trig_time = time_us;
|
ignA_status.coils34.trig_time = time_us;
|
||||||
xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
|
xTaskNotifyFromISR(trigA_TaskHandle, flag, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
|
||||||
}
|
break;
|
||||||
|
case SPARK_FLAG_12:
|
||||||
if (flag & SPARK_FLAG_A12) {
|
|
||||||
ignA_status.spark12 = true;
|
ignA_status.spark12 = true;
|
||||||
ignA_status.coils12.spark_time = time_us;
|
ignA_status.coils12.spark_time = time_us;
|
||||||
xTaskNotifyGive(trigA_TaskHandle);
|
vTaskNotifyGiveFromISR(trigA_TaskHandle, &xHigherPriorityTaskWoken);
|
||||||
}
|
break;
|
||||||
if (flag & SPARK_FLAG_A34) {
|
case SPARK_FLAG_34:
|
||||||
ignA_status.spark12 = false;
|
ignA_status.spark34 = true;
|
||||||
ignA_status.coils34.spark_time = time_us;
|
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();
|
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
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// Serial debug flag
|
||||||
|
// #define DEBUG
|
||||||
|
|
||||||
// Arduino Libraries
|
// Arduino Libraries
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
@@ -11,241 +14,290 @@
|
|||||||
// DEVICES
|
// DEVICES
|
||||||
#include "devices.h"
|
#include "devices.h"
|
||||||
|
|
||||||
//Global Variables and Flags
|
// Global Variables and Flags
|
||||||
static bool rt_task_running = true;
|
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
|
// Debug Variables
|
||||||
struct rtTaskParams {
|
#ifdef DEBUG
|
||||||
bool rt_running;
|
static const std::map<const uint32_t, const char *> names = {
|
||||||
Devices *dev;
|
{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");
|
LOG_ERROR("Null task parameters");
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Task Parameters and Devices
|
// Task Parameters and Devices
|
||||||
rtTaskParams* params = (rtTaskParams*) pvParameters;
|
const rtTaskParams *params = (const rtTaskParams *)pvParameters;
|
||||||
Devices* dev = (Devices*) params->dev;
|
const rtTaskInterrupts rt_int = params->rt_int; // copy to avoid external override
|
||||||
ADS1256* adc = dev->adc_a;
|
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
|
// Attach Pin Interrupts
|
||||||
attachInterruptArg(TRIG_A12P, trig_isr_a, (void*)TRIG_FLAG_A12P, RISING);
|
attachInterruptArg(rt_int.trig_pin_12p, rt_int.isr_ptr, (void *)TRIG_FLAG_12P, RISING);
|
||||||
attachInterruptArg(TRIG_A12N, trig_isr_a, (void*)TRIG_FLAG_A12N, RISING);
|
attachInterruptArg(rt_int.trig_pin_12n, rt_int.isr_ptr, (void *)TRIG_FLAG_12N, RISING);
|
||||||
attachInterruptArg(TRIG_A34P, trig_isr_a, (void*)TRIG_FLAG_A34P, RISING);
|
attachInterruptArg(rt_int.trig_pin_34p, rt_int.isr_ptr, (void *)TRIG_FLAG_34P, RISING);
|
||||||
attachInterruptArg(TRIG_A34N, trig_isr_a, (void*)TRIG_FLAG_A34N, RISING);
|
attachInterruptArg(rt_int.trig_pin_34n, rt_int.isr_ptr, (void *)TRIG_FLAG_34N, RISING);
|
||||||
attachInterruptArg(SPARK_A12, trig_isr_a, (void*)SPARK_FLAG_A12, RISING);
|
attachInterruptArg(rt_int.spark_pin_12, rt_int.isr_ptr, (void *)SPARK_FLAG_12, RISING);
|
||||||
attachInterruptArg(SPARK_A34, trig_isr_a, (void*)SPARK_FLAG_A34, RISING);
|
attachInterruptArg(rt_int.spark_pin_34, rt_int.isr_ptr, (void *)SPARK_FLAG_34, RISING);
|
||||||
|
|
||||||
uint32_t it=0;
|
// Compute Reset Pin Bitmask
|
||||||
while (rt_task_running) {
|
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
|
// Global task variables
|
||||||
uint32_t pickup_flag = 0;
|
uint32_t pickup_flag = 0;
|
||||||
uint32_t spark_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[2J"); // clear screen
|
||||||
Serial.print("\033[H"); // cursor home
|
Serial.print("\033[H"); // cursor home
|
||||||
LOG_INFO("Iteration [", it, "]");
|
LOG_INFO("Iteration [", it, "]");
|
||||||
|
#endif
|
||||||
|
|
||||||
//LOG_INFO("Pickup Flags: ", printBits(pickup_flag).c_str());
|
// WAIT FOR PICKUP SIGNAL
|
||||||
if (!names.contains(pickup_flag)) {
|
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");
|
LOG_ERROR("Wrong Pickup Flag");
|
||||||
continue;
|
continue;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
LOG_INFO("Pickup Trigger: ", names.at(pickup_flag));
|
LOG_INFO("Pickup Trigger: ", names.at(pickup_flag));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// WAIT FOR SPARK TO HAPPEN
|
// WAIT FOR SPARK TO HAPPEN
|
||||||
auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(5));
|
auto spark_timeout = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(spark_timeout_max));
|
||||||
//auto spark_timeout = xTaskNotifyWait(
|
if (ignA_status.spark12 || ignA_status.spark34) // otherwise timeout if none is set in the ISR
|
||||||
// 0x00, // non pulire all'ingresso
|
spark_flag = ignA_status.spark12 ? SPARK_FLAG_12 : SPARK_FLAG_34;
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
xTaskNotifyStateClear(NULL);
|
xTaskNotifyStateClear(NULL);
|
||||||
ulTaskNotifyValueClear(NULL, 0xFFFFFFFF);
|
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
|
// 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;
|
ignA_status.coils12.spark_status = ignA_status.coils34.spark_status = sparkStatus::SPARK_SYNC_FAIL;
|
||||||
// Save error on circular buffer and skip to next cycle //
|
// Save error on circular buffer and skip to next cycle //
|
||||||
LOG_ERROR("Spark Mismatch");
|
LOG_ERROR("Spark Mismatch");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
coilsStatus* c;
|
coilsStatus *c;
|
||||||
switch (pickup_flag)
|
switch (pickup_flag)
|
||||||
{
|
{
|
||||||
case TRIG_FLAG_A12P:
|
case TRIG_FLAG_12P:
|
||||||
case TRIG_FLAG_A12N:
|
case TRIG_FLAG_12N:
|
||||||
//case SPARK_FLAG_A12:
|
c = &ignA_status.coils12;
|
||||||
c = &ignA_status.coils12;
|
break;
|
||||||
break;
|
case TRIG_FLAG_34P:
|
||||||
case TRIG_FLAG_A34P:
|
case TRIG_FLAG_34N:
|
||||||
case TRIG_FLAG_A34N:
|
c = &ignA_status.coils34;
|
||||||
//case SPARK_FLAG_A34:
|
break;
|
||||||
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
|
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
|
if (adc) // read only if adc initialized
|
||||||
{
|
{
|
||||||
ignA_status.coils12.pickup_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A12_P);
|
ignA_status.volts_gen = adcReadChannel(adc, rt_adcch.adc_gen);
|
||||||
ignA_status.coils12.output_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A12_N);
|
// from peak detector circuits
|
||||||
ignA_status.coils34.pickup_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A34_P);
|
ignA_status.coils12.peak_p_in = adcReadChannel(adc, rt_adcch.adc_peak_12p_in);
|
||||||
ignA_status.coils34.output_volts = adcReadChannel(adc, ADC_A_DRDY, IN_A34_N);
|
ignA_status.coils12.peak_n_in = adcReadChannel(adc, rt_adcch.adc_peak_12n_in);
|
||||||
} else {
|
ignA_status.coils34.peak_p_in = adcReadChannel(adc, rt_adcch.adc_peak_34p_in);
|
||||||
LOG_WARN("ADC not initialized, skipping conversion");
|
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
|
else // simulate adc read timig
|
||||||
digitalWrite(POT_A_CS, HIGH);
|
vTaskDelay(pdMS_TO_TICKS(6));
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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");
|
LOG_WARN("Ending realTime Task");
|
||||||
// Ignition A Interrupts DETACH
|
// Ignition A Interrupts DETACH
|
||||||
detachInterrupt(TRIG_A12P);
|
detachInterrupt(rt_int.trig_pin_12p);
|
||||||
detachInterrupt(TRIG_A12N);
|
detachInterrupt(rt_int.trig_pin_12n);
|
||||||
detachInterrupt(TRIG_A34P);
|
detachInterrupt(rt_int.trig_pin_34p);
|
||||||
detachInterrupt(TRIG_A34N);
|
detachInterrupt(rt_int.trig_pin_34n);
|
||||||
detachInterrupt(SPARK_A12);
|
detachInterrupt(rt_int.spark_pin_12);
|
||||||
detachInterrupt(SPARK_A34);
|
detachInterrupt(rt_int.spark_pin_34);
|
||||||
// delete present task
|
// delete present task
|
||||||
vTaskDelete(NULL);
|
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
|
|
||||||
|
|||||||
Reference in New Issue
Block a user