#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_DIV16    0x15

static void acia_init(void)
{
    io_out(ACIA_CTRL_STATUS, ACIA_CMD_MASTER_RESET);
    io_out(ACIA_CTRL_STATUS, ACIA_CMD_8N1_DIV16);
}

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);

    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);
    }
}
