Subversion Repositories group.electronics

Rev

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

Rev Author Line No. Line
21 pfowler 1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
#include <avr/interrupt.h>
4
 
5
#define F_CPU 12000000
6
#include <util/delay.h>
7
#include <avr/wdt.h>
8
#include <usbdrv.h>
9
 
10
#include <stdlib.h>
11
#include <string.h>
12
 
13
#include "config.h"
14
#include "hiddesc.h"
15
 
16
 
17
void doInt(void);
24 pfowler 18
uint8_t getKey(void);
21 pfowler 19
 
20
volatile uint8_t pcIntCurr = 0;
21
volatile uint8_t pcIntLast = 0;
22
volatile uint8_t pcIntMask = 0;
23
 
22 pfowler 24
volatile uint8_t rot_stat = 0;
23 pfowler 25
volatile uint8_t rot_sent = 0;
21 pfowler 26
 
27
struct{
24 pfowler 28
  int data1;	// X axis
29
  int data2;	// Y axis
21 pfowler 30
  union {
24 pfowler 31
    uint8_t data3;	// Rotaries
21 pfowler 32
    struct {
24 pfowler 33
	uint8_t rot1a:1;
34
	uint8_t rot1b:1;
35
	uint8_t rot2a:1;
36
	uint8_t rot2b:1;
21 pfowler 37
    };
38
  };
24 pfowler 39
  union {
40
    uint16_t data4;	// 16 buttons
41
    struct {
42
      uint8_t b00:1;
43
      uint8_t b01:1;
44
      uint8_t b02:1;
45
      uint8_t b03:1;
46
      uint8_t b04:1;
47
      uint8_t b05:1;
48
      uint8_t b06:1;
49
      uint8_t b07:1;
50
      uint8_t b08:1;
51
      uint8_t b09:1;
52
      uint8_t b10:1;
53
      uint8_t b11:1;
54
      uint8_t b12:1;
55
      uint8_t b13:1;
56
      uint8_t b14:1;
57
      uint8_t b15:1;
58
    };
59
  };
21 pfowler 60
} report;
61
 
62
usbMsgLen_t usbFunctionSetup(uchar data[8]) {
63
  usbRequest_t *rq = (void *)data;
64
 
65
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
66
        if(rq->bRequest == USBRQ_HID_GET_REPORT) {  
67
            return sizeof(report);
68
        } else if(rq->bRequest == USBRQ_HID_GET_IDLE) {
69
            return 1;
70
        } 
71
    }
72
 
73
  return 0;
74
}
75
 
76
void hadUsbReset(void) {
77
}
78
 
79
int main(void) {
80
 
81
  ACSR |= (1<<ACD); // Disable analog comparator
82
 
23 pfowler 83
  /*
84
  DDR : 1 = Output, 0 = Input
85
  PORT: 1 = Pullup for Input, otherwise set output
86
  PIN : Read input pin
87
  */
88
 
89
  /*
24 pfowler 90
	PB0	- Input	 		- Keypad 5
91
	PB1	- Input	 		- Keypad 6
92
	PB2	- Input	 		- Keypad 7
93
	PB3	- Input	 		- Keypad 8
94
	PB4	- Input, Pullup		- Function select
23 pfowler 95
  */
24 pfowler 96
  DDRB		= 0B00000000;
97
  PORTB 	= 0B00010000;
21 pfowler 98
 
23 pfowler 99
  /*
24 pfowler 100
	PD0	- Input, Pullup, PCINT16	- Rotary 1a
101
	PD1	- Input, Pullup, PCINT17	- Rotary 1b
102
 
103
 
104
	PD4	- Output			- Keypad 1
105
	PD5	- Output			- Keypad 2
106
	PD6	- Output			- Keypad 3
107
	PD7	- Output			- Keypad 4
23 pfowler 108
  */
24 pfowler 109
  DDRD		= 0B11110000;
110
  PORTD		= 0B00000011;
21 pfowler 111
 
24 pfowler 112
  PCMSK2 |= (( 1 << PCINT16 ) | ( 1 << PCINT17 )); //enable encoder pins interrupt sources
113
  PCICR |= ( 1 << PCIE2 ); //enable pin change interupts
21 pfowler 114
 
23 pfowler 115
  // Timers not used for the moment
116
  // Setup timer0 - Enable overflow, 8 times prescaler
117
  //TIMSK0 = (1<<TOIE0);			// Eable timer overflow for Timer0
118
  //TCNT0 = 0x00;				// Set Timer0 to 0
119
  //TCCR0B = (1<< CS01) ;			// /8 prescaler
21 pfowler 120
 
121
  usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
122
  _delay_ms(500);
123
  usbDeviceConnect();
124
 
125
  wdt_enable(WDTO_1S);
126
  usbInit();
127
  sei();
128
 
129
 
130
  for(;;) {
131
    wdt_reset();
132
    usbPoll();
133
 
134
    if(usbInterruptIsReady()){
24 pfowler 135
        report.data1 = 0; // Center X
136
        report.data2 = 0; // Center Y
21 pfowler 137
 
138
 
24 pfowler 139
	report.data4 |= (1 << getKey());
140
 
23 pfowler 141
	// Now work out what rotary to send, if any
142
	// Also record if we sent a positive response, 
143
	//  so we can send a '0' next time (if selected on PD4)
144
	if (rot_stat == 0x01 && rot_sent == 0) {
24 pfowler 145
		report.rot1a = 1;
23 pfowler 146
		rot_sent = 1;
147
	} else if (rot_stat == 0x02 && rot_sent == 0) {
24 pfowler 148
		report.rot1b = 1;
23 pfowler 149
		rot_sent = 1;
22 pfowler 150
	} else {
23 pfowler 151
		rot_sent = 0;
22 pfowler 152
	}
153
 
23 pfowler 154
	// Reset our stat so ready for next turn
22 pfowler 155
	rot_stat = 0;
156
 
23 pfowler 157
	// If our function select is set, dont bother
158
	//  sending a 'o' between consequtive 1's.
24 pfowler 159
	if (rbi(PINB, PB4))
23 pfowler 160
		rot_sent = 0;
161
 
21 pfowler 162
      /* called after every poll of the interrupt endpoint */
163
      usbSetInterrupt(&report, sizeof(report));
164
    }
165
  }
166
}
167
 
24 pfowler 168
uint8_t getKey() {
169
	uint8_t col, row = 0;
170
	uint8_t key = 0;
171
	uint8_t n = 0;
172
 
173
	for (col=4; col<=7; col++) {
174
		sbi(PORTD, col);
175
		for (row=0; row<=3; row++); {
176
			if (rbi(PINB, row))
177
				key = n;
178
			n++;
179
		}
180
		cbi(PORTD, col);
181
	}
182
	return key;
183
}
184
 
21 pfowler 185
void doInt() {
23 pfowler 186
	// If rot_stat is not 0, we havn't sent
187
	//  our last results yet. Skip this click.
22 pfowler 188
	if (rot_stat != 0) {
189
		pcIntMask = 0;
190
		return;
191
	}
23 pfowler 192
 
193
	// Check which pin caused the interrupt. If they both
194
	//  equal 0, the pin that interrupted is the direction
24 pfowler 195
  	if (rbi(pcIntCurr, PCINT17) == 0 
196
		&& rbi(pcIntCurr, PCINT17) == 0 
197
		&& rbi(pcIntMask, PCINT16) ) {
23 pfowler 198
			rot_stat = 1;
24 pfowler 199
  	} else if (rbi(pcIntCurr, PCINT16) == 0 
200
		&& rbi(pcIntCurr, PCINT17) == 0 
201
		&& rbi(pcIntMask, PCINT17) ) {
23 pfowler 202
			rot_stat = 2;
203
  	}
204
 
205
	// Clear the mask so we know we've delth with it
206
	pcIntMask = 0;
21 pfowler 207
}
208
 
23 pfowler 209
/* Not used for the moment
21 pfowler 210
ISR(TIMER0_OVF_vect) {
211
	timer0_ovf++;
212
}
23 pfowler 213
*/
21 pfowler 214
 
24 pfowler 215
ISR(PCINT2_vect)
21 pfowler 216
{
23 pfowler 217
	// Save the state and work out which pin caused
218
	//  the interrupt to occur
24 pfowler 219
	pcIntCurr = PIND;
23 pfowler 220
	pcIntMask = pcIntCurr ^ pcIntLast;
221
	pcIntLast = pcIntCurr;
222
	doInt();
21 pfowler 223
}
224