summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c312
1 files changed, 0 insertions, 312 deletions
diff --git a/main.c b/main.c
deleted file mode 100644
index bad8df1..0000000
--- a/main.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- Project: Rotary-Dial-To-USB Interface
- Author: Florian Jung (flo@windfisch.org)
- Copyright: (c) 2014 by Florian Jung and partially others (see below)
- License: GNU GPL v3 (see LICENSE)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 3 as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
- This project is based on the code for the AVR ATtiny USB Tutorial at
- http://codeandlife.com/ by Joonas Pihlajamaa, joonas.pihlajamaa@iki.fi,
- which is in turn based on the V-USB example code by Christian Starkjohann
- (Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH)
-*/
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/wdt.h>
-#include <avr/eeprom.h>
-#include <util/delay.h>
-
-#include "usbdrv/usbdrv.h"
-
-// ************************
-// *** USB HID ROUTINES ***
-// ************************
-
-// From Frank Zhao's USB Business Card project
-// http://www.frank-zhao.com/cache/usbbusinesscard_details.php
-PROGMEM const char
- usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
- 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
- 0x09, 0x06, // USAGE (Keyboard)
- 0xa1, 0x01, // COLLECTION (Application)
- 0x75, 0x01, // REPORT_SIZE (1)
- 0x95, 0x08, // REPORT_COUNT (8)
- 0x05, 0x07, // USAGE_PAGE (Keyboard)(Key Codes)
- 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)(224)
- 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)(231)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x25, 0x01, // LOGICAL_MAXIMUM (1)
- 0x81, 0x02, // INPUT (Data,Var,Abs) ; Modifier byte
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x81, 0x03, // INPUT (Cnst,Var,Abs) ; Reserved byte
- 0x95, 0x05, // REPORT_COUNT (5)
- 0x75, 0x01, // REPORT_SIZE (1)
- 0x05, 0x08, // USAGE_PAGE (LEDs)
- 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
- 0x29, 0x05, // USAGE_MAXIMUM (Kana)
- 0x91, 0x02, // OUTPUT (Data,Var,Abs) ; LED report
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x75, 0x03, // REPORT_SIZE (3)
- 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) ; LED report padding
- 0x95, 0x06, // REPORT_COUNT (6)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x25, 0x65, // LOGICAL_MAXIMUM (101)
- 0x05, 0x07, // USAGE_PAGE (Keyboard)(Key Codes)
- 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))(0)
- 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)(101)
- 0x81, 0x00, // INPUT (Data,Ary,Abs)
- 0xc0 // END_COLLECTION
-};
-
-typedef struct
-{
- uint8_t modifier;
- uint8_t reserved;
- uint8_t keycode[6];
-} keyboard_report_t;
-
-static keyboard_report_t keyboard_report; // sent to PC
-volatile static uchar LED_state = 0xff; // received from PC
-static uchar idleRate; // repeat rate for keyboards
-
-
-#define LED_BLUE (1<<5)
-#define LED_RED (1<<4)
-#define LED_GREEN (1<<3)
-
-usbMsgLen_t usbFunctionSetup(uchar data[8])
-{
- usbRequest_t *rq = (void *) data;
-
- if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
- {
- switch (rq->bRequest)
- {
- case USBRQ_HID_GET_REPORT: // send "no keys pressed" if asked here
- // wValue: ReportType (highbyte), ReportID (lowbyte)
- usbMsgPtr = (void *) &keyboard_report; // we only have this one
- keyboard_report.modifier = 0;
- keyboard_report.keycode[0] = 0;
- return sizeof(keyboard_report);
-
- case USBRQ_HID_SET_REPORT: // if wLength == 1, should be LED state
- return (rq->wLength.word == 1) ? USB_NO_MSG : 0;
-
- case USBRQ_HID_GET_IDLE: // send idle rate to PC as required by spec
- usbMsgPtr = &idleRate;
- return 1;
-
- case USBRQ_HID_SET_IDLE: // save idle rate as required by spec
- idleRate = rq->wValue.bytes[1];
- return 0;
- }
- }
-
- return 0; // by default don't return any data
-}
-
-usbMsgLen_t usbFunctionWrite(uint8_t * data, uchar len)
-{
- if (data[0] == LED_state)
- return 1;
- else
- LED_state = data[0];
-
- return 1; // Data read, not expecting more
-}
-
-// Now only supports letters 'a' to 'z' and 0 (NULL) to clear buttons
-void buildReport(int n)
-{
- keyboard_report.modifier = 0;
-
- if (n > 0 && n <= 10)
- keyboard_report.keycode[0] = 29+n;
- else if (n == 0)
- keyboard_report.keycode[0] = 39;
- else if (n == -2)
- keyboard_report.keycode[0] = 40; // enter
- else if (n == -1)
- keyboard_report.keycode[0] = 0;
-}
-
-#define STATE_WAIT 0
-#define STATE_SEND_KEY 1
-#define STATE_RELEASE_KEY 2
-
-void jump_to_bootloader(void)
-{
- cli();
- wdt_enable(WDTO_15MS);
- while (1);
-}
-
-
-#define DEBOUNCE_MAX 100
-uint8_t idle_stable = 42;
-uint8_t pulse_stable = 42;
-uint16_t idlectr = DEBOUNCE_MAX;
-uint16_t pulsectr = DEBOUNCE_MAX;
-
-uint8_t oldidle = 42;
-uint8_t oldpulse = 42;
-
-int main()
-{
- int key_to_send;
- int n_pulses = 0;
-
- uchar i, button_release_counter = 0, state = STATE_WAIT;
-
- DDRC = 0x38; // LEDs as output
- PORTC |= LED_BLUE | LED_RED | LED_GREEN;
- DDRD &= ~0xF3; // connector ports as input
- DDRB &= ~0x3C;
- PORTD &= ~0xF3; // disable pullups for unused ports
- PORTB &= ~0x0C;
- PORTB |= 0x30; // enable pullups for PB4 and 5
-
- cli();
-
- for (i = 0; i < sizeof(keyboard_report); i++) // clear report initially
- ((uchar *) & keyboard_report)[i] = 0;
-
- wdt_enable(WDTO_1S); // enable 1s watchdog timer
-
- usbInit();
-
- usbDeviceDisconnect(); // enforce re-enumeration
- for (i = 0; i < 250; i++)
- { // wait 500 ms
- wdt_reset(); // keep the watchdog happy
- _delay_ms(10);
- }
- usbDeviceConnect();
-
- sei(); // Enable interrupts after re-enumeration
- uint32_t j;
-
- while (1)
- {
- wdt_reset(); // keep the watchdog happy
- usbPoll();
-
-
- // characters are sent when messageState == STATE_SEND and after receiving
- // the initial LED state from PC (good way to wait until device is recognized)
-
- int idle = (PINB & 0x10);
- int pulse = (PINB & 0x20);
-
- if (idle != idle_stable)
- {
- idlectr++;
- if (idlectr > DEBOUNCE_MAX)
- idle_stable = idle;
- }
- else
- idlectr=0;
-
- if (pulse != pulse_stable)
- {
- pulsectr++;
- if (pulsectr > DEBOUNCE_MAX)
- pulse_stable = pulse;
- }
- else
- pulsectr=0;
-
- if (pulse_stable)
- PORTC &= ~LED_RED;
- else
- PORTC |= LED_RED;
-
- if (idle_stable)
- PORTC |= LED_GREEN;
- else
- PORTC &= ~LED_GREEN;
-
-
- if (oldidle == 42) // init
- {
- oldidle = idle_stable;
- oldpulse = pulse_stable;
- }
-
- if (oldidle && !idle_stable)
- n_pulses = 0;
-
- if (!oldidle == 0 && idle_stable)
- {
- if (n_pulses > 17)
- jump_to_bootloader();
-
- // also check if some time has elapsed since last button press
- if (state == STATE_WAIT && button_release_counter == 255)
- {
- if (n_pulses >= 1 && n_pulses <=10)
- {
- state = STATE_SEND_KEY;
- key_to_send = n_pulses;
- }
- }
-
- button_release_counter = 0; // now button needs to be released a while until retrigger
-
- }
-
- if (!oldpulse && pulse_stable)
- n_pulses++;
-
- oldidle = idle_stable;
- oldpulse = pulse_stable;
-
-
- if (button_release_counter < 255)
- button_release_counter++; // increase release counter
-
-
-
- if (usbInterruptIsReady() && state != STATE_WAIT && LED_state != 0xff)
- {
- switch (state)
- {
- case STATE_SEND_KEY:
- buildReport(key_to_send);
- state = STATE_RELEASE_KEY; // release next
- PORTC &= ~LED_BLUE;
- break;
-
- case STATE_RELEASE_KEY:
- buildReport(-1);
- state = STATE_WAIT; // go back to waiting
- PORTC |= LED_BLUE;
- break;
-
- default:
- state = STATE_WAIT; // should not happen
- }
-
- // start sending
- usbSetInterrupt((void *) &keyboard_report, sizeof(keyboard_report));
- }
- }
-
- jump_to_bootloader();
- return 0;
-}