accessors.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. /*
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <stdio.h>
  8. #include "esp_log.h"
  9. #include "driver/gpio.h"
  10. #include "driver/i2c.h"
  11. #include "driver/spi_master.h"
  12. #include "platform_config.h"
  13. #include "accessors.h"
  14. #include "globdefs.h"
  15. #include "display.h"
  16. #include "display.h"
  17. #include "cJSON.h"
  18. #include "driver/gpio.h"
  19. #include "stdbool.h"
  20. #include "driver/adc.h"
  21. #include "esp_attr.h"
  22. #include "soc/spi_periph.h"
  23. #include "esp_err.h"
  24. #include "soc/rtc.h"
  25. #include "sdkconfig.h"
  26. #include "soc/efuse_periph.h"
  27. #include "driver/gpio.h"
  28. #include "driver/spi_common_internal.h"
  29. #include "esp32/rom/efuse.h"
  30. #include "adac.h"
  31. #include "trace.h"
  32. #include "monitor.h"
  33. #include "messaging.h"
  34. static const char *TAG = "services";
  35. const char *i2c_name_type="I2C";
  36. const char *spi_name_type="SPI";
  37. static cJSON * gpio_list=NULL;
  38. #define min(a,b) (((a) < (b)) ? (a) : (b))
  39. #ifndef QUOTE
  40. #define QUOTE(name) #name
  41. #endif
  42. #ifndef STR
  43. #define STR(macro) QUOTE(macro)
  44. #endif
  45. bool are_statistics_enabled(){
  46. #if defined(CONFIG_FREERTOS_USE_TRACE_FACILITY) && defined (CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS)
  47. return true;
  48. #endif
  49. return false;
  50. }
  51. /****************************************************************************************
  52. *
  53. */
  54. static char * config_spdif_get_string(){
  55. return config_alloc_get_str("spdif_config", CONFIG_SPDIF_CONFIG, "bck=" STR(CONFIG_SPDIF_BCK_IO)
  56. ",ws=" STR(CONFIG_SPDIF_WS_IO) ",do=" STR(CONFIG_SPDIF_DO_IO));
  57. }
  58. /****************************************************************************************
  59. *
  60. */
  61. static char * get_dac_config_string(){
  62. return config_alloc_get_str("dac_config", CONFIG_DAC_CONFIG, "model=i2s,bck=" STR(CONFIG_I2S_BCK_IO)
  63. ",ws=" STR(CONFIG_I2S_WS_IO) ",do=" STR(CONFIG_I2S_DO_IO)
  64. ",sda=" STR(CONFIG_I2C_SDA) ",scl=" STR(CONFIG_I2C_SCL)
  65. ",mute=" STR(CONFIG_MUTE_GPIO));
  66. }
  67. /****************************************************************************************
  68. *
  69. */
  70. bool is_dac_config_locked(){
  71. #if ( defined CONFIG_DAC_CONFIG )
  72. if(strlen(CONFIG_DAC_CONFIG) > 0){
  73. return true;
  74. }
  75. #endif
  76. #if defined(CONFIG_I2S_BCK_IO) && CONFIG_I2S_BCK_IO>0
  77. return true;
  78. #endif
  79. return false;
  80. }
  81. /****************************************************************************************
  82. *
  83. */
  84. bool is_spdif_config_locked(){
  85. #if ( defined CONFIG_SPDIF_CONFIG )
  86. if(strlen(CONFIG_SPDIF_CONFIG) > 0){
  87. return true;
  88. }
  89. #endif
  90. #if defined(CONFIG_SPDIF_BCK_IO) && CONFIG_SPDIF_BCK_IO>0
  91. return true;
  92. #endif
  93. return false;
  94. }
  95. /****************************************************************************************
  96. * Set pin from config string
  97. */
  98. static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) {
  99. char *p;
  100. pin_config->bck_io_num = pin_config->ws_io_num = pin_config->data_out_num = pin_config->data_in_num = -1;
  101. if ((p = strcasestr(config, "bck")) != NULL) pin_config->bck_io_num = atoi(strchr(p, '=') + 1);
  102. if ((p = strcasestr(config, "ws")) != NULL) pin_config->ws_io_num = atoi(strchr(p, '=') + 1);
  103. if ((p = strcasestr(config, "do")) != NULL) pin_config->data_out_num = atoi(strchr(p, '=') + 1);
  104. }
  105. /****************************************************************************************
  106. * Get i2s config structure from config string
  107. */
  108. const i2s_platform_config_t * config_get_i2s_from_str(char * dac_config ){
  109. static i2s_platform_config_t i2s_dac_pin = {
  110. .i2c_addr = -1,
  111. .sda= -1,
  112. .scl = -1,
  113. .mute_gpio = -1,
  114. .mute_level = -1
  115. };
  116. set_i2s_pin(dac_config, &i2s_dac_pin.pin);
  117. strcpy(i2s_dac_pin.model, "i2s");
  118. char * p=NULL;
  119. if ((p = strcasestr(dac_config, "i2c")) != NULL) i2s_dac_pin.i2c_addr = atoi(strchr(p, '=') + 1);
  120. if ((p = strcasestr(dac_config, "sda")) != NULL) i2s_dac_pin.sda = atoi(strchr(p, '=') + 1);
  121. if ((p = strcasestr(dac_config, "scl")) != NULL) i2s_dac_pin.scl = atoi(strchr(p, '=') + 1);
  122. if ((p = strcasestr(dac_config, "model")) != NULL) sscanf(p, "%*[^=]=%31[^,]", i2s_dac_pin.model);
  123. if ((p = strcasestr(dac_config, "mute")) != NULL) {
  124. char mute[8] = "";
  125. sscanf(p, "%*[^=]=%7[^,]", mute);
  126. i2s_dac_pin.mute_gpio = atoi(mute);
  127. if ((p = strchr(mute, ':')) != NULL) i2s_dac_pin.mute_level = atoi(p + 1);
  128. }
  129. return &i2s_dac_pin;
  130. }
  131. /****************************************************************************************
  132. * Get spdif config structure
  133. */
  134. const i2s_platform_config_t * config_spdif_get( ){
  135. char * spdif_config = config_spdif_get_string();
  136. static i2s_platform_config_t i2s_dac_config;
  137. memcpy(&i2s_dac_config, config_get_i2s_from_str(spdif_config), sizeof(i2s_dac_config));
  138. free(spdif_config);
  139. return &i2s_dac_config;
  140. }
  141. /****************************************************************************************
  142. * Get dac config structure
  143. */
  144. const i2s_platform_config_t * config_dac_get(){
  145. char * spdif_config = get_dac_config_string();
  146. static i2s_platform_config_t i2s_dac_config;
  147. memcpy(&i2s_dac_config, config_get_i2s_from_str(spdif_config), sizeof(i2s_dac_config));
  148. free(spdif_config);
  149. return &i2s_dac_config;
  150. }
  151. /****************************************************************************************
  152. *
  153. */
  154. esp_err_t config_i2c_set(const i2c_config_t * config, int port){
  155. int buffer_size=255;
  156. esp_err_t err=ESP_OK;
  157. char * config_buffer=calloc(buffer_size,1);
  158. if(config_buffer) {
  159. snprintf(config_buffer,buffer_size,"scl=%u,sda=%u,speed=%u,port=%u",config->scl_io_num,config->sda_io_num,config->master.clk_speed,port);
  160. log_send_messaging(MESSAGING_INFO,"Updating I2C configuration to %s",config_buffer);
  161. err = config_set_value(NVS_TYPE_STR, "i2c_config", config_buffer);
  162. if(err!=ESP_OK){
  163. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  164. }
  165. free(config_buffer);
  166. }
  167. return err;
  168. }
  169. /****************************************************************************************
  170. *
  171. */
  172. esp_err_t config_display_set(const display_config_t * config){
  173. int buffer_size=512;
  174. esp_err_t err=ESP_OK;
  175. char * config_buffer=calloc(buffer_size,1);
  176. char * config_buffer2=calloc(buffer_size,1);
  177. if(config_buffer && config_buffer2) {
  178. snprintf(config_buffer,buffer_size,"%s:width=%i,height=%i",config->type,config->width,config->height);
  179. if(strcasecmp("I2C",config->type)==0){
  180. if(config->address>0 ){
  181. snprintf(config_buffer2,buffer_size,"%s,address=%i",config_buffer,config->address);
  182. strcpy(config_buffer,config_buffer2);
  183. }
  184. }
  185. else {
  186. if(config->CS_pin >=0 ){
  187. snprintf(config_buffer2,buffer_size,"%s,cs=%i",config_buffer,config->CS_pin);
  188. strcpy(config_buffer,config_buffer2);
  189. }
  190. }
  191. if(config->RST_pin >=0 ){
  192. snprintf(config_buffer2,buffer_size,"%s,reset=%i",config_buffer,config->RST_pin);
  193. strcpy(config_buffer,config_buffer2);
  194. }
  195. // I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
  196. // SPI,width=<pixels>,height=<pixels>,cs=<gpio>[,back=<gpio>][,reset=<gpio>][,speed=<speed>][,HFlip][,VFlip][driver=SSD1306|SSD1322|SSD1326[:1|4]|SSD1327|SH1106|SSD1675|ST7735|ST7789[,rotate]]
  197. if(config->back >=0 ){
  198. snprintf(config_buffer2,buffer_size,"%s,back=%i",config_buffer,config->back);
  199. strcpy(config_buffer,config_buffer2);
  200. }
  201. if(config->speed >0 && strcasecmp("SPI",config->type)==0){
  202. snprintf(config_buffer2,buffer_size,"%s,speed=%i",config_buffer,config->speed);
  203. strcpy(config_buffer,config_buffer2);
  204. }
  205. snprintf(config_buffer2,buffer_size,"%s,driver=%s%s%s%s",config_buffer,config->drivername,config->hflip?",HFlip":"",config->vflip?",VFlip":"",config->rotate?",rotate":"");
  206. strcpy(config_buffer,config_buffer2);
  207. log_send_messaging(MESSAGING_INFO,"Updating display configuration to %s",config_buffer);
  208. err = config_set_value(NVS_TYPE_STR, "display_config", config_buffer);
  209. if(err!=ESP_OK){
  210. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  211. }
  212. }
  213. else {
  214. err = ESP_ERR_NO_MEM;
  215. }
  216. FREE_AND_NULL(config_buffer);
  217. FREE_AND_NULL(config_buffer2);
  218. return err;
  219. }
  220. /****************************************************************************************
  221. *
  222. */
  223. esp_err_t config_i2s_set(const i2s_platform_config_t * config, const char * nvs_name){
  224. int buffer_size=255;
  225. esp_err_t err=ESP_OK;
  226. char * config_buffer=calloc(buffer_size,1);
  227. char * config_buffer2=calloc(buffer_size,1);
  228. if(config_buffer && config_buffer2) {
  229. snprintf(config_buffer,buffer_size,"model=%s,bck=%u,ws=%u,do=%u",config->model,config->pin.bck_io_num,config->pin.ws_io_num,config->pin.data_out_num);
  230. if(config->mute_gpio>=0){
  231. snprintf(config_buffer2,buffer_size,"%s,mute=%u:%u",config_buffer,config->mute_gpio,config->mute_level);
  232. strcpy(config_buffer,config_buffer2);
  233. }
  234. if(config->sda>=0){
  235. snprintf(config_buffer2,buffer_size,"%s,sda=%u,scl=%u",config_buffer,config->sda,config->scl);
  236. strcpy(config_buffer,config_buffer2);
  237. }
  238. if(config->i2c_addr>0){
  239. snprintf(config_buffer2,buffer_size,"%s,i2c=%u",config_buffer,config->i2c_addr);
  240. strcpy(config_buffer,config_buffer2);
  241. }
  242. log_send_messaging(MESSAGING_INFO,"Updating dac configuration to %s",config_buffer);
  243. err = config_set_value(NVS_TYPE_STR, nvs_name, config_buffer);
  244. if(err!=ESP_OK){
  245. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  246. }
  247. }
  248. else {
  249. err = ESP_ERR_NO_MEM;
  250. }
  251. FREE_AND_NULL(config_buffer);
  252. FREE_AND_NULL(config_buffer2);
  253. return err;
  254. }
  255. /****************************************************************************************
  256. *
  257. */
  258. esp_err_t config_spdif_set(const i2s_platform_config_t * config){
  259. int buffer_size=255;
  260. esp_err_t err=ESP_OK;
  261. char * config_buffer=calloc(buffer_size,1);
  262. if(config_buffer ) {
  263. snprintf(config_buffer,buffer_size,"bck=%u,ws=%u,do=%u",config->pin.bck_io_num,config->pin.ws_io_num,config->pin.data_out_num);
  264. log_send_messaging(MESSAGING_INFO,"Updating SPDIF configuration to %s",config_buffer);
  265. err = config_set_value(NVS_TYPE_STR, "spdif_config", config_buffer);
  266. if(err!=ESP_OK){
  267. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  268. }
  269. }
  270. else {
  271. err = ESP_ERR_NO_MEM;
  272. }
  273. FREE_AND_NULL(config_buffer);
  274. return err;
  275. }
  276. /****************************************************************************************
  277. *
  278. */
  279. esp_err_t config_spi_set(const spi_bus_config_t * config, int host, int dc){
  280. int buffer_size=255;
  281. esp_err_t err = ESP_OK;
  282. char * config_buffer=calloc(buffer_size,1);
  283. if(config_buffer) {
  284. snprintf(config_buffer,buffer_size,"data=%u,clk=%u,dc=%u,host=%u",config->mosi_io_num,config->sclk_io_num,dc,host);
  285. log_send_messaging(MESSAGING_INFO,"Updating SPI configuration to %s",config_buffer);
  286. err = config_set_value(NVS_TYPE_STR, "spi_config", config_buffer);
  287. if(err!=ESP_OK){
  288. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  289. }
  290. free(config_buffer);
  291. }
  292. return err;
  293. }
  294. /****************************************************************************************
  295. *
  296. */
  297. const display_config_t * config_display_get(){
  298. static display_config_t dstruct = {
  299. .back = -1,
  300. .CS_pin = -1,
  301. .RST_pin = -1,
  302. .depth = -1,
  303. .address = 0,
  304. .drivername = NULL,
  305. .height = 0,
  306. .width = 0,
  307. .vflip = false,
  308. .hflip = false,
  309. .type = NULL,
  310. .speed = 0,
  311. .rotate = false
  312. };
  313. char *config = config_alloc_get(NVS_TYPE_STR, "display_config");
  314. if (!config) {
  315. return NULL;
  316. }
  317. char * p=NULL;
  318. if ((p = strcasestr(config, "driver")) != NULL){
  319. sscanf(p, "%*[^:]:%u", &dstruct.depth);
  320. dstruct.drivername = display_conf_get_driver_name(strchr(p, '=') + 1);
  321. }
  322. dstruct.drivername=dstruct.drivername?dstruct.drivername:"SSD1306";
  323. if ((p = strcasestr(config, "width")) != NULL) dstruct.width = atoi(strchr(p, '=') + 1);
  324. if ((p = strcasestr(config, "height")) != NULL) dstruct.height = atoi(strchr(p, '=') + 1);
  325. if ((p = strcasestr(config, "reset")) != NULL) dstruct.RST_pin = atoi(strchr(p, '=') + 1);
  326. if (strstr(config, "I2C") ) dstruct.type=i2c_name_type;
  327. if ((p = strcasestr(config, "address")) != NULL) dstruct.address = atoi(strchr(p, '=') + 1);
  328. if (strstr(config, "SPI") ) dstruct.type=spi_name_type;
  329. if ((p = strcasestr(config, "cs")) != NULL) dstruct.CS_pin = atoi(strchr(p, '=') + 1);
  330. if ((p = strcasestr(config, "speed")) != NULL) dstruct.speed = atoi(strchr(p, '=') + 1);
  331. if ((p = strcasestr(config, "back")) != NULL) dstruct.back = atoi(strchr(p, '=') + 1);
  332. dstruct.hflip= strcasestr(config, "HFlip") ? true : false;
  333. dstruct.vflip= strcasestr(config, "VFlip") ? true : false;
  334. dstruct.rotate= strcasestr(config, "rotate") ? true : false;
  335. return &dstruct;
  336. }
  337. /****************************************************************************************
  338. *
  339. */
  340. const i2c_config_t * config_i2c_get(int * i2c_port) {
  341. char *nvs_item, *p;
  342. static i2c_config_t i2c = {
  343. .mode = I2C_MODE_MASTER,
  344. .sda_io_num = -1,
  345. .sda_pullup_en = GPIO_PULLUP_ENABLE,
  346. .scl_io_num = -1,
  347. .scl_pullup_en = GPIO_PULLUP_ENABLE,
  348. .master.clk_speed = 0,
  349. };
  350. i2c.master.clk_speed = i2c_system_speed;
  351. nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
  352. if (nvs_item) {
  353. if ((p = strcasestr(nvs_item, "scl")) != NULL) i2c.scl_io_num = atoi(strchr(p, '=') + 1);
  354. if ((p = strcasestr(nvs_item, "sda")) != NULL) i2c.sda_io_num = atoi(strchr(p, '=') + 1);
  355. if ((p = strcasestr(nvs_item, "speed")) != NULL) i2c.master.clk_speed = atoi(strchr(p, '=') + 1);
  356. if ((p = strcasestr(nvs_item, "port")) != NULL) i2c_system_port = atoi(strchr(p, '=') + 1);
  357. free(nvs_item);
  358. }
  359. if(i2c_port) {
  360. #ifdef CONFIG_I2C_LOCKED
  361. *i2c_port= I2C_NUM_1;
  362. #else
  363. *i2c_port=i2c_system_port;
  364. #endif
  365. }
  366. return &i2c;
  367. }
  368. /****************************************************************************************
  369. *
  370. */
  371. const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
  372. char *nvs_item, *p;
  373. static spi_bus_config_t spi = {
  374. .mosi_io_num = -1,
  375. .sclk_io_num = -1,
  376. .miso_io_num = -1,
  377. .quadwp_io_num = -1,
  378. .quadhd_io_num = -1
  379. };
  380. nvs_item = config_alloc_get_str("spi_config", CONFIG_SPI_CONFIG, NULL);
  381. if (nvs_item) {
  382. if ((p = strcasestr(nvs_item, "data")) != NULL) spi.mosi_io_num = atoi(strchr(p, '=') + 1);
  383. if ((p = strcasestr(nvs_item, "clk")) != NULL) spi.sclk_io_num = atoi(strchr(p, '=') + 1);
  384. if ((p = strcasestr(nvs_item, "dc")) != NULL) spi_system_dc_gpio = atoi(strchr(p, '=') + 1);
  385. if ((p = strcasestr(nvs_item, "host")) != NULL) spi_system_host = atoi(strchr(p, '=') + 1);
  386. free(nvs_item);
  387. }
  388. if(spi_host) *spi_host = spi_system_host;
  389. return &spi;
  390. }
  391. /****************************************************************************************
  392. *
  393. */
  394. void parse_set_GPIO(void (*cb)(int gpio, char *value)) {
  395. char *nvs_item, *p, type[16];
  396. int gpio;
  397. if ((nvs_item = config_alloc_get(NVS_TYPE_STR, "set_GPIO")) == NULL) return;
  398. p = nvs_item;
  399. do {
  400. if (sscanf(p, "%d=%15[^,]", &gpio, type) > 0) cb(gpio, type);
  401. p = strchr(p, ',');
  402. } while (p++);
  403. free(nvs_item);
  404. }
  405. /****************************************************************************************
  406. *
  407. */
  408. cJSON * get_gpio_entry(const char * name, const char * prefix, int gpio, bool fixed){
  409. cJSON * entry = cJSON_CreateObject();
  410. cJSON_AddNumberToObject(entry,"gpio",gpio);
  411. cJSON_AddStringToObject(entry,"name",name);
  412. cJSON_AddStringToObject(entry,"group",prefix);
  413. cJSON_AddBoolToObject(entry,"fixed",fixed);
  414. return entry;
  415. }
  416. /****************************************************************************************
  417. *
  418. */
  419. cJSON * get_GPIO_nvs_list(cJSON * list) {
  420. cJSON * ilist = list?list:cJSON_CreateArray();
  421. char *nvs_item, *p, type[16];
  422. int gpio;
  423. bool fixed=false;
  424. #ifdef CONFIG_JACK_LOCKED
  425. bool bFoundJack=false;
  426. #endif
  427. #ifdef CONFIG_SPKFAULT_LOCKED
  428. bool bFoundSpkFault = false;
  429. #endif
  430. if ((nvs_item = config_alloc_get(NVS_TYPE_STR, "set_GPIO")) == NULL) return ilist;
  431. p = nvs_item;
  432. do {
  433. fixed=false;
  434. if (sscanf(p, "%d=%15[^,]", &gpio, type) > 0 && (GPIO_IS_VALID_GPIO(gpio) || gpio==GPIO_NUM_NC)){
  435. #ifdef CONFIG_JACK_LOCKED
  436. if(strcasecmp(type,"jack")==0){
  437. fixed=true;
  438. bFoundJack=true;
  439. }
  440. #endif
  441. #ifdef CONFIG_SPKFAULT_LOCKED
  442. if(strcasecmp(type,"spkfault")==0){
  443. fixed=true;
  444. bFoundSpkFault=true;
  445. }
  446. #endif
  447. cJSON_AddItemToArray(ilist,get_gpio_entry(type,"gpio", gpio, fixed));
  448. }
  449. p = strchr(p, ',');
  450. } while (p++);
  451. #ifdef CONFIG_JACK_LOCKED
  452. if(!bFoundJack){
  453. monitor_gpio_t *jack= get_jack_insertion_gpio();
  454. cJSON_AddItemToArray(list,get_gpio_entry("jack", "other", jack->gpio, true));
  455. }
  456. #endif
  457. #ifdef CONFIG_SPKFAULT_LOCKED
  458. if(!bFoundSpkFault){
  459. monitor_gpio_t *jack= get_spkfault_gpio();
  460. cJSON_AddItemToArray(list,get_gpio_entry("spkfault", "other", jack->gpio, true));
  461. }
  462. #endif
  463. free(nvs_item);
  464. return ilist;
  465. }
  466. /****************************************************************************************
  467. *
  468. */
  469. cJSON * get_DAC_GPIO(cJSON * list){
  470. cJSON * llist = list;
  471. if(!llist){
  472. llist = cJSON_CreateArray();
  473. }
  474. const i2s_platform_config_t * i2s_config= config_dac_get();
  475. if(i2s_config->pin.bck_io_num>=0){
  476. cJSON_AddItemToArray(llist,get_gpio_entry("bck","dac",i2s_config->pin.bck_io_num,is_dac_config_locked()));
  477. cJSON_AddItemToArray(llist,get_gpio_entry("ws","dac",i2s_config->pin.ws_io_num,is_dac_config_locked()));
  478. cJSON_AddItemToArray(llist,get_gpio_entry("do","dac",i2s_config->pin.data_out_num,is_dac_config_locked()));
  479. if(i2s_config->sda>=0){
  480. cJSON_AddItemToArray(llist,get_gpio_entry("sda","dac",i2s_config->sda,is_dac_config_locked()));
  481. cJSON_AddItemToArray(llist,get_gpio_entry("scl","dac",i2s_config->scl,is_dac_config_locked()));
  482. }
  483. if(i2s_config->mute_gpio>=0){
  484. cJSON_AddItemToArray(llist,get_gpio_entry("mute","dac",i2s_config->mute_gpio,is_dac_config_locked()));
  485. }
  486. }
  487. return llist;
  488. }
  489. /****************************************************************************************
  490. *
  491. */
  492. cJSON * get_Display_GPIO(cJSON * list){
  493. cJSON * llist = list;
  494. if(!llist){
  495. llist = cJSON_CreateArray();
  496. }
  497. const display_config_t * config= config_display_get();
  498. if(config->back >=0){
  499. cJSON_AddItemToArray(llist,get_gpio_entry("backlight","display",config->back,false));
  500. }
  501. if(config->CS_pin >=0){
  502. cJSON_AddItemToArray(llist,get_gpio_entry("CS","display",config->CS_pin,false));
  503. }
  504. if(config->RST_pin >=0){
  505. cJSON_AddItemToArray(llist,get_gpio_entry("reset","display",config->RST_pin,false));
  506. }
  507. return llist;
  508. }
  509. /****************************************************************************************
  510. *
  511. */
  512. cJSON * get_I2C_GPIO(cJSON * list){
  513. cJSON * llist = list;
  514. if(!llist){
  515. llist = cJSON_CreateArray();
  516. }
  517. int port=0;
  518. const i2c_config_t * i2c_config = config_i2c_get(&port);
  519. if(i2c_config->scl_io_num>=0){
  520. cJSON_AddItemToArray(llist,get_gpio_entry("scl","i2c",i2c_config->scl_io_num,false));
  521. cJSON_AddItemToArray(llist,get_gpio_entry("sda","i2c",i2c_config->sda_io_num,false));
  522. }
  523. return llist;
  524. }
  525. /****************************************************************************************
  526. *
  527. */
  528. cJSON * get_SPI_GPIO(cJSON * list){
  529. cJSON * llist = list;
  530. if(!llist){
  531. llist = cJSON_CreateArray();
  532. }
  533. spi_host_device_t spi_host;
  534. const spi_bus_config_t * spi_config = config_spi_get(&spi_host);
  535. if(spi_config->miso_io_num>=0){
  536. cJSON_AddItemToArray(llist,get_gpio_entry("data","spi",spi_config->miso_io_num,false));
  537. cJSON_AddItemToArray(llist,get_gpio_entry("data","clk",spi_config->sclk_io_num,false));
  538. }
  539. if(spi_system_dc_gpio>0){
  540. cJSON_AddItemToArray(llist,get_gpio_entry("data","dc",spi_system_dc_gpio,false));
  541. }
  542. return llist;
  543. }
  544. /****************************************************************************************
  545. *
  546. */
  547. cJSON * get_GPIO_from_string(const char * nvs_item, const char * prefix, cJSON * list, bool fixed){
  548. cJSON * llist = list;
  549. int gpio=0,offset=0,soffset=0,ret1=0,sret=0;
  550. if(!llist){
  551. llist = cJSON_CreateArray();
  552. }
  553. const char *p=NULL;
  554. char type[16];
  555. int slen=strlen(nvs_item)+1;
  556. char * buf1=malloc(slen);
  557. char * buf2=malloc(slen);
  558. ESP_LOGD(TAG,"Parsing string %s",nvs_item);
  559. p = strchr(nvs_item, ':');
  560. p=p?p+1:nvs_item;
  561. while((((ret1=sscanf(p, "%[^=]=%d%n", type,&gpio,&offset)) ==2) || ((sret=sscanf(p, "%[^=]=%[^, ],%n", buf1,buf2,&soffset)) > 0 )) && (offset || soffset)){
  562. if(ret1==2 && (GPIO_IS_VALID_GPIO(gpio) || gpio==GPIO_NUM_NC)){
  563. if(gpio>0){
  564. cJSON_AddItemToArray(llist,get_gpio_entry(type,prefix,gpio,fixed));
  565. }
  566. p+=offset;
  567. } else {
  568. p+=soffset;
  569. }
  570. while(*p==' ' || *p==',') p++;
  571. gpio=-1;
  572. }
  573. free(buf1);
  574. free(buf2);
  575. return llist;
  576. }
  577. /****************************************************************************************
  578. *
  579. */
  580. cJSON * get_GPIO_from_nvs(const char * item, const char * prefix, cJSON * list, bool fixed){
  581. char * nvs_item=NULL;
  582. cJSON * llist=list;
  583. if ((nvs_item = config_alloc_get(NVS_TYPE_STR, item)) == NULL) return list;
  584. llist = get_GPIO_from_string(nvs_item,prefix,list, fixed);
  585. free(nvs_item);
  586. return llist;
  587. }
  588. /****************************************************************************************
  589. *
  590. */
  591. esp_err_t get_gpio_structure(cJSON * gpio_entry, gpio_entry_t ** gpio){
  592. esp_err_t err = ESP_OK;
  593. *gpio = malloc(sizeof(gpio_entry_t));
  594. cJSON * val = cJSON_GetObjectItem(gpio_entry,"gpio");
  595. if(val){
  596. (*gpio)->gpio= (int)val->valuedouble;
  597. } else {
  598. ESP_LOGE(TAG,"gpio pin not found");
  599. err=ESP_FAIL;
  600. }
  601. val = cJSON_GetObjectItem(gpio_entry,"name");
  602. if(val){
  603. (*gpio)->name= strdup(cJSON_GetStringValue(val));
  604. } else {
  605. ESP_LOGE(TAG,"gpio name value not found");
  606. err=ESP_FAIL;
  607. }
  608. val = cJSON_GetObjectItem(gpio_entry,"group");
  609. if(val){
  610. (*gpio)->group= strdup(cJSON_GetStringValue(val));
  611. } else {
  612. ESP_LOGE(TAG,"gpio group value not found");
  613. err=ESP_FAIL;
  614. }
  615. val = cJSON_GetObjectItem(gpio_entry,"fixed");
  616. if(val){
  617. (*gpio)->fixed= cJSON_IsTrue(val);
  618. } else {
  619. ESP_LOGE(TAG,"gpio fixed indicator not found");
  620. err=ESP_FAIL;
  621. }
  622. return err;
  623. }
  624. /****************************************************************************************
  625. *
  626. */
  627. esp_err_t free_gpio_entry( gpio_entry_t ** gpio) {
  628. if(* gpio){
  629. free((* gpio)->name);
  630. free((* gpio)->group);
  631. free(* gpio);
  632. * gpio=NULL;
  633. return ESP_OK;
  634. }
  635. return ESP_FAIL;
  636. }
  637. /****************************************************************************************
  638. *
  639. */
  640. gpio_entry_t * get_gpio_by_no(int gpionum, bool refresh){
  641. cJSON * gpio_header=NULL;
  642. gpio_entry_t * gpio=NULL;
  643. if(refresh){
  644. get_gpio_list();
  645. }
  646. cJSON_ArrayForEach(gpio_header,gpio_list)
  647. {
  648. if(get_gpio_structure(gpio_header, &gpio)==ESP_OK && gpio->gpio==gpionum){
  649. ESP_LOGD(TAG,"Found GPIO: %s=%d %s", gpio->name,gpio->gpio,gpio->fixed?"(FIXED)":"(VARIABLE)");
  650. }
  651. }
  652. return gpio;
  653. }
  654. /****************************************************************************************
  655. *
  656. */
  657. gpio_entry_t * get_gpio_by_name(char * name,char * group, bool refresh){
  658. cJSON * gpio_header=NULL;
  659. if(refresh){
  660. get_gpio_list();
  661. }
  662. gpio_entry_t * gpio=NULL;
  663. cJSON_ArrayForEach(gpio_header,gpio_list)
  664. {
  665. if(get_gpio_structure(gpio_header, &gpio)==ESP_OK && strcasecmp(gpio->name,name)&& strcasecmp(gpio->group,group)){
  666. ESP_LOGD(TAG,"Found GPIO: %s=%d %s", gpio->name,gpio->gpio,gpio->fixed?"(FIXED)":"(VARIABLE)");
  667. }
  668. }
  669. return gpio;
  670. }
  671. #ifndef PICO_PSRAM_CLK_IO
  672. #define PICO_PSRAM_CLK_IO 6
  673. #endif
  674. #ifndef PSRAM_SPIQ_SD0_IO
  675. #define PSRAM_SPIQ_SD0_IO 7
  676. #define PSRAM_SPID_SD1_IO 8
  677. #define PSRAM_SPIWP_SD3_IO 10
  678. #define PSRAM_SPIHD_SD2_IO 9
  679. #define FLASH_HSPI_CLK_IO 14
  680. #define FLASH_HSPI_CS_IO 15
  681. #define PSRAM_HSPI_SPIQ_SD0_IO 12
  682. #define PSRAM_HSPI_SPID_SD1_IO 13
  683. #define PSRAM_HSPI_SPIWP_SD3_IO 2
  684. #define PSRAM_HSPI_SPIHD_SD2_IO 4
  685. #endif
  686. cJSON * get_psram_gpio_list(cJSON * list){
  687. const char * psram_dev = "psram";
  688. const char * flash_dev = "flash";
  689. const char * clk = "clk";
  690. const char * cs = "cs";
  691. const char * spiq_sd0_io="spiq_sd0_io";
  692. const char * spid_sd1_io = "spid_sd1_io";
  693. const char * spiwp_sd3_io = "spiwp_sd3_io";
  694. const char * spihd_sd2_io = "spihd_sd2_io";
  695. cJSON * llist=list;
  696. uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
  697. uint32_t pkg_ver = chip_ver & 0x7;
  698. if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
  699. rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
  700. if (cfg.tieh != RTC_VDDSDIO_TIEH_1_8V) {
  701. return llist;
  702. }
  703. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,CONFIG_D2WD_PSRAM_CLK_IO,true));
  704. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,CONFIG_D2WD_PSRAM_CS_IO,true));
  705. } else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
  706. rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
  707. if (cfg.tieh != RTC_VDDSDIO_TIEH_3_3V) {
  708. return llist;
  709. }
  710. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,PICO_PSRAM_CLK_IO,true));
  711. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,CONFIG_PICO_PSRAM_CS_IO,true));
  712. } else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5)){
  713. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,CONFIG_D0WD_PSRAM_CLK_IO,true));
  714. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,CONFIG_D0WD_PSRAM_CS_IO,true));
  715. } else {
  716. ESP_LOGW(TAG, "Cant' determine GPIOs for PSRAM chip id: %d", pkg_ver);
  717. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,-1,true));
  718. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,-1,true));
  719. }
  720. const uint32_t spiconfig = ets_efuse_get_spiconfig();
  721. if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
  722. cJSON_AddItemToArray(list,get_gpio_entry(spiq_sd0_io,psram_dev,PSRAM_SPIQ_SD0_IO,true));
  723. cJSON_AddItemToArray(list,get_gpio_entry(spid_sd1_io,psram_dev,PSRAM_SPID_SD1_IO,true));
  724. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,PSRAM_SPIWP_SD3_IO,true));
  725. cJSON_AddItemToArray(list,get_gpio_entry(spihd_sd2_io,psram_dev,PSRAM_SPIHD_SD2_IO,true));
  726. } else if (spiconfig == EFUSE_SPICONFIG_HSPI_DEFAULTS) {
  727. cJSON_AddItemToArray(list,get_gpio_entry(spiq_sd0_io,psram_dev,PSRAM_HSPI_SPIQ_SD0_IO,true));
  728. cJSON_AddItemToArray(list,get_gpio_entry(spid_sd1_io,psram_dev,PSRAM_HSPI_SPID_SD1_IO,true));
  729. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,PSRAM_HSPI_SPIWP_SD3_IO,true));
  730. cJSON_AddItemToArray(list,get_gpio_entry(spihd_sd2_io,psram_dev,PSRAM_HSPI_SPIHD_SD2_IO,true));
  731. } else {
  732. cJSON_AddItemToArray(list,get_gpio_entry(spiq_sd0_io,psram_dev,EFUSE_SPICONFIG_RET_SPIQ(spiconfig),true));
  733. cJSON_AddItemToArray(list,get_gpio_entry(spid_sd1_io,psram_dev,EFUSE_SPICONFIG_RET_SPID(spiconfig),true));
  734. cJSON_AddItemToArray(list,get_gpio_entry(spihd_sd2_io,psram_dev,EFUSE_SPICONFIG_RET_SPIHD(spiconfig),true));
  735. // If flash mode is set to QIO or QOUT, the WP pin is equal the value configured in bootloader.
  736. // If flash mode is set to DIO or DOUT, the WP pin should config it via menuconfig.
  737. #if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
  738. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,CONFIG_BOOTLOADER_SPI_WP_PIN,true));
  739. #else
  740. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,CONFIG_SPIRAM_SPIWP_SD3_PIN,true));
  741. #endif
  742. }
  743. if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
  744. cJSON_AddItemToArray(list,get_gpio_entry(clk,flash_dev,SPI_IOMUX_PIN_NUM_CLK,true));
  745. cJSON_AddItemToArray(list,get_gpio_entry(cs,flash_dev,SPI_IOMUX_PIN_NUM_CS,true));
  746. } else if (spiconfig == EFUSE_SPICONFIG_HSPI_DEFAULTS) {
  747. cJSON_AddItemToArray(list,get_gpio_entry(clk,flash_dev,FLASH_HSPI_CLK_IO,true));
  748. cJSON_AddItemToArray(list,get_gpio_entry(cs,flash_dev,FLASH_HSPI_CS_IO,true));
  749. } else {
  750. cJSON_AddItemToArray(list,get_gpio_entry(clk,flash_dev,EFUSE_SPICONFIG_RET_SPICLK(spiconfig),true));
  751. cJSON_AddItemToArray(list,get_gpio_entry(cs,flash_dev,EFUSE_SPICONFIG_RET_SPICS0(spiconfig),true));
  752. }
  753. return llist;
  754. }
  755. /****************************************************************************************
  756. *
  757. */
  758. cJSON * get_gpio_list() {
  759. gpio_num_t gpio_num;
  760. if(gpio_list){
  761. cJSON_Delete(gpio_list);
  762. }
  763. gpio_list = cJSON_CreateArray();
  764. #ifndef CONFIG_BAT_LOCKED
  765. char *bat_config = config_alloc_get_default(NVS_TYPE_STR, "bat_config", NULL, 0);
  766. if (bat_config) {
  767. char *p;
  768. int channel;
  769. if ((p = strcasestr(bat_config, "channel") ) != NULL) {
  770. channel = atoi(strchr(p, '=') + 1);
  771. if(channel != -1){
  772. if(adc1_pad_get_io_num(channel,&gpio_num )==ESP_OK){
  773. cJSON_AddItemToArray(gpio_list,get_gpio_entry("bat","other",gpio_num,false));
  774. }
  775. }
  776. }
  777. free(bat_config);
  778. }
  779. #else
  780. if(adc1_pad_get_io_num(CONFIG_BAT_CHANNEL,&gpio_num )==ESP_OK){
  781. cJSON_AddItemToArray(gpio_list,get_gpio_entry("bat","other",gpio_num,true));
  782. }
  783. #endif
  784. gpio_list = get_GPIO_nvs_list(gpio_list);
  785. char * spdif_config = config_spdif_get_string();
  786. gpio_list=get_GPIO_from_string(spdif_config,"spdif", gpio_list, is_spdif_config_locked());
  787. free(spdif_config);
  788. gpio_list=get_Display_GPIO(gpio_list);
  789. gpio_list=get_SPI_GPIO(gpio_list);
  790. gpio_list=get_I2C_GPIO(gpio_list);
  791. gpio_list=get_DAC_GPIO(gpio_list);
  792. gpio_list=get_psram_gpio_list(gpio_list);
  793. return gpio_list;
  794. }