rushabhcodes/desk-fidget-counter
A desk knob assembly combining a circuit board with PETG-printed mechanical parts and vendor CAD-modeled hardware.
- Version
- 5.6.1
- License
- MIT
- Stars
- 0
firmware/lcd_ui.c
// SPDX-License-Identifier: MIT
#include "counter.h"
#include "lcd.h"
#include <string.h>
#include <stdio.h>
// Original compact 5x7 bitmap alphabet, rows packed as five bits.
static const struct {
char c;
uint8_t rows[7];
} font[] = {
{'0', {14, 17, 19, 21, 25, 17, 14}}, {'1', {4, 12, 4, 4, 4, 4, 14}},
{'2', {14, 17, 1, 2, 4, 8, 31}}, {'3', {30, 1, 1, 14, 1, 1, 30}},
{'4', {2, 6, 10, 18, 31, 2, 2}}, {'5', {31, 16, 16, 30, 1, 1, 30}},
{'6', {14, 16, 16, 30, 17, 17, 14}}, {'7', {31, 1, 2, 4, 8, 8, 8}},
{'8', {14, 17, 17, 14, 17, 17, 14}}, {'9', {14, 17, 17, 15, 1, 1, 14}},
{'A', {14, 17, 17, 31, 17, 17, 17}}, {'B', {30, 17, 17, 30, 17, 17, 30}},
{'C', {14, 17, 16, 16, 16, 17, 14}}, {'D', {30, 17, 17, 17, 17, 17, 30}},
{'E', {31, 16, 16, 30, 16, 16, 31}}, {'F', {31, 16, 16, 30, 16, 16, 16}},
{'G', {14, 17, 16, 23, 17, 17, 14}}, {'H', {17, 17, 17, 31, 17, 17, 17}},
{'I', {14, 4, 4, 4, 4, 4, 14}}, {'K', {17, 18, 20, 24, 20, 18, 17}},
{'W', {17, 17, 17, 21, 21, 21, 10}}, {'L', {16, 16, 16, 16, 16, 16, 31}},
{'M', {17, 27, 21, 21, 17, 17, 17}}, {'N', {17, 25, 21, 19, 17, 17, 17}},
{'O', {14, 17, 17, 17, 17, 17, 14}}, {'P', {30, 17, 17, 30, 16, 16, 16}},
{'R', {30, 17, 17, 30, 20, 18, 17}}, {'S', {15, 16, 16, 14, 1, 1, 30}},
{'T', {31, 4, 4, 4, 4, 4, 4}}, {'U', {17, 17, 17, 17, 17, 17, 14}},
{'V', {17, 17, 17, 17, 17, 10, 4}}, {'Y', {17, 17, 10, 4, 4, 4, 4}},
{':', {0, 6, 6, 0, 6, 6, 0}}, {'%', {17, 2, 4, 4, 8, 16, 17}},
{'.', {0, 0, 0, 0, 0, 6, 6}}, {'-', {0, 0, 0, 31, 0, 0, 0}}};
static void text(uint16_t row[240], unsigned y, const char *s, unsigned top,
unsigned scale, uint16_t color) {
if (y < top || y >= top + 7 * scale)
return;
int left = (240 - (int)strlen(s) * 6 * (int)scale + (int)scale) / 2;
unsigned line = (y - top) / scale;
for (unsigned i = 0; s[i]; i++) {
uint8_t bits = 0;
for (unsigned k = 0; k < sizeof(font) / sizeof(font[0]); k++)
if (font[k].c == s[i]) {
bits = font[k].rows[line];
break;
}
for (unsigned col = 0; col < 5; col++)
if (bits & (16u >> col))
for (unsigned dx = 0; dx < scale; dx++) {
int x = left + (int)(i * 6 * scale + col * scale + dx);
if (x >= 0 && x < 240)
row[x] = color;
}
}
}
void lcd_render_row(const LcdView *v, unsigned y, uint16_t row[240]) {
const uint16_t bg=0x0863, white=0xe71c, gold=0xfdea, mint=0x6f39, red=0xfa88;
for (unsigned x=0;x<240;x++) row[x]=bg;
if (y>=240) return;
bool live=dashboard_fresh(&v->host,v->now);
char b[40];
if (live) {
unsigned yr,mo,day; dashboard_date(&v->host,v->now,&yr,&mo,&day);
snprintf(b,sizeof b,"%04u-%02u-%02u",yr,mo,day);
} else strcpy(b,"LAPTOP DASHBOARD");
text(row,y,b,24,1,mint);
if (live) {
unsigned s=dashboard_seconds(&v->host,v->now);
snprintf(b,sizeof b,"%02u:%02u:%02u",s/3600,s/60%60,s%60);
} else strcpy(b,"--:--:--");
text(row,y,b,42,3,gold);
for (unsigned i=0;i<2;i++) {
unsigned value=i?v->host.ram_tenths:v->host.cpu_tenths, top=83+i*29;
if (live) snprintf(b,sizeof b,"%s %3u.%u%%",i?"RAM":"CPU",value/10,value%10);
else snprintf(b,sizeof b,"%s --.-%%",i?"RAM":"CPU");
text(row,y,b,top,2,white);
if (y>=top+17 && y<top+20)
for (unsigned x=54;x<186;x++) row[x]=live && x-54<value*132/1000?mint:0x2188;
}
if (!live) strcpy(b,"HOST OFFLINE");
else if (v->host.battery_percent<0) strcpy(b,"NO HOST BATTERY");
else snprintf(b,sizeof b,"HOST %d%% %s",v->host.battery_percent,v->host.ac?"AC":"BAT");
text(row,y,b,147,live && v->host.battery_percent<0?1:2,
live && v->host.battery_percent>=0 && v->host.battery_percent<15 && !v->host.ac?red:white);
text(row,y,"TURNS",175,1,mint);
counter_format_total(v->turns,b);
text(row,y,b,186,strlen(b)<=10?2:1,gold);
const char *state = !v->encoder_ok ? "TIMER ERROR" :
v->hold_ms>=500 ? (v->storage_ok?"HOLD TO CLEAR":"HOLD TO INIT") :
!v->storage_ok ? "HOLD 3S TO INIT" :
v->count_cleared ? "COUNT CLEARED" :
v->scroll_on ? "SCROLL MODE" : "COUNT MODE";
text(row,y,state,210,1,!v->storage_ok || !v->encoder_ok ? red:mint);
if (v->hold_ms>=500 && y>=222 && y<225)
for(unsigned x=84;x<156;x++) row[x]=x-84<v->hold_ms*72/3000?gold:0x2188;
}
