Skip to content

Commit e8eeca1

Browse files
committed
Expose HID, TIMERS, GPIO in CPU mapped space
1 parent 905f48e commit e8eeca1

File tree

10 files changed

+144
-26
lines changed

10 files changed

+144
-26
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"name": "Launch",
1111
"cwd": "${workspaceFolder}",
1212
"program": "${workspaceFolder}/build/emu",
13-
"args": ["-z", "../examples/build/src/bitmap_modes.xex"],
13+
"args": ["-z", "../examples/build/src/controller.xex"],
1414
"preLaunchTask": "CMake: build"
1515
},
1616
{

ext/pico.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,12 @@
33
#define __in_flash(s)
44
#define __not_in_flash(s)
55
#define __not_in_flash_func(f) f
6+
7+
#if PICO_C_COMPILER_IS_GNU && (__GNUC__ <= 6 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || !defined(__cplusplus))))
8+
#define __force_inline inline __always_inline
9+
#else
10+
#define __force_inline __always_inline
11+
#endif
12+
13+
#define _STRINGIFY(x) #x
14+
#define STRINGIFY(x) _STRINGIFY(x)

src/chips/m6526.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ void m6526_reset(m6526_t* c);
273273
// tick the m6526_t instance
274274
uint64_t m6526_tick(m6526_t* c, uint64_t pins);
275275

276+
uint8_t m6526_read(m6526_t* c, uint8_t addr);
277+
276278
#ifdef __cplusplus
277279
} // extern "C"
278280
#endif
@@ -578,7 +580,7 @@ static inline void _m6526_write_cr(m6526_timer_t* t, uint8_t data) {
578580
}
579581

580582
/* read a register */
581-
static uint8_t _m6526_read(m6526_t* c, uint8_t addr) {
583+
uint8_t m6526_read(m6526_t* c, uint8_t addr) {
582584
uint8_t data = 0xFF;
583585
switch (addr) {
584586
case M6526_REG_PRA:
@@ -671,7 +673,7 @@ uint64_t m6526_tick(m6526_t* c, uint64_t pins) {
671673
if (pins & M6526_CS) {
672674
uint8_t addr = pins & M6526_RS;
673675
if (pins & M6526_RW) {
674-
uint8_t data = _m6526_read(c, addr);
676+
uint8_t data = m6526_read(c, addr);
675677
M6526_SET_DATA(pins, data);
676678
}
677679
else {

src/chips/ria816.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ uint8_t ria816_uart_status(const ria816_t* c) {
6868
return data;
6969
}
7070

71-
static uint8_t _ria816_read(ria816_t* c, uint8_t addr) {
71+
uint8_t ria816_reg_read(ria816_t* c, uint8_t addr) {
7272
uint8_t data = 0xFF;
7373

7474
switch (addr) {
@@ -115,15 +115,15 @@ static uint8_t _ria816_read(ria816_t* c, uint8_t addr) {
115115
return data;
116116
}
117117

118-
static void _ria816_write(ria816_t* c, uint8_t addr, uint8_t data) {
118+
void ria816_reg_write(ria816_t* c, uint8_t addr, uint8_t data) {
119119
switch (addr) {
120120
case RIA816_UART_TX_RX: rb_put(&c->uart_tx, data); break;
121121

122122
case RIA816_IRQ_STATUS: break;
123123
case RIA816_IRQ_ENABLE: c->irq_enable = (data && 0x01); break;
124124

125125
case RIA816_API_STACK: rb_put(&c->api_stack, data); break;
126-
case RIA816_API_OP:
126+
case RIA816_API_OP_RET:
127127
if (c->api_cb) c->api_cb(data, c->user_data);
128128
break;
129129

@@ -140,25 +140,62 @@ static uint64_t _ria816_update_irq(ria816_t* c, uint64_t pins) {
140140
return pins;
141141
}
142142

143+
#include "sys/ria.h"
144+
145+
static uint8_t HID_dev = 0;
146+
147+
typedef uint32_t DWORD;
148+
#include "hid/hid.c"
149+
static void kbd_queue_char(char ch) {}
150+
static void kbd_queue_key(uint8_t modifier, uint8_t keycode, bool initial_press) {}
151+
#include "hid/kbd.c"
152+
#include "hid/mou.c"
153+
#include "hid/pad.c"
154+
uint8_t ria816_hid_read(ria816_t* c, uint8_t reg) {
155+
uint8_t data = 0xFF; // invalid
156+
switch (HID_dev & 0xF) {
157+
case RIA_HID_DEV_KEYBOARD: data = kbd_get_reg((HID_dev & 0xF0) | reg); break;
158+
case RIA_HID_DEV_MOUSE: data = mou_get_reg(reg); break;
159+
case RIA_HID_DEV_GAMEPAD: data = pad_get_reg(HID_dev >> 4, reg); break;
160+
}
161+
return data;
162+
}
163+
void ria816_hid_write(ria816_t* c, uint8_t reg, uint8_t data) {
164+
if (reg == 0x00) // HID SELECT
165+
HID_dev = data;
166+
}
167+
143168
uint64_t ria816_tick(ria816_t* c, uint64_t pins) {
144169
pins = _ria816_tick(c, pins);
145170
if (pins & RIA816_CS) {
146171
uint8_t addr = pins & RIA816_RS;
147172
if (pins & RIA816_RW) {
148-
uint8_t data = _ria816_read(c, addr);
173+
uint8_t data = ria816_reg_read(c, addr);
174+
RIA816_SET_DATA(pins, data);
175+
}
176+
else {
177+
uint8_t data = RIA816_GET_DATA(pins);
178+
ria816_reg_write(c, addr, data);
179+
}
180+
}
181+
if (pins & RIA816_HID_CS) {
182+
// HID devices
183+
const uint8_t addr = pins & RIA816_HID_RS;
184+
if (pins & M6526_RW) {
185+
uint8_t data = ria816_hid_read(c, addr);
149186
RIA816_SET_DATA(pins, data);
150187
}
151188
else {
152189
uint8_t data = RIA816_GET_DATA(pins);
153-
_ria816_write(c, addr, data);
190+
ria816_hid_write(c, addr, data);
154191
}
155192
}
156193
if (pins & RIA816_TIMERS_CS) {
157194
// CIA timers emulation
158195
uint8_t addr = pins & M6526_RS;
159196
if (addr < M6526_REG_ICR) addr -= 4;
160197
if (pins & M6526_RW) {
161-
uint8_t data = _m6526_read(&c->cia, addr);
198+
uint8_t data = m6526_read(&c->cia, addr);
162199
M6526_SET_DATA(pins, data);
163200
}
164201
else {

src/chips/ria816.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,11 @@ extern "C" {
8686

8787
// chip-specific control pins
8888
#define RIA816_PIN_CS (40)
89-
#define RIA816_PIN_TIMERS_CS (41)
90-
#define RIA816_PIN_IRQ (42)
89+
#define RIA816_PIN_IRQ (41)
90+
#define RIA816_PIN_TIMERS_CS (48)
91+
#define RIA816_PIN_RGB_CS (49)
92+
#define RIA816_PIN_BUZZER_CS (50)
93+
#define RIA816_PIN_HID_CS (52)
9194

9295
// interrupt sources
9396
#define RIA816_INT_CIA_MASK (0x01) // CIA interrupt
@@ -111,9 +114,15 @@ extern "C" {
111114
#define RIA816_DB_PINS (0xFF0000ULL)
112115
#define RIA816_RW (1ULL << RIA816_PIN_RW)
113116
#define RIA816_CS (1ULL << RIA816_PIN_CS)
114-
#define RIA816_TIMERS_CS (1ULL << RIA816_PIN_TIMERS_CS)
115-
#define RIA816_TIMERS_RS (RIA816_RS4 | RIA816_RS3 | RIA816_RS2 | RIA816_RS1 | RIA816_RS0)
116117
#define RIA816_IRQ (1ULL << RIA816_PIN_IRQ)
118+
#define RIA816_TIMERS_CS (1ULL << RIA816_PIN_TIMERS_CS)
119+
#define RIA816_TIMERS_RS (RIA816_RS2 | RIA816_RS1 | RIA816_RS0)
120+
#define RIA816_RGB_CS (1ULL << RIA816_PIN_RGB_CS)
121+
#define RIA816_RGB_RS (RIA816_RS3 | RIA816_RS2 | RIA816_RS1 | RIA816_RS0)
122+
#define RIA816_BUZZER_CS (1ULL << RIA816_PIN_BUZZER_CS)
123+
#define RIA816_BUZZER_RS (RIA816_RS1 | RIA816_RS0)
124+
#define RIA816_HID_CS (1ULL << RIA816_PIN_HID_CS)
125+
#define RIA816_HID_RS (RIA816_RS3 | RIA816_RS2 | RIA816_RS1 | RIA816_RS0)
117126

118127
// register indices
119128
#define RIA816_MATH_OPERA (0x00) // Operand A for multiplication and division.
@@ -128,9 +137,11 @@ extern "C" {
128137
#define RIA816_DMA_COUNT (0x18) // DMA transfers count.
129138
#define RIA816_DMA_DMAERR (0x19) // DMA transfer errno.
130139
#define RIA816_FS_FDA (0x1A) // File-descriptor A number. (Obtained from open() API call.)
131-
#define RIA816_FS_FDARW (0x1B) // Read bytes from the FDA. Write bytes to the FDA.
132-
#define RIA816_FS_FDB (0x1C) // File-descriptor B number.
140+
#define RIA816_FS_FDB (0x1B) // File-descriptor B number.
141+
#define RIA816_FS_FDARW (0x1C) // Read bytes from the FDA. Write bytes to the FDA.
133142
#define RIA816_FS_FDBRW (0x1D) // Read bytes from the FDB. Write bytes to the FDB.
143+
#define RIA816_FS_FDAST (0x1E) // File-descriptor A status.
144+
#define RIA816_FS_FDBST (0x1F) // File-descriptor B status.
134145
#define RIA816_UART_READY (0x20) // Flow control for UART FIFO.
135146
#define RIA816_UART_TX_RX (0x21) // Write bytes to the UART. Read bytes from the UART.
136147
#define RIA816_HW_RNG (0x22) // Random Number Generator.
@@ -141,7 +152,7 @@ extern "C" {
141152
#define RIA816_IRQ_ENABLE (0x2C) // RIA interrupts enable
142153
#define RIA816_IRQ_STATUS (0x2D) // Interrupt Controller status
143154
#define RIA816_CPU_N_IRQB (0x2E) // 65816 vector.
144-
#define RIA816_API_OP (0x30) // Write the API operation id here to begin a kernel call.
155+
#define RIA816_API_OP_RET (0x30) // Write the API operation id here to begin a kernel call.
145156
#define RIA816_API_RET_HI (0x31) // High byte of 16 bit return value. Otherwise `0`.
146157
#define RIA816_API_STACK (0x32) // 512 bytes for passing call parameters.
147158
#define RIA816_API_STATUS (0x33) // Bit 7 high while operation is running. Bit 0 high when ERRNO.
@@ -202,6 +213,10 @@ void ria816_reset(ria816_t* ria816);
202213
uint64_t ria816_tick(ria816_t* ria816, uint64_t pins);
203214

204215
uint8_t ria816_uart_status(const ria816_t* c);
216+
uint8_t ria816_reg_read(ria816_t* c, uint8_t addr);
217+
void ria816_reg_write(ria816_t* c, uint8_t addr, uint8_t data);
218+
uint8_t ria816_hid_read(ria816_t* c, uint8_t reg);
219+
void ria816_hid_write(ria816_t* c, uint8_t reg, uint8_t data);
205220

206221
#ifdef __cplusplus
207222
} // extern "C"

src/chips/tca6416a.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static uint64_t _tca6416a_tick(tca6416a_t* c, uint64_t pins) {
6060
}
6161

6262
/* read a register */
63-
static uint8_t _tca6416a_read(tca6416a_t* c, uint8_t addr) {
63+
uint8_t tca6416a_read(tca6416a_t* c, uint8_t addr) {
6464
uint8_t data = 0xFF;
6565
switch (addr) {
6666
case TCA6416A_REG_IN0:
@@ -81,7 +81,7 @@ static uint8_t _tca6416a_read(tca6416a_t* c, uint8_t addr) {
8181
return data;
8282
}
8383

84-
static void _tca6416a_write(tca6416a_t* c, uint8_t addr, uint8_t data) {
84+
void tca6416a_write(tca6416a_t* c, uint8_t addr, uint8_t data) {
8585
switch (addr) {
8686
case TCA6416A_REG_OUT0: c->p0.out = data; break;
8787
case TCA6416A_REG_OUT1: c->p1.out = data; break;
@@ -97,12 +97,12 @@ uint64_t tca6416a_tick(tca6416a_t* c, uint64_t pins) {
9797
if (pins & TCA6416A_CS) {
9898
uint8_t addr = pins & TCA6416A_RS;
9999
if (pins & TCA6416A_RW) {
100-
uint8_t data = _tca6416a_read(c, addr);
100+
uint8_t data = tca6416a_read(c, addr);
101101
TCA6416A_SET_DATA(pins, data);
102102
}
103103
else {
104104
uint8_t data = TCA6416A_GET_DATA(pins);
105-
_tca6416a_write(c, addr, data);
105+
tca6416a_write(c, addr, data);
106106
}
107107
}
108108
if (c->intr) pins |= TCA6416A_INT;

src/chips/tca6416a.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ void tca6416a_reset(tca6416a_t* c, uint8_t p0, uint8_t p1);
213213
// tick the tca6416a_t instance
214214
uint64_t tca6416a_tick(tca6416a_t* c, uint64_t pins);
215215

216+
uint8_t tca6416a_read(tca6416a_t* c, uint8_t addr);
217+
void tca6416a_write(tca6416a_t* c, uint8_t addr, uint8_t data);
218+
216219
#ifdef __cplusplus
217220
} // extern "C"
218221
#endif

src/systems/x65.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,20 @@ static uint64_t _x65_tick(x65_t* sys, uint64_t pins) {
140140
// RIA (FFC0..FFFF)
141141
ria_pins |= RIA816_CS;
142142
}
143-
else if (addr >= 0xFFA0) {
144-
// NOT_USED (FFA0..FFBF)
143+
else if (addr >= X65_IO_HID_BASE) {
144+
// GPIO (FFB0..FFBF)
145+
ria_pins |= RIA816_HID_CS;
146+
}
147+
else if (addr >= 0xFFAC) {
148+
// NOT_USED (FFAC..FFAF)
149+
}
150+
else if (addr >= X65_IO_BUZZER_BASE) {
151+
// GPIO (FFA8..FFAB)
152+
ria_pins |= RIA816_BUZZER_CS;
153+
}
154+
else if (addr >= X65_IO_RGB_BASE) {
155+
// GPIO (FFA0..FFA7)
156+
ria_pins |= RIA816_RGB_CS;
145157
}
146158
else if (addr >= X65_IO_TIMERS_BASE) {
147159
// GPIO (FF98..FF9F)
@@ -269,10 +281,42 @@ static uint64_t _x65_tick(x65_t* sys, uint64_t pins) {
269281
uint8_t mem_rd(x65_t* sys, uint8_t bank, uint16_t addr) {
270282
if (bank == 0) {
271283
if (addr >= X65_IO_RIA_BASE) {
272-
return sys->ria.reg[addr & 0x3F];
284+
const uint8_t reg = addr & RIA816_RS;
285+
switch (reg) {
286+
case RIA816_FS_FDARW:
287+
case RIA816_FS_FDBRW:
288+
case RIA816_UART_TX_RX:
289+
case RIA816_API_STACK: return 0xFF;
290+
}
291+
return ria816_reg_read(&sys->ria, reg);
292+
}
293+
else if (addr >= X65_IO_HID_BASE) {
294+
return ria816_hid_read(&sys->ria, addr & RIA816_HID_RS);
295+
}
296+
else if (addr >= 0xFFAC) {
297+
// NOT_USED (FFAC..FFAF)
298+
return 0xFF;
299+
}
300+
else if (addr >= X65_IO_BUZZER_BASE) {
301+
return 0xFF;
302+
}
303+
else if (addr >= X65_IO_RGB_BASE) {
304+
return 0xFF;
305+
}
306+
else if (addr >= X65_IO_TIMERS_BASE) {
307+
const uint8_t reg = addr & RIA816_TIMERS_RS;
308+
switch (reg) {
309+
case M6526_REG_ICR: return sys->ria.cia.intr.icr;
310+
}
311+
return m6526_read(&sys->ria.cia, reg);
273312
}
274313
else if (addr >= X65_IO_GPIO_BASE) {
275-
return 0xEA; // NOP
314+
const uint8_t reg = addr & TCA6416A_RS;
315+
switch (reg) {
316+
case TCA6416A_REG_IN0: return sys->gpio.p0.in;
317+
case TCA6416A_REG_IN1: return sys->gpio.p1.in;
318+
}
319+
return tca6416a_read(&sys->gpio, reg);
276320
}
277321
else if (addr >= X65_IO_CGIA_BASE) {
278322
return cgia_reg_read((uint8_t)addr);
@@ -287,7 +331,11 @@ uint8_t mem_rd(x65_t* sys, uint8_t bank, uint16_t addr) {
287331
void mem_wr(x65_t* sys, uint8_t bank, uint16_t addr, uint8_t data) {
288332
if (bank == 0) {
289333
if (addr >= X65_IO_RIA_BASE) {
290-
sys->ria.reg[addr & 0x3F] = data;
334+
ria816_reg_write(&sys->ria, addr & RIA816_RS, data);
335+
return;
336+
}
337+
else if (addr >= X65_IO_HID_BASE) {
338+
ria816_hid_write(&sys->ria, addr & RIA816_HID_RS, data);
291339
return;
292340
}
293341
else if (addr >= X65_IO_GPIO_BASE) {
@@ -566,6 +614,7 @@ void _x65_api_call(uint8_t data, void* user_data) {
566614
code_page |= (uint16_t)value << 8;
567615

568616
// copy chargen to memory
617+
printf("Loading font page %02X to $%06X\n", code_page, mem_addr);
569618
for (size_t i = 0; i < 256 * 8; ++i) {
570619
mem_ram_write(sys, mem_addr++, font_get_byte(i, code_page));
571620
}

src/systems/x65.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ typedef enum {
109109
#define X65_IO_CGIA_BASE (0xFF00)
110110
#define X65_IO_GPIO_BASE (0xFF80)
111111
#define X65_IO_TIMERS_BASE (0xFF98)
112+
#define X65_IO_RGB_BASE (0xFFA0)
113+
#define X65_IO_BUZZER_BASE (0xFFA8)
114+
#define X65_IO_HID_BASE (0xFFB0)
112115
#define X65_IO_RIA_BASE (0xFFC0)
113116

114117
#define X65_RAM_SIZE_BYTES (1 << 24) // 16 MBytes of RAM

0 commit comments

Comments
 (0)