From: Michel Pollet Date: Tue, 15 Mar 2011 13:33:54 +0000 (+0000) Subject: uart: Added logic to regulate data rate X-Git-Tag: v1.0a8~10 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=5b1830d85cd06020f50290b5e5b8e9e5e7049dae;p=sx%2Fsimavr.git uart: Added logic to regulate data rate Now uses a data rate thst is proportional to speed. Could be made a bit better by using the cycle clock count directly, but this method is a bit clearer Signed-off-by: Michel Pollet --- diff --git a/simavr/sim/avr_uart.c b/simavr/sim/avr_uart.c index f6000e6..7cb019a 100644 --- a/simavr/sim/avr_uart.c +++ b/simavr/sim/avr_uart.c @@ -97,8 +97,9 @@ static uint8_t avr_uart_read(struct avr_t * avr, avr_io_addr_t addr, void * para // made to trigger potential watchpoints v = avr_core_watch_read(avr, addr); - if (!uart_fifo_isempty(&p->input)) - avr_cycle_timer_register_usec(avr, 100, avr_uart_rxc_raise, p); // should be uart speed dependent + // should always trigger that timer +// if (!uart_fifo_isempty(&p->input)) + avr_cycle_timer_register_usec(avr, p->usec_per_byte, avr_uart_rxc_raise, p); return v; } @@ -113,7 +114,17 @@ static void avr_uart_baud_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t baud /= 8; else baud /= 16; - printf("UART-%c configured to %04x = %d baud\n", p->name, val, baud); + + const int databits[] = { 5,6,7,8, /* 'reserved', assume 8 */8,8,8, 9 }; + int db = databits[avr_regbit_get(avr, p->ucsz) | (avr_regbit_get(avr, p->ucsz2) << 2)]; + int sb = 1 + avr_regbit_get(avr, p->usbs); + int word_size = 1 /* start */ + db /* data bits */ + 1 /* parity */ + sb /* stops */; + + printf("UART-%c configured to %04x = %d bps, %d data %d stop\n", + p->name, val, baud, db, sb); + // TODO: Use the divider value and calculate the straight number of cycles + p->usec_per_byte = 1000000 / (baud / word_size); + printf("Roughtly %d usec per bytes\n", (int)p->usec_per_byte); } static void avr_uart_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) @@ -124,7 +135,8 @@ static void avr_uart_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, vo avr_core_watch_write(avr, addr, v); avr_regbit_clear(avr, p->udrc.raised); - avr_cycle_timer_register_usec(avr, 100, avr_uart_txc_raise, p); // should be uart speed dependent + avr_cycle_timer_register_usec(avr, + p->usec_per_byte, avr_uart_txc_raise, p); // should be uart speed dependent if (p->flags & AVR_UART_FLAG_STDIO) { static char buf[128]; @@ -180,7 +192,7 @@ static void avr_uart_irq_input(struct avr_irq_t * irq, uint32_t value, void * pa return; if (uart_fifo_isempty(&p->input)) - avr_cycle_timer_register_usec(avr, 100, avr_uart_rxc_raise, p); // should be uart speed dependent + avr_cycle_timer_register_usec(avr, p->usec_per_byte, avr_uart_rxc_raise, p); // should be uart speed dependent uart_fifo_write(&p->input, value); // add to fifo // printf("UART IRQ in %02x (%d/%d) %s\n", value, p->input.read, p->input.write, uart_fifo_isfull(&p->input) ? "FULL!!" : ""); @@ -201,7 +213,7 @@ void avr_uart_reset(struct avr_io_t *io) // DEBUG allow printf without fidding with enabling the uart avr_regbit_set(avr, p->txen); - + p->usec_per_byte = 100; } static int avr_uart_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param) diff --git a/simavr/sim/avr_uart.h b/simavr/sim/avr_uart.h index 4764e72..dc9e805 100644 --- a/simavr/sim/avr_uart.h +++ b/simavr/sim/avr_uart.h @@ -92,6 +92,9 @@ typedef struct avr_uart_t { avr_regbit_t rxen; // receive enabled avr_regbit_t txen; // transmit enable avr_regbit_t u2x; // double UART speed + avr_regbit_t usbs; // stop bits + avr_regbit_t ucsz; // data bits + avr_regbit_t ucsz2; // data bits, continued avr_io_addr_t r_ubrrl,r_ubrrh; @@ -102,6 +105,7 @@ typedef struct avr_uart_t { uart_fifo_t input; uint32_t flags; + avr_cycle_count_t usec_per_byte; } avr_uart_t; /* takes a uint32_t* as parameter */