move all of uart state to a struct, preparing for save/restore
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 21 Jan 2022 14:52:25 +0000 (14:52 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 21 Jan 2022 14:52:25 +0000 (14:52 +0000)
verilator/uart-verilator.c

index 0346f6be6761d5d010b542e7d81a6039e9db7c9e..79c055628d725a23df300ad9e54276dfadc227b0 100644 (file)
 /* Round to nearest */
 #define BITWIDTH ((CLK_FREQUENCY+(BAUD/2))/BAUD)
 
+enum state {
+       IDLE, START_BIT, BITS, STOP_BIT, ERROR
+};
+
 /*
  * Our UART uses 16x oversampling, so at 50 MHz and 115200 baud
  * each sample is: 50000000/(115200*16) = 27 clock cycles. This
  * means each bit is off by 0.47% so for 8 bits plus a start and
  * stop bit the errors add to be 4.7%.
  */
-static double error = 0.05;
-
-enum state {
-       IDLE, START_BIT, BITS, STOP_BIT, ERROR
+struct uart_tx_state {
+    double error = 0.05;
+
+    enum state tx_state = IDLE;
+    unsigned long tx_countbits;
+    unsigned char tx_bits;
+    unsigned char tx_byte;
+    unsigned char tx_prev;
+
+    enum state rx_state = IDLE;
+    unsigned char rx_char;
+    unsigned long rx_countbits;
+    unsigned char rx_bit;
+    unsigned char rx = 1;
 };
 
-static enum state tx_state = IDLE;
-static unsigned long tx_countbits;
-static unsigned char tx_bits;
-static unsigned char tx_byte;
-static unsigned char tx_prev;
+static struct uart_tx_state uart;
 
 /*
  * Return an error if the transition is not close enough to the start or
@@ -37,9 +47,9 @@ static unsigned char tx_prev;
  */
 static bool is_error(unsigned long bits)
 {
-       double e = 1.0 * tx_countbits / BITWIDTH;
+       double e = 1.0 * uart.tx_countbits / BITWIDTH;
 
-       if ((e <= (1.0-error)) && (e >= error))
+       if ((e <= (1.0-uart.error)) && (e >= uart.error))
                return true;
 
        return false;
@@ -47,88 +57,88 @@ static bool is_error(unsigned long bits)
 
 void uart_tx(unsigned char tx)
 {
-       switch (tx_state) {
+       switch (uart.tx_state) {
                case IDLE:
                        if (tx == 0) {
-                               tx_state = START_BIT;
-                               tx_countbits = BITWIDTH;
-                               tx_bits = 0;
-                               tx_byte = 0;
+                               uart.tx_state = START_BIT;
+                               uart.tx_countbits = BITWIDTH;
+                               uart.tx_bits = 0;
+                               uart.tx_byte = 0;
                        }
                        break;
 
                case START_BIT:
-                       tx_countbits--;
+                       uart.tx_countbits--;
                        if (tx == 1) {
-                               if (is_error(tx_countbits)) {
-                                       printf("START_BIT error %ld %ld\n", BITWIDTH, tx_countbits);
-                                       tx_countbits = BITWIDTH*2;
-                                       tx_state = ERROR;
+                               if (is_error(uart.tx_countbits)) {
+                                       printf("START_BIT error %ld %ld\n", BITWIDTH, uart.tx_countbits);
+                                       uart.tx_countbits = BITWIDTH*2;
+                                       uart.tx_state = ERROR;
                                        break;
                                }
                        }
 
-                       if (tx_countbits == 0) {
-                               tx_state = BITS;
-                               tx_countbits = BITWIDTH;
+                       if (uart.tx_countbits == 0) {
+                               uart.tx_state = BITS;
+                               uart.tx_countbits = BITWIDTH;
                        }
                        break;
 
                case BITS:
-                       tx_countbits--;
-                       if (tx_countbits == BITWIDTH/2) {
-                               tx_byte = tx_byte | (tx << tx_bits);
-                               tx_bits = tx_bits + 1;
+                       uart.tx_countbits--;
+                       if (uart.tx_countbits == BITWIDTH/2) {
+                               uart.tx_byte = uart.tx_byte | (tx << uart.tx_bits);
+                               uart.tx_bits = uart.tx_bits + 1;
                        }
 
-                       if (tx != tx_prev) {
-                               if (is_error(tx_countbits)) {
-                                       printf("BITS error %ld %ld\n", BITWIDTH, tx_countbits);
-                                       tx_countbits = BITWIDTH*2;
-                                       tx_state = ERROR;
+                       if (tx != uart.tx_prev) {
+                               if (is_error(uart.tx_countbits)) {
+                                       printf("BITS error %ld %ld\n", BITWIDTH, uart.tx_countbits);
+                                       uart.tx_countbits = BITWIDTH*2;
+                                       uart.tx_state = ERROR;
                                        break;
                                }
                        }
 
-                       if (tx_countbits == 0) {
-                               if (tx_bits == 8) {
-                                       tx_state = STOP_BIT;
+                       if (uart.tx_countbits == 0) {
+                               if (uart.tx_bits == 8) {
+                                       uart.tx_state = STOP_BIT;
                                }
-                               tx_countbits = BITWIDTH;
+                               uart.tx_countbits = BITWIDTH;
                        }
                        break;
 
                case STOP_BIT:
-                       tx_countbits--;
+                       uart.tx_countbits--;
 
                        if (tx == 0) {
-                               if (is_error(tx_countbits)) {
-                                       printf("STOP_BIT error %ld %ld\n", BITWIDTH, tx_countbits);
-                                       tx_countbits = BITWIDTH*2;
-                                       tx_state = ERROR;
+                               if (is_error(uart.tx_countbits)) {
+                                       printf("STOP_BIT error %ld %ld\n", BITWIDTH, uart.tx_countbits);
+                                       uart.tx_countbits = BITWIDTH*2;
+                                       uart.tx_state = ERROR;
                                        break;
                                }
                                /* Go straight to idle */
-                               write(STDOUT_FILENO, &tx_byte, 1);
-                               tx_state = IDLE;
+                               write(STDOUT_FILENO, &uart.tx_byte, 1);
+                               uart.tx_state = IDLE;
                        }
 
-                       if (tx_countbits == 0) {
-                               write(STDOUT_FILENO, &tx_byte, 1);
-                               tx_state = IDLE;
+                       if (uart.tx_countbits == 0) {
+                               write(STDOUT_FILENO, &uart.tx_byte, 1);
+                               uart.tx_state = IDLE;
                        }
                        break;
 
                case ERROR:
-                       tx_countbits--;
-                       if (tx_countbits == 0) {
-                               tx_state = IDLE;
+                       uart.tx_countbits--;
+                       if (uart.tx_countbits == 0) {
+                               uart.tx_state = IDLE;
                        }
 
                        break;
        }
 
-       tx_prev = tx;
+       uart.tx_prev = tx;
 }
 
 static struct termios oldt;
@@ -188,12 +198,6 @@ static int nonblocking_read(unsigned char *c)
        }
 }
 
-static enum state rx_state = IDLE;
-static unsigned char rx_char;
-static unsigned long rx_countbits;
-static unsigned char rx_bit;
-static unsigned char rx = 1;
-
 /* Avoid calling poll() too much */
 #define RX_INTERVAL 10000
 static unsigned long rx_sometimes;
@@ -202,60 +206,60 @@ unsigned char uart_rx(void)
 {
        unsigned char c;
 
-       switch (rx_state) {
+       switch (uart.rx_state) {
                case IDLE:
                        if (rx_sometimes++ >= RX_INTERVAL) {
                                rx_sometimes = 0;
 
                                if (nonblocking_read(&c)) {
-                                       rx_state = START_BIT;
-                                       rx_char = c;
-                                       rx_countbits = BITWIDTH;
-                                       rx_bit = 0;
-                                       rx = 0;
+                                       uart.rx_state = START_BIT;
+                                       uart.rx_char = c;
+                                       uart.rx_countbits = BITWIDTH;
+                                       uart.rx_bit = 0;
+                                       uart.rx = 0;
                                }
                        }
 
                        break;
 
                case START_BIT:
-                       rx_countbits--;
-                       if (rx_countbits == 0) {
-                               rx_state = BITS;
-                               rx_countbits = BITWIDTH;
-                               rx = rx_char & 1;
+                       uart.rx_countbits--;
+                       if (uart.rx_countbits == 0) {
+                               uart.rx_state = BITS;
+                               uart.rx_countbits = BITWIDTH;
+                               uart.rx = uart.rx_char & 1;
                        }
                        break;
 
                case BITS:
-                       rx_countbits--;
-                       if (rx_countbits == 0) {
-                               rx_bit = rx_bit + 1;
-                               if (rx_bit == 8) {
-                                       rx = 1;
-                                       rx_state = STOP_BIT;
+                       uart.rx_countbits--;
+                       if (uart.rx_countbits == 0) {
+                               uart.rx_bit = uart.rx_bit + 1;
+                               if (uart.rx_bit == 8) {
+                                       uart.rx = 1;
+                                       uart.rx_state = STOP_BIT;
                                } else {
-                                       rx = (rx_char >> rx_bit) & 1;
+                                       uart.rx = (uart.rx_char >> uart.rx_bit) & 1;
                                }
-                               rx_countbits = BITWIDTH;
+                               uart.rx_countbits = BITWIDTH;
                        }
                        break;
 
                case STOP_BIT:
-                       rx_countbits--;
-                       if (rx_countbits == 0) {
-                               rx_state = IDLE;
+                       uart.rx_countbits--;
+                       if (uart.rx_countbits == 0) {
+                               uart.rx_state = IDLE;
                        }
                        break;
        }
 
-       return rx;
+       return uart.rx;
 }
 
 // cheating, here: to avoid having to save the uart state, check if it
 // is idle (both tx and rx)
-bool uart_idle(void)
+bool uart_state(void)
 {
-       return (tx_state == IDLE && rx_state == IDLE);
+       return (uart.tx_state == IDLE && uart.rx_state == IDLE);
 }