#include "serial.h" /* Line Control * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * |dla| | parity | s | data | */ enum LineControlRegister : uint8_t { // data bits d5bit = 0b00000000, d6bit = 0b00000001, d7bit = 0b00000010, d8bit = 0b00000011, // parity bits none = 0b00000000, odd = 0b00001000, even = 0b00011000, mark = 0b00101000, space = 0b00111000, // stop bits s1bit = 0b00000000, s2bit = 0b00000100, // 1.5 for 5bit data; 2 otherwise // divisor latch access bit dlab = 0b10000000, }; /* Line Status Register */ enum LineStatusRegister : uint8_t { DR = 0b00000001, // data ready: see if there is data to read OE = 0b00000010, // overrun error: see if there has been data lost PE = 0b00000100, // parity error: see if there was error in transmission FE = 0b00001000, // framing error: see if a stop bit was missing BI = 0b00010000, // break indicator: see if there is a break in data input THRE = 0b00100000, // transmitter holding register empty: see if transmission buffer is empty TEMT = 0b01000000, // transmitter empty: see if transmitter is not doing anything ERRO = 0b10000000, // impending error: see if there is an error with a word in the input buffer }; SerialPort::SerialPort() { /* * The serial controller (UART) has a baud rate of 115200 ticks per second; to limit the speed of the port set the * divisor: * 1. set DLAB on LineControl * 2. set BaudDiv_l * 3. set BaudDiv_h * 4. clear LineControl */ port.write(0x00, InterruptControl); // disable all interrupts port.write(dlab, LineControl); port.write(0x03, BaudDiv_l); // div_l: 0x03 38400 baud port.write(0x00, BaudDiv_h); // div_h: 0x00 port.write(d8bit | none | s1bit, LineControl); // 8 bits, no parity, one stop bit port.write(0xc7, FifoControl); // enable FIFO, clear, with 14-byte threshold port.write(0x0b, ModemControl); // IRQ enabled, RTS/DSR set } bool SerialPort::ready_read() { return (port.read(LineStatus) & DR); } uint8_t SerialPort::read() { while (!ready_read()) { asm volatile("nop"); } return port.read(); } bool SerialPort::ready_write() { return (port.read(LineStatus) & THRE); } void SerialPort::write(char c) { while (!ready_write()) { asm volatile("nop"); } switch (c) { case '\n': port.write('\n'); port.write('\r'); break; default: port.write(static_cast(c)); } }