stuff
This commit is contained in:
9
boot.asm
9
boot.asm
@@ -1,12 +1,13 @@
|
|||||||
STACK_TOP = 0xFFFF
|
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:
|
; The inner delay loop below costs about 26 T-states per taken iteration:
|
||||||
; dec hl = 6T
|
; dec hl = 6T
|
||||||
; ld a,h = 4T
|
; ld a,h = 4T
|
||||||
; or l = 4T
|
; or l = 4T
|
||||||
; jr nz = 12T
|
; jr nz = 12T
|
||||||
; 500 / 26 = 19.2, so 20 iterations is the nearest simple whole-number choice.
|
; 1000 / 26 = 38.5. Use 40 iterations to retain the previous calibration,
|
||||||
DELAY_LOOPS_PER_MS = 20
|
; which used 20 iterations at 500 kHz.
|
||||||
|
DELAY_LOOPS_PER_MS = 40
|
||||||
|
|
||||||
.globl _main
|
.globl _main
|
||||||
.globl _delay_ms
|
.globl _delay_ms
|
||||||
@@ -99,7 +100,7 @@ _io_in::
|
|||||||
|
|
||||||
; Approximate millisecond delay.
|
; Approximate millisecond delay.
|
||||||
; Input: HL = delay in milliseconds.
|
; 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::
|
_delay_ms::
|
||||||
ld a, h
|
ld a, h
|
||||||
or l
|
or l
|
||||||
|
|||||||
148
main.c
148
main.c
@@ -1,117 +1,65 @@
|
|||||||
#include "boot.h"
|
#include "boot.h"
|
||||||
|
|
||||||
/*
|
#define VID_CMD 0x80
|
||||||
* 6850 ACIA test wiring assumption:
|
#define VID_DAT 0x81
|
||||||
* /CS2 is driven by not-A5, so the ACIA is selected when A5 = 1.
|
#define VID_CMD_SET_TEXT_MODE 0
|
||||||
* RS is assumed to be wired to A0, giving:
|
#define VID_CMD_SET_PIXEL_MODE 1
|
||||||
* 0x20 = status/control
|
#define VID_CMD_CLR 2
|
||||||
* 0x21 = data
|
#define VID_CMD_TEXT_POS_X 3
|
||||||
*/
|
#define VID_CMD_TEXT_POS_Y 5
|
||||||
#define ACIA_CTRL_STATUS 0x20
|
#define VID_CMD_PIXEL_POS_X 4
|
||||||
#define ACIA_DATA 0x21
|
#define VID_CMD_PIXEL_POS_Y 6
|
||||||
|
|
||||||
#define ACIA_STATUS_RDRF 0x01
|
void putc(char c){
|
||||||
#define ACIA_STATUS_TDRE 0x02
|
io_out(VID_DAT, c);
|
||||||
|
|
||||||
#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)
|
void puts(char * s){
|
||||||
{
|
while(*s){
|
||||||
/* Leave unused channels in reset. */
|
putc(*s);
|
||||||
io_out(CTC_CHANNEL_1, CTC_CMD_RESET);
|
s++;
|
||||||
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)
|
void main(void)
|
||||||
{
|
{
|
||||||
uint8_t cnt = 0;
|
delay_ms(100);
|
||||||
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(;;){
|
for(;;){
|
||||||
uint8_t status = acia_status();
|
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);
|
||||||
|
|
||||||
if (acia_getc_nonblocking(&ch)) {
|
|
||||||
io_out(PIO_A_DATA, ch);
|
for(uint8_t i=0; i<18; i++){
|
||||||
acia_putc(ch);
|
putc('0'+i);
|
||||||
if (ch == '\r') {
|
puts("\r\n");
|
||||||
acia_putc('\n');
|
|
||||||
}
|
|
||||||
delay_ms(50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
acia_putc((uint8_t)('0' + (cnt & 0x07)));
|
delay_ms(2000);
|
||||||
acia_puts("\r\n");
|
|
||||||
cnt++;
|
|
||||||
delay_ms(250);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user