avatar_Joss

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

Started by Joss, 18:42, 27 August 12

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

MacDeath

Weren't chips like the AY used to manage keyboards in addition to produce sounds  ?


I mean, those Soundchips were mostly produced to be put into keyboards synthetisers/electronic pianos...

Bryce

Well they offered generic i/o ports that could be used be used for anything. But if you were to build a keyboard scanner today, there are so many other more easily available ICs that will do the job just as well.

Bryce.

Joss

As I see there are two interesting projects:
- adapt CPC keyboard to be used as a PS/2 keyboard


and (for me useful)
- connect a PS/2 keyboard to the CPC. The second one perhaps can be done through another machine: raspberry, android-box .....  ;D  .... an old and cheap android phone with extra logic over the USB port? .....

joska

Quote from: Bryce on 11:31, 29 August 12
Connecting a real CPC keyboard to other devices is really easy. A simple µP (PIC/AVR) can easily scan the keys. The only slightly difficult part is the interface to the new device. If it's a USB connection, the device would need to emulate USB HID, but if it was something like an Arduino or Beagle bone, the device could simply produce an 8-bit value on the TTL inputs available. Then the entire hardware would be a PIC and a few resistors / capacitors. Could be made for under €10.


Or simply use a Teensy 2++. It's pretty cheap, easy to program and can emulate keyboard, mouse and joystick HIDs with ease. I've used these to convert Atari keyboards to USB and PS/2. Several people are using this in "Atari PC's" - Atari ST's with the guts replaced with small PC motherboards.


Connecting PS/2 keyboards to a CPC shouldn't be a problem either, as long as the user is prepared to do some soldering. You can save a few $$ if you shop around, but when a complete Teensy 2 is around $20 I don't see the point.

joska

Quote from: Joss on 19:55, 29 August 12
- connect a PS/2 keyboard to the CPC. The second one perhaps can be done through another machine: raspberry, android-box .....  ;D  .... an old and cheap android phone with extra logic over the USB port? .....


Or one of these:  PJRC Store


These can be programmed with the Arduino tools. Use the Arduino PS/2 library to read a PS/2 keyboard, and translate the PS/2 scancodes to matrix events. Should be quite easy for someone with basic programming and electronics skills.

Ynot.zer0

Teensy++ 2.0 ordered.  Next week I'll have to look into how to connect the CPC 6128 keyboard to it and read the keys pressed... will share the progress (if I make any!)

joska

A few tips:


- Use the Teensy's internal pullup-resistors on all the matrix lines. This prevents the inputs from floating, which could cause false readings.


- Scanning the keyboard is relatively simple - you loop around the rows, pulling down the rows one by one and read the state of each column for each row. Now, if you put the row number in the upper nibble and the column number in the low nibble, you'll have an 8 bit number that identifes the key. Use this number to look up the corresponding HID scancode in a translation table.


- Every time you scan the matrix, store the state of each key in a table. So when you scan the matrix, you can detect if the state of a key has changed. You'll need this as you'll only send scancodes when a key is pressed or released.


- The Teensyduino USB HID-library takes care of key repeat, no need to worry about that :)


This is the part of the code that handles the matrix in my Atari Stacy keyboard controller:

// Define the pins that connects to the matrix
int rowpins[] = { 10,11,12,13,14,15,16,17 };
int colpins[] = { 19,18,40,41,42,43,44,45,20,21,22,23,24,25,26 };

// Key state is stored in this array every time the matrix is scanned
uint8_t matrix[128];

// Translation table. You will need a 256 byte table with the CPC using this technique.
uint8_t scan[128] = {
  0,0,0,0x1d,0,0,0,0,                     
  0,0,0x2a,0x1d,0,0,0,0x3b,                   
  0,0x38,0,0,0,0,0,0x3c,                   
  0x36,0,0,0,0,0,0,0x3d,                   
  0x2c,0x60,0x1e,0x10,0x0f,0x02,0x01,0x3e,
  0x2d,0x20,0x1f,0x12,0x11,0x04,0x03,0x3f,
  0x2f,0x2e,0x21,0x14,0x13,0x06,0x05,0x40,
  0x31,0x30,0x23,0x22,0x15,0x08,0x07,0x41,
  0x32,0x25,0x24,0x17,0x16,0x0a,0x09,0x42,
  0x39,0x33,0x26,0x19,0x18,0x0c,0x0b,0x43,
  0x3a,0x34,0x27,0x1b,0x1a,0x29,0x0d,0x44,
  0x35,0x28,0x1c,0x2b,0x52,0x53,0x0e,0x62,
  0x70,0x6d,0x4d,0x50,0x4b,0x47,0x48,0x61,
  0x71,0x6e,0x6b,0x6a,0x68,0x67,0x54,0x63,
  0x72,0x6f,0x4e,0x6c,0x4a,0x69,0x66,0x65
};

// Set up the matrix pins.
void keyboard_init(void)
{
  for (int i=0; i < 8; i++)
  {
    // Rows as output, status HIGH.
    pinMode(rowpins[i], OUTPUT);
    digitalWrite(rowpins[i], HIGH);
  }

  // Columns as INPUT, pullup-resistors enabled.
  for (int i=0; i < 15; pinMode(colpins[i++], INPUT_PULLUP));
  for (int i=0; i < 128; matrix[i++] = 0);
}

// Scan the matrix once.
void keyboard_scan(void)
{
  for (int i = 0; i < 8; i++) // Rows
  {
    digitalWrite(rowpins[i], LOW); // Pull the row low...

    for (int j = 0; j < 15; j++) // ...and read the state of every column.
    {
      uint8_t iscan = i + (j << 3); // Create an internal scancode by combining the row and column numbers.
      uint8_t key = !digitalRead(colpins[j]); // Read the state of the key


      if (key != matrix[iscan]) // Has the state changed since the last scan?
      {
        // Look up the scancode translation table to find the key's IKBD (Atari) scancode.
        uint8_t scanc = (key ? scan[iscan] : (scan[iscan] | 0x80)); // High bit indicates press or release
     
        matrix[iscan] = key; // Store the new state for the next scan.
        convert_ST_USB(scanc); // Convert the IKBD scancode to USB HID.
      }
    }

    digitalWrite(rowpins[i], HIGH); // Finished with this row, pull it HIGH again.
  }
}


The HID stuff is well documented on the Teensyduino webpages, you should have no problems with that.

arnoldemu

Nice.

For the cpc you would need to remember the up/down state of every key internally.
Then when the cpc requests a specific keyboard "line", send it the state of those keys on that line.

It'll be interesting to see a usb keyboard hooked up to a cpc :)

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Joss

Quote from: arnoldemu on 17:54, 30 August 12
...
It'll be interesting to see a usb keyboard hooked up to a cpc :)
me too  :)  it looks nice and I didnt know about it


Bryce told in this post it is not possible to read and write the keyboard from expansion port and joystick port. Could it be possible to do it through the pins of the Z80? It is more difficult. The instructions to read the keyboard which are send by CPU have to be decode ..... I mean it because I don't want to touch much the CPC with soldering, it can go broken and the keyboard could be changed quickly to other CPC.

joska

Quote from: arnoldemu on 17:54, 30 August 12
It'll be interesting to see a usb keyboard hooked up to a cpc :)


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.

TFM

I would add a keyboard using the EXP-port and a patched OS. Nice use for the LowerROM board. But no, I'm fine with CPC's keyboard too  :)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bryce

That would be too much traffic for the EXP bus. Any other expansions (MegaFlash etc) may not work or work really slow. As the MegaFlash, SF2 and any floppy controller are very time sensitive, a delay like that would probably cause timing errors and malfunction.

Bryce.

IanS

Quote from: Bryce on 20:07, 30 August 12
That would be too much traffic for the EXP bus. Any other expansions (MegaFlash etc) may not work or work really slow. As the MegaFlash, SF2 and any floppy controller are very time sensitive, a delay like that would probably cause timing errors and malfunction.
What would be too much traffic for the EXP bus?

The existing keyboard routines that talk to the 8255 and indirectly to the AY sound chip all happen over the same data bus that appears on the EXP bus under interrupt control, there isn't a seperate external data bus. The MegaFlash, SF2 or floppy controller all probably turn off interupts (I know my flash programming routines do) during any time critical events.

Bryce

It uses the same address and databus, but everything external are addressed as I/0 with the /IORQ signal. Is it possible to poll the keyboard and write to the DDI-1 without timing out on the µPD ? I didn't think you could call an I/O address on every cycle. And if you could, wouldn't that slow the CPC down?

Bryce.

gerald

Quote from: Joss on 18:07, 30 August 12
I don't want to touch much the CPC with soldering, it can go broken and the keyboard could be changed quickly to other CPC.

On which CPC model you need to use the PS2 to CPC keyboard adapter?
The highly integrated version on 6128 was dictated by the lack of height between the PCB and the keyboard.
On 464, you can just piggypack the adapter (using a socket) on the 8255 and only solder the 10 needed pins (A0(A8), A1(A9), CSn(A11), WRn(IOWRn), C[3:0], VCC, GND).
The keyboard matrix part (X[7:0]) can be either soldered on PSG directly or on original keyboard connector.

Note that the adapter I did is usable in parallel with the keyboard.

Now to a bit of teasing  :D


gerald

Quote from: Bryce on 20:07, 30 August 12
That would be too much traffic for the EXP bus.
I would say it sill be too much capacitive/current load on the addr/data/control bus that may exceed drive capability of Z80 and other bus drivers, and cause timing or voltage issue. :P

Bryce

Very nice solution. Simple and to the point, although the µP seems a bit over the top for what it needs to do. Couldn't you have got away with using something smaller?

Bryce.

gerald

Well, a tiny2313 does the job as current code is 1.8k byte with one keymap. One keymap is about 190 bytes.
Since i've freed 2 pins compared to the previous incarnation (AT89C2051), more code/ram/eeprom space is welcome. 8)
Talking of space, AT89C2051 is 10% smaller with 2 keymaps  :o .

By the way, for 6128+, one just need to add a 4bit latch controlled by PPICWRn signal to catch the LINE value.

Bryce

Well you could use an external shift register and produce the output sequence with just one pin of the µP.

Bryce.

gerald

Timing requirement is quite tight. OS keyboard scan take about 6.5us from setting the line (falling edge of WRn) to reading the row (rising edge of RDn).
The ISR response time is the most important there, and is currently 4.5us. If you do not answer fast enough, you just get garbage.
Using a shift register may require a faster clock speed, and a shift register  ;D , so more space on board.

With a Tiny4313 costing something like 2 Euros, I do not think using a smaller device with a shift register is a good idea.

IanS

Quote from: Bryce on 20:56, 30 August 12
It uses the same address and databus, but everything external are addressed as I/0 with the /IORQ signal. Is it possible to poll the keyboard and write to the DDI-1 without timing out on the µPD ? I didn't think you could call an I/O address on every cycle. And if you could, wouldn't that slow the CPC down?
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.

You read or write to I/O address, can you explain what you mean by "call an I/O address"?

Bryce

Yes, but other (non-standard) bits that are connected externally, are they limited to how often they could be called? My problem is that I have no idea about the Firmware routines or restrictions, I've never looked that deeply into it. So I've no idea what's allowed and what's not in the firmware.

Bryce.

TFM

Quote from: Bryce on 20:07, 30 August 12
That would be too much traffic for the EXP bus. Any other expansions (MegaFlash etc) may not work or work really slow. As the MegaFlash, SF2 and any floppy controller are very time sensitive, a delay like that would probably cause timing errors and malfunction.

Bryce.

Hmmm. Well, I didn't intend to simulate the CPCs keyboard on a hardware level. I thougt more about transferring a byte only when a key is pressed.
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

MacDeath

QuoteIt'll be interesting to see a usb keyboard hooked up to a cpc
Then comes the main problem...


Locomotive Basic is done for specific keyboards... and doesn't manage all those Extra keys... could it ?


I guess you will have to kustomise the keys, while the average square letter key can be swaped, others would need to get new "sticker" on it.


Also as told, modern "PC (or Amiga or ST...16bit+) keyboard has a lot of extra keys...


Perhaps a patched Locobasic ROM would be needed, or the Extra keys simply "discarded" ?


What is the theoric limitation in the number of keys a CPC can handle ? does the official CPC keyboard use the maximum or not ?








Extra bonus : manage to kustomise the USB keyboard to get the 464 or 664 (über!) colour theme.


Cyan keys FTW !

Joss

Quote from: gerald on 21:02, 30 August 12
On which CPC model you need to use the PS2 to CPC keyboard adapter?


I was trying to understand a little more about the HW on the CPC. I thought such a project should be a good DIY-first project  ::)  and I thought there were plenty of solutions out there .... but I was wrong .... I don't need it, is only nice-to-have.


I will TRY to do it first in a Schneider CPC464. The keyboard socket/cable there is very easy to hack. If it works I will try to take it to the expansion port. I have a 664 with keyboard problems and it would be nice to easy change it from a CPC to another.


As I write this post I see a Amstrad CPC464 motherboard and I see the connector which are use in the Schneider are in the Amstrad too but unused. They can be use to solder (people like me w/o experience need a lot of room ...... )


And ... when I think about using the expansion port for the keyboard I mean I use the expansion port ONLY with the keyboard extension and it only has to read there the bus. No other stuff attached. I think now it should not be a problem .....  ::)  .... I think ;-) I don't have much know-how about it but trying to buffering what is attached to the CPC with his own power supply should not be extra load for the CPC.


Powered by SMFPacks Menu Editor Mod