Subversion Repositories group.electronics

Rev

Rev 143 | Rev 152 | Go to most recent revision | Details | Compare with Previous | 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
 
150 pfowler 27
#define DISPLAYS_ATTACHED 2
139 pfowler 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
 
150 pfowler 35
	int8_t rotary;		// State of the rotary encoder
139 pfowler 36
	uint8_t buttons;	// State of the buttons
150 pfowler 37
} display[DISPLAYS_ATTACHED];
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
150 pfowler 86
 
87
 
137 pfowler 88
    uint8_t i;
150 pfowler 89
    for (i=0; i<DISPLAYS_ATTACHED; i++) {
90
    	display[i].address = 0x26 + i;
91
    	display[i].decpts = 0x00;
92
 
139 pfowler 93
    	uint8_t j;
94
    	for (j=0; j<10; j++)
95
    		display[i].value[j] = 0x0a;
137 pfowler 96
    	updateDisplay(i);
139 pfowler 97
    }
137 pfowler 98
 
130 pfowler 99
    for(;;){
100
    	 wdt_reset();
136 pfowler 101
    	 usbPoll();
130 pfowler 102
 
139 pfowler 103
    	// Only update the display when a change
104
    	//  comes in fron the usb port
137 pfowler 105
    	if (update != 255) {
106
    		updateDisplay(update);
107
    		update = 255;
130 pfowler 108
    	}
109
 
139 pfowler 110
		if (systime > refresh) {
150 pfowler 111
			refresh = systime + INPUT_REFRESH;
139 pfowler 112
			updateInput();
113
		}
130 pfowler 114
    }
115
    return 0;
116
}
117
 
139 pfowler 118
static void updateInput() {
150 pfowler 119
	uint8_t i;
120
	for (i = 0; i < DISPLAYS_ATTACHED; i++) {
121
		i2cbb_Init();
122
		i2cbb_Start();
123
		i2cbb_Write( display[i].address << 1 );
124
		i2cbb_Write( 0x0a );
125
		i2cbb_Stop();
139 pfowler 126
 
150 pfowler 127
		i2cbb_Start();
128
		i2cbb_Write( (display[i].address << 1) + 1 );
129
		display[i].rotary += (int8_t)i2cbb_Read(1);
130
		i2cbb_Stop();
139 pfowler 131
 
150 pfowler 132
		i2cbb_Init();
133
		i2cbb_Start();
134
		i2cbb_Write( display[i].address << 1 );
135
		i2cbb_Write( 0x09 );
136
		i2cbb_Stop();
139 pfowler 137
 
138
 
150 pfowler 139
		i2cbb_Init();
140
		i2cbb_Start();
141
		i2cbb_Write( display[i].address << 1 );
142
		i2cbb_Write( 0x0c );
143
		i2cbb_Stop();
139 pfowler 144
 
150 pfowler 145
		i2cbb_Start();
146
		i2cbb_Write( (display[i].address << 1) + 1 );
147
		display[i].buttons = i2cbb_Read(1);
148
		i2cbb_Stop();
149
	}
139 pfowler 150
 
151
}
152
 
137 pfowler 153
static void updateDisplay(uint8_t dis) {
154
    cbi(PORTB, PB0);
139 pfowler 155
 
156
    // Send the display buffer to display board
137 pfowler 157
    i2cbb_Init();
158
    i2cbb_Start();
150 pfowler 159
    i2cbb_Write( display[dis].address << 1);
160
    i2cbb_Write( 0x05 );
137 pfowler 161
    uint8_t n;
139 pfowler 162
    for (n=0; n<10; n++) {
150 pfowler 163
    	uint8_t send = (n << 4) | display[dis].value[n];
139 pfowler 164
    	i2cbb_Write( send );
137 pfowler 165
    }
166
    i2cbb_Stop();
139 pfowler 167
 
168
    /*
169
    // Send the decimal point
170
	i2cbb_Init();
171
	i2cbb_Start();
172
	i2cbb_Write( 0x4c );
173
	i2cbb_Write(0x08);
174
	i2cbb_Write((uint8_t)(display[dis].decpts>>8));
175
	i2cbb_Write((uint8_t)display[dis].decpts);
176
	i2cbb_Stop();
177
	*/
178
 
137 pfowler 179
    sbi(PORTB, PB0);
180
}
181
 
139 pfowler 182
#define USB_SET_LATCH			20
183
#define USB_SET_DISPLAY1		21
184
#define USB_SET_DISPLAY2		22
136 pfowler 185
 
139 pfowler 186
#define USB_GET_INPUT			30
136 pfowler 187
 
139 pfowler 188
#define USB_SET_INT16			50
136 pfowler 189
 
139 pfowler 190
usbMsgLen_t usbFunctionSetup(uchar data[8])
191
{
192
    usbRequest_t    *rq = (void *)data;
136 pfowler 193
 
139 pfowler 194
	switch (rq->bRequest ) {
195
		case USB_SET_LATCH: {
150 pfowler 196
			update = rq->wValue.bytes[0];;
139 pfowler 197
			break;
198
		}
199
		case USB_SET_DISPLAY1: {
200
			uint8_t dis = rq->wValue.bytes[1];
201
			uint8_t dig = rq->wValue.bytes[0];
202
			//uint8_t dp = rq->wIndex.bytes[1];
203
			uint8_t val = rq->wIndex.bytes[0];
204
			display[dis].value[dig] = val;
205
			/*
206
			if (dp)
207
				sbi(display[dis].decpts, 1 << dig);
208
			else
209
				cbi(display[dis].decpts, 1 << dig);
210
			//display[dis].decpts |= dp << dig;*/
211
			break;
212
		}
213
		case USB_GET_INPUT: {
150 pfowler 214
			uint8_t i;
215
			for (i=0; i<DISPLAYS_ATTACHED; i++) {
216
				usbReplyBuf[(i*2)] = display[i].buttons;
217
				usbReplyBuf[(i*2+1)] = display[i].rotary;
218
				display[i].rotary = 0;
219
			}
220
 
139 pfowler 221
			usbMsgPtr = usbReplyBuf;
222
			return sizeof(usbReplyBuf);
223
		}
224
 
225
	}
226
	return 0;
136 pfowler 227
}
228
 
229
static void calibrateOscillator(void) {
230
    uchar step = 128;
231
    uchar trialValue = 0, optimumValue;
232
    int x, optimumDev;
233
    int targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
234
 
235
    /* do a binary search: */
236
    do {
237
        OSCCAL = trialValue + step;
238
        x = usbMeasureFrameLength();    /* proportional to current real frequency */
239
        if(x < targetValue)             /* frequency still too low */
240
            trialValue += step;
241
        step >>= 1;
242
    } while(step > 0);
243
    /* We have a precision of +/- 1 for optimum OSCCAL here */
244
    /* now do a neighborhood search for optimum value */
245
    optimumValue = trialValue;
246
    optimumDev = x; /* this is certainly far away from optimum */
247
    for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
248
        x = usbMeasureFrameLength() - targetValue;
249
        if(x < 0)
250
            x = -x;
251
        if(x < optimumDev){
252
            optimumDev = x;
253
            optimumValue = OSCCAL;
254
        }
255
    }
256
    OSCCAL = optimumValue;
257
}
258
 
259
 
260
void usbEventResetReady(void) {
261
    cli();
262
    calibrateOscillator();
263
    sei();
264
    eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */
265
}
266
 
132 pfowler 267
ISR(TIM0_OVF_vect) {
130 pfowler 268
 
132 pfowler 269
	tmr0_ovf++;
130 pfowler 270
 
271
	// Clk/1 TCCR0B = (1<< CS00);
272
	//20.0Mhz, 1ms = 78ovf
273
	//16.5Mhz, 1ms = 64ovf
274
	//16.0Mhz, 1ms = 62ovf
275
	//12.0Mhz, 1ms = 46ovf
276
	// 8.0Mhz, 1ms = 31ovf
131 pfowler 277
	// 8.0Mhz, .5ms = 15ovf, 160r
130 pfowler 278
 
132 pfowler 279
	if (tmr0_ovf>=64) {
130 pfowler 280
			systime++;
281
			tmr0_ovf = 0;
282
	}
283
 
284
}