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!