The Leyden Jar, a tentative PCB replacement for the Brand New Model F Keyboards

Hello keeb lovers,

Long time no see in this ‘Making keyboards’ section!

This time it is not for a new home made keyboard case and PCB combo, only a PCB for an existing keyboard.

But what a keyboard!
I am talking about the Model F keyboards and specially the F62 and F77 variants that @Ellipse made.
IBM Model F was the predecessor of the IBM Model M, another iconic board that I learned programming on a long time ago.
In term of feeling/tactility the Model F does not disappoint: this is a pure joy to type on, really something that everyone should try at least once in a lifetime.

Long before having my own I wanted to undergo the task of making my own PCB for it.
So started to look at various documentation about the electro-capacitive technology behind those boards.
The IBM patents are an interesting read, but the place were I found the most information is on the website of the creator of the original Model-F-USB controllers, Tom Wong-Cornall:

Why making another PCB ? After all there is already a PCB on the new Model Fs that has QMK/VIA support.
The reasons are:

  1. Not much has improved in the technology behind those PCBs since 2014: most if not all PCBs are based on Tom Wong-Cornall design, up to the components used.
  2. The small ATMEGA32u2 MCU used in those designs struggle to make everything fit in it’s memory.
  3. There is a silicon shortage and those Atmel MCUs are now very hard to find and expensive for what they are.
  4. I want to know if I can do it :smiley:

So here we are with the Leyden Jar PCB, name taken from the first ever (crude) capacitor ever invented: Leyden jar - Wikipedia

Some quick specs:

  • A modern RP2040 MCU
  • Columns directly driven by IO pins (original design uses a IO pin multiplexer that can also work as level shifter).
  • Lots of flash storage (16Mbits).
  • Lots of EEPROM external storage (512Kbits).
  • Uses I2C protocol for EEPROM and DAC chips, saves a few pins doing that.

After having seen Gondolindrim constantly use the LTSpice software for simulation, I learned the tool and could make a simulation of a full Model F matrix work.
Without this tool it would have been impossible to find the right technique and components values.
We’ll see how it work in practice but Gondo told me that LTSpice was already giving a good approximation of how things should work(if used well) so I have hope :wink:

There is a lot of things that could go wrong in this design as a lot of things are new to me.
As a result I have a list of stepping stones or goals in mind, so that if the boards is unusable on my Model F I have at least learned something in the process.

  1. Have the RP2040 succesfully starting and flashable.
  2. Can use SWD debugging on it, do the reset circuitry work ?
  3. Can configure and use the EEPROM and DAC chip through I2C.
  4. Can validate that the capacitive sensing works outside of a Model F keyboard.
  5. Can use one of the QMK fork to have a real firmware.
  6. Can make the solenoid work (do not have a solenoid at the moment).

I should be able to order my first fully assembled PCBs at JLCPCB very soon.
Here is a graphic view of the PCB.



See ya people!


This is great Rico! Please keep us updated on this project!

I am definitely looking to switch the Brand New Model F and Brand New Beam Spring projects to an open source RP2040 based controller due to the chip shortage.

Please see the below 33 pin controller design that is the latest version of the project controller, for reference. It allows the 3 LEDs of the beam spring keyboards to be a part of the PCB instead of through wires, and it is also backwards compatible for all of the new Model F keyboards.

It seems like QMK support is in progress but not yet completed for the RP2040, and there are other projects like KMK which seem to work with the RP2040. The question is, is it better to go with KMK? How stable is it? It may take a while for QMK RP2040 support to be ready. Some recent related links:

What would it take to get the Model F firmware working on the RP2040 chip?


Hello @Ellipse,

Thank you very much for your interest in my little project!
I am not sure yet I will succeed but will definitely try.

A big thank you for the link to the last PCB design you have, this will probably help me understand how the 3 leds are working, and will try to add this feature in my PCB (but I only have 2 free IO pins left).
Looks like Diptrace program have been used for the design, never used it but will see what I can do.
I could at least have a look at the PCB design and there are several dimensions displayed that I had to measure by hand on the real PCB, this will help me tune my holes positioning if needed.

As for KMK vs QMK.

KMK is a very nice technology and the RP2040 chip is powerfull enough to run it without any problem.
But asking people to dive into Python programming to adapt their layout will probably be too much for most.
Also I am not sure how easy it is to implement a custom matrix scanning on it.

IMO QMK/VIA/VIAL should be the way to go, while dealing with the problems you mentioned earlier.
My take on that is that RP2040 port to QMK is seriously taken by QMK and ChibiOS team and it is only a matter of time.
In the mean time if KalrK90 fork is working as intended an early support could already been done.
With VIA/VIAL support people don’t really need to dive in to firmware compiling themselves.
Also this early situation would not be that much different from the current status of firmware for the current hardware … until full RP2040 support is officially supported on QMK of course.


A little bit of news.

I took @Ellipse suggestion into account of adding support to the 3 leds for the future beam spring keyboards.
It has not been easy as I had only 2 free pins left and I initially needed 3.
So added an IO expander that will be in charge of driving both the solenoid and the 3 leds.
It is controlled by the second available I2C controller of the RP2040, the first one been used by both the external EEPROM and the DAC.

Cleaned up a few things, and voilà!

Now on to double/triple check and send all that for fabrication !


I had the pleasure to test the Kicad 6 plugin “JLCBCB Tools” by Bouni:

I highly recommend it, this dramatically helps filling the BOM information when you want to go through JLCPB or at least order components at LCSC.
The one button that generates all the fabrication files for JLCPCB (gerbers, BOM, POS files) is a god-like feature :slight_smile:

The PCB references only components that are listed at JLCPCB so one could easily make it’s own without having to solder anything.

Just ordered 5 assembled PCBs at JLCPCB, most chips were in stock except the buttons and the QSPI flash.
There were lots of stock available at Mouser so ordered them here and will solder them by hand.

Will keep you posted of my progress!


Just a bit of news on the PCB fabrication and assembly, and some generation information on PCB fabrication at JLCPCB in general.

You may know that often the component placement preview can be messed up at JLCPCB, and they say there will be manual review to correctly place the components.

Here is an example on the Leyden Jar PCB, before the correction:

Pretty messed up uh ?
This was even worse on the preview before doing the order, some resistors were completely outside the PCB area.

And after manual correction:

This is just perfect!

So if you plan to order an assembled PCB at JLCPCB, don’t be put off by weird components placements on the preview, this will be fixed later.
They may even ask you confirmation by email if they have a doubt.

And also you can check daily the production process, they give very precise information.
For example I know that as of now I have 15% of PCB fabrication complete, with the top and first hidden layer manufactured.
And also that they corrected the placement of the components for the future assembly process :wink:


The PCB just came into my doorstep, and they are beautifully made :slight_smile:
Sorry for the, as usual, crappy picture.

Now need to solder the missing parts that JLCPCB didn’t have (the Winbond QSPI flash and the switches) and then begin the testing to see how far I succeeded (or how fast I failed).


Had a little bit of time this WE to work on the PCB.

First, to solder all the missing components on the PCB, that is the push buttons and the QSPI flash. I was not too concerned about beeing able to solder the buttons, the QSPI flash on the other side …
This flash comes in a very tiny USON8 package, with 8 connections on a 3x2mm package. I decided to not stress the already soldered components too much by using hot air soldering, and used my trusted soldering station with a small tip instead.
Here is the result once soldered:

And now the moment of truth, that is plugging the thing in with an USB cable.
For this kind of first connection attempt on all my newly designed PCB I always use an USB hub and never the USB ports on my PC.
The reason ? If something bad happens it fries my shitty 15$ USB hub and not the USB ports on my costly 300$ motherboard (in happened to me before, not with my own designs though).

Let’s go!

Yay, it works!
Having this already validates a lot of things:

  • USB connection and ESD protection correctly wired.
  • 3.3V voltage regulator is correctly working.
  • RP2040 MCU, crystal, and bypass capacitors wiring are good.

This does not yet validate that the QSPI flash is working, for that we have to flash an executable file in UF2 format to see if it works.
But my design is using the same 2MB Winbond flash as the Raspberry Pi Pico board, so why not trying to install CircuitPython on it ?

It works!
Now the QSPI flash is known to work correctly.
I also tested that the two push button ‘Run’ and ‘Bootsel’ were doing their job correctly, that is reset the device and also be able to boot from the ROM.

Things not validated yet are if the SWD interface is working correctly and all the surrounding design that is Model-F/Beamspring specific.
This is my next step and now that CircuitPython is installed why not do that in Python ?

See you!


A quick python script to scan for i2c devices on i2c0 and i2c1 and here is the result:

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. output:
Scanning I2C bus 0
2 device(s) found on I2C bus 0
Scanning I2C bus 1
1 device(s) found on I2C bus 1
Code done running.

This is looking good, all my 3 I2C devices are correctly detected :slight_smile:
This means that I have good chance to have working:

  • The external EEPROM.
  • The DAC chip to set the voltage reference value for the comparators.
  • The IO expander to drive solenoid and LEDs.

Another little news about testing the PCB.

While writing small python code to check the I2C devices was very time effective, it is not how I want to proceed to fully proof test all hardware components.
And before starting firmware development with QMK I need to write the basic libraries to pilot the various devices and put in place the matrix scanning stategy.

  1. I want full control of the hardware and adequate speed so Python will not fit my development purposes, will use the great C++ Pico SDK instead.
  2. I want to iterate fast so drag and dropping compiled executable file each time I make a code modification is out of question, need hardware SWD debugging.

But fortunately there is a way to use a standard Pico PCB as a SWD debugger, this way I can upload and debug code under VS Code editor and go fast.

Already did that some time ago to debug programs with two Pico PCBs, there is a great article that explains it:

And I recently found a new one that explains how to wire everything while using USB port to power the target board:

Here is my debugging setup:

Yellow wire is SWCLK, Orange is SWDIO and Green is ground.
Green wire is very important as both boards (Pico PCB that contain picoprobe software and Leyden Jar PC) need to share their ground, it will not work without it!

And the debugging session of a very basic progran that runs on the Leyden Jar PCB:

So the two SWD pins are working correctly, nice :slight_smile:
I feel at home with a real debugger :stuck_out_tongue:


After a few weeks of holidays I am back on track to work on this project.
The goal is to now see if capacitive detection is working as well as on the LTSpice simulations.

Below is a test setup with one switch:

And the results I got were at first unexpected: not only it proved to work, but was working too well based on my initial expectations.
I could detect exactly the voltage value when no colum/row was connected, with the same value as the simulations.
But when a capacitor was wired the detected voltage level was out of the roof, so high that anything bigger than 0.5pF capacitance was out of my detectable voltage range (a maximun of 1V).
As I had only conducted serious LTSpice simulation on a full 16x8 switch matrix I told myself that I missed something for my understanding, so began to make simulations of a single switch.
… And I could obtain very close results compared to my initial test, great!

Also when adding columns in the mix the detected voltage level is getting lower and lower.
Let’s see what happens with a 5 colums and 5 rows matrix:

And I obtain very close results to my simulations of the same matrix with ~20pF of parasitic capacitance!

I am starting to think that having a working controller is now more a question of ‘when’ than a question of ‘if’ :slight_smile:
To be 100% sure I have to write a full QMK firmware, let’s go!


Good Luck! Inspiring as always.

1 Like

I am happy to say that things progressed quite a bit!

The first step was to design a good matrix scanning program.
This is more difficult than it looks, as during my simulations I saw that I had only 1us window to read all the row values.
So it works no problem using CPU polling if you want to read only one row (and this is what I did to check that the PCB was working as intended).
But reading 8 rows by reading IO pins using the CPU and expecting to have consistent results is another matter…
Several factors can make this process using the CPU unreliable:

  • We could simply not have time to scan all 8 row IO pins, and we’d miss key presses.
  • This could ‘work’ most of the time, but be interrupted by an external code or kernel process and miss some keypresses as a result.
  • The timing at witch to read the IO pins is important, a bit sooner or a bit later and we can have slightly different results; we need to have this timing very consistant (I measured an optimum time of 0.8us between activating a column and reading row IO pins).

While current Model-F PCB is reading row IO pins using CPU “as fast as possible” (said Tom Wong-Cornall in it’s blog), this not gonna do it at least for my design.

But I knew that from the start thanks to the LTSpice simulations and selected the right MCU for this task :wink:
Hello RP2040 and it’s PIO feature!
I should be able to make a PIO program to do the matrix scanning without CPU usage and very tight and consistent timings.
I took me a while to do that (my first time doing PIO stuff and this is another specialized hardware to learn) but finally had my PIO matrix scanning program working like a charm :slight_smile:

Second step, test this matrix scanning program on the real beast, my own Model-F F77 board.
For that I needed to desolder the current PCB and solder the Leyden Jar PCB.
This was a big step for me as it would not only determine that my PCB work on the real hardware, but also would validate that everything fits nicely mechanically.
Not entering too much into details, I have to say that the official PCB has been a bitch to desolder :frowning:
But here is the result:

This is ugly but had to put back the kapton tape as the lower part of the PCB is touching the bottom case (as with the official PCB).

Happy that everything screws and fits as intended, there is even place for my SWD connector for developping/debugging!
Debugging session that started shortly after:

So how does it works?
First the detected voltages are lower than in my simulations:

  • This is normal as we now have to deal with parasitic capacitance and inductance.
  • I have very early timings in my PIO program, this could improve in the future (already tweaked a few things to make it better).
  • We are using 3.3V for the column IO pins instead of 5V for the official PCB, having a lower voltage peak was more or less planned.

But the most important thing to have is consistency and we have excellent consistency here:

  • We have only ~1mV deviation for the same keys tested during several tests sessions.
  • Variance between all unpressed keys is 8mV at most (looks to be the same with pressed keys).
  • We have a peak voltage variance of ~30mV between pressed and unpressed key, this is more than enough to perform a very stable key press detection :slight_smile:
  • Pressing several keys at once or only one does not look to change the detected peak voltage much.

I think that the key of this consistency is to have a reliable 3.3V voltage source as it is generated by the onboard voltage regulator.
On the other end, I had some undetected keys problems with the official PCB when plugged on my shitty USB hub; this may be explained by some fluctuations on the 5V line, that even the calibration program can’t handle. No problem when plugged on my PC USB ports though :slight_smile:

To conclude this will definitely work like a charm and I am excited to start writing a VIAL firmware to confirm this.

On top of that there is another good news, the scanning process is quite fast: as of now scanning all 16 columns and 8 rows takes only 640uS (40uS per column).
This could change in the future:

  • If changing the timings helps to have better peak voltage detection it could end to be slower.
  • But it could also be possible to have something even faster :stuck_out_tongue:

This is sounding like it’s going to be better than the PCB the Model F77 ships with.

1 Like

Those last days I worked mostly on having an early QMK/VIAL firmware working on my F77 board equiped with the Leyden Jar PCB.

Although I previously had a ‘bare metal’ program using the Pico SDK that demonstrated that the hardware was working nicely I was afraid to find many QMK integration problems.

Problem 1:

When talking about QMK firmware there is a significant software fragmentation issue.
This started by the VIAL fork in order to have an opensource alternative to VIA software.
Then due to the need to add support to the RP2040 MCU, things got even worse and you can find on the net many git repositories that gives early support for it.
Fortunately QMK has recently added official support of RP2040 into their main branch, but VIAL did not yet merged this support to their own repo.
So had to select one of the numerous git VIAL repositories for my integration task.
Fortunately Zykrah, very active in VIAL Discord, did all the tedious task of merging official QMK RP2040 support to it’s own VIAL repository:

All my work will use this repository as a base.

Problem 2:

As my matrix scanning is using PIO, I was not sure yet what kind of support would be available for that, if any.
Looking at the QMK source code, there are official support of WS2812 led drivers using PIO.
IO pin configuration is using ChibiOS HAL api directly and for PIO stuff the Pico SDK API is used.
Let’s see if I can do the same thing for my PIO matrix scanning program.

I had to perform different tasks in order to hope to have everything working:

  • Review QMK source code to understand how/what RP2040 support was added.
  • Configure a work enviromnent to be able to use a SWD debugger.
  • Review previous QMK firmware source codes that implement F77/F62 firmware using the official controller, mostly to understand or reuse how physical rows/columns are arranged.

And this last task proved to be more complicated that planned: to my surprise I could not easily reuse the work already done.
So time to start a debugging session and see what happen when you press the buttons, came with this ugly postit writeup of the matrix reverse engineering:

Fortunately using PIO proved not to be the headache I was fearing.

I was soon greated by the VIAL keymap display :slight_smile:

And finally could validate that all the keys were working with the matrix tester:)

It is very early, need a lot code polish and add missing features, but it works !

Things that work:

  • All keys work.
  • Storage settings on external EEPROM works.
  • Storage settings on RP2040 flash storage also works! I was surprised by seeing this feature added in QMK repo. Now need to choose between EEPROM and flash, if flash is selected I could remove the EEPROM chip for future PCB revisions.
  • Key commands to reset the MCU and erase the storage settings (EEPROM or flash) are also working.

Things not done:

  • Implement a proper voltage threshold calibration program, as of now it is harcoded and may not work on other boards.
  • Implement solenoid support, unfortunately I don’t have such hardware at the moment so this task alone could take time.
  • Tidy up code, fix bugs, add F62 support.

Happy man I am :slight_smile:


The Model-F soledoid and it’s driver juste arrived today, ty very much @Ellipse for having sent this so quickly!

So now on to try to make it work!

I already checked that the solenoid connector on the Leyden Jar PCB was correctly wired, good :wink:

I could work a bit on the software part also.
Having the connector pins connected to the I2C IO expander makes things a bit more complicated as QMK firmware does not handle this case at the moment.
With a bit of cheating and after studying QMK haptic/solenoid management code I could come with something not too terrible.
But I’ll definitely assign 2 MCU pins for a future revision of the PCB, this will make it more QMK friendly for the implementation.

The biggest unknown is now if I can drive the solenoid with 3.3V logic instead of 5V, time will tell …


Was the time to work on the solenoid support this WE.
And to discover if a 3.3V logic would be enough to drive it correctly.

I had read long time before the datasheets of both the current limit and the darlington array chips that are used inside the solenoid driver PCB.
At that time I concluded that a 3.3V signal would be enough to make everything working.
It is time to confirm that I guessed well !

Here is my current test setup in picture with everything attached:

After a long time of frustrations, numerous failures, and fear that in the end it may not work, I finally managed to make it work perfectly :slight_smile:
And oh boy this thing is noisy as f**k :smiley:

I have been very lucky up until now, having everything working as hoped.
Of course this design is still not perfect and may need further investigations and probably a revision 2.

Things that are still to do:

  • Cap sensing voltage variations are smaller than I intended, need to investigate how to improve that.
    This does not prevent to make Model F keyboards work very nicely, just that with more columns used things could get more complicated and would prevent BeamSpring keyboards to work reliably enough. I could try to improve this my modifying the current revision of the board.

  • Solenoid is driven by IO pins from the I2C IO expander chip. QMK has native support to only direct MCU IO pins usage; had to do little code tricks to make everything work. Would be best to use MCU IO pins next time.

  • Current design uses 2 I2C devices; again the QMK API does manage only one I2C device, I had to rely on ChibiOS API to drive the second one, complicating the code a bit. I’d wire all used I2C chips to only one I2C device for the next design.

  • External I2C EEPROM chip is now not needed as QMK has official support for EEPROM emulation using RP2040 flash storage; I tested that both were indeed working but would remove the external chip to reduce BOM (and then cost).

  • @Ellipse would like to have 2 additional columns to drive for possible future BeamSpring projet, like for example a 122 keys battleship. I saw a possibility of doing that and may add it in a future revision.

See ya !


Hello all!

Long time no see in this thread, did you thought it was a dead project ?
Far from it :wink:
It fact I continued slowly working on it, mostly on the firmware development side.

As I had little visibility on how this controller would work on other boards than mine, I needed someone with other variations of capacitive keyboards to help me.
And after discussing with @Ellipse he kindly accepted to give me some help on that task.

After receiving the Leyden Jar PCB he decided to solder it to one of it’s Brand New Beamspring Round 2 Full Size keyboards, our goal was then to try to make the Leyden Jar controller PCB work with this hardware.

Here are some shots of the Leyden Jar PCB assembly on the Beamspring Full Size, courtesy of @Ellipse.

As I didn’t have the board on hand, making the controller work on it was a complicated matter.

First I had to figure out how the switch matrix was organized and did a complete visual reverse engineeing of the beamspring PCB plate based on images provided by @Ellipse.

And also had to find the correct values for the calibration process.

After quite a few back and forth exchanges and firmware revisions we finally managed to do it :slight_smile:
There is now at @Ellipse workspace a Brand New Beamspring Full Size Round 2 keyboard with a Leyden Jar controller working nicely with solenoid and leds support, than you very much for your great support Joe!

Now is this controller perfect ?
Of course not, even if the most important feature, the capacitive sensing technology, is working very reliably.
So it is now time to make a revision 2 of this PCB and try to make it perfect.
The plan is also to add two additional columns, if possible, for future keyboards with a lot of keys like 122 keys battleships.

See ya people!

1 Like

This is interesting to me, as I’m becoming more interested recently in the new Model Fs after a surface-level look a while back. Thanks for the update.

1 Like

And with recent Joe announcment for selling IBM Model M like keyboards with Model F technology, this makes the appeal even stronger :wink:

1 Like