1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#include <mos/types.hpp>
6
7typedef enum : u16
8{
9 OFFSET_INTERRUPT_ENABLE = 1, // Interrupt Enable Register
10 OFFSET_INTERRUPT_ID_FIFO = 2, // Interrupt ID Register and FIFO Control Register
11 OFFSET_LINE_CONTROL = 3, // Line Control Register
12 OFFSET_MODEM_CONTROL = 4, // Modem Control Register
13 OFFSET_LINE_STATUS = 5, // Line Status Register
14 OFFSET_MODEM_STATUS = 6, // Modem Status Register
15 OFFSET_SCRATCH = 7, // Scratch Register
16
17 OFFSET_DLAB_DIVISOR_LSB = 0, // With DLAB set to 1, this is the least significant byte of the divisor value for setting the baud rate.
18 OFFSET_DLAB_DIVISOR_MSB = 1, // With DLAB set to 1, this is the most significant byte of the divisor value.
19} serial_register_t;
20
21typedef enum
22{
23 CHAR_LENGTH_5 = 0x0,
24 CHAR_LENGTH_6 = 0x1,
25 CHAR_LENGTH_7 = 0x2,
26 CHAR_LENGTH_8 = 0x3,
27} serial_charlength_t;
28
29typedef enum
30{
31 STOP_BITS_1, // 1 stop bit
32 STOP_BITS_15_OR_2, // 1.5 or 2 stop bits
33} serial_stopbits_t;
34
35typedef enum
36{
37 PARITY_NONE = 0, // No parity
38 PARITY_ODD = 1, // Odd parity
39 PARITY_EVEN = 2, // Even parity
40 PARITY_MARK = 3, // Parity bit always 1
41 PARITY_SPACE = 4, // Parity bit always 0
42} serial_parity_t;
43
44typedef enum
45{
46 INTERRUPT_DATA_AVAILABLE = 1 << 0, // Data ready interrupt
47 INTERRUPT_TRANSMITTER_EMPTY = 1 << 1, // Transmitter empty interrupt
48 INTERRUPT_BREAK_ERROR = 1 << 2, // Break error interrupt
49 INTERRUPT_STATUS_CHANGE = 1 << 3, // Status change interrupt
50 INTERRUPT_NONE = 0, // No interrupts
51 INTERRUPT_ALL = INTERRUPT_DATA_AVAILABLE | INTERRUPT_TRANSMITTER_EMPTY | INTERRUPT_BREAK_ERROR | INTERRUPT_STATUS_CHANGE,
52} serial_interrupt_t;
53
54typedef enum
55{
56 BAUD_RATE_115200 = 1,
57 BAUD_RATE_57600 = 2,
58 BAUD_RATE_38400 = 3,
59 BAUD_RATE_19200 = 4,
60 BAUD_RATE_9600 = 5,
61 BAUD_RATE_4800 = 6,
62 BAUD_RATE_2400 = 7,
63 BAUD_RATE_1200 = 8,
64 BAUD_RATE_600 = 9,
65 BAUD_RATE_300 = 10,
66 BAUD_RATE_110 = 11,
67} serial_baudrate_t;
68
69class ISerialDevice;
70
71class ISerialDevice
72{
73 public:
74 virtual ~ISerialDevice() = default;
75
76 virtual u8 read_byte() = 0;
77 virtual int write_byte(u8 byte) = 0;
78 virtual bool get_data_ready() = 0;
79 virtual u8 read_register(serial_register_t offset) = 0;
80 virtual void write_register(serial_register_t offset, u8 value) = 0;
81
82 public:
83 bool setup();
84 int read_data(char *data, size_t length);
85 int write_data(const char *data, size_t length);
86
87 protected:
88 serial_baudrate_t baudrate_divisor;
89 serial_charlength_t char_length;
90 serial_stopbits_t stop_bits;
91 serial_parity_t parity;
92
93 private:
94 typedef enum
95 {
96 MODEM_DCTS = 1 << 0, // Clear To Send input has changed since last read.
97 MODEM_DDSR = 1 << 1, // Data Set Ready input has changed since last read.
98 MODEM_TERI = 1 << 2, // Ring Indicator input has changed since last read.
99 MODEM_DDCD = 1 << 3, // Data Carrier Detect input has changed since last read.
100 MODEM_CLEAR_TO_SEND = 1 << 4,
101 MODEM_DATA_SET_READY = 1 << 5,
102 MODEM_RING_INDICATOR = 1 << 6,
103 MODEM_DATA_CARRIER_DETECT = 1 << 7,
104 } serial_modem_status_t;
105
106 typedef enum
107 {
108 MODEM_DTR = 1 << 0, // Data Terminal Ready
109 MODEM_RTS = 1 << 1, // Request To Send
110 MODEM_UNUSED_PIN1 = 1 << 2, // Unused
111 MODEM_IRQ = 1 << 3, // Interrupt Request
112 MODEM_LOOP = 1 << 4, // Loopback
113 } serial_modem_control_t;
114
115 typedef enum
116 {
117 LINE_DATA_READY = 1 << 0, // Data ready to be read.
118 LINE_ERR_OVERRUN = 1 << 1, // There has been data lost.
119 LINE_ERR_PARITY = 1 << 2, // Parity error.
120 LINE_ERR_FRAMING = 1 << 3, // Stop bit is missing.
121 LINE_ERR_BREAK = 1 << 4, // Break detected.
122 LINE_TRANSMITR_BUF_EMPTY = 1 << 5, // (transmitter buffer is empty) Data can be sent.
123 LINE_TRANSMITR_EMPTY = 1 << 6, // Transmitter is not doing anything.
124 LINE_ERR_IMPENDING = 1 << 7, // There is an error with a word in the input buffer
125 } serial_line_status_t;
126
127 void SetBaudrateDivisor();
128 void SetDataBits();
129 void SetStopBits();
130 void SetParity();
131 void SetInterrupts(int interrupts);
132 void SetModemOptions(serial_modem_control_t control, bool enable);
133
134 char GetLineStatus();
135 __maybe_unused char GetModelStatus();
136 bool GetDataReady();
137
138 void WaitReadyToRead();
139 void WaitReadyToWrite();
140};
141