mirror of
https://github.com/satoshinm/pill_6502.git
synced 2025-03-13 01:33:36 +00:00
Add beginning of 6850 ACIA emulation
This commit is contained in:
parent
fb7f66b717
commit
f1f1a1f8ac
@ -12,6 +12,7 @@ LDFLAGS += $(OPT_FLAGS)
|
||||
|
||||
SRC = \
|
||||
fake6502.c \
|
||||
acia6850.c \
|
||||
cdcacm.c \
|
||||
main.c \
|
||||
|
||||
|
60
src/acia6850.c
Normal file
60
src/acia6850.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
|
||||
#include "acia6850.h"
|
||||
#include "cdcacm.h"
|
||||
|
||||
extern usbd_device *usbd_dev;
|
||||
|
||||
// Motorola MC6850 Asynchronous Communications Interface Adapter (ACIA) emulation
|
||||
|
||||
// http://www.cpcwiki.eu/index.php/6850_ACIA_chip
|
||||
// http://www.cpcwiki.eu/imgs/3/3f/MC6850.pdf
|
||||
//
|
||||
|
||||
#define ACIAControl 0
|
||||
#define ACIAStatus 1
|
||||
#define ACIAData 2
|
||||
|
||||
// "MC6850 Data Register (R/W) Data can be read when Status.Bit0=1, and written when Status.Bit1=1."
|
||||
#define RDRF 1
|
||||
#define TDRE 2
|
||||
|
||||
uint8_t read6850(uint16_t address) {
|
||||
switch(address & 3) {
|
||||
case ACIAControl:
|
||||
break;
|
||||
case ACIAStatus:
|
||||
return TDRE; // writable
|
||||
break;
|
||||
case ACIAData:
|
||||
// TODO: read buffer from serial port
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void write6850(uint16_t address, uint8_t value) {
|
||||
switch(address & 3) {
|
||||
case ACIAControl:
|
||||
// TODO: decode baudrate, mode, break control, interrupt
|
||||
break;
|
||||
case ACIAStatus:
|
||||
(void) value;
|
||||
break;
|
||||
case ACIAData: {
|
||||
static char buf[1];
|
||||
buf[0] = value;
|
||||
cdcacm_send_chunked_blocking(buf, sizeof(buf), usbd_dev);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
4
src/acia6850.h
Normal file
4
src/acia6850.h
Normal file
@ -0,0 +1,4 @@
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t read6850(uint16_t address);
|
||||
void write6850(uint16_t address, uint8_t value);
|
@ -174,16 +174,16 @@ static int cdcacm_control_request(usbd_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_chunked_blocking(char *buf, int len, usbd_device *dev, int endpoint, int max_packet_length) {
|
||||
void cdcacm_send_chunked_blocking(char *buf, int len, usbd_device *dev) {
|
||||
uint16_t bytes_written = 0;
|
||||
uint16_t total_bytes_written = 0;
|
||||
uint16_t bytes_remaining = len;
|
||||
|
||||
do {
|
||||
uint16_t this_length = bytes_remaining;
|
||||
if (this_length > max_packet_length) this_length = max_packet_length;
|
||||
if (this_length > CDCACM_PACKET_SIZE) this_length = CDCACM_PACKET_SIZE;
|
||||
|
||||
bytes_written = usbd_ep_write_packet(dev, endpoint, buf + total_bytes_written, this_length);
|
||||
bytes_written = usbd_ep_write_packet(dev, CDCACM_UART_ENDPOINT, buf + total_bytes_written, this_length);
|
||||
bytes_remaining -= bytes_written;
|
||||
total_bytes_written += bytes_written;
|
||||
} while (bytes_remaining > 0);
|
||||
@ -232,7 +232,7 @@ static void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep)
|
||||
}
|
||||
}
|
||||
|
||||
send_chunked_blocking(reply_buf, j, dev, CDCACM_UART_ENDPOINT, CDCACM_PACKET_SIZE);
|
||||
cdcacm_send_chunked_blocking(reply_buf, j, dev);
|
||||
}
|
||||
|
||||
static void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep)
|
||||
|
@ -7,3 +7,4 @@ extern const struct usb_interface_descriptor uart_data_iface[];
|
||||
extern const struct usb_iface_assoc_descriptor uart_assoc;
|
||||
|
||||
void cdcacm_set_config(usbd_device *dev, uint16_t wValue);
|
||||
void cdcacm_send_chunked_blocking(char *buf, int len, usbd_device *dev);
|
||||
|
22
src/main.c
22
src/main.c
@ -26,15 +26,15 @@
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/usb/hid.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
|
||||
#include "fake6502.h"
|
||||
#include "acia6850.h"
|
||||
#include "rom.h"
|
||||
#include "cdcacm.h"
|
||||
#include "version.h"
|
||||
|
||||
static usbd_device *usbd_dev;
|
||||
usbd_device *usbd_dev;
|
||||
|
||||
const struct usb_device_descriptor dev_descr = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
@ -83,8 +83,10 @@ static const char *usb_strings[] = {
|
||||
"Pill 6502 UART Port",
|
||||
};
|
||||
|
||||
static bool running = false;
|
||||
void sys_tick_handler(void)
|
||||
{
|
||||
if (!running) return;
|
||||
step6502();
|
||||
gpio_toggle(GPIOC, GPIO13);
|
||||
}
|
||||
@ -100,6 +102,9 @@ char *process_serial_command(char *buf, int len) {
|
||||
|
||||
if (buf[0] == 'v') {
|
||||
return "Pill 6502 version " FIRMWARE_VERSION;
|
||||
} else if (buf[0] == 'r') {
|
||||
running = !running;
|
||||
return running ? "resumed" : "paused";
|
||||
} else if (buf[0] == 't') {
|
||||
static char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%ld ticks\r\n%ld instructions", clockticks6502, instructions);
|
||||
@ -138,7 +143,6 @@ uint8_t usbd_control_buffer[128];
|
||||
|
||||
// 6502 processor memory, 16KB (< 20KB)
|
||||
uint8_t ram[0x4000];
|
||||
// TODO: serial interface, 0xa000-0xbfff
|
||||
uint8_t read6502(uint16_t address) {
|
||||
// RAM
|
||||
if (address < sizeof(ram)) {
|
||||
@ -152,13 +156,25 @@ uint8_t read6502(uint16_t address) {
|
||||
return rom[address - 0xc000];
|
||||
}
|
||||
|
||||
// ACIA
|
||||
if (address >= 0xa000 && address <= 0xbfff) {
|
||||
return read6850(address);
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void write6502(uint16_t address, uint8_t value) {
|
||||
// RAM
|
||||
if (address < sizeof(ram)) {
|
||||
ram[address] = value;
|
||||
}
|
||||
|
||||
// ACIA
|
||||
if (address >= 0xa000 && address <= 0xbfff) {
|
||||
write6850(address, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
Loading…
x
Reference in New Issue
Block a user