Subversion Repositories group.electronics

Rev

Rev 80 | Rev 84 | Go to most recent revision | Details | Compare with Previous | 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"
81 pfowler 19
//#include "oddebug.h"
79 pfowler 20
#include "config.h"
21
 
22
#ifndef NULL
23
#define NULL    ((void *)0)
24
#endif
25
 
26
/* ------------------------------------------------------------------------- */
27
 
28
struct {
29
	union {
81 pfowler 30
		int16_t axis[1];
79 pfowler 31
		struct {
32
			int16_t axis0:16;
81 pfowler 33
			//int16_t axis1:16;
79 pfowler 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
 
80 pfowler 169
  /*
170
  DDR : 1 = Output, 0 = Input
171
  PORT: 1 = Pullup for Input, otherwise set output
172
  PIN : Read input pin
173
  */
174
  /*
175
 
176
        PA0     - Output        - ButtonPad 1
177
        PA1     - Output        - ButtonPad 0
178
        PA2     - Output        - Reset
179
  */
180
  DDRD          = 0B00000000;
181
  PORTD         = 0B00000000;
182
  /*
183
        PB0     - Output                - LED 0
184
        PB1     - Output                - LED 1
185
        PB2     - Output                - LED 2
186
        PB3     - Output                - LED 3
187
        PB4     - Output                - LED 4
188
        PB5     - Output                - LED 5
189
        PB6     - Output                - LED 6
190
        PB7     - Output                - LED 7
191
  */
192
  DDRB          = 0B00000000;
193
  PORTB         = 0B00000000;
194
  /*
195
 
196
        PD0     - Output        - ButtonPad Gnd1
197
        PD1     - Output        - ButtonPad Gnd2
198
        PD2     - Output        - USB D+
199
        PD3     - Output        - USB D-
200
        PD4     - Output        - ButtonPad 2
201
        PD5     - Output        - ButtonPad 3
202
        PD6     - Output        - Select Switch
203
  */
204
  DDRD          = 0B01000000;
205
  PORTD         = 0B00000000;
206
 
207
 
81 pfowler 208
    //odDebugInit();
79 pfowler 209
    usbDeviceDisconnect();
210
    for(i=0;i<20;i++){  /* 300 ms disconnect */
211
        _delay_ms(15);
212
    }
213
 
214
    usbDeviceConnect();
215
    wdt_enable(WDTO_1S);
216
 
217
 
218
    TIMSK = (1<<TOIE0);                    // Enable timer overflow
219
    TCNT0 = 0x00;                           // Set Timer0 initial value to 0
220
    TCCR0B = (1<< CS01) ;                   // /1 prescaler
221
 
222
    usbInit();
223
    sei();
224
 
225
    reportBuffer.axis0 = 0;
81 pfowler 226
    //reportBuffer.axis1 = 0;
79 pfowler 227
    reportBuffer.buttons = 0;
228
 
80 pfowler 229
	PORTB = 0xaa;
230
 
79 pfowler 231
    for(;;){    /* main event loop */
232
        wdt_reset();
233
        usbPoll();
234
 
80 pfowler 235
 
236
 
79 pfowler 237
        if(usbInterruptIsReady()){ 
238
 
239
		// ReportBuffer logic here
240
 
241
		usbSendHidReport(&reportBuffer, sizeof(reportBuffer));
242
        }
243
    }
244
    return 0;
245
}
246
 
247
void pcInterrupt(uint8_t pcint) {
248
 
249
        switch (pcint) {
250
                case 0: pcInt[pcint].current = PINB; break;
251
        }
252
        pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;
253
        pcInt[pcint].last = pcInt[pcint].current;
254
 
255
        if (pcInt[pcint].mask == 0)
256
		return;
257
 
258
	// PCINT logic here
259
 
260
        // Clear the mask so we know we've delth with it
261
        pcInt[pcint].mask = 0;
262
}
263
 
80 pfowler 264
ISR(PCINT_vect) {
79 pfowler 265
        pcInterrupt(0);
266
}
267
 
268
ISR(TIMER0_OVF_vect) {
269
        tmr0_ovf++;
270
        if (tmr0_ovf>=50) {
271
                systime++;
272
                tmr0_ovf = 0;
273
        }
274
}