Jump to content

PS/2 Direction for the Commander X16


Recommended Posts

Hello everyone, 

  I wanted to discuss an issue we have been struggling with, and that is PS/2 keyboard and mouse support.  This is probably not a secret to anyone watching the videos on the X16 as most of the time we are running at 4MHz or 2MHz.  This is completely due to PS/2 timing issues.  I've spoken with Michael Steil about this issue many times and he has taken several approaches to get it to working stably.  After adding the microcontroller to control the ATX power supply, I proposed the idea of adding a few more pins to also control the PS/2 ports.  Like many in the community, he would perfer to get it working as it stands, so I proposed adding jumpers to select between the microcontroller, or the 65c22.   So, I did just that on the third prototype.  With tiny revisions, this will become our development board so it will give folks the option to try either approach. 

  I initially thought about writing the code for the Arduino myself.  I've messed around with Atmel microcontrollers going on 20 years now, but the truth is, I'm probably not the best one for this task.  The code I wrote for the ATX power control is working, but I can't seem to get my reboot function to work for some reason.... Anyway, I digress, I guess the real reason I'm making this post is to ask for some help from the community!

  We are not committed to one approach or the other necessarily.  IE, we are still planning to work on the 65c22 'bit-bang' approach (heck, we maybe could use some help here too), but alternately I wanted to start working on the microcontroller code to at least evaluate it before the final version of the board.  

  If you're interested, here are some details wrt to how I have the HW setup on the current prototype.  The attached pic shows U18, which is the ATTINY861 microcontroller.  I really wanted to stick with no more than a 20 pin IC if possible, to make it look like it matches the board.  This chip can run at 8 or 16MHz without an external crystal, but I gather the 16MHz mode may not be as stable.  Not sure if this will be an issue later, but I wanted to mention it.  I sort of just guessed the chip would be fast enough to handle both the mouse and the keyboard.  There are certainly plenty of keyboard libraries out there, and at least one mouse library I'm aware of, but I'm not sure if they have ever been combined.  I am running the microcontroller as an I2C device with the 6522 acting as the host to this IC.  Right now, it is only listening for commands to power-off the system, reboot, reset, NMI & HDD LED control.  I also hooked a line up to the 65C02 IRQ, so it could be polled.   (Just as an FYI, the real-time clock is U10, which is read via I2C.  J16 is the external I2C header to drive other devices if desired.  J16 will also work as a 6-pin ISP header to program the ATTINY861.  J6-J9 toggles the clock/data line for each PS/2 port from 65c22 to the ATTINY861.)

 In a nutshell, I'd like it to maintain the existing functions which should be taking next to nothing in terms of CPU, except maybe the I2C library.  Integrate IRQ driven PS/2 mouse and keyboard routines and make the code as clean as possible for easy editing.  If we do wind up going this route, your work could be part of the open-source library at the end of the rainbow for the system.  Clearly, there will need to be some interaction on the kernal-side to process the data from these interrupts.  This will take some coordination too, but I suspect the Arduino-side could be tested with another Arduino reading the data for the time being.  Keep in mind, we could also wind up not using it too, just fair warning.

  Keep the responses on this thread for the time-being.  I know this is a big ask, but I really want to make sure we have a nice solid library, so I decided it would be better to get a rock-star developer out there.  Assembly is fine too, if you want to do it the hard way 🙂but I suspect C will be fine.  I also attached the code which is running on the proto for now.

Please let me know if you have any questions, I'm looking forward to testing this out!

Thanks!
-Kevin

micro.png

X16_Power-current.zip

  • Like 10
  • Thanks 1
Link to comment
Share on other sites

Hrrrng... if I didn't have a day-job that I loved dearly, I would be all over both this and offering to help out with the kernal. I mean, I'm continuing to work on the emulator; albeit in my own fork that I haven't formally announced here, but has been named dropped here by others. Suddenly, so many things I want to add to my precious hobby time. And I've previously worked with 2-way communications in microcontrollers for various sensors, so adding a PS/2 communication routine here sounds like fun to me. I hope someone pops up who can help out with this.

Edited by StephenHorn
  • Like 2
Link to comment
Share on other sites

2 hours ago, ZeroByte said:

Someone get Ben Eater on the phone!

He's been messing with PS/2 and USB in his last 3 or 4 videos.  Pretty sure he will be able to solve this in 30 minutes or recommend a different, yet elegant approach.

I wasn't joking when I suggested somebody get the guy that did the "C=key" on the line.  It maps PS/2 to traditional Commodore style row/column scanning; in a worst case scenario, just get it over with using something that works even if it costs an additional $1.29 per unit.

 

  • Like 2
Link to comment
Share on other sites

I have until the next wednesday on vacation from my full time job here in Brazil to help you.

Although I have not worked with that mcu (nor have it in hands) in particular, I am use to work with ATtiny+ATmega series as a hobbyist (not as a professional). The mcu datasheet seems pretty familiar comparing to other models I have used.

I can develop in C with Arduino, when it finish I can also try to make it work without the Arduino Bootloader to save more memory. I can do in assembly too, but there is no need to do that way.

I do not have experience working with keyboard+mouse interfaces (w/ PS2) with microcontrolers, there is a good library in github for that. Even so, I will have to study deeper to work with that.

Until my vacation's end, I can help to work in this task. But I have no experience (as a professional) in doing that job!!!

 

 

  • Like 6
Link to comment
Share on other sites

I would gladly help too but I don't think I'm a wizard-level developper with Arduinos (hobby programmer on Arduino and ESP32). Anyway, if any help is needed, i'll try as hard as I can. I'm also on vacation for the next 2,5 week.

__________

By the way, I found a library for PS/2 mouse handling to add with the keyboard library. Not sure if that could help but putting it anyway.

Edited by VincentF
  • Like 1
Link to comment
Share on other sites

I looked around a bit for trustworthy information on PS/2 timing.

I found this 1991 IBM manual titled "Keyboard and Auxiliary Device Controller" page 16 (page 230 in the file).

https://archive.org/details/bitsavers_ibmpcps284erfaceTechnicalReferenceCommonInterfaces_39004874/page/n229/mode/2up?q=keyboard

Possible timing problems:

  • The time it takes after PS/2 lines are released by the host before the keyboard starts sending data. The current X16 Kernal waits about 108 us @ 8 MHz according to my manual clock counting. I have found no documentation stating when the keyboard must start sending data, only that it cannot begin before 50 us after the PS/2 lines were released. It would be interesting to see what happens if the time the Kernal is waiting for the keyboard to start sending data is made longer.
  • The current Kernal samples the data line immediately after the clock goes low. This should be fine according to the specification, if the keyboard in question follows the specification. It would, however, be interesting to see what happens if the data data line is sampled in the middle of the clock low period, for example about 15-20 us after the clock transition.

ps2 timing.png

  • Like 3
Link to comment
Share on other sites

I can do the embedded implementation, and I have an oscilloscope and logic analyzer on my bench to verify timing correctness. I haven't worked with an ATTINY861 before and I only have ATTINY85s in my bins here so I'd have to order an 861 from Mouser and hope that the 861 has a pretty similar toolchain to the 85. I'm not sure what the 861 needs for programming, but I assume if nothing else, my TL866II can do so. It would help, but isn't completely necessary, to have the X16 schematic page (or portion of a page) that details the 861 connection so that I can replicate a similar circuit on my benchtop.

I'm competent with most assembly languages, however I'm probably all thumbs when it comes to 65xx assembly specifically. I can read it well enough, but have limited hobbyist experience writing it and zero professional experience with it. I'd be most useful for the embedded/861 implementation.

I'm in the Seattle area (I work at the tech giant in Redmond) so it would have to be all remote work. Send me a DM if interested and I'll order the 861 parts from Mouser and we can take this to email/zoom.

  • Like 4
Link to comment
Share on other sites

The ATTINY861 is just like any other IC in the series.  I switched from the ATTINY84 mostly because it had the leg count I want. 🙂  I'm using the ATTINY (arduino) core with the small bootloader.  I have a really old original STK500 I'm using to program it, although any old Atmel ISP programmer will work fine.  This IC is focused on automotive applications, as I recall,  but I'm just using it as a general purpose controller with I2C being the only weirdness.  It also has a way to generate a 16MHz clock internally, but it may be less stable.  I figure 8MHz may well be enough, but I thought it was nice to have as an option.  A programmer like this will work fine: USB AVR Programmer w/ 6-Pin 10-Pin IDC ISP Connector For USBASP | eBay

I also saw these: ATtiny 861 or 167 Development Board (assembled) from Azduino by Spence Konde on Tindie 

I can't vouch for them, I would just buy the dip IC and use it on a breadboard myself, but it could make it easy if you want a quickie and pretty cheap dev board for it.  

So there really should be two forks here. 

The first is for the 65c22 approach, which honestly, the only real input I can offer is testing on the real HW at this point.  The code is here: commanderx16/x16-rom (github.com)  I believe it's more up to date than the current emulator build, including some code I've tested which did sort of work at 8MHz.  This means the emulator needs to be updated at some point to match the new code-base as well.  Michael Steil is really the guy to ask here, I'll see what I can do to loop him in.   Honestly, don't know if the mouse code even exists yet in the kernal.

As far as the microcontroller goes, we should be able to test this for now with a second arduino running as an I2C master, and reading the fake IRQ.  Not as ideal, but getting the kernal to process this data is also a whole other matter.  I'd like to be able to validate the idea externally first.  

I know David is reading through the thread right now.  I'm going to chat with him a little later today and get back to you guys,

Thanks so much for the offer of assistance!  It is greatly appreciated.

-Kevin

  • Like 4
Link to comment
Share on other sites

@Kevin Williams

I made a quick test introducing a wait of about 15 us after clock low transition before the data line is sampled. At least that was my intention, but I have no means of testing it. It still works in the emulator.

Enclosed is the changed source file (kernal/drivers/x16/ps2.s and the compiled rom image.

The changes in the source file is on line 69 and on lines 105 and forward.

ps2.s rom.bin

  • Like 3
Link to comment
Share on other sites

I also looked briefly at the code that handles SD card communication (dos/fat32/sdcard.s).

It's a bit banged SPI solution that depends on proper timing.

The necessary timing delays are measured in processor cycles, calculated on the assumption that the X16 runs at 8 MHz.

It would be surprising if the code worked properly if you run the computer at 4 or 2 MHz.

Before any other troubleshooting, it would be interesting to know how well the SD card communication works at 8 MHz. To test this you may first need the keyboard to work at that speed 🙂

  • Like 1
Link to comment
Share on other sites

I also looked briefly at the code that handles SD card communication (dos/fat32/sdcard.s).
It's a bit banged SPI solution that depends on proper timing.
The necessary timing delays are measured in processor cycles, calculated on the assumption that the X16 runs at 8 MHz.
It would be surprising if the code worked properly if you run the computer at 4 or 2 MHz.
Before any other troubleshooting, it would be interesting to know how well the SD card communication works at 8 MHz. To test this you may first need the keyboard to work at that speed [emoji846]

SPI has no strict timing requirements. It should work regardless of system speed.


Sent from my iPhone using Tapatalk
  • Like 1
Link to comment
Share on other sites

2 hours ago, Stefan said:

I also looked briefly at the code that handles SD card communication (dos/fat32/sdcard.s).

It's a bit banged SPI solution that depends on proper timing.

The necessary timing delays are measured in processor cycles, calculated on the assumption that the X16 runs at 8 MHz.

It would be surprising if the code worked properly if you run the computer at 4 or 2 MHz.

Before any other troubleshooting, it would be interesting to know how well the SD card communication works at 8 MHz. To test this you may first need the keyboard to work at that speed 🙂

I don't think that's quite right, unless I am looking at the wrong branch:

spi_write:
    sta SPI_DATA
@1:    bit SPI_CTRL
    bmi @1
    rts

That writes a byte to the SPI data register and then waits for the busy bit to clear. That looks like a complete hardware implementation. It would be nice to get a better description of what the SD failure mode is. Nicer still to hookup my protocol analyzer to the SD slot and probe traffic to see if the problem is the wire protocol or the hardware state machine.

Regardless, since the X16 is acting as SPI master, it has control of SCK. As long as it isn't driven faster than 25MHz (the guaranteed minimum speed supported in the SD spec), that should be fine. I've written SPI bit bang drivers for bootstrap code with an effective clock speed around 0.1 MHz and did not see an issue on any card tested. The one problem I did see was un-branded cards that did not correctly implement SPI in their hardware, but this was roughly 10 years ago - I'd like to think all SD card manufacturers have figured that out by now.

Are you mixing SD and PS2? The keyboard is a PS2 interface.

Link to comment
Share on other sites

2 hours ago, Wavicle said:

I don't think that's quite right, unless I am looking at the wrong branch:

 


spi_write:
    sta SPI_DATA
@1:    bit SPI_CTRL
    bmi @1
    rts

 

Even though there is no timing dependent code in those lines, there is in other places within the module, for instance:

  • wait_ready, begins at line 40 
  • sdcard_init, begins at line 236

I haven't gone into the details of the SD card protocol. I haven't analyzed if the changed timing when the clock rate is reduced would be OK. I only said that the Kernal code clearly is written on the assumption that the computer runs at 8 MHz, and that it would be interesting to know if the problem is still there when the computer is run at that speed.

EDIT: Let me be clear about that I have no practical experience interfacing SD cards. Reading about the protocol in datasheets, I understand that there is no minimum clock frequency during normal communication. But during card initialization, you may not go below 100 kHz. When X16 is run at 2 MHz, 100 kHz corresponds to 20 processor cycles. It so happens that the spi_read function that is called several times during card initialization is a little more than 20 cycles. As I said, it would be interesting to know how well SD card communication works at 8 MHz...

Edited by Stefan
Link to comment
Share on other sites

2 hours ago, Stefan said:

Even though there is no timing dependent code in those lines, there is in other places within the module, for instance:

  • wait_ready, begins at line 40 
  • sdcard_init, begins at line 236

I haven't gone into the details of the SD card protocol. I haven't analyzed if the changed timing when the clock rate is reduced would be OK. I only said that the Kernal code clearly is written on the assumption that the computer runs at 8 MHz, and that it would be interesting to know if the problem is still there when the computer is run at that speed.

EDIT: Let me be clear about that I have no practical experience interfacing SD cards. Reading about the protocol in datasheets, I understand that there is no minimum clock frequency during normal communication. But during card initialization, you may not go below 100 kHz. When X16 is run at 2 MHz, 100 kHz corresponds to 20 processor cycles. It so happens that the spi_read function that is called several times during card initialization is a little more than 20 cycles. As I said, it would be interesting to know how well SD card communication works at 8 MHz...

This would probably be best taken to a new thread to avoid cluttering this one with non-PS/2 related discussion. VERA drives SCLK so the CPU frequency should have no impact. The 100-400khz SPI clock requirement is only during transfers; the clock may stop between transfers. (See section 4.4 Clock Control of the SD Physical Layer Simplified Spec)

  • Like 2
Link to comment
Share on other sites

I started prototyping an implementation using an ATTINY85 that I have. After I had a circuit assembled, test programs written, and everything tested (Arduino UNO as I2C master, ATTINY85 as I2C slave and PS/2 host) I started looking to integrate it into the sketch attached here and noticed that the only thing done is initialization of the Wire library. (By funny coincidence, we selected the same I2C address - we may have read the same books in the 80s or something.) It doesn't look like there is any I2C receive/request handlers implemented. Is this correct? (Is this the current state of the sketch, or is this maybe an older version of the sketch?)

IMG_20210829_014550001.thumb.jpg.0a9df19ee33888f7ad479802db731cd6.jpg

  • Like 1
Link to comment
Share on other sites

Yes, this is really just a quick and dirty bit of code I setup to get the power button working and make sure I could send data to it from the system.  This works, (except for the reboot command for some odd reason).  I never really took it any further.  

Sorry I've been away for so long.  I didn't intend to, but I wound up getting pretty busy over the last few weeks and now I'm less than a week from going to VCF Midwest.  When I get back, I'll hopefully be caught up soon thereafter and can focus on this more.

Take care!
-Kevin

  • Like 2
Link to comment
Share on other sites

4 hours ago, Kevin Williams said:

This works, (except for the reboot command for some odd reason).  I never really took it any further.  

Hard to tell without a schematic and a description of the failure, but assuming this screen cap is still the board:

image.thumb.png.f78370304de953fc5f65b07be7f7539a.png

 

I'm guessing that R38 and R8 are current limiting resistors for the LEDs and R39 and R40 are pullups for I2C, so you have no external resistor on the daughterboard connected to RESET_BUTTON_PIN. The ATTINY does have internal pullups that can be used on input pins, but that functionality appears to require you to specify the pinMode as INPUT_PULLUP (see lines 95 and 101 here: https://github.com/SpenceKonde/ATTinyCore/blob/a2387a8d5551272e6860fb830099c2473a6da22a/avr/cores/tinymodern/wiring_digital.c):

	 //Button Setup
 pinMode(POWER_BUTTON_PIN, INPUT);
 pinMode(RESET_BUTTON_PIN, INPUT_PULLUP); // don't leave this floating
 pinMode(NMI_BUTTON_PIN, INPUT);
	

If this were the problem and I'm reading the code correctly, I think it would show up as a floating pin so the attiny could think the button was still down even after being released. Alternatively, you could have a pullup on the motherboard and this isn't the problem at all. That's my best guess after 10 minutes of investigation 🤔. If that is the issue, the other two buttons probably need the same change.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

Suggestion: use an ESP32 or possibly ESP8266.

They're cheap, much more powerful than Arduino, there's already a working and well used Mouse/Keyboard/SDCard library for the ESP32 which has been flogged to death (partly by me, it does colour video as well !). You also have a Wifi system thrown in for good measure for later use. Should be possible to bit bang an SPI or I2C connection to transfer data reasonably quickly (not sure about SD Card may be too slow). Many boards can be powered of 5v even if they run at 3v3 and I don't think I2C cares.

You could go the whole hog and connect it to the sound chip as well (the library does sound as well ....) and use it as an auxiliary device.

Even better, dump the A/D audio system on Vera which doesn't have enough memory and use the memory in the ESP32 to store audio waveforms, and keep Vera for graphics.

Authenticity rules ok .....

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use