C64 emulation on STM32F429 Discovery board with builtin LCD and USB keyboard support (OTG). More info at davevw.com and/or github.com/davervw

Dependencies:   LCD_DISCO_F429ZI BSP_DISCO_F429ZI USBHOST

Files at this revision

API Documentation at this revision

Comitter:
davervw
Date:
Thu Apr 16 06:38:02 2020 +0000
Parent:
8:d356d6930bdb
Child:
10:95591a8ad254
Commit message:
1.3 - keyboard RESTORE (NMI) implemented

Changed in this revision

emu6502.cpp Show annotated file Show diff for this revision Revisions of this file
emu6502.h Show annotated file Show diff for this revision Revisions of this file
emuc64.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/emu6502.cpp	Wed Apr 15 05:34:25 2020 +0000
+++ b/emu6502.cpp	Thu Apr 16 06:38:02 2020 +0000
@@ -70,7 +70,7 @@
 }
 #endif
 
-static void PHP()
+extern void PHP()
 {
 	int flags = (N ? 0x80 : 0)
 		| (V ? 0x40 : 0)
--- a/emu6502.h	Wed Apr 15 05:34:25 2020 +0000
+++ b/emu6502.h	Thu Apr 16 06:38:02 2020 +0000
@@ -60,6 +60,7 @@
 extern void Execute(ushort addr, bool (*ExecutePatch)(void));
 extern void Push(int value);
 extern byte Pop(void);
+extern void PHP();
 extern void DisassembleLong(ushort addr, bool *p_conditional, byte *p_bytes, ushort *p_addr2, char *dis, int dis_size, char *line, int line_size);
 extern void DisassembleShort(ushort addr, bool *p_conditional, byte *p_bytes, ushort *p_addr2, char *dis, int dis_size);
 extern byte LO(ushort value);
--- a/emuc64.cpp	Wed Apr 15 05:34:25 2020 +0000
+++ b/emuc64.cpp	Thu Apr 16 06:38:02 2020 +0000
@@ -79,11 +79,13 @@
 //static int startup_state = 0;
 //LocalFileSystem local("local");
 
+// array allows multiple keys/modifiers pressed at one time
 static int scan_codes[9] = { 64, 64, 64, 64, 64, 64, 64, 64, 64 } ;
 
 // USB key code to C64 keyboard scan code, plus shift modifiers
 // +256 means to apply L.Shift
 // -512 means to take away Shift
+// +1024 means to apply RESTORE
 static int usb_to_c64[2][100] = {
 { // normal/other modifier
 	64, 64,	64,	64, 10, 28, 20, 18, 14, 21, // na, na, na, na, a, b, c, d, e, f
@@ -93,7 +95,7 @@
 	1, 63, 0, 58, 60, 43, 53, 256+45, 256+50, 48, // RET, STOP, DEL, CTRL, SPC, -, =, [, ], £
 	64, 50, 256+24, 64, 47, 44, 55, 64, 4, 256+4, // na, ;, ', na, ,, ., /, na, f1, f2
 	5, 256+5, 6, 256+6, 3, 256+3, 64, 64, 64, 64, // f3, f4, f5, f6, f7, f8, na, na, na, na
-	64, 64, 63, 256+0, 51, 64, 0, 64, 64, 2, // na, na, STOP, INS, HM, na, DEL, na, na, RT
+	1024+64, 64, 63, 256+0, 51, 64, 0, 64, 64, 2, // RESTORE, na, STOP, INS, HM, na, DEL, na, na, RT
 	256+2, 7, 256+7, 64, 55, 49, 43, 40, 1, 56, // LT, DN, UP, na, /, *, -, +, ENTER, 1
 	59, 8, 11, 16, 19, 24, 27, 32, 35, 44 // 2, 3, 4, 5, 6, 7, 8, 9, 0, . (keypad)
 },
@@ -105,18 +107,22 @@
 	1, 63, 0, 58, 60, 512+57, 512+40, 256+45, 256+50, 48, // RET, STOP, DEL, CTRL, SPC, L.Arrow, +, [, ], £
 	64, 512+45, 256+59, 64, 47, 44, 55, 64, 4, 256+4, // na, :, ", na, ,, ., /, na, f1, f2
 	5, 256+5, 6, 256+6, 3, 256+3, 64, 64, 64, 64, // f3, f4, f5, f6, f7, f8, na, na, na, na
-	64, 64, 63, 256+0, 51, 64, 0, 64, 64, 2, // na, na, STOP, INS, HM, na, DEL, na, na, RT
+	1024+64, 64, 63, 256+0, 51, 64, 0, 64, 64, 2, // RESTORE, na, STOP, INS, HM, na, DEL, na, na, RT
 	256+2, 7, 256+7, 64, 55, 49, 43, 40, 1, 56, // LT, DN, UP, na, /, *, -, +, ENTER, 1
 	59, 8, 11, 16, 19, 24, 27, 32, 35, 44 // 2, 3, 4, 5, 6, 7, 8, 9, 0, . (keypad)
 }
 };
 
+// Resources
+// See Keyboard/Keypad Page (0x07) of https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
+// See Commodore 64 Keycodes in Appendix of https://archive.org/details/Compute_s_Mapping_the_64_and_64C/
+
 // The initial goal of the keyboard tables and logic is to provide access to at 
 // least the following keys from a standard USB keyboard, symbolic mapping more 
 // like a PC (not positional)
 // USB keyboard support is provided by USBHOST library and STM32F429 BSP
 //
-// STOP(ESC) F1 F2 F3 F4 F5 F6 F7 F8                                  Run/Stop(Pause/Break)
+// STOP(ESC) F1 F2 F3 F4 F5 F6 F7 F8            Restore(PrtScr/SysRq) Run/Stop(Pause/Break)
 //           1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ += Del/Ins(Back)    Ins Hme/Clr     / * -
 // Ctrl(Tab) Q  W  E  R  T  Y  U  I  O  P  [  ]  £ (\)            Del           7 8 9 +
 //           A  S  D  F  G  H  J  K  L  ;: '" Return(ENTER)                     4 5 6
@@ -145,17 +151,17 @@
 	if (len == 8)
 	{ 
 		if ((data[0] & 0x11) != 0) // PC Ctrl => Commodore
-			scan_codes[6] = 61;
+			scan_codes[6] = 61; // usb hid buffer supports 6 simultaneous keys, put modifier in next available slot
 		else
 			scan_codes[6] = 64;
 			
 		if ((data[0] & 2) != 0) // LShift
-			scan_codes[7] = 15;
+			scan_codes[7] = 15; // usb hid buffer supports 6 simultaneous keys, put modifier in next available slot
 		else
 			scan_codes[7] = 64;
 			
 		if ((data[0] & 0x20) != 0) // RShift
-			scan_codes[8] = 52;
+			scan_codes[8] = 52; // usb hid buffer supports 6 simultaneous keys, put modifier in next available slot
 		else
 			scan_codes[8] = 64;
 
@@ -163,23 +169,27 @@
 	    {
 			if (data[i+2] < 100)
 			{
-				scan_codes[i] = usb_to_c64[((data[0] & 0x22) != 0) ? 1 : 0][data[i+2]]; // L.Shift/R.Shift handled by a different table
+				scan_codes[i] = usb_to_c64[((data[0] & 0x22) != 0) ? 1 : 0][data[i+2]]; // Normal vs. Shift
 				if ((scan_codes[i] & 256) != 0)
 					scan_codes[7] = 15; // LShift
-				if (i==0 && (scan_codes[i] & 512) != 0)
+				if (i==0 && (scan_codes[i] & 512) != 0) // remove shift flag works only if key is first non-modifier pressed
+				{
 					scan_codes[7] = 64; // No LShift
-				scan_codes[i] &= 127; // take out shift codes
-				//printf(" %d", scan_code);
-				fflush(stdout);
+					scan_codes[8] = 64; // No RShift
+				}
+				if (scan_codes[i] != 64)
+				{
+					printf(" %d", scan_codes[i]);
+					fflush(stdout);
+				}
 			}
 			else
 				scan_codes[i] = 64;
 		}
-			
-//		printf("C64 scan_code = %d\n", scan_code);
 	}
 }
 
+// CREDIT: keyboard_task() borrowed from USBHOST sample program main.cpp at https://os.mbed.com/teams/ST/code/Nucleo_usbhost/
 void keyboard_task(void const *)
 {
     USBHostKeyboard keyboard;
@@ -252,8 +262,31 @@
 //	return result;
 //}
 
+// remembering state because NMI is edge triggered false->true
+static bool NMI = false;
+
 bool ExecutePatch(void)
 {
+	int found_NMI = 0;
+	for (int i=0; !found_NMI && i<9; ++i)
+		if (scan_codes[i] == 1024+64)
+			found_NMI = 1;
+	
+	if (NMI)
+	{
+		if (!found_NMI)
+			NMI = false; // reset when not pressed
+	}
+	else if (found_NMI) // newly pressed, detected edge
+	{
+		NMI = true; // set so won't trigger again until cleared
+		Push(HI(PC));
+		Push(LO(PC));
+		PHP();
+		PC = (ushort)(GetMemory(0xFFFA) + (GetMemory(0xFFFB) << 8)); // JMP(NMI)
+		return true; // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc.
+	}
+	
 //	if (PC == 0xFFD2) // CHROUT
 //	{
 //		CBM_Console_WriteChar((char)A);
@@ -1119,10 +1152,11 @@
 			
 			for (int i=0; i<9; ++i)
 			{
-				if (scan_codes[i] < 64)
-				{
-					int col = scan_codes[i] / 8;
-					int row = scan_codes[i] % 8;
+				int scan_code = scan_codes[i] & 127; // remove any modifiers
+				if (scan_code < 64)
+				{			
+					int col = scan_code / 8;
+					int row = scan_code % 8;
 					
 					if ((io[0xC00] & (1 << col)) == 0)
 						value |= (1 << row);
--- a/main.cpp	Wed Apr 15 05:34:25 2020 +0000
+++ b/main.cpp	Thu Apr 16 06:38:02 2020 +0000
@@ -49,7 +49,7 @@
 {
     printf("\n");
     printf("C64-stm429_discovery\n");
-	printf("C64 Emu6502 (for STM32F429 Discovery), version 1.2\n");
+	printf("C64 Emu6502 (for STM32F429 Discovery), version 1.3\n");
 	printf("Copyright (c) 2020 by David R. Van Wagner\n");
 	printf("Open Source - MIT License\n");
 	printf("github.com/davervw\n");