Created
February 16, 2015 08:56
-
-
Save a-c-t-i-n-i-u-m/b066327e2afb088aa9b6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define F_CPU 1000000UL | |
#include <stdio.h> | |
#include <avr/io.h> | |
#include <util/delay.h> | |
#include <avr/interrupt.h> | |
#define DIGITS 6 | |
#define REFRESH_RATE 60 | |
#define IS_ANODE_COMMON | |
#define LONG_PRESS_THRESHOLD_SEC 0.8 | |
#define DAYSECOND 86400 | |
volatile unsigned long current_time = 0; | |
volatile char buf[DIGITS + 1]; | |
void current_time_format(void) | |
{ | |
snprintf( | |
buf, | |
sizeof(buf), | |
"%02u%02u%02u", | |
(unsigned int)(current_time / 3600), | |
(unsigned int)((current_time % 3600) / 60), | |
(unsigned int)(current_time % 60) | |
); | |
} | |
void current_time_increment(unsigned long increments) | |
{ | |
unsigned long a = current_time + increments; | |
if (a >= DAYSECOND) | |
{ | |
current_time = a - DAYSECOND; | |
} | |
else | |
{ | |
current_time = a; | |
} | |
current_time_format(); | |
} | |
void current_time_decrement(unsigned long decrements) | |
{ | |
if (current_time < decrements) | |
{ | |
current_time = DAYSECOND - decrements; | |
} | |
else | |
{ | |
current_time -= decrements; | |
} | |
current_time_format(); | |
} | |
volatile int is_setting_mode = 0; | |
ISR(TIMER1_COMPA_vect) | |
{ | |
if (!is_setting_mode) | |
{ | |
current_time_increment(1); | |
} | |
} | |
ISR(PCINT1_vect) | |
{ | |
_delay_ms(1); | |
int pc0s = PINC & _BV(PC0); | |
int pc1s = PINC & _BV(PC1); | |
int pc2s = PINC & _BV(PC2); | |
if (pc0s == 0) | |
{ | |
is_setting_mode ^= 1; | |
if (!is_setting_mode) | |
{ | |
TCNT1 = 0; | |
} | |
} | |
else if (is_setting_mode && pc1s == 0) | |
{ | |
current_time_increment(1); | |
} | |
else if (is_setting_mode && pc2s == 0) | |
{ | |
current_time_decrement(1); | |
} | |
} | |
int char_to_segment(char input) | |
{ | |
switch (input) | |
{ | |
case '0': | |
return 0b11111100; | |
case '1': | |
return 0b01100000; | |
case '2': | |
return 0b11011010; | |
case '3': | |
return 0b11110010; | |
case '4': | |
return 0b01100110; | |
case '5': | |
return 0b10110110; | |
case '6': | |
return 0b10111110; | |
case '7': | |
return 0b11100100; | |
case '8': | |
return 0b11111110; | |
case '9': | |
return 0b11110110; | |
default: | |
return 0b00000000; | |
} | |
} | |
void Initialize(void) | |
{ | |
// 16bit timer(timer1) interrupt compare A | |
TCCR1B = _BV(WGM12) | _BV(CS11) | _BV(CS10);// clock / 64 | |
OCR1A = 15625;// 1000000 / 64 | |
TIMSK1 = _BV(OCIE1A); | |
// I/O | |
DDRB = 0b11111111; | |
DDRD = 0b11111111; | |
// Pin Change INTerrupt | |
DDRC = 0b00000000; | |
PORTC |= _BV(PC0) | _BV(PC1) | _BV(PC2); | |
PCMSK1 |= _BV(PCINT8) | _BV(PCINT9) | _BV(PCINT10); | |
PCICR |= _BV(PCIE1); | |
// Enable Interrupt | |
sei(); | |
} | |
int main (void) | |
{ | |
Initialize(); | |
unsigned int i; | |
double wait_ms = 1000 / DIGITS / REFRESH_RATE; | |
unsigned long long_press_count_threshold = REFRESH_RATE * LONG_PRESS_THRESHOLD_SEC; | |
unsigned long long_press_count_increase = 0; | |
unsigned long long_press_count_decrease = 0; | |
while(1) | |
{ | |
// long press | |
if (is_setting_mode) | |
{ | |
if (PINC & _BV(PC1)) | |
{ | |
long_press_count_increase = 0; | |
} | |
else | |
{ | |
long_press_count_increase++; | |
} | |
if (PINC & _BV(PC2)) | |
{ | |
long_press_count_decrease = 0; | |
} | |
else | |
{ | |
long_press_count_decrease++; | |
} | |
unsigned int lpc_inc = long_press_count_increase / long_press_count_threshold; | |
unsigned int lpc_dec = long_press_count_decrease / long_press_count_threshold; | |
if (lpc_inc > 4) | |
{ | |
current_time_increment(30); | |
} | |
else if (lpc_inc > 2) | |
{ | |
current_time_increment(15); | |
} | |
else if (lpc_inc > 0) | |
{ | |
current_time_increment(1); | |
} | |
else if (lpc_dec > 4) | |
{ | |
current_time_decrement(30); | |
} | |
else if (lpc_dec > 2) | |
{ | |
current_time_decrement(15); | |
} | |
else if (lpc_dec > 0) | |
{ | |
current_time_decrement(1); | |
} | |
} | |
// output | |
for (i = 0; i < DIGITS; i++) | |
{ | |
PORTD = 1 << (DIGITS - i - 1); | |
#ifdef IS_ANODE_COMMON | |
PORTB = ~(char_to_segment(buf[i]) | (is_setting_mode ? 1 : 0)); | |
#else | |
PORTB = char_to_segment(buf[i]) | (is_setting_mode ? 1 : 0); | |
#endif | |
_delay_ms(wait_ms); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment