Thursday, April 10, 2025
The trials of installing a modern linux distro on an original Pentium laptop with 80MB of RAM
Wednesday, August 07, 2024
Simple Fix for WSL2 and GlobalProtect VPN
I ran across this today and am documenting it in case it helps others. To make WSL work with GlobalProtect VPN, add the following into a file called "wslconfig" under your %USERPROFILE%\ directory:
[wsl2]
networkingMode=mirrored
dnsTunneling=true
Then in a powershell, run the following:
wsl --shutdown
wsl --update
Now when you start wsl, it should have network access.
Friday, April 14, 2023
Crkbd keymap from configurator json and using kb2040 microcontroller
I wanted to document this for anyone else who's not super familiar with qmk and wants to get a setup working with the kb2040. Here are the steps I followed:
Design a layout on QMK Configurator
https://config.qmk.fm/#/crkbd/rev1/LAYOUT_split_3x6_3
Export the json, e.g. to ~/Downloads/my_custom_keymap.json
Setup QMK on your computer
sudo apt install python3-pip
pip3 install qmk
qmk setup
And setup the keymap
cd ~/qmk_firmware/keyboards/crkbd/keymaps
cp default foo
cd foo
mv keymap.c keymap.c.defaultl
qmk json2c ~/Downloads/my_custom_keymap.json > keymap.c
Then build the firmware and flash it!
The secret sauce here was "CONVERT_TO=kb2040" - I didn't have to modify anything else, it just did what was needed to make this compatible with the kb2040 microcontrollers.
qmk flash -kb crkbd -km foo -e CONVERT_TO=kb2040
Press the boot button on the mcu, plug it into usb, and it should flash. You can run it again for the second half of the kb, or just drag the .df2 over to it.
Thursday, March 30, 2023
Installing VS Code on Raspberry Pi and Ubuntu
The aarch64 build of VS Code is available in Raspberry Pi OS repositories to bi installed directly with "apt install code", but the Ubuntu repos only have x86 and x86_64 versions of code. So we need to manually install code - once we install the .deb package, it adds the Microsoft repo for us to keep it up to date:
Thursday, March 02, 2023
First tests with the new Amp Ripper 4k
I've use the Amp Ripper 3000, from kickstart-design, in previous projects - it is one of the highest quality, most simple to use charger/boost converters available for powering Raspberry Pi and other 5v projects. It's plug-and-play from charger to battery to Raspberry Pi with enough power to run the Pi 4 and has a low-voltage pin to signal when the battery gets low. And its one of the few solutions supporting pass-through-charging so it's suitable for a UPS.
The Amp Ripper 4000 (Kickstarter link) builds on the 3k with loads of improvements:
- Increased 4 amp maximum current supply for more demanding setups.
- I2C reporting of charging/battery voltage, battery percentage, charge/discharge rates via a MAX17084 chip.
- Several large VOUT solder connections.
- Support for a wide range of charging voltages: 5-14v! Charge from 12v automotive systems, solar, etc.
- Battery temperature thermistor support.
- Configurable charging current if you'r adventurous enough to replace a surface mount resistor.
- Power performance - Does it run an Intel Compute Stick m3? (YES!)
- Reading battery charge stats via i2c using a pi 4 and python.
- Reading battery charge stats via i2c using a pi pico and micropython.
- Verifying battery percentage estimates and high/low cutoff voltages.
Raw Power Performance
Reading battery charge stats via i2c
Using a Pi 4 and Python
Wiring Guide
Example Code For Reading Battery Voltage and Percent
Notes for Ubuntu 22.10
Enabling Safe-Shutdown on Low Voltage
Implementing a kernel module to make the power supply and battery appear as a laptop battery for the Raspberry Pi
Monday, October 10, 2022
Micropython - Driving an LCM4004A LCD with dual HD44780 (clone) driver chips
- Define our pins
- Initialize some globals with the values for specific instructions that the contorller understands
- Call the initialize function to turn the display on
- Subsequently use the "write8" function to write characters to the display.
- Figure out how to control the cursor and write to specific locations on the display.
- Figure out how to turn on the backlight.
- Get contrast control working. I tried to do this with a 10k pot, but the display isn't responding.
- Adapt this module to work with the fbconsole library for a fun terminal.
Saturday, August 13, 2022
Micropython - Modifying fbconsole.py to support keystroke injection with os.dupterm
This is something I needed to make an interactive micropython terminal without using the serial connection to interact with it. E.g. a separate library handles keyborad scanning using the pi pico pins and when a keypress is registered, a callback function is used to pass the dupterm instance. Since I want to use fbconsole to display the console on a screen, it made sense to add the needed bits to the fbconsole library to support passing in the keystrokes:
Usage:
In our display module:
And for a callback function, we can use something like this:
To pass in single or multiple characters, you can use the inject method. You'll see them appear in the terminal when the function is called:
fbconsole.py Modifications:
Within fbconsole.py, we add a couple imports, constants, and define self._data in __init__:
And methods in the class:
And finally modify the readinto method.
Finally, in addition to regular numbers, letters, and symbols, you'll need a few ascii codes to pass in enter, backspace, etc as well as ctrl+key cobmos:
I'll do a followup article with more info on ctrl and other special characters. We should be able to pass in arrows to move the cursor, etc.
Finally, this article will be updated with a link to the complete code soon.
Reference:
Tuesday, July 26, 2022
RP2040 Micropython PIO - Part 4 - Using IRQ to signal when pins changes have been pushed!
I'm delighted that this worked exactly as it seemed it ought to. Just like we did in Part 3, we track the pins states and only push them when there's been a change. But now, when we push the changed pins, we toggle the irq.
When we initialize the state machine, we bind a function, "printFromGet" to the state machine irq. When the irq is toggled, this function is called, and a pointer to the state machine is passed to the function. Then we can call sm.get() to read the new pins values. This is fantastic because python doesn't need to spin checking the pins using the gpio library wasting cpu cycles. When we press a key, python is detoured momentarily to our needed function to handle the pin press, and once it returns, python can resume whatever else it was working on!
Here's a more complete code from the last couple examples.
The last thing I might want to do is sort of look up which pin changed and push an integer value corresponding with the addr of the changed pin so each time I do a get() in python, I get the number of the changed pin.
Monday, July 25, 2022
RP2040 Micropython PIO - Part 3 - Pushing pins only on changes
In order to check for changes to the pins, each time we read the pins values, we can compare them to previous values stored in the x or y scratch registers.
So the statemachine records the pin state in y when it starts, pushes y so python has the initial state as well, and then the state machine keeps checking the pins until the pin values cached in x aren't equal to y. Then it pushes x, copies x to y, and starts checking again.
Next step is setting an irq to tell python it's time to pull a value from the fifo.
And maybe later some time, we can implement matrix scanning! I'm not too sure how that would work since we'd need to potentially track the state of more than 32 keys... maybe we'd use separate state machines for each row of the keyboard!
Sunday, July 24, 2022
RP2040 Micropython PIO - Part 2 - Reading all the pins!
The next thing I wanted to get working with PIO was reading the pin values. I struggled with this until I realized that I needed to initialize the pins and set them to pull_up before starting the state machine. Anyway, here's an example reading all available pins and returning their states on the fifo:
And the output looks like the following. Some of the bits change as I press keys on the keyboard:
>>>MPY: soft reboot
Checking Safety Pin 25...
In Main Now
Couldn't initialize pin: 30
Couldn't initialize pin: 31
0, 00111110111111111111101111111011
1, 00111110111111111111101111111011
2, 00111110111111111111101111111011
3, 00111110111111111111101111111011
4, 00111110110101011111101101111011
5, 00111110110101011111101101111011
6, 00111110110101011111101101111011
7, 00111110111111111111101111111011
8, 00111110111111111111101111111011
9, 00111110110101011111101101111011
MicroPython v1.19.1 on 2022-06-18; Arduino Nano RP2040 Connect with RP2040
Type "help()" for more information.
>>>
In Part 3, we'll track the pin states and only output a value when there is a change.
And in Part 4, we'll use an irq to trigger a python function only when there is a key press event so we don't need to keep a cpu core busy watching for button presses.
Saturday, July 23, 2022
RP2040 Micropython PIO - Part 1 - Blinking nop, jmp, and .side experiments!
I'm working on incrementally adding complexity to PIO programs to learn how to use them. Here are a few examples. Note that I'm using Pin 6 for the LED on the Arduino Connect Nano RP2040 board. I think the pin is different for the Pi Pico.
Most Simple Blinking the LED:
Blinking the LED Using sideset and jmp for more nop:
Up next...
Micropython - Safety pin to avoid soft-bricking
I ran into an issue on an Arduino Connect Nano RP2040 board this last week where I got some code in main.py that caused micropython to hang without functional serial or shared drive, so I had no way to change the code and fix it.
It was a little difficult to fix this. A few things I tried:
- Re-flash the micropython uf2 - this doesn't wipe the main.py and other code, so the problem remains.
- Flash circuitpython uf2 - circuitpython stores code at a different addr and works perfectly when flashed, but when you put micropython back, the old broken main.py remains. I even tried to dd a large random data file to the circuitpython shared folder, but somehow it didn't overwrite the micropython content!
- Flash the various nuke uf2 files - It seems that these are all set up for the pi pico, which has 4MB of storage. The arduino board has 8MB of storage and the area micropython uses is unaffected.
- Flash the OpenMV customized version of Micropython. It didn't load the main.py and exposed the same memory/file share that micropython uses so I was able to rename the broken main.py and flash standard Micropython back onto the board to resume working on it!
- https://github.com/openmv/openmv/
from machine import Pin
import time
import sys
PIN_NUM = 25
SAFETY_PIN = Pin(PIN_NUM, Pin.IN, Pin.PULL_UP)
print(f"Checking Safety Pin {PIN_NUM}...")
time.sleep(.1)
if not SAFETY_PIN.value():
print("PIN Shorted to Ground!")
print("Aborting loading and quitting.")
sys.exit()
To use it, I put a key between the two pins shown here and plug the board into the usb port:
Friday, July 08, 2022
Micropython - Keyboard library with chording, layers, etc.
I'm working on a project to build an interacive terminal using micropython, and a component of that is checking for button presses and translating them to keys to be used to control the terminal or however that works.
I've made a couple of attempts at keyboard firmwares in the past and changed strategies this time from key-focused to event-focused - events start when a key is pressed and terminate after either a hold timer or key that is part of the event is released.
Based on the numbers of keys in the event, their functions, and hold duration, we can figure out the correct keyboard key to be returned.
Examples to consider:
- Chords can map combinations of keys to letters, numbers, or symbols,
- A single key, if held for some duration, can trigger a layer shift and then subsequent keys or combinations of keys can result in letters, numbers, etc from that layer.
- Short taps result in a number, letter, etc.
https://github.com/a8ksh4/MicroNote/blob/main/keeb.py




