mirror of https://github.com/smartykit/apple1.git
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:
commit
9cce8e0b62
|
@ -1 +1,2 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.vscode
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue