MacroPad

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

MacroPad

Post by FireFlower » Thu Mar 05, 2009 12:50 am

Hello.

I'm in a bit pinch at this moment. Me and my friend wanted to do our graduation work but there is now some problems.

Seems like this site doesn't have enough information regarding what AVR C program you should use, and program that I'm using doesn't have necessary libraries already and I can't find them anywhere.

I'm using CodeVisionAVR program at this moment but i'm wondering where I might more information about USB Interface configuration, because our device needs to be able to ask host to send data and then again send data to host.


Anyway here are currently things I need to get:
interrupt.h (or instructions how to code this to main program file)
pgmspace.h (needed by usbdrv.h thats all i know, what for this is needed?)


I really would appreciate these information because I think we won't be able to graduate otherwise. Yeah we became too greedy thinking, hey we don't have to use RS-232 because here is simple avr-usb driver... Yeah, but without information how to get that working its kinda useless...

Well anyway.

MacroPad idea is same as Logitech G15 macro keys. When you press a start it then asks you to select macro key where it will save all recorded keyboard's keys pressed. Pressing Start button again stops recording and saves current macro to macro that was selected.

If I understood right this doesn't need a driver for host when device is configured to be HID device?

Thanks for your help, I really appreciate all help you can give me.

Schematics:
http://i403.photobucket.com/albums/pp113/sl06bhytmar/lopputypiirifinal.jpg
Last edited by FireFlower on Sat May 23, 2009 10:33 pm, edited 3 times in total.

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Post by Grendel » Thu Mar 05, 2009 4:39 am

AVR-USB requires IAR or AVR GCC for a compiler, WinAVR 20071221 works out-of-the-box. As for an IDE, Atmel's AVR Studio comes w/ native support for WinAVR.

Correct, most OS's come w/ native HID drivers. USB itself is pretty complex, take a look at USB in a Nutshell to get an idea. Check out the community HID projects for references as well (esp. the HIDKeys).

Edit: just checked, WinAVR 20081205 works as well. Creates slightly bigger code tho. The headers you are missing are part of avr-libc. WinAVR includes avr-libc. I would suggest you switch to the AVR Studio/WinAVR environment, trying to make it work w/ CodeVisionAVR will probably be too time consuming.

Guest

Post by Guest » Fri Mar 06, 2009 9:49 pm

Okay here is schematics. Pretty simple but so it should be :)

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Post by FireFlower » Fri Mar 06, 2009 9:52 pm

Cursed guest accounts.. Well anyway I have soon readed whole USB in nuts shell and hopefully tomorrow I can start study this WinAVR

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Post by FireFlower » Mon Mar 23, 2009 8:34 am

I'm wondering about this usb report thing. I doubt I can make this on my own, so could anyone explain how to make this step by step or make ready one?

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Post by Grendel » Wed Mar 25, 2009 7:21 am

Grendel wrote:Check out the community HID projects for references as well (esp. the HIDKeys).

;)

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Post by FireFlower » Wed Mar 25, 2009 5:58 pm

Well then I noticed AVR Studio doesn't have any libraries on its own so I copied all libraries from WinAVR but seems like AVR Studio is a lot different than AVRCodeVision.

Also I have been using Kanda 200/300 cable for uploading program to microcontroller but seems like I need to use AVRISP mkII (I saw this one in school too).

Well main question is layout is too different. If I understand correctly I/O view tells me current microcontroller port, flag, timer, etc status but doesn't let me modify them.

So probably I need to write hardwareinit by hand to main program? Atleast project wizard doesn't do this. If someone could tell me main things I need to know to make code work with this.

Well thanks for advices you might give me, hopefully I can get atleast USB interface working so I can focus on creating features and later then finishing product and then I need to finish documentation, upload here code, schematic etc. (And write instruction what each function does and where to find more information, because at this point seems like new users find using this really hard, because there really ain't any step by step instructions for this).

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Re: MacroPad

Post by FireFlower » Mon Apr 27, 2009 9:25 am

Ok here is the code what I have created so far. I have downloaded now the rest of the community projects that are related to keyboard. I wonder is request a pressed key from host possible without driver software for the host. Anyway I have not been really able to write USB descriptor because I don't really understand it, hopefully I will when I have compared other projects.

Code: Select all

/*****************************************************                          
This program was produced by the
CodeWizardAVR V2.03.9 Evaluation
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

LICENSE : GNU General Public License Version 2 (GPL)
Project : LopputyöMHJR
Version : 0001proto
Date    : 27.4.2009
Author  : Freeware, for evaluation and non-commercial use only
Company : KAO (Kainuun ammattiopisto), Kainuu Vocational College ||| www.kao.fi
Comments: MacroPAD USB project. Save anykind 256 characters long string to any 8 Macro buttons.

To do:
* odDebugInit();              // Find out what this does
* sei();                      // Interrupt (interrupt.h)
* DBG1(0x00, 0, 0);           // Find out this too
* Send USB request to computer for key data
*

Chip type               : ATmega32
Program type            : Application
AVR Core Clock frequency: 12,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wtd.h>
#include <mega32.h>

#include "usbdrv.h"

// Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions |||
// Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions |||
// Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions |||

void Hardware_init ()
{
int   i, j;
     
         PORTD = 0x00;   /* 0000 0000 bin: activate pull-ups except on USB lines */
         DDRD = 0x;ff    /* 1111 1111 bin: all pins output (-> 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 = 0xfa;    /* 1111 1010 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 */
}


int get_keys()                                                         
{
    for (j=0;j<256; j++)
    {
    temp[j]= //Inset Here USB Data request from host for keyboard button pressed
   
    if (PINC.7==0 || j==256) // Is stop called?
        {
        return temp[];
        break;
        }
    }


}


void send_keys(char macro[256])
{
// Insert here USB send keys code
}


/*interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here

}*/

// Declare your global variables here
char Macro_1[256];  // M1 macro key's saved keys are saved in this chart
char Macro_2[256];  // M2 macro key's saved keys are saved in this chart
char Macro_3[256];  // M3 macro key's saved keys are saved in this chart
char Macro_4[256];  // M4 macro key's saved keys are saved in this chart
char Macro_5[256];  // M5 macro key's saved keys are saved in this chart
char Macro_6[256];  // M6 macro key's saved keys are saved in this chart
char Macro_7[256];  // M7 macro key's saved keys are saved in this chart
char Macro_8[256];  // M8 macro key's saved keys are saved in this chart


void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTA=0xFF;
DDRA=0x00;

// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=In Func0=In
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=P State0=P
PORTC=0x03;
DDRC=0xFC;

/*// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xFF;*/

wdt_enable(WDTO_2S);        // Watchdog timer enabled
Hardware_init();            // USB line reset and loader
odDebugInit();              // Find out what this does
usbInit();                  // I only know this has to here
sei();                      // Interrupt (interrupt.h)
DBG1(0x00, 0, 0);           // What is this?

// Global enable interrupts
// #asm("sei")


// Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program |||
// Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program |||
// Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program |||
while (1)
      {
      wdt_reset();          // watchdog timer reset
     usbPoll();            // Needed by USB protocol
      if (PINC.7==0)        // Is Record/Stop button pressed to start recording
      {
        for (i=0;i>10;i--)  // Eternal loop until variable i is bigger than 10.
        {
            if (PORTA!=0xff)
            {
                MacroID=PORTA;
                switch MacroID
                {
                case 0xfe:              // M1 key
                Macro_1[]=get_keys();
                i=20;
                break;
           
                case 0xfd:              // M2 key
                Macro_2[]=get_keys();
                i=20;
                break;
           
                case 0xfb:              // M3 key
                Macro_3[]=get_keys();
                i=20;
                break;
           
                case 0xf7:             // M4 Key
                Macro_4[]=get_keys();
                i=20;
                break;
           
                case 0xef:             // M5 key
                Macro_5[]=get_keys();
                i=20;
                break;
           
                case 0xdf:             // M6 key
                Macro_6[]=get_keys();
                i=20;
                break;
           
                case 0xbf:             // M7 key
                Macro_7[]=get_keys();
                i=20;
                break;
           
                case 0x7f:             // M8 key
                Macro_8[]=get_keys();
                i=20;
                break;
           
                case default:
                break;
                }
            }
        }
      }
     
      if (PORTA!=0xff) // Is in PORTA any key pressed
        {
        MacroID=PORTA; // Any key was pressed, save data to MacroID
        switch MacroID
                {
                case 0xfe:            // M1 key
                    if (Macro_1[]==0)
                    break;
               
                    else
                    {                 
                    send_keys(Macro_1[]);
                    break;
                    }
           
                case 0xfd:            // M2 key
                    if (Macro_2[]==0)
                    break;
               
                    else
                    {                 
                    send_keys(Macro_2[]);
                    break;
                    }
               
                case 0xfb:            // M3 key
                    if (Macro_3[]==0)
                    break;
               
                    else
                    {
                    send_keys(Macro_3[]);
                    break;
                    }
               
                case 0xf7:           // M4 key
                    if (Macro_4[]==0)
                    break;
               
                    else
                    {
                    send_keys(Macro_4[]);
                    break;
                    }
               
                case 0xef:          // M5 key
                    if (Macro_5[]==0)
                    break;
               
                    else
                    {
                    send_keys(Macro_5[]);
                    break;
                    }
               
                case 0xdf:          // M6 key
                    if (Macro_6[]==0)
                    break;
               
                    else
                    {
                    send_keys(Macro_6[]);
                    break;
                    }
               
                case 0xbf:          // M7 key
                    if (Macro_7[]==0)
                    break;
               
                    else
                    {   
                    send_keys(Macro_7[]);
                    break;
                    }
               
                case 0x7f:         // M8 key
                    if (Macro_8[]==0)
                    break;
               
                    else
                    {
                    send_keys(Macro_8[]);
                    break;
                    }
                   
                case default:     // Any other key combination
                    break;
                }
     
        }
      }
}

mojo
Rank 1
Rank 1
Posts: 39
Joined: Tue Mar 04, 2008 3:57 pm

Re: MacroPad

Post by mojo » Sun May 03, 2009 10:18 pm

I already made something like this as a quick hack. No schematic yet but the code should speak for itself. I will try and update my web site soon.

Need to find some key stickers :)

Image

Code: Select all

#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 ------------------------ */

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

    PORTB   = 0xff;         /* activate all pull-ups */
    DDRB   = 0;             /* all pins input */
    PORTD   = 0b11110011;   /* 1111 1010 bin: activate pull-ups except on USB lines */
    DDRD    = 0b00001100;   /* 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   = 0b00000000;   /* 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    8 //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;

   for (i = 0; i < 8; i++)
   {
      if ((PINB & (1<<i)) == 0)
         return i + 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
};
/* 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_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

#define   KEY_F13      104
#define   KEY_F14      105
#define   KEY_F15      106
#define   KEY_F16      107
#define   KEY_F17      108
#define   KEY_F18      109
#define   KEY_F19      110
#define   KEY_F20      111

#define   KEY_NUM1   89
#define   KEY_NUM2   90
#define   KEY_NUM3   91
#define   KEY_NUM4   92
#define   KEY_NUM5   93
#define   KEY_NUM6   94
#define   KEY_NUM7   95
#define   KEY_NUM8   96

static const uchar  keyReport[NUM_KEYS + 1][2] PROGMEM = {
/* none */  {0, 0},                     /* no key pressed */
/*  1 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM1},
/*  2 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM2},
/*  3 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM3},
/*  4 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM4},
/*  5 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM5},
/*  6 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM6},
/*  7 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM7},
/*  8 */    {MOD_CONTROL_LEFT | MOD_ALT_LEFT | MOD_GUI_LEFT, KEY_NUM8}
};

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(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)){   
            TIFR = 1<<TOV0;
            if(idleRate != 0){
                if(idleCounter > 4){
                    idleCounter -= 5;   
                }else{
                    idleCounter = idleRate;
                    keyDidChange = 1;
                }
            }
        }
*/
        if((keyDidChange == 1) && usbInterruptIsReady()){
            keyDidChange = 2;
            /* use last key and not current key status in order to avoid lost
               changes in key status. */
            buildReport(lastKey);
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
        }


      if((keyDidChange == 2) && usbInterruptIsReady())
      {
         keyDidChange = 0;
            buildReport(0);
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
      }

   }
   return 0;
}

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Re: MacroPad

Post by FireFlower » Tue May 19, 2009 11:28 am

I can't debug usbInit & usbPoll undefined refence error in my main code.

Seems like It doesn't go and get it from usbdrv.h (I have defined USB_PUBLIC to static). Any quick ideas why it does this?

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Re: MacroPad

Post by FireFlower » Wed May 20, 2009 12:42 pm

Schematics:
http://i403.photobucket.com/albums/pp11 ... ifinal.jpg

main.c

Code: Select all

/*****************************************************
LICENSE : GNU General Public License Version 2 (GPL)
Program : AVR Studio 4.16 SP1, WinAVR 20071221
Project : LopputyöMHJR
Version : 0.1.01
Date    : 19.5.2009
Author  : Freeware, for evaluation and non-commercial use only
Company : KAO (Kainuun ammattiopisto), Kainuu Vocational College ||| www.kao.fi
Comments: MacroPAD USB project. Save anykind 256 characters long string to any 8 Macro buttons.

To do list:
* Fix errors
* Check how many keys are saved to data column, 0=no key
* Timer interrupt to do USB Poll?
* Check USB-config
* Start find a way to dynamically save keyboard data to Macropad


Chip type               : ATmega32
Program type            : Application
AVR Core Clock frequency: 12,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

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

#define F_CPU 12000000

#define uchar unsigned char

uchar   idleRate, idleCounter=0;           /* in 4 ms units */
uchar   reportBuffer[8]; // Buffer for HID reports
uchar   MacroData[256][8];

// Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions ||| Functions |||

void Hardware_init ()
{
int    i, j;
     
         PORTD = 0x00;   /* 0000 0000 bin: activate pull-ups except on USB lines */
         DDRD = 0xff;    /* 1111 1111 bin: all pins output (-> 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 = 0xfa;    /* 1111 1010 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 */
}



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

#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
#define NUM_KEYS   26

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},
/* 18 */   {MOD_SHIFT_LEFT, KEY_R},
/* 19 */   {MOD_SHIFT_LEFT, KEY_S},
/* 20 */   {MOD_SHIFT_LEFT, KEY_T},
/* 21 */   {MOD_SHIFT_LEFT, KEY_U},
/* 22 */   {MOD_SHIFT_LEFT, KEY_V},
/* 23 */   {MOD_SHIFT_LEFT, KEY_W},
/* 24 */   {MOD_SHIFT_LEFT, KEY_X},
/* 25 */   {MOD_SHIFT_LEFT, KEY_Y},
/* 26 */   {MOD_SHIFT_LEFT, KEY_Z},
};

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(0);
          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;
}

static uchar macroPressed(void)
{
uchar MACROID;
MACROID = PORTA;
switch (MACROID)
        {
      case 0xfe:              // M1 key
      return 1;
        break;
           
        case 0xfd:              // M2 key
         return 2;
      break;
           
        case 0xfb:              // M3 key
        return 3;
      break;
           
        case 0xf7:             // M4 Key
         return 4;
      break;
           
        case 0xef:             // M5 key
          return 5;
      break;
           
        case 0xdf:             // M6 key
        return 6;
      break;
           
        case 0xbf:             // M7 key
        return 7;
      break;
           
        case 0x7f:             // M8 key
        return 8;
      break;
           
        default:         // Any other Macro key combination
        return 0;
      break;
     }
}

static void macrotestdata(void)
{
int i,j;
   for (j=0; j<=8; j++) // Setting all to 0
      {
      for (i=0; i<=256; i++)
         {
         MacroData[i][j]=0;
         }
      }
MacroData[1][1]=KEY_T; // M1 Key test data
MacroData[2][1]=KEY_E;
MacroData[3][1]=KEY_S;
MacroData[4][1]=KEY_T;
MacroData[1][2]=KEY_P; // M2 Key test data
MacroData[2][2]=KEY_R;
MacroData[3][2]=KEY_O;
MacroData[4][2]=KEY_G;
MacroData[5][2]=KEY_R;
MacroData[6][2]=KEY_A;
MacroData[7][2]=KEY_M;
MacroData[1][3]=KEY_R; // M3 Key test data
MacroData[2][3]=KEY_U;
MacroData[3][3]=KEY_N;
MacroData[4][3]=KEY_N;
MacroData[5][3]=KEY_I;
MacroData[6][3]=KEY_N;
MacroData[7][3]=KEY_G;
MacroData[1][4]=KEY_P; // M4 Key test data
MacroData[2][4]=KEY_L;
MacroData[3][4]=KEY_E;
MacroData[4][4]=KEY_A;
MacroData[5][4]=KEY_S;
MacroData[6][4]=KEY_E;
MacroData[1][5]=KEY_S; // M5 Key test data
MacroData[2][5]=KEY_T;
MacroData[3][5]=KEY_A;
MacroData[4][5]=KEY_N;
MacroData[5][5]=KEY_D;
MacroData[6][5]=KEY_B;
MacroData[7][5]=KEY_Y;
MacroData[1][6]=KEY_H; // M6 Key test data
MacroData[1][6]=KEY_E;
MacroData[1][6]=KEY_L;
MacroData[1][6]=KEY_L;
MacroData[1][6]=KEY_O;
MacroData[1][7]=KEY_W; // M7 Key test data
MacroData[2][7]=KEY_O;
MacroData[3][7]=KEY_R;
MacroData[4][7]=KEY_L;
MacroData[5][7]=KEY_D;
MacroData[1][8]=KEY_A; // M8 Key test data
MacroData[2][8]=KEY_S;
MacroData[3][8]=KEY_D;
MacroData[4][8]=KEY_D;
MacroData[5][8]=KEY_S;
MacroData[6][8]=KEY_A;
}


// Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program ||| Main Program |||

int main(void)
{
macrotestdata();

// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTA=0xFF;
DDRA=0x00;

// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func7=Out Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=P State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x40;
DDRC=0xBF;


wdt_enable(WDTO_2S);        // Watchdog timer enabled
Hardware_init();            // USB line reset and loader
odDebugInit();              // Debugger
void usbInit(void);         // needs to be here before interrupt
sei();                      // Interrupt (interrupt.h)
DBG1(0x00, 0, 0);           

// Main loop ||| Main loop ||| Main loop ||| Main loop ||| Main loop ||| Main loop

while (1)
      {
     uchar Macro;
     uchar lastMacro=0;
     uchar MacroDidChange=0;


      wdt_reset();                // watchdog timer reset
      void usbPoll(void);           // Needed by USB protocol
     Macro = macroPressed();
        if(lastMacro != Macro)
         {
            lastMacro = Macro;
            MacroDidChange=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;
                    MacroDidChange = 1;
                   }
               }
           }

         if(lastMacro!=0 && MacroDidChange && usbInterruptIsReady())
            {
            int i;
               MacroDidChange = 0;
               /* use last key and not current key status in order to avoid lost
                changes in key status. */
            for (i=0; i>256; i++)
               {
               buildReport(MacroData[i][lastMacro]);
                  usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
               }
           }
      } // While
return 0;
} // Main


usbconfig.h

Code: Select all

/* Name: usbconfig.h
 * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
 * Author: Christian Starkjohann
 * Creation Date: 2005-04-01
 * Tabsize: 4
 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
 * This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
 */

#ifndef __usbconfig_h_included__
#define __usbconfig_h_included__

/*
General Description:
This file is an example configuration (with inline documentation) for the USB
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
other hardware interrupt, as long as it is the highest level interrupt, see
section at the end of this file).
+ To create your own usbconfig.h file, copy this file to your project's
+ firmware source directory) and rename it to "usbconfig.h".
+ Then edit it accordingly.
*/

/* ---------------------------- Hardware Config ---------------------------- */

#define USB_CFG_IOPORTNAME      D
/* This is the port where the USB bus is connected. When you configure it to
 * "B", the registers PORTB, PINB and DDRB will be used.
 */
#define USB_CFG_DMINUS_BIT      2
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
 * This may be any bit in the port.
 */
#define USB_CFG_DPLUS_BIT       0
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
 * This may be any bit in the port. Please note that D+ must also be connected
 * to interrupt pin INT0! [You can also use other interrupts, see section
 * "Optional MCU Description" below, or you can connect D- to the interrupt, as
 * it is required if you use the USB_COUNT_SOF feature. If you use D- for the
 * interrupt, the USB interrupt will also be triggered at Start-Of-Frame
 * markers every millisecond.]
 */
#define USB_CFG_CLOCK_KHZ       (F_CPU/1000)
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
 * 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no
 * crystal, they tolerate +/- 1% deviation from the nominal frequency. All
 * other rates require a precision of 2000 ppm and thus a crystal!
 * Default if not specified: 12 MHz
 */
#define USB_CFG_CHECK_CRC       0
/* Define this to 1 if you want that the driver checks integrity of incoming
 * data packets (CRC checks). CRC checks cost quite a bit of code size and are
 * currently only available for 18 MHz crystal clock. You must choose
 * USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
 */

/* ----------------------- Optional Hardware Config ------------------------ */

/* #define USB_CFG_PULLUP_IOPORTNAME   D */
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
 * V+, you can connect and disconnect the device from firmware by calling
 * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
 * This constant defines the port on which the pullup resistor is connected.
 */
/* #define USB_CFG_PULLUP_BIT          4 */
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
 * above) where the 1.5k pullup resistor is connected. See description
 * above for details.
 */

/* --------------------------- Functional Range ---------------------------- */

#define USB_CFG_HAVE_INTRIN_ENDPOINT    1
/* Define this to 1 if you want to compile a version with two endpoints: The
 * default control endpoint 0 and an interrupt-in endpoint (any other endpoint
 * number).
 */
#define USB_CFG_HAVE_INTRIN_ENDPOINT3   0
/* Define this to 1 if you want to compile a version with three endpoints: The
 * default control endpoint 0, an interrupt-in endpoint 3 (or the number
 * configured below) and a catch-all default interrupt-in endpoint as above.
 * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
 */
#define USB_CFG_EP3_NUMBER              3
/* If the so-called endpoint 3 is used, it can now be configured to any other
 * endpoint number (except 0) with this macro. Default if undefined is 3.
 */
/* #define USB_INITIAL_DATATOKEN           USBPID_DATA1 */
/* The above macro defines the startup condition for data toggling on the
 * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
 * Since the token is toggled BEFORE sending any data, the first packet is
 * sent with the oposite value of this configuration!
 */
#define USB_CFG_IMPLEMENT_HALT          0
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
 * for endpoint 1 (interrupt endpoint). Although you may not need this feature,
 * it is required by the standard. We have made it a config option because it
 * bloats the code considerably.
 */
#define USB_CFG_SUPPRESS_INTR_CODE      0
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
 * want to send any data over them. If this macro is defined to 1, functions
 * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
 * you need the interrupt-in endpoints in order to comply to an interface
 * (e.g. HID), but never want to send any data. This option saves a couple
 * of bytes in flash memory and the transmit buffers in RAM.
 */
#define USB_CFG_INTR_POLL_INTERVAL      10
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
 * interval. The value is in milliseconds and must not be less than 10 ms for
 * low speed devices.
 */
#define USB_CFG_IS_SELF_POWERED         0
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
 * device is powered from the USB bus.
 */
#define USB_CFG_MAX_BUS_POWER           100
/* Set this variable to the maximum USB bus power consumption of your device.
 * The value is in milliamperes. [It will be divided by two since USB
 * communicates power requirements in units of 2 mA.]
 */
#define USB_CFG_IMPLEMENT_FN_WRITE      0
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
 * transfers. Set it to 0 if you don't need it and want to save a couple of
 * bytes.
 */
#define USB_CFG_IMPLEMENT_FN_READ       0
/* Set this to 1 if you need to send control replies which are generated
 * "on the fly" when usbFunctionRead() is called. If you only want to send
 * data from a static buffer, set it to 0 and return the data from
 * usbFunctionSetup(). This saves a couple of bytes.
 */
#define USB_CFG_IMPLEMENT_FN_WRITEOUT   0
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
 * You must implement the function usbFunctionWriteOut() which receives all
 * interrupt/bulk data sent to any endpoint other than 0. The endpoint number
 * can be found in 'usbRxToken'.
 */
#define USB_CFG_HAVE_FLOWCONTROL        0
/* Define this to 1 if you want flowcontrol over USB data. See the definition
 * of the macros usbDisableAllRequests() and usbEnableAllRequests() in
 * usbdrv.h.
 */
#define USB_CFG_LONG_TRANSFERS          0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
 * in a single control-in or control-out transfer. Note that the capability
 * for long transfers increases the driver size.
 */
/* #define USB_RX_USER_HOOK(data, len)     if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
/* This macro is a hook if you want to do unconventional things. If it is
 * defined, it's inserted at the beginning of received message processing.
 * If you eat the received message and don't want default processing to
 * proceed, do a return after doing your things. One possible application
 * (besides debugging) is to flash a status LED on each packet.
 */
/* #define USB_RESET_HOOK(resetStarts)     if(!resetStarts){hadUsbReset();} */
/* This macro is a hook if you need to know when an USB RESET occurs. It has
 * one parameter which distinguishes between the start of RESET state and its
 * end.
 */
/* #define USB_SET_ADDRESS_HOOK()              hadAddressAssigned(); */
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
 * received.
 */
#define USB_COUNT_SOF                   0
/* define this macro to 1 if you need the global variable "usbSofCount" which
 * counts SOF packets. This feature requires that the hardware interrupt is
 * connected to D- instead of D+.
 */
/* #ifdef __ASSEMBLER__
 * macro myAssemblerMacro
 *     in      YL, TCNT0
 *     sts     timer0Snapshot, YL
 *     endm
 * #endif
 * #define USB_SOF_HOOK                    myAssemblerMacro
 * This macro (if defined) is executed in the assembler module when a
 * Start Of Frame condition is detected. It is recommended to define it to
 * the name of an assembler macro which is defined here as well so that more
 * than one assembler instruction can be used. The macro may use the register
 * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
 * immediately after an SOF pulse may be lost and must be retried by the host.
 * What can you do with this hook? Since the SOF signal occurs exactly every
 * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
 * designs running on the internal RC oscillator.
 * Please note that Start Of Frame detection works only if D- is wired to the
 * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
 */
#define USB_CFG_CHECK_DATA_TOGGLING     0
/* define this macro to 1 if you want to filter out duplicate data packets
 * sent by the host. Duplicates occur only as a consequence of communication
 * errors, when the host does not receive an ACK. Please note that you need to
 * implement the filtering yourself in usbFunctionWriteOut() and
 * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
 * for each control- and out-endpoint to check for duplicate packets.
 */
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0
/* define this macro to 1 if you want the function usbMeasureFrameLength()
 * compiled in. This function can be used to calibrate the AVR's RC oscillator.
 */

/* -------------------------- Device Description --------------------------- */
/* We cannot use Obdev's free shared VID/PID pair because this is a HID.
 * We use John Hyde's VID (author of the book "USB Design By Example") for
 * this example instead. John has offered this VID for use by students for
 * non-commercial devices. Well... This example is for demonstration and
 * education only... DO NOT LET DEVICES WITH THIS VID ESCAPE YOUR LAB!
 * The Product-ID is a random number.
 */
#define  USB_CFG_VENDOR_ID       0x42, 0x42
/* USB vendor ID for the device, low byte first. If you have registered your
 * own Vendor ID, define it here. Otherwise you use one of obdev's free shared
 * VID/PID pairs. Be sure to read USBID-License.txt for rules!
 * + This template uses obdev's shared VID/PID pair: 0x16c0/0x5dc.
 * + Use this VID/PID pair ONLY if you understand the implications!
 */
#define  USB_CFG_DEVICE_ID       0xad, 0xde
/* This is the ID of the product, low byte first. It is interpreted in the
 * scope of the vendor ID. If you have registered your own VID with usb.org
 * or if you have licensed a PID from somebody else, define it here. Otherwise
 * you use obdev's free shared VID/PID pair. Be sure to read the rules in
 * USBID-License.txt!
 * + This template uses obdev's shared VID/PID pair: 0x16c0/0x5dc.
 * + Use this VID/PID pair ONLY if you understand the implications!
 */
#define USB_CFG_DEVICE_VERSION  0x00, 0x01
/* Version number of the device: Minor number first, then major number.
 */
#define USB_CFG_VENDOR_NAME     'o', 'b', 'd', 'e', 'v', '.', 'a', 't'
#define USB_CFG_VENDOR_NAME_LEN 8
/* These two values define the vendor name returned by the USB device. The name
 * must be given as a list of characters under single quotes. The characters
 * are interpreted as Unicode (UTF-16) entities.
 * If you don't want a vendor name string, undefine these macros.
 * ALWAYS define a vendor name containing your Internet domain name if you use
 * obdev's free shared VID/PID pair. See the file USBID-License.txt for
 * details.
 */
#define USB_CFG_DEVICE_NAME     'M', 'a', 'c', 'r', 'o', 'P', 'a', 'd'
#define USB_CFG_DEVICE_NAME_LEN 8
/* Same as above for the device name. If you don't want a device name, undefine
 * the macros. See the file USBID-License.txt before you assign a name if you
 * use a shared VID/PID.
 */
/*#define USB_CFG_SERIAL_NUMBER   'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN   0 */
/* Same as above for the serial number. If you don't want a serial number,
 * undefine the macros.
 * It may be useful to provide the serial number through other means than at
 * compile time. See the section about descriptor properties below for how
 * to fine tune control over USB descriptors such as the string descriptor
 * for the serial number.
 */
#define USB_CFG_DEVICE_CLASS        0    /* set to 0 if deferred to interface */
#define USB_CFG_DEVICE_SUBCLASS     0
/* See USB specification if you want to conform to an existing device class.
 * Class 0xff is "vendor specific".
 */
#define USB_CFG_INTERFACE_CLASS     0x03   /* define class here if not at device level */
#define USB_CFG_INTERFACE_SUBCLASS  0
#define USB_CFG_INTERFACE_PROTOCOL  0
/* See USB specification if you want to conform to an existing device class or
 * protocol. The following classes must be set at interface level:
 * HID class is 3, no subclass and protocol required (but may be useful!)
 * CDC class is 2, use subclass 2 and protocol 1 for ACM
 */
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    35
/* Define this to the length of the HID report descriptor, if you implement
 * an HID device. Otherwise don't define it or define it to 0.
 * If you use this define, you must add a PROGMEM character array named
 * "usbHidReportDescriptor" to your code which contains the report descriptor.
 * Don't forget to keep the array and this define in sync!
 */

#define USB_PUBLIC static
/* Use the define above if you #include usbdrv.c instead of linking against it.
 * This technique saves a couple of bytes in flash memory.
 */

/* ------------------- Fine Control over USB Descriptors ------------------- */
/* If you don't want to use the driver's default USB descriptors, you can
 * provide our own. These can be provided as (1) fixed length static data in
 * flash memory, (2) fixed length static data in RAM or (3) dynamically at
 * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
 * information about this function.
 * Descriptor handling is configured through the descriptor's properties. If
 * no properties are defined or if they are 0, the default descriptor is used.
 * Possible properties are:
 *   + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
 *     at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
 *     used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
 *     you want RAM pointers.
 *   + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
 *     in static memory is in RAM, not in flash memory.
 *   + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
 *     the driver must know the descriptor's length. The descriptor itself is
 *     found at the address of a well known identifier (see below).
 * List of static descriptor names (must be declared PROGMEM if in flash):
 *   char usbDescriptorDevice[];
 *   char usbDescriptorConfiguration[];
 *   char usbDescriptorHidReport[];
 *   char usbDescriptorString0[];
 *   int usbDescriptorStringVendor[];
 *   int usbDescriptorStringDevice[];
 *   int usbDescriptorStringSerialNumber[];
 * Other descriptors can't be provided statically, they must be provided
 * dynamically at runtime.
 *
 * Descriptor properties are or-ed or added together, e.g.:
 * #define USB_CFG_DESCR_PROPS_DEVICE   (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
 *
 * The following descriptors are defined:
 *   USB_CFG_DESCR_PROPS_DEVICE
 *   USB_CFG_DESCR_PROPS_CONFIGURATION
 *   USB_CFG_DESCR_PROPS_STRINGS
 *   USB_CFG_DESCR_PROPS_STRING_0
 *   USB_CFG_DESCR_PROPS_STRING_VENDOR
 *   USB_CFG_DESCR_PROPS_STRING_PRODUCT
 *   USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
 *   USB_CFG_DESCR_PROPS_HID
 *   USB_CFG_DESCR_PROPS_HID_REPORT
 *   USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
 *
 * Note about string descriptors: String descriptors are not just strings, they
 * are Unicode strings prefixed with a 2 byte header. Example:
 * int  serialNumberDescriptor[] = {
 *     USB_STRING_DESCRIPTOR_HEADER(6),
 *     'S', 'e', 'r', 'i', 'a', 'l'
 * };
 */

#define USB_CFG_DESCR_PROPS_DEVICE                  0
#define USB_CFG_DESCR_PROPS_CONFIGURATION           0
#define USB_CFG_DESCR_PROPS_STRINGS                 0
#define USB_CFG_DESCR_PROPS_STRING_0                0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR           0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT          0
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    0
#define USB_CFG_DESCR_PROPS_HID                     0
#define USB_CFG_DESCR_PROPS_HID_REPORT              0
#define USB_CFG_DESCR_PROPS_UNKNOWN                 0

/* ----------------------- Optional MCU Description ------------------------ */

/* The following configurations have working defaults in usbdrv.h. You
 * usually don't need to set them explicitly. Only if you want to run
 * the driver on a device which is not yet supported or with a compiler
 * which is not fully supported (such as IAR C) or if you use a differnt
 * interrupt than INT0, you may have to define some of these.
 */
/* #define USB_INTR_CFG            MCUCR */
/* #define USB_INTR_CFG_SET        ((1 << ISC00) | (1 << ISC01)) */
/* #define USB_INTR_CFG_CLR        0 */
/* #define USB_INTR_ENABLE         GIMSK */
/* #define USB_INTR_ENABLE_BIT     INT0 */
/* #define USB_INTR_PENDING        GIFR */
/* #define USB_INTR_PENDING_BIT    INTF0 */
/* #define USB_INTR_VECTOR         SIG_INTERRUPT0 */

#endif /* __usbconfig_h_included__ */


warnings

Code: Select all

[list]
[*]../macropadmain.c:34:1: warning: "F_CPU" redefined
[*]<command-line>: warning: this is the location of the previous definition
[*]C:\Documents and Settings\Make\Omat tiedostot\avrstudio lopputyo\..\..\usbdrv/usbdrv.h:218: warning: 'usbSetInterrupt' used but never defined
[*]../macropadmain.c:355: warning: 'usbInit' declared 'static' but never defined
[*]../macropadmain.c:370: warning: 'usbPoll' declared 'static' but never defined
[*]../macropadmain.c:182: warning: 'usbFunctionSetup' defined but not used
[*]C:\Documents and Settings\Make\Omat tiedostot\avrstudio lopputyo\..\..\usbdrv/usbdrv.h:211: warning: 'usbFunctionDescriptor' declared 'static' but never defined
[/list]


Alright me and my partner fixed all errors but we still have those warnings and usbPoll() and usbInit() still need to be 'void usbPoll(void)' and 'void usbInit(void)' to not give error message. I think I have miss configured somewhere when it says that but I don't know what I have misconfigured or not configured yet.

Also I tried to use above code to my device but nothing happened. Atleast I know it gets is power to chip because I made the led flash so that is not the problem.

I check during monday for possible short circuit that might have happened and fix them and try again but now I really need veterans help. I have mainly used UsbHIDkeys project as example and other hid projects too to understand this.

Well now my "finished" code doesn't give error but I think because of the voids in usbPoll and usbInit this thingy won't work yet. Hopefully you can help me to fix this so I can move on to next feature =)

FireFlower
Posts: 9
Joined: Wed Jan 07, 2009 7:24 pm

Re: MacroPad

Post by FireFlower » Sat May 23, 2009 10:47 pm

See above post for updated info about project. I really now need your help with 'usbInit' and 'usbPoll' function.

Post Reply