Figuring out the ATmega644 UART
Posted: Sun Aug 19, 2018 3:10 pm
So I started to explore the matter a little, how the ATmega's UART possibly works at low-level.
Very soon it revealed that this wouldn't be easy to emulate. For a start, the peripheral is more complex than SPI, even when used just as an ordinary UART. Now add that CunningFellow started to put cycle-accurate tasks on it...
Fiddling around with the RLE mode demo and how it relates timing, I found a likely implementation, would need further work for confirming, but it seems rather reasonable.
CunningFellow in the RLE mode sets the baud rate, and immediately after that, puts a character on the transmitter. Setting the baud rate (low) is odd, but likely it is there for a reason, that the mode didn't work properly without it. Why that could be? Examining the timing and the settings of the UART, it is set up for 16 samples for a bit, 7 bits per character + 1 start + 1 stop, which would make 9 bits * 16 samples * (8 + 1) baudrate, which is 1296 cycles. But it actually delays 1304 cycles there, 8 cycles more. Just why?
With a bit of reasoning, the baud rate generator should actually be a timer, started by writing the baud rate register if the UART is already enabled. So this timer could be running, dividing the main clock by 9 in this case. That could explain the 8 cycles experienced there, with an additional penalty cycle for the baud rate register write (as those are STS instructions, so the interrupt actually happens 1306 cycles from the baud rate register write, not 1305). Since 9 is not a divisor of 1820 (a scanline takes this many clocks), without setting the baud rate register again and again, it just wouldn't work.
Just a theory for now, but it should be something along the lines of this.
Cycle-accurate UART won't be a simple thing to accomplish.
CunningFellow: If you could provide details on findings while you did this, or possibly even code to experiment with, that could make figuring out the UART's cycle-accurate behavior easier!
Very soon it revealed that this wouldn't be easy to emulate. For a start, the peripheral is more complex than SPI, even when used just as an ordinary UART. Now add that CunningFellow started to put cycle-accurate tasks on it...
Fiddling around with the RLE mode demo and how it relates timing, I found a likely implementation, would need further work for confirming, but it seems rather reasonable.
CunningFellow in the RLE mode sets the baud rate, and immediately after that, puts a character on the transmitter. Setting the baud rate (low) is odd, but likely it is there for a reason, that the mode didn't work properly without it. Why that could be? Examining the timing and the settings of the UART, it is set up for 16 samples for a bit, 7 bits per character + 1 start + 1 stop, which would make 9 bits * 16 samples * (8 + 1) baudrate, which is 1296 cycles. But it actually delays 1304 cycles there, 8 cycles more. Just why?
With a bit of reasoning, the baud rate generator should actually be a timer, started by writing the baud rate register if the UART is already enabled. So this timer could be running, dividing the main clock by 9 in this case. That could explain the 8 cycles experienced there, with an additional penalty cycle for the baud rate register write (as those are STS instructions, so the interrupt actually happens 1306 cycles from the baud rate register write, not 1305). Since 9 is not a divisor of 1820 (a scanline takes this many clocks), without setting the baud rate register again and again, it just wouldn't work.
Just a theory for now, but it should be something along the lines of this.
Cycle-accurate UART won't be a simple thing to accomplish.
CunningFellow: If you could provide details on findings while you did this, or possibly even code to experiment with, that could make figuring out the UART's cycle-accurate behavior easier!