Rev 143 | Rev 152 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <avr/io.h>#include <avr/wdt.h>#include <avr/eeprom.h>#include <avr/interrupt.h>#include <avr/pgmspace.h>#include <util/delay.h>#include "config.h"#include "avrutil.h"#include "usbdrv.h"#include "i2cbb.h"#ifndef NULL#define NULL ((void *)0)#endifvoid usbEventResetReady(void);static void calibrateOscillator(void);static void updateDisplay(uint8_t dis);static void updateInput();//static void requestData(uint8_t addr, uint8_t code, uint8_t* data, uint8_t len);void print16(uint8_t dis, uint8_t dig, uint16_t val);#define DISPLAYS_ATTACHED 2#define INPUT_REFRESH 5struct display_type {uint8_t address;uint8_t value[10];uint16_t decpts;int8_t rotary; // State of the rotary encoderuint8_t buttons; // State of the buttons} display[DISPLAYS_ATTACHED];static uint8_t usbReplyBuf[8];static uint8_t update = 255;volatile uint8_t tmr0_ovf = 0;int main(void) {// calibration value from last timeuchar calibrationValue;calibrationValue = eeprom_read_byte(0);if(calibrationValue != 0xff){OSCCAL = calibrationValue;}/*DDR : 1 = Output, 0 = InputPORT: 1 = Pullup for Input, otherwise set outputPIN : Read input pinPB0 -PB1 - - USB D- Low SpeedPB2 - - USB D+PB3 - - SCL i2c bbPB4 - - SDA i2c bbPB5 -*/DDRB = 0B00000001;PORTB = 0B00000001;usbDeviceDisconnect();_delay_ms(500);usbDeviceConnect();systime = 0;uint32_t refresh = 0;sysclockInit();wdt_enable(WDTO_1S);usbInit();sei();// Set the displays to blankuint8_t i;for (i=0; i<DISPLAYS_ATTACHED; i++) {display[i].address = 0x26 + i;display[i].decpts = 0x00;uint8_t j;for (j=0; j<10; j++)display[i].value[j] = 0x0a;updateDisplay(i);}for(;;){wdt_reset();usbPoll();// Only update the display when a change// comes in fron the usb portif (update != 255) {updateDisplay(update);update = 255;}if (systime > refresh) {refresh = systime + INPUT_REFRESH;updateInput();}}return 0;}static void updateInput() {uint8_t i;for (i = 0; i < DISPLAYS_ATTACHED; i++) {i2cbb_Init();i2cbb_Start();i2cbb_Write( display[i].address << 1 );i2cbb_Write( 0x0a );i2cbb_Stop();i2cbb_Start();i2cbb_Write( (display[i].address << 1) + 1 );display[i].rotary += (int8_t)i2cbb_Read(1);i2cbb_Stop();i2cbb_Init();i2cbb_Start();i2cbb_Write( display[i].address << 1 );i2cbb_Write( 0x09 );i2cbb_Stop();i2cbb_Init();i2cbb_Start();i2cbb_Write( display[i].address << 1 );i2cbb_Write( 0x0c );i2cbb_Stop();i2cbb_Start();i2cbb_Write( (display[i].address << 1) + 1 );display[i].buttons = i2cbb_Read(1);i2cbb_Stop();}}static void updateDisplay(uint8_t dis) {cbi(PORTB, PB0);// Send the display buffer to display boardi2cbb_Init();i2cbb_Start();i2cbb_Write( display[dis].address << 1);i2cbb_Write( 0x05 );uint8_t n;for (n=0; n<10; n++) {uint8_t send = (n << 4) | display[dis].value[n];i2cbb_Write( send );}i2cbb_Stop();/*// Send the decimal pointi2cbb_Init();i2cbb_Start();i2cbb_Write( 0x4c );i2cbb_Write(0x08);i2cbb_Write((uint8_t)(display[dis].decpts>>8));i2cbb_Write((uint8_t)display[dis].decpts);i2cbb_Stop();*/sbi(PORTB, PB0);}#define USB_SET_LATCH 20#define USB_SET_DISPLAY1 21#define USB_SET_DISPLAY2 22#define USB_GET_INPUT 30#define USB_SET_INT16 50usbMsgLen_t usbFunctionSetup(uchar data[8]){usbRequest_t *rq = (void *)data;switch (rq->bRequest ) {case USB_SET_LATCH: {update = rq->wValue.bytes[0];;break;}case USB_SET_DISPLAY1: {uint8_t dis = rq->wValue.bytes[1];uint8_t dig = rq->wValue.bytes[0];//uint8_t dp = rq->wIndex.bytes[1];uint8_t val = rq->wIndex.bytes[0];display[dis].value[dig] = val;/*if (dp)sbi(display[dis].decpts, 1 << dig);elsecbi(display[dis].decpts, 1 << dig);//display[dis].decpts |= dp << dig;*/break;}case USB_GET_INPUT: {uint8_t i;for (i=0; i<DISPLAYS_ATTACHED; i++) {usbReplyBuf[(i*2)] = display[i].buttons;usbReplyBuf[(i*2+1)] = display[i].rotary;display[i].rotary = 0;}usbMsgPtr = usbReplyBuf;return sizeof(usbReplyBuf);}}return 0;}static void calibrateOscillator(void) {uchar step = 128;uchar trialValue = 0, optimumValue;int x, optimumDev;int targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);/* do a binary search: */do {OSCCAL = trialValue + step;x = usbMeasureFrameLength(); /* proportional to current real frequency */if(x < targetValue) /* frequency still too low */trialValue += step;step >>= 1;} while(step > 0);/* We have a precision of +/- 1 for optimum OSCCAL here *//* now do a neighborhood search for optimum value */optimumValue = trialValue;optimumDev = x; /* this is certainly far away from optimum */for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){x = usbMeasureFrameLength() - targetValue;if(x < 0)x = -x;if(x < optimumDev){optimumDev = x;optimumValue = OSCCAL;}}OSCCAL = optimumValue;}void usbEventResetReady(void) {cli();calibrateOscillator();sei();eeprom_write_byte(0, OSCCAL); /* store the calibrated value in EEPROM */}ISR(TIM0_OVF_vect) {tmr0_ovf++;// Clk/1 TCCR0B = (1<< CS00);//20.0Mhz, 1ms = 78ovf//16.5Mhz, 1ms = 64ovf//16.0Mhz, 1ms = 62ovf//12.0Mhz, 1ms = 46ovf// 8.0Mhz, 1ms = 31ovf// 8.0Mhz, .5ms = 15ovf, 160rif (tmr0_ovf>=64) {systime++;tmr0_ovf = 0;}}