-
-
Notifications
You must be signed in to change notification settings - Fork 114
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
42de0a0
commit daa0c1c
Showing
4 changed files
with
363 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,353 @@ | ||
#include <string.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <freertos/FreeRTOS.h> | ||
#include <freertos/task.h> | ||
#include <xtensa/hal.h> | ||
#include <esp_intr_alloc.h> | ||
#include "driver/gpio.h" | ||
#include "../zephyr/types.h" | ||
#include "../util.h" | ||
#include "../adapter/adapter.h" | ||
#include "../adapter/config.h" | ||
#include "npiso.h" | ||
|
||
#define NPISO_PORT_MAX 2 | ||
#define NPISO_LATCH_PIN 32 | ||
#define NPISO_LATCH_MASK (1U << 0) /* First of 2nd bank of GPIO */ | ||
#define NPISO_TIMEOUT 4096 | ||
|
||
enum { | ||
NPISO_CLK = 0, | ||
NPISO_SEL, | ||
NPISO_D0, | ||
NPISO_D1, | ||
NPISO_PIN_MAX, | ||
}; | ||
|
||
enum { | ||
DEV_NONE = 0, | ||
DEV_FC_NES_PAD, | ||
DEV_FC_NES_MULTITAP, | ||
DEV_FC_MULTITAP_ALT, | ||
DEV_FC_TRACKBALL, | ||
DEV_FC_KB, | ||
DEV_SFC_SNES_PAD, | ||
DEV_SFC_SNES_MULTITAP, | ||
DEV_SFC_SNES_MOUSE, | ||
DEV_SNES_XBAND_KB, | ||
}; | ||
|
||
static const uint8_t gpio_pins[NPISO_PORT_MAX][NPISO_PIN_MAX] = { | ||
{ 5, 23, 19, 21}, | ||
{18, 26, 22, 25}, | ||
}; | ||
|
||
static const uint32_t gpio_mask[NPISO_PORT_MAX][NPISO_PIN_MAX] = { | ||
{(1U << 5), (1U << 23), (1U << 19), (1U << 21)}, | ||
{(1U << 18), (1U << 26), (1U << 22), (1U << 25)}, | ||
}; | ||
|
||
static uint8_t dev_type[NPISO_PORT_MAX] = {0}; | ||
static uint8_t mt_first_port[NPISO_PORT_MAX] = {0}; | ||
static uint8_t buffer[8]; | ||
static uint32_t cnt[2] = {0}; | ||
static uint8_t mask[2] = {0x80, 0x80}; | ||
|
||
static void IRAM_ATTR set_data(uint8_t port, uint8_t data_id, uint8_t value) { | ||
uint8_t pin = gpio_pins[port][NPISO_D0 + data_id]; | ||
|
||
if (value) { | ||
GPIO.out_w1ts = BIT(pin); | ||
} | ||
else { | ||
GPIO.out_w1tc = BIT(pin); | ||
} | ||
} | ||
|
||
static void IRAM_ATTR npiso_fc_nes_2p_isr(void* arg) { | ||
const uint32_t low_io = GPIO.acpu_int; | ||
const uint32_t high_io = GPIO.acpu_int1.intr; | ||
|
||
/* reset bit counter, set first bit */ | ||
if (high_io & NPISO_LATCH_MASK) { | ||
set_data(0, 0, wired_adapter.data[0].output[0] & 0x80); | ||
set_data(1, 0, wired_adapter.data[1].output[0] & 0x80); | ||
cnt[0] = 1; | ||
cnt[1] = 1; | ||
mask[0] = 0x40; | ||
mask[1] = 0x40; | ||
} | ||
|
||
/* Update port 0 */ | ||
if (low_io & gpio_mask[0][NPISO_CLK]) { | ||
if (cnt[0] > 7) { | ||
set_data(0, 0, 0); | ||
} | ||
else { | ||
set_data(0, 0, wired_adapter.data[0].output[0] & mask[0]); | ||
} | ||
cnt[0]++; | ||
mask[0] >>= 1; | ||
} | ||
|
||
/* Update port 1 */ | ||
if (low_io & gpio_mask[1][NPISO_CLK]) { | ||
if (cnt[1] > 7) { | ||
set_data(1, 0, 0); | ||
} | ||
else { | ||
set_data(1, 0, wired_adapter.data[1].output[0] & mask[1]); | ||
} | ||
cnt[1]++; | ||
mask[1] >>= 1; | ||
} | ||
|
||
if (high_io) GPIO.status1_w1tc.intr_st = high_io; | ||
if (low_io) GPIO.status_w1tc = low_io; | ||
} | ||
|
||
static void IRAM_ATTR npiso_fc_4p_isr(void* arg) { | ||
const uint32_t low_io = GPIO.acpu_int; | ||
const uint32_t high_io = GPIO.acpu_int1.intr; | ||
|
||
/* reset bit counter, set first bit */ | ||
if (high_io & NPISO_LATCH_MASK) { | ||
set_data(0, 0, wired_adapter.data[0].output[0] & 0x80); | ||
set_data(1, 0, wired_adapter.data[1].output[0] & 0x80); | ||
set_data(0, 1, wired_adapter.data[2].output[0] & 0x80); | ||
set_data(1, 1, wired_adapter.data[3].output[0] & 0x80); | ||
cnt[0] = 1; | ||
cnt[1] = 1; | ||
mask[0] = 0x40; | ||
mask[1] = 0x40; | ||
} | ||
|
||
/* Update port 0 */ | ||
if (low_io & gpio_mask[0][NPISO_CLK]) { | ||
if (cnt[0] > 7) { | ||
set_data(0, 0, 0); | ||
set_data(0, 1, 0); | ||
} | ||
else { | ||
set_data(0, 0, wired_adapter.data[0].output[0] & mask[0]); | ||
set_data(0, 1, wired_adapter.data[2].output[0] & mask[0]); | ||
} | ||
cnt[0]++; | ||
mask[0] >>= 1; | ||
} | ||
|
||
/* Update port 1 */ | ||
if (low_io & gpio_mask[1][NPISO_CLK]) { | ||
if (cnt[1] > 7) { | ||
set_data(1, 0, 0); | ||
set_data(1, 1, 0); | ||
} | ||
else { | ||
set_data(1, 0, wired_adapter.data[1].output[0] & mask[1]); | ||
set_data(1, 1, wired_adapter.data[3].output[0] & mask[1]); | ||
} | ||
cnt[1]++; | ||
mask[1] >>= 1; | ||
} | ||
|
||
if (high_io) GPIO.status1_w1tc.intr_st = high_io; | ||
if (low_io) GPIO.status_w1tc = low_io; | ||
} | ||
|
||
static void IRAM_ATTR npiso_nes_fs_isr(void* arg) { | ||
const uint32_t low_io = GPIO.acpu_int; | ||
const uint32_t high_io = GPIO.acpu_int1.intr; | ||
uint32_t idx0, idx1; | ||
|
||
/* reset bit counter, set first bit */ | ||
if (high_io & NPISO_LATCH_MASK) { | ||
set_data(0, 0, wired_adapter.data[0].output[0] & 0x80); | ||
set_data(1, 0, wired_adapter.data[1].output[0] & 0x80); | ||
cnt[0] = 1; | ||
cnt[1] = 1; | ||
mask[0] = 0x40; | ||
mask[1] = 0x40; | ||
} | ||
|
||
idx0 = cnt[0] >> 3; | ||
idx1 = cnt[1] >> 3; | ||
|
||
/* Update port 0 */ | ||
if (low_io & gpio_mask[0][NPISO_CLK]) { | ||
switch (idx0) { | ||
case 0: | ||
set_data(0, 0, wired_adapter.data[0].output[0] & mask[0]); | ||
break; | ||
case 1: | ||
set_data(0, 0, wired_adapter.data[2].output[0] & mask[0]); | ||
break; | ||
case 2: | ||
set_data(0, 0, 0xEF & mask[0]); | ||
break; | ||
default: | ||
set_data(0, 0, 0); | ||
break; | ||
} | ||
cnt[0]++; | ||
mask[0] >>= 1; | ||
if (!mask[0]) { | ||
mask[0] = 0x80; | ||
} | ||
} | ||
|
||
/* Update port 1 */ | ||
if (low_io & gpio_mask[1][NPISO_CLK]) { | ||
switch (idx1) { | ||
case 0: | ||
set_data(1, 0, wired_adapter.data[1].output[0] & mask[1]); | ||
break; | ||
case 1: | ||
set_data(1, 0, wired_adapter.data[3].output[0] & mask[1]); | ||
break; | ||
case 2: | ||
set_data(1, 0, 0xDF & mask[1]); | ||
break; | ||
default: | ||
set_data(1, 0, 0); | ||
break; | ||
} | ||
cnt[1]++; | ||
mask[1] >>= 1; | ||
if (!mask[1]) { | ||
mask[1] = 0x80; | ||
} | ||
} | ||
|
||
if (high_io) GPIO.status1_w1tc.intr_st = high_io; | ||
if (low_io) GPIO.status_w1tc = low_io; | ||
} | ||
|
||
void npiso_init(void) | ||
{ | ||
gpio_config_t io_conf = {0}; | ||
|
||
if (wired_adapter.system_id == NES) { | ||
switch (config.global_cfg.multitap_cfg) { | ||
case MT_SLOT_1: | ||
case MT_SLOT_2: | ||
case MT_DUAL: | ||
dev_type[0] = DEV_FC_NES_MULTITAP; | ||
dev_type[1] = DEV_FC_NES_MULTITAP; | ||
mt_first_port[1] = 2; | ||
break; | ||
case MT_ALT: | ||
dev_type[0] = DEV_FC_MULTITAP_ALT; | ||
dev_type[1] = DEV_FC_MULTITAP_ALT; | ||
break; | ||
default: | ||
mt_first_port[1] = 1; | ||
break; | ||
} | ||
|
||
for (uint32_t i = 0; i < NPISO_PORT_MAX; i++) { | ||
if (dev_type[i] == DEV_NONE) { | ||
switch (config.out_cfg[i].dev_mode) { | ||
case DEV_PAD: | ||
case DEV_PAD_ALT: | ||
dev_type[i] = DEV_FC_NES_PAD; | ||
break; | ||
case DEV_KB: | ||
dev_type[i] = DEV_FC_KB; | ||
break; | ||
case DEV_MOUSE: | ||
dev_type[i] = DEV_FC_TRACKBALL; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
else { | ||
switch (config.global_cfg.multitap_cfg) { | ||
case MT_SLOT_1: | ||
dev_type[0] = DEV_SFC_SNES_MULTITAP; | ||
mt_first_port[1] = 4; | ||
break; | ||
case MT_SLOT_2: | ||
dev_type[1] = DEV_SFC_SNES_MULTITAP; | ||
mt_first_port[1] = 1; | ||
break; | ||
case MT_DUAL: | ||
dev_type[0] = DEV_SFC_SNES_MULTITAP; | ||
dev_type[1] = DEV_SFC_SNES_MULTITAP; | ||
mt_first_port[1] = 4; | ||
break; | ||
default: | ||
mt_first_port[1] = 1; | ||
break; | ||
} | ||
|
||
for (uint32_t i = 0; i < NPISO_PORT_MAX; i++) { | ||
if (dev_type[i] == DEV_NONE) { | ||
switch (config.out_cfg[i].dev_mode) { | ||
case DEV_PAD: | ||
case DEV_PAD_ALT: | ||
dev_type[i] = DEV_SFC_SNES_PAD; | ||
break; | ||
case DEV_KB: | ||
dev_type[i] = DEV_SNES_XBAND_KB; | ||
break; | ||
case DEV_MOUSE: | ||
dev_type[i] = DEV_SFC_SNES_MOUSE; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
/* Latch */ | ||
io_conf.intr_type = GPIO_PIN_INTR_POSEDGE; | ||
io_conf.pin_bit_mask = 1ULL << NPISO_LATCH_PIN; | ||
io_conf.mode = GPIO_MODE_INPUT; | ||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; | ||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; | ||
gpio_config(&io_conf); | ||
|
||
/* Clocks */ | ||
for (uint32_t i = 0; i < NPISO_PORT_MAX; i++) { | ||
io_conf.intr_type = GPIO_PIN_INTR_POSEDGE; | ||
io_conf.pin_bit_mask = 1ULL << gpio_pins[i][NPISO_CLK]; | ||
io_conf.mode = GPIO_MODE_INPUT; | ||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; | ||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; | ||
gpio_config(&io_conf); | ||
} | ||
|
||
/* Selects */ | ||
for (uint32_t i = 0; i < NPISO_PORT_MAX; i++) { | ||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE; | ||
io_conf.pin_bit_mask = 1ULL << gpio_pins[i][NPISO_SEL]; | ||
io_conf.mode = GPIO_MODE_INPUT; | ||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; | ||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; | ||
gpio_config(&io_conf); | ||
} | ||
|
||
/* D0, D1 */ | ||
for (uint32_t i = 0; i < NPISO_PORT_MAX; i++) { | ||
for (uint32_t j = NPISO_D0; j <= NPISO_D1; j++) { | ||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE; | ||
io_conf.pin_bit_mask = 1ULL << gpio_pins[i][j]; | ||
io_conf.mode = GPIO_MODE_OUTPUT; | ||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; | ||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; | ||
gpio_config(&io_conf); | ||
set_data(i, j & 0x1, 1); | ||
} | ||
} | ||
|
||
if (dev_type[0] == DEV_FC_NES_MULTITAP) { | ||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3, npiso_nes_fs_isr, NULL, NULL); | ||
} | ||
else if (dev_type[0] == DEV_FC_MULTITAP_ALT) { | ||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3, npiso_fc_4p_isr, NULL, NULL); | ||
} | ||
else { | ||
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3, npiso_fc_nes_2p_isr, NULL, NULL); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef _NPISO_H_ | ||
#define _NPISO_H_ | ||
|
||
void npiso_init(void); | ||
|
||
#endif /* _NPISO_H_ */ |