Subversion Repositories group.electronics

Rev

Rev 77 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
75 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[3];
31
		struct {
32
			int16_t axis0:16;
33
			int16_t axis1:16;
34
			int16_t axis2:16;
35
		};
76 pfowler 36
		uint8_t buttons;
37
		struct {
38
			int8_t b1:1;
39
			int8_t b2:2;
40
			int8_t reserved:6;
41
		};
75 pfowler 42
	};
43
} reportBuffer;
44
 
45
 
46
volatile struct {
47
        uint8_t current;
48
        uint8_t last;
49
        uint8_t mask;
50
} pcInt[1];
51
 
78 pfowler 52
volatile struct {
53
	uint8_t button;
54
	uint8_t timer;
55
} buttons;
56
 
57
 
75 pfowler 58
static uchar    idleRate;           /* in 4 ms units */
78 pfowler 59
volatile uint8_t tmr0_ovf = 0;
60
volatile uint32_t systime = 0;
75 pfowler 61
 
62
/* ------------------------------------------------------------------------- */
63
 
64
const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
65
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
66
    0x09, 0x05,                    // USAGE (Game Pad)
67
    0xa1, 0x01,                    // COLLECTION (Application)
68
    0x09, 0x01,                    //   USAGE (Pointer)
69
    0xa1, 0x00,                    //   COLLECTION (Physical)
70
    0x09, 0x30,                    //     USAGE (X)
71
    0x09, 0x31,                    //     USAGE (Y)
72
    0x09, 0x38,                    //     USAGE (Y)
73
    0x16, 0x00, 0x80,		   //	  Log Min -32768
74
    0x26, 0xff, 0x7f,		   //	  Log max 32768
75
    0x75, 0x10,                    //     REPORT_SIZE (16)
76
    0x95, 0x03,                    //     REPORT_COUNT (2)
77
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
77 pfowler 78
 
79
    0x05, 0x09,                    //     USAGE_PAGE (Button)
80
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
81
    0x29, 0x02,                    //     USAGE_MAXIMUM (Button 2)
82
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
83
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
84
    0x75, 0x01,                    //     REPORT_SIZE (1)
78 pfowler 85
    0x95, 0x08,                    //     REPORT_COUNT (2)
77 pfowler 86
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
87
 
75 pfowler 88
    0xc0,                          //   END_COLLECTION
89
    0xc0                           // END_COLLECTION
90
};
91
 
92
 
93
uchar	usbFunctionSetup(uchar data[8])
94
{
78 pfowler 95
    usbRequest_t    *rq = (void *)data;
75 pfowler 96
 
97
    //usbMsgPtr = reportBuffer;
98
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ 
99
        if(rq->bRequest == USBRQ_HID_GET_REPORT){ 
100
            return sizeof(reportBuffer);
101
        }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
102
            usbMsgPtr = &idleRate;
103
            return 1;
104
        }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
105
            idleRate = rq->wValue.bytes[1];
106
        }
107
    }else{
108
 
109
    }
110
	return 0;
111
}
112
 
113
 
78 pfowler 114
static void calibrateOscillator(void) {
115
    uchar step = 128;
116
    uchar trialValue = 0, optimumValue;
117
    int x, optimumDev;
118
    int targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
75 pfowler 119
 
120
    /* do a binary search: */
78 pfowler 121
    do {
75 pfowler 122
        OSCCAL = trialValue + step;
123
        x = usbMeasureFrameLength();    /* proportional to current real frequency */
124
        if(x < targetValue)             /* frequency still too low */
125
            trialValue += step;
126
        step >>= 1;
78 pfowler 127
    } while(step > 0);
75 pfowler 128
    /* We have a precision of +/- 1 for optimum OSCCAL here */
129
    /* now do a neighborhood search for optimum value */
130
    optimumValue = trialValue;
131
    optimumDev = x; /* this is certainly far away from optimum */
132
    for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
133
        x = usbMeasureFrameLength() - targetValue;
134
        if(x < 0)
135
            x = -x;
136
        if(x < optimumDev){
137
            optimumDev = x;
138
            optimumValue = OSCCAL;
139
        }
140
    }
141
    OSCCAL = optimumValue;
142
}
143
 
78 pfowler 144
void usbEventResetReady(void) {
75 pfowler 145
    cli();
146
    calibrateOscillator();
147
    sei();
148
    eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */
149
}
150
 
151
 
152
void usbSendHidReport(uchar * data, uchar len) {
78 pfowler 153
	usbSetInterrupt(data, len);
75 pfowler 154
}
155
 
156
 
78 pfowler 157
int main(void) {
75 pfowler 158
uchar   i;
159
uchar   calibrationValue;
160
 
161
    calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
162
    if(calibrationValue != 0xff){
163
        OSCCAL = calibrationValue;
164
    }
165
 
166
    odDebugInit();
167
    usbDeviceDisconnect();
168
    for(i=0;i<20;i++){  /* 300 ms disconnect */
169
        _delay_ms(15);
170
    }
171
 
172
    usbDeviceConnect();
173
    wdt_enable(WDTO_1S);
174
 
175
  PCMSK |= (( 1 << PCINT3 ) | ( 1 << PCINT4 )); //enable encoder pins interrupt sources
176
  GIMSK |= ( 1 << PCIE ); //enable pin change interupts
177
 
78 pfowler 178
        TIMSK = (1<<TOIE0);                    // Enable timer overflow
179
        TCNT0 = 0x00;                           // Set Timer0 initial value to 0
180
        TCCR0B = (1<< CS01) ;                   // /1 prescaler
181
 
75 pfowler 182
  DDRB          = 0B00000001;
183
  PORTB         = 0B00000000;
184
 
185
    usbInit();
186
    sei();
187
 
76 pfowler 188
    reportBuffer.axis0 = 0;
189
    reportBuffer.axis1 = 0;
190
    reportBuffer.axis2 = 0;
191
    reportBuffer.buttons = 0;
75 pfowler 192
 
193
    for(;;){    /* main event loop */
194
        wdt_reset();
195
        usbPoll();
196
 
78 pfowler 197
 
198
 
75 pfowler 199
        if(usbInterruptIsReady()){ 
78 pfowler 200
 
201
		// Check if our buttons need pressing
202
		reportBuffer.buttons = 0;
203
		if (buttons.timer != 0) {
204
			if (buttons.button == 1)
205
				reportBuffer.b1 = 1;
206
			else
207
				reportBuffer.b2 = 1;
208
		}
209
 
75 pfowler 210
		usbSendHidReport(&reportBuffer, sizeof(reportBuffer));
211
        }
212
    }
213
    return 0;
214
}
215
 
216
void pcInterrupt(uint8_t pcint) {
217
 
218
        switch (pcint) {
219
                case 0: pcInt[pcint].current = PINB; break;
220
        }
221
        pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;
222
        pcInt[pcint].last = pcInt[pcint].current;
223
 
224
        if (pcInt[pcint].mask == 0)
225
		return;
226
 
227
        // Check which pin caused the interrupt. If they both
228
        //  equal 0, the pin that interrupted is the direction
229
        if (rbi(pcInt[pcint].current, PCINT3) == 0
230
                && rbi(pcInt[pcint].current, PCINT4) == 0
231
                && rbi(pcInt[pcint].mask, PCINT4) ) {
76 pfowler 232
 
75 pfowler 233
                        if (reportBuffer.axis2 < 32500)
234
                                reportBuffer.axis2 += 200;
76 pfowler 235
 
78 pfowler 236
			buttons.button = 1;
237
			buttons.timer = 5;
76 pfowler 238
 
75 pfowler 239
        } else if (rbi(pcInt[pcint].current, PCINT3) == 0
240
                && rbi(pcInt[pcint].current, PCINT4) == 0
241
                && rbi(pcInt[pcint].mask, PCINT3) ) {
76 pfowler 242
 
75 pfowler 243
                        if (reportBuffer.axis2 > -32500)
244
                                reportBuffer.axis2 -= 200;
76 pfowler 245
 
78 pfowler 246
			buttons.button = 2;
247
			buttons.timer = 5;
75 pfowler 248
        }
249
 
250
        // Clear the mask so we know we've delth with it
251
        pcInt[pcint].mask = 0;
252
}
253
 
254
ISR(PCINT0_vect) {
255
        pcInterrupt(0);
256
}
78 pfowler 257
 
258
ISR(TIMER0_OVF_vect) {
259
        tmr0_ovf++;
260
        if (tmr0_ovf>=50) {
261
                systime++;
262
                tmr0_ovf = 0;
263
 
264
		if (buttons.timer != 0) 
265
			buttons.timer--;
266
        }
267
}