Rev 20 | 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
#define USB_GET_ANALOG 102
#define USB_SET_POWER_LED 103
/* ------------------------------------------------------------------------- */
uint8_t getKey(void);
inline void setLeds();
void analogInit();
uint8_t analogRead(uint8_t channel);
/*
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 pwrLed = 0;
volatile uint8_t currLeds = 0;
volatile uint8_t currKeys = 0;
volatile uint8_t analogPin = 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;
case USB_GET_ANALOG:
usbReplyBuf[0] = (analogPin);
usbMsgPtr = usbReplyBuf;
return sizeof(usbReplyBuf);
case USB_SET_POWER_LED:
pwrLed = rq->wValue.bytes[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 - Input - Config Switch 1
PB6 - Osc
PB7 - Osc
*/
DDRB = 0B00011111;
PORTB = 0B00000000;
/*
PC0 - Input, ADC - Potentiometer
PC1 - Output - Power LED
PC2 - Input, Pullup - ButtonPad 0
PC3 - Input, Pullup - ButtonPad 1
PC4 - Input, Pullup - ButtonPad 2
PC5 - Input, Pullup - ButtonPad 3
PC6 - Reset
*/
DDRC = 0B00000010;
PORTC = 0B00111100;
/*
PD0 - Output - ButtonPad Gnd0
PD1 - Output - ButtonPad Gnd1
PD2 - USB D+
PD3 - USB D-
PD4 - Input - Config Switch 2
PD5 - Output - LED 0
PD6 - Output - LED 1
PD7 - Output - LED 2
*/
DDRD = 0B11100011;
PORTD = 0B00000011;
// The USB connect stuff, flash the power led
sbi(PORTC, PC1);
usbDeviceDisconnect();
_delay_ms(500);
usbDeviceConnect();
cbi(PORTC, PC1);
// @TODO: Don't really need the system time anymore, remove?
TIMSK0 = (1<<TOIE0); // Enable timer overflow
TCNT0 = 0x00; // Set Timer0 initial value to 0
TCCR0B = (1<< CS00) ; // /1 prescaler
wdt_enable(WDTO_1S); // WatchDog at 1s
usbInit(); // Init the USB port
sei(); // Enable interrupts
setLeds(); // Set default LED status
analogInit(); // Init the ADC for PC0 (ADC0)
/*
* @TODO: PowerSave - Only read ADC every 100ms
* @TODO: PowerSave - Only set leds on change
* @TODO: PowerSave - Sleep for a few us each cycle
*/
for(;;){
wdt_reset();
usbPoll(); // Poll USB port (Every ~10ms!)
currKeys = getKey(); // Check the button presses
analogPin = analogRead(0); // Read the pot (VolControl)
setLeds(); // Set the leds
// @TODO: Only do this on change
}
return 0;
}
inline void setLeds() {
// Set the status leds.
// @TODO: Verify that this doesn't mess with other port functions
PORTB &= 0xE0;
PORTB |= (0x1F & (currLeds >> 3));
PORTD &= 0x1F;
PORTD |= (0xE0 & (currLeds << 5));
// Set the power led state
if (pwrLed)
sbi(PORTC, PC1);
else
cbi(PORTC, PC1);
}
// Gnd = PD0, PD1
// Btn = PC2, PC3, PC4, PC5
uint8_t getKey() {
uint8_t key = 0;
cbi(PORTD, PD1); // Read the first row of buttons
_delay_us(10); // Wait for the port change
if (rbi(PINC, PC2) == 0) key = 1;
if (rbi(PINC, PC3) == 0) key = 2;
if (rbi(PINC, PC4) == 0) key = 4;
if (rbi(PINC, PC5) == 0) key = 8;
sbi(PORTD, PD1);
cbi(PORTD, PD0); // Read the second row of buttons
_delay_us(10);
if (rbi(PINC, PC2) == 0) key = 16;
if (rbi(PINC, PC3) == 0) key = 32;
if (rbi(PINC, PC4) == 0) key = 64;
if (rbi(PINC, PC5) == 0) key = 128;
sbi(PORTD, PD0);
return key;
}
uint8_t analogRead(uint8_t channel) {
ADMUX = (1<<ADLAR) | (1<<REFS0) | (0<<REFS1) | (channel & 0x0f);
ADCSRA |= (1<<ADSC); // Start converting
while (((ADCSRA >> ADSC) & 1)) {} //Wait until conversion finished
uint8_t result = ADCH;
//ADCSRA |= (0<<ADSC); // Stop converting
return result;
}
void analogInit() {
ACSR |= (1<<ACD); // Disable analog comparator
/*
Setup ADC
ADMUX: 8 bit mode, Avcc ref
ADCSRA: Enable, 128 prescale
*/
ADMUX = (1<<ADLAR) | (0<<REFS0) | (1<<REFS1);
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) ;
}
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;
}
}