Subversion Repositories group.electronics

Rev

Rev 81 | Rev 85 | 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
 
84 pfowler 28
uint8_t getKey(void);
29
void doButtons(void);
30
 
79 pfowler 31
struct {
32
	union {
84 pfowler 33
		int16_t axis[2];
79 pfowler 34
		struct {
35
			int16_t axis0:16;
84 pfowler 36
			int16_t axis1:16;
79 pfowler 37
		};
38
		uint8_t buttons;
39
		struct {
40
			int8_t b1:1;
41
			int8_t b2:2;
42
			int8_t b3:3;
43
			int8_t b4:4;
44
			int8_t b5:5;
45
			int8_t b6:6;
46
			int8_t b7:7;
47
			int8_t b8:8;
48
		};
49
	};
50
} reportBuffer;
51
 
52
 
53
volatile struct {
84 pfowler 54
	uint8_t buttons;
55
	uint8_t waitup;
79 pfowler 56
	uint8_t timer;
84 pfowler 57
} debounce;
79 pfowler 58
 
84 pfowler 59
uint8_t currleds = 128;
79 pfowler 60
static uchar    idleRate;           /* in 4 ms units */
61
volatile uint8_t tmr0_ovf = 0;
62
volatile uint32_t systime = 0;
63
 
64
/* ------------------------------------------------------------------------- */
65
 
66
const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
67
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
68
    0x09, 0x05,                    // USAGE (Game Pad)
69
    0xa1, 0x01,                    // COLLECTION (Application)
70
    0x09, 0x01,                    //   USAGE (Pointer)
71
    0xa1, 0x00,                    //   COLLECTION (Physical)
72
    0x09, 0x30,                    //     USAGE (X)
73
    0x09, 0x31,                    //     USAGE (Y)
74
    0x16, 0x00, 0x80,		   //	  Log Min -32768
75
    0x26, 0xff, 0x7f,		   //	  Log max 32768
76
    0x75, 0x10,                    //     REPORT_SIZE (16)
77
    0x95, 0x02,                    //     REPORT_COUNT (2)
78
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
79
 
80
    0x05, 0x09,                    //     USAGE_PAGE (Button)
81
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
84 pfowler 82
    0x29, 0x08,                    //     USAGE_MAXIMUM (Button 8)
79 pfowler 83
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
84
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
85
    0x75, 0x01,                    //     REPORT_SIZE (1)
86
    0x95, 0x08,                    //     REPORT_COUNT (2)
87
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
88
 
89
    0xc0,                          //   END_COLLECTION
90
    0xc0                           // END_COLLECTION
91
};
92
 
93
 
94
uchar	usbFunctionSetup(uchar data[8])
95
{
96
    usbRequest_t    *rq = (void *)data;
97
 
98
    //usbMsgPtr = reportBuffer;
99
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ 
100
        if(rq->bRequest == USBRQ_HID_GET_REPORT){ 
101
            return sizeof(reportBuffer);
102
        }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
103
            usbMsgPtr = &idleRate;
104
            return 1;
105
        }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
106
            idleRate = rq->wValue.bytes[1];
107
        }
108
    }else{
109
 
110
    }
111
	return 0;
112
}
113
 
114
 
115
static void calibrateOscillator(void) {
116
    uchar step = 128;
117
    uchar trialValue = 0, optimumValue;
118
    int x, optimumDev;
119
    int targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
120
 
121
    /* do a binary search: */
122
    do {
123
        OSCCAL = trialValue + step;
124
        x = usbMeasureFrameLength();    /* proportional to current real frequency */
125
        if(x < targetValue)             /* frequency still too low */
126
            trialValue += step;
127
        step >>= 1;
128
    } while(step > 0);
129
    /* We have a precision of +/- 1 for optimum OSCCAL here */
130
    /* now do a neighborhood search for optimum value */
131
    optimumValue = trialValue;
132
    optimumDev = x; /* this is certainly far away from optimum */
133
    for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
134
        x = usbMeasureFrameLength() - targetValue;
135
        if(x < 0)
136
            x = -x;
137
        if(x < optimumDev){
138
            optimumDev = x;
139
            optimumValue = OSCCAL;
140
        }
141
    }
142
    OSCCAL = optimumValue;
143
}
144
 
145
void usbEventResetReady(void) {
146
    cli();
147
    calibrateOscillator();
148
    sei();
149
    eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */
150
}
151
 
152
 
153
void usbSendHidReport(uchar * data, uchar len) {
154
	usbSetInterrupt(data, len);
155
}
156
 
157
 
158
int main(void) {
159
uchar   i;
160
uchar   calibrationValue;
161
 
162
    calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
163
    if(calibrationValue != 0xff){
164
        OSCCAL = calibrationValue;
165
    }
166
 
80 pfowler 167
  /*
168
  DDR : 1 = Output, 0 = Input
169
  PORT: 1 = Pullup for Input, otherwise set output
170
  PIN : Read input pin
171
  */
172
  /*
173
 
84 pfowler 174
        PA0     - Input, Pullup - ButtonPad 1
175
        PA1     - Input, Pullup - ButtonPad 0
80 pfowler 176
        PA2     - Output        - Reset
177
  */
178
  DDRD          = 0B00000000;
84 pfowler 179
  PORTD         = 0B00000011;
80 pfowler 180
  /*
181
        PB0     - Output                - LED 0
182
        PB1     - Output                - LED 1
183
        PB2     - Output                - LED 2
184
        PB3     - Output                - LED 3
185
        PB4     - Output                - LED 4
186
        PB5     - Output                - LED 5
187
        PB6     - Output                - LED 6
188
        PB7     - Output                - LED 7
189
  */
84 pfowler 190
  DDRB          = 0B11111111;
80 pfowler 191
  PORTB         = 0B00000000;
192
  /*
193
 
194
        PD0     - Output        - ButtonPad Gnd1
195
        PD1     - Output        - ButtonPad Gnd2
196
        PD2     - Output        - USB D+
197
        PD3     - Output        - USB D-
84 pfowler 198
        PD4     - Input, Pullup - ButtonPad 2
199
        PD5     - Input, Pullup - ButtonPad 3
200
        PD6     - Input, Pullup - Select Switch
80 pfowler 201
  */
84 pfowler 202
  DDRD          = 0B00000011;
203
  PORTD         = 0B01110011;
80 pfowler 204
 
84 pfowler 205
	PORTB = 255;
206
	_delay_ms(20);
207
	PORTB = currleds;
80 pfowler 208
 
81 pfowler 209
    //odDebugInit();
79 pfowler 210
    usbDeviceDisconnect();
211
    for(i=0;i<20;i++){  /* 300 ms disconnect */
212
        _delay_ms(15);
213
    }
214
 
215
    usbDeviceConnect();
216
    wdt_enable(WDTO_1S);
217
 
218
 
219
    TIMSK = (1<<TOIE0);                    // Enable timer overflow
220
    TCNT0 = 0x00;                           // Set Timer0 initial value to 0
221
    TCCR0B = (1<< CS01) ;                   // /1 prescaler
222
 
223
    usbInit();
224
    sei();
225
 
226
    reportBuffer.axis0 = 0;
84 pfowler 227
    reportBuffer.axis1 = 0;
79 pfowler 228
    reportBuffer.buttons = 0;
229
 
80 pfowler 230
 
79 pfowler 231
    for(;;){    /* main event loop */
232
        wdt_reset();
233
        usbPoll();
234
 
84 pfowler 235
	doButtons();	
80 pfowler 236
 
79 pfowler 237
        if(usbInterruptIsReady()){ 
238
 
239
		usbSendHidReport(&reportBuffer, sizeof(reportBuffer));
240
        }
84 pfowler 241
 
242
	_delay_ms(1);
79 pfowler 243
    }
244
    return 0;
245
}
246
 
84 pfowler 247
void doButtons() {
248
        uint8_t pressed = getKey();
79 pfowler 249
 
84 pfowler 250
        // Deboucing
251
        // When i key first goes down, wait 5 ms, check it again to see if its still down
252
        if (pressed && debounce.buttons == 0 && debounce.timer == 0) {
253
                debounce.buttons = pressed;
254
                debounce.timer = 5;
79 pfowler 255
        }
256
 
84 pfowler 257
        // The key has come up
258
        if (pressed != debounce.buttons) {
259
                debounce.buttons = 0;
260
                debounce.timer = 0;
261
                debounce.waitup = 0;
262
        }
79 pfowler 263
 
84 pfowler 264
        // Debounce timer is up, process our button
265
        if (debounce.buttons && debounce.timer == 0 && debounce.waitup != 1) {
266
                uint8_t i = 0;
267
                for (i=0; i<=7; i++) {
268
                        // Button pressed and the led is currently on
269
                        if ( rbi(debounce.buttons, i) == 1 && rbi(currleds, i) == 1 ) {
270
                                if ( i == 6 && rbi(currleds, 7) != 1)  //Dont turn off com1 if no comm2
271
                                        break;
79 pfowler 272
 
84 pfowler 273
                                if ( i == 7 && rbi(currleds, 6) != 1)  //Dont turn off com2 if no comm1
274
                                        break;
275
 
276
                                cbi(currleds, i);
277
                        // Button is pressed and led is currently off
278
                         } else if ( rbi(debounce.buttons, i) == 1 && rbi(currleds, i) == 0 ) {
279
                                if ( i == 6 && rbi(currleds, 7) == 1)  //Turn on comm2, turn off comm1
280
                                        cbi(currleds,7);
281
 
282
                                if ( i == 7 && rbi(currleds, 6) == 1)  //Turn on comm1, turn off comm2
283
                                        cbi(currleds,6);
284
 
285
                                sbi(currleds, i);
286
                        }
287
                }
288
                PORTB = currleds;
289
                reportBuffer.buttons = debounce.buttons;
290
                // Set debounce to wait to button up
291
                debounce.waitup = 1;
292
        }
79 pfowler 293
}
294
 
84 pfowler 295
// Gnd = PD0, PD1
296
// Btn = PA1, PA0, PD4, PD5
297
uint8_t getKey() {
298
        uint8_t key = 0;
299
 
300
        cbi(PORTD, 0);
301
        _delay_us(10);        // Wait for the port change
302
        if (rbi(PIND, 5) == 0) key = 1;
303
        if (rbi(PIND, 4) == 0) key = 2;
304
        if (rbi(PINA, 0) == 0) key = 4;
305
        if (rbi(PINA, 1) == 0) key = 8;
306
        sbi(PORTD, 0);
307
 
308
        cbi(PORTD, 1);
309
        _delay_us(10);
310
        if (rbi(PIND, 5) == 0) key = 16;
311
        if (rbi(PIND, 4) == 0) key = 32;
312
        if (rbi(PINA, 0) == 0) key = 64;
313
        if (rbi(PINA, 1) == 0) key = 128;
314
        sbi(PORTD, 1);
315
 
316
        return key;
79 pfowler 317
}
318
 
84 pfowler 319
 
79 pfowler 320
ISR(TIMER0_OVF_vect) {
321
        tmr0_ovf++;
84 pfowler 322
 
323
	//16.5Mhz, 1ms = 50ovf
324
 
79 pfowler 325
        if (tmr0_ovf>=50) {
326
                systime++;
327
                tmr0_ovf = 0;
84 pfowler 328
 
329
		if (debounce.timer != 0)
330
			debounce.timer--;
79 pfowler 331
        }
332
}