stoper/firmware/main.c

311 lines
9.4 KiB
C
Executable File

/* Name: main.c
* Project: hid-mouse, a very simple HID example
* Author: Christian Starkjohann
* Creation Date: 2008-04-07
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: main.c 692 2008-11-07 15:07:40Z cs $
*/
/*
This example should run on most AVRs with only little changes. No special
hardware resources except INT0 are used. You may have to change usbconfig.h for
different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
at least be connected to INT0 as well.
We use VID/PID 0x046D/0xC00E which is taken from a Logitech mouse. Don't
publish any hardware using these IDs! This is for demonstration only!
*/
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h> /* for sei() */
#include <util/delay.h> /* for _delay_ms() */
#include <avr/pgmspace.h> /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug macros */
/* 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_RETURN 40
#define KEY_UP 82
#define KEY_DOWN 81
#define KEY_LEFT 80
#define KEY_RIGHT 79
/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */
PROGMEM char usbHidReportDescriptor[63] = {
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)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
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)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
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)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define SENDBUFFER_SIZE 128
char g_SendBuffer[SENDBUFFER_SIZE];
char *g_SendBufferWritePointer = g_SendBuffer;
char *g_SendBufferReadPointer = g_SendBuffer;
void SendBufferWrite(char Character)
{
*g_SendBufferWritePointer = Character;
g_SendBufferWritePointer++;
if (g_SendBufferWritePointer - g_SendBuffer >= SENDBUFFER_SIZE)
g_SendBufferWritePointer = g_SendBuffer;
}
char SendBufferRead(void)
{
if (g_SendBufferWritePointer == g_SendBufferReadPointer)
return 0;
char Character = *g_SendBufferReadPointer;
g_SendBufferReadPointer++;
if (g_SendBufferReadPointer - g_SendBuffer >= SENDBUFFER_SIZE)
g_SendBufferReadPointer = g_SendBuffer;
return Character;
}
void SendString(char *String)
{
while (*String != 0)
{
char Character = *String;
String++;
SendBufferWrite(Character);
}
}
typedef struct{
uchar buttonMask;
uchar reserved;
uchar buttons[6];
}report_t;
static report_t reportBuffer;
static uchar idleRate; /* repeat rate for keyboards, never used for mice */
char g_ShouldKeyUp = 0;
static void SendKeys(void)
{
reportBuffer.buttonMask=0;
reportBuffer.reserved=0;
reportBuffer.buttons[0]=0;
reportBuffer.buttons[1]=0;
reportBuffer.buttons[2]=0;
reportBuffer.buttons[3]=0;
reportBuffer.buttons[4]=0;
reportBuffer.buttons[5]=0;
if (g_ShouldKeyUp)
{
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
g_ShouldKeyUp = 0;
return;
}
g_ShouldKeyUp = 1;
char Character = SendBufferRead();
if (!Character)
{
g_ShouldKeyUp = 0;
return;
}
if ('a' <= Character && Character <= 'z')
{
reportBuffer.buttons[0] = Character - 'a' + KEY_A;
}
else if ('A' <= Character && Character <= 'Z')
{
reportBuffer.buttons[0] = Character - 'A' + KEY_A;
// reportBuffer.buttonMask = MOD_SHIFT_LEFT;
}
else if ('1' <= Character && Character <= '9')
{
reportBuffer.buttons[0] = Character - '1' + KEY_1;
}
else if (Character == '0')
{
reportBuffer.buttons[0] = KEY_0;
}
else if (Character == ' ')
{
reportBuffer.buttons[0] = 44;
}
else if (Character == '.')
{
reportBuffer.buttons[0] = 55;
}
else
{
g_ShouldKeyUp = 0;
return;
}
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
}
/* ------------------------------------------------------------------------- */
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
DBG1(0x50, &rq->bRequest, 1); /* debug output: print our request */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
usbMsgPtr = (void *)&reportBuffer;
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; /* default for not implemented requests: return no data back to host */
}
int main(void)
{
uint16_t i;
SendString("this is some pretty awesome stuff");
wdt_enable(WDTO_1S);
/* Even if you don't use the watchdog, turn it off here. On newer devices,
* the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
*/
DBG1(0x00, 0, 0); /* debug output: main starts */
/* RESET status: all port bits are inputs without pull-up.
* That's the way we need D+ and D-. Therefore we don't need any
* additional hardware initialization.
*/
odDebugInit();
usbInit();
usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
i = 0b11111111111;
while(--i){ /* fake USB disconnect for > 250 ms */
wdt_reset();
_delay_ms(1);
}
usbDeviceConnect();
sei();
DBG1(0x01, 0, 0); /* debug output: main loop starts */
for(;;){ /* main event loop */
DBG1(0x02, 0, 0); /* debug output: main loop iterates */
wdt_reset();
usbPoll();
if(usbInterruptIsReady()){
/* called after every poll of the interrupt endpoint */
SendKeys();
}
}
return 0;
}
/* ------------------------------------------------------------------------- */