Subversion Repositories group.electronics

Rev

Rev 136 | 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();
static void updateDisplay(uint8_t dis);

#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] = {
                                                        { 6, 6, 6, 6, 6},       // DIS_COM_ACTIVE
                                                        { 7, 7, 7, 7, 7},       // 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 = 255;



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(500);
    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);
*/

    uint8_t i;
    for (i=0; i<2; i++)
        updateDisplay(i);


    for(;;){
         wdt_reset();
         usbPoll();

        if (update != 255) {
                updateDisplay(update);
                update = 255;
        }

    }
    return 0;
}

static void updateDisplay(uint8_t dis) {
    cbi(PORTB, PB0);
    i2cbb_Init();
    i2cbb_Start();
    i2cbb_Write(0x4c);
    i2cbb_Write(0x05);
    uint8_t n;
    for (n=0; n<5; n++) {
        i2cbb_Write( ((n+5*dis)<<4) | (displays[dis][n] & 0x0f) );
    }
    i2cbb_Stop();
    sbi(PORTB, PB0);
}

/*
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_DIGIT                   20              // Set a digit on display

#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 USB_SET_DIGIT: {
                        uint8_t dis = rq->wValue.bytes[1];
                        uint8_t dig = rq->wValue.bytes[0];
                        uint8_t val = rq->wIndex.bytes[0];
                        displays[dis][dig] = val;
                        update = dis;
                        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;
        }

}