The other day I was sorting some of my old hardware and found a cheap USB optical mouse I had in a box, so I thought it would be interesting to recycle it into something more... interesting? cooler? unnecessary over-tinkered? Whatever.

I wanted to learn more about USB communications and the V-USB library I discovered some months ago (I'm also using it to connect a NES Mini Controller as a USB gamepad - details in the future, hopefully) so I decided to build a keyboard inside the mouse with an attiny85.

The inital idea is pretty simple: the microcontroller controls three buttons to switch between selected characters and can send them (or a fixed one with the third button - the backspace) using the V-USB library.

On the "computer side" the connected usb device is recognized as a generic keyboard. This can be done sending the proper USB descriptors according to the standard. Then, each "report" will tell the new keys pressed, the mod-keys and so on (still learning on that, so the core is a simple keyboard example from the V-USB libs with some modifications to fit the rest of the logic control, the button behaviour and the leds).

One of the main and most notorious limitations when doing this was the small number of pins on the attiny85: it has 6 I/O pins - 8 with VCC and GND -, but since one of them is the RESET one (and I don't want to re-fuse it because that will disable the regular programming stuff) this left me only FIVE pins to work with.

This means FIVE pins for:

  • THREE buttons
  • TWO USB lines (Data+ and Data-)
  • THREE control pins for a 74HC595N 8-bits shift register (with these three pins I can control up to 8 outputs. In my case I use it to control the 5 leds for the visual feedback or "show me which key it's selected right now")

Since the two USB lines are interrupt-related I "reserved" two pins only for them and "multiplexed" the other three pins into INPUTS (reading the buttons) and OUTPUTS (sending the proper data to communicate the state of the selected keys).

So, in one "cycle"/"iteration":

  1. The three pins are set to "input mode", reading the buttons and performing the pressed-unpressed button logic.
  2. The same three pins are set to "output mode", outputting in the proper order the sequence of bits representing the selected key. The leds work as a binary counter, so with each new selected key the value will increase by one (1 for 'a', 2 for 'b', etc. - as a side note, this could also be some ascii code to be more intuitive, but as a quick and raw proof of concept it does the work).
  3. The USB report is sent (it was all set and ready on the beginning).
  4. Victory dance. Repeat.

This "change the pins" thing causes a little bit of flickering with the leds, but it works surprinsingly well (didn't think this could be a valid solution, since I have little experience with this kind of devices). Some resistors between the buttons and the pins are necessary in order to change between input and ouput without any trouble, but that's all the changes I did for that.

The main soldered board is hooked on the buttons from the -almost empty now- original mouse board, leaving almost no space to work with (again, as a side note, I need to work with proper wire length!). It's solved with some pressure when closing it, but sometimes it seems to be unstable and even stops working.

Some spacing rework may be done here, of course, but that's something I will do (or not) in the upcoming future. For now, I'm proud on how I solved most of the problems I've encountered and I learned some useful things both about the hardware and the software running on it.

Also, I have a keyboard-in-a-mouse now!