GCC Code Coverage Report


Directory: main/
File: system/manager.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 275 0.0%
Functions: 0 23 0.0%
Branches: 0 120 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019-2024, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <freertos/FreeRTOS.h>
9 #include <freertos/task.h>
10 #include <freertos/ringbuf.h>
11 #include <esp_partition.h>
12 #include <esp_sleep.h>
13 #include <esp_system.h>
14 #include <soc/efuse_reg.h>
15 #include "driver/gpio.h"
16 #include "hal/ledc_hal.h"
17 #include "hal/gpio_hal.h"
18 #include "driver/ledc.h"
19 #include "esp_rom_gpio.h"
20 #include "adapter/adapter.h"
21 #include "adapter/config.h"
22 #include "adapter/memory_card.h"
23 #include "bluetooth/host.h"
24 #include "bluetooth/hci.h"
25 #include "wired/wired_bare.h"
26 #include "tools/util.h"
27 #include "system/fs.h"
28 #include "system/led.h"
29 #include "bare_metal_app_cpu.h"
30 #include "manager.h"
31
32 #define BOOT_BTN_PIN 0
33
34 #define RESET_PIN 14
35
36 #define POWER_ON_PIN 13
37 #define POWER_OFF_PIN 16
38 #define POWER_SENSE_PIN 39
39
40 #define POWER_OFF_ALT_PIN 12
41
42 #define SENSE_P1_PIN 35
43 #define SENSE_P2_PIN 36
44 #define SENSE_P3_PIN 32
45 #define SENSE_P4_PIN 33
46
47 #define SENSE_P1_ALT_PIN 15
48 #define SENSE_P2_ALT_PIN 34
49
50 #define LED_P1_PIN 2
51 #define LED_P2_PIN 4
52 #define LED_P3_PIN 12
53 #define LED_P4_PIN 15
54
55 #define INHIBIT_CNT 200
56
57 typedef void (*sys_mgr_cmd_t)(void);
58
59 enum {
60 SYS_MGR_BTN_STATE0 = 0,
61 SYS_MGR_BTN_STATE1,
62 SYS_MGR_BTN_STATE2,
63 SYS_MGR_BTN_STATE3,
64 };
65
66 #ifdef CONFIG_BLUERETRO_HW2
67 static uint8_t sense_list[] = {
68 SENSE_P1_PIN, SENSE_P2_PIN, SENSE_P3_PIN, SENSE_P4_PIN
69 };
70 #endif
71 static uint8_t led_list[] = {
72 LED_P1_PIN, LED_P2_PIN, LED_P3_PIN, LED_P4_PIN
73 };
74 static uint8_t current_pulse_led = LED_P1_PIN;
75 static uint8_t err_led_pin;
76 static uint8_t power_off_pin = POWER_OFF_PIN;
77 static uint8_t led_init_cnt = 1;
78 static uint16_t port_state = 0;
79 static RingbufHandle_t cmd_q_hdl = NULL;
80 static uint32_t chip_package = EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6;
81 static bool factory_reset = false;
82
83 static int32_t sys_mgr_get_power(void);
84 static int32_t sys_mgr_get_boot_btn(void);
85 static void sys_mgr_reset(void);
86 static void sys_mgr_power_on(void);
87 static void sys_mgr_power_off(void);
88 static void sys_mgr_inquiry_toggle(void);
89 static void sys_mgr_factory_reset(void);
90 static void sys_mgr_deep_sleep(void);
91 static void sys_mgr_esp_restart(void);
92 static void sys_mgr_wired_reset(void);
93
94 static const sys_mgr_cmd_t sys_mgr_cmds[] = {
95 sys_mgr_reset,
96 sys_mgr_power_on,
97 sys_mgr_power_off,
98 sys_mgr_inquiry_toggle,
99 sys_mgr_factory_reset,
100 sys_mgr_deep_sleep,
101 sys_mgr_esp_restart,
102 sys_mgr_wired_reset,
103 };
104
105 static inline uint32_t sense_port_is_empty(uint32_t index) {
106 #ifdef CONFIG_BLUERETRO_HW2
107 if (hw_config.ports_sense_input_polarity) {
108 return !gpio_get_level(sense_list[index]);
109 }
110 else {
111 return gpio_get_level(sense_list[index]);
112 }
113 #else
114 return 1;
115 #endif
116 }
117
118 static inline void set_power_on(uint32_t state) {
119 if (hw_config.power_pin_polarity) {
120 gpio_set_level(POWER_ON_PIN, !state);
121 }
122 else {
123 gpio_set_level(POWER_ON_PIN, state);
124 }
125 }
126
127 static inline void set_power_off(uint32_t state) {
128 if (hw_config.power_pin_polarity) {
129 gpio_set_level(power_off_pin, !state);
130 }
131 else {
132 gpio_set_level(power_off_pin, state);
133 }
134 }
135
136 static inline void set_reset(uint32_t state) {
137 if (hw_config.reset_pin_polarity) {
138 gpio_set_level(RESET_PIN, !state);
139 }
140 else {
141 gpio_set_level(RESET_PIN, state);
142 }
143 }
144
145 static inline void set_sense_out(uint32_t pin, uint32_t state) {
146 if (hw_config.ports_sense_output_polarity) {
147 gpio_set_level(pin, !state);
148 }
149 else {
150 gpio_set_level(pin, state);
151 }
152 }
153
154 static inline void set_port_led(uint32_t index, uint32_t state) {
155 if (state) {
156 esp_rom_gpio_connect_out_signal(led_list[index], ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_1, 0, 0);
157 }
158 else {
159 esp_rom_gpio_connect_out_signal(led_list[index], ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_2, 0, 0);
160 }
161 }
162
163 static inline uint32_t get_port_led_pin(uint32_t index) {
164 return led_list[index];
165 }
166
167 static void internal_flag_init(void) {
168 #ifdef CONFIG_BLUERETRO_HW2
169 if (hw_config.power_pin_polarity) {
170 if (!gpio_get_level(POWER_ON_PIN) && gpio_get_level(RESET_PIN)) {
171 hw_config.external_adapter = 1;
172 }
173 }
174 else {
175 if (gpio_get_level(POWER_ON_PIN) && gpio_get_level(RESET_PIN)) {
176 hw_config.external_adapter = 1;
177 }
178 }
179 #else
180 hw_config.external_adapter = 1;
181 #endif
182 if (hw_config.external_adapter) {
183 printf("# %s: External adapter\n", __FUNCTION__);
184 }
185 else {
186 printf("# %s: Internal adapter\n", __FUNCTION__);
187 }
188 }
189
190 static void port_led_pulse(uint32_t pin) {
191 if (pin) {
192 PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
193 gpio_set_direction(pin, GPIO_MODE_OUTPUT);
194 esp_rom_gpio_connect_out_signal(pin, ledc_periph_signal[LEDC_HIGH_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_0, 0, 0);
195 }
196 }
197
198 static void set_leds_as_btn_status(uint8_t state) {
199 ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, hw_config.led_flash_on_duty_cycle, 0);
200
201 /* Use all port LEDs */
202 for (uint32_t i = 0; i < hw_config.port_cnt; i++) {
203 uint8_t pin = led_list[i];
204
205 PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
206 gpio_set_direction(pin, GPIO_MODE_OUTPUT);
207 if (state) {
208 esp_rom_gpio_connect_out_signal(pin, ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_1, 0, 0);
209 }
210 }
211
212 /* Use error LED as well */
213 if (state) {
214 esp_rom_gpio_connect_out_signal(err_led_pin, ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_1, 0, 0);
215 }
216 else {
217 esp_rom_gpio_connect_out_signal(err_led_pin, ledc_periph_signal[LEDC_HIGH_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_0, 0, 0);
218 }
219 }
220
221 static void power_on_hdl(void) {
222 #ifdef CONFIG_BLUERETRO_HW2
223 static int32_t curr = 0, prev = 0;
224 struct bt_dev *not_used;
225
226 prev = curr;
227 curr = sys_mgr_get_power();
228 if (curr) {
229 /* System is power on */
230 bt_hci_inquiry_override(0);
231
232 if (bt_host_get_active_dev(&not_used) < 0) {
233 /* No Bt device */
234 uint32_t port_cnt_loc = 0;
235
236 for (uint32_t i = 0; i < hw_config.port_cnt; i++) {
237 if (sense_port_is_empty(i)) {
238 port_cnt_loc++;
239 }
240 }
241 if (port_cnt_loc == hw_config.port_cnt) {
242 /* No wired controller */
243 if (!bt_hci_get_inquiry()) {
244 bt_hci_start_inquiry();
245 }
246 }
247 }
248 }
249 else {
250 /* System is off */
251 if (curr != prev) {
252 /* Kick BT controllers on off transition */
253 bt_host_disconnect_all();
254 }
255 else if (bt_host_get_hid_init_dev(&not_used) > -1) {
256 /* Power on BT connect */
257 bt_hci_inquiry_override(0);
258 sys_mgr_power_on();
259 return;
260 }
261 /* Make sure no inquiry while power off */
262 bt_hci_inquiry_override(1);
263 if (bt_hci_get_inquiry()) {
264 bt_hci_stop_inquiry();
265 }
266 }
267 #endif /* CONFIG_BLUERETRO_HW2 */
268 }
269
270 static void wired_port_hdl(void) {
271 uint32_t update = 0;
272 uint16_t port_mask = 0;
273 uint8_t err_led_set = 0;
274
275 for (int32_t i = 0, j = 0, idx = 0; i < BT_MAX_DEV; i++) {
276 struct bt_dev *device = NULL;
277 uint8_t bt_ready = 0;
278
279 bt_host_get_dev_from_id(i, &device);
280
281 for (; j < hw_config.port_cnt; j++) {
282 if (sense_port_is_empty(j)) {
283 j++;
284 break;
285 }
286 set_port_led(j, 0);
287 idx++;
288 }
289
290 bt_ready = atomic_test_bit(&device->flags, BT_DEV_HID_INIT_DONE);
291
292 #ifdef CONFIG_BLUERETRO_HW2
293 int32_t prev_idx = device->ids.out_idx;
294 #endif
295 device->ids.out_idx = idx;
296 if ((hw_config.hotplug && bt_ready) || !hw_config.hotplug) {
297 port_mask |= BIT(idx) | adapter_get_out_mask(idx);
298 }
299 idx++;
300
301
302 if (device->ids.out_idx < hw_config.port_cnt) {
303 if (bt_ready) {
304 set_port_led(device->ids.out_idx, 1);
305 }
306 else if (get_port_led_pin(device->ids.out_idx) != current_pulse_led) {
307 set_port_led(device->ids.out_idx, 0);
308 }
309 }
310
311 if (!bt_ready && !err_led_set) {
312 uint8_t new_led = (device->ids.out_idx < hw_config.port_cnt) ? get_port_led_pin(device->ids.out_idx) : 0;
313
314 if (bt_hci_get_inquiry()) {
315 port_led_pulse(new_led);
316 err_led_set = 1;
317 current_pulse_led = new_led;
318 }
319 else {
320 current_pulse_led = 0;
321 }
322 }
323
324 #ifdef CONFIG_BLUERETRO_HW2
325 if (device->ids.out_idx != prev_idx) {
326 update++;
327 printf("# %s: BTDEV %ld map to WIRED %ld\n", __FUNCTION__, i, device->ids.out_idx);
328 if (bt_ready) {
329 struct raw_fb fb_data = {0};
330
331 fb_data.header.wired_id = device->ids.out_idx;
332 fb_data.header.type = FB_TYPE_PLAYER_LED;
333 fb_data.header.data_len = 0;
334 adapter_q_fb(&fb_data);
335 }
336 }
337 #endif
338 }
339 if (hw_config.hotplug) {
340 if (port_state != port_mask) {
341 update++;
342 }
343 }
344 if (update && !mc_get_state()) {
345 printf("# %s: Update ports state: %04X\n", __FUNCTION__, port_mask);
346 wired_bare_port_cfg(port_mask);
347 port_state = port_mask;
348 if (hw_config.ports_sense_p3_p4_as_output) {
349 /* Toggle Wii classic sense line to force ctrl reinit */
350 set_sense_out(SENSE_P3_PIN, 0);
351 set_sense_out(SENSE_P4_PIN, 0);
352 vTaskDelay(hw_config.ports_sense_output_ms / portTICK_PERIOD_MS);
353 set_sense_out(SENSE_P3_PIN, 1);
354 set_sense_out(SENSE_P4_PIN, 1);
355 }
356 }
357 }
358
359 static void boot_btn_hdl(void) {
360 static uint32_t check_qdp = 0;
361 static uint32_t inhibit_cnt = 0;
362 uint32_t hold_cnt = 0;
363 uint32_t state = 0;
364
365 /* Let inhibit_cnt reach 0 before handling button again */
366 if (inhibit_cnt && inhibit_cnt--) {
367 /* Power off on quick double press */
368 if (check_qdp && sys_mgr_get_power() && sys_mgr_get_boot_btn()) {
369 sys_mgr_power_off();
370 check_qdp = 0;
371 }
372 return;
373 }
374 check_qdp = 0;
375
376 if (sys_mgr_get_boot_btn()) {
377 set_leds_as_btn_status(1);
378
379 while (sys_mgr_get_boot_btn()) {
380 hold_cnt++;
381 if (hold_cnt > (hw_config.sw_io0_hold_thres_ms[state] / 10) && state < SYS_MGR_BTN_STATE3) {
382 ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, hw_config.led_flash_duty_cycle, 0);
383 ledc_set_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_1, hw_config.led_flash_hz[state]);
384 state++;
385 }
386 if (hold_cnt == 3000) {
387 printf("# FW will be factory reset\n");
388 factory_reset = true;
389 }
390 vTaskDelay(10 / portTICK_PERIOD_MS);
391 }
392
393 #ifndef CONFIG_BLUERETRO_SYSTEM_UNIVERSAL
394 if (hw_config.external_adapter)
395 #endif
396 {
397 state++;
398 }
399
400 if (sys_mgr_get_power()) {
401 /* System is on */
402 switch (state) {
403 case SYS_MGR_BTN_STATE0:
404 sys_mgr_reset();
405 check_qdp = 1;
406 break;
407 case SYS_MGR_BTN_STATE1:
408 if (bt_hci_get_inquiry()) {
409 bt_hci_stop_inquiry();
410 }
411 else {
412 bt_host_disconnect_all();
413 }
414 break;
415 case SYS_MGR_BTN_STATE2:
416 bt_hci_start_inquiry();
417 break;
418 default:
419 sys_mgr_factory_reset();
420 break;
421 }
422 }
423 else {
424 /* System is off */
425 switch (state) {
426 case SYS_MGR_BTN_STATE0:
427 sys_mgr_power_on();
428 break;
429 default:
430 set_reset(0);
431 sys_mgr_power_on();
432 set_reset(1);
433 break;
434 }
435 }
436
437 set_leds_as_btn_status(0);
438 inhibit_cnt = INHIBIT_CNT;
439 }
440 }
441
442 static void sys_mgr_task(void *arg) {
443 uint32_t cnt = 0;
444 uint8_t *cmd;
445 size_t cmd_len;
446
447 while (1) {
448 boot_btn_hdl();
449
450 /* Fetch system cmd to execute */
451 if (cmd_q_hdl) {
452 cmd = (uint8_t *)xRingbufferReceive(cmd_q_hdl, &cmd_len, 0);
453 if (cmd) {
454 if (sys_mgr_cmds[*cmd]) {
455 sys_mgr_cmds[*cmd]();
456 }
457 vRingbufferReturnItem(cmd_q_hdl, (void *)cmd);
458 }
459 }
460
461 /* Update those only 1/32 loop */
462 if ((cnt & 0x1F) == 0x1F) {
463 wired_port_hdl();
464 if (!hw_config.external_adapter) {
465 power_on_hdl();
466 }
467 }
468 cnt++;
469 vTaskDelay(10 / portTICK_PERIOD_MS);
470 }
471 }
472
473 static void sys_mgr_reset(void) {
474 set_reset(0);
475 vTaskDelay(hw_config.reset_pin_pulse_ms / portTICK_PERIOD_MS);
476 set_reset(1);
477 }
478
479 static void sys_mgr_inquiry_toggle(void) {
480 if (bt_hci_get_inquiry()) {
481 bt_hci_stop_inquiry();
482 }
483 else {
484 bt_hci_start_inquiry();
485 }
486 }
487
488 static void sys_mgr_power_on(void) {
489 set_power_on(1);
490 if (!hw_config.power_pin_is_hold) {
491 vTaskDelay(hw_config.power_pin_pulse_ms / portTICK_PERIOD_MS);
492 set_power_on(0);
493 }
494 }
495
496 static void sys_mgr_power_off(void) {
497 bt_host_disconnect_all();
498 #ifdef CONFIG_BLUERETRO_HW2
499 if (hw_config.power_pin_is_hold) {
500 set_power_on(0);
501 }
502 else {
503 set_power_off(1);
504 vTaskDelay(hw_config.power_pin_pulse_ms / portTICK_PERIOD_MS);
505 set_power_off(0);
506 }
507 #endif
508 }
509
510 static int32_t sys_mgr_get_power(void) {
511 #ifdef CONFIG_BLUERETRO_SYSTEM_UNIVERSAL
512 return 1;
513 #else
514 if (hw_config.external_adapter) {
515 return 1;
516 }
517 else {
518 return gpio_get_level(POWER_SENSE_PIN);
519 }
520 #endif
521 }
522
523 static int32_t sys_mgr_get_boot_btn(void) {
524 return !gpio_get_level(BOOT_BTN_PIN);
525 }
526
527 static void sys_mgr_factory_reset(void) {
528 const esp_partition_t* partition = esp_partition_find_first(
529 ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, "otadata");
530 if (factory_reset && partition) {
531 esp_partition_erase_range(partition, 0, partition->size);
532 }
533
534 fs_reset();
535 printf("BlueRetro factory reset\n");
536 bt_host_disconnect_all();
537 vTaskDelay(1000 / portTICK_PERIOD_MS);
538 esp_restart();
539 }
540
541 static void sys_mgr_esp_restart(void) {
542 vTaskDelay(1000 / portTICK_PERIOD_MS);
543 esp_restart();
544 }
545
546 static void sys_mgr_deep_sleep(void) {
547 vTaskDelay(1000 / portTICK_PERIOD_MS);
548 esp_deep_sleep_start();
549 }
550
551 static void IRAM_ATTR sys_mgr_wired_reinit_task(void) {
552 for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) {
553 adapter_init_buffer(i);
554 }
555
556 if (wired_adapter.system_id < WIRED_MAX) {
557 wired_bare_init(chip_package);
558 }
559 }
560
561 static void sys_mgr_wired_reset(void) {
562 init_app_cpu_baremetal();
563 start_app_cpu(sys_mgr_wired_reinit_task);
564 port_state = 0;
565 }
566
567 void sys_mgr_cmd(uint8_t cmd) {
568 if (cmd_q_hdl) {
569 UBaseType_t ret = xRingbufferSend(cmd_q_hdl, &cmd, sizeof(cmd), portMAX_DELAY);
570 if (ret != pdTRUE) {
571 printf("# %s cmd_q full!\n", __FUNCTION__);
572 }
573 }
574 else {
575 printf("# %s cmd_q_hdl NULL!\n", __FUNCTION__);
576 if (cmd == SYS_MGR_CMD_WIRED_RST) {
577 /* For gameid cfg we may need to reset bare core very early */
578 sys_mgr_wired_reset();
579 }
580 }
581 }
582
583 void sys_mgr_init(uint32_t package) {
584 gpio_config_t io_conf = {0};
585
586 io_conf.intr_type = GPIO_INTR_DISABLE;
587 io_conf.mode = GPIO_MODE_INPUT;
588 io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
589 io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
590
591 io_conf.pin_bit_mask = 1ULL << BOOT_BTN_PIN;
592 gpio_config(&io_conf);
593
594 chip_package = package;
595 err_led_pin = err_led_get_pin();
596
597 ledc_timer_config_t ledc_timer = {
598 .duty_resolution = LEDC_TIMER_20_BIT,
599 .freq_hz = 2,
600 .speed_mode = LEDC_LOW_SPEED_MODE,
601 .timer_num = LEDC_TIMER_1,
602 .clk_cfg = LEDC_AUTO_CLK,
603 };
604 ledc_channel_config_t ledc_channel = {
605 .channel = LEDC_CHANNEL_1,
606 .duty = hw_config.led_flash_on_duty_cycle,
607 .gpio_num = LED_P1_PIN,
608 .speed_mode = LEDC_LOW_SPEED_MODE,
609 .hpoint = 0,
610 .timer_sel = LEDC_TIMER_1,
611 };
612 ledc_timer_config(&ledc_timer);
613 ledc_channel_config(&ledc_channel);
614
615 while (wired_adapter.system_id <= WIRED_AUTO) {
616 boot_btn_hdl();
617 vTaskDelay(10 / portTICK_PERIOD_MS);
618 }
619
620 cmd_q_hdl = xRingbufferCreate(32, RINGBUF_TYPE_NOSPLIT);
621 if (cmd_q_hdl == NULL) {
622 printf("# Failed to create cmd_q ring buffer\n");
623 }
624
625 switch (wired_adapter.system_id) {
626 case GENESIS:
627 case SATURN:
628 hw_config.port_cnt = 2;
629 #ifdef CONFIG_BLUERETRO_HW2
630 sense_list[0] = SENSE_P1_ALT_PIN;
631 sense_list[1] = SENSE_P2_ALT_PIN;
632 power_off_pin = POWER_OFF_ALT_PIN;
633 #endif
634 break;
635 case JAGUAR:
636 hw_config.port_cnt = 1;
637 #ifdef CONFIG_BLUERETRO_HW2
638 sense_list[0] = SENSE_P1_ALT_PIN;
639 sense_list[1] = SENSE_P2_ALT_PIN;
640 #endif
641 break;
642 case WII_EXT:
643 hw_config.port_cnt = 2;
644 hw_config.power_pin_is_hold = 1;
645 hw_config.ports_sense_input_polarity = 1;
646 hw_config.power_pin_polarity = 1;
647 hw_config.ports_sense_p3_p4_as_output = 1;
648 break;
649 case N64:
650 case DC:
651 case GC:
652 hw_config.port_cnt = 4;
653 break;
654 case PARALLEL_1P:
655 case PCE:
656 case REAL_3DO:
657 case JVS:
658 case VBOY:
659 case PARALLEL_1P_OD:
660 case SEA_BOARD:
661 hw_config.port_cnt = 1;
662 break;
663 default:
664 hw_config.port_cnt = 2;
665 break;
666 }
667
668 #ifdef CONFIG_BLUERETRO_BT_H4_TRACE
669 hw_config.port_cnt = 1;
670 #endif
671
672 io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
673 #ifdef CONFIG_BLUERETRO_HW2
674 io_conf.pin_bit_mask = 1ULL << POWER_ON_PIN;
675 gpio_config(&io_conf);
676 io_conf.pin_bit_mask = 1ULL << RESET_PIN;
677 gpio_config(&io_conf);
678 #endif
679
680 internal_flag_init();
681
682 hw_config_patch();
683
684 err_led_cfg_update();
685
686 led_init_cnt = hw_config.port_cnt;
687 if (wired_adapter.system_id == PSX || wired_adapter.system_id == PS2) {
688 led_init_cnt = 4;
689 }
690
691 #ifdef CONFIG_BLUERETRO_HW2
692 for (uint32_t i = 0; i < hw_config.port_cnt; i++) {
693 io_conf.pin_bit_mask = 1ULL << sense_list[i];
694 gpio_config(&io_conf);
695 }
696 io_conf.pin_bit_mask = 1ULL << POWER_SENSE_PIN;
697 gpio_config(&io_conf);
698 #endif
699
700 #ifndef CONFIG_BLUERETRO_HW2
701 for (uint32_t i = 0; i < sizeof(led_list); i++) {
702 led_list[i] = hw_config.hw1_ports_led_pins[i];
703 }
704 #endif
705
706 io_conf.mode = GPIO_MODE_OUTPUT;
707 for (uint32_t i = 0; i < led_init_cnt; i++) {
708 #ifdef CONFIG_BLUERETRO_HW2
709 /* Skip pin 15 if alt sense pin are used */
710 if (sense_list[0] == led_list[i]) {
711 continue;
712 }
713 #endif
714 gpio_set_level(led_list[i], 0);
715 io_conf.pin_bit_mask = 1ULL << led_list[i];
716 gpio_config(&io_conf);
717
718 if (i < hw_config.port_cnt) {
719 /* Can't use GPIO mode on port LED as some wired driver overwrite whole GPIO port */
720 /* Use unused LEDC channel 2 to force output low */
721 esp_rom_gpio_connect_out_signal(led_list[i], ledc_periph_signal[LEDC_LOW_SPEED_MODE].sig_out0_idx + LEDC_CHANNEL_2, 0, 0);
722 }
723 }
724
725 #ifdef CONFIG_BLUERETRO_HW2
726 if (hw_config.power_pin_od) {
727 io_conf.mode = GPIO_MODE_OUTPUT_OD;
728 }
729 else {
730 io_conf.mode = GPIO_MODE_OUTPUT;
731 }
732 set_power_on(0);
733 io_conf.pin_bit_mask = 1ULL << POWER_ON_PIN;
734 gpio_config(&io_conf);
735
736 set_power_off(0);
737 io_conf.pin_bit_mask = 1ULL << power_off_pin;
738 gpio_config(&io_conf);
739
740 gpio_set_level(RESET_PIN, 1);
741 if (hw_config.reset_pin_od) {
742 io_conf.mode = GPIO_MODE_OUTPUT_OD;
743 }
744 else {
745 io_conf.mode = GPIO_MODE_OUTPUT;
746 }
747 io_conf.pin_bit_mask = 1ULL << RESET_PIN;
748 gpio_config(&io_conf);
749
750 if (hw_config.ports_sense_p3_p4_as_output) {
751 /* Wii-ext got a sense line that we need to control */
752 if (hw_config.ports_sense_output_od) {
753 io_conf.mode = GPIO_MODE_OUTPUT_OD;
754 }
755 else {
756 io_conf.mode = GPIO_MODE_OUTPUT;
757 }
758 io_conf.intr_type = GPIO_INTR_DISABLE;
759 io_conf.pin_bit_mask = 1ULL << SENSE_P4_PIN;
760 io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
761 io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
762 gpio_config(&io_conf);
763 gpio_set_level(SENSE_P4_PIN, 1);
764 io_conf.pin_bit_mask = 1ULL << SENSE_P3_PIN;
765 gpio_config(&io_conf);
766 gpio_set_level(SENSE_P3_PIN, 1);
767 }
768
769 /* If boot switch pressed at boot, trigger system on and goes to deep sleep */
770 if (sys_mgr_get_boot_btn() && !sys_mgr_get_power()) {
771 sys_mgr_power_on();
772 sys_mgr_deep_sleep();
773 }
774 #endif /* CONFIG_BLUERETRO_HW2 */
775
776 xTaskCreatePinnedToCore(sys_mgr_task, "sys_mgr_task", 2048, NULL, 5, NULL, 0);
777 }
778