#include <avr/io.h>
void display_on(int);
void decode(int, int);
void delay_1ms();
char get_button();
// Button
int pressed = 1;
int main(void)
{
DDRB = 0xFF; // Cathode (4)
DDRD = 0xFF; // Anode
DDRC = 0b11110000; // 4 Buttons
// Numbers
// Indicate the mode of the clock
// 1: Increase
// 2: Decrease
int mode = 1;
// Numbers
int DIP[4] = {0,0,0,0};
int DOT[4] = {0,0,1,0};
int display = 0;
int value_display = 0;
int count = 0;
int increment = 1;
// Set blink
int stack_blink = 0;
int set = 0;
int BLINK_CONSTANT = 100; // 0.5s encendido 0.5s apagado
int blink_counter = BLINK_CONSTANT;
// Blink stop
int stop_blink = 0;
int BLINK_STOP = 2*5*BLINK_CONSTANT*4;
int stop_counter = BLINK_STOP; // 5s
int display_out = 1; // Out on
// Digit set
int digit = 0;
// Stop: 0
// Start: 1
int status = 0;
char button = ' ';
while(1)
{
// Get button
button = get_button();
// Stop/Start
if (button=='S' && pressed==1){
stack_blink = 0;
if (status==1 && set==0){
status = 0;
}
// Start
else{
status = 1;
set = 0;
}
pressed = 0;
}
// Reset
else if (button=='R' && pressed==1){
mode = 1;
stack_blink = 0;
set = 0;
value_display = 0;
status = 0;
pressed = 0;
}
// Set
else if (button=='T' && pressed==1){
mode = 2;
status = 0;
blink_counter = BLINK_CONSTANT;
if (set==0){
set = 1;
stack_blink = 0;
}
else{
stack_blink += 1;
if (stack_blink==4){
stack_blink = 0;
}
}
pressed = 0;
}
// Increase
else if (button=='I' && pressed==1 && set==1){
digit = (int)(value_display/pow(10, stack_blink))%10;
if (digit==9){
value_display -= 9*pow(10, stack_blink);
}
else{
value_display += pow(10, stack_blink);
}
pressed = 0;
}
// Counter 0-999.9
// 1ms
if (status==1){
if (count==90){
value_display += increment;
count = 0;
}
//Add 1 to counter
count += 1;
}
if (mode==1){
increment = 1;
if (value_display>=10000){
value_display = 0;
// Stop cronometer
status = 0;
}
}
else{
increment = -1;
if (value_display==-1){
value_display = 0;
// Stop cronometer
status = 0;
mode = 1;
// Animation 5 seconds
stop_blink = 1;
stop_counter = BLINK_STOP; // 5seconds
blink_counter = BLINK_CONSTANT*4;
}
}
DIP[3] = value_display%10;
DIP[2] = (int)(value_display/10)%10;
DIP[1] = (int)(value_display/100)%10;
DIP[0] = (int)(value_display/1000)%10;
// Off anode
decode(-1, 0);
if (set==1 && abs(display-3)==stack_blink){
blink_counter -= 1;
if (blink_counter==-1){
blink_counter = BLINK_CONSTANT;
}
if (blink_counter>=BLINK_CONSTANT/2){
display_on(-1);
}
else{
display_on(display);
}
}
else if (set==0 && (stop_blink==1)){
stop_counter -= 1;
if (stop_counter==-1){
stop_blink = 0;
}
// Counter blink
blink_counter -= 1;
if (blink_counter==-1){
blink_counter = BLINK_CONSTANT*2;
if (display_out==1){
display_out = 0;
}
else{
display_out = 1;
}
}
if (display_out){
display_on(display);
}
else{
display_on(-1);
}
}
else{
display_on(display);
}
decode(DIP[display], DOT[display]);
// Multiplexing
display += 1;
if (display==5){
display = 0;
}
delay_1ms();
}
}
void delay_1ms(){
//TCNT1H = 0XE0; //TEMP = 0x85
//TCNT1L = 0xC1;
TCNT1H = 0xC1; //TEMP = 0x85
TCNT1L = 0x81;
//TCNT1H = 0x0B; //TEMP = 0x85
//TCNT1L = 0xDD;
TCCR1A = 0x00; //Normal mode
TCCR1B = 0x01; //Normal mode, 1:256 prescaler
while ((TIFR1&(0x1<<TOV1))==0); //wait for TF0 to roll over
TCCR1B = 0;
TIFR1 = 0x1<<TOV1; //clear TOV1
}
char get_button(){
char mask_C = PINC&0b00001111;
// Start/Stop
if (mask_C==0b00001110){
return 'S';
}
// Reset
else if (mask_C==0b00001101){
return 'R';
}
// Set
else if (mask_C==0b00001011){
return 'T';
}
// Increase
else if (mask_C==0b00000111){
return 'I';
}
else if (mask_C==0b00001111){
pressed = 1;
return ' ';
}
}
void display_on(int number){
switch (number){
case 0:
PORTB = ~0x01;
break;
case 1:
PORTB = ~0x02;
break;
case 2:
PORTB = ~0x04;
break;
case 3:
PORTB = ~0x08;
break;
default:
PORTB = 0xFF;
break;
}
}
void decode(int number, int dot){
switch (number){
case 0:
PORTD = 0b00111111;
break;
case 1:
PORTD = 0b00000110;
break;
case 2:
PORTD = 0b01011011;
break;
case 3:
PORTD = 0b01001111;
break;
case 4:
PORTD = 0b01100110;
break;
case 5:
PORTD = 0b01101101;
break;
case 6:
PORTD = 0b01111101;
break;
case 7:
PORTD = 0b00000111;
break;
case 8:
PORTD = 0b01111111;
break;
case 9:
PORTD = 0b01101111;
break;
default:
PORTD = 0x00;
}
PORTD |= (dot<<7);
}