Merge pull request #2 from sparky62/master

Upgrade to use PS2KeyAdvanced to support modern PS/2 Keyboards (like Perixx from Amazon – https://youtu.be/6pjx7aud5Eo).
This commit is contained in:
Computer construction kit SmartyKit 2022-01-26 11:03:58 +03:00 committed by GitHub
commit 9cce8e0b62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 99 additions and 91 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
.DS_Store .DS_Store
.vscode

View File

@ -15,7 +15,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "PS2Keyboard.h" #include <PS2KeyAdvanced.h>
#include <PS2KeyMap.h>
// Keyboard Driver pins connections: // Keyboard Driver pins connections:
// D0 & D1 reserved for Serial connection // D0 & D1 reserved for Serial connection
@ -27,92 +28,96 @@
// A4 -> Low-rate clock output for CPU CLK input // A4 -> Low-rate clock output for CPU CLK input
// A5 -> Low-rate clock output for indicating LED connection // A5 -> Low-rate clock output for indicating LED connection
const int PS2Socket_Data = 2; #define PS2KEYBOARDCLOCK_PIN 2
const int CPUreadsKeyboardPin = 3; #define KEYBOARD_RD_PIN 3
const int PS2Socket_Clk = 4; #define PS2KEYBOARD_DATA_PIN 4
#define KEYBOARD_BIT7_PIN 5
const int KeyboardPort[8] = {6, 7, 8, 9, 10, 11, 12, 13};
const int KeyboardBIT7pin = 5; // static boolean autoMode = false; //run pre-set command or wait for user input from PS/2 keyboard
const int DataBus[8] = {6, 7, 8, 9, 10, 11, 12, 13};
static boolean BIT7flag = false;
static boolean autoMode = true; //run pre-set command or wait for user input from PS/2 keyboard
static boolean autoCommandSent = false; // run pre-set command only once after reboot of Keyboard controller static boolean autoCommandSent = false; // run pre-set command only once after reboot of Keyboard controller
//low-rate clock for tests on A4-A5 //low-rate clock for tests on A4-A5
#define CLOCK A4 #define LORATE_CLOCK_PIN A4
#define LED A5 #define LORATE_CLOCK_LED_PIN A5
int lowRateClockPeriod = 10; //10 milliseconds = 100 times per second (100 Hz)
//#define _WITH_SERIAL_ //10 milliseconds = 100 times per second (100 Hz)
#define _WITH_PS2_ #define LORATE_CLOCK_PERIOD_MILLIS 100
#ifdef _WITH_PS2_ PS2KeyAdvanced keyboard;
PS2Keyboard keyboard; PS2KeyMap keymap;
#endif
void setup() void setup()
{ {
pinMode(CLOCK, OUTPUT); pinMode(LORATE_CLOCK_PIN, OUTPUT);
pinMode(LED, OUTPUT); pinMode(LORATE_CLOCK_LED_PIN, OUTPUT);
pinMode(CPUreadsKeyboardPin, INPUT_PULLUP); pinMode(KEYBOARD_RD_PIN, INPUT_PULLUP);
for (int count = 1; count <= 8; count++) {
pinMode(DataBus[count-1], OUTPUT);
};
pinMode(KeyboardBIT7pin, OUTPUT);
KeyboardBIT7_Disable();
for (int bit = 0; bit < 8; bit++) {
pinMode(KeyboardPort[bit], OUTPUT);
}
pinMode(KEYBOARD_BIT7_PIN, OUTPUT);
digitalWrite(KEYBOARD_BIT7_PIN, LOW);
Serial.begin(9600);
Serial.println("SmartyKit 1 PS2 Keyboard is ready...");
if (autoMode) if (autoMode)
delay(7500); //for start without Keyboard connected delay(7500); //for start without Keyboard connected
else else
delay(500); delay(500);
#ifdef _WITH_PS2_ keyboard.begin(PS2KEYBOARD_DATA_PIN, PS2KEYBOARDCLOCK_PIN);
keyboard.begin(PS2Socket_Clk, PS2Socket_Data); keyboard.echo();
#endif delay( 6 );
attachInterrupt(1, cpuReadsKeyboard, FALLING); uint16_t scan_code = keyboard.read();
#ifdef _WITH_SERIAL_ if( (scan_code & 0xff) == PS2_KEY_ECHO || (scan_code & 0xff) == PS2_KEY_BAT || (scan_code & 0xff) == 0xe8 )
Serial.begin(9600); Serial.println( "Keyboard OK.." ); // Response was Echo or power up
Serial.println("SmartyKit 1 Serial Keyboard is ready..."); else
#endif if ((scan_code & 0xff) == 0)
{
Serial.println( "Keyboard Not Found" );
}
else
{
Serial.print( "Invalid Code received of 0x" );
Serial.println(scan_code, HEX);
}
keyboard.setNoBreak(1);
keyboard.setNoRepeat(1);
keymap.selectMap((char *)"UK");
attachInterrupt(digitalPinToInterrupt(KEYBOARD_RD_PIN), cpuReadsKeyboard, FALLING);
} }
void cpuReadsKeyboard(void) void cpuReadsKeyboard(void)
{ {
KeyboardBIT7_Disable(); digitalWrite(KEYBOARD_BIT7_PIN, LOW);
}
void KeyboardBIT7_Enable()
{
digitalWrite(KeyboardBIT7pin, HIGH);
BIT7flag = true;
}
void KeyboardBIT7_Disable()
{
digitalWrite(KeyboardBIT7pin, LOW);
BIT7flag = false;
} }
void sendCharToKeyboardPort(char c) void sendCharToKeyboardPort(char c)
{ {
while(BIT7flag == true) //wait untill the previous char is read by CPU if (c == '\r')
delay(5); Serial.println();
else
for (int count = 1; count <= 8 ; count++) Serial.print(c);
for (int bit = 0; bit < 8 ; bit++)
{ {
if (c & (1 << (count-1))) if (c & (1 << (bit)))
digitalWrite(DataBus[count-1], HIGH); digitalWrite(KeyboardPort[bit], HIGH);
else else
digitalWrite(DataBus[count-1], LOW); digitalWrite(KeyboardPort[bit], LOW);
} }
digitalWrite(DataBus[7], HIGH); digitalWrite(KeyboardPort[7], HIGH);
KeyboardBIT7_Enable(); digitalWrite(KEYBOARD_BIT7_PIN, HIGH);
} }
void loop() { void loop()
{
//run pre-set command in auto-mode when PS/2 keyboard is not connected //run pre-set command in auto-mode when PS/2 keyboard is not connected
//only once after reboot of Keyboard controller //only once after reboot of Keyboard controller
if (autoMode && !autoCommandSent) if (autoMode && !autoCommandSent)
@ -121,55 +126,58 @@ void loop() {
runAutoModeCommand(); runAutoModeCommand();
} }
#ifdef _WITH_PS2_
//check PS2 input //check PS2 input
if (keyboard.available()) { if (!digitalRead(KEYBOARD_BIT7_PIN) && keyboard.available())
char c = keyboard.read(); {
uint16_t scan_code = keymap.remapKey(keyboard.read());
char c = scan_code & 0xff;
Serial.print(":0x");
Serial.print(scan_code, HEX);
Serial.print(":");
if (c == PS2_TAB)
runCommand();
//process Backspace, Left Arrow, Delete as Apple I backspace '_' //process Backspace, Left Arrow, Delete as Apple I backspace '_'
if (c == PS2_BACKSPACE) { switch (c)
c = '_'; {
} else if (c == PS2_LEFTARROW) { case PS2_KEY_TAB:
c = '_'; runCommand();
} else if (c == PS2_DELETE) { break;
c = '_'; case PS2_KEY_BS:
case PS2_KEY_DELETE:
case PS2_KEY_L_ARROW:
c = '_';
break;
case PS2_KEY_ENTER:
c = '\r';
break;
case PS2_KEY_SPACE:
c = ' ';
break;
} }
int scan_code = (int)c;
//make all symbols uppercase (from 'a' (ASCII code 0x61) to 'z' (ASCII code 0x7A)) //make all symbols uppercase (from 'a' (ASCII code 0x61) to 'z' (ASCII code 0x7A))
//as in original Apple-1 //as in original Apple-1
if (scan_code >= 0x61 && scan_code <= 0x7A) c = toupper(c);
scan_code -= 0x20;
c = (char) scan_code;
//print c to Keyboard Port to be read by CPU //print c to Keyboard Port to be read by CPU
sendCharToKeyboardPort(c); sendCharToKeyboardPort(c);
#ifdef _WITH_SERIAL_
Serial.print(c);
if (c == '\r')
Serial.println();
#endif
} }
#endif
//low-rate clock //low-rate clock
digitalWrite(CLOCK, HIGH); digitalWrite(LORATE_CLOCK_PIN, HIGH);
digitalWrite(LED, HIGH); digitalWrite(LORATE_CLOCK_LED_PIN, HIGH);
delay(lowRateClockPeriod); // wait for a lowRateClockPeriod delay(LORATE_CLOCK_PERIOD_MILLIS); // wait for a LORATE_CLOCK_PERIOD_MILLIS
digitalWrite(CLOCK, LOW); digitalWrite(LORATE_CLOCK_PIN, LOW);
digitalWrite(LED, LOW); digitalWrite(LORATE_CLOCK_LED_PIN, LOW);
delay(lowRateClockPeriod); // wait for a lowRateClockPeriod delay(LORATE_CLOCK_PERIOD_MILLIS); // wait for a LORATE_CLOCK_PERIOD_MILLIS
} }
//running pre-set Woz OS command for auto mode //running pre-set Woz OS command for auto mode
void runAutoModeCommand() void runAutoModeCommand()
{ {
const int CMD_COUNT = 1; const int cmd_count = 1;
String cmd1 = String("F000R\r"); // Woz face demo program at $F000 String cmd1 = String("F000R\r"); // Woz face demo program at $F000
String commands[] = {cmd1}; String commands[] = {cmd1};
for (int i = 0; i < CMD_COUNT; i++) for (int i = 0; i < cmd_count; i++)
for (int j = 0; j < commands[i].length(); j++) for (int j = 0; j < commands[i].length(); j++)
{ {
char c = commands[i].charAt(j); char c = commands[i].charAt(j);
@ -179,17 +187,16 @@ void runAutoModeCommand()
//running pre-set Woz OS command (drawing 8x8 pixel art) //running pre-set Woz OS command (drawing 8x8 pixel art)
void runCommand() void runCommand()
{ {
const int CMD_COUNT = 4; const int cmd_count = 4;
String cmd1 = String("1111: 88 A8 50\r"); String cmd1 = String("1111: 88 A8 50\r");
String cmd2 = String(":07 61 92\r"); String cmd2 = String(":07 61 92\r");
String cmd3 = String(":94 67\r"); String cmd3 = String(":94 67\r");
String cmd4 = String("FC00R\r"); String cmd4 = String("FC00R\r");
String commands[] = {cmd1, cmd2, cmd3, cmd4}; String commands[] = {cmd1, cmd2, cmd3, cmd4};
for (int i = 0; i < CMD_COUNT; i++) for (int i = 0; i < cmd_count; i++)
for (int j = 0; j < commands[i].length(); j++) for (int j = 0; j < commands[i].length(); j++)
{ {
char c = commands[i].charAt(j); char c = commands[i].charAt(j);
sendCharToKeyboardPort(c); sendCharToKeyboardPort(c);
} }
} }