Rev 134 | Blame | 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)
#endif
static void calibrateOscillator(void);
void usbEventResetReady(void);
static void updateDisplays();
#define DIS_COM_ACTIVE
#define DIS_COM_STANDBY
#define DIS_NAV_ACTIVE
#define DIS_NAV_STANDBY
// Hold the chars for the display panels
volatile uint8_t displays[5][6] = {
{ 0, 0, 0, 0, 0}, // DIS_COM_ACTIVE
{ 0, 0, 0, 0, 0}, // DIS_COM_STANDBY
{ 0, 0, 0, 0, 0}, // DIS_NAV_ACTIVE
{ 0, 0, 0, 0, 0}, // DIS_NAV_STANDBY
};
//static uchar usbReplyBuf[16];
volatile static uint8_t bytesRemaining;
volatile static uint8_t* writeIdx;
volatile uint8_t tmr0_ovf = 0;
volatile uint8_t update = 1;
int main(void) {
uchar calibrationValue;
calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
if(calibrationValue != 0xff){
OSCCAL = calibrationValue;
}
/*
DDR : 1 = Output, 0 = Input
PORT: 1 = Pullup for Input, otherwise set output
PIN : Read input pin
PB0 -
PB1 - - USB D- Low Speed
PB2 - - USB D+
PB3 - - SCL i2c bb
PB4 - - SDA i2c bb
PB5 -
*/
DDRB = 0B00000001;
PORTB = 0B00000001;
usbDeviceDisconnect();
_delay_ms(300);
usbDeviceConnect();
systime = 0;
sysclockInit();
wdt_enable(WDTO_1S); // Watchdog for 1 sec
usbInit();
sei(); // Enable interrupts
/*
cbi(PORTB, PB0);
i2cbb_Init();
i2cbb_Start();
i2cbb_Write(0x4c);
i2cbb_Write(0x05);
i2cbb_Write(0x08);
i2cbb_Stop();
sbi(PORTB, PB0);
*/
for(;;){
wdt_reset();
usbPoll();
if (update) {
updateDisplays();
}
}
return 0;
}
static void updateDisplays() {
cbi(PORTB, PB0);
i2cbb_Init();
i2cbb_Start();
i2cbb_Write(0x4c);
i2cbb_Write(0x05);
i2cbb_Write(0x00 | displays[0][0]);
i2cbb_Write(0x10 | displays[0][1]);
i2cbb_Write(0x20 | displays[0][2]);
i2cbb_Write(0x30 | displays[0][3]);
i2cbb_Write(0x40 | displays[0][4]);
i2cbb_Stop();
sbi(PORTB, PB0);
cbi(PORTB, PB0);
i2cbb_Init();
i2cbb_Start();
i2cbb_Write(0x4c);
i2cbb_Write(0x05);
i2cbb_Write(0x50 | displays[1][0]);
i2cbb_Write(0x60 | displays[1][1]);
i2cbb_Write(0x70 | displays[1][2]);
i2cbb_Write(0x80 | displays[1][3]);
i2cbb_Write(0x90 | displays[1][4]);
i2cbb_Stop();
sbi(PORTB, PB0);
update = 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;
}
#define USB_GET_CONT_VER 10 // Send the controller version data
#define USB_GET_COMM_VER 11 // Send the comm display version data
#define USB_GET_NAV_VER 12 // Send the nav display version data
#define USB_SET_COMM_ACTIVE 20 // Set the comm active freq
#define USB_SET_COMM_STANDBY 21 // Set the comm standby freq
#define USB_SET_NAV_ACTIVE 22 // Set the nav active freq
#define USB_SET_NAV_STANDBY 23 // Set the nav standby freq
#define USB_BLANK_ALL 24 // Blank all displays
#define USB_SET_ALL 25 // Blank all displays
#define USB_GET_COMM_ENC 30 // Send the comm rotary encoder position
#define USB_RESET_COMM_ENC 31 // Reset the comm encoder to 0
#define USB_GET_NAV_ENC 32 // Send the nav rotary encoder position
#define USB_RESET_NAV_ENC 33 // Reset the nav encoder to 0
#define USB_GET_BUTTONS 32 // Send the status of all the buttons
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
switch (rq->bRequest ) {
case 20: {
uint8_t dis = rq->wValue.bytes[0];
uint8_t dig = rq->wValue.bytes[1];
uint8_t val = rq->wIndex.bytes[0];
displays[dis][dig] = val;
update = 1;
break;
}
}
return 0;
}
/*
uchar usbFunctionWrite(uchar *data, uchar len) {
uint8_t i;
if (len > bytesRemaining)
len = bytesRemaining;
bytesRemaining -= len;
for (i=0; i<len; i++) {
*writeIdx++ = data[i];
}
displays[0][3] = 2;
displays[0][4] = 2;
update = 1;
return (bytesRemaining == 0);
}
*/
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, 160r
if (tmr0_ovf>=64) {
systime++;
tmr0_ovf = 0;
}
}