accessors.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214
  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 "cJSON.h"
  17. #include "driver/gpio.h"
  18. #include "stdbool.h"
  19. #include "driver/adc.h"
  20. #include "esp_attr.h"
  21. #include "soc/spi_periph.h"
  22. #include "esp_err.h"
  23. #include "soc/rtc.h"
  24. #include "sdkconfig.h"
  25. #include "soc/efuse_periph.h"
  26. #include "driver/gpio.h"
  27. #include "driver/spi_common_internal.h"
  28. #if CONFIG_IDF_TARGET_ESP32
  29. #include "esp32/rom/efuse.h"
  30. #endif
  31. #include "tools.h"
  32. #include "monitor.h"
  33. #include "messaging.h"
  34. #include "network_ethernet.h"
  35. static const char *TAG = "services";
  36. const char *i2c_name_type="I2C";
  37. const char *spi_name_type="SPI";
  38. cJSON * gpio_list=NULL;
  39. #define min(a,b) (((a) < (b)) ? (a) : (b))
  40. #ifndef QUOTE
  41. #define QUOTE(name) #name
  42. #endif
  43. #ifndef STR
  44. #define STR(macro) QUOTE(macro)
  45. #endif
  46. extern cJSON * get_gpio_list(bool refresh);
  47. bool are_statistics_enabled(){
  48. #if defined(CONFIG_FREERTOS_USE_TRACE_FACILITY) && defined (CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS)
  49. return true;
  50. #endif
  51. return false;
  52. }
  53. /****************************************************************************************
  54. *
  55. */
  56. static char * config_spdif_get_string(){
  57. return config_alloc_get_str("spdif_config", CONFIG_SPDIF_CONFIG, "bck=" STR(CONFIG_SPDIF_BCK_IO)
  58. ",ws=" STR(CONFIG_SPDIF_WS_IO) ",do=" STR(CONFIG_SPDIF_DO_IO));
  59. }
  60. /****************************************************************************************
  61. *
  62. */
  63. static char * get_dac_config_string(){
  64. return config_alloc_get_str("dac_config", CONFIG_DAC_CONFIG, "model=i2s,bck=" STR(CONFIG_I2S_BCK_IO)
  65. ",ws=" STR(CONFIG_I2S_WS_IO) ",do=" STR(CONFIG_I2S_DO_IO)
  66. ",sda=" STR(CONFIG_I2C_SDA) ",scl=" STR(CONFIG_I2C_SCL)
  67. ",mute=" STR(CONFIG_MUTE_GPIO));
  68. }
  69. /****************************************************************************************
  70. *
  71. */
  72. bool is_dac_config_locked(){
  73. #if ( defined CONFIG_DAC_CONFIG )
  74. if(strlen(CONFIG_DAC_CONFIG) > 0){
  75. return true;
  76. }
  77. #endif
  78. #if defined(CONFIG_I2S_BCK_IO) && CONFIG_I2S_BCK_IO>0
  79. return true;
  80. #endif
  81. return false;
  82. }
  83. /****************************************************************************************
  84. *
  85. */
  86. bool is_spdif_config_locked(){
  87. #if ( defined CONFIG_SPDIF_CONFIG )
  88. if(strlen(CONFIG_SPDIF_CONFIG) > 0){
  89. return true;
  90. }
  91. #endif
  92. #if defined(CONFIG_SPDIF_BCK_IO) && CONFIG_SPDIF_BCK_IO>0
  93. return true;
  94. #endif
  95. return false;
  96. }
  97. /****************************************************************************************
  98. * Set pin from config string
  99. */
  100. static void set_i2s_pin(char *config, i2s_pin_config_t *pin_config) {
  101. pin_config->bck_io_num = pin_config->ws_io_num = pin_config->data_out_num = pin_config->data_in_num = -1;
  102. PARSE_PARAM(config, "bck", '=', pin_config->bck_io_num);
  103. PARSE_PARAM(config, "ws", '=', pin_config->ws_io_num);
  104. PARSE_PARAM(config, "do", '=', pin_config->data_out_num);
  105. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
  106. pin_config->mck_io_num = strcasestr(config, "mck") ? 0 : -1;
  107. PARSE_PARAM(config, "mck", '=', pin_config->mck_io_num);
  108. #endif
  109. }
  110. /****************************************************************************************
  111. * Get i2s config structure from config string
  112. */
  113. const i2s_platform_config_t * config_i2s_get_from_str(char * dac_config ){
  114. static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_pin;
  115. memset(&i2s_dac_pin, 0xff, sizeof(i2s_dac_pin));
  116. set_i2s_pin(dac_config, &i2s_dac_pin.pin);
  117. strcpy(i2s_dac_pin.model, "i2s");
  118. char * p=NULL;
  119. PARSE_PARAM(dac_config, "i2c", '=', i2s_dac_pin.i2c_addr);
  120. PARSE_PARAM(dac_config, "sda", '=', i2s_dac_pin.sda);
  121. PARSE_PARAM(dac_config, "scl", '=', i2s_dac_pin.scl);
  122. PARSE_PARAM_STR(dac_config, "model", '=', i2s_dac_pin.model, 31);
  123. if ((p = strcasestr(dac_config, "mute"))) {
  124. char mute[8] = "";
  125. sscanf(p, "%*[^=]=%7[^,]", mute);
  126. i2s_dac_pin.mute_gpio = atoi(mute);
  127. PARSE_PARAM(p, "mute", ':', i2s_dac_pin.mute_level);
  128. }
  129. return &i2s_dac_pin;
  130. }
  131. /****************************************************************************************
  132. * Get eth config structure from config string
  133. */
  134. const eth_config_t * config_eth_get_from_str(char* config ){
  135. static EXT_RAM_ATTR eth_config_t eth_config;
  136. eth_config.rst = eth_config.intr = -1;
  137. PARSE_PARAM_STR(config, "model", '=', eth_config.model, 15);
  138. PARSE_PARAM(config, "rst", '=', eth_config.rst);
  139. // RMII
  140. PARSE_PARAM(config, "mdc", '=', eth_config.mdc);
  141. PARSE_PARAM(config, "mdio", '=', eth_config.mdio);
  142. // SPI
  143. PARSE_PARAM(config, "intr", '=', eth_config.intr);
  144. PARSE_PARAM(config, "cs", '=', eth_config.cs);
  145. PARSE_PARAM(config, "speed", '=', eth_config.speed);
  146. /* not used as SPI must be shared
  147. PARSE_PARAM(config, "mosi", '=', eth_config.mosi);
  148. PARSE_PARAM(config, "miso", '=', eth_config.miso);
  149. PARSE_PARAM(config, "clk", '=', eth_config.clk);
  150. PARSE_PARAM(config, "host", '=', eth_config.host);
  151. */
  152. // only system host is available
  153. eth_config.host = spi_system_host;
  154. eth_config.valid = true;
  155. if(!eth_config.model || strlen(eth_config.model)==0){
  156. eth_config.valid = false;
  157. return &eth_config;
  158. }
  159. network_ethernet_driver_t* network_driver = network_ethernet_driver_autodetect(eth_config.model);
  160. if(!network_driver || !network_driver->valid){
  161. messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Ethernet config invalid: model %s %s",eth_config.model,network_driver?"was not compiled in":"was not found");
  162. eth_config.valid = false;
  163. }
  164. if(network_driver){
  165. eth_config.rmii = network_driver->rmii;
  166. eth_config.spi = network_driver->spi;
  167. if(network_driver->rmii){
  168. if(!GPIO_IS_VALID_GPIO(eth_config.mdio) || !GPIO_IS_VALID_GPIO(eth_config.mdc)){
  169. messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Ethernet config invalid: %s %s",!GPIO_IS_VALID_GPIO(eth_config.mdc)?"Invalid MDC":"",!GPIO_IS_VALID_GPIO(eth_config.mdio)?"Invalid mdio":"");
  170. eth_config.valid = false;
  171. }
  172. }
  173. else if(network_driver->spi){
  174. if(!GPIO_IS_VALID_GPIO(eth_config.cs)){
  175. messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Ethernet config invalid: invalid CS pin");
  176. return false;
  177. }
  178. }
  179. }
  180. return &eth_config;
  181. }
  182. /****************************************************************************************
  183. * Get spdif config structure
  184. */
  185. const i2s_platform_config_t * config_spdif_get( ){
  186. char * spdif_config = config_spdif_get_string();
  187. static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_config;
  188. memcpy(&i2s_dac_config, config_i2s_get_from_str(spdif_config), sizeof(i2s_dac_config));
  189. free(spdif_config);
  190. return &i2s_dac_config;
  191. }
  192. /****************************************************************************************
  193. * Get dac config structure
  194. */
  195. const i2s_platform_config_t * config_dac_get(){
  196. char * spdif_config = get_dac_config_string();
  197. static EXT_RAM_ATTR i2s_platform_config_t i2s_dac_config;
  198. memcpy(&i2s_dac_config, config_i2s_get_from_str(spdif_config), sizeof(i2s_dac_config));
  199. free(spdif_config);
  200. return &i2s_dac_config;
  201. }
  202. /****************************************************************************************
  203. * Get ethernet config structure
  204. */
  205. const eth_config_t * config_eth_get( ){
  206. char * config = config_alloc_get_str("eth_config", CONFIG_ETH_CONFIG, "rst=" STR(CONFIG_ETH_PHY_RST_IO)
  207. #if defined(ETH_LAN8720)
  208. #else
  209. #if defined(CONFIG_ETH_USE_SPI_ETHERNET)
  210. #if defined(CONFIG_ETH_DM9051)
  211. ",model=dm9051"
  212. #elif defined(CONFIG_ETH_W5500)
  213. ",model=w5500"
  214. #endif
  215. ",host=" STR(CONFIG_ETH_SPI_HOST) ",cs=" STR(CONFIG_ETH_SPI_CS_IO)
  216. ",mosi=" STR(CONFIG_ETH_SPI_MOSI_IO) ",miso=" STR(CONFIG_ETH_SPI_MISO_IO)
  217. ",intr=" STR(CONFIG_ETH_SPI_INTR_IO)
  218. ",clk=" STR(CONFIG_ETH_SPI_CLK_IO) ",speed=" STR(CONFIG_ETH_SPI_SPEED)
  219. #elif defined(CONFIG_ETH_PHY_INTERFACE_RMII)
  220. ",model=lan8720, tx_en=21, tx0=19, tx1=22, rx0=25, rx1=26, crs_dv=27"
  221. #endif
  222. #endif
  223. ",mdc=" STR(CONFIG_ETH_MDC_IO) ",mdio=" STR(CONFIG_ETH_MDIO_IO)) ;
  224. if(config && strlen(config)>0){
  225. ESP_LOGD(TAG,"Parsing ethernet configuration %s", config);
  226. }
  227. static EXT_RAM_ATTR eth_config_t eth_config;
  228. memcpy(&eth_config, config_eth_get_from_str(config), sizeof(eth_config));
  229. FREE_AND_NULL(config);
  230. return &eth_config;
  231. }
  232. /****************************************************************************************
  233. * Get ethernet config structure and assign to eth config structure
  234. */
  235. void config_eth_init( eth_config_t * target ){
  236. const eth_config_t * source = config_eth_get();
  237. memcpy(target,source,sizeof(eth_config_t));
  238. }
  239. /****************************************************************************************
  240. *
  241. */
  242. esp_err_t config_i2c_set(const i2c_config_t * config, int port){
  243. int buffer_size=255;
  244. esp_err_t err=ESP_OK;
  245. char * config_buffer=malloc_init_external(buffer_size);
  246. if(config_buffer) {
  247. 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);
  248. log_send_messaging(MESSAGING_INFO,"Updating I2C configuration to %s",config_buffer);
  249. err = config_set_value(NVS_TYPE_STR, "i2c_config", config_buffer);
  250. if(err!=ESP_OK){
  251. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  252. }
  253. free(config_buffer);
  254. }
  255. return err;
  256. }
  257. /****************************************************************************************
  258. *
  259. */
  260. esp_err_t config_rotary_set(rotary_struct_t * config){
  261. int buffer_size=512;
  262. esp_err_t err=ESP_OK;
  263. char * config_buffer=malloc_init_external(buffer_size);
  264. char * config_buffer2=malloc_init_external(buffer_size);
  265. if(config_buffer && config_buffer2) {
  266. snprintf(config_buffer,buffer_size,"A=%i,B=%i",config->A, config->B);
  267. if(config->SW >=0 ){
  268. snprintf(config_buffer2,buffer_size,"%s,SW=%i",config_buffer,config->SW);
  269. strcpy(config_buffer,config_buffer2);
  270. }
  271. if(config->knobonly){
  272. strncat(config_buffer,",knobonly",buffer_size);
  273. if(config->timer>0){
  274. snprintf(config_buffer2,buffer_size,"%s=%i",config_buffer,config->timer);
  275. strcpy(config_buffer,config_buffer2);
  276. }
  277. }
  278. if(config->volume_lock){
  279. strncat(config_buffer,",volume",buffer_size);
  280. }
  281. if(config->longpress){
  282. strncat(config_buffer,",longpress",buffer_size);
  283. }
  284. log_send_messaging(MESSAGING_INFO,"Updating rotary configuration to %s",config_buffer);
  285. err = config_set_value(NVS_TYPE_STR, "rotary_config", config_buffer);
  286. if(err!=ESP_OK){
  287. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  288. }
  289. }
  290. else {
  291. err = ESP_ERR_NO_MEM;
  292. }
  293. FREE_AND_NULL(config_buffer);
  294. FREE_AND_NULL(config_buffer2);
  295. return err;
  296. }
  297. /****************************************************************************************
  298. *
  299. */
  300. esp_err_t config_ledvu_set(ledvu_struct_t * config){
  301. int buffer_size=512;
  302. esp_err_t err=ESP_OK;
  303. char * config_buffer=malloc_init_external(buffer_size);
  304. if(config_buffer) {
  305. snprintf(config_buffer,buffer_size,"%s,length=%i,gpio=%i",config->type, config->length, config->gpio);
  306. log_send_messaging(MESSAGING_INFO,"Updating ledvu configuration to %s",config_buffer);
  307. err = config_set_value(NVS_TYPE_STR, "led_vu_config", config_buffer);
  308. if(err!=ESP_OK){
  309. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  310. }
  311. }
  312. else {
  313. err = ESP_ERR_NO_MEM;
  314. }
  315. FREE_AND_NULL(config_buffer);
  316. return err;
  317. }
  318. /****************************************************************************************
  319. *
  320. */
  321. esp_err_t config_display_set(const display_config_t * config){
  322. int buffer_size=512;
  323. esp_err_t err=ESP_OK;
  324. char * config_buffer=malloc_init_external(buffer_size);
  325. char * config_buffer2=malloc_init_external(buffer_size);
  326. if(config_buffer && config_buffer2) {
  327. snprintf(config_buffer,buffer_size,"%s,width=%i,height=%i",config->type,config->width,config->height);
  328. if(strcasecmp("I2C",config->type)==0){
  329. if(config->address>0 ){
  330. snprintf(config_buffer2,buffer_size,"%s,address=%i",config_buffer,config->address);
  331. strcpy(config_buffer,config_buffer2);
  332. }
  333. }
  334. else {
  335. if(config->CS_pin >=0 ){
  336. snprintf(config_buffer2,buffer_size,"%s,cs=%i",config_buffer,config->CS_pin);
  337. strcpy(config_buffer,config_buffer2);
  338. }
  339. }
  340. if(config->RST_pin >=0 ){
  341. snprintf(config_buffer2,buffer_size,"%s,reset=%i",config_buffer,config->RST_pin);
  342. strcpy(config_buffer,config_buffer2);
  343. }
  344. // I2C,width=<pixels>,height=<pixels>[address=<i2c_address>][,reset=<gpio>][,HFlip][,VFlip][driver=SSD1306|SSD1326[:1|4]|SSD1327|SH1106]
  345. // 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]]
  346. if(config->back >=0 ){
  347. snprintf(config_buffer2,buffer_size,"%s,back=%i",config_buffer,config->back);
  348. strcpy(config_buffer,config_buffer2);
  349. }
  350. if(config->speed >0 && strcasecmp("SPI",config->type)==0){
  351. snprintf(config_buffer2,buffer_size,"%s,speed=%i",config_buffer,config->speed);
  352. strcpy(config_buffer,config_buffer2);
  353. }
  354. if(config->mode >=0 && strcasecmp("SPI",config->type)==0){
  355. snprintf(config_buffer2,buffer_size,"%s,mode=%i",config_buffer,config->mode);
  356. strcpy(config_buffer,config_buffer2);
  357. }
  358. snprintf(config_buffer2,buffer_size,"%s,driver=%s%s%s%s",config_buffer,config->drivername,config->hflip?",HFlip":"",config->vflip?",VFlip":"",config->rotate?",rotate":"");
  359. strcpy(config_buffer,config_buffer2);
  360. log_send_messaging(MESSAGING_INFO,"Updating display configuration to %s",config_buffer);
  361. err = config_set_value(NVS_TYPE_STR, "display_config", config_buffer);
  362. if(err!=ESP_OK){
  363. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  364. }
  365. }
  366. else {
  367. err = ESP_ERR_NO_MEM;
  368. }
  369. FREE_AND_NULL(config_buffer);
  370. FREE_AND_NULL(config_buffer2);
  371. return err;
  372. }
  373. /****************************************************************************************
  374. *
  375. */
  376. esp_err_t config_i2s_set(const i2s_platform_config_t * config, const char * nvs_name){
  377. int buffer_size=255;
  378. esp_err_t err=ESP_OK;
  379. char * config_buffer=malloc_init_external(buffer_size);
  380. char * config_buffer2=malloc_init_external(buffer_size);
  381. if(config_buffer && config_buffer2) {
  382. 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);
  383. if(config->mute_gpio>=0){
  384. snprintf(config_buffer2,buffer_size,"%s,mute=%u:%u",config_buffer,config->mute_gpio,config->mute_level);
  385. strcpy(config_buffer,config_buffer2);
  386. }
  387. if(config->sda>=0){
  388. snprintf(config_buffer2,buffer_size,"%s,sda=%u,scl=%u",config_buffer,config->sda,config->scl);
  389. strcpy(config_buffer,config_buffer2);
  390. }
  391. if(config->i2c_addr>0){
  392. snprintf(config_buffer2,buffer_size,"%s,i2c=%u",config_buffer,config->i2c_addr);
  393. strcpy(config_buffer,config_buffer2);
  394. }
  395. log_send_messaging(MESSAGING_INFO,"Updating dac configuration to %s",config_buffer);
  396. err = config_set_value(NVS_TYPE_STR, nvs_name, config_buffer);
  397. if(err!=ESP_OK){
  398. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  399. }
  400. }
  401. else {
  402. err = ESP_ERR_NO_MEM;
  403. }
  404. FREE_AND_NULL(config_buffer);
  405. FREE_AND_NULL(config_buffer2);
  406. return err;
  407. }
  408. /****************************************************************************************
  409. *
  410. */
  411. esp_err_t config_spdif_set(const i2s_platform_config_t * config){
  412. int buffer_size=255;
  413. esp_err_t err=ESP_OK;
  414. char * config_buffer=malloc_init_external(buffer_size);
  415. if(config_buffer ) {
  416. 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);
  417. log_send_messaging(MESSAGING_INFO,"Updating SPDIF configuration to %s",config_buffer);
  418. err = config_set_value(NVS_TYPE_STR, "spdif_config", config_buffer);
  419. if(err!=ESP_OK){
  420. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  421. }
  422. }
  423. else {
  424. err = ESP_ERR_NO_MEM;
  425. }
  426. FREE_AND_NULL(config_buffer);
  427. return err;
  428. }
  429. /****************************************************************************************
  430. *
  431. */
  432. esp_err_t config_spi_set(const spi_bus_config_t * config, int host, int dc){
  433. int buffer_size=255;
  434. esp_err_t err = ESP_OK;
  435. char * config_buffer=malloc_init_external(buffer_size);
  436. if(config_buffer) {
  437. snprintf(config_buffer,buffer_size,"data=%u,clk=%u,dc=%u,host=%u,miso=%d",config->mosi_io_num,config->sclk_io_num,dc,host,config->miso_io_num);
  438. log_send_messaging(MESSAGING_INFO,"Updating SPI configuration to %s",config_buffer);
  439. err = config_set_value(NVS_TYPE_STR, "spi_config", config_buffer);
  440. if(err!=ESP_OK){
  441. log_send_messaging(MESSAGING_ERROR,"Error: %s",esp_err_to_name(err));
  442. }
  443. free(config_buffer);
  444. }
  445. return err;
  446. }
  447. /****************************************************************************************
  448. *
  449. */
  450. const display_config_t * config_display_get(){
  451. static display_config_t dstruct = {
  452. .back = -1,
  453. .CS_pin = -1,
  454. .RST_pin = -1,
  455. .depth = -1,
  456. .address = 0,
  457. .drivername = NULL,
  458. .height = 0,
  459. .width = 0,
  460. .vflip = false,
  461. .hflip = false,
  462. .type = NULL,
  463. .speed = 0,
  464. .rotate = false,
  465. .invert = false,
  466. .colorswap = 0,
  467. .mode = 0,
  468. };
  469. char *config = config_alloc_get(NVS_TYPE_STR, "display_config");
  470. if (!config) {
  471. return NULL;
  472. }
  473. char * p=NULL;
  474. if ((p = strcasestr(config, "driver")) != NULL){
  475. sscanf(p, "%*[^:]:%u", &dstruct.depth);
  476. dstruct.drivername = display_conf_get_driver_name(strchr(p, '=') + 1);
  477. }
  478. PARSE_PARAM(config, "width", '=', dstruct.width);
  479. PARSE_PARAM(config, "height", '=', dstruct.height);
  480. PARSE_PARAM(config, "reset", '=', dstruct.RST_pin);
  481. PARSE_PARAM(config, "address", '=', dstruct.address);
  482. PARSE_PARAM(config, "cs", '=', dstruct.CS_pin);
  483. PARSE_PARAM(config, "speed", '=', dstruct.speed);
  484. PARSE_PARAM(config, "back", '=', dstruct.back);
  485. PARSE_PARAM(config, "mode", '=', dstruct.mode);
  486. if (strstr(config, "I2C") ) dstruct.type=i2c_name_type;
  487. if (strstr(config, "SPI") ) dstruct.type=spi_name_type;
  488. dstruct.hflip= strcasestr(config, "HFlip") ? true : false;
  489. dstruct.vflip= strcasestr(config, "VFlip") ? true : false;
  490. dstruct.rotate= strcasestr(config, "rotate") ? true : false;
  491. dstruct.invert= strcasestr(config, "invert") ? true : false;
  492. dstruct.colorswap= strcasestr(config, "cswap") ? 1 : 0;
  493. return &dstruct;
  494. }
  495. /****************************************************************************************
  496. *
  497. */
  498. const i2c_config_t * config_i2c_get(int * i2c_port) {
  499. char *nvs_item;
  500. static i2c_config_t i2c = {
  501. .mode = I2C_MODE_MASTER,
  502. .sda_io_num = -1,
  503. .sda_pullup_en = GPIO_PULLUP_ENABLE,
  504. .scl_io_num = -1,
  505. .scl_pullup_en = GPIO_PULLUP_ENABLE,
  506. .master.clk_speed = 0,
  507. };
  508. i2c.master.clk_speed = i2c_system_speed;
  509. nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
  510. if (nvs_item) {
  511. PARSE_PARAM(nvs_item, "scl", '=', i2c.scl_io_num);
  512. PARSE_PARAM(nvs_item, "sda", '=', i2c.sda_io_num);
  513. PARSE_PARAM(nvs_item, "speed", '=', i2c.master.clk_speed);
  514. PARSE_PARAM(nvs_item, "port", '=', i2c_system_port);
  515. free(nvs_item);
  516. }
  517. if(i2c_port) {
  518. #ifdef CONFIG_I2C_LOCKED
  519. *i2c_port= I2C_NUM_1;
  520. #else
  521. *i2c_port=i2c_system_port;
  522. #endif
  523. }
  524. return &i2c;
  525. }
  526. /****************************************************************************************
  527. * Get IO expander config structure from config string
  528. */
  529. const gpio_exp_config_t* config_gpio_exp_get(int index) {
  530. char *nvs_item, *item, *p;
  531. static gpio_exp_config_t config;
  532. // re-initialize config every time
  533. memset(&config, 0, sizeof(config));
  534. config.intr = -1; config.count = 16; config.base = GPIO_NUM_MAX; config.phy.port = i2c_system_port; config.phy.host = spi_system_host;
  535. nvs_item = config_alloc_get(NVS_TYPE_STR, "gpio_exp_config");
  536. if (!nvs_item || !*nvs_item) return NULL;
  537. // search index items
  538. for (item = strtok(nvs_item, ";"); index && item; index--) {
  539. if ((item = strtok(NULL, ";")) == NULL) {
  540. free(nvs_item);
  541. return NULL;
  542. }
  543. }
  544. PARSE_PARAM(item, "addr", '=', config.phy.addr);
  545. PARSE_PARAM(item, "cs", '=', config.phy.cs_pin);
  546. PARSE_PARAM(item, "speed", '=', config.phy.speed);
  547. PARSE_PARAM(item, "intr", '=', config.intr);
  548. PARSE_PARAM(item, "base", '=', config.base);
  549. PARSE_PARAM(item, "count", '=', config.count);
  550. PARSE_PARAM_STR(item, "model", '=', config.model, sizeof(config.model)-1);
  551. if ((p = strcasestr(item, "port")) != NULL) {
  552. char port[8] = "";
  553. sscanf(p, "%*[^=]=%7[^,]", port);
  554. if (strcasestr(port, "dac")) config.phy.port = 0;
  555. }
  556. free(nvs_item);
  557. return &config;
  558. }
  559. /****************************************************************************************
  560. *
  561. */
  562. const gpio_with_level_t * get_gpio_struct_member(const char * nvs_item, const char * name){
  563. static gpio_with_level_t gpio_member={
  564. .gpio=-1,
  565. .level=0
  566. };
  567. if(!nvs_item) return &gpio_member;
  568. const char * p=nvs_item;
  569. char type[20]={0};
  570. int match=0;
  571. do {
  572. if ((match=sscanf(p, "%d=%19[^,:]:%d", &gpio_member.gpio, type,&gpio_member.level)) >0 && (GPIO_IS_VALID_GPIO(gpio_member.gpio) || gpio_member.gpio==GPIO_NUM_NC) && strcasestr(type,name)){
  573. return &gpio_member;
  574. }
  575. p = strchr(p, ',');
  576. } while (p++);
  577. gpio_member.gpio=-1;
  578. gpio_member.level=0;
  579. return &gpio_member;
  580. }
  581. #define HANDLE_GPIO_STRUCT_MEMBER(name,fixval) memcpy(&gpio_struct.name, get_gpio_struct_member(nvs_item, QUOTE(name)), sizeof(gpio_struct.name)); gpio_struct.name.fixed=fixval
  582. #define ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(array,structvar,name,type) if(((set_GPIO_struct_t *)structvar)->name.gpio>=0){cJSON_AddItemToArray(array,get_gpio_entry(QUOTE(name),type,((set_GPIO_struct_t *)structvar)->name.gpio, ((set_GPIO_struct_t *)structvar)->name.fixed));}
  583. /****************************************************************************************
  584. *
  585. */
  586. const set_GPIO_struct_t * get_gpio_struct(){
  587. static set_GPIO_struct_t gpio_struct;
  588. char * nvs_item=config_alloc_get(NVS_TYPE_STR, "set_GPIO");
  589. #ifdef CONFIG_LED_GREEN_GPIO_LEVEL
  590. gpio_struct.green.level = CONFIG_LED_GREEN_GPIO_LEVEL;
  591. #endif
  592. #ifdef CONFIG_LED_GREEN_GPIO
  593. gpio_struct.green.gpio = CONFIG_LED_GREEN_GPIO;
  594. #endif
  595. #ifdef CONFIG_LED_RED_GPIO_LEVEL
  596. gpio_struct.green.level = CONFIG_LED_RED_GPIO_LEVEL;
  597. #endif
  598. #ifdef CONFIG_LED_RED_GPIO
  599. gpio_struct.red.gpio = CONFIG_LED_RED_GPIO;
  600. #endif
  601. #if defined(CONFIG_POWER_GPIO) && CONFIG_POWER_GPIO != -1
  602. gpio_struct.power.gpio = CONFIG_POWER_GPIO;
  603. #endif
  604. #ifdef CONFIG_POWER_GPIO_LEVEL
  605. gpio_struct.power.level = CONFIG_POWER_GPIO_LEVEL;
  606. #endif
  607. if(nvs_item){
  608. HANDLE_GPIO_STRUCT_MEMBER(amp,false);
  609. #ifndef CONFIG_LED_LOCKED
  610. HANDLE_GPIO_STRUCT_MEMBER(green,false);
  611. HANDLE_GPIO_STRUCT_MEMBER(red,false);
  612. #endif
  613. HANDLE_GPIO_STRUCT_MEMBER(jack,false);
  614. HANDLE_GPIO_STRUCT_MEMBER(spkfault,false);
  615. HANDLE_GPIO_STRUCT_MEMBER(vcc,false);
  616. HANDLE_GPIO_STRUCT_MEMBER(gnd,false);
  617. HANDLE_GPIO_STRUCT_MEMBER(ir,false);
  618. HANDLE_GPIO_STRUCT_MEMBER(power,false);
  619. free(nvs_item);
  620. }
  621. #ifdef CONFIG_LED_LOCKED
  622. gpio_struct.red.fixed=true;
  623. gpio_struct.green.fixed=true;
  624. #endif
  625. #ifdef CONFIG_JACK_LOCKED
  626. gpio_struct.jack.gpio=CONFIG_JACK_GPIO;
  627. gpio_struct.jack.fixed=true;
  628. gpio_struct.jack.level=CONFIG_JACK_GPIO_LEVEL;
  629. #endif
  630. #ifdef CONFIG_SPKFAULT_LOCKED
  631. gpio_struct.spkfault.gpio=CONFIG_SPKFAULT_GPIO;
  632. gpio_struct.spkfault.fixed=true;
  633. gpio_struct.spkfault.level=CONFIG_SPKFAULT_GPIO_LEVEL;
  634. #endif
  635. return &gpio_struct;
  636. }
  637. /****************************************************************************************
  638. *
  639. */
  640. const spi_bus_config_t * config_spi_get(spi_host_device_t * spi_host) {
  641. char *nvs_item;
  642. // don't memset all to 0xff as it's more than just GPIO
  643. static spi_bus_config_t spi = {
  644. .mosi_io_num = -1,
  645. .sclk_io_num = -1,
  646. .miso_io_num = -1,
  647. .quadwp_io_num = -1,
  648. .quadhd_io_num = -1
  649. };
  650. nvs_item = config_alloc_get_str("spi_config", CONFIG_SPI_CONFIG, NULL);
  651. if (nvs_item) {
  652. PARSE_PARAM(nvs_item, "data", '=', spi.mosi_io_num);
  653. PARSE_PARAM(nvs_item, "mosi", '=', spi.mosi_io_num);
  654. PARSE_PARAM(nvs_item, "miso", '=', spi.miso_io_num);
  655. PARSE_PARAM(nvs_item, "clk", '=', spi.sclk_io_num);
  656. PARSE_PARAM(nvs_item, "dc", '=', spi_system_dc_gpio);
  657. // only VSPI (1) can be used as Flash and PSRAM run at 80MHz
  658. // if ((p = strcasestr(nvs_item, "host")) != NULL) spi_system_host = atoi(strchr(p, '=') + 1);
  659. free(nvs_item);
  660. }
  661. if(spi_host) *spi_host = spi_system_host;
  662. return &spi;
  663. }
  664. /****************************************************************************************
  665. *
  666. */
  667. void parse_set_GPIO(void (*cb)(int gpio, char *value)) {
  668. char *nvs_item, *p, type[16];
  669. int gpio;
  670. if ((nvs_item = config_alloc_get(NVS_TYPE_STR, "set_GPIO")) == NULL) return;
  671. p = nvs_item;
  672. do {
  673. if (sscanf(p, "%d=%15[^,]", &gpio, type) > 0) cb(gpio, type);
  674. p = strchr(p, ',');
  675. } while (p++);
  676. free(nvs_item);
  677. }
  678. /****************************************************************************************
  679. *
  680. */
  681. const rotary_struct_t * config_rotary_get() {
  682. static rotary_struct_t rotary={ .A = -1, .B = -1, .SW = -1, .longpress = false, .knobonly=false,.timer=0,.volume_lock=false};
  683. char *config = config_alloc_get_default(NVS_TYPE_STR, "rotary_config", NULL, 0);
  684. if (config && *config) {
  685. char *p;
  686. // parse config
  687. PARSE_PARAM(config, "A", '=', rotary.A);
  688. PARSE_PARAM(config, "B", '=', rotary.B);
  689. PARSE_PARAM(config, "SW", '=', rotary.SW);
  690. if ((p = strcasestr(config, "knobonly")) != NULL) {
  691. p = strchr(p, '=');
  692. rotary.knobonly = true;
  693. rotary.timer = p ? atoi(p + 1) : 350;
  694. rotary.longpress = false;
  695. } else {
  696. rotary.knobonly = false;
  697. rotary.timer = 0;
  698. if ((p = strcasestr(config, "volume")) != NULL) rotary.volume_lock = true;
  699. if ((p = strcasestr(config, "longpress")) != NULL) rotary.longpress = true;
  700. }
  701. free(config);
  702. }
  703. return &rotary;
  704. }
  705. /****************************************************************************************
  706. *
  707. */
  708. const ledvu_struct_t * config_ledvu_get() {
  709. static ledvu_struct_t ledvu={ .type = "WS2812", .gpio = -1, .length = 0};
  710. char *config = config_alloc_get_default(NVS_TYPE_STR, "led_vu_config", NULL, 0);
  711. if (config && *config) {
  712. char *p;
  713. // ToDo: Add code for future support of alternate led types
  714. if ((p = strcasestr(config, "gpio")) != NULL) ledvu.gpio = atoi(strchr(p, '=') + 1);
  715. if ((p = strcasestr(config, "length")) != NULL) ledvu.length = atoi(strchr(p, '=') + 1);
  716. free(config);
  717. }
  718. return &ledvu;
  719. }
  720. /****************************************************************************************
  721. *
  722. */
  723. cJSON * get_gpio_entry(const char * name, const char * prefix, int gpio, bool fixed){
  724. cJSON * entry = cJSON_CreateObject();
  725. cJSON_AddNumberToObject(entry,"gpio",gpio);
  726. cJSON_AddStringToObject(entry,"name",name);
  727. cJSON_AddStringToObject(entry,"group",prefix);
  728. cJSON_AddBoolToObject(entry,"fixed",fixed);
  729. return entry;
  730. }
  731. /****************************************************************************************
  732. *
  733. */
  734. cJSON * add_gpio_for_value(cJSON * list,const char * name,int gpio, const char * prefix, bool fixed){
  735. cJSON * llist = list?list:cJSON_CreateArray();
  736. if(GPIO_IS_VALID_GPIO(gpio) && gpio>0){
  737. cJSON_AddItemToArray(llist,get_gpio_entry(name,prefix,gpio,fixed));
  738. }
  739. return llist;
  740. }
  741. /****************************************************************************************
  742. *
  743. */
  744. cJSON * add_gpio_for_name(cJSON * list,const char * nvs_entry,const char * name, const char * prefix, bool fixed){
  745. cJSON * llist = list?list:cJSON_CreateArray();
  746. int gpioNum=0;
  747. PARSE_PARAM(nvs_entry, name, '=', gpioNum);
  748. if(gpioNum>=0){
  749. cJSON_AddItemToArray(llist,get_gpio_entry(name,prefix,gpioNum,fixed));
  750. }
  751. return llist;
  752. }
  753. /****************************************************************************************
  754. *
  755. */
  756. cJSON * get_GPIO_nvs_list(cJSON * list) {
  757. cJSON * ilist = list?list:cJSON_CreateArray();
  758. const set_GPIO_struct_t * gpios = get_gpio_struct();
  759. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,vcc,"other");
  760. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,gnd,"other");
  761. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,amp,"other");
  762. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,ir,"other");
  763. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,jack,"other");
  764. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,green,"other");
  765. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,red,"other");
  766. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,power,"other");
  767. ADD_GPIO_STRUCT_MEMBER_TO_ARRAY(ilist,gpios,spkfault,"other");
  768. return ilist;
  769. }
  770. /****************************************************************************************
  771. *
  772. */
  773. cJSON * get_DAC_GPIO(cJSON * list){
  774. cJSON * llist = list;
  775. if(!llist){
  776. llist = cJSON_CreateArray();
  777. }
  778. const i2s_platform_config_t * i2s_config= config_dac_get();
  779. if(i2s_config->pin.bck_io_num>=0){
  780. cJSON_AddItemToArray(llist,get_gpio_entry("bck","dac",i2s_config->pin.bck_io_num,is_dac_config_locked()));
  781. cJSON_AddItemToArray(llist,get_gpio_entry("ws","dac",i2s_config->pin.ws_io_num,is_dac_config_locked()));
  782. cJSON_AddItemToArray(llist,get_gpio_entry("do","dac",i2s_config->pin.data_out_num,is_dac_config_locked()));
  783. if(i2s_config->sda>=0){
  784. cJSON_AddItemToArray(llist,get_gpio_entry("sda","dac",i2s_config->sda,is_dac_config_locked()));
  785. cJSON_AddItemToArray(llist,get_gpio_entry("scl","dac",i2s_config->scl,is_dac_config_locked()));
  786. }
  787. if(i2s_config->mute_gpio>=0){
  788. cJSON_AddItemToArray(llist,get_gpio_entry("mute","dac",i2s_config->mute_gpio,is_dac_config_locked()));
  789. }
  790. }
  791. return llist;
  792. }
  793. /****************************************************************************************
  794. *
  795. */
  796. cJSON * get_Display_GPIO(cJSON * list){
  797. cJSON * llist = list;
  798. if(!llist){
  799. llist = cJSON_CreateArray();
  800. }
  801. const display_config_t * config= config_display_get();
  802. if(config->back >=0){
  803. cJSON_AddItemToArray(llist,get_gpio_entry("backlight","display",config->back,false));
  804. }
  805. if(config->CS_pin >=0){
  806. cJSON_AddItemToArray(llist,get_gpio_entry("CS","display",config->CS_pin,false));
  807. }
  808. if(config->RST_pin >=0){
  809. cJSON_AddItemToArray(llist,get_gpio_entry("reset","display",config->RST_pin,false));
  810. }
  811. return llist;
  812. }
  813. /****************************************************************************************
  814. *
  815. */
  816. cJSON * get_I2C_GPIO(cJSON * list){
  817. cJSON * llist = list;
  818. if(!llist){
  819. llist = cJSON_CreateArray();
  820. }
  821. int port=0;
  822. const i2c_config_t * i2c_config = config_i2c_get(&port);
  823. if(i2c_config->scl_io_num>=0){
  824. cJSON_AddItemToArray(llist,get_gpio_entry("scl","i2c",i2c_config->scl_io_num,false));
  825. cJSON_AddItemToArray(llist,get_gpio_entry("sda","i2c",i2c_config->sda_io_num,false));
  826. }
  827. return llist;
  828. }
  829. /****************************************************************************************
  830. *
  831. */
  832. cJSON * get_SPI_GPIO(cJSON * list){
  833. cJSON * llist = list;
  834. if(!llist){
  835. llist = cJSON_CreateArray();
  836. }
  837. spi_host_device_t spi_host;
  838. const spi_bus_config_t * spi_config = config_spi_get(&spi_host);
  839. if(spi_config->miso_io_num>=0){
  840. cJSON_AddItemToArray(llist,get_gpio_entry("data","spi",spi_config->miso_io_num,false));
  841. cJSON_AddItemToArray(llist,get_gpio_entry("data","clk",spi_config->sclk_io_num,false));
  842. }
  843. if(spi_system_dc_gpio>0){
  844. cJSON_AddItemToArray(llist,get_gpio_entry("data","dc",spi_system_dc_gpio,false));
  845. }
  846. return llist;
  847. }
  848. /****************************************************************************************
  849. *
  850. */
  851. cJSON * get_eth_GPIO(cJSON * list){
  852. cJSON * llist = list;
  853. if(!llist){
  854. llist = cJSON_CreateArray();
  855. }
  856. spi_host_device_t spi_host;
  857. const eth_config_t * eth_config = config_eth_get(&spi_host);
  858. #if defined(CONFIG_ETH_CONFIG)
  859. bool fixed = strlen(CONFIG_ETH_CONFIG)>0;
  860. #else
  861. bool fixed =false;
  862. #endif
  863. if(eth_config->valid ){
  864. add_gpio_for_value(llist,"mdc",eth_config->mdc,"ethernet",fixed);
  865. add_gpio_for_value(llist,"rst",eth_config->rst,"ethernet",fixed);
  866. add_gpio_for_value(llist,"mdio",eth_config->mdio,"ethernet",fixed);
  867. if(eth_config->rmii){
  868. add_gpio_for_value(llist,"tx_en", 21,"ethernet",true);
  869. add_gpio_for_value(llist,"tx0", 19 ,"ethernet",true);
  870. add_gpio_for_value(llist,"tx1", 22 ,"ethernet",true);
  871. add_gpio_for_value(llist,"rx0", 25 ,"ethernet",true);
  872. add_gpio_for_value(llist,"rx1", 26 ,"ethernet",true);
  873. add_gpio_for_value(llist,"crs_dv",27 ,"ethernet",true);
  874. }
  875. else if(eth_config->spi) {
  876. /* SPI ethernet */
  877. add_gpio_for_value(llist,"cs",eth_config->cs,"ethernet",fixed);
  878. add_gpio_for_value(llist,"mosi",eth_config->mosi,"ethernet",fixed);
  879. add_gpio_for_value(llist,"miso",eth_config->miso,"ethernet",fixed);
  880. add_gpio_for_value(llist,"intr",eth_config->intr,"ethernet",fixed);
  881. add_gpio_for_value(llist,"clk",eth_config->clk,"ethernet",fixed);
  882. }
  883. }
  884. return llist;
  885. }
  886. /****************************************************************************************
  887. *
  888. */
  889. cJSON * get_SPDIF_GPIO(cJSON * list, bool fixed){
  890. cJSON * llist = list?list:cJSON_CreateArray();
  891. char * spdif_config = config_spdif_get_string();
  892. if(spdif_config){
  893. llist = add_gpio_for_name(llist,spdif_config,"bck", "spdif", fixed);
  894. llist = add_gpio_for_name(llist,spdif_config,"ws", "spdif", fixed);
  895. llist = add_gpio_for_name(llist,spdif_config,"do", "spdif", fixed);
  896. free(spdif_config);
  897. }
  898. return llist;
  899. }
  900. /****************************************************************************************
  901. *
  902. */
  903. cJSON * get_Rotary_GPIO(cJSON * list){
  904. cJSON * llist = list?list:cJSON_CreateArray();
  905. const rotary_struct_t *rotary= config_rotary_get();
  906. add_gpio_for_value(llist,"A",rotary->A, "rotary", false);
  907. add_gpio_for_value(llist,"B",rotary->B, "rotary", false);
  908. add_gpio_for_value(llist,"SW",rotary->SW, "rotary", false);
  909. return llist;
  910. }
  911. /****************************************************************************************
  912. *
  913. */
  914. cJSON * get_ledvu_GPIO(cJSON * list){
  915. cJSON * llist = list?list:cJSON_CreateArray();
  916. const ledvu_struct_t *ledvu= config_ledvu_get();
  917. add_gpio_for_value(llist,"gpio",ledvu->gpio, "led_vu", false);
  918. return llist;
  919. }
  920. /****************************************************************************************
  921. *
  922. */
  923. esp_err_t get_gpio_structure(cJSON * gpio_entry, gpio_entry_t ** gpio){
  924. esp_err_t err = ESP_OK;
  925. *gpio = malloc_init_external(sizeof(gpio_entry_t));
  926. cJSON * val = cJSON_GetObjectItem(gpio_entry,"gpio");
  927. if(val){
  928. (*gpio)->gpio= (int)val->valuedouble;
  929. } else {
  930. ESP_LOGE(TAG,"gpio pin not found");
  931. err=ESP_FAIL;
  932. }
  933. val = cJSON_GetObjectItem(gpio_entry,"name");
  934. if(val){
  935. (*gpio)->name= strdup_psram(cJSON_GetStringValue(val));
  936. } else {
  937. ESP_LOGE(TAG,"gpio name value not found");
  938. err=ESP_FAIL;
  939. }
  940. val = cJSON_GetObjectItem(gpio_entry,"group");
  941. if(val){
  942. (*gpio)->group= strdup_psram(cJSON_GetStringValue(val));
  943. } else {
  944. ESP_LOGE(TAG,"gpio group value not found");
  945. err=ESP_FAIL;
  946. }
  947. val = cJSON_GetObjectItem(gpio_entry,"fixed");
  948. if(val){
  949. (*gpio)->fixed= cJSON_IsTrue(val);
  950. } else {
  951. ESP_LOGE(TAG,"gpio fixed indicator not found");
  952. err=ESP_FAIL;
  953. }
  954. return err;
  955. }
  956. /****************************************************************************************
  957. *
  958. */
  959. esp_err_t free_gpio_entry( gpio_entry_t ** gpio) {
  960. if(* gpio){
  961. free((* gpio)->name);
  962. free((* gpio)->group);
  963. free(* gpio);
  964. * gpio=NULL;
  965. return ESP_OK;
  966. }
  967. return ESP_FAIL;
  968. }
  969. /****************************************************************************************
  970. *
  971. */
  972. gpio_entry_t * get_gpio_by_no(int gpionum, bool refresh){
  973. cJSON * gpio_header=NULL;
  974. gpio_entry_t * gpio=NULL;
  975. get_gpio_list(refresh);
  976. cJSON_ArrayForEach(gpio_header,gpio_list)
  977. {
  978. if(get_gpio_structure(gpio_header, &gpio)==ESP_OK && gpio->gpio==gpionum){
  979. ESP_LOGD(TAG,"Found GPIO: %s=%d %s", gpio->name,gpio->gpio,gpio->fixed?"(FIXED)":"(VARIABLE)");
  980. }
  981. }
  982. return gpio;
  983. }
  984. /****************************************************************************************
  985. *
  986. */
  987. gpio_entry_t * get_gpio_by_name(char * name,char * group, bool refresh){
  988. cJSON * gpio_header=NULL;
  989. gpio_entry_t * gpio=NULL;
  990. get_gpio_list(refresh);
  991. cJSON_ArrayForEach(gpio_header,gpio_list)
  992. {
  993. if(get_gpio_structure(gpio_header, &gpio)==ESP_OK && strcasecmp(gpio->name,name)&& strcasecmp(gpio->group,group)){
  994. ESP_LOGD(TAG,"Found GPIO: %s=%d %s", gpio->name,gpio->gpio,gpio->fixed?"(FIXED)":"(VARIABLE)");
  995. }
  996. }
  997. return gpio;
  998. }
  999. #ifndef PICO_PSRAM_CLK_IO
  1000. #define PICO_PSRAM_CLK_IO 6
  1001. #endif
  1002. #ifndef PSRAM_SPIQ_SD0_IO
  1003. #define PSRAM_SPIQ_SD0_IO 7
  1004. #define PSRAM_SPID_SD1_IO 8
  1005. #define PSRAM_SPIWP_SD3_IO 10
  1006. #define PSRAM_SPIHD_SD2_IO 9
  1007. #define FLASH_HSPI_CLK_IO 14
  1008. #define FLASH_HSPI_CS_IO 15
  1009. #define PSRAM_HSPI_SPIQ_SD0_IO 12
  1010. #define PSRAM_HSPI_SPID_SD1_IO 13
  1011. #define PSRAM_HSPI_SPIWP_SD3_IO 2
  1012. #define PSRAM_HSPI_SPIHD_SD2_IO 4
  1013. #endif
  1014. cJSON * get_psram_gpio_list(cJSON * list){
  1015. cJSON * llist=list;
  1016. #if CONFIG_IDF_TARGET_ESP32
  1017. const char * psram_dev = "psram";
  1018. const char * flash_dev = "flash";
  1019. const char * clk = "clk";
  1020. const char * cs = "cs";
  1021. const char * spiq_sd0_io="spiq_sd0_io";
  1022. const char * spid_sd1_io = "spid_sd1_io";
  1023. const char * spiwp_sd3_io = "spiwp_sd3_io";
  1024. const char * spihd_sd2_io = "spihd_sd2_io";
  1025. uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
  1026. uint32_t pkg_ver = chip_ver & 0x7;
  1027. if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
  1028. rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
  1029. if (cfg.tieh != RTC_VDDSDIO_TIEH_1_8V) {
  1030. return llist;
  1031. }
  1032. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,CONFIG_D2WD_PSRAM_CLK_IO,true));
  1033. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,CONFIG_D2WD_PSRAM_CS_IO,true));
  1034. } else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
  1035. rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
  1036. if (cfg.tieh != RTC_VDDSDIO_TIEH_3_3V) {
  1037. return llist;
  1038. }
  1039. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,PICO_PSRAM_CLK_IO,true));
  1040. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,CONFIG_PICO_PSRAM_CS_IO,true));
  1041. } else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5)){
  1042. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,CONFIG_D0WD_PSRAM_CLK_IO,true));
  1043. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,CONFIG_D0WD_PSRAM_CS_IO,true));
  1044. } else {
  1045. ESP_LOGW(TAG, "Cant' determine GPIOs for PSRAM chip id: %d", pkg_ver);
  1046. cJSON_AddItemToArray(list,get_gpio_entry(clk,psram_dev,-1,true));
  1047. cJSON_AddItemToArray(list,get_gpio_entry(cs,psram_dev,-1,true));
  1048. }
  1049. const uint32_t spiconfig = ets_efuse_get_spiconfig();
  1050. if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
  1051. cJSON_AddItemToArray(list,get_gpio_entry(spiq_sd0_io,psram_dev,PSRAM_SPIQ_SD0_IO,true));
  1052. cJSON_AddItemToArray(list,get_gpio_entry(spid_sd1_io,psram_dev,PSRAM_SPID_SD1_IO,true));
  1053. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,PSRAM_SPIWP_SD3_IO,true));
  1054. cJSON_AddItemToArray(list,get_gpio_entry(spihd_sd2_io,psram_dev,PSRAM_SPIHD_SD2_IO,true));
  1055. } else if (spiconfig == EFUSE_SPICONFIG_HSPI_DEFAULTS) {
  1056. cJSON_AddItemToArray(list,get_gpio_entry(spiq_sd0_io,psram_dev,PSRAM_HSPI_SPIQ_SD0_IO,true));
  1057. cJSON_AddItemToArray(list,get_gpio_entry(spid_sd1_io,psram_dev,PSRAM_HSPI_SPID_SD1_IO,true));
  1058. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,PSRAM_HSPI_SPIWP_SD3_IO,true));
  1059. cJSON_AddItemToArray(list,get_gpio_entry(spihd_sd2_io,psram_dev,PSRAM_HSPI_SPIHD_SD2_IO,true));
  1060. } else {
  1061. cJSON_AddItemToArray(list,get_gpio_entry(spiq_sd0_io,psram_dev,EFUSE_SPICONFIG_RET_SPIQ(spiconfig),true));
  1062. cJSON_AddItemToArray(list,get_gpio_entry(spid_sd1_io,psram_dev,EFUSE_SPICONFIG_RET_SPID(spiconfig),true));
  1063. cJSON_AddItemToArray(list,get_gpio_entry(spihd_sd2_io,psram_dev,EFUSE_SPICONFIG_RET_SPIHD(spiconfig),true));
  1064. // If flash mode is set to QIO or QOUT, the WP pin is equal the value configured in bootloader.
  1065. // If flash mode is set to DIO or DOUT, the WP pin should config it via menuconfig.
  1066. #if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
  1067. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,CONFIG_BOOTLOADER_SPI_WP_PIN,true));
  1068. #else
  1069. cJSON_AddItemToArray(list,get_gpio_entry(spiwp_sd3_io,psram_dev,CONFIG_SPIRAM_SPIWP_SD3_PIN,true));
  1070. #endif
  1071. }
  1072. if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
  1073. cJSON_AddItemToArray(list,get_gpio_entry(clk,flash_dev,SPI_IOMUX_PIN_NUM_CLK,true));
  1074. cJSON_AddItemToArray(list,get_gpio_entry(cs,flash_dev,SPI_IOMUX_PIN_NUM_CS,true));
  1075. } else if (spiconfig == EFUSE_SPICONFIG_HSPI_DEFAULTS) {
  1076. cJSON_AddItemToArray(list,get_gpio_entry(clk,flash_dev,FLASH_HSPI_CLK_IO,true));
  1077. cJSON_AddItemToArray(list,get_gpio_entry(cs,flash_dev,FLASH_HSPI_CS_IO,true));
  1078. } else {
  1079. cJSON_AddItemToArray(list,get_gpio_entry(clk,flash_dev,EFUSE_SPICONFIG_RET_SPICLK(spiconfig),true));
  1080. cJSON_AddItemToArray(list,get_gpio_entry(cs,flash_dev,EFUSE_SPICONFIG_RET_SPICS0(spiconfig),true));
  1081. }
  1082. #else
  1083. #pragma message("need to add esp32-s3 specific SPIRAM GPIO config code")
  1084. #endif
  1085. return llist;
  1086. }
  1087. /****************************************************************************************
  1088. *
  1089. */
  1090. cJSON * get_gpio_list_handler(bool refresh) {
  1091. gpio_num_t gpio_num;
  1092. if(gpio_list && !refresh){
  1093. return gpio_list;
  1094. }
  1095. if(gpio_list){
  1096. cJSON_Delete(gpio_list);
  1097. }
  1098. gpio_list= cJSON_CreateArray();
  1099. char *bat_config = config_alloc_get_default(NVS_TYPE_STR, "bat_config", NULL, 0);
  1100. if (bat_config) {
  1101. int channel = -1;
  1102. PARSE_PARAM(bat_config, "channel", '=', channel);
  1103. if(channel != -1){
  1104. if(adc1_pad_get_io_num(channel,&gpio_num )==ESP_OK){
  1105. cJSON_AddItemToArray(gpio_list,get_gpio_entry("bat","other",gpio_num,false));
  1106. }
  1107. }
  1108. free(bat_config);
  1109. }
  1110. gpio_list=get_GPIO_nvs_list(gpio_list);
  1111. gpio_list=get_SPDIF_GPIO(gpio_list,is_spdif_config_locked());
  1112. gpio_list=get_Rotary_GPIO(gpio_list);
  1113. gpio_list=get_Display_GPIO(gpio_list);
  1114. gpio_list=get_SPI_GPIO(gpio_list);
  1115. gpio_list=get_I2C_GPIO(gpio_list);
  1116. gpio_list=get_DAC_GPIO(gpio_list);
  1117. gpio_list=get_ledvu_GPIO(gpio_list);
  1118. gpio_list=get_psram_gpio_list(gpio_list);
  1119. gpio_list=get_eth_GPIO(gpio_list);
  1120. return gpio_list;
  1121. }