Conflicts:
	components/config/config.c
	components/display/driver_SSD1306.c
This commit is contained in:
Sebastien
2020-01-15 12:29:27 -05:00
12 changed files with 195 additions and 68 deletions

View File

@@ -70,7 +70,7 @@ void config_set_entry_changed_flag(cJSON * entry, cJSON_bool flag);
void * pval = config_alloc_get(nt, key);\ void * pval = config_alloc_get(nt, key);\
if(pval!=NULL){ *value = *(t * )pval; free(pval); return ESP_OK; }\ if(pval!=NULL){ *value = *(t * )pval; free(pval); return ESP_OK; }\
return ESP_FAIL;} return ESP_FAIL;}
#ifdef RECOVERY_APPLICATION #if RECOVERY_APPLICATION==0
static void * malloc_fn(size_t sz){ static void * malloc_fn(size_t sz){
void * ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM); void * ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM);
@@ -81,7 +81,7 @@ static void * malloc_fn(size_t sz){
} }
static void * free_fn(void * ptr){ static void * free_fn(void * ptr){
if(ptr!=NULL){ if(ptr!=NULL){
free(ptr); heap_caps_free(ptr);
} }
else { else {
ESP_LOGW(TAG,"free_fn: Cannot free null pointer!"); ESP_LOGW(TAG,"free_fn: Cannot free null pointer!");
@@ -92,7 +92,7 @@ static void * free_fn(void * ptr){
void init_cJSON(){ void init_cJSON(){
// initialize cJSON hooks it uses SPIRAM memory // initialize cJSON hooks it uses SPIRAM memory
// as opposed to IRAM // as opposed to IRAM
#ifndef RECOVERY_APPLICATION #if RECOVERY_APPLICATION==0
static cJSON_Hooks hooks; static cJSON_Hooks hooks;
// In squeezelite mode, allocate memory from PSRAM. Otherwise allocate from internal RAM // In squeezelite mode, allocate memory from PSRAM. Otherwise allocate from internal RAM
// as recovery will lock flash access when erasing FLASH or writing to OTA partition. // as recovery will lock flash access when erasing FLASH or writing to OTA partition.
@@ -229,6 +229,8 @@ cJSON * config_set_value_safe(nvs_type_t nvs_type, const char *key, void * value
} }
else { else {
ESP_LOGD(TAG, "Config not changed. "); ESP_LOGD(TAG, "Config not changed. ");
cJSON_Delete(entry);
entry = existing;
} }
} }
else { else {
@@ -698,7 +700,6 @@ esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value){
else { else {
ESP_LOGV(TAG,"config_set_value completed"); ESP_LOGV(TAG,"config_set_value completed");
} }
} }
config_unlock(); config_unlock();
return result; return result;

View File

@@ -23,13 +23,13 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include "esp_log.h" #include "esp_log.h"
#include "display.h" #include "display.h"
#include "globdefs.h"
#include "ssd1306.h" #include "ssd1306.h"
#include "ssd1306_draw.h" #include "ssd1306_draw.h"
#include "ssd1306_font.h" #include "ssd1306_font.h"
#include "ssd1306_default_if.h" #include "ssd1306_default_if.h"
#define I2C_PORT 1
#define I2C_ADDRESS 0x3C #define I2C_ADDRESS 0x3C
#define LINELEN 40 #define LINELEN 40
static const char *TAG = "display"; static const char *TAG = "display";
@@ -77,40 +77,26 @@ static bool display_init(char *config, char *welcome) {
bool res = false; bool res = false;
if (strstr(config, "I2C")) { if (strstr(config, "I2C")) {
int scl = -1, sda = -1;
int width = -1, height = -1, address=I2C_ADDRESS; int width = -1, height = -1, address=I2C_ADDRESS;
char *p; char *p;
ESP_LOGI(TAG, "Initializing I2C display with config: %s",config); ESP_LOGI(TAG, "Initializing I2C display with config: %s",config);
// no time for smart parsing - this is for tinkerers // no time for smart parsing - this is for tinkerers
if ((p = strcasestr(config, "scl")) != NULL) scl = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "sda")) != NULL) sda = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1);
if (sda != -1 && scl != -1 && width != -1 && height != -1) {
res = SSD1306_I2CMasterInitDefault( I2C_PORT, sda, scl ); if (width != -1 && height != -1) {
if(!res){ SSD1306_I2CMasterInitDefault( i2c_system_port, -1, -1 ) ;
ESP_LOGE(TAG,"I2C Master Init failed"); SSD1306_I2CMasterAttachDisplayDefault( &I2CDisplay, width, height, address, -1 );
} SSD1306_SetHFlip( &I2CDisplay, strcasestr(config, "HFlip") ? true : false);
} SSD1306_SetVFlip( &I2CDisplay, strcasestr(config, "VFlip") ? true : false);
if(res){ SSD1306_SetFont( &I2CDisplay, &Font_droid_sans_fallback_15x17 );
res = SSD1306_I2CMasterAttachDisplayDefault( &I2CDisplay, width, height, address, -1);
if(!res){
ESP_LOGE(TAG,"Attach Display default failed");
}
}
if(res){
res = SSD1306_SetFont( &I2CDisplay, &Font_droid_sans_fallback_15x17 );
if(!res){
ESP_LOGE(TAG,"Set Font failed");
}
}
if(res){
print_message(welcome); print_message(welcome);
ESP_LOGI(TAG, "Initialized I2C display %dx%d (sda:%d, scl:%d, address:%02x)", width, height, sda, scl, address); ESP_LOGI(TAG, "Initialized I2C display %dx%d", width, height);
res = true;
} else { } else {
ESP_LOGE(TAG, "Cannot initialized I2C display %s [%dx%d sda:%d, scl:%d, address:%02x]", config, width, height, sda, scl, address); ESP_LOGI(TAG, "Cannot initialized I2C display %s [%dx%d]", config, width, height);
} }
} else { } else {
ESP_LOGE(TAG, "Non-I2C display not supported. Display config %s", config); ESP_LOGE(TAG, "Non-I2C display not supported. Display config %s", config);

View File

@@ -32,21 +32,21 @@ static bool I2CDefaultReset( struct SSD1306_Device* Display );
* Returns true on successful init of the i2c bus. * Returns true on successful init of the i2c bus.
*/ */
bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) { bool SSD1306_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) {
i2c_config_t Config;
memset( &Config, 0, sizeof( i2c_config_t ) );
Config.mode = I2C_MODE_MASTER;
Config.sda_io_num = SDA;
Config.sda_pullup_en = GPIO_PULLUP_ENABLE;
Config.scl_io_num = SCL;
Config.scl_pullup_en = GPIO_PULLUP_ENABLE;
Config.master.clk_speed = I2CDisplaySpeed;
I2CPortNumber = PortNumber; I2CPortNumber = PortNumber;
ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false ); if (SDA != -1 && SCL != -1) {
ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false ); i2c_config_t Config = { 0 };
Config.mode = I2C_MODE_MASTER;
Config.sda_io_num = SDA;
Config.sda_pullup_en = GPIO_PULLUP_ENABLE;
Config.scl_io_num = SCL;
Config.scl_pullup_en = GPIO_PULLUP_ENABLE;
Config.master.clk_speed = I2CDisplaySpeed;
ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false );
ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false );
}
return true; return true;
} }

View File

@@ -41,7 +41,7 @@ static int n_buttons = 0;
#define DEBOUNCE 50 #define DEBOUNCE 50
static EXT_RAM_ATTR struct button_s { static EXT_RAM_ATTR struct button_s {
void *id; void *client;
int gpio; int gpio;
int debounce; int debounce;
button_handler handler; button_handler handler;
@@ -123,18 +123,18 @@ static void buttons_task(void* arg) {
if (event == BUTTON_RELEASED) { if (event == BUTTON_RELEASED) {
// early release of a long-press button, send press/release // early release of a long-press button, send press/release
if (!button.shifting) { if (!button.shifting) {
(*button.handler)(button.id, BUTTON_PRESSED, press, false); (*button.handler)(button.client, BUTTON_PRESSED, press, false);
(*button.handler)(button.id, BUTTON_RELEASED, press, false); (*button.handler)(button.client, BUTTON_RELEASED, press, false);
} }
// button is a copy, so need to go to real context // button is a copy, so need to go to real context
button.self->shifting = false; button.self->shifting = false;
} else if (!button.shifting) { } else if (!button.shifting) {
// normal long press and not shifting so don't discard // normal long press and not shifting so don't discard
(*button.handler)(button.id, BUTTON_PRESSED, press, true); (*button.handler)(button.client, BUTTON_PRESSED, press, true);
} }
} else { } else {
// normal press/release of a button or release of a long-press button // normal press/release of a button or release of a long-press button
if (!button.shifting) (*button.handler)(button.id, event, press, button.long_press); if (!button.shifting) (*button.handler)(button.client, event, press, button.long_press);
// button is a copy, so need to go to real context // button is a copy, so need to go to real context
button.self->shifting = false; button.self->shifting = false;
} }
@@ -151,7 +151,7 @@ void dummy_handler(void *id, button_event_e event, button_press_e press) {
/**************************************************************************************** /****************************************************************************************
* Create buttons * Create buttons
*/ */
void button_create(void *id, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio) { void button_create(void *client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio) {
static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4)));
static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__ ((aligned (4))); static EXT_RAM_ATTR StackType_t xStack[BUTTON_STACK_SIZE] __attribute__ ((aligned (4)));
@@ -168,7 +168,7 @@ void button_create(void *id, int gpio, int type, bool pull, int debounce, button
memset(buttons + n_buttons, 0, sizeof(struct button_s)); memset(buttons + n_buttons, 0, sizeof(struct button_s));
// set mandatory parameters // set mandatory parameters
buttons[n_buttons].id = id; buttons[n_buttons].client = client;
buttons[n_buttons].gpio = gpio; buttons[n_buttons].gpio = gpio;
buttons[n_buttons].debounce = debounce ? debounce: DEBOUNCE; buttons[n_buttons].debounce = debounce ? debounce: DEBOUNCE;
buttons[n_buttons].handler = handler; buttons[n_buttons].handler = handler;
@@ -214,3 +214,53 @@ void button_create(void *id, int gpio, int type, bool pull, int debounce, button
n_buttons++; n_buttons++;
} }
/****************************************************************************************
* Get stored id
*/
void button_get_client(int gpio) {
for (int i = 0; i < n_buttons; i++) {
if (buttons[i].gpio == gpio) return buttons[i].client;
}
return NULL;
}
/****************************************************************************************
* Update buttons
*/
void *button_remap(void *client, int gpio, button_handler handler, int long_press, int shifter_gpio) {
int i;
struct button_s *button = NULL;
void *prev_client;
ESP_LOGI(TAG, "remapping GPIO %u, long press %u shifter %u", gpio, long_press, shifter_gpio);
// find button
for (i = 0; i < n_buttons; i++) {
if (buttons[i].gpio == gpio) {
button = buttons + i;
break;
}
}
// huh
if (!button) return NULL;
prev_client = button->client;
button->client = client;
button->handler = handler;
button->long_press = long_press;
button->shifter_gpio = shifter_gpio;
// find our shifter (if any)
for (i = 0; shifter_gpio != -1 && i < n_buttons; i++) {
if (buttons[i].gpio == shifter_gpio) {
button->shifter = buttons + i;
// a shifter must have a long-press handler
if (!buttons[i].long_press) buttons[i].long_press = -1;
break;
}
}
return prev_client;
}

View File

@@ -33,4 +33,6 @@ set shifter_gpio to -1 for no shift
NOTE: shifter buttons *must* be created before shiftee NOTE: shifter buttons *must* be created before shiftee
*/ */
void button_create(void *id, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio); void button_create(void *client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio);
void *button_remap(void *client, int gpio, button_handler handler, int long_press, int shifter_gpio);
void button_get_client(int gpio);

View File

@@ -0,0 +1,34 @@
/*
* Squeezelite for esp32
*
* (c) Philippe G. 2019, philippe_44@outlook.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#define I2C_SYSTEM_PORT 1
extern int i2c_system_port;
#ifdef CONFIG_SQUEEZEAMP
#define JACK_GPIO 34
#define SPKFAULT_GPIO 2 // this requires a pull-up, so can't be >34
#define LED_GREEN_GPIO 12
#define LED_RED_GPIO 13
#else
#define LED_GREEN_GPIO CONFIG_LED_GREEN_GPIO
#define LED_RED_GPIO CONFIG_LED_RED_GPIO
#endif

View File

@@ -18,11 +18,7 @@
#include "driver/gpio.h" #include "driver/gpio.h"
#include "buttons.h" #include "buttons.h"
#include "led.h" #include "led.h"
#include "globdefs.h"
#ifdef CONFIG_SQUEEZEAMP
#define JACK_GPIO 34
#define SPKFAULT_GPIO 2 // this requires a pull-up, so can't be >34
#endif
#define MONITOR_TIMER (10*1000) #define MONITOR_TIMER (10*1000)

View File

@@ -9,33 +9,69 @@
#include <stdio.h> #include <stdio.h>
#include "esp_log.h" #include "esp_log.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include <driver/i2c.h>
#include "config.h"
#include "battery.h" #include "battery.h"
#include "led.h" #include "led.h"
#include "monitor.h" #include "monitor.h"
#include "globdefs.h"
extern void battery_svc_init(void); extern void battery_svc_init(void);
extern void monitor_svc_init(void); extern void monitor_svc_init(void);
extern void led_svc_init(void); extern void led_svc_init(void);
static const char TAG[] = "services"; int i2c_system_port = I2C_SYSTEM_PORT;
#ifdef CONFIG_SQUEEZEAMP static const char *TAG = "services";
#define LED_GREEN_GPIO 12
#define LED_RED_GPIO 13
#endif
/**************************************************************************************** /****************************************************************************************
* *
*/ */
void services_init(void) { void services_init(void) {
int scl = -1, sda = -1, i2c_speed = 250000;
char *nvs_item, *p;
gpio_install_isr_service(0); gpio_install_isr_service(0);
nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
if (nvs_item) {
if ((p = strcasestr(nvs_item, "scl")) != NULL) scl = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "sda")) != NULL) sda = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "speed")) != NULL) i2c_speed = atoi(strchr(p, '=') + 1);
if ((p = strcasestr(nvs_item, "port")) != NULL) i2c_system_port = atoi(strchr(p, '=') + 1);
free(nvs_item);
}
#ifdef CONFIG_SQUEEZEAMP
if (i2c_system_port == 0) {
i2c_system_port = 1;
ESP_LOGE(TAG, "can't use i2c port 0 on SqueezeAMP");
}
#endif
ESP_LOGI(TAG,"Configuring I2C sda:%d scl:%d port:%u speed:%u", sda, scl, i2c_system_port, i2c_speed);
if (sda != -1 && scl != -1) {
i2c_config_t i2c = { 0 };
i2c.mode = I2C_MODE_MASTER;
i2c.sda_io_num = sda;
i2c.sda_pullup_en = GPIO_PULLUP_ENABLE;
i2c.scl_io_num = scl;
i2c.scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c.master.clk_speed = i2c_speed;
i2c_param_config(i2c_system_port, &i2c);
i2c_driver_install(i2c_system_port, i2c.mode, 0, 0, 0 );
} else {
ESP_LOGE(TAG, "can't initialize I2C");
}
ESP_LOGD(TAG,"Configuring LEDs"); ESP_LOGD(TAG,"Configuring LEDs");
led_svc_init(); led_svc_init();
#ifdef CONFIG_SQUEEZEAMP
led_config(LED_GREEN, LED_GREEN_GPIO, 0); led_config(LED_GREEN, LED_GREEN_GPIO, 0);
led_config(LED_RED, LED_RED_GPIO, 0); led_config(LED_RED, LED_RED_GPIO, 0);
#endif
battery_svc_init(); battery_svc_init();
monitor_svc_init(); monitor_svc_init();

View File

@@ -192,12 +192,31 @@ menu "Squeezelite-ESP32"
string "Screen configuraton" string "Screen configuraton"
default "" default ""
help help
Set parameters of display screen, leave empty for no screen Set parameters for display screen, leave empty for no screen
I2C,width=<size>,height=<size>,sda=<gpio>,scl=<gpio> I2C,width=<size>,height=<size>
SPI,width=<size>,height=<size>,data=<gpio>,clock=<gpio>,select=<gpio> SPI,width=<size>,height=<size>,select=<gpio>
config DISPLAY_I2C_SPEED config DISPLAY_I2C_SPEED
int "I2C bus speed" int "I2C bus speed"
default 250000 default 250000
endmenu endmenu
menu "Various I/O"
config I2C_CONFIG
string "I2C system configuration"
default ""
help
Set parameters of shared I2C interface
sda=<gpio>,scl=<gpio>,speed=<num>,port=<0|1>
config LED_GREEN_GPIO
int "Green led GPIO"
default -1
help
Set to -1 for no LED
config LED_RED_GPIO
int "Red led GPIO"
default -1
help
Set to -1 for no LED
endmenu
endmenu endmenu

View File

@@ -312,6 +312,9 @@ void register_default_nvs(){
ESP_LOGD(TAG,"Registering default value for key %s, value %s", "display_config", STR(CONFIG_DISPLAY_CONFIG)); ESP_LOGD(TAG,"Registering default value for key %s, value %s", "display_config", STR(CONFIG_DISPLAY_CONFIG));
config_set_default(NVS_TYPE_STR, "display_config", STR(CONFIG_DISPLAY_CONFIG), 0); config_set_default(NVS_TYPE_STR, "display_config", STR(CONFIG_DISPLAY_CONFIG), 0);
ESP_LOGD(TAG,"Registering default value for key %s", "i2c_config");
config_set_default(NVS_TYPE_STR, "i2c_config", "", 0);
ESP_LOGD(TAG,"Done setting default values in nvs."); ESP_LOGD(TAG,"Done setting default values in nvs.");
} }

View File

@@ -7,7 +7,7 @@
<sha>799ae4860f9c009ac25c2ec35eb4070c5f474659</sha> <sha>799ae4860f9c009ac25c2ec35eb4070c5f474659</sha>
<email>philippe_44@outlook.com</email> <email>philippe_44@outlook.com</email>
<desc lang="EN">SqueezeESP32 additional player id (100)</desc> <desc lang="EN">SqueezeESP32 additional player id (100)</desc>
<url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32/SqueezeESP32.zip</url> <url>http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip</url>
<title lang="EN">SqueezeESP32</title> <title lang="EN">SqueezeESP32</title>
</plugin> </plugin>
</plugins> </plugins>