Add day of week display
authorNick Downing <nick@ndcode.org>
Thu, 24 Mar 2022 13:44:44 +0000 (00:44 +1100)
committerNick Downing <nick@ndcode.org>
Thu, 24 Mar 2022 13:44:44 +0000 (00:44 +1100)
examples/board_clock_7seg/atmega168_clock_7seg.c
examples/board_clock_7seg/clock_7seg.c

index 2be468b..6348fee 100644 (file)
 #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
@@ -135,7 +135,7 @@ enum EDecimal {
   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
@@ -149,6 +149,20 @@ const uint8_t day_max[12] = {
   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;
 
@@ -190,17 +204,27 @@ static inline void pwmSet(uint8_t pwm)
   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++)
@@ -227,7 +251,7 @@ void decimalInc()
 //   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
@@ -249,7 +273,7 @@ const uint16_t digits2led[10] = {
 //   G
 // E   C
 //   D   DP
-const uint8_t digits2led[10] = {
+const uint8_t digit_to_segments[10] = {
   // GFEDCBA
   0b00111111, // 0
   0b00000110, // 1
@@ -266,6 +290,52 @@ const uint8_t digits2led[10] = {
 #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;
@@ -417,26 +487,33 @@ void updateTimerDisplay()
   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
index 468d034..8b2f233 100644 (file)
@@ -42,7 +42,7 @@
 #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
@@ -50,7 +50,8 @@
 #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
@@ -87,11 +88,14 @@ const float digit_pos[N_DIGITS][3] = {
   {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;