diff --git a/board_single/main/config.cpp b/board_single/main/config.cpp index a230afe..d35a2e1 100644 --- a/board_single/main/config.cpp +++ b/board_single/main/config.cpp @@ -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 +}; \ No newline at end of file diff --git a/board_single/main/display.cpp b/board_single/main/display.cpp index 79450ec..3c6f710 100644 --- a/board_single/main/display.cpp +++ b/board_single/main/display.cpp @@ -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 - dev._flip = true; - ESP_LOGW("display", "Flip upside down"); -#endif - ESP_LOGI("display", "Panel is 128x64"); - ssd1306_init(&dev, 128, 64); + 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(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 diff --git a/board_single/main/display.hpp b/board_single/main/display.hpp index 9c16983..fffe95c 100644 --- a/board_single/main/display.hpp +++ b/board_single/main/display.hpp @@ -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; diff --git a/board_single/main/encoder.cpp b/board_single/main/encoder.cpp index 8f073ae..2912a7c 100644 --- a/board_single/main/encoder.cpp +++ b/board_single/main/encoder.cpp @@ -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 diff --git a/board_single/main/encoder.hpp b/board_single/main/encoder.hpp index 21a60e9..79c9198 100644 --- a/board_single/main/encoder.hpp +++ b/board_single/main/encoder.hpp @@ -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 diff --git a/board_single/main/main.cpp b/board_single/main/main.cpp index 0043b7d..033e18a 100644 --- a/board_single/main/main.cpp +++ b/board_single/main/main.cpp @@ -69,7 +69,7 @@ cControlledRest *backRest; //-> makes it possible to easily use different motor drivers motorSetCommandFunc_t setLeftFunc = [&sabertoothDriver](motorCommand_t cmd) { - sabertoothDriver->setLeft(cmd); //<= note: still using pointer to method in here (but stored in STACK) + sabertoothDriver->setLeft(cmd); //<= note: still using pointer to method in here (but stored in STACK) }; motorSetCommandFunc_t setRightFunc = [&sabertoothDriver](motorCommand_t cmd) { @@ -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(alloca(sizeof(sabertooth2x60a))); - new (sabertoothDriver) sabertooth2x60a(sabertoothConfig); + ///sabertoothDriver = static_cast(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 --- diff --git a/common/speedsensor.cpp b/common/speedsensor.cpp index 22c7f2e..643c128 100644 --- a/common/speedsensor.cpp +++ b/common/speedsensor.cpp @@ -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); - gpio_install_isr_service(0); + 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 diff --git a/common/speedsensor.hpp b/common/speedsensor.hpp index c6e93bf..a07359d 100644 --- a/common/speedsensor.hpp +++ b/common/speedsensor.hpp @@ -24,8 +24,8 @@ class speedSensor { public: //constructor speedSensor(speedSensor_config_t config); - //initializes gpio pin and configures interrupt - void init(); + // initializes gpio pin, configures and starts interrupt + void init(); //negative values = reverse direction //positive values = forward 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 }; diff --git a/components/ssd1306/ssd1306.c b/components/ssd1306/ssd1306.c index f5d97f3..5b2a28c 100644 --- a/components/ssd1306/ssd1306.c +++ b/components/ssd1306/ssd1306.c @@ -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 { diff --git a/components/ssd1306/ssd1306.h b/components/ssd1306/ssd1306.h index 120315d..893694b 100644 --- a/components/ssd1306/ssd1306.h +++ b/components/ssd1306/ssd1306.h @@ -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); diff --git a/components/ssd1306/ssd1306_i2c.c b/components/ssd1306/ssd1306_i2c.c index fe2d821..cb092f3 100644 --- a/components/ssd1306/ssd1306_i2c.c +++ b/components/ssd1306/ssd1306_i2c.c @@ -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; diff --git a/components/ssd1306/ssd1306_spi.c b/components/ssd1306/ssd1306_spi.c index fce2b7f..e6cc5ee 100644 --- a/components/ssd1306/ssd1306_spi.c +++ b/components/ssd1306/ssd1306_spi.c @@ -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;