GCC Code Coverage Report


Directory: main/
File: adapter/wired/sea.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 130 0.0%
Functions: 0 5 0.0%
Branches: 0 71 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019-2025, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <string.h>
7 #include "adapter/config.h"
8 #include "zephyr/types.h"
9 #include "tools/util.h"
10 #include "soc/gpio_struct.h"
11 #include "driver/gpio.h"
12 #include "wired/sea_io.h"
13 #include "tests/cmds.h"
14 #include "bluetooth/mon.h"
15 #include "sea.h"
16
17 #define P1_LD_UP 19
18 #define P1_LD_DOWN 22
19 #define P1_LD_LEFT 18
20 #define P1_LD_RIGHT 21
21 #define P1_RB_DOWN 5
22 #define P1_RB_RIGHT 13
23 #define P1_RB_LEFT 23
24 #define P1_RB_UP 12
25 #define P1_MM 16
26 #define P1_MS 4
27 #define P1_MT 33
28 #define P1_LM 15
29 #define P1_RM 14
30
31 #define GBAHD_OSD_BTNS 0x00150F00
32
33 static const uint32_t sea_mask[4] = {0x337F0F00, 0x00000000, 0x00000000, BR_COMBO_MASK};
34 static const uint32_t sea_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
35 static DRAM_ATTR const uint32_t sea_btns_mask[32] = {
36 0, 0, 0, 0,
37 0, 0, 0, 0,
38 BIT(P1_LD_LEFT), BIT(P1_LD_RIGHT), BIT(P1_LD_DOWN), BIT(P1_LD_UP),
39 0, 0, 0, 0,
40 BIT(P1_RB_LEFT), BIT(P1_RB_RIGHT), BIT(P1_RB_DOWN), BIT(P1_RB_UP),
41 BIT(P1_MM), BIT(P1_MS), BIT(P1_MT - 32) | 0xF0000000, 0,
42 BIT(P1_LM), BIT(P1_LM), 0, 0,
43 BIT(P1_RM), BIT(P1_RM), 0, 0,
44 };
45 static const uint32_t sea_gbahd_btns_mask[32] = {
46 0, 0, 0, 0,
47 0, 0, 0, 0,
48 BIT(GBAHD_LD_LEFT), BIT(GBAHD_LD_RIGHT), BIT(GBAHD_LD_DOWN), BIT(GBAHD_LD_UP),
49 0, 0, 0, 0,
50 BIT(GBAHD_B), 0, BIT(GBAHD_A), 0,
51 BIT(GBAHD_START), BIT(GBAHD_SELECT), 0, 0,
52 BIT(GBAHD_L), BIT(GBAHD_L), 0, 0,
53 BIT(GBAHD_R), BIT(GBAHD_R), 0, 0,
54 };
55
56 void IRAM_ATTR sea_init_buffer(int32_t dev_mode, struct wired_data *wired_data) {
57 struct sea_map *map = (struct sea_map *)wired_data->output;
58 struct sea_map *map_mask = (struct sea_map *)wired_data->output_mask;
59
60 map->buttons = 0xFFFDFFFF;
61 map->buttons_high = 0xFFFFFFFF;
62 map->buttons_osd = GBAHD_OVERLAY;
63 map->gbahd_state = GBAHD_STATE;
64 map->gbahd_config = GBAHD_CONFIG | config.global_cfg.banksel;
65 map_mask->buttons = 0;
66 map_mask->buttons_high = 0;
67 }
68
69 void sea_meta_init(struct wired_ctrl *ctrl_data) {
70 memset((void *)ctrl_data, 0, sizeof(*ctrl_data)*WIRED_MAX_DEV);
71
72 for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) {
73 ctrl_data[i].mask = sea_mask;
74 ctrl_data[i].desc = sea_desc;
75 }
76 }
77
78 static void gbahd_osd(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
79 struct sea_map *map_tmp = (struct sea_map *)wired_data->output;
80 struct sea_map *turbo_map_mask = (struct sea_map *)wired_data->output_mask;
81 static uint32_t gbahd_osd_btn = 0;
82
83 if (!(map_tmp->gbahd_state & BIT(GBAHD_STATE_OSD))) {
84 /* Home button to enter menu */
85 if (ctrl_data->btns[0].value & generic_btns_mask[PAD_MT]) {
86 if (!atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
87 atomic_set_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
88 }
89 }
90 else {
91 if (atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
92 atomic_clear_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
93
94 map_tmp->gbahd_state = GBAHD_LINE_MIN;
95 sea_tx_byte(map_tmp->gbahd_state);
96 }
97 }
98 }
99 else {
100 /* Menu control */
101 if (ctrl_data->btns[0].value & GBAHD_OSD_BTNS) {
102 if (!atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
103 atomic_set_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
104
105 /* Only handlea single button at a time */
106 gbahd_osd_btn = __builtin_ffs(ctrl_data->btns[0].value) - 1;
107 }
108 }
109 else {
110 if (atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
111 atomic_clear_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
112 uint32_t cur_line = ((map_tmp->gbahd_state & 0xFF) >> 1) - 3;
113 uint16_t cur_cfg;
114 uint32_t dir = 1;
115
116 switch(gbahd_osd_btn) {
117 case PAD_LD_LEFT:
118 dir = -1;
119 /* fallthrough */
120 case PAD_LD_RIGHT:
121 case PAD_RB_DOWN: /* A */
122 switch(cur_line) {
123 case 0:
124 do {
125 cur_cfg = map_tmp->gbahd_config;
126 map_tmp->gbahd_config &= ~GBAHD_CFG_GRID_MASK;
127 map_tmp->gbahd_config |= (cur_cfg + 4 * dir) & GBAHD_CFG_GRID_MASK;
128 } while ((map_tmp->gbahd_config & GBAHD_CFG_GRID_MASK) == 0x8);
129 break;
130 case 2:
131 do {
132 cur_cfg = map_tmp->gbahd_config;
133 map_tmp->gbahd_config &= ~GBAHD_CFG_SMOOTH_MASK;
134 map_tmp->gbahd_config |= (cur_cfg + 1 * dir) & GBAHD_CFG_SMOOTH_MASK;
135 } while((map_tmp->gbahd_config & GBAHD_CFG_SMOOTH_MASK) == 0x3);
136 break;
137 case 1:
138 cur_line++;
139 /* fallthrough */
140 default:
141 map_tmp->gbahd_config ^= BIT(cur_line + 2);
142 break;
143 }
144 sea_tx_byte(map_tmp->gbahd_config);
145 break;
146 case PAD_LD_DOWN:
147 if (map_tmp->gbahd_state < GBAHD_LINE_MAX) {
148 map_tmp->gbahd_state += 2;
149 }
150 break;
151 case PAD_LD_UP:
152 if (map_tmp->gbahd_state > GBAHD_LINE_MIN) {
153 map_tmp->gbahd_state -= 2;
154 }
155 break;
156 case PAD_RB_LEFT: /* B */
157 sea_tx_byte(GBAHD_CONFIG | config.global_cfg.banksel);
158 map_tmp->gbahd_state = GBAHD_STATE;
159 break;
160 case PAD_MM: /* Start */
161 config.global_cfg.banksel = map_tmp->gbahd_config & 0xFF;
162 config_update(config_get_src());
163 map_tmp->gbahd_state = GBAHD_STATE;
164 break;
165 }
166
167 sea_tx_byte(map_tmp->gbahd_state);
168 }
169 }
170 }
171 sea_tx_byte(map_tmp->buttons_osd & turbo_map_mask->buttons_osd);
172 }
173
174 void sea_from_generic(int32_t dev_mode, struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
175 if (ctrl_data->index < 1) {
176 struct sea_map *map_tmp = (struct sea_map *)wired_data->output;
177 struct sea_map *turbo_map_mask = (struct sea_map *)wired_data->output_mask;
178 uint32_t map_mask = 0xFFFFFFFF;
179 uint32_t map_mask_high = 0xFFFFFFFF;
180 uint32_t map_mask_osd = 0xFFFF;
181
182 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
183 if (ctrl_data->map_mask[0] & BIT(i)) {
184 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
185 if ((sea_btns_mask[i] & 0xF0000000) == 0xF0000000) {
186 map_tmp->buttons_high &= ~(sea_btns_mask[i] & 0x000000FF);
187 map_mask_high &= ~(sea_btns_mask[i] & 0x000000FF);
188 }
189 else {
190 map_tmp->buttons &= ~sea_btns_mask[i];
191 map_mask &= ~sea_btns_mask[i];
192 }
193 map_tmp->buttons_osd |= sea_gbahd_btns_mask[i];
194 map_mask_osd &= ~sea_gbahd_btns_mask[i];
195 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
196 }
197 else {
198 if ((sea_btns_mask[i] & 0xF0000000) == 0xF0000000) {
199 if (map_mask & (sea_btns_mask[i] & 0x000000FF)) {
200 map_tmp->buttons_high |= sea_btns_mask[i] & 0x000000FF;
201 }
202 }
203 else {
204 if (map_mask & sea_btns_mask[i]) {
205 map_tmp->buttons |= sea_btns_mask[i];
206 }
207 }
208 if (map_mask_osd & sea_gbahd_btns_mask[i]) {
209 map_tmp->buttons_osd &= ~sea_gbahd_btns_mask[i];
210 }
211 wired_data->cnt_mask[i] = 0;
212 }
213 }
214 }
215
216 if (!(map_tmp->gbahd_state & BIT(GBAHD_STATE_OSD))) {
217 GPIO.out = map_tmp->buttons | turbo_map_mask->buttons;
218 GPIO.out1.val = map_tmp->buttons_high | turbo_map_mask->buttons_high;
219 }
220
221 gbahd_osd(ctrl_data, wired_data);
222
223 TESTS_CMDS_LOG("\"wired_output\": {\"btns\": [%ld, %ld, %d]},\n",
224 map_tmp->buttons, map_tmp->buttons_high, map_tmp->buttons_osd);
225 BT_MON_LOG("\"wired_output\": {\"btns\": [%08lX, %08lX, %04X]},\n",
226 map_tmp->buttons, map_tmp->buttons_high, map_tmp->buttons_osd);
227 }
228 }
229
230 void sea_gen_turbo_mask(struct wired_data *wired_data) {
231 struct sea_map *map_mask = (struct sea_map *)wired_data->output_mask;
232
233 memset(map_mask, 0, sizeof(*map_mask));
234 map_mask->buttons_osd = 0xFFFF;
235
236 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
237 uint8_t mask = wired_data->cnt_mask[i] >> 1;
238
239 if (mask) {
240 if (sea_btns_mask[i]) {
241 if (wired_data->cnt_mask[i] & 1) {
242 if (!(mask & wired_data->frame_cnt)) {
243 if ((sea_btns_mask[i] & 0xF0000000) == 0xF0000000) {
244 map_mask->buttons_high |= sea_btns_mask[i];
245 }
246 else {
247 map_mask->buttons |= sea_btns_mask[i];
248 }
249 map_mask->buttons_osd &= ~sea_gbahd_btns_mask[i];
250 }
251 }
252 else {
253 if (!((mask & wired_data->frame_cnt) == mask)) {
254 if ((sea_btns_mask[i] & 0xF0000000) == 0xF0000000) {
255 map_mask->buttons_high |= sea_btns_mask[i];
256 }
257 else {
258 map_mask->buttons |= sea_btns_mask[i];
259 }
260 map_mask->buttons_osd &= ~sea_gbahd_btns_mask[i];
261 }
262 }
263 }
264 }
265 }
266 }
267