Add files via upload
This commit is contained in:
parent
3717799d54
commit
e4911f3e54
4 changed files with 567 additions and 0 deletions
70
Commodore_64/C64keys.txt
Normal file
70
Commodore_64/C64keys.txt
Normal file
|
@ -0,0 +1,70 @@
|
|||
C64 pinout when ping 0-9 and A-I connected to teensy 0-18
|
||||
IMPORTANT: SKIP PIN 13 AS IT IS CONNECTED TO LED
|
||||
AND WILL GIVE YOU FALSE READINGS
|
||||
|
||||
Esc 4 20
|
||||
1 20 2
|
||||
2 16 20
|
||||
3 2 22
|
||||
4 16 22
|
||||
5 2 24
|
||||
6 16 24
|
||||
7 2 26
|
||||
8 16 26
|
||||
9 2 23
|
||||
0 16 23
|
||||
+ 2 21
|
||||
- 16 21
|
||||
Funt 2 19
|
||||
Clr/Home 16 19
|
||||
Inst/Del 17 2
|
||||
Control 6 20
|
||||
Q 14 20
|
||||
W 4 22
|
||||
E 14 22
|
||||
R 24 4
|
||||
T 14 24
|
||||
Y 4 26
|
||||
U 14 26
|
||||
I 4 23
|
||||
O 14 23
|
||||
P 4 21
|
||||
@ 14 21
|
||||
* 4 19
|
||||
Pi 14 19
|
||||
Restore 18 15
|
||||
Run/Stop 8 20
|
||||
ShiftLock 8 22
|
||||
A 6 22
|
||||
S 12 22
|
||||
D 6 24
|
||||
F 12 24
|
||||
G 26 6
|
||||
H 12 26
|
||||
J 23 6
|
||||
K 12 23
|
||||
L 6 21
|
||||
:[ 21 12
|
||||
;] 6 19
|
||||
= 12 19
|
||||
Return 17 4
|
||||
C= 12 20
|
||||
LShift 8 22
|
||||
Z 22 10
|
||||
X 8 24
|
||||
C 24 10
|
||||
V 8 26
|
||||
B 10 26
|
||||
N 8 23
|
||||
M 10 23
|
||||
, 8 21
|
||||
. 10 21
|
||||
/ 19 8
|
||||
RShift 10 19
|
||||
CrsrUpDown 17 8
|
||||
CrsrLeftRight 6 17
|
||||
F1 10 17
|
||||
F3 12 17
|
||||
F5 14 17
|
||||
F7 16 17
|
||||
Spc 10 20
|
8
Commodore_64/C64speckeys.txt
Normal file
8
Commodore_64/C64speckeys.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
cntrl-l 6 20 (Control)
|
||||
cntrl-r ---
|
||||
shift-l 8 22 (LShift)
|
||||
shift-r 10 21 (RShift)
|
||||
alt-l 8 20 (Run Stop)
|
||||
alt-r 17 18 (Restore)
|
||||
gui 20 12 (C=)
|
||||
fn ---
|
489
Commodore_64/Commodore_C64.ino
Normal file
489
Commodore_64/Commodore_C64.ino
Normal file
|
@ -0,0 +1,489 @@
|
|||
/* Copyright 2019 Olga, based on work of Frank Adams
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// This software implements an C64 Keyboard Controller using a Teensy LC connected
|
||||
// directly with keyboard
|
||||
// Keyboard pins 0-9 and A-F are connected to Teensy LC pins 0-18 respectively in order.
|
||||
// IMPORTANT ! DO NOT CONNECT PIN 13 AS IT DRIVES LED AND GIVES RANDOM READING !
|
||||
// This routine uses the Teensyduino "Micro-Manager Method" to send Normal and Modifier
|
||||
// keys over USB.
|
||||
// Description of Teensyduino keyboard functions is at www.pjrc.com/teensy/td_keyboard.html
|
||||
//
|
||||
// Revision History
|
||||
// Initial Release Mar 27, 2019
|
||||
//
|
||||
//
|
||||
|
||||
// comment this line to have debug code included
|
||||
#define NODEBUG
|
||||
|
||||
struct KeyDesc {
|
||||
const char* name;
|
||||
boolean isModifier;
|
||||
int pin1;
|
||||
int pin2;
|
||||
int keyCode;
|
||||
int keyCode2;
|
||||
boolean scanned;
|
||||
};
|
||||
struct KeyDesc Keys[] =
|
||||
{
|
||||
{ "CTRL", true, 6, 20, MODIFIERKEY_CTRL, 0 },
|
||||
{ "LSHIFT", true, 8, 22, MODIFIERKEY_LEFT_SHIFT, 0 },
|
||||
{ "RSHIFT", true, 10, 19, MODIFIERKEY_RIGHT_SHIFT, 0 },
|
||||
{ "LALT (RSTOP)", true, 8, 20, MODIFIERKEY_LEFT_ALT, 0 },
|
||||
{ "RALT (RESTORE)", true, 15, 18, MODIFIERKEY_RIGHT_ALT, 0 },
|
||||
{ "GUI", true, 20, 12, MODIFIERKEY_GUI, 0 },
|
||||
|
||||
{ "ESC", false, 4, 20, KEY_ESC, 0 },
|
||||
{ "1", false, 2, 20, KEY_1, 0 },
|
||||
{ "2", false, 16, 20, KEY_2, 0 },
|
||||
{ "3", false, 22, 2, KEY_3, 0 },
|
||||
{ "4", false, 16, 22, KEY_4, 0 },
|
||||
{ "5", false, 2, 24, KEY_5, 0 },
|
||||
{ "6", false, 16, 24, KEY_6, 0 },
|
||||
{ "7", false, 2, 26, KEY_7, 0 },
|
||||
{ "8", false, 16, 26, KEY_8, 0 },
|
||||
{ "9", false, 2, 23, KEY_9, 0 },
|
||||
{ "0", false, 23, 16, KEY_0, 0 },
|
||||
{ "+", false, 2, 21, KEYPAD_PLUS, 0 },
|
||||
{ "-", false, 21, 16, KEYPAD_MINUS, 0 },
|
||||
{ "END (Pound)", false, 19, 2, KEY_END },
|
||||
{ "HOME", false, 16, 19, KEY_HOME, KEY_DELETE },
|
||||
{ "BACKSPACE", false, 2, 17, KEY_BACKSPACE, KEY_INSERT },
|
||||
{ "Q", false, 14, 20, KEY_Q, 0 },
|
||||
{ "W", false, 4, 22, KEY_W, 0 },
|
||||
{ "E", false, 14, 22, KEY_E, 0 },
|
||||
{ "R", false, 4, 24, KEY_R, 0 },
|
||||
{ "T", false, 14, 24, KEY_T, 0 },
|
||||
{ "Y", false, 4, 26, KEY_Y, 0 },
|
||||
{ "U", false, 26, 14, KEY_U, 0 },
|
||||
{ "I", false, 23, 4, KEY_I, 0 },
|
||||
{ "O", false, 23, 14, KEY_O, 0 },
|
||||
{ "P", false, 21, 4, KEY_P, 0 },
|
||||
{ "TAB (@)", false, 14, 21, KEY_TAB, 0 },
|
||||
{ "*", false, 4, 19, KEYPAD_ASTERIX, 0 },
|
||||
{ "BACKSLASH (Pi)", false, 19, 14, KEY_BACKSLASH, 0 },
|
||||
{ "A", false, 6, 22, KEY_A, 0 },
|
||||
{ "S", false, 22, 12, KEY_S, 0 },
|
||||
{ "D", false, 6, 24, KEY_D, 0 },
|
||||
{ "F", false, 12, 24, KEY_F, 0 },
|
||||
{ "G", false, 6, 26, KEY_G, 0 },
|
||||
{ "H", false, 12, 26, KEY_H, 0 },
|
||||
{ "J", false, 23, 6, KEY_J, 0 },
|
||||
{ "K", false, 23, 12, KEY_K, 0 },
|
||||
{ "L", false, 21, 6, KEY_L, 0 },
|
||||
{ "'", false, 12, 21, KEY_QUOTE, 0 },
|
||||
{ ";", false, 6, 19, KEY_SEMICOLON, 0 },
|
||||
{ "=", false, 12, 19, KEY_EQUAL, 0 },
|
||||
{ "ENTER", false, 4, 17, KEY_ENTER, 0 },
|
||||
{ "Z", false, 10, 22, KEY_Z, 0 },
|
||||
{ "X", false, 8, 24, KEY_X, 0 },
|
||||
{ "C", false, 10, 24, KEY_C, 0 },
|
||||
{ "V", false, 8, 26, KEY_V, 0 },
|
||||
{ "B", false, 10, 26, KEY_B, 0 },
|
||||
{ "N", false, 23, 8, KEY_N, 0 },
|
||||
{ "M", false, 23, 10, KEY_M, 0 },
|
||||
{ ",", false, 8, 21, KEY_COMMA, 0 },
|
||||
{ ".", false, 10, 21, KEY_PERIOD, 0 },
|
||||
{ "/", false, 8, 19, KEY_SLASH, 0 },
|
||||
{ "UP", false, 8, 17, KEY_DOWN, KEY_UP },
|
||||
{ "LEFT", false, 6, 17, KEY_RIGHT, KEY_LEFT },
|
||||
{ "F1", false, 10, 17, KEY_F1, KEY_F2 },
|
||||
{ "F3", false, 12, 17, KEY_F3, KEY_F4 },
|
||||
{ "F5", false, 17, 14, KEY_F5, KEY_F6 },
|
||||
{ "F7", false, 16, 17, KEY_F7, KEY_F8 },
|
||||
{ "SPACE", false, 10, 20, KEY_SPACE, 0 },
|
||||
{ "none", false, 0, 0, 0, 0 } // last key - no key
|
||||
};
|
||||
|
||||
// second keycode accessible via modifier
|
||||
#define SECOND_CODE MODIFIERKEY_RIGHT_SHIFT
|
||||
|
||||
// number of teensy pins
|
||||
#define PIN_MAX 26
|
||||
|
||||
// PIN to IO number; zero-index is not valid and hence -1
|
||||
const int PinToIO[] = { -1, 23, 0, 22, 1, 24, 2, 21, 3, 25, 4, 20, 5, 19, 6, 18, 7, 17, 8, 16, 9, 15, 10, 14, 11, 26, 12 };
|
||||
|
||||
const int ForbiddenInputs[] = { -1 };
|
||||
const int ForbiddenOutputs[] = { -1 };
|
||||
|
||||
boolean is_input_allowed(int pin) {
|
||||
for(int i = 0 ; ; i++) {
|
||||
int input = ForbiddenInputs[i];
|
||||
if (input <= 0) {
|
||||
break;
|
||||
}
|
||||
if (input == pin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean is_output_allowed(int pin) {
|
||||
for(int i = 0 ; ; i++) {
|
||||
int output = ForbiddenOutputs[i];
|
||||
if (output <= 0) {
|
||||
break;
|
||||
}
|
||||
if (output == pin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// slots hold the normal key values to be sent over USB.
|
||||
// WARNING - this must be set between 1 and 6
|
||||
#define SLOT_NORMAL_COUNT 6
|
||||
int slots[SLOT_NORMAL_COUNT];
|
||||
|
||||
// modifiers table holds - surprise - the modifier keys states
|
||||
#define SLOT_MOD_COUNT 6
|
||||
int mods[SLOT_MOD_COUNT];
|
||||
|
||||
// general check for button pressed
|
||||
boolean is_pressed(int key, int* slot, int slotCount) {
|
||||
for(int i = 0; i < slotCount ; i++) {
|
||||
if (slot[i] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// general slot setup function, returns true on change
|
||||
boolean set_slot(int key, boolean isPressed, int* slot, int slotCount) {
|
||||
boolean currentlyPressed = is_pressed(key, slot, slotCount);
|
||||
if (currentlyPressed == isPressed) {
|
||||
return false;
|
||||
}
|
||||
for(int i = 0; i < slotCount ; i++) {
|
||||
if ((isPressed && slot[i] == 0) || (!isPressed && slot[i] == key)) {
|
||||
slot[i] = isPressed ? key : 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if normal key pressed
|
||||
boolean is_key_pressed(int key) {
|
||||
return is_pressed(key, slots, SLOT_NORMAL_COUNT);
|
||||
}
|
||||
|
||||
// check if mod key pressed
|
||||
boolean is_mod_pressed(int key) {
|
||||
return is_pressed(key, mods, SLOT_MOD_COUNT);
|
||||
}
|
||||
|
||||
// Function to load the key name into the first available slot
|
||||
boolean load_slot(int key) {
|
||||
return set_slot(key, true, slots, SLOT_NORMAL_COUNT);
|
||||
}
|
||||
|
||||
// Function to clear the slot that contains the key name
|
||||
boolean clear_slot(int key) {
|
||||
return set_slot(key, false, slots, SLOT_NORMAL_COUNT);
|
||||
}
|
||||
|
||||
// Function to load the modifier key name into the appropriate mod variable
|
||||
boolean load_mod(int m_key) {
|
||||
return set_slot(m_key, true, mods, SLOT_MOD_COUNT);
|
||||
}
|
||||
|
||||
// Function to load 0 into the appropriate mod variable
|
||||
boolean clear_mod(int m_key) {
|
||||
return set_slot(m_key, false, mods, SLOT_MOD_COUNT);
|
||||
}
|
||||
//
|
||||
// Function to send the modifier keys over usb
|
||||
void send_mod() {
|
||||
int totalMod = 0;
|
||||
for(int i = 0; i < SLOT_MOD_COUNT ; i++) {
|
||||
totalMod |= mods[i];
|
||||
}
|
||||
Keyboard.set_modifier(totalMod);
|
||||
Keyboard.send_now();
|
||||
}
|
||||
//
|
||||
// Function to send the normal keys in the 6 slots over usb
|
||||
void send_normals() {
|
||||
for(int i = 0 ; i < SLOT_NORMAL_COUNT ; i++) {
|
||||
int value = slots[i];
|
||||
switch(i) {
|
||||
case 0:
|
||||
Keyboard.set_key1(value);
|
||||
break;
|
||||
case 1:
|
||||
Keyboard.set_key2(value);
|
||||
break;
|
||||
case 2:
|
||||
Keyboard.set_key3(value);
|
||||
break;
|
||||
case 3:
|
||||
Keyboard.set_key4(value);
|
||||
break;
|
||||
case 4:
|
||||
Keyboard.set_key5(value);
|
||||
break;
|
||||
case 5:
|
||||
Keyboard.set_key6(value);
|
||||
break;
|
||||
default:
|
||||
// no send here
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyboard.send_now();
|
||||
}
|
||||
//
|
||||
// Function to set a pin to high impedance (acts like open drain output)
|
||||
void go_z(int pin)
|
||||
{
|
||||
pinMode(pin, INPUT);
|
||||
digitalWrite(pin, HIGH);
|
||||
}
|
||||
//
|
||||
// Function to set a pin as an input with a pullup
|
||||
void go_pu(int pin)
|
||||
{
|
||||
pinMode(pin, INPUT_PULLUP);
|
||||
digitalWrite(pin, HIGH);
|
||||
}
|
||||
//
|
||||
// Function to send a pin to a logic low
|
||||
void go_0(int pin)
|
||||
{
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, LOW);
|
||||
}
|
||||
//
|
||||
// Function to send a pin to a logic high
|
||||
void go_1(int pin)
|
||||
{
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, HIGH);
|
||||
}
|
||||
// find highest count less than given if given
|
||||
int FindMaxPin(int* PinCount, int lessThan) {
|
||||
int maxPin = -1;
|
||||
int currentMax = -1;
|
||||
for(int i = 1 ; i <= PIN_MAX ; i++) {
|
||||
int value = PinCount[i];
|
||||
if (value > currentMax && (lessThan < 0 || value <= lessThan)) {
|
||||
maxPin = i;
|
||||
currentMax = value;
|
||||
}
|
||||
}
|
||||
return maxPin;
|
||||
}
|
||||
|
||||
////// DEBUG CODE
|
||||
|
||||
void d_start() {
|
||||
#ifndef NODEBUG
|
||||
Serial.begin(9600);
|
||||
#endif
|
||||
}
|
||||
|
||||
void d_print(const char* format, ...) {
|
||||
#ifndef NODEBUG
|
||||
va_list(aptr);
|
||||
int ret;
|
||||
char buffer[200];
|
||||
va_start(aptr, format);
|
||||
ret = vsprintf(buffer, format, aptr);
|
||||
va_end(aptr);
|
||||
if (ret >= 0) {
|
||||
Serial.println(buffer);
|
||||
} else {
|
||||
Serial.println("--- error constructing debug log ---");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////// END DEBUG CODE
|
||||
|
||||
int KeyCount;
|
||||
int PinOrderFromMax[PIN_MAX];
|
||||
//
|
||||
//----------------------------------Setup-------------------------------------------
|
||||
void setup() {
|
||||
d_start();
|
||||
d_print("Setup Start");
|
||||
// setup keyboard tables
|
||||
for(int i = 0 ; i < SLOT_NORMAL_COUNT ; i++) {
|
||||
slots[i] = 0;
|
||||
}
|
||||
for(int i = 0 ; i < SLOT_MOD_COUNT ; i++) {
|
||||
mods[i] = 0;
|
||||
}
|
||||
int PinCount[PIN_MAX + 1];
|
||||
// calculate pin count given
|
||||
for(int i = 1 ; i <= PIN_MAX ; i++) {
|
||||
PinCount[i] = 0;
|
||||
}
|
||||
for(int i = 0 ; ; i++) {
|
||||
const struct KeyDesc& keyDesc = Keys[i];
|
||||
if (keyDesc.keyCode == 0) {
|
||||
KeyCount = i;
|
||||
break;
|
||||
}
|
||||
PinCount[keyDesc.pin1]++;
|
||||
PinCount[keyDesc.pin2]++;
|
||||
}
|
||||
int maxPin = -1;
|
||||
for(int i = 0 ; i < PIN_MAX ; i++) {
|
||||
maxPin = FindMaxPin(PinCount, maxPin > 0 ? PinCount[maxPin] : -1);
|
||||
if (maxPin > 0) {
|
||||
PinOrderFromMax[i] = maxPin;
|
||||
PinCount[maxPin] = -1;
|
||||
} else {
|
||||
PinOrderFromMax[i] = -1;
|
||||
}
|
||||
}
|
||||
for(int i = 1 ; i <= PIN_MAX ; i++) {
|
||||
go_pu(PinToIO[i]);
|
||||
}
|
||||
d_print("Setup OK");
|
||||
}
|
||||
//
|
||||
|
||||
//
|
||||
//---------------------------------Main Loop---------------------------------------------
|
||||
//
|
||||
void loop() {
|
||||
// prepare table of scanned keys
|
||||
for(int i = 0 ; i < KeyCount ; i++) {
|
||||
Keys[i].scanned = false;
|
||||
}
|
||||
for(int i = 0 ; i < PIN_MAX ; i++) {
|
||||
// find maximum pin count in prepared table
|
||||
int pinAsOutput = PinOrderFromMax[i];
|
||||
if (pinAsOutput <= 0 || !is_output_allowed(pinAsOutput)) {
|
||||
continue;
|
||||
}
|
||||
// set this pin as output, find corresponding keys and set their other pins as input will pullup
|
||||
// input on other pins
|
||||
boolean anyKey = false;
|
||||
boolean hasUnscanned = false;
|
||||
for(int i = 0 ; i < KeyCount; i++) {
|
||||
KeyDesc& keyDesc = Keys[i];
|
||||
hasUnscanned |= !keyDesc.scanned;
|
||||
int pinAsInput = -1;
|
||||
if (keyDesc.pin1 == pinAsOutput) {
|
||||
pinAsInput = keyDesc.pin2;
|
||||
} else
|
||||
if (keyDesc.pin2 == pinAsOutput) {
|
||||
pinAsInput = keyDesc.pin1;
|
||||
}
|
||||
if (pinAsInput > 0 && is_input_allowed(pinAsInput) && !keyDesc.scanned) {
|
||||
anyKey = true;
|
||||
go_pu(PinToIO[pinAsInput]);
|
||||
}
|
||||
}
|
||||
// if no unscanned keys found, break
|
||||
if (!hasUnscanned) {
|
||||
break;
|
||||
}
|
||||
// if no keys for this pin found, next loop
|
||||
if (!anyKey) {
|
||||
continue;
|
||||
}
|
||||
// logic LOW will set this to active
|
||||
go_0(PinToIO[pinAsOutput]);
|
||||
// delay to settle
|
||||
delayMicroseconds(10);
|
||||
// read state
|
||||
for(int i = 0 ; i < KeyCount ; i++) {
|
||||
KeyDesc& keyDesc = Keys[i];
|
||||
int pinAsInput = -1;
|
||||
if (keyDesc.pin1 == pinAsOutput) {
|
||||
pinAsInput = keyDesc.pin2;
|
||||
} else
|
||||
if (keyDesc.pin2 == pinAsOutput) {
|
||||
pinAsInput = keyDesc.pin1;
|
||||
}
|
||||
if (pinAsInput > 0 && !keyDesc.scanned) {
|
||||
keyDesc.scanned = true;
|
||||
int keyCode = keyDesc.keyCode;
|
||||
int keyCode2 = keyDesc.keyCode2;
|
||||
boolean useCode2 = keyCode2 != 0 && is_mod_pressed(SECOND_CODE);
|
||||
int currentValue = digitalRead(PinToIO[pinAsInput]);
|
||||
if (!currentValue) {
|
||||
// new key pressed
|
||||
if (keyDesc.isModifier) {
|
||||
if (load_mod(keyCode)) {
|
||||
d_print("Mod pressed: %s",keyDesc.name);
|
||||
send_mod();
|
||||
}
|
||||
} else {
|
||||
// if must use code2, then release keyCode and substitute keyCode with second code
|
||||
// then release SECOND_CODE, then press code2, then re-press SECOND_CODE
|
||||
if (useCode2) {
|
||||
if (load_slot(keyCode2)) {
|
||||
d_print("Code 2 pressed: %s",keyDesc.name);
|
||||
clear_mod(SECOND_CODE);
|
||||
send_mod();
|
||||
send_normals();
|
||||
load_mod(SECOND_CODE);
|
||||
send_mod();
|
||||
}
|
||||
} else {
|
||||
// normal way
|
||||
if (load_slot(keyCode)) {
|
||||
d_print("Normal pressed: %s",keyDesc.name);
|
||||
send_normals();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // key released
|
||||
if (keyDesc.isModifier) {
|
||||
if (clear_mod(keyCode)) {
|
||||
d_print("Mod released: %s",keyDesc.name);
|
||||
send_mod();
|
||||
}
|
||||
} else {
|
||||
if (useCode2) {
|
||||
if (clear_slot(keyCode2)) {
|
||||
d_print("Code 2 released: %s",keyDesc.name);
|
||||
send_normals();
|
||||
}
|
||||
} else {
|
||||
// normal way
|
||||
if (clear_slot(keyCode)) {
|
||||
d_print("Normal released: %s",keyDesc.name);
|
||||
send_normals();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// disable pin
|
||||
go_z(PinToIO[pinAsOutput]);
|
||||
}
|
||||
//
|
||||
// **********keyboard scan complete
|
||||
//
|
||||
// Turn on the LED on the Teensy for Caps Lock based on bit 1 in the keyboard_leds variable controlled by the USB host computer
|
||||
//
|
||||
if (is_mod_pressed(MODIFIERKEY_LEFT_SHIFT) || is_mod_pressed(MODIFIERKEY_RIGHT_SHIFT)) { // mask off all bits but D1 and test if set
|
||||
go_1(LED_BUILTIN); // turn on the LED
|
||||
} else {
|
||||
go_0(LED_BUILTIN); // turn off the LED
|
||||
}
|
||||
//
|
||||
delay(25); // The overall keyboard scanning rate is about 30ms
|
||||
}
|
BIN
Commodore_64/Readme.pdf
Normal file
BIN
Commodore_64/Readme.pdf
Normal file
Binary file not shown.
Loading…
Reference in a new issue