#include "boot.h" /* * 6850 ACIA test wiring assumption: * /CS2 is driven by not-A5, so the ACIA is selected when A5 = 1. * RS is assumed to be wired to A0, giving: * 0x20 = status/control * 0x21 = data */ #define ACIA_CTRL_STATUS 0x20 #define ACIA_DATA 0x21 #define ACIA_STATUS_RDRF 0x01 #define ACIA_STATUS_TDRE 0x02 #define ACIA_CMD_MASTER_RESET 0x03 #define ACIA_CMD_8N1_DIV1 0x14 /* * Z80 CTC wiring assumption: * /CE is driven by not-A4, so use 0x10 as the base address. * A0 and A1 select channels 0 through 3. */ #define CTC_CHANNEL_0 0x10 #define CTC_CHANNEL_1 0x11 #define CTC_CHANNEL_2 0x12 #define CTC_CHANNEL_3 0x13 #define CTC_CMD_RESET 0x03 #define CTC_CMD_COUNTER_RISING 0x4F #define CTC_TEST_TIME_CONSTANT 52 static void acia_init(void) { io_out(ACIA_CTRL_STATUS, ACIA_CMD_MASTER_RESET); io_out(ACIA_CTRL_STATUS, ACIA_CMD_8N1_DIV1); } static void ctc_init(void) { /* Leave unused channels in reset. */ io_out(CTC_CHANNEL_1, CTC_CMD_RESET); io_out(CTC_CHANNEL_2, CTC_CMD_RESET); io_out(CTC_CHANNEL_3, CTC_CMD_RESET); /* * Channel 0: counter mode, rising-edge trigger, no interrupt. CLK/TRG0 * must be connected to the 500 kHz clock. Writing the time constant * starts the counter, and ZC/TO0 produces a pulse at: * * 500000 / 52 = 9615.4 Hz * * This is the closest integer division to 9600 Hz (about +0.16%). */ io_out(CTC_CHANNEL_0, CTC_CMD_COUNTER_RISING); io_out(CTC_CHANNEL_0, CTC_TEST_TIME_CONSTANT); } static uint8_t acia_status(void) { return io_in(ACIA_CTRL_STATUS); } static void acia_putc(uint8_t value) { while ((acia_status() & ACIA_STATUS_TDRE) == 0) { } io_out(ACIA_DATA, value); } static uint8_t acia_getc_nonblocking(uint8_t *value) { if ((acia_status() & ACIA_STATUS_RDRF) == 0) { return 0; } *value = io_in(ACIA_DATA); return 1; } static void acia_puts(const char *text) { while (*text) { acia_putc((uint8_t)*text++); } } void main(void) { uint8_t cnt = 0; uint8_t ch = 0; io_out(PIO_A_CTRL, 0x0F); io_out(PIO_A_DATA, 0x00); ctc_init(); acia_init(); acia_puts("ACIA 6850 test ready\r\n"); for (;;) { uint8_t status = acia_status(); if (acia_getc_nonblocking(&ch)) { io_out(PIO_A_DATA, ch); acia_putc(ch); if (ch == '\r') { acia_putc('\n'); } delay_ms(50); } acia_putc((uint8_t)('0' + (cnt & 0x07))); acia_puts("\r\n"); cnt++; delay_ms(250); } }