Jakub Tiller, Jan Kolář, UREL, FEEC, VUT Brno
xtille00stud.feec.vutbr.cz, xkolar
stud.feec.vutbr.cz
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.
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.
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.
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.