Skip to content

Commit 027dd4d

Browse files
committed
Add clock design with digital time and seconds marker
Closes #6
1 parent 44c04bf commit 027dd4d

File tree

3 files changed

+198
-1
lines changed

3 files changed

+198
-1
lines changed

pixelwall/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ OBJECTS = \
2323
design_pong.o \
2424
design_life.o \
2525
design_cm5.o \
26-
design_text_arcade.o
26+
design_text_arcade.o \
27+
design_clock.o
2728

2829
.PHONY: all
2930
all: $(PROGRAM)

pixelwall/design_clock.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3+
Version 2, December 2004
4+
5+
Copyright (C) 2004 Sam Hocevar <[email protected]>
6+
7+
Everyone is permitted to copy and distribute verbatim or modified
8+
copies of this license document, and changing it is allowed as long
9+
as the name is changed.
10+
11+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
12+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
13+
14+
0. You just DO WHAT THE FUCK YOU WANT TO.
15+
*/
16+
17+
#include "pixelwall.h"
18+
19+
// 3x6 seven-segment digit bitmaps (3 bits per row, MSB = col 0)
20+
// Row layout: top bar, upper verticals, middle bar,
21+
// lower verticals, lower verticals, bottom bar
22+
static const uint8_t digitFont[10][6] = {
23+
{0x7, 0x5, 0x5, 0x5, 0x5, 0x7}, // 0
24+
{0x2, 0x6, 0x2, 0x2, 0x2, 0x7}, // 1
25+
{0x7, 0x1, 0x7, 0x4, 0x4, 0x7}, // 2
26+
{0x7, 0x1, 0x7, 0x1, 0x1, 0x7}, // 3
27+
{0x5, 0x5, 0x7, 0x1, 0x1, 0x1}, // 4
28+
{0x7, 0x4, 0x7, 0x1, 0x1, 0x7}, // 5
29+
{0x7, 0x4, 0x4, 0x7, 0x5, 0x7}, // 6
30+
{0x7, 0x1, 0x1, 0x1, 0x1, 0x1}, // 7
31+
{0x7, 0x5, 0x7, 0x5, 0x5, 0x7}, // 8
32+
{0x7, 0x5, 0x7, 0x1, 0x1, 0x7}, // 9
33+
};
34+
35+
#define DIGIT_W 3
36+
#define DIGIT_H 6
37+
#define DIGIT_TOP_ROW 5 // (16 - 6) / 2, vertically centered
38+
39+
// Horizontal column positions for HH:MM layout
40+
// margin(2) + H1(3) + gap(1) + H0(3) + gap(1) + colon(2) + gap(1) + M1(3) + gap(1) + M0(3) + margin(2) = 22
41+
#define COL_H1 2
42+
#define COL_H0 6
43+
#define COL_COLON 10
44+
#define COL_M1 13
45+
#define COL_M0 17
46+
47+
typedef struct {
48+
Color digitColor;
49+
Color markerColor;
50+
} ClockConf;
51+
52+
static ClockConf defaultClockConf = {
53+
.digitColor = GREEN,
54+
.markerColor = GREEN,
55+
};
56+
57+
static void ParseOptions(ClockConf *conf, int argc, char *argv[]) {
58+
int opt;
59+
optind = 1;
60+
while ((opt = getopt(argc, argv, ":T:S:")) != -1) {
61+
switch (opt) {
62+
case 'T': conf->digitColor = ParseColor(optarg); break;
63+
case 'S': conf->markerColor = ParseColor(optarg); break;
64+
}
65+
}
66+
}
67+
68+
static void PrintHelp() {
69+
printf(" -T <color> Digit color (default: green)\n");
70+
printf(" -S <color> Seconds marker color (default: green)\n");
71+
}
72+
73+
static void DrawDigit(Grid *grid, int digit, int startCol, Color color) {
74+
for (int r = 0; r < DIGIT_H; r++) {
75+
uint8_t row = digitFont[digit][r];
76+
for (int c = 0; c < DIGIT_W; c++) {
77+
if (row & (0x4 >> c)) {
78+
Pos pos = {startCol + c, DIGIT_TOP_ROW + r};
79+
GridSetColor(grid, pos, color);
80+
}
81+
}
82+
}
83+
}
84+
85+
static void DrawColon(Grid *grid, int startCol, Color color, int sec) {
86+
// Animated 2x6 colon: two dots that alternate diagonal position
87+
// Even seconds: top-left (#.) and bottom-right (.#)
88+
// Odd seconds: top-right (.#) and bottom-left (#.)
89+
if (sec % 2 == 0) {
90+
GridSetColor(grid, (Pos){startCol, DIGIT_TOP_ROW}, color);
91+
GridSetColor(grid, (Pos){startCol + 1, DIGIT_TOP_ROW + 5}, color);
92+
} else {
93+
GridSetColor(grid, (Pos){startCol + 1, DIGIT_TOP_ROW}, color);
94+
GridSetColor(grid, (Pos){startCol, DIGIT_TOP_ROW + 5}, color);
95+
}
96+
}
97+
98+
static void *Create(Grid *grid, int argc, char *argv[]) {
99+
ClockConf *conf = (ClockConf *)malloc(sizeof(ClockConf));
100+
if (!conf) return NULL;
101+
*conf = defaultClockConf;
102+
ParseOptions(conf, argc, argv);
103+
return conf;
104+
}
105+
106+
static void UpdateFrame(Grid *grid, void *data) {
107+
ClockConf *conf = (ClockConf *)data;
108+
109+
GridFillColor(grid, grid->conf.backgroundColor);
110+
111+
time_t now = time(NULL);
112+
struct tm *t = localtime(&now);
113+
int hour = t->tm_hour;
114+
int min = t->tm_min;
115+
int sec = t->tm_sec;
116+
117+
// Draw digits
118+
DrawDigit(grid, hour / 10, COL_H1, conf->digitColor);
119+
DrawDigit(grid, hour % 10, COL_H0, conf->digitColor);
120+
DrawColon(grid, COL_COLON, conf->digitColor, sec);
121+
DrawDigit(grid, min / 10, COL_M1, conf->digitColor);
122+
DrawDigit(grid, min % 10, COL_M0, conf->digitColor);
123+
124+
// Draw seconds marker: 12 evenly spaced positions around the perimeter
125+
// Corners use L-shaped 3 pixels, edges use 2 pixels
126+
int slot = sec / 5;
127+
Color mc = conf->markerColor;
128+
switch (slot) {
129+
case 0: // :00 top center
130+
GridSetColor(grid, (Pos){10, 0}, mc);
131+
GridSetColor(grid, (Pos){11, 0}, mc);
132+
break;
133+
case 1: // :05 top right
134+
GridSetColor(grid, (Pos){15, 0}, mc);
135+
GridSetColor(grid, (Pos){16, 0}, mc);
136+
break;
137+
case 2: // :10 top-right corner
138+
GridSetColor(grid, (Pos){20, 0}, mc);
139+
GridSetColor(grid, (Pos){21, 0}, mc);
140+
GridSetColor(grid, (Pos){21, 1}, mc);
141+
break;
142+
case 3: // :15 right middle
143+
GridSetColor(grid, (Pos){21, 6}, mc);
144+
GridSetColor(grid, (Pos){21, 7}, mc);
145+
break;
146+
case 4: // :20 bottom-right corner
147+
GridSetColor(grid, (Pos){21, 14}, mc);
148+
GridSetColor(grid, (Pos){21, 15}, mc);
149+
GridSetColor(grid, (Pos){20, 15}, mc);
150+
break;
151+
case 5: // :25 bottom right
152+
GridSetColor(grid, (Pos){15, 15}, mc);
153+
GridSetColor(grid, (Pos){16, 15}, mc);
154+
break;
155+
case 6: // :30 bottom center
156+
GridSetColor(grid, (Pos){10, 15}, mc);
157+
GridSetColor(grid, (Pos){11, 15}, mc);
158+
break;
159+
case 7: // :35 bottom left
160+
GridSetColor(grid, (Pos){5, 15}, mc);
161+
GridSetColor(grid, (Pos){6, 15}, mc);
162+
break;
163+
case 8: // :40 bottom-left corner
164+
GridSetColor(grid, (Pos){1, 15}, mc);
165+
GridSetColor(grid, (Pos){0, 15}, mc);
166+
GridSetColor(grid, (Pos){0, 14}, mc);
167+
break;
168+
case 9: // :45 left middle
169+
GridSetColor(grid, (Pos){0, 7}, mc);
170+
GridSetColor(grid, (Pos){0, 6}, mc);
171+
break;
172+
case 10: // :50 top-left corner
173+
GridSetColor(grid, (Pos){0, 1}, mc);
174+
GridSetColor(grid, (Pos){0, 0}, mc);
175+
GridSetColor(grid, (Pos){1, 0}, mc);
176+
break;
177+
case 11: // :55 top left
178+
GridSetColor(grid, (Pos){5, 0}, mc);
179+
GridSetColor(grid, (Pos){6, 0}, mc);
180+
break;
181+
}
182+
}
183+
184+
static void Destroy(void *data) {
185+
free(data);
186+
}
187+
188+
Design clockDesign = {
189+
.name = "clock",
190+
.PrintHelp = PrintHelp,
191+
.Create = Create,
192+
.UpdateFrame = UpdateFrame,
193+
.Destroy = Destroy,
194+
};

pixelwall/designs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern Design pongDesign;
2525
extern Design lifeDesign;
2626
extern Design cm5Design;
2727
extern Design arcadeDesign;
28+
extern Design clockDesign;
2829

2930
Design *designs[] = {
3031
&snakeDesign,
@@ -34,4 +35,5 @@ Design *designs[] = {
3435
&lifeDesign,
3536
&cm5Design,
3637
&arcadeDesign,
38+
&clockDesign,
3739
};

0 commit comments

Comments
 (0)