On 10/21/2022 at 8:59 AM, neutrino said:
How will the ATTiny microcontroller attach to the computer? which MCU model is it?
NMI interferes with PS/2 communication
NMI interferes with PS/2 communication
NMI interferes with PS/2 communication
Alright..
So the plan is:
Keyboard: PS/2 --> MCU: ATTiny861 --> (I2C) --> I/O: VIA #1 --> CPU: 6502
https://www.microchip.com/en-us/product/ATTINY861
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2588-8-bit-AVR-Microcontrollers-tinyAVR-ATtiny261-ATtiny461-ATtiny861_Datasheet.pdf
td;lr Flashmemory 8 kB (4096 x 16), SRAM 512 byte (512 x 8), EEPROM 512 bytes, 8-bit, instruction set AVR, performance 20 DMIPS,
(Also a bonus A/D with 10-bits at 15 kSPS with 11-inputs)
@BruceMcF already spotted a performance opportunity:
https ://www.commanderx16.com/forum/index.php?/topic/3634-ps2-keyboard-working-with-attiny-and-i2c/&do=findComment&comment=21112
"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."
(more on this interface in the datatasheet page 125, "Universal Serial Interface")
The MCU can most likely provide a bonus RS-232 asynchronous port at ~24 kbit/s with plain bit-bang, provided the MCU<->6502 link is good enough. And additional MCUs can be added like on a bus (I2C/SPI).
As for USB keyboards there's plenty of USB HID --> PS/2 active adapters to solve that. And in the worst case there's MCUs with builtin USB.
Threads:
https ://www.commanderx16.com/forum/index.php?/topic/1684-ps2-direction-for-the-commander-x16/
https ://www.commanderx16.com/forum/index.php?/topic/3634-ps2-keyboard-working-with-attiny-and-i2c/
NMI interferes with PS/2 communication
An MCU as the ATtiny85 is capable of providing USB at 1.5 Mbit/s, should the need arise for USB support on a component budget.
https://www.instructables.com/ATtiny-V-USB-Project-Board/
https://www.taydaelectronics.com/attiny85-attiny85-20pu-8-bit-20mhz-microcontroller-ic.html
https://www.taydaelectronics.com/datasheets/A-307.pdf
ATtiny85-20PU
QuickSummary: Flashmemory 8 kB (4096 x16), SRAM 512 byte (512 x 8), 8-bit, instruction set AVR, clock 20 MHz 20 MIPS, GPIO x6
NMI interferes with PS/2 communication
https://github.com/commanderx16/x16-rom/blob/master/kernal/drivers/x16/ps2.s
ps2_receive_byte:
"lc04a: bit port_data,x"
So the PS/2 data bits are retrieved one by one. Which means any NMI etc which last longer than 30 µs is most likely to mess up the keyboard reading. And should the scancode be two bytes it will be synchronized at byte level too. If an MCU handles these time critical parts just like on a PC (intel 8042) then it should be possible to get around.
NMI interferes with PS/2 communication
On 10/21/2022 at 9:27 PM, neutrino said:
https://github.com/commanderx16/x16-rom/blob/master/kernal/drivers/x16/ps2.s
ps2_receive_byte:
"lc04a: bit port_data,x"
So the PS/2 data bits are retrieved one by one. Which means any NMI etc which last longer than 30 µs is most likely to mess up the keyboard reading. And should the scancode be two bytes it will be synchronized at byte level too. If an MCU handles these time critical parts just like on a PC (intel 8042) then it should be possible to get around.
PS/2 was moved to the SMC this past summer. A pull request to bring this into the kernel proper is in process: Move keyboard and mouse to I2C interface by jburks · Pull Request #338 · commanderx16/x16-rom (github.com)
- kliepatsch
- Posts: 247
- Joined: Thu Oct 08, 2020 9:54 pm
NMI interferes with PS/2 communication
It is possible to code around the "short NMI" limitation. I promised to describe my solution in that case, so here you go.
The idea consists of two major steps:
make the NMI routine check whether it interrupted the Kernel's ISR. This can be done by checking the processor status and return address lying on the stack when the NMI is issued.
If it didn't interrupt the ISR, do the whole NMI routine.
If it did interrupt the ISR, just set a flag and finish early.
Set up a "hook" at the end of the Kernal's ISR.
When the Kernal's ISR is done, control is passed to our "end hook code" so we can check if the flag has been set and do then what the NMI left out.
This can be done by installing a "normal" custom ISR for the normal interrupt, which inserts a custom return address into the stack before calling the Kernal's ISR.
It was a bit more involved than I anticipated, and I think it's a good thing that we (hopefully) won't have to worry about this stuff as soon as the emulator is updated. Until then, this is my solution ?
NMI interferes with PS/2 communication
The good news is that there is also a PR for an emulator update that moves keyboard and mouse to I2C fetches.
The other good news is that I do not think this NMI problem exists on the hardware. If an NMI hits when retrieving the keyboard status from the SMC, it will just cause that I2C clock to get stretched.
NMI interferes with PS/2 communication
On 10/22/2022 at 9:47 PM, kliepatsch said:
make the NMI routine check whether it interrupted the Kernel's ISR. This can be done by checking the processor status and return address lying on the stack when the NMI is issued.
Checking the return address is a very dumb way to see if the KERNAL ISR is being executed. The return address could be inside the main ISR, inside some often used KERNAL function that happens to be called at that particular moment, or inside your own interrupt routine that you've hooked through $0314. Besides, only the KERNAL vectors are guaranteed to be at the same address in any given ROM version.
A better (and cleaner) solution would be for the KERNAL itself to set a specific memory location to FF upon ISR entry and to set it back to 0 upon exit. That's about 10 cycles more for the ISR, and a simple test for your NMI routine.
- kliepatsch
- Posts: 247
- Joined: Thu Oct 08, 2020 9:54 pm
NMI interferes with PS/2 communication
On 10/22/2022 at 10:50 PM, Guybrush said:
Checking the return address is a very dumb way to see if the KERNAL ISR is being executed. The return address could be inside the main ISR, inside some often used KERNAL function that happens to be called at that particular moment, or inside your own interrupt routine that you've hooked through $0314. Besides, only the KERNAL vectors are guaranteed to be at the same address in any given ROM version.
A better (and cleaner) solution would be for the KERNAL itself to set a specific memory location to FF upon ISR entry and to set it back to 0 upon exit. That's about 10 cycles more for the ISR, and a simple test for your NMI routine.
It works well for me, but I like your solution, too. ?
If either the Interrupt flag hasn't been set or the program counter was outside the ROM, we can be sure that no PS/2 polling was happening before the NMI. False positives, on the other hand, is not so much of a concern (i.e. that we guessed one time too often that the Kernal's ISR was running). Either way, I think I am going to adopt your suggestion.
NMI interferes with PS/2 communication
On 10/23/2022 at 6:09 AM, kliepatsch said:
If either the Interrupt flag hasn't been set or the program counter was outside the ROM, we can be sure that no PS/2 polling was happening before the NMI. ...
The challenge here is if there are two ISR's using the same technique, then an NMI from both too close together might generate a false negative. By contrast, if done correctly, the wrapper around the Kernel ISR to set a flag byte can be repeated and will still work correctly.