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;
    }
  }
   
}