V-USB on ATMega162/12MHz - Basic Keyboard Functionality

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
gknigh_t
Posts: 2
Joined: Tue Dec 22, 2009 5:26 am

V-USB on ATMega162/12MHz - Basic Keyboard Functionality

Post by gknigh_t » Mon Mar 22, 2010 11:11 pm

Hello,

I've taken the most basic example of HID Keyboard example from V-USB to frankenstein together the most basic of interface panels.
Think of it as a LCD with function keys around it. The ATMega162 keyscans the user defined buttons and the V-USB soft-core sends USB messaging to a Windows PC who thinks its a keyboard.

The V-USB keyboard functionality works great with messaging being sent and received by the PC. Some of the keys tell the MCU to bit-bang serial data off to the LCD to do things like brightness/contrast and so forth. Inside the for(;;) where the USB stuff resides, there is a keyscan routine that scans rows/colums to determine what buttons you pressed and acts accordingly.

The problem is this, if pressing key 1 returns 0x31 saying ascii '7' V-USB transmits it. If you press a key that has to invoke a function that has to toggle an IO to emulate serial data, its like it gets skipped over completely.

Code: Select all

main.c {

vusb_preemble();
for(;;){
      wdt_reset();
      usbPoll();
       
      //BlinkFault();
      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));
        } */

}
}

vusb_preenble contains things like the 300ms disconnect, odDebugInit, usbInit(), sei(), DBG1(0x00,0,0) and so on.
A snipped of keypressed is shown below.

Code: Select all

static uchar keyPressed(void)
{
   uchar  ch = 0;

   // First Column
   output_low(PORTD, KEYPIN1);
   output_high(PORTB, KEYPIN7);
   output_high(PORTB, KEYPIN8);
   output_high(PORTB, KEYPIN9);
   NOP;
   NOP;
   NOP;
   NOP;
   NOP;
   NOP;
   NOP;
   if (sw_is_pressed(PIND,KEYPIN2)) { ch = KEY_A; }   // SW02: 'TEST'
   if (sw_is_pressed(PIND,KEYPIN3)) { ch = KEY_B; }   // SW04: '2'
   if (sw_is_pressed(PIND,KEYPIN4)) { TogglePD0(); }   // SW05: '3'
   if (sw_is_pressed(PINB,KEYPIN10)) { ch = KEY_D; }   // SW07: '5'
   if (sw_is_pressed(PINA,KEYPIN11)) { ch = KEY_E; }   // SW08: '6'
   if (sw_is_pressed(PINA,KEYPIN12)) { ch = KEY_F; }   // SW10: '8'
   if (sw_is_pressed(PINA,KEYPIN13)) { ch = KEY_G; }   // SW11: '9'
return ch;
}


The function TogglePD0() can be something simple like blink an LED or use a simple bit-bang example for faking serial data.
It is totally bypassed. The function was tested separately before being included.

Comments welcome!

Post Reply