Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2016:cc2500-hid

Systém bezdrátových herních ovladačů

Vypracoval Stanislav Rozum.

Kompletní zdrojové kódy pro Keil uVision5 jsou ke stažení zde.
Záznam komunikace z logického analyzátoru pro program Saleae Logic v1.2.10 lze stáhnout zde.


Zadání

Realizujte soustavu jednoduchých bezdrátových herních ovladačů. Navrhněte systém pro podporu až osmi ovladačů s odezvou stisku do 30ms. Master jednotka připojená k PC se bude chovat jako HID klávesnice. Každý ovladač pak bude reprezentován jednou klávesou. Pokuste se eliminovat zvýhodnění některých ovladačů, které by mohlo vzniknout vlivem komunikačního protokolu. Využijte rádiové moduly s čipsetem CC2500.

Úvod

Realizace práce byla rozdělena do tří tématických oblastí. V první části se bude věnovat komunikaci mikrokontroléru s rádiovým modulem A2500R24C od společnosti Anaren s čipem CC2500 od Texas Instruments.

Druhá část se bude zabývat komunikačním protokolem pro bezdrátové spojení mezi master jednotkou a jednotlivými ovladači.

Nakonec bude implementována komunikace s počítačem prostřednictvím rozhraní USB pracující ve třídě HID.

Pro realizaci budou použity vývojové kity STM32F429IDISCOVERY jako master jednotka a STM32F4DISCOVERY jako ovladač. Inicializační kód a drivery k perifériím byly vygenerovány pomocí STM32CubeMX. Připojení vodičů z testovacího modulu na vývojové kity bude provedeno podle následující tabulky:

STM32F429IDISCOVERY STM32F4DISCOVERY
MOSI PC12 PB15
MISO PC11 PC2
SCK PB3 PB13
CS PB4 PB4
INT2 PD7 PB5
VCC 3V 3V
GND GND GND

A2500R24C (CC2500)

Komunikovat s CC2500 je možné přes rozhraní SPI. Kmitočet hodinového signálu byl zvolen 2,625 Mbit/s aby mohly být posílány data v burstech. Maximální pracovní kmitočet pro přístup v burstech je podle [1] stanoven na 6,25 Mbit/s, ovšem i při 5,25 Mbit/s docházelo k shiftnutí některých bytů o jeden bit, případně k nastavení bitů do 1 na pozici LSB, bitový posun by mohl být způsoben propojovacími vodiči mezi rádiovým modulem a mikrokontrolérem při vyšších kmitočtech. Pokud by SPI master nepracoval v burst módu, mohl by být hodinový kmitočet vyšší (jednotlivé byty odděleny CS enable/disable a nečinné úseky v hodinovém signálu), ale z časového hlediska vychází burst (dlouhý blok dat s nepřetržitým hodinovým signálem) lépe.

Změnu vnitřních stavů CC2500 je možné provádět pomocí strobe příkazů a operace s registry se provádí zápisem a čtením registrů, kdy v SPI komunikaci po aktivování CS je odeslána adresa registru a v dalším bytu jsou pro zápis odeslány data po lince MOSI, popřípadě pro čtení jsou přijímány bity po vodiči MISO. Osazený modul A2500R24C je na obrázku 1, redukci na 2,54 mm mikro BUS, kde jsou připojeny propojovací vodiče podle popisků zobrazuje obrázek 2. Anténu lze použít libovolnou pro 2,4 GHz, nejlépe však všesměrovou.

cc2500.jpg
Obrázek 1 Osazený modul A2500R24C (modrá DPS) do testovací redukce.

cc2500_r.jpg
Obrázek 2 Redukce konektoru HARWIN na připojení s 2,54 mm roztečí. (alternativa ccRF click )

Rozlišení zda jde o příkaz nebo přístup k registru a čtení/zápis je dáno pomocí 2 bitů z adresního bytu. Uvedené informace byly využity při definovaní funkcí pro snadný a přehledný přistup k CC2500:

bool CC2500_Write_Register(SPI_HandleTypeDef* hspi, CC2500Registers_Enum Reg, uint8_t Data)
{
    uint8_t TxBuff[2];
    uint8_t RxBuff[2];
 
    if (Reg > CC2500_TEST0) return false;
    TxBuff[0] = (Reg & ~READ_SINGLE);   //write only (0x7F)
    TxBuff[1] = Data;
 
    CC2500_SPI_Comm(hspi, TxBuff, RxBuff, 2);
 
    return true;
}
 
uint8_t CC2500_Read_Register(SPI_HandleTypeDef* hspi, CC2500Registers_Enum reg)
{
    uint8_t TxBuff[2];
    uint8_t RxBuff[2];
 
    if (reg <=CC2500_TEST0) TxBuff[0] = (reg | READ_SINGLE);
    else TxBuff[0] = (reg | READ_BURST);                          //burst mode
    TxBuff[1] = 0xFF;
 
    CC2500_SPI_Comm(hspi,TxBuff,RxBuff,2);
 
    return RxBuff[1];
}	
 
 
uint8_t CC2500_Send_Strobe_Command(SPI_HandleTypeDef* hspi, CC2500StrobeCommands_Enum Command)
{
    uint8_t TxBuff[1];
    uint8_t RxBuff[1];
 
    TxBuff[0] = Command & ~WRITE_BURST; //0xBF;    // set Burst bit to  zero                 
 
    CC2500_SPI_Comm(hspi,TxBuff,RxBuff,1);
    return RxBuff[0];
}

Funkce CC2500_SPI_Comm je v tomto případě blokující. K tomuto kroku bylo přistoupeno pro zjednodušení modulu driveru, kdy tak muže funkce vracet přímo hodnotu vyčtenou z SPI slave bez callbacku a velkého množství stavů. Zároveň není konfigurace až na některé případy příliš časově kritická ani časově náročná - není třeba provádět jiné operace během komnunikace. Odesílání a příjem dat již blokující není a využívá jednoduchý stavový automat.

Konfigurace vnitřních registrů vychází z před certifikovaným dat pro maximální přenosovou rychlost 500 kbit/s pro modulaci MSK. Hodnoty, které nemají vliv na splnění certifikačních požadavků, byly upraveny pro potřeby projektu a jsou okomentovány v ukázce:

    CC2500_Write_Register(hspi, CC2500_IOCFG0    ,0x00);	
    CC2500_Write_Register(hspi, CC2500_IOCFG1    ,0x00);	
    CC2500_Write_Register(hspi, CC2500_IOCFG2    ,0x06);	//pin GDO2 se nastavi pri odeslani/prijetí SYNC a resetuje po odvysilani
    CC2500_Write_Register(hspi, CC2500_FIFOTHR   ,0x08);	//prah zaplneni FIFO - v soucasne dobe nepotrebny
    CC2500_Write_Register(hspi, CC2500_PKTCTRL0  ,0x45);	//promenna delka, nasobeni s pseudonahodou sekvenci - dochazelo ke strate synchronizace pri nulovych paketech
    CC2500_Write_Register(hspi, CC2500_PKTLEN    ,0x78);	//maximani povolena delka paketu 120 - nepouziva se
    CC2500_Write_Register(hspi, CC2500_PKTCTRL1  ,0x00);        //pro test 0x04-posilat RSSI a LQI
    CC2500_Write_Register(hspi, CC2500_FSCTRL1   ,0x10);  
    CC2500_Write_Register(hspi, CC2500_FREQ2   	 ,0x5C);	
    CC2500_Write_Register(hspi, CC2500_FREQ1   	 ,0x60);	
    CC2500_Write_Register(hspi, CC2500_FREQ0   	 ,0x7E);	
    CC2500_Write_Register(hspi, CC2500_MDMCFG4 	 ,0x0E);	
    CC2500_Write_Register(hspi, CC2500_MDMCFG3 	 ,0x3B);	
    CC2500_Write_Register(hspi, CC2500_MDMCFG2 	 ,0x73);	
    CC2500_Write_Register(hspi, CC2500_MDMCFG1 	 ,0x43);	
    CC2500_Write_Register(hspi, CC2500_MDMCFG0 	 ,0x84);	
    CC2500_Write_Register(hspi, CC2500_CHANNR 	 ,0x00);
    CC2500_Write_Register(hspi, CC2500_DEVIATN 	 ,0x00);	
    CC2500_Write_Register(hspi, CC2500_MCSM0   	 ,0x08);	//nekalibrovat(IDLE to RX,TX)
    CC2500_Write_Register(hspi, CC2500_FOCCFG  	 ,0x1D);	
    CC2500_Write_Register(hspi, CC2500_BSCFG   	 ,0x1C);	
    CC2500_Write_Register(hspi, CC2500_AGCCTRL2	 ,0xC7);	
    CC2500_Write_Register(hspi, CC2500_AGCCTRL0	 ,0xB0);	
    CC2500_Write_Register(hspi, CC2500_FREND1  	 ,0xB6);	
    CC2500_Write_Register(hspi, CC2500_FSCAL3  	 ,0xEA);	
    CC2500_Write_Register(hspi, CC2500_FSCAL1  	 ,0x00);	
    CC2500_Write_Register(hspi, CC2500_FSCAL0  	 ,0x19);

Jelikož bude v komunikaci figurovat kmitočtové skákání pro omezení případných úniků a silného úzkopásmového rušení, je nutné co nejvíce zkrátit dobu pro přepnutí kanálu. Nejvíce časově náročná operace v přepínání kanálů je kalibrace [2] ~720 us. Naštěstí CC2500 umožňuje provést kalibraci přes všechny kanály například během inicializace a výsledky uložit do paměti v mikrokontroléru. Při změně kanálu se poté nahrají uložené kalibrační hodnoty do příslušných registrů a doba přepnutí se zkrátí přibližně na 90 us. Funkce provádějící kalibraci všech kanálů je uvedena zde:

bool CC2500_CalibrateFrequencies(SPI_HandleTypeDef* hspi)
{
    uint16_t i;
    CC2500_STATUS State;
    uint16_t timeout;
 
    for(i=0;i<256;i++)
    {
        timeout = 1000;
        CC2500_Write_Register(hspi, CC2500_CHANNR ,i);
        CC2500_Send_Strobe_Command(hspi, CC2500_STROBE_SCAL);        //0x33
        do
        {
            State.StatusByte = CC2500_Send_Strobe_Command(hspi, CC2500_STROBE_SNOP);
            timeout--;
        }
        while ((State.StatusBits.STATE == CC2500_CALIBRATE) && (timeout !=0));
        if (timeout==0)
        {
            return false;
        }
 
        StoredCalibration1[i]=CC2500_Read_Register(hspi, CC2500_FSCAL1);
        if(i==255)
        {
            StoredCalibration2=CC2500_Read_Register(hspi, CC2500_FSCAL2);
            StoredCalibration3=CC2500_Read_Register(hspi, CC2500_FSCAL3);
        }
    }
    return true;
}

Pro odeslání paketu menšího než 64B (velikost FIFO v CC2500) s proměnnou délkou stačí po SPI poslat adresu FIFO, délku paketu a data. Poté je možné zapnout vysílání pomocí strobe příkazu.

Přijímání paketu je mírně složitější. S využitím pomocných pinu GDO0, popřípadě GDO2 a jejich konfigurace lze detekovat začátek paketu (detekce SYNC slova, vzestupná hrana) a konec paketu (bylo přijato tolik bytů, jaká je délka paketu, sestupná hrana). Je tedy dobré použít externí přerušení pro vyvolání přečtení dat. Funkce pro přečtení dat nejprve ověří kolik dat je v bufferu a pokud se jedná o dosažitelnou hodnotu (0 až 64) jsou vyčtena data. Následně se ověří, zda hodnota délky paketu odpovídá předpokládané délce a pokud ano, paket se přesune ke zpracování. Protože se posílané data porovnávají přímo s definovanými hodnotami, není ověření správnosti dat pomocí CRC nutné. Pokud bude chybný nějaký bit, nebude podmínka splněna.

Komunikační protokol

Protože je tento systém ovladačů navrhován pro online hry typu GSwitch a podobné skákací hry, kde se využívá pouze stisku klávesy, stačí přenášet pouze stisk a uvolnění si doplní master jednotka sama. Tento způsob také zjednodušuje ošetření zákmitů. Klasicky používané metody pro ošetření zákmitů vnáší již při stisku nezanedbatelnou dobu odezvy, proto byla zvolena metoda zaměřená pouze na detekci stisku. Jakmile je detekován stisk, nemůže být po uvolnění (zákmitem nebo normálním způsobem) dalších 40ms detekován žádný další stisk. Metoda byla odladěna na tlačítku na vývojovém kitu, pro horší tlačítka by nejspíše byla nutná úprava algoritmu.

Pro komunikaci master jednotky a ovladačů byl sestaven jednoduchý protokol. Komunikace je tvořena ze superrámců, které se skládají ze 3 rámců. Každý rámec (9ms) pak obsahuje 10 timeslotů, z čehož je jeden jako pouze časová rezerva. V nultém timeslotu (1ms) je odeslán Poll paket z master jednotky, následuje časová rezerva (0,4 ms) a 8 timeslotů (0,95 ms) pro každý ovladač. Názorněji zobrazeno na záznamu z logického analyzátoru (Obrázek 3), kde je při změně timeslotu změněna úroveň na pinu.
Obrázek 3 Znázornění rámce. (doporučeno otevřít v novém panelu, kde nebude omezena velikost na polovinu monitoru)

Pro timesloty jsou použity 2 časovače. Časovač s označením TIM2 zajišťuje časování rámců 9ms a běží neustále. Časovač TIM3 je spouštěn automaticky s každým update eventem od časovače TIM2 a zajištuje časování jednotlivých timeslotů. Protože nemají všechny časovače stejnou dobu trvání, zapisuje se do registru horní hranice časovače hodnota pro další timeslot při každém update eventu. V posledním timeslotu rámce se časovač TIM3 zastaví a resetuje. Případná odchyla se dorovná do 9 ms (poslední timeslot je o pár mikrosekund delší/kratší) a tak je zajištěna vyšší časová stálost.

Na začátku každého datového timeslotu je změněn kanál podle vztahu:

CH = 20*cislo_ramce + cislo_timeslotu,

například pro druhý timeslot v druhém rámci bude nastaven kanál 42. Tímto je zajištěno, že se ovladače navzájem neslyší a mohou po odeslání paketu přejít do režimu naslouchání. Zároveň je systém odolnější proti případnému úzkopásmovému rušení, protože pokud ovladač nedostane informaci o přijatém stisku, odešle jej v dalším rámci znovu. Pokud ani tak nebude stisk potvrzen, bude vynechán, jelikož by se pak pro daný stisk zvýšila odezva k hranici 30 ms.

Jakmile je detekováno ukončení příjmu (sestupná hrana na pomocném pinu), je v master jednotce vyčten obsah vnitřního FIFO bufferu čipu CC2500 - přijatá data.

Synchronizace

První myšlenka byla provádět synchronizaci ovladačů na základě ukončení přijímání (vysílaní z mastera), to lze detekovat na dedikovaném výstupním pinu z čipu CC2500. To se ovšem ukázalo jako nevhodné, neboť z následně zjištěného příliž vysokého kmitočtu SPI komunikace (5,25Mbit/s) byl někdy náhodně příjem delší než samotné vysílání, kdy nadbytečné byty po vyčtení nepředstavovaly žádné deterministické data a první byte paketu určující délku paketu byl také pozměněn, což způsobilo posun synchronizace pro další pakety. Problém by mohl být vyřešen vyhodnocením zda dorazil správný paket a poté provést synchronizaci, to by ovšem vnášelo další krátké nedefinovatelné zpoždění vlivem zpracování.

Proto byla stanovena synchronizace na začátek příjmu (detekci SYNC slova v paketu), která se nemění. Může se však měnit doba od začátku timeslotu po začátek vysílaní master jednotky. Tato přesnost byla vyhodnocena jako dostačující, jelikož se zjednoduší obsluha oproti případu kde by začátek timeslotu byl shodný se začátek vysílaní a zároveň vzniká rezervní okno pro možný časový posun synchronizace. Synchronizace je tedy prováděna i když nejsou data v paketu korektní. Právě proto, že se využívá k synchronizaci detekce SYNC slova je pravděpodobnost přijetí vysílání od jiného zdroje na daném kmitočtu s danou modulací a přenosovou rychlostí nízká. Jestliže bude pracovat v používaném pásmu jiný systém, který způsobí chyby v synchronizaci, nejspíše nebude navržený systém ovladačů v takovém prostředí spolehlivě pracovat.

Bylo otestováno pro extrémní případ,kdy 9 sekund nebyl přijat žádný packet z master jednotky se vzájemná synchronizace rozešla o 55 us a komunikace stále fungovala. Na obrázku 4 je zachycen horší případ chyby synchronizace a detail začátku timeslotu 2, v průměru je chyba synchronizace do 100 ns.


Obrázek 4 Detail TS2 a sychnronizace. Zelený průběh odpovídá timeslotům master jednotky, žlutý timeslotům ovladače. (doporučeno otevřít v novém panelu, kde nebude omezena velikost na polovinu monitoru)

Nepřijde-li poll paket do ovladače 10x po sobě, předpokládá se, že master jednotka byla vypnuta nebo restartována a proto se ukončí vysílaní ovladače a začne se hledat poll packet znovu. Jakmile se nalezne, synchronizace je obnovena a ovladač může opět komunikovat.

Ovladač

Po zapnutí ovladače se rozsvítí modrá LED na 4s. Během tohoto času lze vybrat číslo ovladače 0 až 7 (odpovídá znakům 'a' až 'h') podle počtu stisknutí modrého tlačítka na desce. Každý stisk je signalizován oranžovou LED. Po uplynutí tohoto času přechází ovladač do pracovního stavu, kdy stisk modrého tlačítka představuje stisk klávesy. Pro správnou funkci systému musí uživatel zajistit, aby se nevyskytovali dva ovladače se stejným číslem. Viz poznámky pro budoucí vylepšení v závěrečné části.

USB HID

Základní kostra pro USB třídu HID byla vygenerována pomocí nástroje STM32CubeMX. Ve vygenerovaném kódu je však nutné upravit konfigurační descriptor a discriptor pro Reporty. Upravy byly provedeny s využitím návodu do počítačového cvičení 7 [3] a [4]. V konfiguračním descriptoru byla upravena položka nInterfaceProtocol na 0x01 (klávesnice), délka Reportu na 45 B, interval pollování reportů na 1 ms a velikost paketu na 10 B. Konfigurační descriptor:

#define HID_EPIN_ADDR                 0x81
#define HID_EPIN_SIZE                 0x0A          //orig 0x04
 
#define USB_HID_CONFIG_DESC_SIZ       34
#define USB_HID_DESC_SIZ              9
#define HID_KEYBOARD_REPORT_DESC_SIZE    45            //orig 74
 
#define HID_DESCRIPTOR_TYPE           0x21
#define HID_REPORT_DESC               0x22
 
#define HID_HS_BINTERVAL               0x01         //orig 0x07
#define HID_FS_BINTERVAL               0x0A
#define HID_POLLING_INTERVAL           0x0A
 
#define HID_REQ_SET_PROTOCOL          0x0B
#define HID_REQ_GET_PROTOCOL          0x03
 
#define HID_REQ_SET_IDLE              0x0A
#define HID_REQ_GET_IDLE              0x02
 
#define HID_REQ_SET_REPORT            0x09
#define HID_REQ_GET_REPORT            0x01
 
 
__ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ]  __ALIGN_END =
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
  USB_HID_CONFIG_DESC_SIZ,
  /* wTotalLength: Bytes returned */
  0x00,
  0x01,         /*bNumInterfaces: 1 interface*/
  0x01,         /*bConfigurationValue: Configuration value*/
  0x00,         /*iConfiguration: Index of string descriptor describing
  the configuration*/
  0xE0,         /*bmAttributes: bus powered and Support Remote Wake-up */
  0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
 
  /************** Descriptor of Joystick Mouse interface ****************/
  /* 09 */
  0x09,         /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
  0x00,         /*bInterfaceNumber: Number of Interface*/
  0x00,         /*bAlternateSetting: Alternate setting*/
  0x01,         /*bNumEndpoints*/
  0x03,         /*bInterfaceClass: HID*/
  0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
  0x01,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
  0,            /*iInterface: Index of string descriptor*/
  /******************** Descriptor of Joystick Mouse HID ********************/
  /* 18 */
  0x09,         /*bLength: HID Descriptor size*/
  HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
  0x11,         /*bcdHID: HID Class Spec release number*/
  0x01,
  0x00,         /*bCountryCode: Hardware target country*/
  0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
  0x22,         /*bDescriptorType*/
  HID_KEYBOARD_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /******************** Descriptor of Mouse endpoint ********************/
  /* 27 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
 
  HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_EPIN_SIZE, /*wMaxPacketSize: 10 Byte max */
  0x00,
  HID_HS_BINTERVAL,          /*bInterval: Polling Interval (1 ms)  puv.: HID_HS_BINTERVAL, */
  /* 34 */
} ;

V descriptoru pro Reporty klávesnice byla oproti tomu uvedenému v [3] odstraněna identifikace reportu, jelikož se nejedná o složené zařízení a dále byl report rozšířen o 2 sloty (2 Byty) pro klávesy. V jednom reportu tak bude možné odeslat 8 stisknutých kláves najednou. To je vhodné jednak pro odesílání dat ze všech ovladačů v jednom čase, ale zároveň je to nutné z hlediska časování. Odesílaní všech kláves v jednom reportu přijatých během jednoho rámce odstraňuje znevýhodnění případných hráčů, kteří by byly obslouženi v pozdějším timeslotu v případě odesílání reportů po každém timeslotu. Stále je zde určitá míra znevýhodnění tím, že všechny ovladače odpovídají v tomtéž timeslotu po celou dobu provozu, ale protože uživatelé nejsou schopní používat systém synchronně s časováním timeslotů vnese se do systému potřebná míra náhodnosti sama o sobě.

Descriptor HID klávesnice:

__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE]  __ALIGN_END =
{
  0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  0x09, 0x06, // USAGE (Keyboard)
  0xa1, 0x01, // COLLECTION (Application)
  0x05, 0x07, // USAGE_PAGE (Keyboard)
  0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
  0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
  0x15, 0x00, // LOGICAL_MINIMUM (0)
  0x25, 0x01, // LOGICAL_MAXIMUM (1)
  0x75, 0x01, // REPORT_SIZE (1)
  0x95, 0x08, // REPORT_COUNT (8)
  0x81, 0x02, // INPUT (Data,Var,Abs)
  0x95, 0x01, // REPORT_COUNT (1)
  0x75, 0x08, // REPORT_SIZE (8)
  0x81, 0x03, // INPUT (Cnst,Var,Abs)
  0x95, 0x08, // REPORT_COUNT (8)
  0x75, 0x08, // REPORT_SIZE (8)
  0x15, 0x00, // LOGICAL_MINIMUM (0)
  0x25, 0x65, // LOGICAL_MAXIMUM (101)
  0x05, 0x07, // USAGE_PAGE (Keyboard)
  0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
  0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
  0x81, 0x00, // INPUT (Data,Ary,Abs)
  0xc0, // END_COLLECTION
};

Z testování vyplynulo, že při pollovacím intervalu 1 ms a čekání na 2 ms na vyčtení reportu řadičem v počítači a následnému uvolnění klávesy sice dojde k zaznamenání stisku v textových editorech, ale v některých aplikacích není výše popsaný stisk detekován. Problém je odstraněn po prodloužení doby aktivního stisku z ~2ms na ~20ms. Při takovém chování již základních 6 pozic pro klávesu nedostačuje, ani není možné zapisovat HID reporty po každém timeslotu.

Princip odesílání reportů je následující. Při příchodu paketu z ovladače se sdělením, že došlo ke stisku klávesy, je nastaveno počítadlo pro danou klávesu. Jakmile má být zapsán HID report, je nejprve sestavena zpráva o stisknutých klávesách podle toho, zda je počítadlo pro dané klávesy vetší než nula. Po vytvoření zprávy jsou všechna aktivní počitadla zmenšena o 1. Hodnota počítadla je nastavena na 3, což znamená že daná klávesa se odesílá ve 3 reportech po sobě a ve čtvrtém se odesílá již nula(žádná stisknutá klávesa). S uvážením času jednoho rámce 9ms je přibližná doba stisku 27ms, což se blíží době nejkratšího stisku který se podařilo změřit na herní klávesnici 34ms. Poté co bylo odesláno uvolnění všech kláves, se reporty dále nezapisují. Zachycené reporty jsou na Obrázku 5

hid.jpg
Obrázek 5 HID reporty z master jednotky včetně časování. Je zachycen scan kod 0x0B, což odpovídá písmenu 'h'. Ve čtvrtém reportu jsou samé nuly.

Závěr

Práce s čipem CC2500 není jednoduchá, jakmile však člověk zná datasheet téměř nazpaměť a oživí první aplikaci, je práce velmi příjemná. Nevýhodou je velká citlivost na elektrostatický výboj, kdy při přímém dotyku antény i sebemenší výboj s velkou pravděpodobností způsobí vynechávání paketů a to přibližně 50%, přičemž nelze pozorovat vliv na jakoukoliv jinou funkci.

Jelikož otestovat systém v plné sestavě by bylo velmi nákladné (8 vývojových kitů, 8 rádiových modulů CC2500, 8 + 1 USB kabelů, případně jiné propojení napájení a 56 propojovacích vodičů), byla otestována funkce jednoho ovladače ve všech možných pozicích.

Pro ověření descriptorů HID zařízení byl využit program USBlyzer, tento program umí analyzovat i USB komunikaci, verze zdarma to v tomto režimu však pracuje pouze omezenou dobu. Proto pro ověření USB komunikace byl využit program Wireshark, který umožnuje analyzovat USB komunikaci stejným způsobem jako komunikaci síťovou.

Protože muže být vysílání stisknuté klávesy až jednou opakováno na jiném frekvenčním kanálu, bez výrazného zvýšení odezvy, muže systém pracovat i za zhoršených podmínek šumu v rádiovém prostředí. Dojde-li ze ztrátě synchronizace (v ovladači nebude přijat 10x po sobě poll packet z masteru) začně ovladač znovu vyhledávat máster jednotku. Obnovení tedy nastane nejpozději po 14 rámcích, což odpovídá 126 ms.



Náměty pro budoucí rozšíření:

Implementovat automatické rozpoznání a přidání ovladačů do systému. Řešením by mohlo být vysílání poll packetu pouze v sudých rámcích. Liché rámce by sloužili pro přihlášení ovladače do systému a výměně důležitých informací.

Snížení latence. Jelikož se odesílá malé množství dat trvá odesílání pouze krátkou dobu, proto by bylo možné zkrátit jednotlivé timesloty až o 40%.

Vytvořit samostatnou desku s menším mikrokontrolérem a pro ovladače se zaměřit nízkou spotřebu zařízení. Uspat mikrokontrolér i CC2500 a probouzet pouze v době očekávání poll packetu nebo vysílaní packetu.

Skenování výkonu po zapnutí přes všechny kanály s vhodným časovým úsekem pro jeden kanál za účelem posunutí pracovních kmitočtů do nejméně využívané oblasti.

Video ukázka:

Použitá literatura

[1] DN503 – SPI Access (Rev. B) Texas Instruments [online]. [cit. 2017-01-15]. Dostupné z: http://www.ti.com/lit/pdf/swra112
[2] CC2500 Texas Instruments [online]. [cit. 2017-01-15]. Dostupné z: http://www.ti.com/lit/gpn/cc2500
[3] POVALAČ, A. STM32F4DISCOVERY (EmBitz+STM32CubeMX): USB myš standardu HID [online]. [cit. 2017-01-15]. Dostupné z: https://moodle.vutbr.cz/mod/resource/view.php?id=100242
[4] AXELSON, Jan. USB complete everything you need to develop custom USB peripherals. 3rd ed. Madison, WI: Lakeview Research, 2005. ISBN 9781931448031.


Kompletní zdrojové kódy pro Keil uVision5 jsou ke stažení zde.

2016/cc2500-hid.txt · Poslední úprava: 2017/01/15 22:30 autor: Stanislav Rozum