mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-23 16:38:06 +11:00
emul/rc2014: add support for Zilog SIO
Very very simplistic, but works with our driver.
This commit is contained in:
parent
35840ad8e6
commit
1195b0313b
@ -1,5 +1,5 @@
|
|||||||
EXTOBJS = ../../emul.o ../../libz80/libz80.o
|
EXTOBJS = ../../emul.o ../../libz80/libz80.o
|
||||||
OBJS = acia.o sdc.o classic.o
|
OBJS = sio.o acia.o sdc.o classic.o
|
||||||
TARGET = classic
|
TARGET = classic
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
@ -10,6 +10,9 @@ Run `make` to build.
|
|||||||
Run `./classic /path/to/rom` (for example, `os.bin` from RC2014's recipe).
|
Run `./classic /path/to/rom` (for example, `os.bin` from RC2014's recipe).
|
||||||
Serial I/O is hooked to stdin/stdout. `CTRL+D` to quit.
|
Serial I/O is hooked to stdin/stdout. `CTRL+D` to quit.
|
||||||
|
|
||||||
|
There are 2 options. `-s` replaces the ACIA with a Zilog SIO and
|
||||||
|
`-c/path/to/image` hooks up a SD card with specified contents.
|
||||||
|
|
||||||
## Memory dump
|
## Memory dump
|
||||||
|
|
||||||
You can press `CTRL+E` to dump the whole 64K of memory into `memdump`.
|
You can press `CTRL+E` to dump the whole 64K of memory into `memdump`.
|
||||||
|
@ -13,16 +13,21 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include "../../emul.h"
|
#include "../../emul.h"
|
||||||
#include "acia.h"
|
#include "acia.h"
|
||||||
|
#include "sio.h"
|
||||||
#include "sdc.h"
|
#include "sdc.h"
|
||||||
|
|
||||||
#define RAMSTART 0x8000
|
#define RAMSTART 0x8000
|
||||||
#define ACIA_CTL_PORT 0x80
|
#define ACIA_CTL_PORT 0x80
|
||||||
#define ACIA_DATA_PORT 0x81
|
#define ACIA_DATA_PORT 0x81
|
||||||
|
#define SIO_ACTL_PORT 0x80
|
||||||
|
#define SIO_ADATA_PORT 0x81
|
||||||
#define SDC_CTL 0x05
|
#define SDC_CTL 0x05
|
||||||
#define SDC_SPI 0x04
|
#define SDC_SPI 0x04
|
||||||
#define MAX_ROMSIZE 0x2000
|
#define MAX_ROMSIZE 0x2000
|
||||||
|
|
||||||
|
bool use_sio = false;
|
||||||
static ACIA acia;
|
static ACIA acia;
|
||||||
|
static SIO sio;
|
||||||
static SDC sdc;
|
static SDC sdc;
|
||||||
|
|
||||||
static uint8_t iord_acia_ctl()
|
static uint8_t iord_acia_ctl()
|
||||||
@ -45,6 +50,26 @@ static void iowr_acia_data(uint8_t val)
|
|||||||
acia_data_wr(&acia, val);
|
acia_data_wr(&acia, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t iord_sio_ctl()
|
||||||
|
{
|
||||||
|
return sio_actl_rd(&sio);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t iord_sio_data()
|
||||||
|
{
|
||||||
|
return sio_adata_rd(&sio);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iowr_sio_ctl(uint8_t val)
|
||||||
|
{
|
||||||
|
sio_actl_wr(&sio, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iowr_sio_data(uint8_t val)
|
||||||
|
{
|
||||||
|
sio_adata_wr(&sio, val);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t iord_sdc_spi()
|
static uint8_t iord_sdc_spi()
|
||||||
{
|
{
|
||||||
return sdc_spi_rd(&sdc);
|
return sdc_spi_rd(&sdc);
|
||||||
@ -67,13 +92,65 @@ static void iowr_sdc_ctl(uint8_t val)
|
|||||||
sdc_ctl_wr(&sdc, val);
|
sdc_ctl_wr(&sdc, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool has_irq()
|
||||||
|
{
|
||||||
|
return use_sio ? sio_has_irq(&sio) : acia_has_irq(&acia);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hastx()
|
||||||
|
{
|
||||||
|
return use_sio ? sio_hastx(&sio) : acia_hastx(&acia);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hasrx()
|
||||||
|
{
|
||||||
|
return use_sio ? sio_hasrx(&sio) : acia_hasrx(&acia);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t _read()
|
||||||
|
{
|
||||||
|
return use_sio ? sio_read(&sio) : acia_read(&acia);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _write(uint8_t val)
|
||||||
|
{
|
||||||
|
if (use_sio) { sio_write(&sio, val); } else { acia_write(&acia, val); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: ./classic [-s] [-c sdcard.img] /path/to/rom\n");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int ch;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
fprintf(stderr, "Usage: ./classic /path/to/rom [sdcard.img]\n");
|
usage();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
FILE *fp = fopen(argv[1], "r");
|
acia_init(&acia);
|
||||||
|
sio_init(&sio);
|
||||||
|
sdc_init(&sdc);
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "sc:")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 's':
|
||||||
|
use_sio = true;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
fprintf(stderr, "Setting up SD card image with %s\n", optarg);
|
||||||
|
sdc.fp = fopen(optarg, "r+");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optind != argc-1) {
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fp = fopen(argv[optind], "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
fprintf(stderr, "Can't open %s\n", argv[1]);
|
fprintf(stderr, "Can't open %s\n", argv[1]);
|
||||||
return 1;
|
return 1;
|
||||||
@ -106,16 +183,17 @@ int main(int argc, char *argv[])
|
|||||||
tcsetattr(0, TCSADRAIN, &term);
|
tcsetattr(0, TCSADRAIN, &term);
|
||||||
}
|
}
|
||||||
|
|
||||||
acia_init(&acia);
|
if (use_sio) {
|
||||||
sdc_init(&sdc);
|
m->iord[SIO_ACTL_PORT] = iord_sio_ctl;
|
||||||
if (argc == 3) {
|
m->iord[SIO_ADATA_PORT] = iord_sio_data;
|
||||||
fprintf(stderr, "Setting up SD card image\n");
|
m->iowr[SIO_ACTL_PORT] = iowr_sio_ctl;
|
||||||
sdc.fp = fopen(argv[2], "r+");
|
m->iowr[SIO_ADATA_PORT] = iowr_sio_data;
|
||||||
|
} else {
|
||||||
|
m->iord[ACIA_CTL_PORT] = iord_acia_ctl;
|
||||||
|
m->iord[ACIA_DATA_PORT] = iord_acia_data;
|
||||||
|
m->iowr[ACIA_CTL_PORT] = iowr_acia_ctl;
|
||||||
|
m->iowr[ACIA_DATA_PORT] = iowr_acia_data;
|
||||||
}
|
}
|
||||||
m->iord[ACIA_CTL_PORT] = iord_acia_ctl;
|
|
||||||
m->iord[ACIA_DATA_PORT] = iord_acia_data;
|
|
||||||
m->iowr[ACIA_CTL_PORT] = iowr_acia_ctl;
|
|
||||||
m->iowr[ACIA_DATA_PORT] = iowr_acia_data;
|
|
||||||
m->iord[SDC_SPI] = iord_sdc_spi;
|
m->iord[SDC_SPI] = iord_sdc_spi;
|
||||||
m->iowr[SDC_SPI] = iowr_sdc_spi;
|
m->iowr[SDC_SPI] = iowr_sdc_spi;
|
||||||
m->iord[SDC_CTL] = iord_sdc_ctl;
|
m->iord[SDC_CTL] = iord_sdc_ctl;
|
||||||
@ -124,12 +202,12 @@ int main(int argc, char *argv[])
|
|||||||
char tosend = 0;
|
char tosend = 0;
|
||||||
while (emul_step()) {
|
while (emul_step()) {
|
||||||
// Do we have an interrupt?
|
// Do we have an interrupt?
|
||||||
if (acia_has_irq(&acia)) {
|
if (has_irq()) {
|
||||||
Z80INT(&m->cpu, 0);
|
Z80INT(&m->cpu, 0);
|
||||||
}
|
}
|
||||||
// Is the RC2014 transmitting?
|
// Is the RC2014 transmitting?
|
||||||
if (acia_hastx(&acia)) {
|
if (hastx()) {
|
||||||
putchar(acia_read(&acia));
|
putchar(_read());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
// Do we have something to send?
|
// Do we have something to send?
|
||||||
@ -150,8 +228,8 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tosend && !acia_hasrx(&acia)) {
|
if (tosend && !hasrx()) {
|
||||||
acia_write(&acia, tosend);
|
_write(tosend);
|
||||||
tosend = 0;
|
tosend = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
70
emul/hw/rc2014/sio.c
Normal file
70
emul/hw/rc2014/sio.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sio.h"
|
||||||
|
|
||||||
|
void sio_init(SIO *sio)
|
||||||
|
{
|
||||||
|
memset(sio->wr, 0, sizeof(sio->wr));
|
||||||
|
memset(sio->rr, 0, sizeof(sio->rr));
|
||||||
|
sio->rx = 0;
|
||||||
|
sio->tx = 0;
|
||||||
|
sio->in_int = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sio_has_irq(SIO *sio)
|
||||||
|
{
|
||||||
|
bool res = sio->in_int;
|
||||||
|
sio->in_int = false;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sio_hasrx(SIO *sio)
|
||||||
|
{
|
||||||
|
return sio->rr[0] & 0x01; // Receive Character Available
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sio_hastx(SIO *sio)
|
||||||
|
{
|
||||||
|
return !(sio->rr[0] & 0x04); // Transmit Buffer Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sio_read(SIO *sio)
|
||||||
|
{
|
||||||
|
sio->rr[0] |= 0x04; // Transmit Buffer Empty high
|
||||||
|
return sio->tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sio_write(SIO *sio, uint8_t val)
|
||||||
|
{
|
||||||
|
sio->rr[0] |= 0x01; // Receive Character Available high
|
||||||
|
sio->rx = val;
|
||||||
|
sio->in_int = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sio_actl_rd(SIO *sio)
|
||||||
|
{
|
||||||
|
uint8_t target = sio->wr[0] & 0x3; // PTR
|
||||||
|
return sio->rr[target];
|
||||||
|
}
|
||||||
|
|
||||||
|
void sio_actl_wr(SIO *sio, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t target = sio->wr[0] & 0x7; // PTR
|
||||||
|
sio->wr[target] = val;
|
||||||
|
if (target != 0) {
|
||||||
|
sio->wr[0] &= ~0x7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sio_adata_rd(SIO *sio)
|
||||||
|
{
|
||||||
|
sio->rr[0] &= ~0x01; // Receive Character Available low
|
||||||
|
return sio->rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sio_adata_wr(SIO *sio, uint8_t val)
|
||||||
|
{
|
||||||
|
sio->tx = val;
|
||||||
|
sio->rr[0] &= ~0x04; // Transmit Buffer Empty low
|
||||||
|
}
|
||||||
|
|
27
emul/hw/rc2014/sio.h
Normal file
27
emul/hw/rc2014/sio.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/* Extremely simplified Zilog SIO */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Write registers WR7:0
|
||||||
|
uint8_t wr[7];
|
||||||
|
// Read registers RR2:0
|
||||||
|
uint8_t rr[2];
|
||||||
|
uint8_t rx;
|
||||||
|
uint8_t tx;
|
||||||
|
// Set to true when writing a byte while SIO is enabled and set back to
|
||||||
|
// false when sio_has_irq() is false.
|
||||||
|
bool in_int;
|
||||||
|
} SIO;
|
||||||
|
|
||||||
|
void sio_init(SIO *sio);
|
||||||
|
bool sio_has_irq(SIO *sio);
|
||||||
|
bool sio_hasrx(SIO *sio);
|
||||||
|
bool sio_hastx(SIO *sio);
|
||||||
|
uint8_t sio_read(SIO *sio);
|
||||||
|
void sio_write(SIO *sio, uint8_t val);
|
||||||
|
uint8_t sio_actl_rd(SIO *sio);
|
||||||
|
void sio_actl_wr(SIO *sio, uint8_t val);
|
||||||
|
uint8_t sio_adata_rd(SIO *sio);
|
||||||
|
void sio_adata_wr(SIO *sio, uint8_t val);
|
Loading…
Reference in New Issue
Block a user