I designed the circuit board shown above to make a USB controller for a laptop keyboard with up to 34 FPC pins using the RP2350 Stamp XL from Solder Party. The Stamp, USB Breakout, and FPC Breakout boards come with all the surface mount components already attached, leaving you to do the easy soldering of header pins. All associated files for this project are at my USB_Laptop_Keyboard_Controller GitHub repository in the StampXL_34Pin_Keyboard folder.
Typically a laptop keyboard connector has 24 to 34 pins. Since the Raspberry Pi Pico only has 26 GPIO's, it won't work for a lot of keyboards. To solve this problem, I use the RP2350 Stamp XL which contains the "B" variant of the latest Raspberry Pi microcontroller. It has 48 GPIO's but I only use 34 since this is more than enough for most keyboards and it reduces the board size.
The carrier board was designed in KiCad and measures 2.82 x 2.68 inches (71.7 x 68.0mm). The KiCad board file “2350B_Keybd_Cntrl.kicad_pcb” can be sent to fab houses like OSHPark.com ($38/3 boards) and Eurocircuits.com (€47/1 board). The zipped Gerber file “2350B_Keybd_Cntrl.zip” can be sent to fab houses like JLCPCB.com and PCBWay.com. With slow economy shipping to the US, the cost is under $10 for 5 boards. The above files are available for download at my repo. The 3 components that attach to my carrier board are shown below prior to soldering.
FPC Breakout Board
Flexible Printed Circuit (FPC) cables are the standard method to route the keyboard signals to a laptop motherboard. The end of the cable has exposed metal traces on one side and the pitch, (distance between each trace) is usually 1.0 mm or 0.5 mm. FPC breakout boards are very common and can be found at Amazon, AliExpress, and EBay among other sellers. Pick the FPC breakout board pitch and pin count that matches your keyboard FPC cable. These boards will have 2 rows of through-hole pads with a 2.54 mm pitch. Avoid boards that come with the header pins already soldered because this limits how the board can be mounted. The 32 pin FPC breakout board shown above was needed for a Lenovo E550 keyboard. The E550 FPC cable had locking notches that had to be trimmed off with scissors in order to use the generic connector on the FPC adapter board. The typical breakout board uses FPC connectors with bottom contacts. Determine if your FPC cable will end up with its contacts facing up or down when routed to the carrier board. It’s common for the FPC cable to be flipped back 180 degrees when the FPC connector is underneath the keyboard. The pictures below show when to solder the FPC breakout board facing up or facing down so it can handle bottom contacts or top contacts on the cable. The left picture shows the cable will be flipped over so the carrier board ends up mounted underneath the keyboard. The right picture shows the FPC cable is not flipped and the carrier board will be mounted under the palm rest.
Keyboards with Two FPC Cables
To use this project with 2 FPC cables, attach one FPC breakout board to the carrier board and solder wires to a second FPC breakout board as shown below. One of the FPC cables will have bottom contacts and the second will have top contacts. As described previously, determine where you will mount the carrier board and if the cables will be flipped. The cable that will have its contacts facing down should go to the FPC breakout board that is directly soldered to the carrier board. The other FPC cable will have its contacts facing up and will go to the breakout board attached with wires. This breakout board will be flipped upside down (prior to connecting the FPC cable) in order to connect with the contacts.
USB
The Type C USB connector board from Amazon, Sparkfun, or AliExpress can be installed directly on the carrier board with 6 header pins or with 4 wires that allow the USB connector to be at the back or side of your keyboard enclosure. Only 4 wires (VBUS, GND, D+, D-) are needed because CC1 and CC2 are connected to 5.1K resistors on the USB C board and are not used by the Stamp XL. You can run wires to a USB Type A,Mini-B, or microB breakout connector if you don’t want to use USB C.
GPIO to FPCYou must attach the Stamp XL to the board with 2 mm pitch header pins (not the standard 2.54 mm pitch). The picture below shows how GPIO’s 0 through 33 are connected to the 2 rows of pads for the FPC breakout board. If your FPC connector has less than 34 pins, solder it any way you want. The software will figure out which GPIO signals are connected to key switches and which are no-connects. My code only deals with GPIO numbers, never pin numbers. This eliminates the problem of defining which end of the connector is pin 1.
Circuit Python
I used Circuit Python instead of Arduino C code to program the Stamp XL board. A good starting point for learning Circuit Python is at circuitpython.org. Select the “Get Started” box. The following is a synopsis of the steps that they provide.
To enter into loader mode, hold the boot push button down while plugging in the USB cable. A new folder will show as a USB drive, named RP2350.
If things are acting weird or you want to start with a clean slate, copy the flash_nuke.uf2 file (downloaded here) over to the USB drive folder. The drive will blink out and then return all clean. I did this because the Stamp XL arrived with an old version of Python installed.
Start with the circuitpython.org/downloads page, then select the Stamp XL. Download and copy the latest Adafruit Circuit Python uf2 over to the drive folder. The drive will blink out and return as CIRCUITPY with an empty lib folder. The code.py file is a one-line “Hello world” program. You will be replacing this file later.
Go to circuitpython.org/libraries and download/unzip the library bundle that matches the version of Python you are using. The bundle includes lots of libraries but you only need to copy the Adafruit_HID folder into the lib folder on the CIRCUITPY drive.
As you write and debug your Python code, you will need an editor. I prefer Thonny and it can be downloaded at thonny.org/.
A fresh Thonny install defaults to running the Python code locally on your PC, not on the RP2350. It will error because it can't find the "board" library that's embedded in Circuitpython. Go to the bottom right corner of Thonny and click Local Python 3 and then "configure interpreter". In the first drop down, select CircuitPython (generic). Under Port, leave it at <Try to detect port automatically>. Leave everything else checked and then select OK. Now you can select stop and then run in Thonny and it runs the code in the Pico.
Row/Column Keyboard MatrixThis is a partial example of how the keys of a laptop are wired in a row/column matrix format.
I've shown GPIO's 0 - 3 as rows and GPIO's 4 - 7 as columns but you typically don't know how they're connected. To figure out the connections, load and run my Matrix Decoder Python program (described below). It constantly cycles through all of the GPIO's looking for when a key is pressed. When it detects two GPIO's are tied together, it sends the two GPIO numbers over the USB interface to your PC. The PC thinks it's connected to a USB keyboard so it displays the numbers in whatever screen you have up. I usually bring up an editor on my PC like Notepad++ and load a text file that lists every key on the keyboard. This allows me to build a complete list of how the key switches are wired.
Keyboard Matrix Decoder Program
Download my Matrix_Decoder_RP2350B.py code. In Thonny, select File, Open, This Computer and navigate to the Matrix Decoder code you downloaded. This will bring it up in the editor and you can read through the comments to get an idea of how it works. In Thonny, select the “Stop” icon to halt the "Hello World" program. Next select File, Save As, CircuitPython Device. Overwrite the "Hello World" code.py file with your Thonny code (renamed to code.py). With the keyboard not connected, hit the "Stop" icon and then "Run" icon. To prove the program will send numbers, use a wire to short two GPIO's together. Disconnect the USB cable to power down and hook up the keyboard FPC cable. When you reconnect the USB cable, the code will start running again but it's best to hit the "Stop" icon and then the “Run” icon. The Thonny console window will show key press and release events but to see the GPIO pin numbers sent by the Matrix_Decoder program, you must open an editor like Notepad++. If two numbers are sent before any keys are pressed, these GPIO pins are probably connected to grounds or LEDs in the keyboard. They must be skipped by removing the numbers from the I_O array starting on line 33 in the code. Once you have no numbers reported when you hit "Run", you're ready to make a key matrix.
Load into Notepad++, the blank keyboard_pin_list found in the code section at the bottom of this project or at my repo. This text file lists all the possible keyboard keys (using KMK names) followed by tabs so it will make easy to read columns of numbers. Place your cursor to the far right tab of the first key in the list (Control Left key). This is where the Python program will send the GPIO numbers when you push a key and then it will send a down arrow to position the cursor so it's ready for the next key. If you make a mistake or need to reposition the cursor, just use your PC keyboard and mouse to delete or move the cursor. You don't need to remove keys that are not on your keyboard, just use your mouse to skip over them. Once you have GPIO numbers for all your keys, you can use the manual procedure described in step 12 of my Keyboard Instructable to determine the row and column GPIO's. This procedure is detailed in the following example for a Lenovo E550 keyboard. A semi-automated matrix generator program in the code section below, allows you to skip the manual procedure. It will determine the rows, columns, and key matrix with minimal editing. The PDF description for using this program is available at my repo.
Determine the Columns - Lenovo E550 Example
To create the key matrix manually, you must determine which GPIO's connect to the columns and the remainder are the rows. The modifier keys, (Control, Alt, Shift, GUI, and Fn) are a good place to start. Note that GUI is the Windows key on a PC or the Clover key on a Mac. The Lenovo E550 key list is given in the code section at the bottom of this project and at my repo. The GPIO connections were determined using the Matrix_Decoder_RP2350B.py routine. The left and right control keys show 2 and 8 are columns and 17 is a row. The Shift keys show 0 and 2 are columns (we already knew 2) and 3 is a row. The Alt keys show 1 and 11 are columns and 18 is a row. GUI shows 0 is a column (which we already knew) and 19 is a row. Lenovo keyboards typically give the Fn "Hot Key" its own two signals so 28 and 29 will be treated separately. So far, the columns we know are 0, 1, 2, 8, 11 and the rows we know are 17, 3, 18, and 19. Scan down the list and find when these rows are used and if they reveal a new column. 19 is used with 5 for the F12 key so 5 is a column. Next start with “A”, looking for numbers not yet known to be rows or columns. “A” uses 6 and 4 so look at other keys that use either 6 or 4. “Z” uses 6 and 2 but we already know 2 is a column so 6 must be a row. Going back to “A”, if 6 is a row, 4 is a column. Now the known columns are 0, 1, 2, 4, 5, 8, 11. Typically there are 8 columns so there’s 1 more to find. Going down the list, “E” uses 10 and 7 but “C” tells us that 10 is a row so 7 must be the last column. To confirm all columns are identified, put all the keys into a matrix table. If you find a key can't be placed, then you have another column to figure out. I picked 29 as a column for Fn but 28 would also have worked. The Lenovo E550 Key matrix shown below has each key name at the intersection of the row and column GPIO's. GPIO's 24 through 27 are not used on this keyboard.
Use KMK to turn the matrix table into a USB keyboard routine. It's open-source firmware normally used for mechanical keyboards but it also works for laptop keyboards (once you have the matrix). KMK uses CircuitPython which is why I also wrote the matrix decoder code in CircuitPython. All of the hard work of scanning key switches and communicating over USB is embedded in KMK. All you need to do is edit my KMK example keyboard code with your key matrix information. Getting started with KMK is described at their KMK GitHub repo which I will detail below.
For step 1, you already have CircuitPython installed.
For step 2, click on “get an up-to-date copy of KMK”, to start the download.
For step 3, unzip the kmk_firmware-main folder. It has many folders and files. Copy the KMK folder and boot.py to the CIRCUITPY drive on the Stamp.
For step 4, use code_LenovoE550.py as your starting point. Load the code into Thonny and edit as described below:
Change keyboard.col_pins to list the GPIO column pins left to right across the top of your matrix.
Change keyboard.row_pins to list the GPIO row pins top to bottom along the side of your matrix.
Change the keyboard.keymap matrix for the base layer per the table you created. The basic keycode names (and aliases) that KMK uses are given here plus you can see the names I used in the E550 code example. Each keycode name (except FN) must be preceded with KC. Put KC.NO in the matrix locations that have no key assigned. If you have a number keypad, these keys must start with KC.P followed by the name or number from the keycode basic list.
Copy your layer 0: Base Layer over to the layer 1: Fn Media Layer. Now look at your keyboard’s media keys to see which (if any) you want to make work. The media keycode names are given here. For the Lenovo E550, I wanted the Mute, Volume Down, Volume Up, Brightness Down, and Brightness Up keys to work when Fn is pressed. These media keycode names replace the corresponding Function key names at F1, F2, F3, F5, and F6 in the Fn Media Layer.
Click the “Stop” icon in Thonny just to make sure it's ready for new code. Save your code to your computer and then save it to the Stamp’s CIRCUITPY drive with the name "code.py" (this will overwrite your previous code.py that was the matrix decoder).
Now click the “Run” icon in Thonny and see if you have any typos reported in the console window. Once all typos are cleared, you should be able to type on the keyboard to test if all the keys work.
For normal USB keyboard operation (without Thonny), you can just plug in the USB cable. This will bring up a CIRCUITPY drive folder which you can close. The Stamp will start running the code as soon as USB power is applied.
Example Keyboard EnclosureYou can install the keyboard in the original laptop base or make a new base with a 3D printer but I chose to use plywood to make a keyboard bridge. The bridge sits over my new Lenovo IdeaPad 5 laptop (which has a terrible keyboard). I don’t need the trackpoint or touchpad to work since I use a wireless mouse but this would be an interesting future project. This picture shows the finished laptop keyboard bridge.
The top board for the bridge is 3/16” 3 ply finish grade plywood with a cutout for the keyboard. The board underneath is ½” 4 ply standard plywood with cutouts for the carrier board and cables (see below). The side boards are made from ¾” solid pine and have cutouts for the connectors on the side of the laptop.
If you have a laptop keyboard with 26 or fewer pins on it's FPC cable, then you can use the Raspberry Pi Pico instead of the RP2350 Stamp XL. I designed the circuit board shown below with 26 surface mount pads for a 1mm, 0.8mm, or 0.5mm pitch FPC connector. If you're handy with a soldering iron and want to use the Pico, this provides a smaller and cheaper USB keyboard controller. The Eagle board file or zipped Gerber file at my repo can be sent out to be fabricated. The procedure for creating the matrix and updating the USB code is the same as described above. The Matrix_Decoder code is slightly different due to GPIO's 23, 24, and 25 not being available on the Pico. The PDF documentation describes the entire build and programming process. KMK code for a Dell 1545 keyboard is provided as an example. The Pico W has Bluetooth capability so a future project is to update the KMK code to utilize this feature.
These Lenovo keyboards stay under the 26 pin GPIO limit so they can be controlled by a Raspberry Pi Pico W. I have created circuit boards for the T60 and T400 series keyboards. The Eagle board files and zipped Gerber files are at my repo. This picture shows the Raspberry Pi Pico T61 keyboard controller.
The Pi_Pico_T61_Keyboard_Controller.PDF provides all the information needed to build this board. The KMK USB keyboard controller code is available at my repo. The board includes circuitry to power and level translate the PS/2 signals to the trackpoint but KMK can't handle this interface. I was able to confirm the trackpoint circuitry works with bit-bang Arduino C code. The Pico W is capable of Bluetooth operation but I've yet to figure this out using KMK. There's lot of future software to develop for this controller but the hardware is all working.
If you have any questions about the RP2350 Stamp XL or Pico USB keyboard controllers, let me know in the comment section below.






_3u05Tpwasz.png?auto=compress%2Cformat&w=40&h=40&fit=fillmax&bg=fff&dpr=2)
Comments