Programing with a PICkit 2 on Linux

January 8, 2020

I recently bought a PICkit 2 clone (the ICA03) from PICCircuit.com. Programming it has been something of a challenge, mostly because Microchip no longer really supports Linux programming of PIC chips.

First, I needed to get pk2cmd. There are lots of pointers to Microchip’s website, but all of them go to 404s. What I ended up using is a github repo: https://github.com/psmay/pk2cmd. After reading the threatening license agreement, I cloned the repo and built it with make then sudo make install.

git clone https://github.com/psmay/pk2cmd
cd pk2cmd/pk2cmd
make linux
sudo make install

Even after installing PK2DeviceFile.dat in /usr/share and including /usr/share/pk2 on the path (ugh) per the instructions, I still wasn’t able to use it from anywhere except the directory I built it from. At some point I’ll need to look into that.

I plugged the PIC into the ZIF socket with the marking near the top, and made sure the selection switch was on 28-40.

Next, I took my .hex file and stuffed it in ~/pk2cmd/pk2cmd/. Then:

~/pk2cmd/pk2cmd$ sudo pk2cmd -P
Auto-Detect: Found part PIC16F886.

Yay! Let’s try writing the file:

~/pk2cmd/pk2cmd$ sudo ./pk2cmd -PPIC16F886 \
 -f my_hex_file.hex -MPC -Y

(I didn’t include IE on the -M switch because I think my hex file has ID and EEPROM memory in it. -Y does the verification.)

PICkit 2 Program Report
8-1-2020, 23:12:12
Device Type: PIC16F886

Program Succeeded.
PICkit 2 Verify Report
8-1-2020, 23:12:12
Device Type: PIC16F886

Verify Succeeded.

Operation Succeeded

Yay!


Mapping a USB volume knob into a keyboard on Linux for SDR

December 16, 2019

I recently discovered the existence of USB volume knobs. A Reddit user posted an article about reflashing the firmware on one to convert it to a keyboard.

 

IMG_20191216_010138

Inspired, I picked one up for $18 on eBay (“USB Volume Controller Knob Adjuster Switcher for Tablet PC Speaker Audio“) and thought that I might be able to do something similar.

It turns out, under Linux, this is pretty easy.

First, I plugged in the volume knob and saw that Linux detected it correctly and used it to adjust the volume. That was a promising start. I could see it show the “HDMI / DisplayPort” volume – and it went up when I turned the knob to the right, down when I turned the knob to the left, and muted when I pressed the knob.

Next, I wanted to see what events were being generated. I found some very useful instructions at https://yulistic.gitlab.io/2017/12/linux-keymapping-with-udev-hwdb/ and did them:

$ cat /proc/bus/input/devices
...
I: Bus=0003 Vendor=0483 Product=572d Version=0111
N: Name="STMicroelectronics USB Volume Control"
P: Phys=usb-0000:00:1d.0-1.7.2.4.3.1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.7/2-1.7.2/2-1.7.2.4/2-1.7.2.4.3/2-1.7.2.4.3.1/2-1.7.2.4.3.1:1.0/0003:0483:572D.0008/input/input14
U: Uniq=2070363C4250
H: Handlers=kbd event8 
B: PROP=0
B: EV=13
B: KEY=3800000000 e000000000000 0
B: MSC=10
...

This showed me a few useful things:

  • The device vendor for my device is 0483 (the “I:” line)
  • The product ID for my device is 572d (also on the “I:” line)
  • The device is attached on /dev/input/event8 (on the “H:” line)

So now I could scan the events that came across when I moved the knob:

$ sudo evtest /dev/input/event8
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x483 product 0x572d version 0x111
Input device name: "STMicroelectronics USB Volume Control"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 113 (KEY_MUTE)
    Event code 114 (KEY_VOLUMEDOWN)
    Event code 115 (KEY_VOLUMEUP)
    Event code 163 (KEY_NEXTSONG)
    Event code 164 (KEY_PLAYPAUSE)
    Event code 165 (KEY_PREVIOUSSONG)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)
Event: time 1576479720.245227, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1576479720.245227, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1576479720.245227, -------------- SYN_REPORT ------------
Event: time 1576479720.253248, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1576479720.253248, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1576479720.253248, -------------- SYN_REPORT ------------
Event: time 1576479722.325231, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1576479722.325231, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1
Event: time 1576479722.325231, -------------- SYN_REPORT ------------
Event: time 1576479722.333224, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1576479722.333224, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 0
Event: time 1576479722.333224, -------------- SYN_REPORT ------------
Event: time 1576479724.381251, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e2
Event: time 1576479724.381251, type 1 (EV_KEY), code 113 (KEY_MUTE), value 1
Event: time 1576479724.381251, -------------- SYN_REPORT ------------
Event: time 1576479724.389251, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e2
Event: time 1576479724.389251, type 1 (EV_KEY), code 113 (KEY_MUTE), value 0
Event: time 1576479724.389251, -------------- SYN_REPORT ------------

Neat, even more useful things. In particular:

  • When I turn the knob to the right, I get an MSC_SCAN event of type c00e9 (along with a KEY_VOLUMEUP event)
  • When I turn the knob to the left, I get an MSC_SCAN event of type c00ea (along with a KEY_VOLUMEDOWN event)
  • When I push on the knob, I get an MSC_SCAN event of type c00e2 (along with a KEY_MUTE event)
  • Apparently the firmware supports KEY_NEXTSONG, KEY_PREVIOUSSONG and KEY_PLAYPAUSE as well. Huh.

I want to map those MSC_SCAN events to different key codes. In particular, I want a cursor-left key when I turn the knob to the left, a cursor-right key when I turn the knob to the right, and something useful (say, pressing the “m” key) when I press the knob. So I created a hwdb file for my device:

$ cat /etc/udev/hwdb.d/99-usb-knob.hwdb
evdev:input:b*v0483p572D*
 KEYBOARD_KEY_c00ea=left
 KEYBOARD_KEY_c00e9=right
 KEYBOARD_KEY_c00e2=m

You’ll recognize the vendor (0483) and the device (572d) that I found earlier. It’s important to use uppercase hex codes for vendor and product in the hwdb file – but not for the scan codes, which should be lowercase. The values on the right have to be lowercase, and correspond to the KEY_LEFT, KEY_RIGHT and KEY_M values from /usr/include/linux/input-event-codes.h. (You can pick any of the KEY_ values from there.) Then a quick bit of Linux magic to update the hardware database:

$ sudo systemd-hwdb update
$ sudo udevadm trigger

…and… exactly the same as before. I got the volume control displayed when I turned the knob.

After scratching my head and doing some searching, I happened on https://catswhisker.xyz/log/2018/8/27/use_vecinfinity_usb_foot_pedal_as_a_keyboard_under_linux/ which gave me the clue I needed. My knob was being detected, but not as a keyboard – so it wasn’t being used as a keyboard input device.

So I created this file:

$ cat /etc/udev/rules.d/99-usb-knob.rules
ACTION=="add|change", KERNEL=="event[0-9]*", 
 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="572d",
 ENV{ID_INPUT_KEYBOARD}="1"

(That’s all on one line on my machine.) You’ll recognize the vendor and product ID from earlier, using lowercase for the hex this time. I added ID_INPUT_KEYBOARD to the list of attributes for this device.
Unplug the device, plug it back in, and hooray! I’m doing what I wanted to! When I turn the knob left, I go left. When I turn the knob right, I go right. When I press the knob, “m” shows up on the screen.

Now I just need to install an SDR program… and an SDR….


Updating OpenBSD

August 12, 2019

OpenBSD has a few different mechanism to update, depending on what the update is for.

For packages:
pkg_add -u

For the kernel and base system:
syspatch

For firmware:
fw_update

All of these need to get run with doas if you’re not root.

Finally, if you’re moving from one version to another:
sysupgrade
sysmerge
pkg_add -u


Using an esp32 as an iBeacon

August 4, 2019

I recently discovered the esp32, which is an interesting device that has Bluetooth as well as wifi built in. That got me thinking about setting one up as an iBeacon.

First, I added my board in the File->Preferences->Additional Boards Manager URLs: https://dl.espressif.com/dl/package_esp32_index.json was what I needed.

My next move was to install the 1.0.1 version of ESP32 BLE Arduino by Neil Kolban. Tools->Manage Libraries-> Select 1.0.1 and click Install.

From there, the BLE iBeacon example should be available. Under “Examples from Custom Libraries” you’llĀ  File->Examples and under “Examples from Custom Libraries” you’ll see ESP32 BLE Arduino->BLE_iBeacon.

Strangely, this example gets the BLE ID backwards according to my scanner app. It looks as if there might be a fix in the latest (1.0.1-dev) source, but for now I just enter my UUID backwards. On the line

#define BEACON_UUID "00112233-4455-6677-8899-aabbccddeeff" // UUID 1 128-Bit

I use instead:

#define BEACON_UUID "ffeeccdd-bbaa-9988-7766-554433221100" // UUID 1 128-Bit

Thanks to C, I didn’t need to do the two’s complement of the signal power myself:

  oBeacon.setSignalPower(-58);

Finally, I was getting advertising packets for multiple things (including an old test I’d tried). I had to erase the flash:

esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash

and then re-download in order to have only my iBeacon transmitting.


Changing the search bar text outside of Thunderbird

June 29, 2019

I run Thunderbird on a shared Samba drive. Because of that, it crashes. I know, it’s not supported. But I want to be able to load the profile from multiple clients – one at a time – and can live with it.

Frustratingly, sometimes it doesn’t crash. That means every time I start Thunderbird, the text in the search bar is the thing I searched for back in 2018. I finally got annoyed enough at that to figure out how to change it.

In the Thunderbird profile is a file called session.json which includes what the last session state was. Inside that is the “quickFilter”, which determines what the filter shows. Mine was:

{"quickFilter":{"filterValues" : {"text" : {"text" : "thing I didn't want to search for anymore", "states" : {"sender" : true, "recipients" : true, "subject" : true, "body" : false}}, "results" : 8}, "visible" : true}}

I replaced “thing I didn’t want to search for anymore” with “” and life was good. Incidentally, I usually want to quick filter by sender, recipients, subject but not body – you can set all those with the appropriate booleans.

If you never want to see the quick filter, “visible” : false is your friend.


Finding out which disk is which on Ubuntu

June 9, 2019

My file server often has various disks swapped in and out. It can get confusing which /dev/sd? corresponds to which drive. While reading the man page of findfs, I stumbled on this:

The complete overview about filesystems and partitions you can get for example by:
  lsblk –fs
  partx –show
  blkid

These three things (along with judicious use of e2label and the other *label commands) is going to make my life a lot easier!


Fixing Brother printing on Ubuntu

March 15, 2019

Since moving to Ubuntu 16.04.3, printing to my Brother MFC-J650DW printer has been broken. I can print fine, but it’s always offset by a bit, never where it should be on the page.

Turns out this is a bug and there’s a workaround. So I don’t forget next time I set up printers:

lpadmin -p "Brother_MFC_J650DW" -o pdftops-renderer-default=pdftops