It's finally here! After years of anticipation and a weird workaround, the ideal solution is implemented and working. I can finally use my Palm Portable Keyboard (PPK) with my custom emulators for Commodore 8-bits. Github: ppk_bluetooth_for_cbm
![]() |
| PPK BLE adapter for wearable/portable emulators of 8-bit CBM systems |
History
The Palm Portable Keyboard was released for the Palm Pilot PDA lineup in late 1999. I remember getting mine right away for US$99 from Circuit City. The Palm IIIc came out in early 2000 and got one of those too. To date my longest use was to write up notes on a plane ride. (Let's just not think too much about me leaving/losing the keyboard in the seatback pocket. Ouch! Rushed out and got a replacement at $99.) Back in the day, it was mostly for the cool factor. I loved gadgets, and between the Palm III color and the keyboard, and the Kodak color camera, I had some pretty cool gadgets. I knew I was cool, even if no one else believed.
Fast forward to 2020 when I'm enjoying building emulators for Commodore 64, 128, and Vic-20 on wearable and portable platforms based on ESP32 and similar. One real need was to input into these devices. With the STM32F4 I had gotten USB-OTG to work, and mapped a standard USB keyboard to trick the Commodore into thinking a normal matrix keyboard was present. The Teensy 4.1 target was a direct port of that keyboard code as it had an optional external USB host port. Also worth a mention of leveraging the same algorithms and data to support keyboard mapping with my Typescript port.
![]() |
| STM32F4 with USG OTG |
Once I had a wearable emulator on my wrist, I also looked for keyboard solutions. On one July 4th holiday vacation I was able to research and implement a web page helper that translated keystrokes in the keyboard and sent them as Commodore scan codes over USB serial to the emulated system. And I also found a way to leverage this on my Android phone so it would host the web page and transmit over its USB serial (OTG) to the emulated target host.
![]() |
| Wires and phone required in 2023 |
More development later, and I had an adapter for a real Commodore keyboard to serial TX line (plus 5V/GND input), that could plug into the Grove connector of the M5Stack targets. Sure it was fun to plug in a real C128D keyboard into a system with a 2" LCD; quite the show off I am, looking for a good laugh. But it also worked!
More work (and purchases) later and I had M5Stack's CardKB keyboard, and wrote drivers for that to convert to scan code presses and releases for Commodore.
And then I created a Bluetooth (BLE) adapter to convert serial/I2C connections to a wireless connection. The keyboard and the wrist emulator could be used with direct wiring. Much to the delight of portability and more showing off.
External Commodore Keyboard Scan Code Protocol
Out of necessity, a standardized protocol was born by accident. Standardized to my implementations only so far, but I was for sure the beneficiary of such technological advance.
The protocol depends on two features:
1. Serial transmission of changes
2. List of Commodore 64/128 scan code values, comma separated, newline (serial only) terminated
Example:
15,7
which means left shift and up/dn key (= cursor up)
The emulators targets (see Unified branch of github.com/davervw/c-simple-emu6502-cbm) support this protocol over USB serial, Grove port (UART RX), and custom BLE service depending on hardware capabilities. Internally the list of scan codes is used to provide feedback from I/O read/write processing from the 6502 checking to see what lines are connected. So while I could have implemented a more binary or compact format of transmitting this data, I enjoy the diagnostic capability of seeing the values clearly when necessary.
The keyboard hosts utilizing this protocol include the key scan codes helper for the web (USB serial out), two instantiations of 25-pin matrix to UART TX supporting real Commodore keyboards, and a BLE bridge firmware with a Grove connector (e.g. on M5Stick-C).
The scenarios that work include
1. Type from my Windows keyboard, adapted to scan codes sent over USB serial (any of the targets). Keyboard and target are both wired via USB. A web page is making the translation and bridging between the keyboard and USB serial.
2. Connect Commodore keyboard adapter directly to Grove port on one of the various M5Stack devices: M5Core, M5Core2, M5CoreS3, Tab5. This looks like a Commodore keyboard wired through a mess so tied to the target.
3. BLE adapter takes scenario #2 and cuts the wire between the adapter mess and the target. The target appears free and clear of any wires (if self powered). The adapter can be tucked into/under/next to the keyboard. While this acts as a Commodore BLE keyboard, the keyboard itself has a mess of wires, power supply, and adapters.
The BLE adapter actually accepts THREE different inputs. USB serial (from PC host), Grove UART RX, and Grove I2C for CardKB). Note that CardKB isn't using my keyboard standard as an input because it has its own protocol, and I didn't feel like reprogramming it. CardKB drivers are in both the BLE adapter, and in the emulator itself for supporting direct connection. Both CardKB uses are converting and outputting the Commodore scan codes internally.
4. USB host adapter takes a standard USB keyboard and converts to UART TX. This can be cross wired from Grove port to Grove port, or be used in conjunction with #3 (great!! more adapters to the mess) to appear as a USB to BLE wireless adapter.
So I've created an ecosystem of keyboard compatibility built on a custom "standard" so parts can work together and interchange/swap. It allows for flexibility, and interconnections. And when a new keyboard input source comes along (like PPK), implementing the current standard brings extra value to the table.
PPK BLE adapter firmware customized for Commodore
The pre-existing firmware for the Bluetooth adapter as developed by pymo took the obvious choice - present as a standard Bluetooth HID keyboard. That solution works for Windows, Mac, Android, iPhone, and others. It's a great standard. But it doesn't directly translate to a great Commodore keyboard experience. And I don't have a general BLE HID solution integrated into my emulators yet either.
With the way things are with my custom Commodore scan code protocol, it made sense to revise the PPK BLE adapter directly, take advantage of all keys present including Fn and special purpose keys, and map them to what makes sense for Commodore. And add extra value too!
Let's compare to the layout of my favorite Commodore system
These are the symbolic key mappings I came up with
Reference
- Fn Backspace and Fn Del maps to Home key for moving cursor to upper left on Commodore
- Fn Shift Backspace and Fn Shift Del map to Clear key to erase Commodore screen
- Fn = toggles NumLock mode, sends unique C128 scan codes for numeric keypad, Enter, and arrow keys. Hold a key with Fn to send the opposite scan code if necessary.
- Fn LShift RShift toggles shift lock mode, mimicking the positional switch on Commodore
- Caps acts as a toggle switch to represent the positional switch on the Commodore 128. Whether letters are shifted (capitalized), and punctuation is not shifted is the job of the C128 ROM.
- Fn Done is Esc
- Alt works only in C128 mode of the emulator
The end result is a full-featured Commodore 128 keyboard for use with Commodore 128 emulation. (And some standard ASCII keys [{}~`|] not present with Commodore, so more useful in non-Commodore emulation). And by the way, the Commodore 64 and Vic-20 emulations map the extra C128 keys to its own matrices automatically -- unlike a real Commodore 128, etc. For instance, the four arrow keys and numeric keypad don't work in C64 mode on a real C128, but they do in the emulated system -- appearing as if the original 64 key matrix keys were pressed instead. This is implemented in the emulator itself. The keyboard is optimistic and reports everything expecting a C128 on the other end. The emulator maps extra keys down to C64 keys, and if in Vic-20 mode, unscrambles into the Vic-20 scan codes too.
(C64 and Vic-20 share the same exact keyboard, but the lines were reordered when connected to the I/O chips. The same keyboard would work in the C128 except for the missing keys - the C128 is a superset. How do I know this? I use both a real Vic-20 and real C128D keyboard interchangeably connected to my self designed Commodore to UART Tx [Grove] adapter, and they work interchangeably in my emulator. How cool would it be to build a C128D replacement keyboard from a Vic-20 keyboard in case? That would blow some minds.)
Operation
1. Plug in the 3D printed Bluetooth adapter and circuit into the PPK to automatically turn it on and start transmitting that it is in pairing mode (rapid Green flashes).
2. Turn on or reset the Commodore Emulated system (e.g. M5CoreS3 or Sunton)
3. Wait for Commodore to boot
4. Should be paired (occasional Green flashes)
5. Type away!
![]() |
| Sunton 7" tablet (Perler bead frame) and PPK BLE |






