Úprava joysticku ze standardu Gameport na standard USB-HID

Jakub Tiller, Jan Kolář, UREL, FEEC, VUT Brno
xtille00stud.feec.vutbr.cz, xkolarstud.feec.vutbr.cz

Obsah:

  1. Úvod
  2. Realizace
  3. Závěr
  4. Literatura

Model
Obr. 1 Čelní pohled na upravovaný joystick

Úvod

Protože nová PC postrádají starý Gameport byla hledána možnost, jak využít starý HW pracující na tomto standardu tak, aby byl použitelný se standardy používanými v současnosti. Prakticky veškeré jednoduché herní zařízení dnes pracují se standardem USB-HID, který má tu výhodu, že není třeba psát ovladače pro jednotlivé operační systémy. Tyto systémy již ovladače pro tento standard obsahují.

Tato práce se tedy zabývá software implementací standartu USB-HID do procesoru ATmega8. Dále se práce zabývá návrhem hardware pro snímání polohy jednotlivých ovládacích prvků joysticku.

Realizace

Pro implementaci standardu USB-HID byla využita knihovna V-USB dostupná na www.obdev.at. Tato knihovna podporuje velké množství procesorů vyráběných firmou Atmel. Knihovna je stále vyvíjena.

Knihovna využívá minimálně dvou pinů procesoru. Jeden z těchto pinů musí být INT0 (externí přerušení). Signály DATA+ a DATA- z USB mobou být přivedeny na jakékoliv piny procesoru s tím omezením, že signál DATA+ musí být zároveň přiveden na zmiňovaný pin INT0 (PD2). Pro použití knihovny je klíčové vyplnit deskriptor zařízení (joysticku) a konfigurační soubor usbconfig.h. Deskriptor zařízení popisuje funkci, mezní hodnoty, velikost místa v paměti pro data. Konfigurační soubor usbconfig.h definuje mimo jiné VIP/PID identifikátory, velikost deskriptoru zařízení, využívané piny pro USB implementaci, omezení proudové spotřeby, dále zda je zařízení napájeno externím zdrojem a v neposlední řadě například jméno zařízení. S přihlédnutím na omezení dané knihovny ( použitý krystal a výstupní piny) byl navržen obvod podle obrázku níže.

Schema zapojeni
Obr. 2 Schéma zapojení

Obvod kromě dvou pinů nutných pro USB využívá 5 AD převodníků (4 osy joysticku + jeden zatím nevyužitý) a ceklem 5 pinů pro tlačítka. Použitý krystal pracuje na kmitočtu 16 MHz. Tento krystal je do popisované knihovny přidán až v několika jejich posledních verzích. Celé zařízení pracuje s napájením 3,3V a to z toho důvodu, že USB komunikuje na logice s tímto napájením. Protože je napětí USB +5V, bylo třeba využít Low-Drop stabilizátor. Samozřejmostí je implementace ISP konektoru pro potřeby programování přímo v aplikaci.

Firmware

Práce na projektu dále pokračovala psaním zdrojového kódu. Ověření SW implementace standardu USB-HID je nejprve ověřeno převzetím projektu USB myši implementované do ATmega8. Tento projekt je součástí .zip souboru s knihovnou. Po ověření funkčnosti je přistoupeno k tvorbě deskriptoru zařízení pro správnou činnost joysticku s výše zmiňovanými funkcemi.

Pro tvorbu deskriptoru byl využit program, který je na stažení přímo na stránkách www.usb.org, okdaz na program je zde. Deskriptor je následující:

	PROGMEM char usbHidReportDescriptor[68] = { /* USB report descriptor, size must match usbconfig.h */ 
          0x05, 0x01,	// USAGE_PAGE (Generic Desktop)
          0x09, 0x04,	// USAGE (Joystick)
          0xA1, 0x01,	// COLLECTION (Application)
          0xA1, 0x00,     // COLLECTION (Physical)
          0x09, 0x30,	    // USAGE (x)
          0x09, 0x31,	    // USAGE (y)
          0x35, 0x81,	    // PHYSICAL_MINIMUM (-127)
          0x45, 0x7F,	    // PHUSICAL_MAXIMUM (127)
          0x75, 0x08,	    // REPORT_SIZE (8)
          0x95, 0x02,	    // REPORT_COUNT (2)
          0x81, 0x02,	    // INPUT (Data,Var,Abs)
          0x05, 0x09,	    // USAGE (Button)
          0x19, 0x01,	    // USAGE_MINIMUM (Button 1) 
          0x29, 0x04,	    // USAGE_MAXIMUM (Button 4) 
          0x15, 0x00,	    // LOGICAL_MINIMUM (0)    
          0x25, 0x04,	    // LOGICAL_MAXIMUM (1)   
          0x75, 0x01,	    // REPORT_SIZE (1)				 
          0x95, 0x08,	    // REPORT_COUNT (8)        
          0x81, 0x03,	    // INPUT (Csnt, Var, Abs)
          0xC0,	          // END_COLLECTION          
          0x05, 0x02,	  // USAGE_PAGE (Simulation Controls) 
          0x09, 0xBB,	  // USAGE (Throttle)            
          0x15, 0x81,	  // LOGICAL_MINIMUM (-127)    
          0x25, 0x7F,	  // LOGICAL_MINIMUM (127)     
          0x75, 0x08,	  // REPORT_SIZE (8)            
          0x95, 0x01,	  // REPORT_COUNT (1)           
          0x81, 0x02,	  // INPUT (Data,Var,Abs)        
          0x05, 0x02,	  // USAGE_PAGE (Simulation Controls) 
          0x09, 0xBA,	  // USAGE (Rudder)                 
          0x15, 0x81,	  // LOGICAL_MINIMUM (-127)        
          0x25, 0x7F,	  // LOGICAL_MINIMUM (127)        
          0x75, 0x08,	  // REPORT_SIZE (8)                
          0x95, 0x01,	  // REPORT_COUNT (1)               
          0x81, 0x02,	  // INPUT (Data,Var,Abs)           
          0xC0,	       // END_COLLECTION                   
      };
	
Jak je z deskriptoru patrné, je uložen v paměti programu, což značným způsobem šetří paměťové prostředky. Vzhledem k jeho délce, tedy v tomto případě 68 bytů, je to ušetření značné. Deskriptor vlastně říká, co je to za zařízení a jaká data by od něho PC mělo čekat. Na druhém řádku tedy je záznam o tom, že se jedná o joystick. Dále v COLLECTION (Physical) je uvedeno, že jsou zde 2 osy (osa x a osa y). Rozmezí jejich hodnot je od -127 do 127. REPORT SIZE potom udává, kolik bitů je třeba vymezit pro data každé z os, REPORT_COUNT říká, kolik proměnných o délce 8 bitů je třeba. Následuje definice tlačítek. Každé z tlačítek může nabývat hodnot 0 nebo 1 a proto pro každé tlačítko stačí 1 bit. Rezervováno je 8 bitů, přičemž využité jsou pouze 4. Dále jsou definovány funkce THROTTLE, tedy otáčky motoru a RUDDER, tedy směrovka. Obě mají rozmezí hodnot od -127 do 127 s délkou slova 8 bitů. Na základě tohoto deskriptoru byl definován typ struktury. Níže je uvedena společně s alokací jednotlivých bitů.
/* The data described by this descriptor consists of 5 bytes:
 *     X7 X6 X5 X4 X3 X2 X1 X0 .... 8 bit signed coordinate x
 *     Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 .... 8 bit signed coordinate y
 *      .  .  .  . B3 B2 B1 B0 .... one byte with joystick button states
 *     T7 T6 T5 T4 T3 T2 T1 T0 .... 8 bit signed throttle
 *     R7 R6 R5 R4 R3 R2 R1 R0 .... 8 bit signed rudder
 */ 
typedef struct{
  char   dx;	   // one byte to handle coordinate x
  char   dy;	   // one byte to handle coordinate y
  char	 buttons;  // one byte to handle all buttons
  char   throttle; // one byte to handle throttle
  char 	 rudder;   // one byte to handle rudder
}report_t;

Kromě dalšího se firmware skládá z funcke, která má za úkol zjistit stav všech čidel, tedy převod jednotlivých AD kanálů a zjistit stav tlačítek. Protože je v hlavní smyčce funkce USBPoll();, která má za úkol obstarávat potvrzování nastavovacích zpráv, je důležité hlídat časování hlavní smyčky. Doba výkonu funkce pro zjištění stavu jednotlivých senzorů byla pomocí AVR Simulatoru stanovena na 877.5 us, což je v pořádku. Uvedenou funkci USBPoll() je třeba volat minimálně jednou za 50 ms. AD převod je řízen funckí z knihovny adc_driver.c, která byla vytvořena jedním z autorů projektu. V hlavním souboru main.c potom byla vytvořena funkce, která tuto knihovnu používá:

	unsigned int adc_get(unsigned char ADCx)
  {
	   unsigned int ADCval = 0;
	
	   ADMUX &= 0b11100000;
	   ADMUX |= ADCx;
	   ADCSRA |= (1 << ADSC);
	   while(!(ADCSRA & (1 << ADIF)));
	   ADCval = ADC;

	   return(ADCval);	
  }
	
Tato funkce nastaví příslšný ADCx kanál (parametr funkce), zahájí převod a čeká, dokud není převod hotov. Nakonec vrátí 10-bitové číslo odpovídající napětí na vstupu daného AD kanálu. Definové hodnoty v deskriptoru jsou od -127 do 127, tedy 8-bitové a je tedy třeba hodnoty upravit. Je třeba od hodnot odečíst hodnotu, při jakou AD převodníky mají v případě klidové polohy ovladačů. Tato hodnota byla určena pro jeden z ovladačů a její velikost je 576. Tato hodnota je odečítána a dále je číslo děleno čtyřmi. Výsledná hodnota je tedy znaménkové 8-bitové číslo. Kód například pro ovladač otáček motoru:
	reportBuffer.throttle = (int8_t)((th - ADC_OFFSET) >> 2);
	
Pro obsluhu tlačítek byla využita knihovna keyb_drv.c, která byla také vytvořena jedním z autorů. Protože ale je tato knihovna psaná pouze pro využití jednoho portu, bylo nutné v hlavním souboru do dané proměnné na vhodné místo přidat čtení z jednoho pinu na portu D (zbylá tlačítka jsou na portu B).

Na obrázku níže je uveden model DPS, kde nejsou zobrazeny modely přepínačů ani potenciometrů. To proto, že nejsou ani na finální hotové DPS. Jsou totiž umísteny na různých místech joystiku a mají za úkol snímat jednotlivé osy a také funkce joystiku.

Model
Obr. 3 Model DPS

Model
Obr. 3 Realizovaná DPS připevněná ve funkční realizaci joysticku

Závěr

Výsledkem projektu je funkční joystick využívající standardu USB-HID. Obsahuje čtyři ovladače pro plynulé nastavení polohy, tedy osu x,y dále nastavení otáček motoru a ovladač směrovky. Dále joystick obsahuje 4 tlačítka. Joystick je možné dále rozšířit. Z pohledu HW je zde jeden vyvedený konektor pro další potenciometr. S tím by bylo možné například plynule ovládat vztlakové klapky. Samozřejmostí je také možnost rozšíření počtu tlačítek. Joystick byl testován na operačních systémech Windows 7 64-bit a Windows 7 32-bit, kde pracoval bez problémů.

Celý projekt obsahující zdrojový kód pro procesor ATmega8, soubory pro Eagle a také soubory s předlohami pro výrobu prošných spojů je možné stáhnout zde.

Literatura

[1] ATMEL ATmega8 datasheet. [Cit. 22.2.2012] Dostupný z www: http://www.atmel.com/Images/doc2486.pdf
[2] http://www.obdev.at/products/vusb/index.html Domovské stránky knihovny pro SW implementaci USB do AVR. [Cit. 22.2.2012] Dostupný z www: http://www.obdev.at/products/vusb/index.html
[3] USB Implementers’ Forum Specifikace standardu USB HID. [Cit. 22.2.2012] Dostupný z www: http://www.usb.org/developers/devclass_docs/HID1_11.pdf