A laptop keyboard conversion which really works.
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
Noted the GPIO_Init, GPIO_PinAFConfig functions don't do anything. The USB hardware automatically takes over the GPIOs. Helas, it sets the suspended voltages but does not enable communication. The GPIO initialization is still required for communication.
The USB_OTG_MODIFY_REG32 function doesn't do anything. You have to mangle the bits manually.
A few days of randomly poking registers, perusing random STM32Cube firmware & perusing the datasheet finally got it to release the GPIO's & give the wakeup signal. Moreover, it can restart USB from this state, eliminating the need to reset & set both pins to 0. If it ever resets & sets the pins to 0, the host won't detect the wakeup signal.
This got it to properly wake the host up.
Method of probing the suspended & wakeup signals with a dummy USB port, since it would always crash the laptop.
Testing suspend with the laptop instead of the development machine.
Test points for probing wakeup signals with the laptop.
With that, LEDs & an enclosure were next, along with more comparison with the Sunsonny.
Noted it can't wake up the confuser from a suspend & it doesn't come back after the confuser wakes up. It's a glitch in the USB driver.
After suspend, the keyboard gets a DCD_HandleUSBSuspend_ISR. Then after wakeup, the keyboard gets DCD_HandleResume_ISR, USBD_USR_DeviceResumed, USBD_USR_DeviceReset, DCD_HandleUSBSuspend_ISR. The ISRs don't work. The only way to restore USB is to reboot.
Waking up the confuser requires raising DM & lowering DP. The trick is there's no way to disable USB after it's enabled & manually set the GPIOs on the STM32. It has to reset & if the user is pressing a key, set the GPIOs during startup. If the user isn't pressing a key, initialize USB. Sadly, this still can't wake it up. The hub detects a lowering of the pins during the reset as a disconnect. It would have to fully support a runtime USB suspend or it would need glue logic. Any pullup resistor gets pulled to 0 during reset. It could bit bang USB, with immense effort.
2 weeks into this, it became clear a recycled STM32 was not the right solution. The right solution was buying a $25 arduino teensy & making a custom connector breakout board. That has a finished keyboard library & could probably handle the USB suspend. The arduino keyboard library might have a simpler way of handling multiple keypresses but you're still on your own with the integrating of the keyboard scans.
For a home made laptop, it wouldn't need to support wakeup commands. For replacing a home PC keyboard, it's a real problem. There could be an additional power button wired to the desk.
----------------------------------------------------------------------------------------------------------------------------------
Decided to put a lot of typing into the board & swap it with the Sunsonny a few times before continuing with LEDs & an enclosure. It still seemed to drop keys despite all the algorithms. Were the dropped keys really worse than a worn Sunsonny or just the same? Was the key travel assertive enough? The lion kingdom got the Sunsonny after many years of progressively worse boards, culminating in an absolutely awful Insignia board. Somehow lions got conditioned over the years to tolerate the worst of the worst, then lost the tolerance after the Sunsonny.
1 option is continuously fixing all the dropping keys as they come or burning another $40 on a new mechanical keyboard. Mechanical keyboards seem to have settled into an accessible option between the totally unusable flat keyboards that are only intended for minimal use & the lavishly overpriced unicomps that are only intended for collectors. The unicomp would definitely need continuous manetenance.
The laptop board is going to be the lion kingdom's custom laptop board, no matter what. Besides dropped keys, it's not as good as full sized keys. It's mane advantage was always how it felt the most like a macbook.
After much testing, a nasty integration algorithm was giving the best results. It was also proving more resistant to RF interference.
It needs to set the GND pins to push/pull mode. Then it needs to raise them all to pull all the keys high instead of waiting for the pullup resistors. This takes only 1 microsecond. Then it needs to lower 1 GND to scan 1 sector. This takes only 1 microsecond. It needs to scan all the sectors about 200 times while remembering all the keys detected. Then to debouce, it only sends 1 report after a complete integration which contains the change since the last integration. 100 scans take 10ms.
To speed up the scans, it used the last 8 pins as the GND & the 1st 17 as the sense pins. This had a lot less bounces but still had a lot of dropped keys. There was no improvement from delays longer than 1us.
It seemed to drop when multiple keys were pressed simultaneously instead of registering the latest keypress. Fortunately, the scanning algorithm successfully detects simultaneous keypresses. The next step was to buffer every keypress it detected & copy the latest keypress to the report. It also needs to blacklist previous hits until they're released. It's actually very important to be able to press keys simultaneously & only show the latest key, then not show any previous keys until they're all released.
It ended up needing a complicated algorithm to determine what keypress out of multiple keypresses should go in the report. These are apparently steps all keyboards take, based on common typing behaviors. There are still memories of the 1st IBM keyboards 45 years ago & how the behavior when multiple keys were pressed was so different than the commodore. Who knew how much programming went into that algorithm.
1 of the source code examples was using a simpler algorithm & scanning at 30Hz.
Suspect the other efforts were for a desperate need or adsense rather than for daily use.
Typing some significant text was pretty unbearable. The keys still have the best feel of any modern keyboard, but they're suffering from bouncing or missing presses. The problem is it has to wait 50us after exciting a ground pin, then takes just 1 sample of the key pins. 50us was the minimum for the voltages to settle. To defeat the dropped keys, it needs to integrate more than 1 sample. 1 way is to sample continuously during the 50us, detect all the points when only 1 key is down, & pick the key that's down the longest. It's not clear what the best integrator algorithm is. This algorithm can only see 1 ground pin at a time, so a key that's pressed elsewhere during the 50us is still going to get dropped. It might need full ADCs for the sense pins.
Then, it needs to accumulate several passes of the entire keyboard to debounce. It needs to scan as fast as possible to not miss any keypresses.
Some other ideas are driving the ground pins in push pull, scanning continuously instead of once per millisecond, trying to sense the last keypress when multiple are pressed simultaneously.
Noted it's currently grounding 17 pins & using 8 as sense pins. If it grounded the 8 & used the 17 for sensing, it could scan a lot faster.
Finally, noted when it's over the part of the desk with motor wires, it picks up spurious keypresses when the desk moves. It might need stronger pullups or a big heavy shield. This seems to be the end of the story. Discrete pullups would be a major fabrication job. It would require sending the sense pins through resistor packs, probably an expensive multilayer board. By that price point, you're better off burning $150 on a unicomp.
This project might be a useful boilerplate for a custom input device but a full, reliable laptop keyboard is a bigger deal than lion paygrade. It really dashes hopes for the custom laptop. Lions might be stuck with the big boys.
https://www.instructables.com/How-to-Make-a-USB-Laptop-Keyboard-Controller/
https://hackaday.com/2018/12/04/teensy-liberates-the-thinkpad-keyboard/
The goog buffered up a few more hits in the last week.
They might have better scanning examples. They're all using the internal pullups in a variety of microcontrollers. Good luck finding any resistance values or part numbers. 1 commenter guessed they were using 33k. The STM32 is rated for 50k. The problem is the reliability of all these projects in different RF conditions, style of typing.
Modern PC keyboards under $150 are all junk, nowadays. Economies of scale & demand has pushed all the good stuff to phones.
It was a high risk to make a board just for 1 rare 15 year old laptop keyboard of questionable quality, from an e-machine.
Acer MP-09B23U4-6983 PK130C93A00
All lions remember was it was a very good feeling keyboard with a buckling spring feel.
Recycled a 13 year old stm32 because it had enough pins, USB, & it was free. Nowadays, there would be no reason to use anything but an RP2040. It's always fun to see what these old chips were running in their original robots. Sadly, the flat flex cables are not standardized & the flat flex connectors aren't reusable.
It's amazing to see what lions programmed long ago & forgot. Developing the flash filesystem in this one was forgotten. The bootloader lions wrote 13 years ago still worked.
------------------------------------------------------------------------------------------------------------------------------------------------
The 26 pins connect to rows & columns. The game is to set 1 pin to 0 while pulling the other 25 high. Then press keys while observing the voltages on the 25 high pins to try to discover the pinout. For this keyboard, it actually has some pins enable sectors of keys & other pins detect keys in the sectors.
You have to make a table converting pin voltages to event codes. This requires sniffing a real keyboard using wireshark to get the codes that go in the USB packets. It needs to sniff the usbmon corresponding to the bus number & the filter needs to contain the device number. For lions, the bus is 5 & the device is 5 so the device is usbmon5 & the filter is usb.device_address==005.
Then come the USB descriptors, which are probably the same as https://github.com/heroineworshiper/cp33/blob/master/elan.X/main.c with some changed bits. It also requires copying bits from an arduino keyboard library https://github.com/arduino-libraries/Keyboard
There were some more bits in
https://github.com/julianschuler/USBKeyboard/blob/master/usbdrv.c
This was the most difficult USB class lions ever worked on. The CDC ACM & mouse classes were a lot more forgiving but the keyboard class for some reason is just incredibly obtuse. A byte for byte comparison on wireshark between the custom keyboard & a store bought keyboard was the only way. The HID report descriptor just had to be copied. None of the internet examples worked.
It became clear that it would be far easier & more modern to connect to it over bluetooth. The USB keyboard class was invented over 25 years ago. The only advantages with USB were cost savings, less parts, simpler configuration, more practical in a self contained, custom laptop. Most of the custom laptop concepts called for a wireless keyboard though. The CPU would stay in a backpack while only the interfaces would be in the lap.
At minimum, everyone now uses an arduino library to do it, rather than the elementary CMSIS library from 2011 lions have been using. Support for the STM32 grew from the CMSIS library to a HAL layer & then the arduino library in the last 15 years but each layer is slower. Some early lion programs were maxing out the system calls to stream video & bit bang I2S so the CMSIS library became the baseline.
-------------------------------------------------------------------------------------------------------------------------------------------
Then B13, D8 started erroring low when USB was on. The 2 pins neighboring USB were problematic even though they weren't set to AF. The only thing that worked was rerouting them to farther pins.
Finally came the usual grounding jumper to escape the bootloader.
In brief amounts of typing, it was still dropping a lot of keypresses like the others. The prime suspect is a case where...
Read more »
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates