mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-08 12:37:01 +03:00
supporting command line driven display configuration
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_log.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "config.h"
|
||||
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
@@ -70,6 +73,147 @@ static struct {
|
||||
struct arg_end *end;
|
||||
} i2cconfig_args;
|
||||
|
||||
static struct {
|
||||
struct arg_lit *clear;
|
||||
struct arg_int *address;
|
||||
struct arg_int *sda;
|
||||
struct arg_int *scl;
|
||||
struct arg_int *width;
|
||||
struct arg_int *height;
|
||||
struct arg_str *name;
|
||||
struct arg_str *driver;
|
||||
struct arg_end *end;
|
||||
} i2cdisp_args;
|
||||
|
||||
static struct {
|
||||
struct arg_end *end;
|
||||
} i2cdisp_show_args;
|
||||
static int do_i2c_show_display(int argc, char **argv){
|
||||
char * config_string = (char * )config_alloc_get(NVS_TYPE_STR, "display_config") ;
|
||||
if(config_string){
|
||||
ESP_LOGI(TAG,"Display configuration string is : \n"
|
||||
"display_config = \"%s\"",config_string);
|
||||
free(config_string);
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG,"No display configuration found in nvs config display_config");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_i2c_set_display(int argc, char **argv)
|
||||
{
|
||||
int sda = 0, scl=0, width=0, height=0, address=120;
|
||||
char * name = strdup("I2S");
|
||||
char * driver= strdup("SSD136");
|
||||
char config_string[200]={};
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cdisp_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, i2cdisp_args.end, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check "--clear" option */
|
||||
if (i2cdisp_args.clear->count) {
|
||||
ESP_LOGW(TAG,"Clearing display config");
|
||||
config_set_value(NVS_TYPE_STR, "display_config", "");
|
||||
}
|
||||
/* Check "--address" option */
|
||||
if (i2cdisp_args.address->count) {
|
||||
address=i2cdisp_args.address->ival[0];
|
||||
}
|
||||
/* Check "--sda" option */
|
||||
if (i2cdisp_args.sda->count) {
|
||||
sda=i2cdisp_args.sda->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing parameter: --sda");
|
||||
nerrors ++;
|
||||
}
|
||||
/* Check "--scl" option */
|
||||
if (i2cdisp_args.scl->count) {
|
||||
scl=i2cdisp_args.scl->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing parameter: --scl");
|
||||
nerrors ++;
|
||||
}
|
||||
|
||||
/* Check "--width" option */
|
||||
if (i2cdisp_args.width->count) {
|
||||
width=i2cdisp_args.width->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing parameter: --width");
|
||||
nerrors ++;
|
||||
}
|
||||
|
||||
/* Check "--height" option */
|
||||
if (i2cdisp_args.height->count) {
|
||||
height=i2cdisp_args.height->ival[0];
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Missing parameter: --height");
|
||||
nerrors ++;
|
||||
}
|
||||
/* Check "--name" option */
|
||||
if (i2cdisp_args.name->count) {
|
||||
free(name);
|
||||
name=strdup(i2cdisp_args.name->sval[0]);
|
||||
}
|
||||
|
||||
/* Check "--name" option */
|
||||
if (i2cdisp_args.driver->count) {
|
||||
free(driver);
|
||||
driver=strdup(i2cdisp_args.driver->sval[0]);
|
||||
}
|
||||
snprintf(config_string, sizeof(config_string),"%s:scl=%i,sda=%i,width=%i,height=%i,address=%i,driver=%s",name,scl,sda,width,height,address,driver );
|
||||
free(name);
|
||||
free(driver);
|
||||
|
||||
if(nerrors!=0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG,"Updating display configuration string configuration to :\n"
|
||||
"display_config = \"%s\"",config_string );
|
||||
|
||||
|
||||
return config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK;
|
||||
}
|
||||
|
||||
static void register_i2c_set_display(){
|
||||
i2cdisp_args.address = arg_int0(NULL, "address", "<n>", "Set the I2C bus port number (decimal format, default 120)");
|
||||
i2cdisp_args.sda = arg_int0("d", "sda", "<gpio>", "Set the gpio for I2C SDA");
|
||||
i2cdisp_args.scl = arg_int0("c", "scl", "<gpio>", "Set the gpio for I2C SCL");
|
||||
i2cdisp_args.width = arg_int0("w", "width", "<n>", "Set the display width");
|
||||
i2cdisp_args.height = arg_int0("h", "height", "<n>", "Set the display height");
|
||||
i2cdisp_args.name = arg_str0("n", "name", "<string>", "Set the display type. Default is I2S");
|
||||
i2cdisp_args.driver = arg_str0("d", "driver", "<string>", "Set the display driver name");
|
||||
i2cdisp_args.clear = arg_litn(NULL, "clear", 0, 1, "clear configuration");
|
||||
i2cdisp_args.end = arg_end(2);
|
||||
i2cdisp_show_args.end = arg_end(1);
|
||||
const esp_console_cmd_t i2c_set_display= {
|
||||
.command = "set_i2c_display",
|
||||
.help="Sets the i2c display options for the board",
|
||||
.hint = NULL,
|
||||
.func = &do_i2c_set_display,
|
||||
.argtable = &i2cdisp_args
|
||||
};
|
||||
const esp_console_cmd_t i2c_show_display= {
|
||||
.command = "show_i2c_display",
|
||||
.help="Sets the i2c display options for the board",
|
||||
.hint = NULL,
|
||||
.func = &do_i2c_show_display,
|
||||
.argtable = &i2cdisp_show_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_set_display));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_show_display));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int do_i2cconfig_cmd(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&i2cconfig_args);
|
||||
@@ -112,6 +256,16 @@ static void register_i2cconfig(void)
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int do_i2cdetect_cmd(int argc, char **argv)
|
||||
{
|
||||
i2c_master_driver_initialize();
|
||||
@@ -407,4 +561,5 @@ void register_i2ctools(void)
|
||||
register_i2cget();
|
||||
register_i2cset();
|
||||
register_i2cdump();
|
||||
register_i2c_set_display();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "ctype.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
@@ -89,10 +90,10 @@ static void * free_fn(void * ptr){
|
||||
}
|
||||
#endif
|
||||
void init_cJSON(){
|
||||
static cJSON_Hooks hooks;
|
||||
// initialize cJSON hooks it uses SPIRAM memory
|
||||
// as opposed to IRAM
|
||||
#ifndef RECOVERY_APPLICATION
|
||||
static cJSON_Hooks hooks;
|
||||
// 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.
|
||||
hooks.malloc_fn=&malloc_fn;
|
||||
@@ -703,6 +704,39 @@ esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value){
|
||||
return result;
|
||||
}
|
||||
|
||||
#define IS_ALPHA(c) isalpha((int)c)
|
||||
#define TO_UPPER(c) toupper((int)c)
|
||||
|
||||
|
||||
|
||||
|
||||
char * strstri (const char * str1, const char * str2){
|
||||
char *cp = (char *) str1;
|
||||
char *s1, *s2;
|
||||
|
||||
if ( *str2=='\0' )
|
||||
return((char *)str1);
|
||||
|
||||
while (*cp){
|
||||
s1 = cp;
|
||||
s2 = (char *) str2;
|
||||
while ( *s1!='\0' && *s2!='\0' && (IS_ALPHA(*s1) && IS_ALPHA(*s2))?!(TO_UPPER(*s1) - TO_UPPER(*s2)):!(*s1-*s2)){
|
||||
ESP_LOGW(TAG,"Matched [%c] = [%c] ", IS_ALPHA(*s1)?TO_UPPER(*s1):*s1,IS_ALPHA(*s2)?TO_UPPER(*s2):*s2);
|
||||
++s1, ++s2;
|
||||
}
|
||||
|
||||
|
||||
if (*s2=='\0'){
|
||||
ESP_LOGW(TAG,"String %s found!", str2);
|
||||
return(cp);
|
||||
}
|
||||
|
||||
++cp;
|
||||
ESP_LOGW(TAG,"%s not found. s2 is [%c]. Moving forward to %s", str2, *s2, cp);
|
||||
}
|
||||
ESP_LOGW(TAG,"String %s not found", str2);
|
||||
return(NULL);
|
||||
}
|
||||
IMPLEMENT_SET_DEFAULT(uint8_t,NVS_TYPE_U8);
|
||||
IMPLEMENT_SET_DEFAULT(int8_t,NVS_TYPE_I8);
|
||||
IMPLEMENT_SET_DEFAULT(uint16_t,NVS_TYPE_U16);
|
||||
@@ -716,3 +750,4 @@ IMPLEMENT_GET_NUM(uint16_t,NVS_TYPE_U16);
|
||||
IMPLEMENT_GET_NUM(int16_t,NVS_TYPE_I16);
|
||||
IMPLEMENT_GET_NUM(uint32_t,NVS_TYPE_U32);
|
||||
IMPLEMENT_GET_NUM(int32_t,NVS_TYPE_I32);
|
||||
|
||||
|
||||
@@ -37,4 +37,4 @@ void * config_alloc_get(nvs_type_t nvs_type, const char *key) ;
|
||||
bool wait_for_commit();
|
||||
char * config_alloc_get_json(bool bFormatted);
|
||||
esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value);
|
||||
|
||||
char * strstri (const char * str1, const char * str2);
|
||||
|
||||
@@ -40,16 +40,22 @@ void display_init(void) {
|
||||
char *item = config_alloc_get(NVS_TYPE_STR, "display_config");
|
||||
|
||||
if (item && *item) {
|
||||
handle = &SSD1306_handle;
|
||||
if (handle->init(item)) {
|
||||
slimp_handler_chain = slimp_handler;
|
||||
slimp_handler = display_handler;
|
||||
ESP_LOGI(TAG, "Display initialization successful");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Display initialization failed");
|
||||
char * drivername=strstr(item,"driver");
|
||||
if( !drivername || (drivername && (strstr(drivername,"SSD1306") || strstr(drivername,"ssd1306")))){
|
||||
handle = &SSD1306_handle;
|
||||
if (handle->init(item)) {
|
||||
slimp_handler_chain = slimp_handler;
|
||||
slimp_handler = display_handler;
|
||||
ESP_LOGI(TAG, "Display initialization successful");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Display initialization failed");
|
||||
}
|
||||
}else {
|
||||
ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item);
|
||||
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "no display");
|
||||
ESP_LOGW(TAG, "no display");
|
||||
}
|
||||
|
||||
if (item) free(item);
|
||||
|
||||
@@ -76,26 +76,41 @@ static bool display_init(char *config) {
|
||||
|
||||
if (strstr(config, "I2C")) {
|
||||
int scl = -1, sda = -1;
|
||||
int width = -1, height = -1;
|
||||
int width = -1, height = -1, address=I2C_ADDRESS;
|
||||
char *p;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing I2C display with config: %s",config);
|
||||
// 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, "height")) != NULL) height = atoi(strchr(p, '=') + 1);
|
||||
if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1);
|
||||
|
||||
if (sda != -1 && scl != -1 && width != -1 && height != -1) {
|
||||
SSD1306_I2CMasterInitDefault( I2C_PORT, sda, scl );
|
||||
SSD1306_I2CMasterAttachDisplayDefault( &I2CDisplay, width, height, I2C_ADDRESS, -1);
|
||||
SSD1306_SetFont( &I2CDisplay, &Font_droid_sans_fallback_15x17 );
|
||||
ESP_LOGI(TAG, "Initialized I2C display %dx%d (sda:%d, scl:%d)", width, height, sda, scl);
|
||||
res = true;
|
||||
res = SSD1306_I2CMasterInitDefault( I2C_PORT, sda, scl );
|
||||
if(!res){
|
||||
ESP_LOGE(TAG,"I2C Master Init failed");
|
||||
}
|
||||
}
|
||||
if(res){
|
||||
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){
|
||||
ESP_LOGI(TAG, "Initialized I2C display %dx%d (sda:%d, scl:%d, address:%02x)", width, height, sda, scl, address);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Cannot initialized I2C display %s [%dx%d sda:%d, scl:%d]", config, width, height, sda, scl);
|
||||
ESP_LOGE(TAG, "Cannot initialized I2C display %s [%dx%d sda:%d, scl:%d, address:%02x]", config, width, height, sda, scl, address);
|
||||
}
|
||||
} else {
|
||||
// other types
|
||||
ESP_LOGE(TAG, "Non-I2C display not supported. Display config %s", config);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -209,7 +209,7 @@ esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *cur_conf
|
||||
|
||||
|
||||
esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_config) {
|
||||
esp_err_t err = ESP_FAIL;
|
||||
esp_err_t err = ESP_OK;
|
||||
const actrls_config_map_t * h=actrls_config_map;
|
||||
|
||||
char * str = cJSON_Print(member);
|
||||
@@ -219,6 +219,7 @@ esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_confi
|
||||
ESP_LOGD(TAG,"found handler for member %s, json value %s", h->member,str?str:"");
|
||||
err = h->handler(member, cur_config, h->offset);
|
||||
} else {
|
||||
err = ESP_FAIL;
|
||||
ESP_LOGE(TAG, "Unknown json structure member : %s", str?str:"");
|
||||
}
|
||||
|
||||
@@ -227,7 +228,7 @@ esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_confi
|
||||
}
|
||||
|
||||
esp_err_t actrls_process_button(const cJSON * button, actrls_config_t *cur_config) {
|
||||
esp_err_t err= ESP_FAIL;
|
||||
esp_err_t err= ESP_OK;
|
||||
const cJSON *member;
|
||||
|
||||
cJSON_ArrayForEach(member, button)
|
||||
@@ -300,9 +301,15 @@ esp_err_t actrls_init_json(const char *config) {
|
||||
esp_err_t loc_err = actrls_process_button(button, cur_config);
|
||||
err = (err == ESP_OK) ? loc_err : err;
|
||||
if (loc_err == ESP_OK) {
|
||||
|
||||
ESP_LOGI(TAG, "Calling button_create");
|
||||
button_create((void*) cur_config, cur_config->gpio,cur_config->type, cur_config->pull,cur_config->debounce,
|
||||
control_handler, cur_config->long_press, cur_config->shifter_gpio);
|
||||
}
|
||||
else{
|
||||
ESP_LOGE(TAG,"Error parsing button structure. Button will not be registered.");
|
||||
}
|
||||
|
||||
cur_config++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user