From 6fb404fe60e6379db0e31591947a6f9bbe29d9fc Mon Sep 17 00:00:00 2001 From: Joppe Blondel Date: Sun, 30 Aug 2026 19:27:08 +0200 Subject: [PATCH] stuff --- boot.asm | 9 ++-- main.c | 148 ++++++++++++++++++------------------------------------- 2 files changed, 53 insertions(+), 104 deletions(-) diff --git a/boot.asm b/boot.asm index 925d5bc..c8f4d14 100644 --- a/boot.asm +++ b/boot.asm @@ -1,12 +1,13 @@ STACK_TOP = 0xFFFF -; At 500 kHz the CPU has about 500 T-states per millisecond. +; At 1 MHz the CPU has about 1000 T-states per millisecond. ; The inner delay loop below costs about 26 T-states per taken iteration: ; dec hl = 6T ; ld a,h = 4T ; or l = 4T ; jr nz = 12T -; 500 / 26 = 19.2, so 20 iterations is the nearest simple whole-number choice. -DELAY_LOOPS_PER_MS = 20 +; 1000 / 26 = 38.5. Use 40 iterations to retain the previous calibration, +; which used 20 iterations at 500 kHz. +DELAY_LOOPS_PER_MS = 40 .globl _main .globl _delay_ms @@ -99,7 +100,7 @@ _io_in:: ; Approximate millisecond delay. ; Input: HL = delay in milliseconds. -; For CLK_SPEED = 500000 Hz this uses 20 inner iterations per ms. +; For CLK_SPEED = 1000000 Hz this uses 40 inner iterations per ms. _delay_ms:: ld a, h or l diff --git a/main.c b/main.c index 96d96cb..c252f88 100644 --- a/main.c +++ b/main.c @@ -1,117 +1,65 @@ #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 VID_CMD 0x80 +#define VID_DAT 0x81 +#define VID_CMD_SET_TEXT_MODE 0 +#define VID_CMD_SET_PIXEL_MODE 1 +#define VID_CMD_CLR 2 +#define VID_CMD_TEXT_POS_X 3 +#define VID_CMD_TEXT_POS_Y 5 +#define VID_CMD_PIXEL_POS_X 4 +#define VID_CMD_PIXEL_POS_Y 6 -#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); +void putc(char c){ + io_out(VID_DAT, c); } -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 puts(char * s){ + while(*s){ + putc(*s); + s++; } } void main(void) { - uint8_t cnt = 0; - uint8_t ch = 0; + delay_ms(100); - io_out(PIO_A_CTRL, 0x0F); - io_out(PIO_A_DATA, 0x00); + for(;;){ + io_out(VID_CMD, VID_CMD_TEXT_POS_X); + io_out(VID_DAT, 0); + io_out(VID_CMD, VID_CMD_TEXT_POS_Y); + io_out(VID_DAT, 0); + io_out(VID_CMD, VID_CMD_SET_TEXT_MODE); + io_out(VID_CMD, VID_CMD_CLR); - 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); + for(uint8_t i=0; i<18; i++){ + putc('0'+i); + puts("\r\n"); } - acia_putc((uint8_t)('0' + (cnt & 0x07))); - acia_puts("\r\n"); - cnt++; - delay_ms(250); + delay_ms(2000); + + + io_out(VID_CMD, VID_CMD_SET_PIXEL_MODE); + io_out(VID_CMD, VID_CMD_CLR); + + for(uint8_t y=0; y<255; y++){ + uint16_t py = 160 + y; + uint16_t px = 256; + + io_out(VID_CMD, VID_CMD_PIXEL_POS_X); + io_out(VID_DAT, px&0xff); + io_out(VID_DAT, px>>8); + io_out(VID_CMD, VID_CMD_PIXEL_POS_Y); + io_out(VID_DAT, py&0xff); + io_out(VID_DAT, py>>8); + io_out(VID_CMD, VID_CMD_SET_PIXEL_MODE); + for(uint8_t x=0; x<32; x++) + io_out(VID_DAT, 0xff); + } + + delay_ms(2000); } }