Subversion Repositories group.electronics

Rev

Rev 122 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#include "usbdrv.h"
#include "config.h"

#ifndef NULL
#define NULL    ((void *)0)
#endif

#define USB_GET_STATE  100
#define USB_LEDS_SET  101

/* ------------------------------------------------------------------------- */

uint8_t getKey(void);
void doButtons(uint8_t);
inline void setLeds(uint8_t);

struct {
        int16_t axis[2];
        uint8_t buttons;
} reportBuffer;


volatile struct {
        uint8_t buttons;
        uint8_t waitup;
        uint8_t timer;
} debounce;

volatile struct {
        uint8_t data;
        union {
                uint8_t led_method:1;
                uint8_t other:1;
                uint8_t reserved:6;
        };
} config;

static uchar usbReplyBuf[16];

volatile uint8_t currLeds = 0;
volatile uint8_t currKeys = 0;
volatile uint8_t tmr0_ovf = 0;
volatile uint32_t systime = 0;

/* ------------------------------------------------------------------------- */

void hadUsbReset(void) {
}


uchar   usbFunctionSetup(uchar data[8])
{
    usbRequest_t    *rq = (void *)data;

        switch (rq->bRequest ) {
                case USB_GET_STATE:
                        usbReplyBuf[0] = currLeds;
                        usbReplyBuf[1] = currKeys;
                        usbMsgPtr = usbReplyBuf;
                        return sizeof(usbReplyBuf);
                case USB_LEDS_SET:
                        currLeds = rq->wValue.bytes[0];
                        return 0;
                        
        }

        return 0;
}

int main(void) {

        DIDR0 = 0x00;

  /*
  DDR : 1 = Output, 0 = Input
  PORT: 1 = Pullup for Input, otherwise set output
  PIN : Read input pin
  */

  /*
        PB0     - Output                - LED 3
        PB1     - Output                - LED 4
        PB2     - Output                - LED 5
        PB3     - Output                - LED 6
        PB4     - Output                - LED 7
        PB5     - 
        PB6     - 
        PB7     - 
  */
  DDRB          = 0B00011111;
  PORTB         = 0B00000000;

  /*
        PC0     - Output                - ButtonPad Gnd0
        PC1     - Output                - ButtonPad Gnd1
        PC2     - Input, Pullup         - ButtonPad 0
        PC3     - Input, Pullup         - ButtonPad 1
        PC4     - Input, Pullup         - ButtonPad 2
        PC5     - Input, Pullup         - ButtonPad 3
  */
  DDRC          = 0B00000011;
  PORTC         = 0B00111111;

  /*
        PD0     - 
        PD1     - 
        PD2     - 
        PD3     - 
        PD4     - 
        PD5     - Output                - LED 0
        PD6     - Output                - LED 1
        PD7     - Output                - LED 2
  */
  DDRD          = 0B11100000;
  PORTD         = 0B00000000;

        setLeds(0xff);

    usbDeviceDisconnect();
    _delay_ms(500);
    usbDeviceConnect();


    TIMSK0 = (1<<TOIE0);                    // Enable timer overflow
    TCNT0 = 0x00;                           // Set Timer0 initial value to 0
    TCCR0B = (1<< CS00) ;                   // /1 prescaler

    wdt_enable(WDTO_1S);
    usbInit();
    sei();

        config.led_method = 1;
        setLeds(currLeds);


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

        currKeys = getKey();

        if (config.led_method != rbi(PORTB, 5)) {
                // Reset the leds when switcing to buttons
                if (config.led_method == 0) currLeds = 1;
                config.led_method = rbi(PORTB, 5);
        }

        if (config.led_method == 1) {
                uint8_t pressed = getKey();
                doButtons(pressed);
        }

        setLeds(currLeds);


    }

    return 0;
}

inline void setLeds(uint8_t leds) {
        PORTB &= 0xE0;
        PORTB |= (0x1F & (leds >> 3));
        PORTD &= 0x1F;
        PORTD |= (0xE0 & (leds << 5));
}

void doButtons(uint8_t pressed) {

        // Deboucing
        // When i key first goes down, wait 5 ms, check it again to see if its still down
        if (pressed && debounce.buttons == 0 && debounce.timer == 0) {
                debounce.buttons = pressed;
                debounce.timer = 5;
        }

        // The key has come up
        if (pressed != debounce.buttons) {
                debounce.buttons = 0;
                debounce.timer = 0;
                debounce.waitup = 0;
        }

        // Debounce timer is up, process our button
        if (debounce.buttons && debounce.timer == 0 && debounce.waitup != 1) {
                uint8_t i = 0;
                for (i=0; i<=7; i++) {
                        // Button pressed and the led is currently on
                        if ( rbi(debounce.buttons, i) == 1 && rbi(currLeds, i) == 1 ) {
                                if ( i == 0 && rbi(currLeds, 1) != 1)  //Dont turn off com1 if no comm2
                                        break;

                                if ( i == 1 && rbi(currLeds, 0) != 1)  //Dont turn off com2 if no comm1
                                        break;

                                cbi(currLeds, i);
                        // Button is pressed and led is currently off
                         } else if ( rbi(debounce.buttons, i) == 1 && rbi(currLeds, i) == 0 ) {
                                if ( i == 0 && rbi(currLeds, 1) == 1)  //Turn on comm2, turn off comm1
                                        cbi(currLeds,1);

                                if ( i == 1 && rbi(currLeds, 0) == 1)  //Turn on comm1, turn off comm2
                                        cbi(currLeds,0);

                                sbi(currLeds, i);
                        }
                }
                debounce.waitup = 1;
        }
}

// Gnd = PC0, PC1
// Btn = PC2, PC3, PC4, PC5
uint8_t getKey() {
        uint8_t key = 0;

        cbi(PORTC, 1);
        _delay_us(10);        // Wait for the port change
        if (rbi(PINC, 2) == 0) key = 1;
        if (rbi(PINC, 3) == 0) key = 2;
        if (rbi(PINC, 4) == 0) key = 4;
        if (rbi(PINC, 5) == 0) key = 8;
        sbi(PORTC, 1);

        cbi(PORTC, 0);
        _delay_us(10);
        if (rbi(PINC, 2) == 0) key = 16;
        if (rbi(PINC, 3) == 0) key = 32;
        if (rbi(PINC, 4) == 0) key = 64;
        if (rbi(PINC, 5) == 0) key = 128;
        sbi(PORTC, 0);

        return key;
}


ISR(TIMER0_OVF_vect) {
        tmr0_ovf++;

        // Clk/1 TCCR0B = (1<< CS00);
        //20.0Mhz, 1ms = 78ovf
        //16.5Mhz, 1ms = 64ovf
        //12.0Mhz, 1ms = 46ovf

        if (tmr0_ovf>=78) {
                systime++;
                tmr0_ovf = 0;

                if (debounce.timer != 0)
                        debounce.timer--;

        }
}