void setup() {
Serial.begin(9600);
Serial.println();
setupUno(); // initialise GPIO pins for keypad/LEDs
//initKIM(); // Enters 0x1C00 in KIM vectors 17FA and 17FE. Might consider doing 17FC as well?
}
int huh = 0;
void loop() {
// put your main code here, to run repeatedly:
// exec6502(100); //do 100 6502 instructions
// varying the number 100 varies keyboard debounce/responsivity ;)
// if (SerialX.available()) { // read input from serial 'emulated' keypad
// curkey = SerialX.read() & 0x7F; // this is normal serial input *and* simulated keypad keypresse
// interpretkeys();
// }
scanKeys(); // ... and read input from physical keypad
}
// for Pro Mini, probably also for Arduino Uno though (that's just untested in recent years)
byte aCols[8] = { A5, 2,3,4,5,6,7,8 }; // note col A5 is the extra one linked to DP
byte kCols[8] = { 2,3,4,5,6,7,8, A5 }; // note col A5 is the extra one linked to DP
byte aRows[3] = { 9,10,11 };
byte ledSelect[8] = { 12, 13, A0, A1, A2, A3, A7, A4 }; // note that A7 not used at present. Can delete .
byte ledSelect7[8] = { 12, 13, A0, A1, A4, A2, A3, A7 }; // note that A7 not used at present. Can delete .
//extern uint8_t SSTmode;
//extern uint8_t useKeyboardLed; // 0 to use Serial port or 1 for HEX digits.
uint8_t curkey = 0; // buffer for the last unread keypress
uint8_t keyboardMode=0; // start with keyboard in KIM-1 mode. 1: calculator, 2: VTL02 mode
// mode 0: serial display emulates hex digits and keypad
// mode 1: ascii terminal with some control (and other) keys redefined
// mode 2: plain ascii terminal, only CTRL-R is still special (reset)
extern "C" uint8_t getAkey() { return(curkey); }
extern "C" void clearkey() { curkey = 0; }
extern "C" uint8_t xkeyPressed() { return (curkey==0?0:1); } // any keypress waiting?
// =================================================================================================
// KIM Uno Circuit Board functions
// =================================================================================================
void setupUno() {
int i;
// Sets up the IO pins to a defined state at boot-up
// set columns to input with pullups
for (i = 0; i < 8; i++)
{
pinMode(aCols[i], INPUT_PULLUP); // set pin to input
}
// set rows to output, and set them High to be in Neutral position
for (i = 0; i < 3; i++)
{
pinMode(aRows[i], OUTPUT); // set pin to output
digitalWrite(aRows[i], HIGH); // set to high
}
}
// translate keyboard commands to KIM-I keycodes or emulator actions
// remember: 2 types of keys. RS and ST are hardware things, the other switches are just read by KIM-1 software.
// also, pressing some keys for >1second toggles a mode
//
void interpretkeys()
{
// 1: keys that always have the same meaning
switch (curkey) {
case 18: // CtrlR = RS key = hardware reset (RST)
//reset6502();
clearkey(); Serial.print("RSet\n"); break;
case 20: // CtrlT = ST key = throw an NMI to stop execution of user program
//nmi6502();
clearkey(); Serial.print("STop\n"); break;
}
// 1B: keys that always have the same meaning but are disabled in VTL-02
// KeyboardMode 2 can be regarded as a switch to a normal ASCII keyboard.
if(keyboardMode!=2)
{
switch(curkey) {
case '[': // SST off
//SSTmode = 0;
clearkey();
//SerialX.print(F(" SST OFF ")); // nice but too many spaces, out of Flash storage ;)
Serial.print(F("\r\nSST OFF\r\n"));
break;
case ']': // SST on
//SSTmode = 1;
clearkey();
Serial.print(F("\r\nSST ON\r\n"));
break;
case 9: // TAB pressed, lets KIM-1 ROM toggle between its KIM-1 Teletype mode and onboard LEDkeypad mode
// if (useKeyboardLed==0)
// {
// //useKeyboardLed=1;
// //SerialX.print(F(" Keyboard/Hex Digits Mode "));
// Serial.print(F("\r\nKeypad Mode\r\n"));
// }
// else
// {
// //useKeyboardLed=0;
// //SerialX.print(F(" Serial Terminal Mode "));
// Serial.print(F("\r\nTTY Mode\r\n"));
// }
//reset6502();
clearkey(); break;
case '>': // Toggle write protect on eeprom
// if (eepromProtect==0) {
// eepromProtect = 1;
// //SerialX.print(F(" Eeprom R/O "));
// SerialX.print(F("\r\nEeprom R/O\r\n"));
// } else {
// eepromProtect = 0;
// //SerialX.print(F(" Eeprom R/W "));
// SerialX.print(F("\r\nEeprom R/W\r\n"));
// delay(20);
// }
clearkey(); break;
}
}
}
// parse keycode of hardware keypad to return its ASCII code
// remember, KIM Uno keypad delivers KIM Uno keycodes, they're not (not always) the same as KIM-1 keycodes!
// this is fine, as we feed KIM Uno keypresses **and** serial 'keypad emulation' keypresses into the ROM later on
//
uint8_t parseChar(uint8_t n)
{
uint8_t c;
// KIM-I keys
switch (n-1) { //KIM Uno keyscan codes to ASCII codes used by emulator
case 7 : c = '0' ; break; // note: these are n-1 numbers!
case 6 : c = '1'; break; //
case 5 : c = '2'; break; //
case 4 : c = '3'; break; //
case 3 : c = '4'; break; //
case 2 : c = '5'; break; //
case 1 : c = '6'; break; //
case 0 : c = 20; break; // ST
case 15 : c = '7' ; break; //
case 14 : c = '8'; break; //
case 13 : c = '9'; break; //
case 12 : c = 'A'; break; //
case 11 : c = 'B'; break; //
case 10 : c = 'C'; break; //
case 9 : c = 'D'; break; //
case 8 : c = 18; break; // RS
case 23 : c = 'E'; break; //
case 22 : c = 'F'; break; //
case 21 : c = 1; break; // AD
case 20 : c = 4; break; // DA
case 19 : c = '+'; break; // +
case 18 : c = 7; break; // GO
case 17 : c = 16; break; // PC
case 16 : c = '['; break; // (SSTmode == 0 ? ']' : '['); break; // SST toggle
}
return c;
}
// scankeys: the actual reading of the hardware keypad
//
extern "C" { // the extern C is to make function accessible from within cpu.c
void scanKeys()
{
int led, row, col, noKeysScanned;
static int keyCode = -1, prevKey = 0;
static unsigned long timeFirstPressed = 0;
// 0. disable driving the 7segment LEDs -----------------
for (led=0;led<8;led++)
{
pinMode(ledSelect[led], INPUT); // set led pins to input
// INPUT_PULLUP not really necessary? could be used just to stop them
// from driving either high or low.
}
// 1. initialise: set columns to input with pullups
for (col=0;col<8;col++)
{
pinMode(aCols[col], INPUT_PULLUP); // set pin to input
}
// 2. perform scanning
noKeysScanned=0;
for (row = 0; row < 3; row++)
{
digitalWrite(aRows[row], LOW); // activate this row
for (col = 0; col < 8; col++)
{
if (digitalRead(aCols[col])==LOW) // key is pressed
{
keyCode = col+row*8+1;
if (keyCode!=prevKey)
{ Serial.println();
Serial.print(" col: "); Serial.print(col, DEC);
Serial.print(" row: "); Serial.print(row, DEC);
Serial.print(" prevKey: "); Serial.print(prevKey, DEC);
Serial.print(" KeyCode: "); Serial.println(keyCode, DEC);
prevKey = keyCode;
curkey = parseChar(keyCode);
Serial.print(" curkey: "); Serial.print(curkey, DEC);
timeFirstPressed=millis(); //
}
else // if pressed for >1sec, it's a ModeShift key
{
if ((millis()-timeFirstPressed)>1000) // more than 1000 ms
{
if (keyCode==17) //it was the SST button
{
keyboardMode=(keyboardMode==0?1:0); // toggle
//SerialX.print(F(" keyboardMode: ")); SerialX.print(keyboardMode, DEC);
Serial.print(F("\r\nkeyboardMode: "));
Serial.print(keyboardMode, DEC);
//SSTmode=0;
curkey=0; // don't do anything else with this keypress
}
if (keyCode==9) // it was RS button
curkey = '>'; // toggle eeprom write protect
// for VTL-02: pressing ST for a second enters VTL02 keyboard mode
if (keyCode==1) // it was ST button
{
curkey = 0; // toggle eeprom write protect
keyboardMode=(keyboardMode==0?2:0); // toggle
//SerialX.print(F(" keyboardMode(VTL): ")); SerialX.print(keyboardMode, DEC);
Serial.print(F("\r\nkeyboardMode(VTL): "));
Serial.println(keyboardMode, DEC);
}
timeFirstPressed=millis(); // because otherwise you toggle right back!
}
}
}
else
noKeysScanned++; // another row in which no keys were pressed
}
digitalWrite(aRows[row], HIGH); // de-activate this row
}
if (noKeysScanned==24) // no keys detected in any row, 3 rows * 8 columns = 24.
prevKey=0; // allows you to enter same key twice
//20200808
//write1742(); write1743(); // restore LED display
//write1741(); write1740(); // restore LED display
if (xkeyPressed()!=0) //KIM Uno board input?
interpretkeys();
// --end 20200808
} // end of function
} // end C segment