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
Diff: emuc64.cpp
- Revision:
- 9:a0c6747e539f
- Parent:
- 7:dce21deeac6c
- Child:
- 10:95591a8ad254
--- 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);