jojolebarjos / vusb-gamepad

Minimal USB-based gamepad, using V-USB and ATtiny84/85

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Minimal HID Gamepad using V-USB on ATtiny84 and ATtiny85

This is a small experiment to create a driver-less gamepad from an ATtiny84 (using external crystal) or an ATtiny85 (using internal PLL clock).

Getting started with ATtiny85

First, reproduce the hardware setup, as described in schema/internal.pdf.

Then, connect your ISP (provided makefile assumes Arduino as ISP on COM3). Go to the code/internal subfolder and run:

make
make flash
make upload

You can test the gamepad using this website.

Hardware design

A few notes regarding hardware components:

  • The system operates at 5v, as provided by USB host.
  • As suggested by V-USB documentation, two 3.6V zener diodes are used to limit voltage of D- and D+.
  • A pull-up (through a 1.5kOhm resistor) is applied on D-, to announce low speed.
  • Do not forget to also connect D+ to INT0 (or to rearrange pins a bit).
  • If the pins on which D- or D+ are connected are also used to program the ATtiny, make sure to disconnect the programmer.
  • 10k resistors are used as pull-up/-down to avoid dangling pins.
  • De-coupling capacitors are used on USB's VCC and near the ATtiny.

ATTiny84 variant:

  • An external 16MHz crystal is used instead of internal clock, as the ATtiny84 internal clock cannot reach minimum requirements.

ATtiny85 variant:

  • The internal PLL clock is set to 16MHz, and then over-clocked using OSCCAL.

For more details, please refer to the schematics in the schema folder.

Software details

A few notes regarding software components:

  • Using V-USB (2012-12-06).
  • The following constants have been modified in usbconfig.h:
    • USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT and USB_CFG_DPLUS_BIT, to match the schematic.
    • USB_CFG_HAVE_INTRIN_ENDPOINT and USB_CFG_INTR_POLL_INTERVAL, to enable interruptions.
    • USB_CFG_MAX_BUS_POWER, to announce low consumption.
    • USB_CFG_DEVICE_NAME and USB_CFG_DEVICE_NAME_LEN, set to Gamepad.
    • USB_CFG_DEVICE_CLASS and USB_CFG_INTERFACE_CLASS, to enable HID descriptor.
    • USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, which match our HID in the code.
  • HID descriptor made using HID Descriptor Tool.
  • The HID interface is a gamepad with a single button (note the 7 bits of padding).
  • Watchdog timer is enabled, to allow automatic reboot on freeze.
  • The makefile assuming that the AVR toolchain is available in the path (e.g. the ones shipped with Arduino IDE).
  • Using avrdude.conf and empty_all.hex from ATTinyCore (1.4.1).

ATtiny85 variant:

  • In usbconfig.h:
    • USB_RESET_HOOK is uncommented, and a forward definition for hadUsbReset is provided.
    • USB_CFG_HAVE_MEASURE_FRAME_LENGTH, to define usbMeasureFrameLength, which is used to callibrate the clock.
  • In main.c, hadUsbReset is implemented. A binary search is done to reach 16.5MHz by tweaking OSCCAL. The code is taken from this blog.

Additional information

This section provides basic instructions, where some of them are actually unnecessary for this project. Hopefully it will help somebody in the future...

Programming an ATtiny84 with an Arduino Micro

Tested with Arduino IDE 1.8.13 and ATTinyCore 1.4.1

First, we need to install a dedicated board manager, to handle the ATTiny family. The ATTinyCore project provides the necessary tools to use Arduino as ISP for an ATTiny84.

  1. In File >> Preferences, add this link to the Additional Boards Manager URLs:
    http://drazzy.com/package_drazzy.com_index.json
    
  2. In Tools >> Board >> Board Manager, install the ATTinyCore package by Spence Konde.

Then, install Arduino ISP sketch:

  1. Connect the Arduino Micro using USB.
  2. Load the ArduinoISP example (File >> Examples >> ArduinoISP).
  3. In Tools >> Board, select Arduino Micro.
  4. In Tools >> Port, select the desired Arduino Micro.
  5. In Tools >> Programmer, select AVR ISP (default).
  6. Select Sketch >> Upload.

Finally, burn the desired code to the ATTiny84. As an example, you can use Examples >> 01.Basics >> Blink, where you need to replace LED_BUILTIN by 0.

  1. In Tools >> Board >> ATTinyCore, select ATTiny24/44/84(a) (No bootloader).
  2. In Tools >> Chip, select ATTiny84(a).
  3. In Tools >> Clock, select 1MHz (internal).
  4. In Tools >> Programmer, select Arduino as ISP (ATmega32U4, ATTinyCore).
  5. Select Tools >> Burn Bootloader to set ATtiny's fuses.
  6. Select Sketch >> Upload.

For more details, see this page.

Using avrdude directly

You might want to enable verbosity in File > Preferences, which shows actual commands sent with avrdude in Arduino IDE

Still assuming Arduino as ISP, you can use avrdude to interact with the ATtiny84 directly. Here we read the values of the fuses:

cd <arduino>/hardware/tools/avr/bin
./avrdude \
    -C <user>/AppData/Local/Arduino15/packages/ATTinyCore/hardware/avr/1.4.1/avrdude.conf \
    -v \
    -p attiny84 \
    -c arduino \
    -P COM3 \
    -b 19200 \
    -U lfuse:r:-:i

See this page for more fuse manipulation.

You can also directly send some hex file you compiled manually. See the manual for details.

COM ports in Python

The serial package can be used to communicate directly with a device on a COM port.

from serial.tools.list_ports import comports

ports = comports()
port = ports[0]
...

References

About

Minimal USB-based gamepad, using V-USB and ATtiny84/85

License:GNU General Public License v3.0


Languages

Language:Assembly 48.8%Language:C 40.1%Language:PHP 10.8%Language:Makefile 0.3%