#include <avr/io.h>
#include <avr/interrupt.h>
unsigned char Hex_Data [] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D,
0x07, 0x7F, 0x67, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};
unsigned adc_value = 0;
int I_flag = 1;
#define BIT(b) (1<<(b))
#define SEQ_COUNT_MAX 16 // hex numbers
#define SW1 3 // PB.3
#define SW2 2 // PB.2
#define SEG_DP 1 // PB.1
#define SEG_G 0 // PB.0
#define BIT_G 0x40 // Bit 7
#define PORTD_OFFSET 0x02 // Skip PORTD[0-1]
#define MIN_DELAY 250
/*
PORTD.[2-7] drive the display bits [a-f]
PORTB.0 drives display bit "g"
PORTB.0 drives display bit "dp" (decimal point)
The display has a common anode, therefore the ports need to
be driven low to activate a segment (i.e., invert the pattern)
PORT A0 senses a potentiometer that spans 0V to 5V; The ADC
can be used to measure the position on a scale of 0 - 1023
*/
int main(void)
{
DDRD = 0xff; // output
DDRB = 0x03; // output on pb.1 and pb.2
PORTB = 0x0c; // pb.3, pb.4 pull up
int index = 0;
unsigned char comp;
ADCSRA = 0x8F; //enable ADC, enable interrupts, prescale 128
ADMUX = 0x60; //VCC ref, ADC on channel 0 (pin A0), left justify bits
ADCSRA |=(1<<ADSC); //start conversion
sei(); //enable global interrupt
while(1)
{
if(I_flag) //check if ADC data ready
{
ADCSRA |=(1<<ADSC); //reset ADC
I_flag = 0; //clear flag
}
//PORTD = adc_value << PORTD_OFFSET;
comp = ~Hex_Data[index];
PORTD = comp << PORTD_OFFSET;
if ( (comp & (1<<6)) ==(1<<6))// if the bit is set on the data, then set it on the port
PORTB |= 1;
else //otherwise clear bit
PORTB &= ~1;
if ( (comp & (1<<7)) ==(1<<7))
PORTB |= (1<<1);
else
PORTB &= ~(1<<1);
if (PINB & (1<<SW2))
{
index++; //increment index
if (index >=16)// make sure index only has values 0-15 for hexidemical
{
index = 0;
}
if(PINB &(1<<SW1)) //delay 1 sec when switch 1 is high
{
timer_delay(1000);
}
else
{
//map adc_value to .25s - 1.25s, and delay that time
timer_delay((((int)adc_value*1000)/16)+MIN_DELAY);
}
}
else
{
index = adc_value;
}
}
}
void timer_delay(unsigned msecs){
TCNT1 = 0xffff -(0x0010 * msecs); //timer counts down, take max
TCCR1A = 0x00;
TCCR1B = 0x05;
while((TIFR1 &(1<<TOV1))==0);
TCCR1B = 0;
TIFR1 = 1<<TOV1;
}
ISR(ADC_vect)
{
adc_value = ADCH >>4;//take 4 MSB
I_flag = 1; //set flag for main loop
}