From 1985fccdabeeaacd87e6a0afebe810736fb5d912 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 27 Jan 2019 18:27:28 +0000 Subject: [PATCH] sc108: sync with CTC and tty work for RC2014 --- Kernel/platform-sc108/config.h | 2 +- Kernel/platform-sc108/devices.c | 2 +- Kernel/platform-sc108/devtty.c | 227 ++++++++++++++++++++++--------- Kernel/platform-sc108/devtty.h | 6 +- Kernel/platform-sc108/discard.c | 9 ++ Kernel/platform-sc108/kernel.def | 6 - Kernel/platform-sc108/main.c | 74 ++++++---- Kernel/platform-sc108/rc2014.h | 16 +++ Kernel/platform-sc108/sc108.s | 200 ++++++++++++++++++++++++--- 9 files changed, 424 insertions(+), 118 deletions(-) diff --git a/Kernel/platform-sc108/config.h b/Kernel/platform-sc108/config.h index 349ffb43..4cbe93df 100644 --- a/Kernel/platform-sc108/config.h +++ b/Kernel/platform-sc108/config.h @@ -63,7 +63,7 @@ extern unsigned int swap_dev; #define CONFIG_IDE /* Device parameters */ -#define NUM_DEV_TTY 2 +#define NUM_DEV_TTY 4 /* UART0 as the console */ #define BOOT_TTY (512 + 1) diff --git a/Kernel/platform-sc108/devices.c b/Kernel/platform-sc108/devices.c index 1a52d3e6..885f9d2d 100644 --- a/Kernel/platform-sc108/devices.c +++ b/Kernel/platform-sc108/devices.c @@ -21,7 +21,7 @@ struct devsw dev_tab[] = /* The device driver switch table */ /* 1: /dev/fd - Floppy disk block devices */ { no_open, no_close, no_rdwr, no_rdwr, no_ioctl}, /* 2: /dev/tty -- serial ports */ - { tty_open, tty_close, tty_read, tty_write, tty_ioctl}, + { rctty_open, tty_close, tty_read, tty_write, tty_ioctl}, /* 3: RAM disk */ { no_open, no_close, no_rdwr, no_rdwr, no_ioctl}, /* 4: /dev/mem etc System devices (one offs) */ diff --git a/Kernel/platform-sc108/devtty.c b/Kernel/platform-sc108/devtty.c index acf5ae5a..d7c230bf 100644 --- a/Kernel/platform-sc108/devtty.c +++ b/Kernel/platform-sc108/devtty.c @@ -8,10 +8,18 @@ static char tbuf1[TTYSIZ]; static char tbuf2[TTYSIZ]; +static char tbuf3[TTYSIZ]; +static char tbuf4[TTYSIZ]; static uint8_t sleeping; -uint8_t ser_type = 2; +struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ + {NULL, NULL, NULL, 0, 0, 0}, + {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2}, + {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, + {tbuf3, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ / 2}, + {tbuf4, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, +}; static tcflag_t uart0_mask[4] = { _ISYS, @@ -32,13 +40,9 @@ static tcflag_t uart1_mask[4] = { tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { NULL, uart0_mask, - uart1_mask -}; - -struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ - {NULL, NULL, NULL, 0, 0, 0}, - {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2}, - {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, + uart1_mask, + uart0_mask, + uart0_mask }; uint8_t sio_r[] = { @@ -47,13 +51,52 @@ uint8_t sio_r[] = { 0x05, 0xEA }; +static uint16_t siobaud[] = { + 0xC0, /* 0 */ + 0, /* 50 */ + 0, /* 75 */ + 0, /* 110 */ + 0, /* 134 */ + 0, /* 150 */ + 0xC0, /* 300 */ + 0x60, /* 600 */ + 0xC0, /* 1200 */ + 0x60, /* 2400 */ + 0x30, /* 4800 */ + 0x18, /* 9600 */ + 0x0C, /* 19200 */ + 0x06, /* 38400 */ + 0x04, /* 57600 */ + 0x02 /* 115200 */ +}; + static void sio2_setup(uint8_t minor, uint8_t flags) { struct termios *t = &ttydata[minor].termios; uint8_t r; + uint8_t baud; + + used(flags); + + baud = t->c_cflag & CBAUD; + if (baud < B300) + baud = B300; + /* Set bits per character */ sio_r[1] = 0x01 | ((t->c_cflag & CSIZE) << 2); + r = 0xC4; + if (ctc_present && minor == 3) { + CTC_CH1 = 0x55; + CTC_CH1 = siobaud[baud]; + if (baud > B600) /* Use x16 clock and CTC divider */ + r = 0x44; + } else + baud = B115200; + + t->c_cflag &= CBAUD; + t->c_cflag |= baud; + if (t->c_cflag & CSTOPB) r |= 0x08; if (t->c_cflag & PARENB) @@ -66,13 +109,13 @@ static void sio2_setup(uint8_t minor, uint8_t flags) void tty_setup(uint8_t minor, uint8_t flags) { - if (ser_type == 1) { + if (sio_present || sio1_present) { sio2_setup(minor, flags); sio2_otir(SIO0_BASE + 2 * (minor - 1)); /* We need to do CTS/RTS support and baud setting on channel 2 yet */ } - if (ser_type == 2) { + if (acia_present) { struct termios *t = &ttydata[1].termios; uint8_t r = t->c_cflag & CSIZE; /* No CS5/CS6 CS7 must have parity enabled */ @@ -115,22 +158,21 @@ void tty_setup(uint8_t minor, uint8_t flags) int tty_carrier(uint8_t minor) { uint8_t c; - if (ser_type == 1) { - if (minor == 1) { - SIOA_C = 0; - c = SIOA_C; - } else { - SIOB_C = 0; - c = SIOB_C; - } - if (c & 0x8) - return 1; - return 0; - } else /* ACIA isn't wired for carrier on any board */ + uint8_t port; + + /* No carrier on ACIA */ + if (sio_present == 0) + return 1; + + port = SIO0_BASE + 2 * (minor - 1); + out(port, 0); + c = in(port); + if (c & 0x08) return 1; + return 0; } -void tty_pollirq_sio(void) +void tty_pollirq_sio0(void) { static uint8_t old_ca, old_cb; uint8_t ca, cb; @@ -157,7 +199,7 @@ void tty_pollirq_sio(void) SIOA_C = 2 << 5; /* Output pending */ if ((ca & 4) && (sleeping & 2)) { - tty_outproc(1); + tty_outproc(2); sleeping &= ~2; SIOA_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending } @@ -174,9 +216,9 @@ void tty_pollirq_sio(void) tty_inproc(2, SIOB_D); progress = 1; } - if ((cb & 4) && (sleeping & 4)) { - tty_outproc(2); - sleeping &= ~4; + if ((cb & 4) && (sleeping & 8)) { + tty_outproc(3); + sleeping &= ~8; SIOB_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending } if ((cb ^ old_cb) & 8) { @@ -188,14 +230,71 @@ void tty_pollirq_sio(void) } while(progress); } +void tty_pollirq_sio1(void) +{ + static uint8_t old_ca, old_cb; + uint8_t ca, cb; + uint8_t progress; + + /* Check for an interrupt */ + SIOC_C = 0; + if (!(SIOC_C & 2)) + return; + + /* FIXME: need to process error/event interrupts as we can get + spurious characters or lines on an unused SIO floating */ + do { + progress = 0; + SIOC_C = 0; // read register 0 + ca = SIOC_C; + /* Input pending */ + if ((ca & 1) && !fullq(&ttyinq[3])) { + progress = 1; + tty_inproc(3, SIOC_D); + } + /* Break */ + if (ca & 2) + SIOC_C = 2 << 5; + /* Output pending */ + if ((ca & 4) && (sleeping & 8)) { + tty_outproc(3); + sleeping &= ~8; + SIOC_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending + } + /* Carrier changed */ + if ((ca ^ old_ca) & 8) { + if (ca & 8) + tty_carrier_raise(3); + else + tty_carrier_drop(3); + } + SIOD_C = 0; // read register 0 + cb = SIOD_C; + if ((cb & 1) && !fullq(&ttyinq[4])) { + tty_inproc(4, SIOD_D); + progress = 1; + } + if ((cb & 4) && (sleeping & 16)) { + tty_outproc(4); + sleeping &= ~16; + SIOD_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending + } + if ((cb ^ old_cb) & 8) { + if (cb & 8) + tty_carrier_raise(4); + else + tty_carrier_drop(4); + } + } while(progress); +} + void tty_pollirq_acia(void) { uint8_t ca; ca = ACIA_C; if (ca & 1) { - ca = ACIA_D; - tty_inproc(1, ca); + tty_inproc(1, ACIA_D); } if ((ca & 2) && sleeping) { tty_outproc(1); @@ -203,25 +302,19 @@ void tty_pollirq_acia(void) } } -static char hex[] = { "0123456789ABCDEF" }; - void tty_putc(uint8_t minor, unsigned char c) { - if (ser_type == 1) { - if (minor == 1) { - SIOA_D = c; - } else if (minor == 2) - SIOB_D = c; - } else if (minor == 1) - ACIA_D = c; - else if (minor = 3) { - /* FIXME: implement */ + if (acia_present) + SIOA_D = c; + else { + uint8_t port = SIO0_BASE + 1 + 2 * (minor - 1); + out(port, c); } } -/* We will need this for SIO once we implement flow control signals */ void tty_sleeping(uint8_t minor) { + sleeping |= (1 << minor); } /* Be careful here. We need to peek at RR but we must be sure nobody else @@ -232,40 +325,33 @@ void tty_sleeping(uint8_t minor) Need to review this we should be ok as the IRQ handler always leaves us pointing at RR0 */ - ttyready_t tty_writeready(uint8_t minor) { irqflags_t irq; uint8_t c; - if (ser_type == 1) { - irq = di(); - if (minor == 1) { - SIOA_C = 0; /* read register 0 */ - c = SIOA_C; - irqrestore(irq); - if (c & 0x04) /* THRE? */ - return TTY_READY_NOW; - return TTY_READY_SOON; - } else if (minor == 2) { - SIOB_C = 0; /* read register 0 */ - c = SIOB_C; - irqrestore(irq); - if (c & 0x04) /* THRE? */ - return TTY_READY_NOW; - return TTY_READY_SOON; - } - irqrestore(irq); - } else if (ser_type == 2 && minor == 1) { + uint8_t port; + + if (acia_present) { c = ACIA_C; if (c & 0x02) /* THRE? */ return TTY_READY_NOW; return TTY_READY_SOON; } - return TTY_READY_NOW; + + irq = di(); + port = SIO0_BASE+ 2 * (minor - 1); + out(port, 0); + c = in(port); + irqrestore(irq); + + if (c & 0x04) /* THRE? */ + return TTY_READY_NOW; + return TTY_READY_SOON; } void tty_data_consumed(uint8_t minor) { + used(minor); } /* kernel writes to system console -- never sleep! */ @@ -277,3 +363,20 @@ void kputchar(char c) while(tty_writeready(TTYDEV - 512) != TTY_READY_NOW); tty_putc(TTYDEV - 512, c); } + +int rctty_open(uint8_t minor, uint16_t flag) +{ + if (acia_present && minor != 1) { + udata.u_error = ENODEV; + return -1; + } + if ((minor == 1 || minor == 2) && !sio_present) { + udata.u_error = ENODEV; + return -1; + } + if ((minor == 3 || minor == 4) && !sio1_present) { + udata.u_error = ENODEV; + return -1; + } + return tty_open(minor, flag); +} diff --git a/Kernel/platform-sc108/devtty.h b/Kernel/platform-sc108/devtty.h index 518450e6..6bc732cd 100644 --- a/Kernel/platform-sc108/devtty.h +++ b/Kernel/platform-sc108/devtty.h @@ -2,9 +2,9 @@ #define __DEVTTY_DOT_H__ void tty_putc(uint8_t minor, unsigned char c); -void tty_pollirq_sio(void); +void tty_pollirq_sio0(void); +void tty_pollirq_sio1(void); void tty_pollirq_acia(void); - -extern uint8_t ser_type; +int rctty_open(uint8_t minor, uint16_t flag); #endif diff --git a/Kernel/platform-sc108/discard.c b/Kernel/platform-sc108/discard.c index 2a91275c..b54093d7 100644 --- a/Kernel/platform-sc108/discard.c +++ b/Kernel/platform-sc108/discard.c @@ -5,10 +5,19 @@ #include #include #include +#include #include "config.h" void map_init(void) { + if (acia_present) + kputs("6850 ACIA detected at 0x80.\n"); + if (sio_present) + kputs("Z80 SIO detected at 0x80.\n"); + if (sio1_present) + kputs("Z80 SIO detected at 0x84.\n"); + if (ctc_present) + kputs("Z80 CTC detected at 0x88.\n"); } /* diff --git a/Kernel/platform-sc108/kernel.def b/Kernel/platform-sc108/kernel.def index 37a5db61..20988a3a 100644 --- a/Kernel/platform-sc108/kernel.def +++ b/Kernel/platform-sc108/kernel.def @@ -17,12 +17,6 @@ CONSOLE_RATE .equ 115200 CPU_CLOCK_KHZ .equ 7372 -; Base address of SIO/2 chip 0x80 -; For the Scott Baker SIO card adjust the order to match rc2014.h -SIOA_C .EQU 0x80 -SIOA_D .EQU SIOA_D+1 -SIOB_C .EQU SIOA_D+2 -SIOB_D .EQU SIOA_D+3 ; Z80 CTC ports CTC_CH0 .equ 0x88 ; CTC channel 0 and interrupt vector CTC_CH1 .equ 0x89 ; CTC channel 1 (periodic interrupts) diff --git a/Kernel/platform-sc108/main.c b/Kernel/platform-sc108/main.c index 64925183..2ac5003c 100644 --- a/Kernel/platform-sc108/main.c +++ b/Kernel/platform-sc108/main.c @@ -6,6 +6,7 @@ #include #include #include +#include extern unsigned char irqvector; struct blkbuf *bufpool_end = bufpool + NBUFS; /* minimal for boot -- expanded after we're done with _DISCARD */ @@ -13,6 +14,10 @@ uint16_t swap_dev = 0xFFFF; uint16_t ramtop = 0xF000; uint8_t need_resched = 0; +uint8_t acia_present; +uint8_t ctc_present; +uint8_t sio_present; +uint8_t sio1_present; void platform_discard(void) { @@ -27,15 +32,15 @@ void platform_discard(void) kprintf("Buffers available: %d\n", bufpool_end - bufpool); } -static uint8_t idlect; - void platform_idle(void) { - /* Check the clock. We try and reduce the impact of the clock on - latency by not doing it so often. 256 may be too small a divide - need t see what 1/10th sec looks like in poll loops */ - if (!++idlect) + if (ctc_present) + __asm halt __endasm; + else { + irqflags_t irq = di(); sync_clock(); + irqrestore(irq); + } } uint8_t platform_param(unsigned char *p) @@ -44,13 +49,32 @@ uint8_t platform_param(unsigned char *p) return 0; } +static int16_t timerct; + +/* Call timer_interrupt at 10Hz */ +static void timer_tick(uint8_t n) +{ + timerct += n; + while (timerct >= 20) { + timer_interrupt(); + timerct -= 20; + } +} + void platform_interrupt(void) { - if (ser_type == 1) - tty_pollirq_sio(); - else + if (acia_present) tty_pollirq_acia(); - return; + if (sio_present) + tty_pollirq_sio0(); + if (sio1_present) + tty_pollirq_sio1(); + if (ctc_present) { + uint8_t n = 255 - CTC_CH3; + CTC_CH3 = 0x47; + CTC_CH3 = 255; + timer_tick(n); + } } /* @@ -93,24 +117,24 @@ static void sync_clock_read(void) */ void sync_clock(void) { - irqflags_t irq = di(); - int16_t tmp; - if (!re_enter++) { - sync_clock_read(); - if (oldticks != 0xFF) { - tmp = newticks - oldticks; - if (tmp < 0) - tmp += 60; - tmp *= 10; - while(tmp--) { - timer_interrupt(); + if (!ctc_present) { + irqflags_t irq = di(); + int16_t tmp; + if (!re_enter++) { + sync_clock_read(); + if (oldticks != 0xFF) { + tmp = newticks - oldticks; + if (tmp < 0) + tmp += 60; + tmp *= 10; + while(tmp--) { + timer_interrupt(); + } } } + re_enter--; + irqrestore(irq); } - re_enter--; - if (re_enter > 1) - kputs("oops"); - irqrestore(irq); } /* diff --git a/Kernel/platform-sc108/rc2014.h b/Kernel/platform-sc108/rc2014.h index 21ee491c..21b405d9 100644 --- a/Kernel/platform-sc108/rc2014.h +++ b/Kernel/platform-sc108/rc2014.h @@ -14,12 +14,28 @@ __sfr __at (SIO0_BASE + 1) SIOA_D; __sfr __at (SIO0_BASE + 2) SIOB_C; __sfr __at (SIO0_BASE + 3) SIOB_D; +#define SIO1_BASE 0x84 +__sfr __at (SIO1_BASE + 0) SIOC_C; +__sfr __at (SIO1_BASE + 1) SIOC_D; +__sfr __at (SIO1_BASE + 2) SIOD_C; +__sfr __at (SIO1_BASE + 3) SIOD_D; + /* ACIA is at same address as SIO but we autodetect */ #define ACIA_BASE 0x80 __sfr __at (ACIA_BASE + 0) ACIA_C; __sfr __at (ACIA_BASE + 1) ACIA_D; +__sfr __at 0x88 CTC_CH0; +__sfr __at 0x89 CTC_CH1; +__sfr __at 0x8A CTC_CH2; +__sfr __at 0x8B CTC_CH3; + extern void sio2_otir(uint8_t port) __z88dk_fastcall; +extern uint8_t acia_present; +extern uint8_t ctc_present; +extern uint8_t sio_present; +extern uint8_t sio1_present; + #endif diff --git a/Kernel/platform-sc108/sc108.s b/Kernel/platform-sc108/sc108.s index 33e65aa2..ee6e9ab5 100644 --- a/Kernel/platform-sc108/sc108.s +++ b/Kernel/platform-sc108/sc108.s @@ -30,7 +30,10 @@ .globl kstack_top .globl unix_syscall_entry .globl outcharhex - .globl _ser_type + .globl _acia_present + .globl _ctc_present + .globl _sio_present + .globl _sio1_present .globl s__COMMONMEM .globl l__COMMONMEM @@ -39,6 +42,26 @@ .include "../kernel.def" +; Base address of SIO/2 chip 0x80 + +SIOA_C .EQU 0x80 +SIOA_D .EQU SIOA_C+1 +SIOB_C .EQU SIOA_C+2 +SIOB_D .EQU SIOA_C+3 + +SIOC_C .EQU 0x84 +SIOC_D .EQU SIOC_C+1 +SIOD_C .EQU SIOC_C+2 +SIOD_D .EQU SIOC_C+3 + +ACIA_C .EQU 0x80 +ACIA_D .EQU 0x81 +ACIA_RESET .EQU 0x03 +ACIA_RTS_HIGH_A .EQU 0xD6 ; rts high, xmit interrupt disabled +ACIA_RTS_LOW_A .EQU 0x96 ; rts low, xmit interrupt disabled +;ACIA_RTS_LOW_A .EQU 0xB6 ; rts low, xmit interrupt enabled + + ; ; Buffers (we use asm to set this up as we need them in a special segment ; so we can recover the discard memory into the buffer pool @@ -119,19 +142,44 @@ init_hardware: call ldir_to_user ; Play guess the serial port - ; This needs doing better. We might be fooled by floating flow - ; control lines as the SC104 does expose flow control. FIXME - in a,(SIOA_C) - and #0x2C - cp #0x2C - ; CTS and DCD should be high as they are not wired - jr nz, try_acia + + ; + ; We are booted under ROMWBW, therefore use the same algorithm as + ; ROMWBW so if the probe fails we at least expect it to have failed + ; before we run. + ; + ; FIXME: see if we can cleanly ask ROMWBW for the device type + ; + + ; + ; This could be the ACIA control port. If so we mash the settings + ; up but that is ok as we will port them back in the ACIA probe + ; + + xor a + ld c,#SIOA_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, try_acia ; Repeat the check on SIO B - in a,(SIOB_C) - and #0x2C - cp #0x2C - jr z, is_sio + + xor a + ld c,#SIOB_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr nz, is_sio + try_acia: ; ; Look for an ACIA @@ -146,8 +194,8 @@ try_acia: ld a, #ACIA_RTS_LOW_A out (ACIA_C),a ; Initialise ACIA - ld a,#2 - ld (_ser_type),a + ld a,#1 + ld (_acia_present),a jp serial_up ; @@ -156,14 +204,12 @@ try_acia: ; At least until RC2014 grows a nice keyboard/display card! ; not_acia_either: - xor a - ld (_ser_type),a jp serial_up ; ; We have an SIO so do the required SIO hdance ; -is_sio: ld a,b - ld (_ser_type),a +is_sio: ld a,#1 + ld (_sio_present),a ld hl,#sio_setup ld bc,#0xA00 + SIOA_C ; 10 bytes to SIOA_C @@ -172,9 +218,123 @@ is_sio: ld a,b ld bc,#0x0A00 + SIOB_C ; and to SIOB_C otir + xor a + ld c,#SIOC_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, serial_up + + ; Repeat the check on SIO B + + xor a + ld c,#SIOD_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, serial_up + + ld a,#0x01 + ld (_sio1_present),a + + ld hl,#sio_setup + ld bc,#0xA00 + SIOC_C ; 10 bytes to SIOC_C + otir + ld hl,#sio_setup + ld bc,#0x0A00 + SIOD_C ; and to SIOD_C + otir + + serial_up: - im 1 ; set CPU interrupt mode - ret + + ; --------------------------------------------------------------------- + ; Initialize CTC + ; + ; Need to do autodetect on this + ; + ; We must initialize all channels of the CTC. The documentation + ; states that the initial CTC state is undefined and we don't want + ; random interrupt surprises + ; + ; --------------------------------------------------------------------- + + ; + ; Defense in depth - shut everything up first + ; + + ld a,#0x43 + out (CTC_CH0),a ; set CH0 mode + out (CTC_CH1),a ; set CH1 mode + out (CTC_CH2),a ; set CH2 mode + out (CTC_CH3),a ; set CH3 mode + + ; + ; Probe for a CTC + ; + + ld a,#0x47 ; CTC 2 as counter + out (CTC_CH2),a + ld a,#0xAA ; Set a count + out (CTC_CH2),a + in a,(CTC_CH2) + cp #0xAA ; Should not have changed + jr nz, no_ctc + + ld a,#0x07 + out (CTC_CH2),a + ld a,#2 + out (CTC_CH2),a + + ; We are now counting down from 2 very fast, so should only see + ; those values on the bus + + ld b,#0 +ctc_check: + in a,(CTC_CH2) + and #0xFC + jr nz, no_ctc + djnz ctc_check + + ; + ; Looks like we have a CTC + ; + +have_ctc: + ld a,#1 + ld (_ctc_present),a + + ; + ; Set up timer for 200Hz + ; + + ld a,#0xB5 + out (CTC_CH2),a + ld a,#144 + out (CTC_CH2),a ; 200 Hz + + ; + ; Set up counter CH3 for official SIO (the SC110 sadly can't be + ; used this way). + + ld a,#0x47 + out (CTC_CH3),a + ld a,#255 + out (CTC_CH3),a + +no_ctc: + ; Done CTC Stuff + ; --------------------------------------------------------------------- + + im 1 ; set Z80 CPU interrupt mode 1 + ret RTS_LOW .EQU 0xEA -- 2.34.1