diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 14f8cd75..8fa93c2d 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -18,6 +18,7 @@ idf_component_register(SRCS "main.c" "adapter/wired/dc.c" "adapter/wired/gc.c" "adapter/wired/ps.c" + "adapter/wired/sea.c" "adapter/wired/parallel_1p.c" "adapter/wired/parallel_2p.c" "adapter/wired/wired.c" @@ -68,6 +69,7 @@ idf_component_register(SRCS "main.c" "wired/ps_spi.c" "wired/real_spi.c" "wired/jag_io.c" + "wired/sea_io.c" "zephyr/atomic.S" "zephyr/xtensa_context.S" PRIV_INCLUDE_DIRS "." diff --git a/main/adapter/wired/parallel_1p.c b/main/adapter/wired/parallel_1p.c index 34d73775..e2db066c 100644 --- a/main/adapter/wired/parallel_1p.c +++ b/main/adapter/wired/parallel_1p.c @@ -6,21 +6,6 @@ #include "soc/gpio_struct.h" #include "driver/gpio.h" -#ifdef CONFIG_BLUERETRO_SYSTEM_SEA_BOARD -#define P1_LD_UP 19 -#define P1_LD_DOWN 4 -#define P1_LD_LEFT 18 -#define P1_LD_RIGHT 13 -#define P1_RB_DOWN 5 -#define P1_RB_RIGHT 21 -#define P1_RB_LEFT 23 -#define P1_RB_UP 12 -#define P1_MM 16 -#define P1_MS 22 -#define P1_MT 33 -#define P1_LM 15 -#define P1_RM 14 -#else #define P1_LD_UP 3 #define P1_LD_DOWN 5 #define P1_LD_LEFT 18 @@ -34,7 +19,6 @@ #define P1_MT 16 #define P1_LM 25 #define P1_RM 33 -#endif struct para_1p_map { uint32_t buttons; @@ -49,15 +33,9 @@ static const uint32_t para_1p_btns_mask[32] = { BIT(P1_LD_LEFT), BIT(P1_LD_RIGHT), BIT(P1_LD_DOWN), BIT(P1_LD_UP), 0, 0, 0, 0, BIT(P1_RB_LEFT), BIT(P1_RB_RIGHT), BIT(P1_RB_DOWN), BIT(P1_RB_UP), -#ifdef CONFIG_BLUERETRO_SYSTEM_SEA_BOARD - BIT(P1_MM), BIT(P1_MS), BIT(P1_MT - 32) | 0xF0000000, 0, - BIT(P1_LM), BIT(P1_LM), 0, 0, - BIT(P1_RM), BIT(P1_RM), 0, 0, -#else BIT(P1_MM - 32) | 0xF0000000, BIT(P1_MS), BIT(P1_MT), 0, BIT(P1_LM), BIT(P1_LM), 0, 0, BIT(P1_RM - 32) | 0xF0000000, BIT(P1_RM - 32) | 0xF0000000, 0, 0, -#endif }; void IRAM_ATTR para_1p_init_buffer(int32_t dev_mode, struct wired_data *wired_data) { diff --git a/main/adapter/wired/sea.c b/main/adapter/wired/sea.c new file mode 100644 index 00000000..4510d830 --- /dev/null +++ b/main/adapter/wired/sea.c @@ -0,0 +1,142 @@ +#include +#include "adapter/config.h" +#include "zephyr/types.h" +#include "tools/util.h" +#include "parallel_1p.h" +#include "soc/gpio_struct.h" +#include "driver/gpio.h" +#include "wired/sea_io.h" + +#define P1_LD_UP 19 +#define P1_LD_DOWN 22 +#define P1_LD_LEFT 18 +#define P1_LD_RIGHT 21 +#define P1_RB_DOWN 5 +#define P1_RB_RIGHT 13 +#define P1_RB_LEFT 23 +#define P1_RB_UP 12 +#define P1_MM 16 +#define P1_MS 4 +#define P1_MT 33 +#define P1_LM 15 +#define P1_RM 14 + +enum { + GBAHD_B = 0, + GBAHD_A, + GBAHD_LD_LEFT, + GBAHD_LD_RIGHT, + GBAHD_LD_DOWN, + GBAHD_LD_UP, + GBAHD_OSD, +}; + +struct sea_map { + uint32_t buttons; + uint32_t buttons_high; + uint8_t buttons_osd; +} __packed; + +static const uint32_t sea_mask[4] = {0x337F0F00, 0x00000000, 0x00000000, 0x00000000}; +static const uint32_t sea_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000}; +static const uint32_t sea_btns_mask[32] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + BIT(P1_LD_LEFT), BIT(P1_LD_RIGHT), BIT(P1_LD_DOWN), BIT(P1_LD_UP), + 0, 0, 0, 0, + BIT(P1_RB_LEFT), BIT(P1_RB_RIGHT), BIT(P1_RB_DOWN), BIT(P1_RB_UP), + BIT(P1_MM), BIT(P1_MS), BIT(P1_MT - 32) | 0xF0000000, 0, + BIT(P1_LM), BIT(P1_LM), 0, 0, + BIT(P1_RM), BIT(P1_RM), 0, 0, +}; +static const uint32_t sea_gbahd_btns_mask[32] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + BIT(GBAHD_LD_LEFT), BIT(GBAHD_LD_RIGHT), BIT(GBAHD_LD_DOWN), BIT(GBAHD_LD_UP), + 0, 0, 0, 0, + BIT(GBAHD_B), 0, BIT(GBAHD_A), 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +void IRAM_ATTR sea_init_buffer(int32_t dev_mode, struct wired_data *wired_data) { + struct sea_map *map = (struct sea_map *)wired_data->output; + + map->buttons = 0xFFFDFFFF; + map->buttons_high = 0xFFFFFFFF; + map->buttons_osd = 0x00; +} + +void sea_meta_init(struct generic_ctrl *ctrl_data) { + memset((void *)ctrl_data, 0, sizeof(*ctrl_data)*WIRED_MAX_DEV); + + for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) { + ctrl_data[i].mask = sea_mask; + ctrl_data[i].desc = sea_desc; + } +} + +void sea_from_generic(int32_t dev_mode, struct generic_ctrl *ctrl_data, struct wired_data *wired_data) { + if (ctrl_data->index < 1) { + struct sea_map map_tmp; + uint32_t map_mask = 0xFFFFFFFF; + uint32_t map_mask_high = 0xFFFFFFFF; + + memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp)); + + for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) { + if (ctrl_data->map_mask[0] & BIT(i)) { + if (ctrl_data->btns[0].value & generic_btns_mask[i]) { + if ((sea_btns_mask[i] & 0xF0000000) == 0xF0000000) { + map_tmp.buttons_high &= ~(sea_btns_mask[i] & 0x000000FF); + map_mask_high &= ~(sea_btns_mask[i] & 0x000000FF); + } + else { + map_tmp.buttons &= ~sea_btns_mask[i]; + map_mask &= ~sea_btns_mask[i]; + } + map_tmp.buttons_osd |= sea_gbahd_btns_mask[i]; + } + else { + if ((sea_btns_mask[i] & 0xF0000000) == 0xF0000000) { + if (map_mask & (sea_btns_mask[i] & 0x000000FF)) { + map_tmp.buttons_high |= sea_btns_mask[i] & 0x000000FF; + } + } + else { + if (map_mask & sea_btns_mask[i]) { + map_tmp.buttons |= sea_btns_mask[i]; + } + } + map_tmp.buttons_osd &= ~sea_gbahd_btns_mask[i]; + } + } + } + + if (!(map_tmp.buttons_osd & BIT(GBAHD_OSD))) { + GPIO.out = map_tmp.buttons; + GPIO.out1.val = map_tmp.buttons_high; + } + + /* OSD buttons */ + if (ctrl_data->map_mask[0] & generic_btns_mask[PAD_MT]) { + if (ctrl_data->btns[0].value & generic_btns_mask[PAD_MT]) { + if (!atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) { + atomic_set_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE); + } + } + else { + if (atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) { + atomic_clear_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE); + + map_tmp.buttons_osd ^= BIT(GBAHD_OSD); + } + } + } + + sea_tx_byte(map_tmp.buttons_osd); + + memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp)); + } +} diff --git a/main/adapter/wired/sea.h b/main/adapter/wired/sea.h new file mode 100644 index 00000000..717165a4 --- /dev/null +++ b/main/adapter/wired/sea.h @@ -0,0 +1,9 @@ +#ifndef _SEA_H_ +#define _SEA_H_ +#include "adapter/adapter.h" + +void sea_meta_init(struct generic_ctrl *ctrl_data); +void sea_init_buffer(int32_t dev_mode, struct wired_data *wired_data); +void sea_from_generic(int32_t dev_mode, struct generic_ctrl *ctrl_data, struct wired_data *wired_data); + +#endif /* _SEA_H_ */ diff --git a/main/adapter/wired/wired.c b/main/adapter/wired/wired.c index 9b1a6cde..8fca4918 100644 --- a/main/adapter/wired/wired.c +++ b/main/adapter/wired/wired.c @@ -19,6 +19,7 @@ #include "gc.h" #include "parallel_1p.h" #include "parallel_2p.h" +#include "sea.h" #include "wired.h" static from_generic_t from_generic_func[WIRED_MAX] = { @@ -45,7 +46,7 @@ static from_generic_t from_generic_func[WIRED_MAX] = { npiso_from_generic, /* VB */ para_1p_from_generic, /* PARALLEL_1P_OD */ para_2p_from_generic, /* PARALLEL_2P_OD */ - para_1p_from_generic, /* SEA_BOARD */ + sea_from_generic, /* SEA_BOARD */ }; static fb_to_generic_t fb_to_generic_func[WIRED_MAX] = { @@ -99,7 +100,7 @@ static meta_init_t meta_init_func[WIRED_MAX] = { npiso_meta_init, /* VB */ para_1p_meta_init, /* PARALLEL_1P_OD */ para_2p_meta_init, /* PARALLEL_2P_OD */ - para_1p_meta_init, /* SEA_BOARD */ + sea_meta_init, /* SEA_BOARD */ }; static DRAM_ATTR buffer_init_t buffer_init_func[WIRED_MAX] = { @@ -126,7 +127,7 @@ static DRAM_ATTR buffer_init_t buffer_init_func[WIRED_MAX] = { npiso_init_buffer, /* VB */ para_1p_init_buffer, /* PARALLEL_1P_OD */ para_2p_init_buffer, /* PARALLEL_2P_OD */ - para_1p_init_buffer, /* SEA_BOARD */ + sea_init_buffer, /* SEA_BOARD */ }; int32_t wired_meta_init(struct generic_ctrl *ctrl_data) { diff --git a/main/linker.lf b/main/linker.lf index 3842b71d..0fe99762 100644 --- a/main/linker.lf +++ b/main/linker.lf @@ -23,4 +23,5 @@ entries: sega_io (noflash) pce_io (noflash) jag_io (noflash) + sea_io (noflash) memory_card (noflash) diff --git a/main/wired/parallel.c b/main/wired/parallel.c index 0ec79e8a..f5045368 100644 --- a/main/wired/parallel.c +++ b/main/wired/parallel.c @@ -9,11 +9,7 @@ #include "tools/util.h" static const uint8_t output_list[] = { -#ifdef CONFIG_BLUERETRO_SYSTEM_SEA_BOARD - 4, 5, 12, 13, 14, 15, 16, 18, 19, 21, 22, 23, 33 -#else 3, 5, 16, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33 -#endif }; void parallel_io_init(void) diff --git a/main/wired/sea_io.c b/main/wired/sea_io.c new file mode 100644 index 00000000..4c646e14 --- /dev/null +++ b/main/wired/sea_io.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019-2022, Jacques Gagnon + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/io_mux_reg.h" +#include +#include "soc/rmt_struct.h" +#include +#include +#include "adapter/adapter.h" +#include "system/gpio.h" +#include "zephyr/types.h" +#include "tools/util.h" + +#define GBAHD_COM_PIN 33 +#define GBAHD_BIT_PERIOD_TICKS 24 +#define BIT_ZERO 0x80080010 +#define BIT_ONE 0x80100008 +#define BIT_STOP 0x80008000 + +static const uint8_t output_list[] = { + 4, 5, 12, 13, 14, 15, 16, 18, 19, 21, 22, 23 +}; +static volatile rmt_item32_t *rmt_items = (volatile rmt_item32_t *)RMTMEM.chan[0].data32; + +void sea_tx_byte(uint8_t data) { + volatile uint32_t *item_ptr = &rmt_items[0].val; + + for (uint32_t mask = 0x80; mask; mask >>= 1, ++item_ptr) { + if (data & mask) { + *item_ptr = BIT_ONE; + } + else { + *item_ptr = BIT_ZERO; + } + } + *item_ptr = BIT_STOP; + rmt_tx_start(0, 1); +} + +void sea_init(void) { + /* SEA specific build required */ + gpio_config_t io_conf = {0}; + + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT_OD; + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pull_up_en = GPIO_PULLUP_ENABLE; + + /* Setup GBA buttons IO */ + for (uint32_t i = 0; i < ARRAY_SIZE(output_list); i++) { + io_conf.pin_bit_mask = 1ULL << output_list[i]; + gpio_config_iram(&io_conf); + gpio_set_level_iram(output_list[i], 1); + } + + /* Setup RMT peripheral for GBAHD comport */ + periph_ll_enable_clk_clear_rst(PERIPH_RMT_MODULE); + + RMT.apb_conf.fifo_mask = RMT_DATA_MODE_MEM; + RMT.conf_ch[0].conf0.div_cnt = 40; /* 80MHz (APB CLK) / 40 = 0.5us TICK */; + RMT.conf_ch[0].conf1.mem_rd_rst = 1; + RMT.conf_ch[0].conf1.mem_wr_rst = 1; + RMT.conf_ch[0].conf1.tx_conti_mode = 0; + RMT.conf_ch[0].conf0.mem_size = 8; + RMT.conf_ch[0].conf1.mem_owner = RMT_MEM_OWNER_TX; + RMT.conf_ch[0].conf1.ref_always_on = RMT_BASECLK_APB; + RMT.conf_ch[0].conf1.idle_out_en = 1; + RMT.conf_ch[0].conf1.idle_out_lv = RMT_IDLE_LEVEL_HIGH; + RMT.conf_ch[0].conf0.carrier_en = 0; + RMT.conf_ch[0].conf0.carrier_out_lv = RMT_CARRIER_LEVEL_LOW; + RMT.carrier_duty_ch[0].high = 0; + RMT.carrier_duty_ch[0].low = 0; + RMT.conf_ch[0].conf0.idle_thres = GBAHD_BIT_PERIOD_TICKS; + RMT.conf_ch[0].conf1.rx_filter_thres = 0; /* No minimum length */ + RMT.conf_ch[0].conf1.rx_filter_en = 0; + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG_IRAM[GBAHD_COM_PIN], PIN_FUNC_GPIO); + gpio_set_direction_iram(GBAHD_COM_PIN, GPIO_MODE_OUTPUT); + gpio_matrix_out(GBAHD_COM_PIN, RMT_SIG_OUT0_IDX, 0, 0); + gpio_matrix_in(GBAHD_COM_PIN, RMT_SIG_IN0_IDX, 0); + + /* No RX, just set in good state */ + rmt_ll_rx_enable(&RMT, 0, 0); + rmt_ll_rx_reset_pointer(&RMT, 0); + rmt_ll_clear_rx_end_interrupt(&RMT, 0); +} diff --git a/main/wired/sea_io.h b/main/wired/sea_io.h new file mode 100644 index 00000000..d4736333 --- /dev/null +++ b/main/wired/sea_io.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2019-2022, Jacques Gagnon + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SEA_H_ +#define _SEA_H_ + +#include + +void sea_tx_byte(uint8_t data); +void sea_init(void); + +#endif /* _SEA_H_ */ diff --git a/main/wired/wired_comm.c b/main/wired/wired_comm.c index c316cf4e..34202bd3 100644 --- a/main/wired/wired_comm.c +++ b/main/wired/wired_comm.c @@ -16,6 +16,7 @@ #include "ps_spi.h" #include "real_spi.h" #include "jag_io.h" +#include "sea_io.h" #include "adapter/adapter.h" typedef void (*wired_init_t)(void); @@ -71,7 +72,7 @@ static const wired_init_t wired_init[WIRED_MAX] = { npiso_init, /* VB */ parallel_io_init, /* PARALLEL_1P_OD */ parallel_io_init, /* PARALLEL_2P_OD */ - parallel_io_init, /* SEA_BOARD */ + sea_init, /* SEA_BOARD */ }; void wired_comm_init(void) {