HID keyboard atmega168p - Solved
Posted: Tue May 03, 2011 12:42 am
I am working on a HID keyboard on the atmega 168p running at 16 MHz.
So far, i've successfully transmittd keycommands to my computer, so that part is working.
My problem is, that once i send a command, the avr just keeps transmitting the same command to the computer. I can't really figure out what is wrong.
My code is heavily inspired from the HID keyboard examples from the obdev.at site.
My main looks like the following:
So far, i've successfully transmittd keycommands to my computer, so that part is working.
My problem is, that once i send a command, the avr just keeps transmitting the same command to the computer. I can't really figure out what is wrong.
My code is heavily inspired from the HID keyboard examples from the obdev.at site.
My main looks like the following:
Code: Select all
#include "common.h"
#include "keycodes.h"
#include "avr/pgmspace.h"
#include "usbdrv/usbdrv.h"
#include "usbdrv/oddebug.h"
#define ReportDescriptor usbHidReportDescriptor
PROGMEM
#include "ir_keyboard_2.hid.h" // reportdescriptor
#define STATIC_ASSERT(expr) extern char static_assert[ (!!(expr))*2 - 1]
STATIC_ASSERT(sizeof(usbHidReportDescriptor) == USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH);
static uchar reportBuffer[2] = {0,0};
static uchar idleRate;
static uchar irKey = 0;
static uchar ir_key_pressed = 0;
uchar irKeyLookup(uchar irkey){
volatile uchar key = 0;
switch(irkey){
case 0x60: //prev
key = 1;
break;
case 0xA0: // next
key = 2;
break;
case 0x40: // stop
key = 8;
break;
case 0x80: // play
key = 4;
break;
default:
key = 0;
break;
}
return key;
}
typedef enum{
reportid_none = 0,
reportid_key = 1
} report_id_t;
static void buildReport(report_id_t id, uchar key)
{
reportBuffer[0] = id;
if (id == reportid_key){
reportBuffer[1] = key;
}
}
usbMsgLen_t 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(rq->wValue.bytes[0], ir_key_pressed);
DBG1(0x50, &rq->bRequest, 1);
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){
cli(); // Disable interrupts
usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
usbInit();
odDebugInit();
IR_init();
/* Port initiation*/
bs(DDRC,3);
bs(DDRC,4);
bs(DDRC,5);
PORTC &= ~(1<<3);
PORTC = ~PORTC;
/* Timer 0 initiation */
TCCR0B = _BV(2) | _BV(0); // 16E6/(1024*256) = 61 ~ 16 ms
/* Variable initiation */
char buf[64];
uchar idleCounter = 0;
static report_id_t keyPressed = reportid_none;
_delay_ms(250);
usbDeviceConnect();
sei(); // Reenable interrupts
DBG1(0x00, 0, 0); /* debug output: main starts */
while(1){
usbPoll(); // must be called at least every 50 ms
bs(PORTC,5); // Clear the indicator led
if(IR_packetReady()){ // check for packets from remote
irKey = IR_getCode();
keyPressed = reportid_key;
}
if(TIFR0 & (1<<TOV0)){ // 16 ms timer
TIFR0 = 1<<TOV0;
if(idleRate != 0){
if(idleCounter > 4){
idleCounter -= 5; // 16 ms in units of 4 ms
}else{
idleCounter = idleRate;
// keyPressed = reportid_none;
}
}
}
if(keyPressed && usbInterruptIsReady()){
DBG1(0x19, &irKey,1); // debug output
ir_key_pressed = irKeyLookup(irKey);
buildReport(keyPressed , ir_key_pressed);
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
keyPressed = reportid_none;
}
}
}