Subversion Repositories group.electronics

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
130 pfowler 1
#include <avr/io.h>
2
#include <avr/wdt.h>
136 pfowler 3
#include <avr/eeprom.h>
130 pfowler 4
#include <avr/interrupt.h>
136 pfowler 5
#include <avr/pgmspace.h>
130 pfowler 6
#include <util/delay.h>
7
 
8
#include "config.h"
9
#include "avrutil.h"
136 pfowler 10
#include "usbdrv.h"
11
#include "i2cbb.h"
130 pfowler 12
 
13
 
14
#ifndef NULL
15
#define NULL    ((void *)0)
16
#endif
17
 
139 pfowler 18
void usbEventResetReady(void);
136 pfowler 19
static void calibrateOscillator(void);
137 pfowler 20
static void updateDisplay(uint8_t dis);
139 pfowler 21
static void updateInput();
130 pfowler 22
 
139 pfowler 23
//static void requestData(uint8_t addr, uint8_t code, uint8_t* data, uint8_t len);
130 pfowler 24
 
139 pfowler 25
void print16(uint8_t dis, uint8_t dig, uint16_t val);
130 pfowler 26
 
139 pfowler 27
#define DISPLAY_ATTACHED 1
28
#define INPUT_REFRESH 5
130 pfowler 29
 
139 pfowler 30
struct display_type {
31
	uint8_t address;
32
	uint8_t value[10];
33
	uint16_t decpts;
136 pfowler 34
 
139 pfowler 35
	uint8_t rotary;		// State of the rotary encoder
36
	uint8_t buttons;	// State of the buttons
37
} display[2];
136 pfowler 38
 
139 pfowler 39
 
40
 
41
static uint8_t usbReplyBuf[8];
42
static uint8_t update = 255;
43
 
44
 
130 pfowler 45
volatile uint8_t tmr0_ovf = 0;
46
 
136 pfowler 47
 
130 pfowler 48
int main(void) {
139 pfowler 49
	// calibration value from last time
136 pfowler 50
	uchar   calibrationValue;
139 pfowler 51
	calibrationValue = eeprom_read_byte(0);
136 pfowler 52
	if(calibrationValue != 0xff){
53
		OSCCAL = calibrationValue;
54
	}
130 pfowler 55
 
136 pfowler 56
	/*
57
		DDR : 1 = Output, 0 = Input
58
		PORT: 1 = Pullup for Input, otherwise set output
59
		PIN : Read input pin
130 pfowler 60
 
136 pfowler 61
		PB0	-
62
		PB1	- 		- USB D- Low Speed
63
		PB2	-		- USB D+
64
		PB3	- 		- SCL i2c bb
65
		PB4	-		- SDA i2c bb
66
		PB5	-
67
	*/
68
	DDRB          = 0B00000001;
69
	PORTB         = 0B00000001;
70
 
137 pfowler 71
 
136 pfowler 72
    usbDeviceDisconnect();
137 pfowler 73
    _delay_ms(500);
136 pfowler 74
    usbDeviceConnect();
75
 
130 pfowler 76
    systime = 0;
139 pfowler 77
    uint32_t refresh = 0;
130 pfowler 78
    sysclockInit();
79
 
139 pfowler 80
    wdt_enable(WDTO_1S);
136 pfowler 81
    usbInit();
139 pfowler 82
    sei();
130 pfowler 83
 
136 pfowler 84
 
139 pfowler 85
    // Set the displays to blank
86
    display[0].address = 0x26;
87
    display[0].decpts = 0x00;
137 pfowler 88
    uint8_t i;
139 pfowler 89
    for (i=0; i<DISPLAY_ATTACHED; i++) {
90
    	uint8_t j;
91
    	for (j=0; j<10; j++)
92
    		display[i].value[j] = 0x0a;
137 pfowler 93
    	updateDisplay(i);
139 pfowler 94
    }
137 pfowler 95
 
130 pfowler 96
    for(;;){
97
    	 wdt_reset();
136 pfowler 98
    	 usbPoll();
130 pfowler 99
 
139 pfowler 100
    	// Only update the display when a change
101
    	//  comes in fron the usb port
137 pfowler 102
    	if (update != 255) {
103
    		updateDisplay(update);
104
    		update = 255;
130 pfowler 105
    	}
106
 
139 pfowler 107
		if (systime > refresh) {
108
			refresh = systime + 5;
109
			updateInput();
110
		}
130 pfowler 111
    }
112
    return 0;
113
}
114
 
139 pfowler 115
static void updateInput() {
116
	/*
117
	uint8_t data[1];
118
	requestData(0x4c, 0x0a, data, 1);
119
	display[0].rotary = data[0];
120
	requestData(0x4c, 0x0c, data, 1);
121
	display[0].buttons = data[0];
122
	*/
123
 
124
 
125
	i2cbb_Init();
126
	i2cbb_Start();
127
	i2cbb_Write( 0x4c );
128
	i2cbb_Write( 0x0a );
129
	i2cbb_Stop();
130
 
131
	i2cbb_Start();
132
	i2cbb_Write( 0x4d );
133
	display[0].rotary = i2cbb_Read(1);
134
	i2cbb_Stop();
135
 
136
	i2cbb_Init();
137
	i2cbb_Start();
138
	i2cbb_Write( 0x4c );
139
	i2cbb_Write( 0x0c );
140
	i2cbb_Stop();
141
 
142
	i2cbb_Start();
143
	i2cbb_Write( 0x4d );
144
	display[0].buttons = i2cbb_Read(1);
145
	i2cbb_Stop();
146
 
147
}
148
 
149
/*
150
static void requestData(uint8_t addr, uint8_t code, uint8_t* data, uint8_t len) {
151
	i2cbb_Init();
152
	i2cbb_Start();
153
	i2cbb_Write( addr );
154
	i2cbb_Write( code );
155
	i2cbb_Stop();
156
 
157
	uint8_t i;
158
	i2cbb_Write( addr + 1 );
159
	for (i=0; i<len; i++)
160
		data[i] = i2cbb_Read(1);
161
	i2cbb_Stop();
162
}
163
*/
164
 
137 pfowler 165
static void updateDisplay(uint8_t dis) {
166
    cbi(PORTB, PB0);
139 pfowler 167
 
168
    // Send the display buffer to display board
137 pfowler 169
    i2cbb_Init();
170
    i2cbb_Start();
171
    i2cbb_Write(0x4c);
172
    i2cbb_Write(0x05);
173
    uint8_t n;
139 pfowler 174
    for (n=0; n<10; n++) {
175
    	uint8_t send = (n << 4) | display[0].value[n];
176
    	i2cbb_Write( send );
137 pfowler 177
    }
178
    i2cbb_Stop();
139 pfowler 179
 
180
    /*
181
    // Send the decimal point
182
	i2cbb_Init();
183
	i2cbb_Start();
184
	i2cbb_Write( 0x4c );
185
	i2cbb_Write(0x08);
186
	i2cbb_Write((uint8_t)(display[dis].decpts>>8));
187
	i2cbb_Write((uint8_t)display[dis].decpts);
188
	i2cbb_Stop();
189
	*/
190
 
137 pfowler 191
    sbi(PORTB, PB0);
192
}
193
 
139 pfowler 194
#define USB_SET_LATCH			20
195
#define USB_SET_DISPLAY1		21
196
#define USB_SET_DISPLAY2		22
136 pfowler 197
 
139 pfowler 198
#define USB_GET_INPUT			30
136 pfowler 199
 
139 pfowler 200
#define USB_SET_INT16			50
136 pfowler 201
 
139 pfowler 202
usbMsgLen_t usbFunctionSetup(uchar data[8])
203
{
204
    usbRequest_t    *rq = (void *)data;
136 pfowler 205
 
139 pfowler 206
	switch (rq->bRequest ) {
207
		case USB_SET_LATCH: {
208
			update = 0;
209
			break;
210
		}
211
		case USB_SET_DISPLAY1: {
212
			uint8_t dis = rq->wValue.bytes[1];
213
			uint8_t dig = rq->wValue.bytes[0];
214
			//uint8_t dp = rq->wIndex.bytes[1];
215
			uint8_t val = rq->wIndex.bytes[0];
216
			display[dis].value[dig] = val;
217
			/*
218
			if (dp)
219
				sbi(display[dis].decpts, 1 << dig);
220
			else
221
				cbi(display[dis].decpts, 1 << dig);
222
			//display[dis].decpts |= dp << dig;*/
223
			break;
224
		}
225
		case USB_SET_INT16: {
226
			uint8_t dis = rq->wValue.bytes[1];
227
			uint8_t dig = rq->wValue.bytes[0];
228
			uint16_t val = ((uint16_t)rq->wIndex.bytes[1]) << 8;
229
			val |= (rq->wIndex.bytes[0] & 0x0f);
230
			print16(dis, dig, val);
231
			break;
232
		}
233
		case USB_GET_INPUT: {
234
			usbReplyBuf[0] = display[0].buttons;
235
			usbReplyBuf[1] = display[0].rotary;
236
			usbMsgPtr = usbReplyBuf;
237
			return sizeof(usbReplyBuf);
238
		}
239
 
240
	}
241
	return 0;
136 pfowler 242
}
243
 
139 pfowler 244
void print16(uint8_t dis, uint8_t dig, uint16_t val) {
245
	uint8_t buf[] = {0x0a, 0x0a, 0x0a, 0x0a, 0x0a};
246
	uint8_t len = itobcd16(val, buf);
247
 
248
	uint8_t i;
249
	for (i=0; i<5; i++) {
250
		if (i < len)
251
			display[dis].value[dig+i] = buf[i];
252
	}
253
}
254
 
136 pfowler 255
static void calibrateOscillator(void) {
256
    uchar step = 128;
257
    uchar trialValue = 0, optimumValue;
258
    int x, optimumDev;
259
    int targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
260
 
261
    /* do a binary search: */
262
    do {
263
        OSCCAL = trialValue + step;
264
        x = usbMeasureFrameLength();    /* proportional to current real frequency */
265
        if(x < targetValue)             /* frequency still too low */
266
            trialValue += step;
267
        step >>= 1;
268
    } while(step > 0);
269
    /* We have a precision of +/- 1 for optimum OSCCAL here */
270
    /* now do a neighborhood search for optimum value */
271
    optimumValue = trialValue;
272
    optimumDev = x; /* this is certainly far away from optimum */
273
    for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
274
        x = usbMeasureFrameLength() - targetValue;
275
        if(x < 0)
276
            x = -x;
277
        if(x < optimumDev){
278
            optimumDev = x;
279
            optimumValue = OSCCAL;
280
        }
281
    }
282
    OSCCAL = optimumValue;
283
}
284
 
285
 
286
void usbEventResetReady(void) {
287
    cli();
288
    calibrateOscillator();
289
    sei();
290
    eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */
291
}
292
 
132 pfowler 293
ISR(TIM0_OVF_vect) {
130 pfowler 294
 
132 pfowler 295
	tmr0_ovf++;
130 pfowler 296
 
297
	// Clk/1 TCCR0B = (1<< CS00);
298
	//20.0Mhz, 1ms = 78ovf
299
	//16.5Mhz, 1ms = 64ovf
300
	//16.0Mhz, 1ms = 62ovf
301
	//12.0Mhz, 1ms = 46ovf
302
	// 8.0Mhz, 1ms = 31ovf
131 pfowler 303
	// 8.0Mhz, .5ms = 15ovf, 160r
130 pfowler 304
 
132 pfowler 305
	if (tmr0_ovf>=64) {
130 pfowler 306
			systime++;
307
			tmr0_ovf = 0;
308
	}
309
 
310
}