Is there any recent project to connect a PC (PS/2) keyboard to the CPC?

Started by Joss, 20:42, 27 August 12

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Joss

Quote from: MacDeath on 00:25, 31 August 12
Then comes the main problem...
Locomotive Basic is done for specific keyboards... and doesn't manage all those Extra keys... could it ?
.....
What is the theoric limitation in the number of keys a CPC can handle ? does the official CPC keyboard use the maximum or not ?



It is like the solution of Gerald. USB/PS2 keyboard is attached to a MCU who act as a host for the keyboard. The microcontroller will have on the other side the pins which are attached to the connector of the original keyboard. You dont have to patch the ROM. Extra keys are not used ... I see it so ..... ;D 

joska

I agree, implementing the CPC keyboard matrix on a microcontroller is relatively easy and 100% compatible with all software.


Btw with a little creativity the extra keys can be used. There's enough pins on the Teensy 2++ to connect to the joystick port too, so the joystick with two buttons can be emulated by the keyboard. It's also possible to connect a PS/2 mouse in addition to the keyboard and emulate the AMX mouse.


It's also possible to assign keystroke sequences to the unused keys, so pressing e.g. F5 would "press" the keys R, U, N, Enter in sequence. I do this in my Atari->USB adapter, which emulates Ctrl+Z when the UNDO-button is pressed.

Bryce

I like the macro idea Joska :)

@MacDeath: Due to the fact that the CPU reads a single byte to read the keyboard input, the theoretical limit would be 256 keys, but the CPCs matrix only scans 10x10, so the CPC keyboard connectors can only handle 100 keys at most (including the joystick inputs).

Bryce.

gerald

Quote from: Joss on 00:46, 31 August 12
If it works I will try to take it to the expansion port.
A solution with expansion and joystick port only is possible:
   - you need to use IORQn and WRN connected on G2A/G2B of 74HCT138 instead of IOWRn to G2A only.
   - add a DFF (74xx574) that will capture low part of C register from data bus. This DFF will be clocked by the same signals that trigger the uC. That is the same as for a CPC+.

Quote from: Joss on 00:53, 31 August 12
It is like the solution of Gerald. USB/PS2 keyboard is attached to a MCU who act as a host for the keyboard. The microcontroller will have on the other side the pins which are attached to the connector of the original keyboard. You dont have to patch the ROM. Extra keys are not used ... I see it so ..... ;D 
Yes, most of the uC SW is doing the re-mapping of PC keyboard to CPC matrix. Unmatched key does nothing.

CPC FW is scanning 10 of the 16 possible lines. We may use the 6 free one to either add some more key or implement a comunication protocol with the uC for Keymap update or other function.
Obviously, all added feature will need SW support on CPC (ROM?)

arnoldemu

Quote from: joska on 21:03, 30 August 12

The code I presented was for the opposite application - connecting a CPC keyboard to a PC/Mac via USB.


Connecting a USB keyboard to a CPC would be more difficult, but not impossible. And many USB keyboards also supports the PS/2 protocol, in this case it would be relatively easy.
I was hoping it was the other way around, because I have at least 1 cpc with a bad keyboard :(
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

gerald

Most if not all wired USB keyboard works as PS2 keyboard as well (need a small widget to adapt the connectors).
This is not true for all USB wireless one, Logitech Unifying does not :(

Bryce

Same with USB Mice. Many of them will work on PS/2, but gaming mice with loads of extra buttons / features or Bluetooth Dongle mice won't work.

Bryce.

joska

Quote from: arnoldemu on 11:06, 31 August 12
I was hoping it was the other way around, because I have at least 1 cpc with a bad keyboard :(


Both my CPC's has working keyboards, so I don't need this myself. But it's perfectly possible. You read the PS/2 keyboard, and convert the scancodes to matrix state by looking up a table. The matrix rows are monitored, whenever a row is pulled down by the CPC you update the column states accordingly.


Using a PS/2 keyboard with a Teensy/Arduino is very simple: Arduino playground - PS2Keyboard. The PS/2 keyboard is handled by an interrupt routine, so you can simply poll the rows continously.


Here's an outline of how this can be done with a Teensy/Arduino. As you see it's not very complicated, as the Teensy/Arduino takes care of all the PS/2 stuff and all the low-level stuff.




/*


   Completely untested, unfinished code to attach a PS/2 keyboard
   to a CPC keyboard connector.


   Lots of assumptions are made here The following must be investigated
   and the code adapted:


   - All pin assignments are bogus! Refer to a real Teensy/Arduino here.
   - From memory: The CPC keyboard connector has 9 rows and 10 columns. Must
     be confirmed.
   - Assumption: The CPC writes to the rows and read the columns. Could be the
     other way around, must be checked.
   - Assumption: The CPC matrix lines are pulled up by default.
   - The update_matrix()-function is empty. This is the function that converts
     the PS/2 scancodes to matrix state. I don't have time to look up all the
     scancodes and the CPC matrix, I'm supposed to be working


*/


#include <PS2Keyboard.h>


#define KBDATA 1   // Bogus value, adapt this to your selected Arduino/Teensy
#define KBCLOCK 2  // Same here. Remember to use an interrupt pin, see library docs.


PS2Keyboard keyboard;


#define ROWS 9     // Number of rows in the CPC keyboard matrix.
#define COLUMNS 10 // Number of columns.


// Store matrix state in this array.
byte matrix[ROWS][COLUMNS]; // Should initialize this to sensible values!


// Use correct pins here!!
byte rowpins[] = {1,2,3,4,5,6,7,8,9};
byte colpins[] = {1,2,3,4,5,6,7,8,9,10};


void setup(void)
{
  // Initialize the PS/2 keyboard
  keyboard.begin(KBDATA, KBCLOCK);


  // Set up the datapins for the matrix connections.
  for (byte i = 0; i < ROWS; pinMode(rowpins[i++], INPUT));
  for (byte i = 0; i < COLUMNS; pinMode(colpins[i++], OUTPUT));
}


void loop(void)
{
  monitor_matrix();


  if (keyboard.available())
    update_matrix();
}


void monitor_matrix(void)
{
  for (byte i = 0; i < ROWS; i++)
    if (digitalRead(rowpins[i]) == LOW) // Row pulled low?
      for (byte j = 0; j < COLUMNS; j++) // Yup. The CPC is scanning this row, lets update the columns.
        digitalWrite(colpins[j], matrix[i][j]);
}


void update_matrix(void)
{
  // In this function you convert the PS/2 scancodes to
  // matrix state. The matrix state is stored in the matrix[][] array,
  // each cell is either HIGH or LOW to indicate whether the key is
  // pressed or not.
}



For those not familiar with the Arduino way of complicating C: Arduino "sketches" doesn't have a main(), this is added by the Arduino framework during the build. main() just calls setup() first and then loops around loop().


Edit: I just noticed that you only got something like 6us from the row is pulled down to the columns are read. Using digitalWrite() and a loop will be too slow I think. It's better to encode the row in two bytes in update_matrix() and just write these directly to the output ports.


Bryce

Quote from: IanS on 23:52, 30 August 12
Internal/external, it's all the same, on the 464 the floppy interface was external, it's the same circuit on a 6128, but it's inside the case. The 8255, Gate array, Printer port, CRT conroller all use the IORQ signal.

I just took a proper look at the schematics and Z80 Datasheet. Seems I was confusing it with a different 8-bit architecture, which I also develop hardware for, but I won't mention it here  :-X Calling the keyboard externally wouldn't have any negative effects on the speed of other devices. That's assuming that the modded firmware code reads and reacts to the keyboard at the same speed.

I'd still prefer a solution that wouldn't involve modding the firmware though. I prefer things to be completely Plug & Play.

Bryce.

ralferoo

Quote from: joska on 17:53, 30 August 12
- Use the Teensy's internal pullup-resistors on all the matrix lines. This prevents the inputs from floating, which could cause false readings.
Further, I'd set PORTx to 0 for the output lines and use DIRx to change between pullup and driven low as this guards you against a short when the corners of the matrix are pressed.

I would definitely second the recommendation to use a teensy or similar. I've used the ATMEGA32U4 in a number of designs and it's a great chip and being flashable over USB is great...  There are enough IO pins to easily drive the matrix directly without relying on external chips too.

joska

Quote from: ralferoo on 14:10, 31 August 12
Further, I'd set PORTx to 0 for the output lines and use DIRx to change between pullup and driven low as this guards you against a short when the corners of the matrix are pressed.


Good point, I didn't think of that.

Joss

Quote from: gerald on 10:52, 31 August 12
A solution with expansion and joystick port only is possible:
   - you need to use IORQn and WRN connected on G2A/G2B of 74HCT138 instead of IOWRn to G2A only.
   - add a DFF (74xx574) that will capture low part of C register from data bus. This DFF will be clocked by the same signals that trigger the uC. That is the same as for a CPC+.


perhaps to connect the output from uC to joystick need extra stuff (buffer and so) to protect the PSG port, just in case it is not protected.


If the uC works with a higher frequency as the CPC (today it can be done easily, I think) I don't think there should be problems with the timing.


gerald

Quote from: Joss on 18:55, 31 August 12
perhaps to connect the output from uC to joystick need extra stuff (buffer and so) to protect the PSG port, just in case it is not protected.

The joystick side quite save. The uC is driving the row bits in an open collector way. It only drive the line low, as will the keyboard membrane or a joystick swich do. When the key is release, the uC stop driving the row bits low, and the pullups within the PSG drive them high.

Joss

Quote from: gerald on 19:05, 31 August 12
The joystick side quite save. The uC is driving the row bits in an open collector way. It only drive the line low, as will the keyboard membrane or a joystick swich do. When the key is release, the uC stop driving the row bits low, and the pullups within the PSG drive them high.


Good to know  :)  thanks!!

gerald

Hi chaps,

It's weekend time so if you have a bit of spare time, you may try to do your own PS2 keyboard adaptor  ;)
Here are the source and schematics of my own interface. Feel free to play with it.

There is no real documentation, but schematic should be self explanatory, as well as the code.
Code is compiled with avrgcc (WinAVR-20100110) using the provided makefile.
Schematic and sample board using DIL component and trough hole resitor/caps is provided in EAGLE 6.2.0 format

Random notes :
  uC : Schematic is using a Tiny4313, but code will fit in a Tiny2313a (Tiny2313 should work as well, but I do not have any to check)
  Pullup resistor on keyboard signal should not be needed (I do not have any on my boards). These are in the keyboard itself.
  SV1 and R1 are not needed by current SW. These allow a single bit configuration using the embeded analog comparator.

MacDeath

QuoteMacDeath: Due to the fact that the CPU reads a single byte to read the keyboard input, the theoretical limit would be 256 keys, but the CPCs matrix only scans 10x10, so the CPC keyboard connectors can only handle 100 keys at most (including the joystick inputs).
I guess it would need to rewire some stuff on the motherboard/chips then ?
And also modify the firmware/Locobasic/OS....


As told, the extra keys could be rewired into Joystick or "Mouse" or even other stuffs... perhaps even a few comands for an Hxc Floppy emulator or Kustom MP3 reader (=tapes)...

Joss

Nice Gerald!
Now the question. Are you using the connections direct to the PPI pins at SV4? Is it possible to use the keyboard pins?
Thanks!!!


Joss

Quote from: MacDeath on 20:22, 31 August 12
As told, the extra keys could be rewired into Joystick or "Mouse" or even other stuffs... perhaps even a few comands for an Hxc Floppy emulator or Kustom MP3 reader (=tapes)...


MacDeath ... imagination is your limit  ;D  it can be adapted to your needs and the original keyboard can be save for the future ......

gerald

Quote from: Joss on 20:29, 31 August 12
Now the question. Are you using the connections direct to the PPI pins at SV4? Is it possible to use the keyboard pins?
These are easier to get on PPI, but are also on the main board (address/IOWRS runs everywere  ;) ).
Line 4 bits however are only on PPI and the 74LS145 that then drive the keyboard matrix.

For a solderless solution you need to add the DFF as discussed in previous posts and use the exp port. I did not have time to do a schematic for this.

KaosOverride

Hello!

My alternative is to go straight for USB keyboards.

I recently tried the USB ATMEGA, more specifically with a pair of  Micropendous-A boards. Thanks to the LUFA libraries I have read in raw USB keyboards.

I hope to have some positive results in the future, but I'm too busy trying to wire a W5100 for hardware TCP / IP on the CPC (See Spectranet and Denyonet on the Spectrum and MSX...) :D
KaosOverride · GitHub
MEGA Amstrad Public Amstrad folder

christosi

Hi my friend

Very good construction. We will try to fix it myself. It's easy you tell me the frequency  Function and fuses for Tiny2313a.

Sorry for my English.

THANKS.

gerald

Fuses setting are the factory defaults : internal 8Mz oscillator + 1/8 ratio.
At start, the code switch itself to 8Mhz.

christosi


n_sonic

2 gerald
Hi pal! I have build your PS2CPC controller but can`t make it work. Some questions please:
1. Fuse bits - default (CKDIV8, SUT0, CKSEL0, CKSEL2, CKSEL3 enabled), but how about CKOUT? It must be enabled too cause of receiving frequency to keyboard CLK input, i think so... May be I`m wrong? Please place your fuses configuration in the thread.
2. I use Tinny2313 without index A. May be this is the reason of malfunction?
3. Can you place here compiled hex?
4. Schematic and your board on photo have some difference. On schematic signal A11 goes to pin3 of HC138 but in photo it`s connected to pin36 of 8255 (IOWR). What connection is correct?
Sorry for disturbing and hope for quick answer! Best regards! Alexey.

gerald

Hi Alexey,

One of my collegue used to say "everithing not tested does not work", and I did not test the standalone version of the PCB >:(
There is a naming error on the connection of A8/A9 to the HC138 and these have to be swapped. In fact, the net label in eagle are correct but are wrongly positioned.

So you have to connect SV4 pin 9 to A8 and SV4 pin 8 to A9.

Regarding the Tiny2313, you can check that the code is running by using the numlock key to toggle the numlock LED. The code will switch the led on after the keyboard reset and then toggle it when you press the numlock key.


Quote from: n_sonic on 13:34, 27 November 12
1. Fuse bits - default (CKDIV8, SUT0, CKSEL0, CKSEL2, CKSEL3 enabled), but how about CKOUT? It must be enabled too cause of receiving frequency to keyboard CLK input, i think so... May be I`m wrong? Please place your fuses configuration in the thread.
The Keyboard clock is generated by SW. Enabling CKOUT fuse will prevent proper keyboad clock control and PS2 protocol.

Quote from: n_sonic on 13:34, 27 November 12
2. I use Tinny2313 without index A. May be this is the reason of malfunction?
3. Can you place here compiled hex?
Tiny2313 should be OK. Hex file is attached

Quote from: n_sonic on 13:34, 27 November 12
4. Schematic and your board on photo have some difference. On schematic signal A11 goes to pin3 of HC138 but in photo it`s connected to pin36 of 8255 (IOWR). What connection is correct?
The prototype is slightly different than the final version and A11 was connected to pin 3 of HC138. I later swapped A11 and IOWR so A11 does not have to slalom between other pins.



Powered by SMFPacks Menu Editor Mod