electronics software USB keyboard

Keyboard controller project update

It has been nearly two years since I mentioned the USB keyboard controller project. For most of that time, my primary keyboard at home has been driven by one or another bread-boarded incarnation of it. A few major points on the hardware side:

  • I’ve given up on the PIC and gone back to AVR. I ended up with some bugs which I couldn’t resolve, and I’m not sure they weren’t in the USB stack; I also wasn’t at all sure what the licensing would and wouldn’t allow me to publish.
  • This will mean learning to solder TQFP packages, and getting boards manufactured. Oh well.
  • I’ve decided to target the ATmega32U2 chip – less pins to solder the the U4. It gives up a handful of IO pins, the ADC, 1k of RAM,  and the ability to sense if the USB is plugged in when the device is externally powered. None of which matter for this project.
  • I’m using a pair of 74HC595 shift registers to drive the columns on the keyboard matrix. 16 pins driven for 3 pins on the AVR is a win. It does mean using a diode per column rather than just setting the undriven AVR pins to inputs (to avoid having outputs fight when multiple keys on the same row are held down) but again, I can live with that.
  • Being able to develop on the Adafruit 32U4 board means I have spare outputs for connecting debug LEDs to and more RAM for debug statements.

The software side has made massive advances over the last 3 days (yay for a long weekend!) and I think is now pretty much final. It presents a dual-interface USB device with a “boot keyboard” interface (all the standard keys) plus a generic HID interface for some some non-standard ones (I’ve assigned one to the “System Sleep” code which does exactly the right thing). Things I’ve learnt:

  • LUFA is awesome. Especially when you consider it was mostly written when the author was a student, and responds to bug requests very quickly (and the ones I found were extremely minor!). I found it so much easier to use than the Microchip USB stack as well. Oh, and the demos are brilliant for getting started.
  • Being able to use GCC is good. I don’t like proprietary development environments.
  • Using the hardware serial port for debugging messages is generally good (and you can run it at silly baudrates like 921600, although I’m not sure if that just ends up meaning bigger gaps between characters on the wire…), BUT:
  • Too much debugging output can cause oddness. I spent several hours chasing a “bug” where Linux would often wait 5 seconds between finding the first interface and the second one. Wireshark was showing “malformed packet” coming back from the device. I took out one debug statement which fired every time the device received a Control Request – and the problem vanished.
  • Oh, wireshark can dump the USB bus. Really handy!
  • Git is good. Should have started using it ages ago (I’ve been using RCS. Clearly I’m too old 🙂 )

Next steps?

  • I’ve ordered some 32U2 chips. I’ve also got some Adafruit 32 pin TQFP breakout boards. Hopefully I should end up with one successfully soldered to the other and integrated into the breadboard in place of the current 32U4 board.
  • Experiment with a bootloader. I think I’ll want one that only triggers if you hold a pin in a specific state when plugging the device in. Working with the bare chip I’ll have access to the HWB line, which I don’t on the board I’m using now.
  • Start working on a board layout in something like Eagle or DesignSpark PCB. Don’t think I’m masochistic enough for GEDA. I’ll see how I go soldering the TQFP chips before deciding if I go SOIC for the shift registers (and maybe a diode pack?).

If I can I’ll lay out the board such that it would make a good development board for other purposes. I might add another optional shift register for driving the LEDs – this keyboard only has 3, but even fairly normal keyboards can have 5, and the kernel source seems to recognize another 6 beyond that…

If you are crazy enough to want to build something similar, the code is up on github. The readme should give you a rough idea of how to set up the hardware – main thing to remember is that the scanning is done active low so I can utilize the pull-up resistors built into the chip rather than having to supply pull-down resistors, so the diodes go in backwards to what you might expect!


photography software

Fixing Flickr timestamps and a rant about software timezones

I keep my camera clock on UTC. I do this because there’s no way I am going to remember to fix the time on it every time I go interstate/overseas – or even just change to daylight savings time (or back). And given my camera has no method for entering timezones it is the only way I can be unambiguously sure what the timestamps mean.

I’ve had serious issues getting Flickr to extract the correct timestamps from my photos. It appears to assume that the normal date/timestamp in the Exif data (Exif.Photo.DateTimeOriginal from my camera anyway) is in the timezone you have signed up with. There is a semi-official tag Exif.Image.TimeZoneOffset (part of the TIFF/EP standard but not officially Exif standard), which Flickr appears to ignore – and which is useless anyway since it appears to be in hours, and is an integer (FAIL by whatever committee put that together).

Flickr does provide the ability to shift timestamps on photos, so you can select a whole slab of them and fix them. And guess what… it only works in whole hours!!!!

Really people – NOT ALL TIMEZONES ARE A WHOLE NUMBER OF HOURS OFFSET FROM UTC. And it isn’t just Adelaide – its all of India! That is 1 billion customers you will potentially be annoying! Yet the amount of software which persists in making this daft assumption never ceases to amaze me.


Digression – why is Adelaide on a half-hour offset anyway? There are 360/24 = 15° per hour, so +9 hours would be at 135°E, +9:30 would be at 142°30’E. At 138° 36’E, we are (slightly) closer to +9:00. Given the amount of trouble the oddball timezone causes someone made a really dumb decision. I suppose we should be glad we didn’t end up at +9:15! Oh, and Melbourne – at 144°58’E you really should be on +9:30 🙂

The good news is that I have a (partial) solution for the Flickr issue. It turns out that there are a pair of date/timestamp fields in the GPS data extensions for Exif (Exif.GPSInfo.GPSDateStamp and Exif.GPSInfo.GPSTimeStamp). Even better – these are defined to be in UTC, so there is no ambiguity. Unfortunately just adding these isn’t good enough – but if you also remove Exif.Photo.DateTimeOriginal (and possibly Exif.Photo.DateTime as well, my photos don’t have that), Flickr will actually get the timestamp right. It still assumes your local timezone (and there appears to be no way to fix that), but at least it gets it right in that timezone!

EDIT: now flickr seem to have broken this method as well. GAH!