Outsource display, encoder cfg to config.cpp, Optimize speedsensor

- outsource configuration of display and encoder from source/header file
  to config.cpp and pass it to init function or task from main()

- optimize logging in several init functions

- speedsensor:
    - fix startup error: initialize ISR only once
    - create instances at initialization instead of first method call

- ssd1306 display library:
    - modify library to pass offsetX to init function instead of using macro
This commit is contained in:
jonny_jr9 2024-02-20 12:24:41 +01:00
parent b7288b442e
commit 021a3660e1
12 changed files with 112 additions and 76 deletions

View File

@ -1,17 +1,22 @@
// NOTE: this file is included in main.cpp only.
// outsourced all configuration related functions and structures to this file:
extern "C"
{
#include "esp_log.h"
}
#include "motordrivers.hpp"
#include "motorctl.hpp"
#include "joystick.hpp"
#include "http.hpp"
#include "speedsensor.hpp"
#include "buzzer.hpp"
#include "control.hpp"
#include "fan.hpp"
#include "auto.hpp"
#include "chairAdjust.hpp"
#include "display.hpp"
#include "encoder.h"
//==================================
//======== define loglevels ========
@ -181,3 +186,36 @@ speedSensor_config_t speedRight_config{
.directionInverted = true,
.logName = "speedRight",
};
//-------------------------
//-------- display --------
//-------------------------
display_config_t display_config {
.gpio_scl = GPIO_NUM_22,
.gpio_sda = GPIO_NUM_23,
.gpio_reset = GPIO_NUM_15,
.width = 128,
.height = 64,
.offsetX = 2,
.flip = false,
.contrast = 0xff, //max: 255
};
//-------------------------
//-------- encoder --------
//-------------------------
//configure rotary encoder (next to joystick)
rotary_encoder_t encoder_config = {
.pin_a = GPIO_NUM_25,
.pin_b = GPIO_NUM_26,
.pin_btn = GPIO_NUM_27,
.code = 1,
.store = 0, //encoder count
.index = 0,
.btn_pressed_time_us = 20000,
.btn_state = RE_BTN_RELEASED //default state
};

View File

@ -8,15 +8,6 @@ extern "C"{
//==== display config ====
#define I2C_INTERFACE y
#define SCL_GPIO 22
#define SDA_GPIO 23
#define RESET_GPIO 15 // FIXME remove this
// the following options are set in menuconfig: (see sdkconfig)
// #define CONFIG_OFFSETX 2 //note: the larger display (actual 130x64) needs 2 pixel offset (prevents bugged column)
// #define CONFIG_I2C_PORT_0 y
//=== content config ===
#define STARTUP_MSG_TIMEOUT 2000
#define ADC_BATT_VOLTAGE ADC1_CHANNEL_6
@ -55,22 +46,21 @@ static const char * TAG = "display";
//==== display_init ====
//======================
//note CONFIG_OFFSETX is used (from menuconfig)
void display_init(){
void display_init(display_config_t config){
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //max voltage
ESP_LOGW("display", "INTERFACE is i2c");
ESP_LOGW("display", "SDA_GPIO=%d",SDA_GPIO);
ESP_LOGW("display", "SCL_GPIO=%d",SCL_GPIO);
ESP_LOGW("display", "RESET_GPIO=%d",RESET_GPIO);
i2c_master_init(&dev, SDA_GPIO, SCL_GPIO, RESET_GPIO);
#if FLIP
ESP_LOGW(TAG, "Initializing Display...");
ESP_LOGI(TAG, "config: sda=%d, sdl=%d, reset=%d, offset=%d, flip=%d, size: %dx%d",
config.gpio_sda, config.gpio_scl, config.gpio_reset, config.offsetX, config.flip, config.width, config.height);
i2c_master_init(&dev, config.gpio_sda, config.gpio_scl, config.gpio_reset);
if (config.flip) {
dev._flip = true;
ESP_LOGW("display", "Flip upside down");
#endif
ESP_LOGI("display", "Panel is 128x64");
ssd1306_init(&dev, 128, 64);
ESP_LOGW(TAG, "Flip upside down");
}
ssd1306_init(&dev, config.width, config.height, config.offsetX);
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_contrast(&dev, config.contrast);
}
@ -264,11 +254,12 @@ void showStartupMsg(){
void display_task(void *pvParameters)
{
ESP_LOGW(TAG, "Initializing display and starting handle loop");
//get struct with pointers to all needed global objects from task parameter
display_task_parameters_t *objects = (display_task_parameters_t *)pvParameters;
// initialize display
display_init();
display_init(objects->displayConfig);
// TODO check if successfully initialized
// show startup message

View File

@ -18,8 +18,22 @@ extern "C" {
#include "control.hpp"
#include "speedsensor.hpp"
// configuration for initializing display (passed to task as well)
typedef struct display_config_t {
gpio_num_t gpio_scl;
gpio_num_t gpio_sda;
gpio_num_t gpio_reset;
int width;
int height;
int offsetX;
bool flip;
int contrast;
} display_config_t;
// struct with variables passed to task from main()
typedef struct display_task_parameters_t {
display_config_t displayConfig;
controlledArmchair * control;
evaluatedJoystick * joystick;
QueueHandle_t encoderQueue;

View File

@ -17,22 +17,6 @@ extern "C"
//------- variables -------
//-------------------------
static const char * TAG = "encoder";
uint16_t encoderCount;
rotary_encoder_btn_state_t encoderButtonState = {};
//global event queue:
QueueHandle_t encoderQueue = NULL;
//encoder config
rotary_encoder_t encoderConfig = {
.pin_a = PIN_A,
.pin_b = PIN_B,
.pin_btn = PIN_BUTTON,
.code = 1,
.store = encoderCount,
.index = 0,
.btn_pressed_time_us = 20000,
.btn_state = encoderButtonState
};
@ -40,11 +24,11 @@ rotary_encoder_t encoderConfig = {
//========== encoder_init ==========
//==================================
//initialize encoder //TODO pass config to this function
QueueHandle_t encoder_init()
QueueHandle_t encoder_init(rotary_encoder_t * encoderConfig)
{
QueueHandle_t encoderQueue = xQueueCreate(QUEUE_SIZE, sizeof(rotary_encoder_event_t));
rotary_encoder_init(encoderQueue);
rotary_encoder_add(&encoderConfig);
rotary_encoder_add(encoderConfig);
if (encoderQueue == NULL)
ESP_LOGE(TAG, "Error initializing encoder or queue");
else

View File

@ -6,12 +6,9 @@ extern "C" {
//config
#define QUEUE_SIZE 10
#define PIN_A GPIO_NUM_25
#define PIN_B GPIO_NUM_26
#define PIN_BUTTON GPIO_NUM_27
//init encoder with config in encoder.cpp
QueueHandle_t encoder_init(); //TODO pass config to function
//init encoder with pointer to encoder config
QueueHandle_t encoder_init(rotary_encoder_t * encoderConfig);
//task that handles encoder events

View File

@ -99,7 +99,7 @@ static const char * TAG = "main";
//=================================
//initialize spi flash filesystem (used for webserver)
void init_spiffs(){
ESP_LOGI(TAG, "init spiffs");
ESP_LOGW(TAG, "initializing spiffs...");
esp_vfs_spiffs_conf_t esp_vfs_spiffs_conf = {
.base_path = "/spiffs",
.partition_label = NULL,
@ -174,6 +174,7 @@ void createObjects()
//=========== app_main ============
//=================================
extern "C" void app_main(void) {
ESP_LOGW(TAG, "===== BOOT (pre main) Completed =====\n");
ESP_LOGW(TAG, "===== INITIALIZING COMPONENTS =====");
//--- define log levels ---
@ -186,19 +187,22 @@ extern "C" void app_main(void) {
gpio_set_level(GPIO_NUM_17, 1);
//--- initialize nvs-flash and netif (needed for wifi) ---
ESP_LOGW(TAG,"initializing wifi...");
wifi_initNvs_initNetif();
//--- initialize spiffs ---
init_spiffs();
//--- initialize and start wifi ---
ESP_LOGD(TAG,"starting wifi...");
ESP_LOGW(TAG,"starting wifi...");
//wifi_init_client(); //connect to existing wifi
wifi_init_ap(); //start access point
ESP_LOGD(TAG,"done starting wifi");
//--- initialize encoder ---
const QueueHandle_t encoderQueue = encoder_init();
const QueueHandle_t encoderQueue = encoder_init(&encoder_config);
printf("\n");
@ -206,12 +210,14 @@ extern "C" void app_main(void) {
ESP_LOGW(TAG, "===== CREATING SHARED OBJECTS =====");
//initialize sabertooth object in STACK (due to performance issues in heap)
sabertoothDriver = static_cast<sabertooth2x60a*>(alloca(sizeof(sabertooth2x60a)));
new (sabertoothDriver) sabertooth2x60a(sabertoothConfig);
///sabertoothDriver = static_cast<sabertooth2x60a*>(alloca(sizeof(sabertooth2x60a)));
///new (sabertoothDriver) sabertooth2x60a(sabertoothConfig);
//create all class instances used below in HEAP
createObjects();
printf("\n");
//--- create tasks ---
@ -256,13 +262,16 @@ extern "C" void app_main(void) {
//----- create task for display -----
//-----------------------------------
////task that handles the display (show stats, handle menu in 'MENU' mode)
display_task_parameters_t display_param = {control, joystick, encoderQueue, motorLeft, motorRight, speedLeft, speedRight, buzzer};
display_task_parameters_t display_param = {display_config, control, joystick, encoderQueue, motorLeft, motorRight, speedLeft, speedRight, buzzer};
xTaskCreate(&display_task, "display_task", 3*2048, &display_param, 3, NULL);
vTaskDelay(200 / portTICK_PERIOD_MS); //wait for all tasks to finish initializing
printf("\n");
//--- startup finished ---
ESP_LOGW(TAG, "===== STARTUP FINISHED =====");
ESP_LOGW(TAG, "===== STARTUP FINISHED =====\n");
buzzer->beep(3, 70, 50);
//--- testing encoder ---

View File

@ -7,6 +7,9 @@
static const char* TAG = "speedSensor";
//initialize ISR only once (for multiple instances)
bool speedSensor::isrIsInitialized = false;
uint32_t min(uint32_t a, uint32_t b){
if (a>b) return b;
@ -84,11 +87,8 @@ void IRAM_ATTR onEncoderChange(void* arg) {
speedSensor::speedSensor(speedSensor_config_t config_f){
//copy config
config = config_f;
//note: currently gets initialized at first method call
//this prevents crash due to too early initialization at boot
//TODO: create global objects later after boot
//init gpio and ISR
//init();
init();
}
@ -102,15 +102,16 @@ void speedSensor::init() {
gpio_pad_select_gpio(config.gpioPin);
gpio_set_direction(config.gpioPin, GPIO_MODE_INPUT);
gpio_set_pull_mode(config.gpioPin, GPIO_PULLUP_ONLY);
ESP_LOGW(TAG, "%s, configured gpio-pin %d", config.logName, (int)config.gpioPin);
//configure interrupt
gpio_set_intr_type(config.gpioPin, GPIO_INTR_ANYEDGE);
if (!isrIsInitialized) {
gpio_install_isr_service(0);
isrIsInitialized = true;
ESP_LOGW(TAG, "Initialized ISR service");
}
gpio_isr_handler_add(config.gpioPin, onEncoderChange, this);
ESP_LOGW(TAG, "%s, configured interrupt", config.logName);
isInitialized = true;
ESP_LOGW(TAG, "[%s], configured gpio-pin %d and interrupt routine", config.logName, (int)config.gpioPin);
}
@ -121,8 +122,6 @@ void speedSensor::init() {
//==========================
//get rotational speed in revolutions per minute
float speedSensor::getRpm(){
//check if initialized
if (!isInitialized) init();
uint32_t timeElapsed = esp_timer_get_time() - lastEdgeTime;
//timeout (standstill)
//TODO variable timeout considering config.degreePerGroup

View File

@ -24,7 +24,7 @@ class speedSensor {
public:
//constructor
speedSensor(speedSensor_config_t config);
//initializes gpio pin and configures interrupt
// initializes gpio pin, configures and starts interrupt
void init();
//negative values = reverse direction
@ -35,8 +35,7 @@ public:
//1=forward, -1=reverse
int direction;
//variables for handling the encoder
//variables for handling the encoder (public because ISR needs access)
speedSensor_config_t config;
int prevState = 0;
uint64_t pulseDurations[3] = {};
@ -44,10 +43,9 @@ public:
uint8_t pulseCounter = 0;
int debugCount = 0;
double currentRpm = 0;
bool isInitialized = false;
private:
static bool isrIsInitialized; // default false due to static
};

View File

@ -17,8 +17,10 @@ typedef union out_column_t {
uint8_t u8[4];
} PACK8 out_column_t;
void ssd1306_init(SSD1306_t * dev, int width, int height)
//void ssd1306_init(SSD1306_t * dev, int width, int height, int offsetX) //original
void ssd1306_init(SSD1306_t * dev, int width, int height, int offsetX)
{
dev->_offsetX = offsetX;
if (dev->_address == SPIAddress) {
spi_init(dev, width, height);
} else {

View File

@ -98,6 +98,7 @@ typedef struct {
int _scDirection;
PAGE_t _page[8];
bool _flip;
int _offsetX; //added offset here instead of using macro variable
} SSD1306_t;
#ifdef __cplusplus
@ -105,7 +106,7 @@ extern "C"
{
#endif
void ssd1306_init(SSD1306_t * dev, int width, int height);
void ssd1306_init(SSD1306_t * dev, int width, int height, int offsetX);
int ssd1306_get_width(SSD1306_t * dev);
int ssd1306_get_height(SSD1306_t * dev);
int ssd1306_get_pages(SSD1306_t * dev);
@ -128,6 +129,7 @@ void _ssd1306_pixel(SSD1306_t * dev, int xpos, int ypos, bool invert);
void _ssd1306_line(SSD1306_t * dev, int x1, int y1, int x2, int y2, bool invert);
void ssd1306_invert(uint8_t *buf, size_t blen);
void ssd1306_flip(uint8_t *buf, size_t blen);
void ssd1306_setOffset(SSD1306_t * dev, int offset);
uint8_t ssd1306_copy_bit(uint8_t src, int srcBits, uint8_t dst, int dstBits);
uint8_t ssd1306_rotate_byte(uint8_t ch1);
void ssd1306_fadeout(SSD1306_t * dev);

View File

@ -112,7 +112,8 @@ void i2c_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int
if (page >= dev->_pages) return;
if (seg >= dev->_width) return;
int _seg = seg + CONFIG_OFFSETX;
//int _seg = seg + CONFIG_OFFSETX; //original
int _seg = seg + dev->_offsetX;
uint8_t columLow = _seg & 0x0F;
uint8_t columHigh = (_seg >> 4) & 0x0F;

View File

@ -158,7 +158,8 @@ void spi_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int
if (page >= dev->_pages) return;
if (seg >= dev->_width) return;
int _seg = seg + CONFIG_OFFSETX;
//int _seg = seg + CONFIG_OFFSETX; //original
int _seg = seg + dev->_offsetX;
uint8_t columLow = _seg & 0x0F;
uint8_t columHigh = (_seg >> 4) & 0x0F;