MAS.863: How To Make (almost) Anything
Kreg Hanning
Lifelong Kindergarten Group
Fall 2016
Week 13: Networking and communications

I have been looking forward to this weeks assignment in HTMaA, networking and communications. Networking will be a major component of my final project, a modular arcade game cabinet interface.

One of my major challenges is figuring out how each button in my arcade cabinet can communicate what keyboard key is assigned to it and it's current state back to a main board which will use USB HID to interact with the host computer. The buttons need to be able to send this information regardless of physical positioning in the interface panel of the cabinet.

This week I decided to try to create a bridge board that uses the v-usb library and receives serial communication from the button "nodes"

I started by creating a custom version of the FabISP without the solder jumpers since I will not be using the board to program other boards.

Using the v-usb library seemed to be pretty straight forward, but initially I had trouble getting it working. After pouring over the schematic and consulting Brian Mayton, I realized that I failed to bridge pins PA7 and PB2 together. Because of the way the v-usb library uses interrupts this step is crucial. After bridging the pins with a bit of solder everything starting working properly!

I spent time reading up about USB HID hardware descriptors and after a bit of trial and error I created a working descriptor that allowed my Linux machine to recognize the board as a USB keyboard. At this point I programmed it to spam my system with the 'b' key at 500ms intervals. Success!


PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)(Key Codes)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)(224)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)(231)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs) ; Modifier byte
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs) ; Reserved byte
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs) ; LED report
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x03,                    //   REPORT_SIZE (3)
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs) ; LED report padding
    0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)(Key Codes)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))(0)
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)(101)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0                           // END_COLLECTION
};

typedef struct {
  uint8_t modifier;
  uint8_t reserved;
  uint8_t keycode[6];
} keyboard_report_t;
          

Here is where the next challenge came up. I needed to read serial data coming in from the buttons, but v-usb is very time sensitive. If I wait for serial data or try to use interrupts the v-usb library fails to connect to the computer. This is because v-usb and my time consuming serial calls are fighting for the processors attention. To work around this issue Eric VanWyk suggested I use a hardware USB solution or try another communication protocol such as SPI. For my final project I will most likely explore the USB hardware options like the atmega32u4.

So I could move forward on networking and not waste too much time on USB HID, I decided that for this example I would just make one button turn on an LED on the bridge board and another button turn it off. To do this one button will send the 1 char (on) when pressed and the other will send the 0 char (off).

Getting this running turned out to be pretty trivial. I followed the example projects and used my FTDI cable for debugging when things weren't working as expected. I am still having trouble getting the 115200 baud rate working on the attiny45 so for now I have fallen back to a baud rate of 9600.

This communication protocol seems like it will work very well in my final project. My only concern is on collisions. What will happen if both buttons are pressed at the same time?