You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

51 lines
1.4 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
writeReg(INTERRUPT_ENABLE_REGISTER, RECEIVED_DATA_AVAILABLE);
// line control, select r/w of divisor latch register
writeReg(LINE_CONTROL_REGISTER, DIVISOR_LATCH_ACCESS_BIT);
writeReg(DIVISOR_LOW_REGISTER, baud_rate & 0xFF);
writeReg(DIVISOR_HIGH_REGISTER, (baud_rate>>8) & 0xFF);
// also turns DLAB off
uint8_t val = parity;
val |= stop_bits;
val |= data_bits;
writeReg(LINE_CONTROL_REGISTER, val);
// FIFO: Enable & clear buffers
writeReg(FIFO_CONTROL_REGISTER,
ENABLE_FIFO | CLEAR_RECEIVE_FIFO | CLEAR_TRANSMIT_FIFO);
// Modem Control: OUT2 (0000 1000) must be set for interrupt
writeReg(MODEM_CONTROL_REGISTER, OUT_2);
}
void Serial::writeReg(RegisterIndex reg, char out) {
uint16_t addr = port;
IOPort iop = IOPort(addr += reg);
iop.outb(out);
}
char Serial::readReg(RegisterIndex reg) {
uint16_t addr = port;
IOPort iop = IOPort(addr += reg);
return iop.inb();
}
int Serial::write(char out) {
//TODO fix behavior when \r\n ist actually sent
if(out == '\n')
write('\r');
while(!(readReg(LINE_STATUS_REGISTER) & TRANSMITTER_EMPTY));
writeReg(TRANSMIT_BUFFER_REGISTER, out);
return out;
}