UART - > Hidkeys
Posted: Fri Jan 30, 2009 11:20 am
Hello!
I'm trying to make UART to HID keyboard translator based on HIDKeys example. Also we recive numbers (ASCII from 0x30 to 0x39) or Carrige Return (0x0D) and tranclate it to USB hid where only difference is CR (Enter) is 0x40;
I probably have error somwhere in my code, couse when i attach it send 0,1,2,3,4,5,6,7,8,9, CR i recieve in my PC strange symbols like "v","m" or even it swithces Keyboard language. I am bad in AVR-GCC and i promise you can help me with following code:
Thank you!
I'm trying to make UART to HID keyboard translator based on HIDKeys example. Also we recive numbers (ASCII from 0x30 to 0x39) or Carrige Return (0x0D) and tranclate it to USB hid where only difference is CR (Enter) is 0x40;
I probably have error somwhere in my code, couse when i attach it send 0,1,2,3,4,5,6,7,8,9, CR i recieve in my PC strange symbols like "v","m" or even it swithces Keyboard language. I am bad in AVR-GCC and i promise you can help me with following code:
Code: Select all
#define F_CPU 12000000L
#define BAUDRATE 600
//calculate UBRR value
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "usbdrv.h"
#include "oddebug.h"
volatile uchar nextDigit;
static void hardwareInit(void)
{
uchar i, j;
//REMOVED SOME INITIALISATION OF PORTS HERE
PORTD = 0xfa; /* 1111 1010 bin: activate pull-ups except on USB lines */
DDRD = 0x07; /* 0000 0111 bin: all pins input except USB (-> USB reset) */
j = 0;
while(--j){ /* USB Reset by device only required on Watchdog Reset */
i = 0;
while(--i); /* delay >10ms for USB reset */
}
DDRD = 0x02; /* 0000 0010 bin: remove USB reset condition */
//Set baud rate
UBRRL=(uint8_t)UBRRVAL; //low byte
UBRRH=(UBRRVAL>>8); //high byte
//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size
UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|
(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);
//Enable Transmitter and Receiver and Interrupt on receive complete
UCSRB=(1<<RXEN)|(1<<RXCIE);//|(1<<TXEN);
//enable global interrupts
}
/* ------------------------------------------------------------------------- */
uint8_t USART_vReceiveByte(void) //receive one byte
{
// Wait until a byte has been received
while((UCSRA&(1<<RXC)) == 0);
// Return received data
return UDR;
}
ISR(USART_RXC_vect) //uart interrupt routine
{
uchar dat;
//receive destination address
dat=USART_vReceiveByte();
//receive data
if ((0x2f<dat)& (dat<0x40)){ // if we have number, just paste it to output
nextDigit = dat;
}
else if (dat == 0x0d){ //else if we have CR put Enter key
nextDigit = 0x40;
}
// OTHER KEYS SHOULD BE IGNORED
}
/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */
static uchar reportBuffer[2]; /* buffer for HID reports */
static uchar idleRate; /* in 4 ms units */
PROGMEM char usbHidReportDescriptor[35] = { /* USB report descriptor */
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)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
/* We use a simplifed keyboard report descriptor which does not support the
* boot protocol. We don't allow setting status LEDs and we only allow one
* simultaneous key press (except modifiers). We can therefore use short
* 2 byte input reports.
* The report descriptor has been created with usb.org's "HID Descriptor Tool"
* which can be downloaded from http://www.usb.org/developers/hidpage/.
* Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
* for the second INPUT item.
*/
/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
* 10 Keyboard/Keypad Page for more codes.
*/
#define MOD_CONTROL_LEFT (1<<0)
#define MOD_SHIFT_LEFT (1<<1)
#define MOD_ALT_LEFT (1<<2)
#define MOD_GUI_LEFT (1<<3)
#define MOD_CONTROL_RIGHT (1<<4)
#define MOD_SHIFT_RIGHT (1<<5)
#define MOD_ALT_RIGHT (1<<6)
#define MOD_GUI_RIGHT (1<<7)
#define KEY_1 30
#define KEY_2 31
#define KEY_3 32
#define KEY_4 33
#define KEY_5 34
#define KEY_6 35
#define KEY_7 36
#define KEY_8 37
#define KEY_9 38
#define KEY_0 39
#define KEY_ENTER 40
#define KEY_F1 58
#define KEY_F2 59
#define KEY_F3 60
#define KEY_F4 61
#define KEY_F5 62
#define KEY_F6 63
#define KEY_F7 64
#define KEY_F8 65
#define KEY_F9 66
#define KEY_F10 67
#define KEY_F11 68
#define KEY_F12 69
static const uchar keyReport[NUM_KEYS + 1][2] PROGMEM = {
/* none */ {0, 0}, /* no key pressed */
/* 1 */ {MOD_SHIFT_LEFT, KEY_A},
/* 2 */ {MOD_SHIFT_LEFT, KEY_B},
/* 3 */ {MOD_SHIFT_LEFT, KEY_C},
/* 4 */ {MOD_SHIFT_LEFT, KEY_D},
/* 5 */ {MOD_SHIFT_LEFT, KEY_E},
/* 6 */ {MOD_SHIFT_LEFT, KEY_F},
/* 7 */ {MOD_SHIFT_LEFT, KEY_G},
/* 8 */ {MOD_SHIFT_LEFT, KEY_H},
/* 9 */ {MOD_SHIFT_LEFT, KEY_I},
/* 10 */ {MOD_SHIFT_LEFT, KEY_J},
/* 11 */ {MOD_SHIFT_LEFT, KEY_K},
/* 12 */ {MOD_SHIFT_LEFT, KEY_L},
/* 13 */ {MOD_SHIFT_LEFT, KEY_M},
/* 14 */ {MOD_SHIFT_LEFT, KEY_N},
/* 15 */ {MOD_SHIFT_LEFT, KEY_O},
/* 16 */ {MOD_SHIFT_LEFT, KEY_P},
/* 17 */ {MOD_SHIFT_LEFT, KEY_Q},
};
static void buildReport(uchar key)
{
/* This (not so elegant) cast saves us 10 bytes of program memory */
*(int *)reportBuffer = pgm_read_word(keyReport[key]);
}
uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
usbMsgPtr = reportBuffer;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
/* we only have one report type, so don't look at wValue */
buildReport(nextDigit);
return sizeof(reportBuffer);
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
usbMsgPtr = &idleRate;
return 1;
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
idleRate = rq->wValue.bytes[1];
}
}else{
/* no vendor specific requests implemented */
}
return 0;
}
/* ------------------------------------------------------------------------- */
int main(void)
{
uchar key, lastKey = 0, keyDidChange = 0;
wdt_enable(WDTO_2S);
hardwareInit();
odDebugInit();
usbInit();
sei();
for(;;){ /* main event loop */
wdt_reset();
usbPoll();
key = nextDigit;
nextDigit=0;
if(lastKey != key){
lastKey = key;
keyDidChange = 1;
}
if(keyDidChange && usbInterruptIsReady()){
keyDidChange = 0;
/* use last key and not current key status in order to avoid lost
changes in key status. */
buildReport(lastKey);
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
}
}
return 0;
}
/* ------------------------------------------------------------------------- */
Thank you!