From 15a1443a098edec7f19ea6628da6170b2f979ea2 Mon Sep 17 00:00:00 2001 From: Pat Thoyts Date: Wed, 6 Nov 2013 22:20:21 +0000 Subject: [PATCH] Fixed return code for usbFunctionWrite to indicate no more data. On some hubs the device was being polled rapidly which slowed down the heartbeat led indicating too much processing was going on. It turns out we failed to respond correctly when the LED status was set and the host permanently attempted to get a response from the device. Also reworked the initialization code and tidied up and added more comments. Signed-off-by: Pat Thoyts --- main.c | 123 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/main.c b/main.c index 21ee415..5d19854 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ /* hid_keybd.c * * This uses a ATtiny45 + * (4K flash, 256 bytes RAM, 256 bytes EEPROM) * +----------+ * reset -| RST VCC|- 5V * Key_A -| PB3 PB2|- D+ / SCK @@ -29,9 +30,10 @@ #include "descriptor.c" -/* one byte reserved for oscillator calibration and 6 bytes for serial number */ -#define CONFIG_TOP ((uint8_t *)1+6) -#define CONFIG_LEN 128 +/* + * Specify the LED pin (used for heartbeat and CapsLock indication). + */ +#define LED_PIN PB1 char EEMEM ee_serial[USB_CFG_SERIAL_NUMBER_LEN] = { USB_CFG_SERIAL_NUMBER }; uint8_t EEMEM ee_calibration = 0xff; @@ -60,7 +62,8 @@ enum { Led_Kana = 5, Led_Power = 6, - Led_Slow = 64000, + Led_Glacial = 65500, + Led_Slow = 48000, Led_Fast = 32000, Led_Quick = 16000, }; @@ -102,24 +105,27 @@ static Global_t Global = { 0, Led_Slow, 0, 0, 0xff, 0, 0xff, {0, 0, {0, 0, 0, 0, 0, 0}} }; +static void +setLEDspeed() +{ + if (Global.LED_state & Led_CapsLock) { + Global.led_limit = Led_Fast; + } else { + Global.led_limit = Led_Slow; + } +} + /* called when the PC sets the LED state, we can set - * set the caps lock led indicator + * set the caps lock led indicator (flash faster for capslock) */ uchar usbFunctionWrite(uchar *data, uchar len) { - if (data[0] == Global.LED_state) - return 1; - else + if (data[0] != Global.LED_state) { Global.LED_state = data[0]; - - if (Global.LED_state & Led_CapsLock) - //PORTB |= 1<< PB0; - Global.led_limit = Led_Fast; - else - //PORTB &= ~(1 << PB0); - Global.led_limit = Led_Slow; - return 0; + setLEDspeed(); + } + return 1; /* tell driver nothing else to write */ } usbMsgLen_t @@ -151,24 +157,37 @@ static void appInit(void) { /* Disable ADC and the Analog comparator as they are not used. */ - ADCSRA &= ~(_BV(ADEN)); - ACSR &= ~(_BV(ACD)); + ACSR |= _BV(ACD); /* disable the analog comparator */ + ADCSRA &= ~_BV(ADEN); /* disable ADC */ + PRR &= ~_BV(PRADC); /* power down the ADC */ - /* see PCMSK for pin change interrupts - * As PCINT interrupts can wake from sleep, we should use these and - * be asleep or low power most of the time? USB interrupt wake? + /* + * LED_PIN is output and set high + * PB5 is input with pullup enabled (reset button) + * PB3 and PB4 are input with pullup enabled (our keyboard buttons) + * PB0 and PB2 are the USB comms pins and are set to output for 10ms + * to cause a USB reset, then set to input. */ - - /* Set PB3 and 4 as input (0 to DDRB bit) - * Set PB0 and 2 as output (1 to DDRB bit) for USB comms - * Enable pullup on PB5 (reset) and drive PB1 high (LED output pin) - */ - PORTB = _BV(PB1) | _BV(PB3) | _BV(PB5); - DDRB = _BV(PB0) | _BV(PB2); /* usb pins output (reset) */ + PORTB = _BV(LED_PIN) | _BV(PB3) | _BV(PB4) | _BV(PB5); + DDRB = _BV(LED_PIN) |_BV(DDB0) |_BV(DDB2); _delay_ms(10); - DDRB = _BV(PB1); /* undo usb reset and set led to output */ + DDRB &= ~(_BV(DDB0) | _BV(DDB2)); +} - TCCR0B |= (1 << CS01); /* timer 0 at clk/8 will generate randomness */ +static void +handleKeyPress(uint8_t modifier, uint8_t keycode) +{ + if (Global.state == State_Default) { + Global.led_limit = Led_Quick; + ++Global.key_down_counter; + + if (Global.key_down_counter > 8000) { + Global.state = State_KeyReady; + Global.keyboard_report.modifier = modifier; + Global.keyboard_report.keycode[0] = keycode; + Global.key_down_counter = 0; + } + } } static void @@ -178,40 +197,20 @@ appPoll(void) ++Global.led_counter; if (Global.led_counter > Global.led_limit) { - PORTB ^= _BV(PB1); /* toggle led */ + PORTB ^= _BV(LED_PIN); /* toggle led */ Global.led_counter = 0; } /* key pressed (pin driven low) */ - if (!(pin_state & (1 << PB3))) { - Global.led_limit = Led_Quick; - if (Global.state == State_Default) { - if (Global.key_down_counter == 255) { - Global.state = State_KeyReady; - Global.keyboard_report.modifier = 0; - Global.keyboard_report.keycode[0] = Key_A; - Global.key_down_counter = 0; - } else { - ++Global.key_down_counter; - } - } + if (!(pin_state & _BV(PB3))) { + handleKeyPress(0, Key_A); } - if (!(pin_state & (1 << PB4))) { - Global.led_limit = Led_Quick; - if (Global.state == State_Default) { - if (Global.key_down_counter == 255) { - Global.state = State_KeyReady; - Global.keyboard_report.modifier = 0; - Global.keyboard_report.keycode[0] = Key_Execute; - Global.key_down_counter = 0; - } else { - ++Global.key_down_counter; - } - } + if (!(pin_state & _BV(PB4))) { + handleKeyPress(0, Key_CapsLock); } - if (pin_state & ((1<