Skip to content

Commit 2b0d56b

Browse files
committed
Add "User Bus" module.
This new module allows the connection of custom peripherals to the computer bus. This module can be used to implement user's mods.
1 parent e1b7d90 commit 2b0d56b

3 files changed

Lines changed: 126 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set(CORE_SRCS
2525
src/time.c
2626
src/timer.c
2727
src/tokenizer.c
28+
src/ubus.c
2829
src/upd8255.c
2930
src/video.c
3031
src/ram/auxram.c

src/ubus.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#include "ubus.h"
2+
3+
#include "conf.h"
4+
5+
#include <stddef.h>
6+
#include <string.h>
7+
8+
#define UBUS_MAX_PERIPHERALS (4)
9+
10+
#define LOG_LEVEL LOG_LVL_INFO
11+
#include "log.h"
12+
13+
struct ubus_io_slot {
14+
ceda_ioaddr_t base;
15+
uint32_t top;
16+
ubus_io_read_t in;
17+
ubus_io_write_t out;
18+
};
19+
20+
static struct ubus_io_slot ubus_slots[UBUS_MAX_PERIPHERALS];
21+
static size_t ubus_used = 0;
22+
23+
void ubus_init(CEDAModule *mod) {
24+
memset(mod, 0, sizeof(*mod));
25+
26+
mod->init = ubus_init;
27+
}
28+
29+
bool ubus_register(ceda_ioaddr_t base, uint32_t top, ubus_io_read_t read,
30+
ubus_io_write_t write) {
31+
if (!read && !write)
32+
return false;
33+
34+
if (top > 0x100)
35+
return false;
36+
37+
if (top <= base)
38+
return false;
39+
40+
if (ubus_used == UBUS_MAX_PERIPHERALS) {
41+
LOG_WARN("Too many peripherals registered\n");
42+
return false;
43+
}
44+
45+
// check if peripherals are overlapping
46+
for (size_t i = 0; i < ubus_used; ++i) {
47+
struct ubus_io_slot *slot = &ubus_slots[i];
48+
if (slot->base >= base && slot->base < top)
49+
return false;
50+
if (slot->top <= top && slot->top > base)
51+
return false;
52+
if (slot->base < base && slot->top > top)
53+
return false;
54+
if (slot->base > base && slot->top < top)
55+
return false;
56+
}
57+
58+
ubus_slots[ubus_used].base = base;
59+
ubus_slots[ubus_used].top = top;
60+
ubus_slots[ubus_used].in = read;
61+
ubus_slots[ubus_used].out = write;
62+
ubus_used += 1;
63+
64+
LOG_INFO("Registered peripheral at %02x\n", (unsigned int)base);
65+
66+
return true;
67+
}
68+
69+
zuint8 ubus_io_in(ceda_ioaddr_t address) {
70+
for (size_t i = 0; i < ubus_used; ++i) {
71+
struct ubus_io_slot *slot = &ubus_slots[i];
72+
if (address >= slot->base && address < slot->top)
73+
if (slot->in)
74+
return slot->in(address - slot->base);
75+
}
76+
return 0;
77+
}
78+
79+
void ubus_io_out(ceda_ioaddr_t address, uint8_t value) {
80+
for (size_t i = 0; i < ubus_used; ++i) {
81+
struct ubus_io_slot *slot = &ubus_slots[i];
82+
if (address >= slot->base && address < slot->top)
83+
if (slot->out) {
84+
slot->out(address - slot->base, value);
85+
return;
86+
}
87+
}
88+
}

src/ubus.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef CEDA_USER_BUS_H
2+
#define CEDA_USER_BUS_H
3+
4+
#include "module.h"
5+
#include "type.h"
6+
7+
#include <stdbool.h>
8+
9+
#include <Z80.h>
10+
11+
typedef uint8_t (*ubus_io_read_t)(ceda_ioaddr_t address);
12+
typedef void (*ubus_io_write_t)(ceda_ioaddr_t address, uint8_t value);
13+
14+
/**
15+
* @brief Initialize the User Bus module.
16+
*
17+
* This module allows users to connect custom peripherals to the computer bus.
18+
*/
19+
void ubus_init(CEDAModule *mod);
20+
21+
/**
22+
* @brief Register a peripheral on the bus.
23+
*
24+
* @param base Peripheral base address.
25+
* @param top Peripheral top address + 1 (eg. the first unused address)
26+
* @param read IO input callback.
27+
* @param write IO output callback.
28+
*
29+
* @return true in case of success, false otherwise.
30+
*/
31+
bool ubus_register(ceda_ioaddr_t base, uint32_t top, ubus_io_read_t read,
32+
ubus_io_write_t write);
33+
34+
zuint8 ubus_io_in(ceda_ioaddr_t address);
35+
void ubus_io_out(ceda_ioaddr_t address, uint8_t value);
36+
37+
#endif // CEDA_USER_BUS_H

0 commit comments

Comments
 (0)