perf: house cleaning

This commit is contained in:
Pietro Marchini
2022-12-07 22:17:44 +01:00
parent 70e70e6fc9
commit 297e2960b2
2 changed files with 450 additions and 0 deletions

363
src/lib/esp32idfDimmer.c Normal file
View File

@@ -0,0 +1,363 @@
#include "esp32idfDimmer.h"
static const char *TAG = "Esp32idfDimmer";
int pulseWidth = 2;
volatile int current_dim = 0;
int all_dim = 3;
int rise_fall = true;
char user_zero_cross = '0';
int debug_signal_zc = 0;
bool flagDebug = false;
static int toggleCounter = 0;
static int toggleReload = 25;
volatile bool _initDone = false;
volatile int _steps = 0;
static dimmertyp *dimmer[ALL_DIMMERS];
volatile bool firstSetup = false;
volatile uint16_t dimPower[ALL_DIMMERS];
volatile gpio_num_t dimOutPin[ALL_DIMMERS];
volatile gpio_num_t dimZCPin[ALL_DIMMERS];
volatile uint16_t zeroCross[ALL_DIMMERS];
volatile DIMMER_MODE_typedef dimMode[ALL_DIMMERS];
volatile ON_OFF_typedef dimState[ALL_DIMMERS];
volatile uint16_t dimCounter[ALL_DIMMERS];
static uint16_t dimPulseBegin[ALL_DIMMERS];
volatile uint16_t togMax[ALL_DIMMERS];
volatile uint16_t togMin[ALL_DIMMERS];
volatile bool togDir[ALL_DIMMERS];
/* timer configurations */
timer_config_t m_timer_config;
dimmertyp *createDimmer(gpio_num_t user_dimmer_pin, gpio_num_t zc_dimmer_pin)
{
if (current_dim >= ALL_DIMMERS)
{
return NULL;
}
current_dim++;
dimmer[current_dim - 1] = malloc(sizeof(dimmertyp));
dimmer[current_dim - 1]->current_num = current_dim - 1;
dimmer[current_dim - 1]->toggle_state = false;
dimPulseBegin[current_dim - 1] = 1;
dimOutPin[current_dim - 1] = user_dimmer_pin;
dimZCPin[current_dim - 1] = zc_dimmer_pin;
dimCounter[current_dim - 1] = 0;
zeroCross[current_dim - 1] = 0;
dimMode[current_dim - 1] = NORMAL_MODE;
togMin[current_dim - 1] = 0;
togMax[current_dim - 1] = 1;
// Return the pointer
return dimmer[current_dim - 1];
}
#define TIMER_DIVIDER 80 // Hardware timer clock divider
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
void config_timer(int ACfreq)
{
ESP_LOGI(TAG, "Timer configuration - start");
/*System timer startup has been done*/
if (_initDone)
{
ESP_LOGW(TAG, "Timer configuration - timer already configured");
return;
}
memset(&m_timer_config, 0, sizeof(m_timer_config));
/* Prepare configuration */
timer_config_t m_timer_config =
{
.alarm_en = TIMER_ALARM_DIS,
.counter_en = TIMER_PAUSE,
.counter_dir = TIMER_COUNT_UP,
.auto_reload = TIMER_AUTORELOAD_EN,
.divider = TIMER_DIVIDER,
};
/*self regulation 50/60 Hz*/
double m_calculated_interval = (1 / (double)(ACfreq * 2)) / 100;
ESP_LOGI(TAG, "Interval between wave calculated for frequency : %3dHz = %5f", ACfreq, m_calculated_interval);
ESP_LOGI(TAG, "Timer configuration - configure interrupt and timer");
/* Configure the alarm value and the interrupt on alarm. */
timer_init(TIMER_GROUP_0, TIMER_0, &m_timer_config);
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_SCALE * m_calculated_interval);
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
timer_isr_register(TIMER_GROUP_0, TIMER_0, onTimerISR, (void *)TIMER_0, ESP_INTR_FLAG_IRAM, NULL);
/* start timer */
ESP_LOGI(TAG, "Timer configuration - start timer");
timer_start(TIMER_GROUP_0, TIMER_0);
timer_set_alarm(TIMER_GROUP_0, TIMER_0, TIMER_ALARM_EN);
ESP_LOGI(TAG, "Timer configuration - completed");
}
/*Zero-crossing pin setting
*set as input
*set as pullup
*set its interrupt*/
void ext_int_init(dimmertyp *ptr)
{
ESP_LOGI(TAG, "Setting ZCPin : %3d as input", dimZCPin[ptr->current_num]);
ESP_LOGI(TAG, "Checking for previous declaration of zc input on the same gpio");
/*Zero crossing*/
bool alreadyInit = false;
for (int i = 0; i < ptr->current_num; i++)
{
if (dimZCPin[i] == dimZCPin[ptr->current_num])
{
alreadyInit = true;
}
}
ESP_LOGI(TAG, "Already init = %3d", alreadyInit);
if (!alreadyInit)
{
gpio_set_direction(dimZCPin[ptr->current_num], GPIO_MODE_INPUT);
gpio_set_intr_type(dimZCPin[ptr->current_num], GPIO_INTR_NEGEDGE);
gpio_intr_enable(dimZCPin[ptr->current_num]);
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
gpio_isr_handler_add(dimZCPin[ptr->current_num], isr_ext, (void *)dimZCPin[ptr->current_num]);
}
ESP_LOGI(TAG, "Zero Cross interrupt configuration - completed");
/*TRIAC command - configuration*/
ESP_LOGI(TAG, "Triac command configuration");
gpio_set_direction(dimOutPin[ptr->current_num], GPIO_MODE_OUTPUT);
ESP_LOGI(TAG, "Triac command configuration - completed");
}
/*ISR debug region*/
#if DEBUG_ISR_DIMMER == ISR_DEBUG_ON
static xQueueHandle gpio_zero_cross_evt_queue = NULL;
static void gpio_isr_zerocross_debug(void *arg)
{
uint32_t io_num;
for (;;)
{
if (xQueueReceive(gpio_zero_cross_evt_queue, &io_num, portMAX_DELAY))
{
ESP_LOGI(TAG, "Zero-cross trigger fired");
}
}
}
#endif
/*ISR timer debug region*/
#if DEBUG_ISR_TIMER == ISR_DEBUG_ON
static xQueueHandle timer_event_queue = NULL;
static void timer_isr_debug(void *arg)
{
uint32_t io_num;
for (;;)
{
if (xQueueReceive(timer_event_queue, &io_num, portMAX_DELAY))
{
printf("Timer interrupt event , counter = %5d \n", io_num);
}
}
}
#endif
void begin(dimmertyp *ptr, DIMMER_MODE_typedef DIMMER_MODE, ON_OFF_typedef ON_OFF, int FREQ)
{
ESP_LOGI(TAG, "Dimmer - begin");
dimMode[ptr->current_num] = DIMMER_MODE;
dimState[ptr->current_num] = ON_OFF;
#if DEBUG_ISR_DIMMER == ISR_DEBUG_ON
if (!_initDone)
{
// create a queue to handle gpio event from isr
gpio_zero_cross_evt_queue = xQueueCreate(10, sizeof(uint32_t));
// start gpio task
xTaskCreate(gpio_isr_zerocross_debug, "gpio_isr_debug", 2048, NULL, 10, NULL);
}
#endif
#if DEBUG_ISR_TIMER == ISR_DEBUG_ON
if (!_initDone)
{
// create a queue to handle timer event
timer_event_queue = xQueueCreate(10, sizeof(uint32_t));
// start gpio task
xTaskCreate(timer_isr_debug, "timer_isr_debug", 2048, NULL, 10, NULL);
}
#endif
config_timer(FREQ);
ext_int_init(ptr);
// init completed
_initDone = true;
ESP_LOGI(TAG, "Dimmer begin - completed");
}
void setPower(dimmertyp *ptr, int power)
{
if (power >= 99)
{
power = 99;
}
dimPower[ptr->current_num] = power;
dimPulseBegin[ptr->current_num] = powerBuf[power];
vTaskDelay(1);
}
int getPower(dimmertyp *ptr)
{
if (dimState[ptr->current_num] == ON)
return dimPower[ptr->current_num];
else
return 0;
}
void setState(dimmertyp *ptr, ON_OFF_typedef ON_OFF)
{
dimState[ptr->current_num] = ON_OFF;
}
bool getState(dimmertyp *ptr)
{
bool ret;
if (dimState[ptr->current_num] == ON)
ret = true;
else
ret = false;
return ret;
}
void changeState(dimmertyp *ptr)
{
if (dimState[ptr->current_num] == ON)
dimState[ptr->current_num] = OFF;
else
dimState[ptr->current_num] = ON;
}
DIMMER_MODE_typedef getMode(dimmertyp *ptr)
{
return dimMode[ptr->current_num];
}
void setMode(dimmertyp *ptr, DIMMER_MODE_typedef DIMMER_MODE)
{
dimMode[ptr->current_num] = DIMMER_MODE;
}
void toggleSettings(dimmertyp *ptr, int minValue, int maxValue)
{
if (maxValue > 99)
{
maxValue = 99;
}
if (minValue < 1)
{
minValue = 1;
}
dimMode[ptr->current_num] = TOGGLE_MODE;
togMin[ptr->current_num] = powerBuf[maxValue];
togMax[ptr->current_num] = powerBuf[minValue];
toggleReload = 50;
}
static void IRAM_ATTR isr_ext(void *arg)
{
#if DEBUG_ISR_DIMMER == ISR_DEBUG_ON
uint32_t gpio_num = (uint32_t)arg;
xQueueSendFromISR(gpio_zero_cross_evt_queue, &gpio_num, NULL);
#endif
for (int i = 0; i < current_dim; i++)
if (dimState[i] == ON)
{
zeroCross[i] = 1;
}
}
static int k;
#if DEBUG_ISR_TIMER == ISR_DEBUG_ON
static int counter = 0;
#endif
/* Execution on timer event */
static void IRAM_ATTR onTimerISR(void *para)
{
/*Block needed to handle timer ISR*/
timer_spinlock_take(TIMER_GROUP_0);
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
/*Give back spinlock at the end of the method*/
/**********************************/
#if DEBUG_ISR_TIMER == ISR_DEBUG_ON
counter++;
uint32_t info = (uint32_t)counter;
xQueueSendFromISR(timer_event_queue, &info, NULL);
#endif
toggleCounter++;
for (k = 0; k < current_dim; k++)
{
if (zeroCross[k] == 1)
{
dimCounter[k]++;
if (dimMode[k] == TOGGLE_MODE)
{
/*****
* TOGGLE DIMMING MODE
*****/
if (dimPulseBegin[k] >= togMax[k])
{
// if reach max dimming value
togDir[k] = false; // downcount
}
if (dimPulseBegin[k] <= togMin[k])
{
// if reach min dimming value
togDir[k] = true; // upcount
}
if (toggleCounter == toggleReload)
{
if (togDir[k] == true)
dimPulseBegin[k]++;
else
dimPulseBegin[k]--;
}
}
/*****
* DEFAULT DIMMING MODE (NOT TOGGLE)
*****/
if (dimCounter[k] >= dimPulseBegin[k])
{
gpio_set_level(dimOutPin[k], 1);
}
if (dimCounter[k] >= (dimPulseBegin[k] + pulseWidth))
{
gpio_set_level(dimOutPin[k], 0);
zeroCross[k] = 0;
dimCounter[k] = 0;
}
}
}
if (toggleCounter >= toggleReload)
toggleCounter = 1;
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
timer_spinlock_give(TIMER_GROUP_0);
}

87
src/lib/esp32idfDimmer.h Normal file
View File

@@ -0,0 +1,87 @@
#ifndef RBDDIMMER_H
#define RBDDIMMER_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#include "freertos/task.h"
#include "math.h"
#include "esp_log.h"
#define ALL_DIMMERS 50
/*ISR debug defines*/
#define ISR_DEBUG_ON 1
#define ISR_DEBUG_OFF 0
/*Activate/Deactivate isr debug*/
#define DEBUG_ISR_DIMMER ISR_DEBUG_OFF
/*If timer is too fast can lead to core 0 panic*/
#define DEBUG_ISR_TIMER ISR_DEBUG_OFF
static const uint8_t powerBuf[] = {
100, 99, 98, 97, 96, 95, 94, 93, 92, 91,
90, 89, 88, 87, 86, 85, 84, 83, 82, 81,
80, 79, 78, 77, 76, 75, 74, 73, 72, 71,
70, 69, 68, 67, 66, 65, 64, 63, 62, 61,
60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
50, 49, 48, 47, 46, 45, 44, 43, 42, 41,
40, 39, 38, 37, 36, 35, 34, 33, 32, 31,
30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
#define ESP_INTR_FLAG_DEFAULT 0
typedef enum
{
NORMAL_MODE = 0,
TOGGLE_MODE = 1
} DIMMER_MODE_typedef;
typedef enum
{
OFF = false,
ON = true
} ON_OFF_typedef;
typedef struct dimmer
{
int current_num;
int timer_num;
bool toggle_state;
int tog_current;
int steps;
uint16_t pulse_begin;
int dimmer_pin;
int tog_max;
int tog_min;
int zc_pin;
} dimmertyp;
dimmertyp *createDimmer(gpio_num_t user_dimmer_pin, gpio_num_t zc_dimmer_pin);
void begin(dimmertyp *ptr, DIMMER_MODE_typedef DIMMER_MODE, ON_OFF_typedef ON_OFF, int FREQ);
void setPower(dimmertyp *ptr, int power);
int getPower(dimmertyp *ptr);
void setState(dimmertyp *ptr, ON_OFF_typedef ON_OFF);
bool getState(dimmertyp *ptr);
void changeState(dimmertyp *ptr);
void setMode(dimmertyp *ptr, DIMMER_MODE_typedef DIMMER_MODE);
DIMMER_MODE_typedef getMode(dimmertyp *ptr);
void toggleSettings(dimmertyp *ptr, int minValue, int maxValue);
void port_init(dimmertyp *ptr);
void config_timer(int freq);
void ext_int_init(dimmertyp *ptr);
static void IRAM_ATTR isr_ext(void* arg);
static void IRAM_ATTR onTimerISR(void* arg);
#endif