#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>
-
+#include <stdbool.h>
#include "atmega168_clock_7seg.h"
// for linker, emulator, and programmer's sake
#include "avr_mcu_section.h"
AVR_MCU(F_CPU, "atmega168");
-#define N_DIGITS 14
+#define N_DIGITS 17
#define USE_17SEG 1
#if USE_17SEG
#define BYTES_PER_DIGIT 3
D_SECOND = 0, D_MINUTE, D_HOUR, D_DAY, D_MONTH, D_YEAR, D_MAX
};
const uint8_t decimal_max[D_MAX] = {60, 60, 24, 31, 12, 200};
-const uint8_t day_max[12] = {
+const uint8_t month_len[12] = {
31, // Jan
28, // Feb
31, // Mar
30, // Nov
31, // Dec
};
+const uint8_t month_weekday[12] = {
+ 0, // Jan
+ 31 % 7, // Feb
+ (31 + 28) % 7, // Mar
+ (31 + 28 + 31) % 7, // Apr
+ (31 + 28 + 31 + 30) % 7, // May
+ (31 + 28 + 31 + 30 + 31) % 7, // Jun
+ (31 + 28 + 31 + 30 + 31 + 30) % 7, // Jul
+ (31 + 28 + 31 + 30 + 31 + 30 + 31) % 7, // Aug
+ (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31) % 7, // Sep
+ (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30) % 7, // Oct
+ (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31) % 7, // Nov
+ (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30) % 7, // Dec
+};
uint8_t decimal[D_MAX] = {0, 0, 0, 0, 0, 0};
uint8_t decimalChanged = 0;
OCR0A = pwm;
}
+bool isLeap(uint8_t year) {
+ return (year & 3) == 0 && year % 100 != 0;
+}
uint8_t dayMax(uint8_t month, uint8_t year) {
- int max = day_max[month];
- if (month == 1 && (year & 3) == 0 && year % 100 != 0)
- ++max;
- return max;
+ return month_len[month] + (month == 1 && isLeap(year));
+}
+
+uint8_t weekDay(uint8_t day, uint8_t month, uint8_t year) {
+ return (
+ day +
+ month_weekday[month] +
+ (month >= 2 && isLeap(year)) +
+ (year >> 2) -
+ year / 100
+ ) % 7;
}
void decimalInc()
{
-#if 0 // for testing day/month/year increments
+#if 1 // for testing day/month/year increments
for (uint8_t in = D_DAY; in < D_MAX; in++)
#else
for (uint8_t in = 0; in < D_MAX; in++)
// G1 G2
// E N M L C
// D1 D2 DP
-const uint16_t digits2led[10] = {
+const uint16_t digit_to_segments[10] = {
//NMLKJHGGFEDDCBAA
// 21 21 21
0b0000000011111111, // 0
// G
// E C
// D DP
-const uint8_t digits2led[10] = {
+const uint8_t digit_to_segments[10] = {
// GFEDCBA
0b00111111, // 0
0b00000110, // 1
#define SEG_h 0b01110100
#endif
+// A1 A2
+// F H J K B
+// G1 G2
+// E N M L C
+// D1 D2 DP
+// note: table starts with Saturday for 1/1/2000
+const uint16_t weekday_to_segments[7][3] = {
+ // NMLKJHGGFEDDCBAA
+ // 21 21 21
+ {
+ 0b0000001110111011, // S
+ 0b0000001111001111, // A
+ 0b0100100000000011, // T
+ },
+ {
+ 0b0000001110111011, // S
+ 0b0000000011111100, // U
+ 0b0010010011001100, // N
+ },
+ {
+ 0b0001010011001100, // M
+ 0b0000000011111111, // O
+ 0b0010010011001100, // N
+ },
+ {
+ 0b0100100000000011, // T
+ 0b0000000011111100, // U
+ 0b0000001111110011, // E
+ },
+ {
+ 0b1010000011001100, // W
+ 0b0000001111110011, // E
+ 0b0100100000111111, // D
+ },
+ {
+ 0b0100100000000011, // T
+ 0b0000001111001100, // H
+ 0b0000000011111100, // U
+ },
+ {
+ 0b0000001111000011, // F
+ 0b0010001111000111, // R
+ 0b0100100000110011, // I
+ },
+};
+
struct {
uint8_t b[N_DIGITS * BYTES_PER_DIGIT];
uint8_t in;
switch (state & ~state_IncrementTime) {
case state_ShowTime: {
uint16_t year = decimal[D_YEAR] + 2000;
- digits[0] = digits2led[year % 10];
+ digits[0] = digit_to_segments[year % 10];
year /= 10;
- digits[1] = digits2led[year % 10];
+ digits[1] = digit_to_segments[year % 10];
year /= 10;
- digits[2] = digits2led[year % 10];
+ digits[2] = digit_to_segments[year % 10];
year /= 10;
- digits[3] = digits2led[year];
+ digits[3] = digit_to_segments[year];
uint8_t temp = decimal[D_MONTH] + 1;
- digits[4] = digits2led[temp % 10] | SEG_DP;
- digits[5] = digits2led[temp / 10];
+ digits[4] = digit_to_segments[temp % 10] | SEG_DP;
+ digits[5] = digit_to_segments[temp / 10];
+
/*uint8_t*/ temp = decimal[D_DAY] + 1;
- digits[6] = digits2led[temp % 10] | SEG_DP;
- digits[7] = digits2led[temp / 10];
- digits[8] = digits2led[decimal[D_SECOND] % 10];
- digits[9] = digits2led[decimal[D_SECOND] / 10];
- digits[10] = digits2led[decimal[D_MINUTE] % 10];
- digits[11] = digits2led[decimal[D_MINUTE] / 10];
- digits[12] = digits2led[decimal[D_HOUR] % 10];
- digits[13] = digits2led[decimal[D_HOUR] / 10];
+ digits[6] = digit_to_segments[temp % 10] | SEG_DP;
+ digits[7] = digit_to_segments[temp / 10];
+
+ temp = weekDay(decimal[D_DAY], decimal[D_MONTH], decimal[D_YEAR]);
+ digits[8] = weekday_to_segments[temp][2];
+ digits[9] = weekday_to_segments[temp][1];
+ digits[10] = weekday_to_segments[temp][0];
+
+ digits[11] = digit_to_segments[decimal[D_SECOND] % 10];
+ digits[12] = digit_to_segments[decimal[D_SECOND] / 10];
+ digits[13] = digit_to_segments[decimal[D_MINUTE] % 10];
+ digits[14] = digit_to_segments[decimal[D_MINUTE] / 10];
+ digits[15] = digit_to_segments[decimal[D_HOUR] % 10];
+ digits[16] = digit_to_segments[decimal[D_HOUR] / 10];
if (!(state & state_IncrementTime))
digits[0] |= SEG_DP; // mapped to colon
#include "button.h"
#include "hc595.h"
-#define N_DIGITS 14
+#define N_DIGITS 17
#define ORIGIN_X 50.f
#define ORIGIN_Y 50.f
#define DIGIT_WIDTH 320.f
#define LINE_HEIGHT 525.f
#define COLON_X (ORIGIN_X + 2.f * DIGIT_WIDTH)
#define COLON_Y (ORIGIN_Y + .6f * LINE_HEIGHT)
-#define WINDOW_X (ORIGIN_X + 5.f * DIGIT_WIDTH + 1.5f * COLON_WIDTH)
+//#define WINDOW_X (ORIGIN_X + 5.f * DIGIT_WIDTH + 1.5f * COLON_WIDTH)
+#define WINDOW_X (ORIGIN_X + 5.5f * DIGIT_WIDTH + .5f * COLON_WIDTH)
#define WINDOW_Y (ORIGIN_Y + 1.5f * LINE_HEIGHT)
#define USE_17SEG 1
{ORIGIN_X, ORIGIN_Y, .5f},
{ORIGIN_X + .5f * DIGIT_WIDTH, ORIGIN_Y, .5f},
{ORIGIN_X + 1.f * DIGIT_WIDTH, ORIGIN_Y, .5f},
- {ORIGIN_X + 1.5f * DIGIT_WIDTH, ORIGIN_Y, .5f},
- {ORIGIN_X + 2.f * DIGIT_WIDTH, ORIGIN_Y, .5f},
- {ORIGIN_X + 2.5f * DIGIT_WIDTH, ORIGIN_Y, .5f},
- {ORIGIN_X + 3.f * DIGIT_WIDTH, ORIGIN_Y, .5f},
- {ORIGIN_X + 3.5f * DIGIT_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 1.5f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 2.f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 2.5f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 3.f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 3.5f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 4.f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 4.5f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
+ {ORIGIN_X + 5.f * DIGIT_WIDTH + .5f * COLON_WIDTH, ORIGIN_Y, .5f},
};
int display_flag = 0;