Subversion Repositories group.electronics

Rev

Rev 91 | Rev 93 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
79 pfowler 1
#include <avr/io.h>
2
#include <avr/wdt.h>
3
#include <avr/interrupt.h>
4
#include <avr/pgmspace.h>
5
#include <util/delay.h>
6
 
7
#include "usbdrv.h"
8
#include "config.h"
9
 
10
#ifndef NULL
11
#define NULL    ((void *)0)
12
#endif
13
 
88 pfowler 14
#define USB_GET_LED_STATE  100
15
#define USB_SET_LED_STATE  101
16
 
79 pfowler 17
/* ------------------------------------------------------------------------- */
18
 
84 pfowler 19
uint8_t getKey(void);
86 pfowler 20
void doButtons(uint8_t);
85 pfowler 21
inline void setLeds(uint8_t);
84 pfowler 22
 
79 pfowler 23
struct {
86 pfowler 24
	int16_t axis[2];
25
	uint8_t buttons;
79 pfowler 26
} reportBuffer;
27
 
28
 
29
volatile struct {
84 pfowler 30
	uint8_t buttons;
31
	uint8_t waitup;
79 pfowler 32
	uint8_t timer;
84 pfowler 33
} debounce;
79 pfowler 34
 
92 pfowler 35
volatile struct {
36
	uint8_t data;
37
	union {
38
		uint8_t led_method:1;
39
		uint8_t other:1;
40
		uint8_t reserved:6;
41
	};
42
} config;
43
 
86 pfowler 44
uint8_t currleds = 1;
79 pfowler 45
static uchar    idleRate;           /* in 4 ms units */
46
volatile uint8_t tmr0_ovf = 0;
47
volatile uint32_t systime = 0;
48
 
49
/* ------------------------------------------------------------------------- */
50
 
51
const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
52
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
53
    0x09, 0x05,                    // USAGE (Game Pad)
54
    0xa1, 0x01,                    // COLLECTION (Application)
55
    0x09, 0x01,                    //   USAGE (Pointer)
56
    0xa1, 0x00,                    //   COLLECTION (Physical)
57
    0x09, 0x30,                    //     USAGE (X)
58
    0x09, 0x31,                    //     USAGE (Y)
59
    0x16, 0x00, 0x80,		   //	  Log Min -32768
60
    0x26, 0xff, 0x7f,		   //	  Log max 32768
61
    0x75, 0x10,                    //     REPORT_SIZE (16)
62
    0x95, 0x02,                    //     REPORT_COUNT (2)
63
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
64
 
65
    0x05, 0x09,                    //     USAGE_PAGE (Button)
66
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
84 pfowler 67
    0x29, 0x08,                    //     USAGE_MAXIMUM (Button 8)
79 pfowler 68
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
69
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
70
    0x75, 0x01,                    //     REPORT_SIZE (1)
71
    0x95, 0x08,                    //     REPORT_COUNT (2)
72
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
73
 
74
    0xc0,                          //   END_COLLECTION
75
    0xc0                           // END_COLLECTION
76
};
77
 
86 pfowler 78
void hadUsbReset(void) {
85 pfowler 79
}
80
 
81
 
79 pfowler 82
uchar	usbFunctionSetup(uchar data[8])
83
{
84
    usbRequest_t    *rq = (void *)data;
85
 
88 pfowler 86
    //if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ 
87
        switch (rq->bRequest ) {
89 pfowler 88
		case USBRQ_HID_GET_REPORT:
89
			return sizeof(reportBuffer);
90
		case USBRQ_HID_GET_IDLE:
91
			usbMsgPtr = &idleRate;
92
			return 1;
93
		case USBRQ_HID_SET_IDLE:
94
			idleRate = rq->wValue.bytes[1];
95
			return 0;
96
		case USB_GET_LED_STATE: // send data to PC
97
			usbMsgPtr = currleds;
98
			return sizeof(currleds);
99
		case USB_SET_LED_STATE: // modify reply buffer
91 pfowler 100
			currleds = rq->wValue.bytes[0];
89 pfowler 101
			return 0;
79 pfowler 102
        }
91 pfowler 103
    //}
79 pfowler 104
 
105
	return 0;
106
}
107
 
108
 
109
void usbSendHidReport(uchar * data, uchar len) {
110
	usbSetInterrupt(data, len);
111
}
112
 
113
int main(void) {
114
 
86 pfowler 115
	DIDR0 = 0x00;
116
 
80 pfowler 117
  /*
118
  DDR : 1 = Output, 0 = Input
119
  PORT: 1 = Pullup for Input, otherwise set output
120
  PIN : Read input pin
121
  */
122
 
123
  /*
85 pfowler 124
        PB0     - Output                - LED 3
125
        PB1     - Output                - LED 4
126
        PB2     - Output                - LED 5
127
        PB3     - Output                - LED 6
128
        PB4     - Output                - LED 7
129
        PB5     - 
130
        PB6     - 
131
        PB7     - 
80 pfowler 132
  */
85 pfowler 133
  DDRB          = 0B00011111;
80 pfowler 134
  PORTB         = 0B00000000;
85 pfowler 135
 
80 pfowler 136
  /*
85 pfowler 137
        PC0     - Output		- ButtonPad Gnd0
138
        PC1     - Output		- ButtonPad Gnd1
139
        PC2     - Input, Pullup		- ButtonPad 0
140
        PC3     - Input, Pullup		- ButtonPad 1
141
        PC4     - Input, Pullup		- ButtonPad 2
142
        PC5     - Input, Pullup		- ButtonPad 3
80 pfowler 143
  */
86 pfowler 144
  DDRC          = 0B00000011;
145
  PORTC         = 0B00111111;
80 pfowler 146
 
85 pfowler 147
  /*
148
        PD0     - 
149
        PD1     - 
150
        PD2     - 
151
        PD3     - 
152
        PD4     - 
153
        PD5     - Output		- LED 0
154
        PD6     - Output		- LED 1
155
        PD7     - Output		- LED 2
156
  */
157
  DDRD          = 0B11100000;
158
  PORTD         = 0B00000000;
159
 
86 pfowler 160
	setLeds(0xff);
80 pfowler 161
 
79 pfowler 162
    usbDeviceDisconnect();
86 pfowler 163
    _delay_ms(500);
79 pfowler 164
    usbDeviceConnect();
165
 
166
 
85 pfowler 167
    TIMSK0 = (1<<TOIE0);                    // Enable timer overflow
79 pfowler 168
    TCNT0 = 0x00;                           // Set Timer0 initial value to 0
85 pfowler 169
    TCCR0B = (1<< CS00) ;                   // /1 prescaler
79 pfowler 170
 
86 pfowler 171
    wdt_enable(WDTO_1S);
79 pfowler 172
    usbInit();
173
    sei();
174
 
86 pfowler 175
    reportBuffer.axis[0] = 0xfffd;
176
    reportBuffer.axis[1] = 0xfffd;
177
    reportBuffer.buttons = 0x00;
79 pfowler 178
 
92 pfowler 179
	config.led_method = 1;
86 pfowler 180
	setLeds(currleds);
80 pfowler 181
 
92 pfowler 182
 
86 pfowler 183
    for(;;){
79 pfowler 184
        wdt_reset();
185
        usbPoll();
186
 
86 pfowler 187
	uint8_t pressed = getKey();
92 pfowler 188
 
189
	if (config.led_method != rbi(PORTB, 5)) {
190
		config.led_method = rbi(PORTB, 5);
191
	}
192
 
193
	if (config.led_method == 1)
194
		doButtons(pressed);
195
 
90 pfowler 196
	setLeds(currleds);
80 pfowler 197
 
79 pfowler 198
        if(usbInterruptIsReady()){ 
86 pfowler 199
                reportBuffer.buttons = pressed;
79 pfowler 200
		usbSendHidReport(&reportBuffer, sizeof(reportBuffer));
201
        }
84 pfowler 202
 
79 pfowler 203
    }
86 pfowler 204
 
79 pfowler 205
    return 0;
206
}
207
 
85 pfowler 208
inline void setLeds(uint8_t leds) {
86 pfowler 209
	PORTB &= 0xE0;
85 pfowler 210
        PORTB |= (0x1F & (leds >> 3));
86 pfowler 211
	PORTD &= 0x1F;
85 pfowler 212
        PORTD |= (0xE0 & (leds << 5));
213
}
214
 
86 pfowler 215
void doButtons(uint8_t pressed) {
79 pfowler 216
 
84 pfowler 217
        // Deboucing
218
        // When i key first goes down, wait 5 ms, check it again to see if its still down
219
        if (pressed && debounce.buttons == 0 && debounce.timer == 0) {
220
                debounce.buttons = pressed;
221
                debounce.timer = 5;
79 pfowler 222
        }
223
 
84 pfowler 224
        // The key has come up
225
        if (pressed != debounce.buttons) {
226
                debounce.buttons = 0;
227
                debounce.timer = 0;
228
                debounce.waitup = 0;
229
        }
79 pfowler 230
 
84 pfowler 231
        // Debounce timer is up, process our button
232
        if (debounce.buttons && debounce.timer == 0 && debounce.waitup != 1) {
233
                uint8_t i = 0;
234
                for (i=0; i<=7; i++) {
235
                        // Button pressed and the led is currently on
236
                        if ( rbi(debounce.buttons, i) == 1 && rbi(currleds, i) == 1 ) {
86 pfowler 237
                                if ( i == 0 && rbi(currleds, 1) != 1)  //Dont turn off com1 if no comm2
84 pfowler 238
                                        break;
79 pfowler 239
 
86 pfowler 240
                                if ( i == 1 && rbi(currleds, 0) != 1)  //Dont turn off com2 if no comm1
84 pfowler 241
                                        break;
242
 
243
                                cbi(currleds, i);
244
                        // Button is pressed and led is currently off
245
                         } else if ( rbi(debounce.buttons, i) == 1 && rbi(currleds, i) == 0 ) {
86 pfowler 246
                                if ( i == 0 && rbi(currleds, 1) == 1)  //Turn on comm2, turn off comm1
247
                                        cbi(currleds,1);
84 pfowler 248
 
86 pfowler 249
                                if ( i == 1 && rbi(currleds, 0) == 1)  //Turn on comm1, turn off comm2
250
                                        cbi(currleds,0);
84 pfowler 251
 
252
                                sbi(currleds, i);
253
                        }
254
                }
92 pfowler 255
                //setLeds(currleds);
84 pfowler 256
                debounce.waitup = 1;
257
        }
79 pfowler 258
}
259
 
85 pfowler 260
// Gnd = PC0, PC1
261
// Btn = PC2, PC3, PC4, PC5
84 pfowler 262
uint8_t getKey() {
263
        uint8_t key = 0;
264
 
86 pfowler 265
        cbi(PORTC, 1);
84 pfowler 266
        _delay_us(10);        // Wait for the port change
85 pfowler 267
        if (rbi(PINC, 2) == 0) key = 1;
268
        if (rbi(PINC, 3) == 0) key = 2;
269
        if (rbi(PINC, 4) == 0) key = 4;
270
        if (rbi(PINC, 5) == 0) key = 8;
86 pfowler 271
        sbi(PORTC, 1);
84 pfowler 272
 
86 pfowler 273
        cbi(PORTC, 0);
84 pfowler 274
        _delay_us(10);
85 pfowler 275
        if (rbi(PINC, 2) == 0) key = 16;
276
        if (rbi(PINC, 3) == 0) key = 32;
277
        if (rbi(PINC, 4) == 0) key = 64;
278
        if (rbi(PINC, 5) == 0) key = 128;
86 pfowler 279
        sbi(PORTC, 0);
84 pfowler 280
 
281
        return key;
79 pfowler 282
}
283
 
84 pfowler 284
 
79 pfowler 285
ISR(TIMER0_OVF_vect) {
286
        tmr0_ovf++;
84 pfowler 287
 
87 pfowler 288
	// Clk/1 TCCR0B = (1<< CS00);
289
	//20.0Mhz, 1ms = 78ovf
290
	//16.5Mhz, 1ms = 64ovf
85 pfowler 291
	//12.0Mhz, 1ms = 46ovf
84 pfowler 292
 
87 pfowler 293
        if (tmr0_ovf>=78) {
79 pfowler 294
                systime++;
295
                tmr0_ovf = 0;
84 pfowler 296
 
297
		if (debounce.timer != 0)
298
			debounce.timer--;
92 pfowler 299
 
79 pfowler 300
        }
301
}