HIDkeys, not recognized.

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
UnhandyMan
Posts: 3
Joined: Wed Oct 21, 2009 11:25 am

HIDkeys, not recognized.

Post by UnhandyMan » Wed Oct 21, 2009 11:49 am

Hello,

I've been trying to make the HIDkeys project that was posted on this website. I've completely recreated the hardware according to the circuit that is displayed, there are only just no keys yet placed on it (this is because we want the device to be recognized first and assume it reads the pins where the keys are connected to will read as 0).

The code is exactly the same as provided by objecte development (HIDkeys project), using the USB driver that comes along with it. Somehow yet, the device won't be recognized by the computer. I'm using Windows XP, I have made sure I'm using the right configurations (e.g. AVRStudio4 working with the ATMega8) and my program is flashed on the microcontroller with succes. I would apreciate if somebody could tell me why it's not recognized.

Edit: It seems that somehow, the computer does not receives any device descriptors from the USB device, I do not know why it happens or how to fix it.

Code: Select all

#define F_CPU   12000000L    /* evaluation board runs on 4MHz */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>

#include "usbdrv.h"
#include "oddebug.h"

/* ----------------------- hardware I/O abstraction ------------------------ */

/* pin functies:
PB0   Key 1 (in use)
PB1   Key 2 (in use)
PB2   Key 3
PB3   Key 4
PB4   Key 5
PB5 Key 6

PC0   Key 7
PC1   Key 8
PC2   Key 9
PC3   Key 10
PC4   Key 11
PC5   Key 12

PD0   USB-
PD1   debug tx
PD2   USB+ (int0)
PD3   Key 13
PD4   Key 14
PD5   Key 15
PD6   Key 16
PD7   Key 17
*/

static void hardwareInit(void)
{
uchar   i, j;

    PORTB = 0xff;   /* activeer alle pull-ups */
    DDRB = 0;       /* alle pins zijn input */
    PORTC = 0xff;   /* activeer alle pull-ups */
    DDRC = 0;       /* alle pins zijn input */
    PORTD = 0xfa;   /* 1111 1010 bin: activeer pull-ups behalve op USB pins */
    DDRD = 0x07;    /* 0000 0111 bin: alle pins zijn input behalve 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 */
    /* configure timer 0 for a rate of 12M/(1024 * 256) = 45.78 Hz (~22ms) */
    TCCR0 = 5;      /* timer 0 prescaler: 1024 */
}

/* ------------------------------------------------------------------------- */

#define NUM_KEYS    17

/* The following function returns an index for the first key pressed. It
 * returns 0 if no key is pressed.
 */
static uchar    keyPressed(void)
{
uchar   i, mask, x;

    x = PINB;
    mask = 1;
    for(i=0;i<6;i++){
        if((x & mask) == 0)
            return i + 1;
        mask <<= 1;
    }
    x = PINC;
    mask = 1;
    for(i=0;i<6;i++){
        if((x & mask) == 0)
            return i + 7;
        mask <<= 1;
    }
    x = PIND;
    mask = 1 << 3;
    for(i=0;i<5;i++){
        if((x & mask) == 0)
            return i + 13;
        mask <<= 1;
    }
    return 0;
}

/* ------------------------------------------------------------------------- */
/* ----------------------------- 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
};
/* 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_A       4
#define KEY_B       5
#define KEY_C       6
#define KEY_D       7
#define KEY_E       8
#define KEY_F       9
#define KEY_G       10
#define KEY_H       11
#define KEY_I       12
#define KEY_J       13
#define KEY_K       14
#define KEY_L       15
#define KEY_M       16
#define KEY_N       17
#define KEY_O       18
#define KEY_P       19
#define KEY_Q       20
#define KEY_R       21
#define KEY_S       22
#define KEY_T       23
#define KEY_U       24
#define KEY_V       25
#define KEY_W       26
#define KEY_X       27
#define KEY_Y       28
#define KEY_Z       29
#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_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)
{
    *(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(keyPressed());
            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;
uchar   idleCounter = 0;

   wdt_enable(WDTO_2S);
    hardwareInit();
   odDebugInit();
   usbInit();
   sei();
    DBG1(0x00, 0, 0);
   for(;;){   /* main event loop */
      wdt_reset();
      usbPoll();
        key = keyPressed();
        if(lastKey != key){
            lastKey = key;
            keyDidChange = 1;
        }
        if(TIFR & (1<<TOV0)){   /* 22 ms timer */
            TIFR = 1<<TOV0;
            if(idleRate != 0){
                if(idleCounter > 4){
                    idleCounter -= 5;   /* 22 ms in units of 4 ms */
                }else{
                    idleCounter = idleRate;
                    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;
}

/* ------------------------------------------------------------------------- */
Last edited by UnhandyMan on Thu Oct 22, 2009 4:27 pm, edited 1 time in total.

Bernd

Re: HIDkeys, not recognized.

Post by Bernd » Wed Oct 21, 2009 4:38 pm

The Computer recognized the HId-devive only by the first use. The ohter ways you dont see a popup, which shows you a conecting Hid-device.
You dont have to install a special Usb-Driver for suing the HID device. The Driver comes with Windos XP.
Look at the control center and check you have an connecting Hid-Device in it.

UnhandyMan
Posts: 3
Joined: Wed Oct 21, 2009 11:25 am

Re: HIDkeys, not recognized.

Post by UnhandyMan » Wed Oct 21, 2009 4:49 pm

What I mean is that it automatically shows a popup saying it does not recognizes the device. The driver I mentioned is the one that is included in the firmware of the HIDkeys project.
The controller center explicitely states it's an unknown device, so somehow personally I suspect the computer does not receives the device descriptors, but I don't get what is going wrong since the code and hardware are the same as that on objective development's website, so basicly it should be tried and proven work.

Bernd

Re: HIDkeys, not recognized.

Post by Bernd » Wed Oct 21, 2009 7:34 pm

Have you set the real Fuse Bit?
Have you change your Atmeaga8 to another one?

Bernd

Re: HIDkeys, not recognized.

Post by Bernd » Wed Oct 21, 2009 7:43 pm

Have you read this about the Hardware Considerations

http://vusb.wikidot.com/hardware

Disadvantages:

* Low drop regulators are often expensive and harder to obtain.
* Many AVRs are not specified for the required clock rates at supply voltages below 4.5 V.
* Other chips on the board may not be specified for 3.3 V.



I use Solution B.

UnhandyMan
Posts: 3
Joined: Wed Oct 21, 2009 11:25 am

Re: HIDkeys, not recognized.

Post by UnhandyMan » Thu Oct 22, 2009 3:45 pm

I'm still using an ATMega8 and AVR Studio is set on ATMega8 in the configuration settings.
I've taken a look at th hardware considerations and I use solution A (lowering the voltage with 2 1N4148 diodes) wich works correctly as far as voltage level measuring and the circuit diagram provided by objective development shows.
I've tried looking up the real Fuse bit very briefly, but have not yet found where I can see/change the real Fuse bit.

Bernd

Re: HIDkeys, not recognized.

Post by Bernd » Thu Oct 22, 2009 4:37 pm

The Rel Fuse Bit Level is in the makefile. Open it with a editor:

# Fuse high byte:
# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0
# | | | | | +------- BOOTSZ1
# | | | | --------- EESAVE (don't preserve EEPROM over chip erase)
# | | | +------------- CKOPT (full output swing)
# | | +--------------- SPIEN (allow serial programming)
# | +----------------- WDTON (WDT not always on)
# +------------------- RSTDISBL (reset pin is enabled)
# Fuse low byte:
# 0x9f = 1 0 0 1 1 1 1 1
# ^ ^ \ / \--+-/
# | | | +------ CKSEL 3..0 (external >8M crystal)
# | | +-------------- SUT 1..0 (crystal osc, BOD enabled)
# | +----------------- BODEN (BrownOut Detector enabled)
# +------------------- BODLEVEL (2.7V)

You can change the Fuse Bit with the Programmer Software. I use Averdude with AVR Burn-O-Mat to set The FUse-Bits.

Post Reply