Skip to content

Instantly share code, notes, and snippets.

@a-c-t-i-n-i-u-m
Created February 16, 2015 08:56
Show Gist options
  • Save a-c-t-i-n-i-u-m/b066327e2afb088aa9b6 to your computer and use it in GitHub Desktop.
Save a-c-t-i-n-i-u-m/b066327e2afb088aa9b6 to your computer and use it in GitHub Desktop.
#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