116 lines
2.8 KiB
C
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;
|
|
}
|