PS/2 Keyboard Working with ATTINY and I2C

Chat about anything CX16 related that doesn't fit elsewhere
Fabio
Posts: 41
Joined: Sat Aug 21, 2021 12:13 pm

PS/2 Keyboard Working with ATTINY and I2C

Post by Fabio »


All of you have done a great job!?.

a point remains open : Does it work also with the mouse?

Trax81
Posts: 16
Joined: Mon Jun 22, 2020 12:34 pm

PS/2 Keyboard Working with ATTINY and I2C

Post by Trax81 »


Wow, that's a great outcome, you explained it well - and what a great use of the microcontroller. Further justifying its existence.

I can't wait to see another video! Thank you!

The "keyboard works as intended" line is +100% awesome.

BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

PS/2 Keyboard Working with ATTINY and I2C

Post by BruceMcF »



On 7/11/2022 at 7:37 PM, Wavicle said:




There is a performance increase. Is it noticeable? That depends.



... If we instead ask "can it get more done in a single frame than it could before", then yes it can, but it may only work out to 0.5 to maybe 2.0 milliseconds per second saved. It's definitely more than nothing; it may be below the threshold of perception. I'd have to put the scope on the hardware and get the per-frame timing of each to answer better.



I would expect that "performance improvement" questions that would be on some people's minds would not be how much of the per-frame time slice is saved, but rather how much of the time slice from the V_SYNC interrupt to the start of the visible frame ... the vertical front porch ... is saved.

But, as for me, "the keyboard goes from not working to working" is the performance upgrade I have been hoping for.

Wavicle
Posts: 284
Joined: Sun Feb 21, 2021 2:40 am

PS/2 Keyboard Working with ATTINY and I2C

Post by Wavicle »


A couple quick updates:


  1. I was able to work with Kevin Williams the last few days and the PS/2 -> I2C -> X16 path is now working on the official X16 Prototype 3 board!


  2. We have been working on stabilizing the I2C code. My initial optimism of 0% key loss was not quite correct.


Tonight I took the time to understand the kernel's I2C code, document it, and fix some of the ugly corners that could have been contributing to the overall stability of I2C. A logic analyzer trace of a key fetch transaction now looks like this:

image.thumb.png.95d263b32656b234bce65cb2009777ec.png

The clocks are fairly even, though the duty cycle is obviously not 50%. The clock is pretty consistently about 33%, which is well within spec. Start conditions (green circles on the purple waveform) and stop conditions (red circles on the purple waveform) are clean and it looks like SDA is only ever changing when SCL is low (per I2C spec).

I2C isn't done yet, but it is getting closer. My greatest point of unhappiness right now is the effective clock rate - it's about 56KHz. Checking the keyboard consumes roughly 700 microseconds. The challenge to increasing the speed here comes down to the ATTINY. The trace above shows two I2C transactions: a write of 0x07 (telling ATTINY that we wish to access register 7, the scan code buffer register) and a single byte read that returns the data in that register. The ATTINY's Universal Serial Interface can receive a single byte at up to 24MHz! BUT it has to process the request in the gap between the "Setup Read" byte and the "0x00 + NAK" byte in the above trace. That's only about 20 microseconds. I switched the ATTINY to use the internal PLL clock which increased it from 8MHz to 16MHz, which helped a lot, but it sometimes misses the window of opportunity leading to bytes that don't start clocking out until the second or third I2C clock.

Things are progressing ever more in the forward direction...

User avatar
desertfish
Posts: 1096
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

PS/2 Keyboard Working with ATTINY and I2C

Post by desertfish »


I understand a few of those words!   ?

Jokes aside, I think this is amazing work. Great job

Wavicle
Posts: 284
Joined: Sun Feb 21, 2021 2:40 am

PS/2 Keyboard Working with ATTINY and I2C

Post by Wavicle »


I think that one of the reasons I need to post these updates is that every time I mention the thing that isn't working, we end up fixing it the next day.

With huge thanks for a small code change suggestion from @Stefan, adding a simple check that allows us to support I2C clock stretching, it now appears that every I2C error we had been seeing has resolved. Previously using an I2C torture tests provided by @ZeroByte and @Jeffrey, we had an error rate of about 1 erroneous value per 5,000 transactions. After this small change, I have yet to see an error after 300K transactions so far over the past 2 hours. The keyboard support seems to be rock solid.

The I2C clock, unfortunately, seems to have maxed out at around an effective rate of 75-80KHz. There might be some things we can do here and there to pick up 1 or 2 KHz, but I think all of the low hanging fruit has been plucked. Each keyboard scan code takes roughly 515 microseconds during VYSNC. I've got a draft PR for the kernel fixes out for review. Those interested can see that here: Improve I2C support and move PS/2 keyboard support to SMC by jburks · Pull Request #331 · commanderx16/x16-rom (github.com)

BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

PS/2 Keyboard Working with ATTINY and I2C

Post by BruceMcF »



On 7/14/2022 at 5:35 AM, Wavicle said:




A couple quick updates:




  1. I was able to work with Kevin Williams the last few days and the PS/2 -> I2C -> X16 path is now working on the official X16 Prototype 3 board!


  2. We have been working on stabilizing the I2C code. My initial optimism of 0% key loss was not quite correct.




Tonight I took the time to understand the kernel's I2C code, document it, and fix some of the ugly corners that could have been contributing to the overall stability of I2C. A logic analyzer trace of a key fetch transaction now looks like this:



image.thumb.png.95d263b32656b234bce65cb2009777ec.png



The clocks are fairly even, though the duty cycle is obviously not 50%. The clock is pretty consistently about 33%, which is well within spec. Start conditions (green circles on the purple waveform) and stop conditions (red circles on the purple waveform) are clean and it looks like SDA is only ever changing when SCL is low (per I2C spec).



I2C isn't done yet, but it is getting closer. My greatest point of unhappiness right now is the effective clock rate - it's about 56KHz. Checking the keyboard consumes roughly 700 microseconds. The challenge to increasing the speed here comes down to the ATTINY. The trace above shows two I2C transactions: a write of 0x07 (telling ATTINY that we wish to access register 7, the scan code buffer register) and a single byte read that returns the data in that register. The ATTINY's Universal Serial Interface can receive a single byte at up to 24MHz! BUT it has to process the request in the gap between the "Setup Read" byte and the "0x00 + NAK" byte in the above trace. That's only about 20 microseconds. I switched the ATTINY to use the internal PLL clock which increased it from 8MHz to 16MHz, which helped a lot, but it sometimes misses the window of opportunity leading to bytes that don't start clocking out until the second or third I2C clock.



Things are progressing ever more in the forward direction...



I still wonder about whether SPI access could be used ... even bit banged, it seems like it would be a higher bandwidth way of accessing an ATTiny ... and if the four VIA pins for the PS2 are no longer being used, then that is the minimum number of pins needed to bit bang an SPI interface.

Wavicle
Posts: 284
Joined: Sun Feb 21, 2021 2:40 am

PS/2 Keyboard Working with ATTINY and I2C

Post by Wavicle »



On 7/14/2022 at 3:58 PM, BruceMcF said:




I still wonder about whether SPI access could be used ... even bit banged, it seems like it would be a higher bandwidth way of accessing an ATTiny ... and if the four VIA pins for the PS2 are no longer being used, then that is the minimum number of pins needed to bit bang an SPI interface.



If we used SPI to talk with the SMC, we would still need I2C to talk with the RTC. I haven't done a deep dive to see why the clock rate is so much slower than I was expecting after I removed all of the superfluous delays. The code is pretty tight, but the clock high pulse is pretty consistently 4.3us. At 8 MHz that works out to 25-26 cycles? That may only be 10 instructions, so it could be the best we can do.

image.thumb.png.1d65fddb4e09f1f3e8486be36a3fa0ea.png

One possibility that just occurred to me was that I was running a few other experiments last night and had moved the clock jumper over to 2MHz. I may not have moved it back. I'll cross my fingers and hope that was it. (I wouldn't expect to land at 4.3us on a 2MHz clock though.)

BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

PS/2 Keyboard Working with ATTINY and I2C

Post by BruceMcF »



On 7/14/2022 at 8:15 PM, Wavicle said:




If we used SPI to talk with the SMC, we would still need I2C to talk with the RTC. I haven't done a deep dive to see why the clock rate is so much slower than I was expecting after I removed all of the superfluous delays. The code is pretty tight, but the clock high pulse is pretty consistently 4.3us. At 8 MHz that works out to 25-26 cycles? That may only be 10 instructions, so it could be the best we can do. ...



Yes, the assumption there is that the preceding VIA assignment of some pins to I2C and some pins to PS/2 would be shifted to some pins to I2C and some pins to SPI. I believe that a half-hardware SPI link, using a VIA serial shift register for the MISO channel so that only the MOSI byte has to be bit banged, would be appreciably faster than an effective SCLK of 75-80 kHz. Indeed, if it is a single device on the SPI port, with an appropriate command byte system it can be organized as a three wire, MISO / MOSI / SCLK system, using the two serial shift register pins and two VIA GPIO pins (with the VIA Serial Shift Register as MISO, the hardware clock pin is an input receiving clock pulses, which originate in the bit banked SCLK on a GPIO pin -- most conveniently on PortA_0 or PartB_0 so that INC or DEC (depending on SPI mode) can be used for the clock transition where the MISO / MOSI bits are latched.

But it also occurs to me that if the single device is an ATTiny, and it is EITHER being written to OR being read from, it can be a bespoke protocol, which could be designed to make use of a single VIA serial shift register for the higher throughput of synchronous hardware serial transmission in both directions. I do not know what the hardware UART / USART capabilities of the ATTiny are, but the VIA hardware serial shift register can easily be used as for a half-duplex byte by byte synchronous serial link {Say, 1MHz SCLK rate +}. Two GPIO pins might serve as handshake ... such as, a master out, device in line, MODE, pulled low for device command mode, up for device response mode, and a master in, device out /ACK line, acknowledging ready to receive after MODE pulled low (going high after command byte received), informing ready to send after MODE pulled high (going high after message has been polled).

 

______________

{+. At 2MHz system clock, the fastest VIA hardware clock is 1MHz, and by setting the countdown appropriately, 1MHz used for 2MHz, 4MHz or 8MHz system clock, for greater ease of programming the ATTiny. If that is not an appropriate synchronous serial clock speed for the ATTiny USART, scale it down appropriately.}

Wavicle
Posts: 284
Joined: Sun Feb 21, 2021 2:40 am

PS/2 Keyboard Working with ATTINY and I2C

Post by Wavicle »


Another brief update - the reliability of the I2C protocol, and by extension the keyboard, continues to be at least five 9s (i.e. 99.999% or no more than 1 error in 100,000 transactions). I'm not patient enough to leave the test running long enough to find out if it is six or seven 9s. Thanks to @Stefan's continued commitment to inlining everything that reasonably can be inlined, single byte register reads over I2C are down to ~285 microseconds which compares favorably to PS/2's ~900 microseconds for single byte.

image.thumb.png.46560042dee8a2f439bae5fed6a43068.png

The one remaining optimization is multi-byte PS/2 scan codes which currently must be fetched one byte at a time over I2C (285us per byte). Stefan wrote the kernel code that should handle this, it is just waiting for the SMC code to support it.

At this point I feel pretty confident that this keyboard solution is good enough for a beta release. I am shifting my focus to PS/2 mouse support. If anyone has experience coding PS/2 wire protocol for microcontrollers talking to a mouse, feel free to join us over on Discord. All you need is an Arduino, a PS/2 Mouse, and a way to connect the two (e.g. a breakout board, or a pair of scissors, wire strippers, and a disregard for the future utility of that mouse).

Post Reply