GCC Code Coverage Report


Directory: main/
File: adapter/wired/jag.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 100 0.0%
Functions: 0 6 0.0%
Branches: 0 60 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2021-2025, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <string.h>
7 #include "adapter/config.h"
8 #include "adapter/wired/wired.h"
9 #include "zephyr/types.h"
10 #include "tools/util.h"
11 #include "tests/cmds.h"
12 #include "bluetooth/mon.h"
13 #include "jag.h"
14 #include "driver/gpio.h"
15 #include "wired/jag_io.h"
16
17 #define P1_J0_PIN 32
18 #define P1_J1_PIN 33
19 #define P1_J2_PIN 35
20 #define P1_J3_PIN 36
21 #define P1_J8_PIN 18
22 #define P1_J9_PIN 19
23 #define P1_J10_PIN 21
24 #define P1_J11_PIN 22
25 #define P1_B0_PIN 25
26 #define P1_B1_PIN 23
27
28 #define P1_J0_MASK (1 << (P1_J0_PIN - 32))
29 #define P1_J1_MASK (1 << (P1_J1_PIN - 32))
30 #define P1_J2_MASK (1 << (P1_J2_PIN - 32))
31 #define P1_J3_MASK (1 << (P1_J3_PIN - 32))
32 #define P1_J8_H_0_S_U_MASK (1 << P1_J8_PIN)
33 #define P1_J9_9_8_7_D_MASK (1 << P1_J9_PIN)
34 #define P1_J10_6_5_4_L_MASK (1 << P1_J10_PIN)
35 #define P1_J11_3_2_1_R_MASK (1 << P1_J11_PIN)
36 #define P1_B0_PAUSE_MASK (1 << P1_B0_PIN)
37 #define P1_B1_OP_C_B_A_MASK (1 << P1_B1_PIN)
38
39 #define NIBBLE_MASK (P1_J8_H_0_S_U_MASK | P1_J9_9_8_7_D_MASK | P1_J10_6_5_4_L_MASK | P1_J11_3_2_1_R_MASK)
40
41 struct jag_6d_axes_idx {
42 uint8_t bank_lo;
43 uint8_t bank_hi;
44 uint8_t row_lo;
45 uint8_t row_hi;
46 };
47
48 static DRAM_ATTR const struct jag_6d_axes_idx jag_6d_axes_idx[ADAPTER_MAX_AXES] =
49 {
50 {.bank_lo = 0, .bank_hi = 0, .row_lo = 0, .row_hi = 3},
51 {.bank_lo = 0, .bank_hi = 1, .row_lo = 1, .row_hi = 3},
52 {.bank_lo = 1, .bank_hi = 2, .row_lo = 0, .row_hi = 0},
53 {.bank_lo = 1, .bank_hi = 2, .row_lo = 1, .row_hi = 1},
54 {.bank_lo = 0, .bank_hi = 2, .row_lo = 2, .row_hi = 3},
55 {.bank_lo = 1, .bank_hi = 2, .row_lo = 2, .row_hi = 2},
56 };
57
58 static DRAM_ATTR const struct ctrl_meta jag_6d_axes_meta[ADAPTER_MAX_AXES] =
59 {
60 {.size_min = -128, .size_max = 127, .neutral = 0x00, .abs_max = 127, .abs_min = 128},
61 {.size_min = -128, .size_max = 127, .neutral = 0x00, .abs_max = 127, .abs_min = 128},
62 {.size_min = -128, .size_max = 127, .neutral = 0x00, .abs_max = 127, .abs_min = 128},
63 {.size_min = -128, .size_max = 127, .neutral = 0x00, .abs_max = 127, .abs_min = 128},
64 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 0},
65 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 255, .abs_min = 0},
66 };
67
68 struct jag_map {
69 uint32_t buttons[4];
70 uint32_t buttons_s1[3][4];
71 } __packed;
72
73 static const uint32_t jag_mask[4] = {0xBB7F0FFF, 0x00000000, 0x00000000, BR_COMBO_MASK};
74 static const uint32_t jag_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
75 static DRAM_ATTR const uint32_t jag_btns_mask[][32] = {
76 /* Pause, A, Up, Down, Left, Right */
77 {
78 0, 0, 0, 0,
79 0, 0, 0, 0,
80 P1_J10_6_5_4_L_MASK, P1_J11_3_2_1_R_MASK, P1_J9_9_8_7_D_MASK, P1_J8_H_0_S_U_MASK,
81 0, 0, 0, 0,
82 0, P1_B1_OP_C_B_A_MASK, 0, 0,
83 0, P1_B0_PAUSE_MASK, 0, 0,
84 0, 0, 0, 0,
85 0, 0, 0, 0,
86 },
87 /* B, *, 7, 4, 1 */
88 {
89 0, 0, P1_J9_9_8_7_D_MASK, 0,
90 P1_J10_6_5_4_L_MASK, 0, 0, P1_J11_3_2_1_R_MASK,
91 0, 0, 0, 0,
92 0, 0, 0, 0,
93 0, 0, P1_B1_OP_C_B_A_MASK, 0,
94 0, 0, 0, 0,
95 P1_J10_6_5_4_L_MASK, P1_J9_9_8_7_D_MASK, 0, P1_J8_H_0_S_U_MASK,
96 0, 0, 0, 0,
97 },
98 /* C, 0, 8, 5, 2 */
99 {
100 P1_J9_9_8_7_D_MASK, 0, 0, P1_J10_6_5_4_L_MASK,
101 0, P1_J11_3_2_1_R_MASK, 0, 0,
102 0, 0, 0, 0,
103 0, 0, 0, 0,
104 P1_B1_OP_C_B_A_MASK, 0, 0, P1_J9_9_8_7_D_MASK,
105 0, 0, P1_J8_H_0_S_U_MASK, 0,
106 0, 0, 0, 0,
107 0, 0, 0, 0,
108 },
109 /* Options, #, 9, 6, 3 */
110 {
111 0, P1_J10_6_5_4_L_MASK, 0, 0,
112 0, 0, P1_J11_3_2_1_R_MASK, 0,
113 0, 0, 0, 0,
114 0, 0, 0, 0,
115 0, 0, 0, 0,
116 P1_B1_OP_C_B_A_MASK, 0, 0, 0,
117 0, 0, 0, 0,
118 P1_J10_6_5_4_L_MASK, P1_J9_9_8_7_D_MASK, 0, P1_J8_H_0_S_U_MASK,
119 },
120 };
121
122 static const uint32_t jag_6d_mask[4] = {0xFFFF7FFF, 0x00000000, 0x00000000, BR_COMBO_MASK};
123 static const uint32_t jag_6d_desc[4] = {0x110000FF, 0x00000000, 0x00000000, 0x00000000};
124 static DRAM_ATTR const uint32_t jag_6d_btns_mask[][32] = {
125 /* Pause, A, Up, Down, Left, Right */
126 {
127 0, 0, 0, 0,
128 0, 0, 0, 0,
129 P1_J10_6_5_4_L_MASK, P1_J11_3_2_1_R_MASK, P1_J9_9_8_7_D_MASK, P1_J8_H_0_S_U_MASK,
130 0, 0, 0, 0,
131 0, P1_B1_OP_C_B_A_MASK, 0, 0,
132 0, P1_B0_PAUSE_MASK, 0, 0,
133 0, 0, 0, 0,
134 0, 0, 0, 0,
135 },
136 /* B, *, 7, 4, 1 */
137 {
138 0, 0, 0, 0,
139 0, 0, 0, 0,
140 0, 0, 0, 0,
141 P1_J8_H_0_S_U_MASK, 0, 0, 0,
142 0, 0, P1_B1_OP_C_B_A_MASK, 0,
143 0, 0, 0, 0,
144 0, P1_J10_6_5_4_L_MASK, P1_J11_3_2_1_R_MASK, P1_J9_9_8_7_D_MASK,
145 0, 0, 0, 0,
146 },
147 /* C, 0, 8, 5, 2 */
148 {
149 0, 0, 0, 0,
150 0, 0, 0, 0,
151 0, 0, 0, 0,
152 0, P1_J8_H_0_S_U_MASK, 0, 0,
153 P1_B1_OP_C_B_A_MASK, 0, 0, P1_J9_9_8_7_D_MASK,
154 0, 0, P1_J11_3_2_1_R_MASK, P1_J10_6_5_4_L_MASK,
155 0, 0, 0, 0,
156 0, 0, 0, 0,
157 },
158 /* Options, #, 9, 6, 3 */
159 {
160 0, 0, 0, 0,
161 0, 0, 0, 0,
162 0, 0, 0, 0,
163 0, 0, P1_J8_H_0_S_U_MASK, 0,
164 0, 0, 0, 0,
165 P1_B1_OP_C_B_A_MASK, 0, 0, 0,
166 0, 0, 0, 0,
167 0, P1_J10_6_5_4_L_MASK, P1_J11_3_2_1_R_MASK, P1_J9_9_8_7_D_MASK,
168 },
169 };
170
171 static const uint8_t jag_6d_btns_idx[32] = {
172 0, 0, 0, 0,
173 0, 0, 0, 0,
174 0, 0, 0, 0,
175 0, 0, 0, 0,
176 0x92, 0x81, 0x82, 0x93,
177 0, 0, 0x91, 0,
178 0, 0x83, 0, 0,
179 0, 0x80, 0, 0,
180 };
181 static const uint32_t jag_6d_nibble_mask[4] = {
182 P1_J8_H_0_S_U_MASK, P1_J9_9_8_7_D_MASK, P1_J10_6_5_4_L_MASK, P1_J11_3_2_1_R_MASK
183 };
184 static DRAM_ATTR const uint32_t jag_6d_cbits[3][4] = {
185 {P1_B0_PAUSE_MASK, 0, P1_B0_PAUSE_MASK, 0},
186 {0, 0, P1_B0_PAUSE_MASK, 0},
187 {0, 0, P1_B0_PAUSE_MASK, 0},
188 };
189 static DRAM_ATTR const uint32_t jag_6d_bbits[3][4] = {
190 {0, 0, 0, 0},
191 {0, 0, 0, 0},
192 {P1_B1_OP_C_B_A_MASK, 0, 0, 0},
193 };
194
195
196 void IRAM_ATTR jag_init_buffer(int32_t dev_mode, struct wired_data *wired_data) {
197 switch (dev_mode) {
198 default:
199 {
200 struct jag_map *map = (struct jag_map *)wired_data->output;
201 struct jag_map *map_mask = (struct jag_map *)wired_data->output_mask;
202
203 for (uint32_t i = 0; i < 4; i++) {
204 map->buttons[i] = 0xFFFDFFFD;
205 map_mask->buttons[i] = 0x00000000;
206 }
207 for (uint32_t i = 0; i < 3; i++) {
208 for (uint32_t j = 0; j < 4; j++) {
209 map->buttons_s1[i][j] = 0xFFFDFFFD & ~(NIBBLE_MASK | jag_6d_cbits[i][j] | jag_6d_bbits[i][j]);
210 map_mask->buttons_s1[i][j] = 0x00000000;
211 }
212 }
213 if (config.global_cfg.multitap_cfg == MT_SLOT_1) {
214 struct jag_map *map3 = (struct jag_map *)wired_adapter.data[3].output;
215
216 map3->buttons[1] = 0xFFFDFFFD & ~P1_B0_PAUSE_MASK;
217 for (uint32_t i = 0; i < 3; i++) {
218 map3->buttons_s1[i][1] &= ~P1_B0_PAUSE_MASK;
219 }
220 }
221 break;
222 }
223 }
224 }
225
226 void jag_meta_init(struct wired_ctrl *ctrl_data) {
227 memset((void *)ctrl_data, 0, sizeof(*ctrl_data)*WIRED_MAX_DEV);
228
229 for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) {
230 for (uint32_t j = 0; j < ADAPTER_MAX_AXES; j++) {
231 switch (config.out_cfg[i].dev_mode) {
232 case DEV_PAD_ALT:
233 ctrl_data[i].mask = jag_6d_mask;
234 ctrl_data[i].desc = jag_6d_desc;
235 ctrl_data[i].axes[j].meta = &jag_6d_axes_meta[j];
236 break;
237 default:
238 ctrl_data[i].mask = jag_mask;
239 ctrl_data[i].desc = jag_desc;
240 }
241 }
242 }
243 }
244
245 static void jag_ctrl_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
246 struct jag_map map_tmp;
247 uint32_t map_mask[4];
248
249 memset(map_mask, 0xFF, sizeof(map_mask));
250 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
251
252 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
253 if (ctrl_data->map_mask[0] & BIT(i)) {
254 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
255 for (uint32_t j = 0; j < 4; j++) {
256 map_tmp.buttons[j] &= ~jag_btns_mask[j][i];
257 map_mask[j] &= ~jag_btns_mask[j][i];
258 }
259 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
260 }
261 else {
262 for (uint32_t j = 0; j < 4; j++) {
263 if (map_mask[j] & jag_btns_mask[j][i]) {
264 map_tmp.buttons[j] |= jag_btns_mask[j][i];
265 }
266 }
267 wired_data->cnt_mask[i] = 0;
268 }
269 }
270 }
271
272 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
273
274 TESTS_CMDS_LOG("\"wired_output\": {\"btns\": [%ld, %ld, %ld, %ld]},\n",
275 map_tmp.buttons[0], map_tmp.buttons[1], map_tmp.buttons[2], map_tmp.buttons[3]);
276 BT_MON_LOG("\"wired_output\": {\"btns\": [%08lX, %08lX, %08lX, %08lX]},\n",
277 map_tmp.buttons[0], map_tmp.buttons[1], map_tmp.buttons[2], map_tmp.buttons[3]);
278 }
279
280 static void jag_6d_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
281 struct jag_map map_tmp;
282
283 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
284
285 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
286 if (ctrl_data->map_mask[0] & BIT(i)) {
287 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
288 for (uint32_t j = 0; j < 4; j++) {
289 map_tmp.buttons[j] &= ~jag_6d_btns_mask[j][i];
290 }
291 if (jag_6d_btns_idx[i]) {
292 map_tmp.buttons_s1[(jag_6d_btns_idx[i] >> 4) & 0x3][jag_6d_btns_idx[i] & 0xF] &= ~P1_B1_OP_C_B_A_MASK;
293 }
294 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
295 }
296 else {
297 for (uint32_t j = 0; j < 4; j++) {
298 map_tmp.buttons[j] |= jag_6d_btns_mask[j][i];
299 }
300 if (jag_6d_btns_idx[i]) {
301 map_tmp.buttons_s1[(jag_6d_btns_idx[i] >> 4) & 0x3][jag_6d_btns_idx[i] & 0xF] |= P1_B1_OP_C_B_A_MASK;
302 }
303 }
304 }
305 }
306
307 for (uint32_t i = 0; i < ADAPTER_MAX_AXES; i++) {
308 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & jag_6d_desc[0])) {
309 uint8_t tmp = ctrl_data->axes[i].meta->neutral;
310
311 if (ctrl_data->axes[i].value > ctrl_data->axes[i].meta->size_max) {
312 tmp = 127;
313 }
314 else if (ctrl_data->axes[i].value < ctrl_data->axes[i].meta->size_min) {
315 tmp = -128;
316 }
317 else {
318 tmp = (uint8_t)(ctrl_data->axes[i].value + ctrl_data->axes[i].meta->neutral);
319 }
320
321 map_tmp.buttons_s1[jag_6d_axes_idx[i].bank_hi][jag_6d_axes_idx[i].row_hi] &= ~NIBBLE_MASK;
322 map_tmp.buttons_s1[jag_6d_axes_idx[i].bank_lo][jag_6d_axes_idx[i].row_lo] &= ~NIBBLE_MASK;
323 for (uint32_t j = 0, mask_l = 0x01, mask_h = 0x10; j < 4; ++j, mask_l <<= 1, mask_h <<= 1) {
324 if (mask_h & tmp) {
325 map_tmp.buttons_s1[jag_6d_axes_idx[i].bank_hi][jag_6d_axes_idx[i].row_hi] |= jag_6d_nibble_mask[j];
326 }
327 if (mask_l & tmp) {
328 map_tmp.buttons_s1[jag_6d_axes_idx[i].bank_lo][jag_6d_axes_idx[i].row_lo] |= jag_6d_nibble_mask[j];
329 }
330 }
331 }
332 }
333
334 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
335
336 TESTS_CMDS_LOG("\"wired_output\": {\"btns\": [%ld, %ld, %ld, %ld]},\n",
337 map_tmp.buttons[0], map_tmp.buttons[1], map_tmp.buttons[2], map_tmp.buttons[3]);
338 BT_MON_LOG("\"wired_output\": {\"btns\": [%08lX, %08lX, %08lX, %08lX]},\n",
339 map_tmp.buttons[0], map_tmp.buttons[1], map_tmp.buttons[2], map_tmp.buttons[3]);
340 }
341
342 void jag_from_generic(int32_t dev_mode, struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
343 switch (dev_mode) {
344 case DEV_PAD_ALT:
345 jag_6d_from_generic(ctrl_data, wired_data);
346 break;
347 default:
348 jag_ctrl_from_generic(ctrl_data, wired_data);
349 break;
350 }
351 jag_io_force_update();
352 }
353
354 void IRAM_ATTR jag_gen_turbo_mask(struct wired_data *wired_data) {
355 const uint32_t (*btns_mask)[32] = (config.out_cfg[0].dev_mode == DEV_PAD_ALT) ? jag_6d_btns_mask : jag_btns_mask;
356 struct jag_map *map_mask = (struct jag_map *)wired_data->output_mask;
357
358 memset(map_mask, 0, sizeof(*map_mask));
359
360 wired_gen_turbo_mask_btns32(wired_data, map_mask->buttons, btns_mask, 4);
361 }
362