1 // Copyright (C) IBM 2019, see LICENSE.CC4
2 // based on code from microwatt https://github.com/antonblanchard/microwatt
12 /* Should we exit simulation on ctrl-c or pass it through? */
13 #define EXIT_ON_CTRL_C
16 /* Round to nearest */
17 #define BITWIDTH ((CLK_FREQUENCY+(BAUD/2))/BAUD)
20 * Our UART uses 16x oversampling, so at 50 MHz and 115200 baud
21 * each sample is: 50000000/(115200*16) = 27 clock cycles. This
22 * means each bit is off by 0.47% so for 8 bits plus a start and
23 * stop bit the errors add to be 4.7%.
25 static double error
= 0.05;
28 IDLE
, START_BIT
, BITS
, STOP_BIT
, ERROR
31 static enum state tx_state
= IDLE
;
32 static unsigned long tx_countbits
;
33 static unsigned char tx_bits
;
34 static unsigned char tx_byte
;
35 static unsigned char tx_prev
;
38 * Return an error if the transition is not close enough to the start or
39 * the end of an expected bit.
41 static bool is_error(unsigned long bits
)
43 double e
= 1.0 * tx_countbits
/ BITWIDTH
;
45 if ((e
<= (1.0-error
)) && (e
>= error
))
51 void uart_tx(unsigned char tx
)
57 tx_countbits
= BITWIDTH
;
66 if (is_error(tx_countbits
)) {
67 printf("START_BIT error %ld %ld\n", BITWIDTH
, tx_countbits
);
68 tx_countbits
= BITWIDTH
*2;
74 if (tx_countbits
== 0) {
76 tx_countbits
= BITWIDTH
;
82 if (tx_countbits
== BITWIDTH
/2) {
83 tx_byte
= tx_byte
| (tx
<< tx_bits
);
84 tx_bits
= tx_bits
+ 1;
88 if (is_error(tx_countbits
)) {
89 printf("BITS error %ld %ld\n", BITWIDTH
, tx_countbits
);
90 tx_countbits
= BITWIDTH
*2;
96 if (tx_countbits
== 0) {
100 tx_countbits
= BITWIDTH
;
108 if (is_error(tx_countbits
)) {
109 printf("STOP_BIT error %ld %ld\n", BITWIDTH
, tx_countbits
);
110 tx_countbits
= BITWIDTH
*2;
114 /* Go straight to idle */
115 write(STDOUT_FILENO
, &tx_byte
, 1);
119 if (tx_countbits
== 0) {
120 write(STDOUT_FILENO
, &tx_byte
, 1);
127 if (tx_countbits
== 0) {
137 static struct termios oldt
;
139 static void disable_raw_mode(void)
141 tcsetattr(STDIN_FILENO
, TCSANOW
, &oldt
);
144 static void enable_raw_mode(void)
146 static bool initialized
= false;
149 static struct termios newt
;
151 tcgetattr(STDIN_FILENO
, &oldt
);
154 #ifdef EXIT_ON_CTRL_C
155 newt
.c_lflag
|= ISIG
;
157 tcsetattr(STDIN_FILENO
, TCSANOW
, &newt
);
159 atexit(disable_raw_mode
);
163 static int nonblocking_read(unsigned char *c
)
166 unsigned long val
= 0;
167 struct pollfd fdset
[1];
171 memset(fdset
, 0, sizeof(fdset
));
173 fdset
[0].fd
= STDIN_FILENO
;
174 fdset
[0].events
= POLLIN
;
176 ret
= poll(fdset
, 1, 0);
180 ret
= read(STDIN_FILENO
, &val
, 1);
182 fprintf(stderr
, "%s: read of stdin returns %d\n", __func__
, ret
);
194 static enum state rx_state
= IDLE
;
195 static unsigned char rx_char
;
196 static unsigned long rx_countbits
;
197 static unsigned char rx_bit
;
198 static unsigned char rx
= 1;
200 /* Avoid calling poll() too much */
201 #define RX_INTERVAL 10000
202 static unsigned long rx_sometimes
;
204 unsigned char uart_rx(void)
210 if (rx_sometimes
++ >= RX_INTERVAL
) {
213 if (nonblocking_read(&c
)) {
214 rx_state
= START_BIT
;
216 rx_countbits
= BITWIDTH
;
226 if (rx_countbits
== 0) {
228 rx_countbits
= BITWIDTH
;
235 if (rx_countbits
== 0) {
241 rx
= (rx_char
>> rx_bit
) & 1;
243 rx_countbits
= BITWIDTH
;
249 if (rx_countbits
== 0) {