Files
nrfwatch/src/watchface.c
T
2026-05-01 11:53:56 +02:00

116 lines
2.8 KiB
C

#include "watchface.h"
#include "fonts.h"
#include <string.h>
static uint8_t framebuffer[WF_BUF_SIZE];
void wf_clear(void)
{
memset(framebuffer, 0xFF, WF_BUF_SIZE);
}
void wf_set_pixel(int x, int y, int black)
{
if (x < 0 || x >= WF_WIDTH || y < 0 || y >= WF_HEIGHT) {
return;
}
int ram_row = (WF_HEIGHT - 1) - y;
int byte_idx = ram_row * WF_LINE_BYTES + (x / 8);
int bit = 7 - (x % 8);
if (black) {
framebuffer[byte_idx] &= ~(1 << bit);
} else {
framebuffer[byte_idx] |= (1 << bit);
}
}
int wf_get_pixel(int x, int y)
{
if (x < 0 || x >= WF_WIDTH || y < 0 || y >= WF_HEIGHT) {
return -1;
}
int ram_row = (WF_HEIGHT - 1) - y;
int byte_idx = ram_row * WF_LINE_BYTES + (x / 8);
int bit = 7 - (x % 8);
return (framebuffer[byte_idx] >> bit) & 1;
}
void wf_draw_glyph(const uint8_t *glyph, int glyph_w, int glyph_h,
int dst_x, int dst_y)
{
int glyph_line_bytes = glyph_w / 8;
for (int row = 0; row < glyph_h; row++) {
for (int byte_col = 0; byte_col < glyph_line_bytes; byte_col++) {
uint8_t val = glyph[row * glyph_line_bytes + byte_col];
for (int bit = 0; bit < 8; bit++) {
if (!(val & (1 << bit))) {
continue;
}
int px = dst_x + byte_col * 8 + (7 - bit);
int py = dst_y + row;
wf_set_pixel(px, py, 1);
}
}
}
}
#define TIME_DIGIT_W FONT_DIGIT_W
#define TIME_DIGIT_H FONT_DIGIT_H
#define TIME_COLON_W FONT_COLON_W
#define TIME_COLON_H FONT_COLON_H
#define TIME_GAP 4
#define TIME_TOTAL_W (4 * TIME_DIGIT_W + TIME_COLON_W + 4 * TIME_GAP)
#define TIME_X_START ((WF_WIDTH - TIME_TOTAL_W) / 2)
#define TIME_Y_START 40
void wf_draw_time(int hours, int minutes)
{
int h1 = (hours / 10) % 10;
int h2 = hours % 10;
int m1 = (minutes / 10) % 10;
int m2 = minutes % 10;
int x = TIME_X_START;
wf_draw_glyph(font_digits[h1], TIME_DIGIT_W, TIME_DIGIT_H, x, TIME_Y_START);
x += TIME_DIGIT_W + TIME_GAP;
wf_draw_glyph(font_digits[h2], TIME_DIGIT_W, TIME_DIGIT_H, x, TIME_Y_START);
x += TIME_DIGIT_W + TIME_GAP;
wf_draw_glyph(font_colon, TIME_COLON_W, TIME_COLON_H, x, TIME_Y_START);
x += TIME_COLON_W + TIME_GAP;
wf_draw_glyph(font_digits[m1], TIME_DIGIT_W, TIME_DIGIT_H, x, TIME_Y_START);
x += TIME_DIGIT_W + TIME_GAP;
wf_draw_glyph(font_digits[m2], TIME_DIGIT_W, TIME_DIGIT_H, x, TIME_Y_START);
}
void wf_draw_battery_indicator(int percent)
{
int bar_w = 30;
int bar_h = 8;
int x_start = WF_WIDTH - bar_w - 10;
int y_start = 10;
for (int x = 0; x < bar_w; x++) {
for (int y = 0; y < bar_h; y++) {
int is_border = (x == 0 || x == bar_w - 1 ||
y == 0 || y == bar_h - 1);
int fill_end = 1 + (percent * (bar_w - 2)) / 100;
int is_filled = (x >= 1 && x < fill_end &&
y >= 1 && y < bar_h - 1);
wf_set_pixel(x_start + x, y_start + y, is_border || is_filled);
}
}
}
uint8_t *wf_get_buffer(void)
{
return framebuffer;
}