Subversion Repositories group.electronics

Rev

Rev 80 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
79 pfowler 1
/* Name: main.c
2
 * Project: EasyLogger
3
 * Author: Christian Starkjohann
4
 * Creation Date: 2006-04-23
5
 * Tabsize: 4
6
 * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
7
 * License: Proprietary, free under certain conditions. See Documentation.
8
 * This Revision: $Id$
9
 */
10
 
11
#include <avr/io.h>
12
#include <avr/wdt.h>
13
#include <avr/eeprom.h>
14
#include <avr/interrupt.h>
15
#include <avr/pgmspace.h>
16
#include <util/delay.h>
17
 
18
#include "usbdrv.h"
19
#include "oddebug.h"
20
#include "config.h"
21
 
22
#ifndef NULL
23
#define NULL    ((void *)0)
24
#endif
25
 
26
/* ------------------------------------------------------------------------- */
27
 
28
struct {
29
	union {
30
		int16_t axis[2];
31
		struct {
32
			int16_t axis0:16;
33
			int16_t axis1:16;
34
		};
35
		uint8_t buttons;
36
		struct {
37
			int8_t b1:1;
38
			int8_t b2:2;
39
			int8_t b3:3;
40
			int8_t b4:4;
41
			int8_t b5:5;
42
			int8_t b6:6;
43
			int8_t b7:7;
44
			int8_t b8:8;
45
		};
46
	};
47
} reportBuffer;
48
 
49
 
50
volatile struct {
51
        uint8_t current;
52
        uint8_t last;
53
        uint8_t mask;
54
} pcInt[1];
55
 
56
volatile struct {
57
	uint8_t button;
58
	uint8_t timer;
59
} buttons;
60
 
61
 
62
static uchar    idleRate;           /* in 4 ms units */
63
volatile uint8_t tmr0_ovf = 0;
64
volatile uint32_t systime = 0;
65
 
66
/* ------------------------------------------------------------------------- */
67
 
68
const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
69
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
70
    0x09, 0x05,                    // USAGE (Game Pad)
71
    0xa1, 0x01,                    // COLLECTION (Application)
72
    0x09, 0x01,                    //   USAGE (Pointer)
73
    0xa1, 0x00,                    //   COLLECTION (Physical)
74
    0x09, 0x30,                    //     USAGE (X)
75
    0x09, 0x31,                    //     USAGE (Y)
76
    0x16, 0x00, 0x80,		   //	  Log Min -32768
77
    0x26, 0xff, 0x7f,		   //	  Log max 32768
78
    0x75, 0x10,                    //     REPORT_SIZE (16)
79
    0x95, 0x02,                    //     REPORT_COUNT (2)
80
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
81
 
82
    0x05, 0x09,                    //     USAGE_PAGE (Button)
83
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
84
    0x29, 0x08,                    //     USAGE_MAXIMUM (Button 2)
85
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
86
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
87
    0x75, 0x01,                    //     REPORT_SIZE (1)
88
    0x95, 0x08,                    //     REPORT_COUNT (2)
89
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
90
 
91
    0xc0,                          //   END_COLLECTION
92
    0xc0                           // END_COLLECTION
93
};
94
 
95
 
96
uchar	usbFunctionSetup(uchar data[8])
97
{
98
    usbRequest_t    *rq = (void *)data;
99
 
100
    //usbMsgPtr = reportBuffer;
101
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ 
102
        if(rq->bRequest == USBRQ_HID_GET_REPORT){ 
103
            return sizeof(reportBuffer);
104
        }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
105
            usbMsgPtr = &idleRate;
106
            return 1;
107
        }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
108
            idleRate = rq->wValue.bytes[1];
109
        }
110
    }else{
111
 
112
    }
113
	return 0;
114
}
115
 
116
 
117
static void calibrateOscillator(void) {
118
    uchar step = 128;
119
    uchar trialValue = 0, optimumValue;
120
    int x, optimumDev;
121
    int targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
122
 
123
    /* do a binary search: */
124
    do {
125
        OSCCAL = trialValue + step;
126
        x = usbMeasureFrameLength();    /* proportional to current real frequency */
127
        if(x < targetValue)             /* frequency still too low */
128
            trialValue += step;
129
        step >>= 1;
130
    } while(step > 0);
131
    /* We have a precision of +/- 1 for optimum OSCCAL here */
132
    /* now do a neighborhood search for optimum value */
133
    optimumValue = trialValue;
134
    optimumDev = x; /* this is certainly far away from optimum */
135
    for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
136
        x = usbMeasureFrameLength() - targetValue;
137
        if(x < 0)
138
            x = -x;
139
        if(x < optimumDev){
140
            optimumDev = x;
141
            optimumValue = OSCCAL;
142
        }
143
    }
144
    OSCCAL = optimumValue;
145
}
146
 
147
void usbEventResetReady(void) {
148
    cli();
149
    calibrateOscillator();
150
    sei();
151
    eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */
152
}
153
 
154
 
155
void usbSendHidReport(uchar * data, uchar len) {
156
	usbSetInterrupt(data, len);
157
}
158
 
159
 
160
int main(void) {
161
uchar   i;
162
uchar   calibrationValue;
163
 
164
    calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
165
    if(calibrationValue != 0xff){
166
        OSCCAL = calibrationValue;
167
    }
168
 
169
    odDebugInit();
170
    usbDeviceDisconnect();
171
    for(i=0;i<20;i++){  /* 300 ms disconnect */
172
        _delay_ms(15);
173
    }
174
 
175
    usbDeviceConnect();
176
    wdt_enable(WDTO_1S);
177
 
178
 
179
    TIMSK = (1<<TOIE0);                    // Enable timer overflow
180
    TCNT0 = 0x00;                           // Set Timer0 initial value to 0
181
    TCCR0B = (1<< CS01) ;                   // /1 prescaler
182
 
183
    DDRB          = 0B00000001;
184
    PORTB         = 0B00000000;
185
 
186
    usbInit();
187
    sei();
188
 
189
    reportBuffer.axis0 = 0;
190
    reportBuffer.axis1 = 0;
191
    reportBuffer.buttons = 0;
192
 
193
    for(;;){    /* main event loop */
194
        wdt_reset();
195
        usbPoll();
196
 
197
        if(usbInterruptIsReady()){ 
198
 
199
		// ReportBuffer logic here
200
 
201
		usbSendHidReport(&reportBuffer, sizeof(reportBuffer));
202
        }
203
    }
204
    return 0;
205
}
206
 
207
void pcInterrupt(uint8_t pcint) {
208
 
209
        switch (pcint) {
210
                case 0: pcInt[pcint].current = PINB; break;
211
        }
212
        pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;
213
        pcInt[pcint].last = pcInt[pcint].current;
214
 
215
        if (pcInt[pcint].mask == 0)
216
		return;
217
 
218
	// PCINT logic here
219
 
220
        // Clear the mask so we know we've delth with it
221
        pcInt[pcint].mask = 0;
222
}
223
 
224
ISR(PCINT0_vect) {
225
        pcInterrupt(0);
226
}
227
 
228
ISR(TIMER0_OVF_vect) {
229
        tmr0_ovf++;
230
        if (tmr0_ovf>=50) {
231
                systime++;
232
                tmr0_ovf = 0;
233
        }
234
}