Showing posts with label ESP32. Show all posts
Showing posts with label ESP32. Show all posts

Saturday, August 15, 2026

Touch points and buttons on M5Core 2" displays, Tab 5" display, and Sunton 7" display for keyboard emulation


I have targeted the following M5 Stack models with my C64/C128/Vic-20/Apple 1 emulator:

(Even though I have targeted other boards, I had only implemented touch on the CoreS3)

The primary reason for targeting these boards was the common 2" 320x240 display perfect for most C64 emulation, and the availability of a wristband that works with Core2 and CoreS3 (it works with the Fire if and only if you never need to charge the battery - not aware of a universe where that works out long term).

[aside... Originally I had supported the M5 Core Basic, but without PSRAM, it was difficult to support the different computer models that currently load into that memory.  So M5 Core BASIC was dropped after its initial development.]

The Basic and Fire have three UI hardware buttons.   The Core2 has three virtual touchscreen buttons (touchscreen expands farther down from the LCD screen to allow for capacitive touch button points, and the M5 library abstracts them similar to physical buttons, so your code doesn't even have to know the difference).  The CoreS3 has no UI buttons, but I've manually implemented virtual touch screen buttons at the bottom of the screen.   From left to right the buttons are known to M5 as A, B, and C.

So button support for Basic, Fire, and Core2 was straightforward.

  • press Button A: Cursor UP
  • press Button B: RETURN
  • press Button C: Cursor Down
With hold functionality as well.
  • hold Button A: toggle computer model (C64, C128, Vic-20, Apple 1, repeats)
  • hold Button B: LOAD"*",8 / RUN for Commodore, snapshot system for Apple 1
  • hold Button C: STOP
Thus, one can demonstrate the emulator loading a menu of programs, scrolling though the listing, and choosing one.  And toggle between the emulators.   The Apple 1 snapshot system allows choosing a snapshot and loading or saving it.

I support other hardware targets, and I have BLE pairing functionality.  So I am thinking of expanding support of the virtual buttons, including more virtual buttons, and providing 8-position joystick inputs (and button) too.  But for now, here is the documentation for the existing buttons.

And then just like that, the CoreS3, Tab5, and Sunton 7" now have more touch points implemented for their capacitive touch screens to allow for more virtual keys.




Sunday, May 17, 2026

Gamepad Test

 


My goal is to play some games on ESP32 hardware.  One step to get there is create a test app to pair with existing game controllers.

Classic (not the newest) ESP32 boards support Bluetooth Classic and BLE.   ESP32-S3, C3, C6 for examples only support BLE.  ESP32-P4 doesn't support wireless directly at all, it uses a C6 as a wireless coprocessor.  Thus it's useful to see what controllers you can attach.

Instructions:
Auto binds to pairing device
gampad activity shows here
and see serial monitoring
for more devices & info

Sunday, September 15, 2024

No name IPS 240*240 ST7789 TFT display with Arduino GFX Library and ESP32-C3 (RISC-V) development board

 

This is an alternative take on the previous article Adafruit ST7789 TFT display with Arduino GFX Library and M5StampS3.   This time with a generic display, and a different MCU (ESP32-C3).  This one has a single RISC-V core (instead of dual core Xtensa).

So excuse the repeated text, the content has been changed only slightly for the different hardware...


Attaching a display to a circuit can provide a lot of detailed info and graphical value.  While "a picture is worth a thousand words," an animated display can be entertainment value, textual information can be informative, and add an input device, and the system can be interactive with billions of possibilities.

The tricks in embedded development is choosing the right display, having the right library that supports the display, and figuring out to use it all together with your target embedded system.

Shown above is a minimal footprint ESP32-C3 development board (I purchased one from AliExpress for around two US dollars, very cheap!), with a generic IPS 240x240 TFT display (ST7789 based) I had purchased years ago on eBay.  An SPI interface is utilized for communications using the GFX Library for Arduino.  I am using a solderless breadboard to prototype the circuit.  Later I will implement as a more permanent circuit.

Besides power and ground, there are only 4 connections from the ESP32: SCLK, MOSI, DC, and Reset.  In this sample, the TFT select line is permanently selected by connecting to ground.

#include <Arduino.h>
#include <Arduino_GFX_Library.h>

Arduino_DataBus *bus = new Arduino_HWSPI(6/*dc*/, 7/*cs*/,
   2/*sclk*/, 3/*mosi*/, 10/*miso*/, &SPI,
   true/*is_shared_interface*/);
Arduino_GFX *gfx = new Arduino_ST7789(bus, 11/*rst*/, 1/*r*/,
   true/*ips*/, 240, 240);

void setup() {
  gfx->begin();
  gfx->fillScreen(BLACK);
  gfx->setTextColor(WHITE);
}

void loop() {
  int x = (int)random(240);
  int w = (int)random(240 - x);
  int y = (int)random(240);
  int h = (int)random(240 - y);  
  int color = (int)random(65536);
  gfx->fillRect(x, y, w, h, color);
  if (random(20)==13)
    delay(100);
}

The wiring corresponds to the code of the databus and gfx initialization parameters, specifically lines GPIO02 (SPI CLK), GPIO03 (SPI MOSI), GPOI06, GPIO11 of the ESP32-C3 connected to SCL, SDA, DC, and RES (Reset) of the display respectively.  Also both the VCC and BLK lines of the display are connected to 3V3, and GND is connected commonly between the display and ESP32-C3 board.  MISO and CS lines are defined for use in the code, but wiring them was unnecessary and not possible.

TFT   ESP32-C3
GND   Ground
VCC   3V3
SCL   SPI Clock (2)
SDA   SPI MOSI (3)
RES   (11)
DC    (6)
BLK   3V3

Not sure why triangles are sometimes displayed (maybe out of range data?).  That is why there is a 5% chance of a tenth of a second delay to pause for the viewer.

This is just a demo.  You should be able to find much better uses for the display that these random rectangles.

Build details:
  • Arduino IDE 2.3.2
  • esp32 boards 3.0.4
  • GFX Library for Arduino 1.4.7
Important!  The board I have will only run its flash chip in DIO mode, so be sure to check all the board options in Tools menu of Arduino IDE before flashing, or if you run into trouble.  Also, updating board libraries may reset your options to default so if flashing after a time, check these settings again, and again.

Some models of the ESP32-C3 development board have a serial chip, and some utilize the C3's built in USB support.  Be sure to set USB CDC on Boot settings accordingly, and use the BOOT/RST buttons to put into bootloader mode for flashing if necessary.

I found it necessary to unplug and replug the ESP32-C3 board to get the graphic demo to work.  Your mileage may vary.

Sunday, September 8, 2024

Adafruit ST7789 TFT display with Arduino GFX Library and M5StampS3

 


Attaching a display to a circuit can provide a lot of detailed info and graphical value.  While "a picture is worth a thousand words," an animated display can be entertainment value, textual information can be informative, and add an input device, and the system can be interactive with billions of possibilities.

The tricks in embedded development is choosing the right display, having the right library that supports the display, and figuring out to use it all together with your target embedded system.

Shown above is a minimal footprint ESP32S3 in the form of an M5StampS3 from M5Stack connected to 2.54mm pins, with a rounded corner ST7789 based 280x240 display from Adafruit.  An SPI interface is utilized for communications using the GFX Library for Arduino.  I am using a solderless breadboard to prototype the circuit.  Later I will implement as a more permanent circuit.

Besides power and ground, there are only 4 connections from the ESP32: SCLK, MOSI, DC, and Reset.  In this sample, the TFT select line is permanently selected by connecting to ground.

(The Adafruit display used in this example also includes a MicroSD connector and SPI connections for that as well.  Support for SD is beyond the scope of this article, and would require additional changes to the circuit and code.)

#include <Arduino.h>
#include <Arduino_GFX_Library.h>
Arduino_DataBus *bus = new Arduino_HWSPI(1/*dc*/,
  GFX_NOT_DEFINED/*cs*/, 7/*sclk*/, 5/*mosi*/,
  GFX_NOT_DEFINED/*miso*/, &SPI, true/*is_shared_interface*/);
Arduino_GFX *gfx = new Arduino_ST7789(bus, 3/*rst*/, 1/*r*/,
  true/*ips*/, 240, 320);

void setup() {
  gfx->begin();
  gfx->fillScreen(BLACK);
  gfx->setTextColor(WHITE);
}

void loop() {
  int x = 20 + (int)random(280);
  int w = (int)random(300 - x);
  int y = (int)random(240);
  int h = (int)random(240 - y);  
  int color = (int)random(65536);
  gfx->fillRect(x, y, w, h, color);
  if (random(20)==13)
    delay(100);
}

The wiring corresponds to the code of the databus and gfx initialization parameters, specifically lines 1, 3, 5, 7 of the M5StampS3 connected to DC, RT (reset), SI (serial in), and CK (clock) of the display.  Also the displays V+ line is connected to 5V, and both TC and G (Ground) are connected to ground common to the ESP32 S3.

TFT   StampS3
V+    5V
3V    NC
G     Ground
CK    SPI Clock (7)
SO    NC
SI    SPI MOSI (5)
TC    Ground
RT    (3)
DC    (1)
CC    No Connection
BL    No Connection

It appears there is an overscan issue, beyond the rounded corners.  The gfx object is defining 320x240 display instead of 280x240, and the position and sizes of the rectangles are also interesting here.

Not sure why triangles are sometimes displayed (maybe out of range data?).  That is why there is a 5% chance of a tenth of a second delay to pause for the viewer.

This is just a demo.  You should be able to find much better uses for the display that these random rectangles.

Build details:
  • Arduino IDE 2.3.2
  • esp32 boards 3.0.4
  • GFX Library for Arduino 1.4.7

Sunday, August 25, 2024

Wireless controller adapter for Commodore

 


It's August 2024.  I've just bought a new (to me) Vic-20 for US$50 to replace my childhood one.  I already have the PenUltimate Vic-20 Cartridge with a ton of games.  I also bought a Hyperkin Trooper joystick.  But I want to game wirelessly!

I've already had great success with a BlueRetro Nintendo GameCube controllers wireless adapter with my original Wii game console.  I purchased it on ebay for a good price and it worked great.

But I wanted to go back further to replacing an Atari joystick on my Commodore Vic-20 that has a DB-9 connector.  Searching the Internet, it looks like BlueRetro internally supports Atari 7800 with a 2-player mode, and there is a single player version available for sale on Amazon for about $25.  Also the ESP 32 firmware source code is available as open source.

Having experience developing with ESP32, and a plethora of electronic parts already at my disposal, I did what any enterprising consumer would do -- I purchased additional parts from AliExpress.  I mean, you can't have enough electronic parts, can you?  Okay, I could've done it completely from scratch but my time is valuable, I have only so much energy at the end of the day, and cheating my way to success is legal here.   So we're doing it halfway.

First I bought the BlueRetro Core.  It provides the base functionality with a DB-25 connector for all its pins.  It is designed to allow connector adapters to be wired to various console systems.  It is a very creative and functional design.  And there are adapters available for many of the common systems.  But I didn't have any luck finding Atari connectors.

But no problem!  I can build my own!  So I found a DIY screw terminal DB25 male connector with the correct optional mating screws, and the counterpart DB9 female connector with screw terminals.  The only trick left is to wire it up.

Steps

  1. Connect BlueRetro Core to USB power adapter (don't require direct connection to computer)
  2. Download latest firmware ZIP via link provided on BlueRetro support site
  3. Unzip, and look for the parallel 2P firmware (1P should work fine too, skip the 3V3 versions.
  4. Follow flashing firmware instructions from BlueRetro support site
  5. Pair a supported wireless controller (I'm using an Xbox One Bluetooth compatible controller)
  6. Plug BlueRetro Core into the DB25 breakout
  7. Connect a voltage meter to ground on the breakout, and then test the voltage at each remaining pin with and without pressing a button (e.g. DPAD up/down/left/right, and A)
  8. Write down the DB25 pin numbers and the names of the controller functions
  9. Unplug the core, and power off for now
  10. Search the internet for the DB9 pin numbers for Atari joystick connector pinout so you have their functions handy
  11. Cut and strip ends of 8 wires of different colors long enough to connect the DB9 and DB25 breakouts
  12. Be sure to first feed the wires through the included rings, and confirm their orientation.
  13. Then connect the appropriate functions: up, down, left, right, fire, framing ground, signal ground, and voltage in  (VIN) to +5V supply from Commodore/Atari
  14. Minimally connect, and test the functionality first with meter, then with Commodore/Atari console
  15. Once verified working, finish connecting wiring stress-relief, bolt the enclosures closed, and otherwise button-up and tidy up the solution.
  16. Play games!
DB25-1   to DB9-4   (right)
DB25-4   to DB9-3   (left)
DB25-GND to DB9-GND (frame ground)
DB25-7   to DB9-7   (VIN to +5V)
DB25-8   to DB9-8   (signal ground)
DB25-13  to DB9-6   (fire)
DB25-15  to DB9-1   (up)
DB25-17  to DB9-2   (down)

Another link to support this wiring is the BlueRetro Hardware Design documented over at hackaday.  There are schematics showing signal ground and VIN with the DB25 pinout.

I had fun with this effort, and should be able to expand this effort to support a second controller simultaneously connected to the same core, or wire up adapters for other systems myself.

The cost of the solution for me was about $22 with shipping, and as I was careful to choose items shipped directly from AliExpress and live on the west coast of USA, received the items quickly in about a week.  While this didn't save me the labor and only saved $3 from the Amazon solution, I learned a lot and feel comfortable leveraging the result to make solutions for other consoles and a second player.

(Any of you worried about 5V tolerance on the ESP32 or the buffer chip included with BlueRetro Core?  The Commodore is at 5V, and while the ESP32 is powered by 5V its IO is exclusively 3.3V.  It works for me without any additional consideration, but your mileage or concerns may vary.  You can usually get away with it for ESP32 as many of the IO are designed to survive 5V, and a 3.3V high signal does read as a high signal with most 5V systems.  So am I just getting away with it?  Maybe.)

But wait! Some keyboard lines are not working. I'm not done yet!

So with some prototyping, it turned out that the circuit to the Vic-20 needed to be open drain instead of push-pull. Pulling down was fine, but something was amiss with pushing 3.3V (or even 5V with other attempts) from the ESP32 BlueRetro Core circuit.

How does an Atari style joystick work anyways? There are 4 directions and one extra button. When any of them are active, the associated line is connected by a switch to ground. The BlueRetro Core simulates this by pulling to ground just fine, but when idle, it is pushing 3.3V. And the Vic-20 has its own 5V pull ups. That does sound messy. Somehow (without looking at the various schematics) this appears to cause a conflict so the 2, 4, etc. and F7 keys for example don't work anymore, they can't pull down to ground when this joystick circuit is attached.

So let's think how to correct this.  We want the connection to ground when the joystick is active, but we want high impedance (appear disconnected) when the no direction or selection is made.

The solution is a circuit that can perform this.  At first I'm thinking I don't have any FETs left over from previous projects, but finally after using one of my go-to buffer chips in breadboard circuits trying to solve this thing, I finally remembered that instead of being annoyed there are enable inputs for each buffer, the enable inputs can function as the inputs from the BlueRetro Core.   They are enable low, so when the joystick selection is made, the circuit will connect, and can take a grounded low input and buffer that to the Vic-20 joystick port.   So when the button or movement is made, the circuit will be grounded low, but otherwise that individual circuit is disabled (high impedance) as if the switch is not connected.  And this separates the 5V Vic-20 circuit from the 3.3V BlueRetro Core (ESP32) circuit.  And best of all, testing on breadboard, it works great!   The keyboard is now functioning normally with the joystick circuit powered and connected, and is still self powered from the Vic-20.

The revision to the above wiring is to connect DB25 joystick lines to OE/ lines of a SN74AHC125N, connect ground to the A lines, and connect the Y lines to the appropriate DB9 joystick lines. Also connect 5V power (14) and ground (7) to the appropriate IC pins.  And since there are five joystick lines, and this is only a quad (4) buffer part, we're gonna need two of them (and three if extending to two joysticks for dual player such as with a C64 or Atari 2600 VCS).  I recommend setting the unused enable lines for the extra buffers high (5V) to disable their outputs.

Again, these buffers are only for up/down/left/right/fire(select).   The voltage and ground wires should be wired between the DB25 and DB9 without buffering.


Saturday, December 9, 2023

Commodore keyboards go wireless for my portable emulators

The c-simple-emu6502-cbm project supports a number of ESP32 platforms to provide a subset of Commodore C64 (and Vic-20, C128) emulation, and many currently include BLE keyboard support.  Originally for CardKB only, now I have added BLE support for Commodore keyboards (20 to 25 pins) to the m5, T-Display-S3, and ESP32-8048S070-7inch ports/branches into the encapsulated BLE_commodore_keyboard_server Arduino sketch.

BLE options: (a) Commodore keyboard (b) CardKB

No expense spared for these awesome graphics, seems retro eh?


While I have wired in the full C128DCR keyboard in the past using a circuit and software sketch with an Adafruit ItsyBitsy, now I trade the wire with another ESP32 and BLE communications.

M5Stick-C with CardKB BLE connected to T-Display-S3

Actually we already had BLE CardKB support, and the protocol for the hard wired keyboard is exactly the same as sent over BLE (string of active C64 and C128 scan codes), it was just a little bit of further coding to make the choice between CardKB and hardwired keyboard.   In fact, that code was already present for CardKB or hardwired keyboard in the M5 branch itself.  The tiny bit of extra work was to duplicate that in the BLE keyboard server project.   And voila!  More options all the way around.

Wired keyboards (a) Commodore (b) CardKB (c) Chrome Browser

There were already three options for wired keyboards.  And three common Commodore keyboards were represented, because they all have compatible pinouts, and because I do have both Vic-20 and C128DCR at home.

Dropping the wire from the wearable (or other ESP32 emulators) adds convenience to mobility, and also defers the need to support wired connections to any ESP32s missing Grove connectors and any that are not 5V tolerant, as both the ItsyBitsy and CardKB use 5V interfacing.   BLE support, and improved BLE support provide more options to the emulators running on hardware such as the T-Display-S3 and the 7"LCD ports without any hardware interventions.  While these latter ports would require extra circuitry for hardwired serial or I2C connections including 5V to 3V3 interfacing, using BLE means that the existing circuit support on the M5Stick-C acting as the BLE server can wire to those keyboards instead.  Going wireless provides the equivalent functionality without requiring a hard-wired circuit to the final display device.

While wireless does have its convenience, it does require careful timing to pair correctly.  Typically if both the BLE client and server are powered or reset at the same moment, they should pair.   A few or more keystrokes may be necessary to confirm pairing is complete.  If it doesn't work, just reset and try again.

Happy C64 computing over BLE!

Tuesday, December 5, 2023

7" LCD (ESP32) with C64 Text Emulator

 

7" is giant compared to this much smaller screen

So this ESP32-8048S070 showed up from AliExpress today.  It is a 7" IPS with touchscreen with ESP32-S3-WROOM-1 module, 16MB flash, 8MB PSRAM, microSD card, USB-C serial (CH3400 serial), Speaker connector, and other IO connectors.   The large LCD is 800x480 resolution.

The ordering page had a ZIP download of the examples, so I made sure I could build their Arduino Hello World TFT sample (I downgraded to Arduino_GFX library 1.3.1), and then ported my c-simple-emu6502-cbm project including upscaling from one to four pixels to cover the screen with C64 goodness.  Without upscaling, the C64 was using less than a quarter of the screen.   I skipped the SD support, and went straight to creating a FATFS partition and uploading a D64 image.  Saves me from pulling an SD, but moving files up and down will be a bit more cumbersome.  Included in the project already was custom wireless BLE keyboard support, so I was typing away and running my programs right away.

The largest IPS I had on hand was 3.5" 480x320, so this is a definite upgrade.  

The only downsides to this board that I can tell are the lack of an enclosure (ships in a nice plastic storage box though - I hear there is a 3D printable one on github somewhere though), and the lack of direct connection to the native ESP32-S3 USB port.  Then again, a permanent serial connection is more convenient for flashing Arduino sketches otherwise you have to keep selecting the COM port on other solutions.

Even though I've worked with it only a few hours, I highly recommend this board!

Monday, December 4, 2023

New! and Improved! C64 text emulator

There has been a steady stream of improvements to my wearable C64/C128 text emulators and related projects since the Summer 2023 debut at VCF West 2023 in Mountain View.  My Twitter/X account includes posts of many of these advancements.

  • used a 6502 test suite to find problems in my emulation
  • Vic-20 emulator
  • Vic-20 upscaled resolution
  • A few more hardware targets supported, including much smaller sizes
    • M5Fire 320x200
    • M5Atom S3 128x128
    • M5Stick-C 160x80
    • LilyGo T-Display-S3 320x170
  • Downscaling resolution as necessary
  • Tilt and pan for 1:1 resolution on tiny screen sizes
  • FATFS partition for files when no SD present, and when PSRAM not present
  • M5Stack CardKb support
  • wireless keyboard (BLE server/client)
And all these changes are stored on GitHub of course!

A fellow attendee at Vintage Computer Festival West 2023 sported a red M5Fire and it looked really good!  So I ordered one soon after, it arrived with some other goodies, and I quickly ported the M5Core2 and M5CoreS3 solution to the M5Fire.   Features are comparable.

Then I added keyboard support to the on-screen buttons.  Left goes up.   Right goes down.   Center is Return.  Left+Center is Shift+Run with a ROM change to make it load the first program from disk.  And Left+Right toggles between the different emulators (C64 -> C128 -> Vic-20)  This made an actual keyboard optional for demos.  I had a boot program to provide a listing of programs selectable by cursor keys and Return key.  

The only downside is that the M5Stack Fire is not watchband compatible in that the recharge circuit is in the detachable base, not in the unit itself.  Otherwise it would make a classy wearable.


Vic-20

The Vic-20 was my original home computer.  It is what I used to deep dive into Commodore, learning BASIC and 6502 Assembly Language inside and out from about 1982 to 1985.  I still have a fondness for this system.

But it has an odd screen resolution.  Text is 22 columns and 23 rows equating to 176x184 pixels.

The M5Core series controllers have an LCD 320x240.   This was just perfect to match the standard text screen of the C64 which is 320x200 pixels. 

Originally I simply increased the border sizes around 176x184 pixels.

Then I revisited my Teensy C64 which has an option for a 480x320 LCD screen.  For that project I researched upscaling, which involved scaling an 8x8 character cell to a 12x12 character cell, using color averaging.

For the M5Core series, I similarly scaled the Vic-20 8x8 character cell to 12x8.   To accomplish this, staring with pixel offset 1, an extra column is interpolated from the previous and next pixels, and repeated a total of four times.  The LCD works in 16-bit color mode with 5 bits for red, 6 bits for green, 5 bits for blue.  The color of the two pixels is broken down into its component red/green/blue parts, the corresponding color parts are averaged (totaled and divided by 2), then recombined into a 16-bit value for the interpolated pixel.

So far only the M5Cores with PSRAM have Vic-20 and C128 support.

M5Atom S3

This is the smallest target hardware I have ported to.  Downscaling was implemented to see what would happen.  The 8x8 character cell is downscaled to 3x4 pixels, so 64 pixels downscaled to 12 pixels which is a large number of pixels to through away.  Priority was given to the center pixels, so it toggles between averaging 6 (3x2) or 4 (2x2) at once.  It does a weighted average between the foreground color, and background color pixel counts, so the resulting downscaled pixel is closer to one or the other.

Surprisingly, the screen is somewhat readable even with this resolution loss.  But to compensate for loss a zoom and tilt to pan feature was implemented.  The whole screen is mounted as a single pushbutton.  Clicking it toggles between zoomed out to the downscaled resolution, and the zoomed in to the pixel perfect 320x200 resolution that is panned, by tilting the device.  Zoomed in, hold the device level with the floor, with the screen pointed to the ceiling, and you will see the top center of the C64 screen.  Tilt to the right and forward to see the top left corner of the emulated screen, and so forth to switch between one of six views of various parts of the emulated screen with every pixel shown.   Click again to zoom out for an overview of the entire screen, but downscaled.  Break out a magnifying loop or such to see the detail of the teeny tiny pixels.

This platform does not include an external storage device such as SD card.  Nor does it have PSRAM normally used by the D64 emulation.   Instead, a FATFS partition was initialized, and individual C64 PRG files were selectively uploaded to the device.   The "$" directory functionality is not present, but LOAD/SAVE/VERIFY are supported.   There is room for about 1.5MB of files in the partition size selected, that's about 9 times larger than the standard single sided C64 floppy, so not too bad!

M5Stick-C

I had forgotten about this hardware device.  It was the first M5Stack device I had purchased, and I had squirreled it away in a project box.   Obviously it was too small for a C64 screen so I didn't give it another thought.   Until I saw a post on Twitter/X showing the solution with CardKB.  Looks like it's using my text-only emulation, using LCD fonts.  Of course I respond!  That would work very well.  I've just been so focused on LCD pixelized solutions simulating the look and feel of Commodore instead of remembering the roots of my text emulation efforts with C64.   Just hook CHARIN and CHAROUT and you're golden.  You don't need a screen editor.  You can just do buffered line input (local edit), and character output.   I was laughing at myself for not pursuing this myself.  CardKB provides ASCII output (from I2C polling) of the alphanumeric characters, and other byte ranges for functions and cursor keys. 

I wanted to do CardKB, but as I have been focused on C64 scan code adapters, it seemed hard.  But here was the challenge presented on the Internet.  I had already implemented an adapter of sorts leveraging a SeeedStudio ATMEGA328P (Uno compatible) board with Grove connectors and an Arduino sketch to translate I2C reads into TTL serial scan code reports.  And it worked, but was very clunky because of all the cords and extra board.   My existing prototype solution was not great for a wearable solution.

The M5Core and such were focused on using the Grove connector as a software serial port, receiving the C64 scan codes.  I had the original C128/C64/Vic-20 keyboard to Grove adapter running on an Adafruit ItsyBitsy and that was my favorite keyboard connection because it was true to the original!  Next best was a web page to USB Serial adapter I had also developed.   The common ground was scan codes, and serial communication.  But the CardKB runs I2C.   So how to do CardKB and serial communication simultaneously on the same Grove port?   Originally I thought of getting the source to CardKB and rewriting, reflashing it to do serial communication instead.  That would make it compatible with my existing solutions.  But I was avoiding the reflashing that would also requiring rigging a programming interface, using an Uno or compatible.   

Instead, I approached the Grove port as an either or, the emulators were updated to check for an I2C response at startup, and if found, regularly read from the I2C port for keyboard presses.  Then adapt those presses from ASCII/function code presses into momentary C64 scan codes, and 1/60th of a second later, respond with no key pressed (key up) scan code response.  This is an out of the box solution that will work for others too!

M5Stick-C also leverages a FATFS partition as there is no built in SD port.  Again 1.5 million bytes.,  Though I did have to revise the partition choices manually via a JSON file as FATFS was not included in the default partition schemes presented.

But the screen resolution is 160x80, with downscaling of one character's 8x8 pixels to 4x3 pixels.  This time the pixels are halved horizontally, and vertically there is an 8 to 3 pixel translation, very similar to 
the downscaling on the AtomS3, but rotated to different axes.

This is by far the worst unreadable display for individual text characters.  More than halving the vertical resolution makes the text completely unreadable (such as the startup screen).  It's not it's fault completely, and is a cute form factor when not pretending to be a C64.

LilyGo T-Display-S3

This is another inexpensive device with a wide yet shorter display 320x170.  Oh so close to the necessary 200 pixels.  So a custom downscaling algorithm favoring the center four vertical pixels of each character cell, while averaging the top two and bottom two pixels.  This results in a very recognizable display of alphanumeric characters with some slight distortion at the top and bottom of each character.

While this device has plenty of flash storage and PSRAM comparable to the best of M5Stack Cores, there is no built in SD card, so the implementation also leverages a FATFS partition successfully.  But with the PSRAM included, D64 support could be included allowing for the floppy drive image feature.

BLE keyboard support has also been included with this one, making it full featured.

The features missing are no Grove connector, no socket for CardKB support, and Vic-20/C128 support.  A bit more effort could transfer these features with software and hardware.

CardKB

     Esc 1! 2@ 3# 4$ 5% 6↑ 7& 8* 9( 0) <x
     Tab Q  W  E[ R] T/ Y£ U| Iπ O' P" fn
  Up  Shift A; S: D  F+ G- H← J= K? L  <-
Lt  Rt  Sym Z  X  C  V  B  N  M  ,< .> __
  Dn

fn+1..fn+0 is ctrl+1..ctrl+0
fn+A..fn+Z is commodore+A..commodore+Z
Esc is stop
fn+Esc is stop+restore
tab is load+run
fn+tab is restore
fn+<x is insert
fn+up is clear
fn+right is home
fn+down is toggle case (cbm+shift)

Wireless BLE Keyboard

Taking CardKB one step farther is joining it with a M5 controller such as M5Stick-C to turn it into a Bluetooth Low Energy keyboard.  Currently integrated with M5Fire, M5Core2, M5CoreS3, and T-Display-S3, turn them both on at about the same time and they will automatically pair.  While the keyboard is wired to the M5Stick-C, another ESP32 system can be battery powered and receive keystrokes over the air with the BLE (2.4GHz) radio.  




I used to wire the full size C128 keyboard to my wrist, and it was a hilarious irony in mobile computing.