aboutsummaryrefslogtreecommitdiff
#include <tft.h>
#include <tty.h>
#include <i2c.h>
#include <zeta.h>
#include <input.h>

void
uart_putchar(char c);

static inline void
enable_input_fifo(void)
{
}

static inline void
disable_input_fifo(void)
{
}

static inline void
init_pio(void)
{
	// Control mode - i.e. no parallel port communication
	port_b_ctrl = PIO_MODE_3;
	// A, B and five keys as inputs
	port_b_ctrl = 0x7F;
	// Load interrupt vector
	//  port_b_ctrl = ISR_ADDRESS(port_b_isr_ptr);
	// Interrupt word - interrupt if any pin goes low, mask follows
    //  port_b_ctrl = PIO_INT_CTRL(PIO_INT_EN | PIO_OR | PIO_LOW | PIO_MASK);
	// Mask - 0 means to check line
	//  port_b_ctrl = 0x80;

	/* port_a_ctrl = PIO_MODE_3; */

	/* port_a_ctrl = 0x7C; */

	/* // Load interrupt vector */
	/* port_a_ctrl = ISR_ADDRESS(port_a_isr_ptr); */

	/* port_a_ctrl = PIO_INT_CTRL(PIO_INT_EN | PIO_OR | PIO_HIGH | PIO_MASK); */
	/* port_a_ctrl = 0x83; */

	/* // SDA and SCL high */
	/* port_a_data = 0x03; */
}

static inline void
init_ctc(void)
{
	/* 200Hz clock */
	ctc_channel_1 = CTC_CTRL(CTC_INT_BIT | CTC_PRESCALER_BIT
							 | CTC_TIME_CONST_BIT | CTC_RST_BIT);
	ctc_channel_1 = 0;

	/* 200Hz clock */
	ctc_channel_2 = CTC_CTRL(CTC_INT_BIT | CTC_PRESCALER_BIT
							 | CTC_TIME_CONST_BIT | CTC_RST_BIT);
	ctc_channel_2 = 0;

    /* ctc_channel_3 = (CPU_FREQ / 256 / 144); */

	ctc_channel_3 = CTC_CTRL(CTC_INT_BIT | CTC_PRESCALER_BIT
							 | CTC_TIME_CONST_BIT | CTC_RST_BIT);
	ctc_channel_3 = 0; // 256

	// Interrupt table for CTC
	// Final address is (Ireg << 8) | ctc_isr_ptr | {00/01/10/11} | 0
	ctc_channel_0 = ISR_ADDRESS(ctc0_isr_ptr);
}

static inline void
init_sio(void)
{
	static const u8 sio_a_cfg[] = {
		0b00011000,                      // Reset channel
		4         ,                      // wr4
		0b01000100,                      // X16 clock (115200), one stop bit, no parity
		1         ,                      // wr1
		SIO_RX_INT_MD0 | SIO_RX_INT_MD1, // interrupt on every Rx, no wait function
		3         ,                      // wr3
		0b11000001,                      // enable Rx - 8 bit char
		5         ,                      // wr5
		0b01101000                       // enable Tx - 8 bit char
	};

	static const u8 sio_b_cfg[] = {
		0b00011000,                     // Reset channel
		2         ,                     // load interrupt vector
		ISR_ADDRESS(rx_isr_ptr)         // int_table_rx
	};

    for (u8 i = 0; i < LENGTH(sio_a_cfg); ++i)
        sio_a_ctrl = sio_a_cfg[i];

    for (u8 i = 0; i < LENGTH(sio_b_cfg); ++i)
        sio_b_ctrl = sio_b_cfg[i];
}

// copy code to ram, so function pointer is modifyable

static uint8_t tick = 0;

void
timer(void) __critical __interrupt(5)
{
	static int prescale = 0;

	if (++prescale == 150) {
		prescale = 0;
		tick = 1;
	}
}

/* i2c_start_condition(); */
/* i2c_send(0xA0); */
/* i2c_send(0x00); */
/* i2c_send(0x00); */
/* i2c_restart_condition(); */
/* i2c_send(0xA1); */
/* b = i2c_recv(NACK); */
/* i2c_stop_condition(); */

void
main(void)
{
	tft_init();

	init_ctc();
	init_pio();
	init_sio();

    // Interrupt mode 2
    IM(2);
    // Enable interrupts
    EI;

	// Boot menu
	addstr("1) Programming mode\r\n");
	addstr("2) Normal boot (default)\r\n");
	addstr("3) Boot address 0xC000\r\n");

	for (int i = 5; i > 0; --i) {
		addch('\r');
		addch(i + '0');

		while (!tick) {
			u8 keys = poll_keys();

			if (!(keys & KEY2)) {
				addch('\r');
				bootloader();
			}

			if (!(keys & KEY3)) {
				goto boot;
			}

			if (!(keys & KEY4)) {
				// Definitely safe looking C code ...
				void (*ptr)(void) = (void (*)(void))0xC000;
				ptr();
			}
		}

		DI;
		tick = 0;
		EI;
	}

	addch('\r');

boot:
	addstr("Starting system ...\r\n");
	// Load interrupt vector
	port_b_ctrl = ISR_ADDRESS(port_b_isr_ptr);
	// Interrupt word - interrupt if any pin goes low, mask follows
    port_b_ctrl = PIO_INT_CTRL(PIO_INT_EN | PIO_OR | PIO_LOW | PIO_MASK);
	// Mask - 0 means to check line
	port_b_ctrl = 0x80;
	_menu();

	while (1)
		;
}