supporting command line driven display configuration

This commit is contained in:
Sebastien
2020-01-14 17:34:51 -05:00
parent bb6d30c45f
commit 89765d9679
6 changed files with 241 additions and 23 deletions

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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++;
}
}