56 lines
1.7 KiB
C++
56 lines
1.7 KiB
C++
#include "serial.h"
|
|
|
|
#include "ioport.h"
|
|
|
|
Serial::Serial(ComPort port, BaudRate baud_rate, DataBits data_bits,
|
|
StopBits stop_bits, Parity parity)
|
|
: port(port) {
|
|
// initialize FIFO mode, no irqs for sending, irq if first byte was received
|
|
|
|
// line control, select r/w of divisor latch register
|
|
writeReg(RegisterIndex::LINE_CONTROL,
|
|
static_cast<uint8_t>(RegisterMask::DIVISOR_LATCH_ACCESS_BIT));
|
|
|
|
// config divisor
|
|
uint16_t divisor = static_cast<uint16_t>(baud_rate);
|
|
// write low byte of divisor latch
|
|
writeReg(RegisterIndex::DIVISOR_LOW, divisor & 0xff);
|
|
// write high byte
|
|
writeReg(RegisterIndex::DIVISOR_HIGH, (divisor >> 8) & 0xff);
|
|
|
|
// deselect r/w of divisor latch register
|
|
// configure line control
|
|
writeReg(RegisterIndex::LINE_CONTROL, static_cast<uint8_t>(data_bits) |
|
|
static_cast<uint8_t>(stop_bits) |
|
|
static_cast<uint8_t>(parity));
|
|
|
|
// FIFO: Enable & clear buffers
|
|
writeReg(RegisterIndex::FIFO_CONTROL,
|
|
static_cast<uint8_t>(RegisterMask::ENABLE_FIFO) |
|
|
static_cast<uint8_t>(RegisterMask::CLEAR_RECEIVE_FIFO) |
|
|
static_cast<uint8_t>(RegisterMask::CLEAR_TRANSMIT_FIFO));
|
|
|
|
// Modem Control: OUT2 (0000 1000) must be set for interrupt
|
|
writeReg(RegisterIndex::MODEM_CONTROL,
|
|
static_cast<uint8_t>(RegisterMask::OUT_2));
|
|
}
|
|
|
|
void Serial::writeReg(RegisterIndex reg, uint8_t out) {
|
|
IOPort p(static_cast<uint16_t>(port) + static_cast<uint16_t>(reg));
|
|
p.outb(out);
|
|
}
|
|
|
|
uint8_t Serial::readReg(RegisterIndex reg) {
|
|
IOPort p(static_cast<uint16_t>(port) + static_cast<uint16_t>(reg));
|
|
return p.inb();
|
|
}
|
|
|
|
int Serial::write(uint8_t out) {
|
|
while ((readReg(RegisterIndex::LINE_STATUS) &
|
|
static_cast<uint8_t>(RegisterMask::TRANSMITTER_EMPTY)) == 0) {
|
|
}
|
|
|
|
writeReg(RegisterIndex::TRANSMIT_BUFFER, out);
|
|
return out;
|
|
}
|