summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@ka-ata-killa.ourano.james.local>2021-03-08 16:50:43 +0000
committerroot <root@ka-ata-killa.ourano.james.local>2021-03-08 16:51:35 +0000
commit11623a5ced1a64264d43f1f844c1cf5f34562581 (patch)
treed63c64852bd56eaf9526495d79696017f3564a10
parent03486e52a2dde8ade759f36fea8b403b6524451c (diff)
downloadclock-11623a5ced1a64264d43f1f844c1cf5f34562581.tar.gz
clock-11623a5ced1a64264d43f1f844c1cf5f34562581.tar.bz2
clock-11623a5ced1a64264d43f1f844c1cf5f34562581.zip
make display code nicer, show some other useful things
-rw-r--r--app/max7219.c300
1 files changed, 154 insertions, 146 deletions
diff --git a/app/max7219.c b/app/max7219.c
index 6cd93f3..add2044 100644
--- a/app/max7219.c
+++ b/app/max7219.c
@@ -9,6 +9,11 @@
#define MOSI (GPIO5)
#define MOSI_PORT GPIOB
+#define N_DISPLAYS 3
+#define N_DIGITS 8
+
+static uint8_t fb[N_DISPLAYS][N_DIGITS];
+
static void
set (int sck, int ncs, int mosi)
@@ -73,54 +78,66 @@ unlock (void)
static void
write_reg (uint8_t reg, uint8_t data)
{
+ unsigned i;
+
while (lock());
set (0, 1, 0);
set (0, 0, 0);
- spip_send_8 (reg);
- spip_send_8 (data);
-
- spip_send_8 (reg);
- spip_send_8 (data);
-
- spip_send_8 (reg);
- spip_send_8 (data);
+ for (i = 0; i < N_DISPLAYS; ++i) {
+ spip_send_8 (reg);
+ spip_send_8 (data);
+ }
set (0, 0, 0);
set (0, 1, 0);
unlock();
}
+static void cls (void)
+{
+ unsigned i;
+
+ for (i = 0; i < N_DISPLAYS; ++i)
+ memset (&fb[i], 0, N_DIGITS);
+}
+
+
+
static void
-_write_regs (uint8_t reg, uint8_t *data)
+refresh (void)
{
+ static uint8_t last_brightness = 255;
+ unsigned i, j;
+
+ if (last_brightness != pot_brightness) {
+ last_brightness = pot_brightness;
+ write_reg (0xa, last_brightness);
+ }
+
+
while (lock());
- set (0, 1, 0);
- set (0, 0, 0);
+ for (j = 0; j < N_DIGITS; ++j) {
+ set (0, 1, 0);
+ set (0, 0, 0);
- spip_send_8 (reg);
- spip_send_8 (data[2]);
+ i = N_DISPLAYS - 1;
- spip_send_8 (reg);
- spip_send_8 (data[1]);
+ do {
+ spip_send_8 (N_DIGITS - j);
+ spip_send_8 (fb[i][j]);
+ } while (i--);
- spip_send_8 (reg);
- spip_send_8 (data[0]);
+ set (0, 0, 0);
+ set (0, 1, 0);
+ }
- set (0, 0, 0);
- set (0, 1, 0);
unlock();
}
-static void write_regs (uint8_t reg, uint8_t d1, uint8_t d2, uint8_t d3)
-{
- uint8_t d[3] = {d1, d2, d3};
- _write_regs (reg, d);
-}
-
#define SDP 0x80
#define SA 0x40
@@ -254,113 +271,49 @@ static uint8_t hex (unsigned v)
return 0;
}
-
-static void _write_triad (uint8_t reg, int *d, int *dp)
+static void write_dd (int u, unsigned x, unsigned y)
{
+ unsigned t;
- uint8_t regs0[3] = {0x0, 0x0, 0x0};
- uint8_t regs1[3] = {0x0, 0x0, 0x0};
- unsigned i;
-
- for (i = 0; i < 3; ++i) {
+ if (u < 0) return;
- if (d[i] < 0) continue;
+ if (u > 99) return;
- if (d[i] > 99) continue;
+ t = u / 10;
+ u %= 10;
- regs0[i] = hex (d[i] % 10);
- regs1[i] = hex (d[i] / 10);
- }
-
- for (i = 0; i < 3; ++i)
- if (dp[i]) regs0[i] |= SDP;
-
-
- _write_regs (reg++, regs0);
- _write_regs (reg, regs1);
+ fb[y][x] = hex (t);
+ fb[y][x + 1] = hex (u);
}
-static void write_triad (uint8_t reg, int d1, int d2, int d3, int dp1, int dp2, int dp3)
-{
- int d[3] = {d1, d2, d3};
- int dp[3] = {dp1, dp2, dp3};
- _write_triad (reg, d, dp);
-}
-static void _write_triad_h (uint8_t reg, int *d, int *dp)
+static void write_string (const char *s, unsigned x, unsigned y)
{
- uint8_t regs0[3] = {0x0, 0x0, 0x0};
- uint8_t regs1[3] = {0x0, 0x0, 0x0};
- unsigned i;
-
- for (i = 0; i < 2; ++i) {
-
- if (d[i] < 0) continue;
- if (d[i] > 99) continue;
+ for (; (x < N_DIGITS) && *s; s++, x++) {
+ fb[y][x] = hex (*s);
- regs0[i] = hex (d[i] % 10);
- regs1[i] = hex (d[i] / 10);
+ if (* (s + 1) == '.') {
+ fb[y][x] |= SDP;
+ s++;
+ }
}
-
- do {
- if (d[i] < 0) continue;
-
- if (d[i] > 0x100) continue;
-
- regs0[i] = hex (d[i] & 0xf);
- regs1[i] = hex (d[i] >> 4);
- } while (0);
-
- for (i = 0; i < 3; ++i)
- if (dp[i]) regs0[i] |= SDP;
-
-
- _write_regs (reg++, regs0);
- _write_regs (reg, regs1);
}
-static void write_triad_h (uint8_t reg, int d1, int d2, int d3, int dp1, int dp2, int dp3)
+static inline void write_dp (unsigned x, unsigned y)
{
- int d[3] = {d1, d2, d3};
- int dp[3] = {dp1, dp2, dp3};
-
- _write_triad_h (reg, d, dp);
+ fb[y][x] |= SDP;
}
-static void write_string_over_numbers (char *str, int d1, int d2, int d3, int d4)
-{
- unsigned reg;
-
- uint8_t digits[9] = {
- 0,
- hex (d4 % 10),
- hex (d4 / 10),
- hex (d3 % 10) | SDP,
- hex (d3 / 10),
- hex (d2 % 10) | SDP,
- hex (d2 / 10),
- hex (d1 % 10) | SDP,
- hex (d1 / 10)
- };
-
- for (reg = 8; reg && *str; reg--, str++)
- write_regs (reg, hex (*str) | (!str[1] ? SDP : 0), digits[reg], 0);
-
- for (; reg; reg--)
- write_regs (reg, 0, digits[reg], 0);
-}
-
void
max7219_init (int on)
{
- uint8_t d[3] = {0xf, 0xf, 0xf};
unsigned i;
MAP_OUTPUT_PP (SCK);
@@ -376,12 +329,11 @@ max7219_init (int on)
write_reg (0xf, 0x0); //normal mode
write_reg (0x9, 0x0); //no decode
- write_reg (0xb, 0x7); //8 digits
+ write_reg (0xb, N_DIGITS - 1); //8 digits
write_reg (0xa, pot_brightness);
- for (i = 1; i <= 8; ++i)
- _write_regs (i, d);
-
+ for (i = 0; i < N_DIGITS; ++i)
+ write_reg (N_DIGITS - i, 0x0);
} else {
write_reg (0xc, 0x0); //Power up
@@ -420,72 +372,128 @@ void max7219_report_svin (int valid, int active)
}
+static const char *day_name[] = {"su", "mo", "tu", "we", "th", "fr", "sa"};
+
void max7219_dispatch (void)
{
uint64_t abs = ref_get();
- static uint8_t last_brightness = 255;
+ char buf[32];
int wday;
EPOCH e;
UTC u;
UTC gu;
ST l;
+ unsigned i;
+ uint64_t wot;
- if (last_brightness != pot_brightness) {
- last_brightness = pot_brightness;
- write_reg (0xa, last_brightness);
- }
+ cls();
if (gps_initting)
- write_string_over_numbers ("gps init", 0, 0, 0, 0);
- else if (!ref_valid)
- write_string_over_numbers ("gps acq", gps_sats_searching, gps_sats_inop, gps_sats_locked, gps_sats_with_e);
-
- else {
- static unsigned m;
-
+ write_string ("gps init", 0, 0);
+
+ else if (!ref_valid) {
+ write_string ("gps acq.", 0, 0);
+ write_dd (gps_sats_searching, 0, 1);
+ write_dp (1, 1);
+ write_dd (gps_sats_inop, 2, 1);
+ write_dp (3, 1);
+ write_dd (gps_sats_locked, 4, 1);
+ write_dp (5, 1);
+ write_dd (gps_sats_with_e, 6, 1);
+ } else {
e = ref_decompose (abs);
u = time_epoch_to_utc (e);
+
+ write_dd (u.hour, 0, 0);
+ write_dp (1, 0);
+ write_dd (u.minute, 2, 0);
+ write_dp (3, 0);
+ write_dd (u.second, 4, 0);
+ write_dp (5, 0);
+ write_dd (u.nanosecond / 10000000, 6, 0);
+
+
l = time_utc_to_lst (u, gps_lon);
- if (have_lock) {
+ write_dd (l.hour, 0, 1);
+ write_dp (1, 1);
+ write_dd (l.minute, 2, 1);
+ write_dp (3, 1);
+ write_dd (l.second, 4, 1);
+ write_dp (5, 1);
+ write_dd (l.nanosecond / 10000000, 6, 1);
+
+ wot = e.s;
+ wot /= 4;
+ wot %= 4;
+
+ switch (wot) {
+ case 0:
+
+ if (!have_lock) break;
+
e.s += 86400;
e.s += gps_utc_diff;
gu = time_epoch_to_utc (e);
- } else {
- gu.hour = 100;
- gu.minute = 100;
- gu.second = 100;
- }
- write_triad (1, u.nanosecond / 10000000, l.nanosecond / 10000000, gu.second, time_lock_enabled, have_time_lock, have_dgps);
- write_triad (3, u.second, l.second, gu.minute, 1, 1, 1);
- write_triad (5, u.minute, l.minute, gu.hour, 1, 1, 1);
- write_triad_h (7, u.hour, l.hour, (if0.ip_addr.addr >> 24) & 0xff, 1, 1, 1);
- if (u.minute == m) return;
+ wday = gps_wday;
+
+ if (wday < 0) wday = 0;
+
+ if (wday > 6) wday = 6;
+
+
+ write_string (day_name[wday], 0, 2);
+ write_dp (1, 2);
+ write_dd (gu.hour, 2, 2);
+ write_dp (3, 2);
+ write_dd (gu.minute, 4, 2);
+ write_dp (5, 2);
+ write_dd (gu.second, 6, 2);
+
+ break;
- m = u.minute;
+ case 1:
+ if (!have_lock) break;
- printf ("LEDS: %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d %02x.%02d.%02d.%02d lon %.6f\r\n",
- u.hour, u.minute, u.second,
- u.nanosecond / 10000000,
- l.hour,
- l.minute,
- l.second,
- l.nanosecond / 10000000,
- (int) ((if0.ip_addr.addr >> 24) & 0xff),
- gu.hour,
- gu.minute,
- gu.second,
- gps_lon);
+ snprintf (buf, sizeof (buf), "%.8f", gps_lat);
+ buf[sizeof (buf) - 1] = 0;
+ write_string (buf, 0, 2);
+ break;
+ case 2:
+ if (!have_lock) break;
+
+ snprintf (buf, sizeof (buf), "%.8f", gps_lon);
+ buf[sizeof (buf) - 1] = 0;
+ write_string (buf, 0, 2);
+ break;
+
+ case 3:
+
+
+ for (i = 0; i < 8; ++i)
+ fb[2][i ^ 1] = hex ((if0.ip_addr.addr >> (i << 2)) & 0xf);
+
+ break;
+ }
}
+ if (time_lock_enabled) write_dp (7, 0);
+ if (have_time_lock) write_dp (7, 1);
+
+ if (have_dgps) write_dp (7, 2);
+
+
+ refresh();
}
+
+
pan> * FXRSTOR can fault if passed a corrupted data block. We handle this * possibility, which may occur if the block was passed to us by control * tools, by silently clearing the block. */ if ( cpu_has_fxsr ) { asm volatile ( #ifdef __i386__ "1: fxrstor %0 \n" #else /* __x86_64__ */ /* See above for why the operands/constraints are this way. */ "1: " REX64_PREFIX "fxrstor (%2)\n" #endif ".section .fixup,\"ax\" \n" "2: push %%"__OP"ax \n" " push %%"__OP"cx \n" " push %%"__OP"di \n" " lea %0,%%"__OP"di \n" " mov %1,%%ecx \n" " xor %%eax,%%eax \n" " rep ; stosl \n" " pop %%"__OP"di \n" " pop %%"__OP"cx \n" " pop %%"__OP"ax \n" " jmp 1b \n" ".previous \n" ".section __ex_table,\"a\"\n" " "__FIXUP_ALIGN" \n" " "__FIXUP_WORD" 1b,2b \n" ".previous \n" : : "m" (*fpu_ctxt), "i" (sizeof(v->arch.guest_context.fpu_ctxt)/4) #ifdef __x86_64__ ,"cdaSDb" (fpu_ctxt) #endif ); } else { asm volatile ( "frstor %0" : : "m" (v->arch.guest_context.fpu_ctxt) ); } } /* * Maximum size (in byte) of the XSAVE/XRSTOR save area required by all * the supported and enabled features on the processor, including the * XSAVE.HEADER. We only enable XCNTXT_MASK that we have known. */ u32 xsave_cntxt_size; /* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */ u32 xfeature_low, xfeature_high; void xsave_init(void) { u32 eax, ebx, ecx, edx; int cpu = smp_processor_id(); u32 min_size; cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); printk("%s: cpu%d: cntxt_max_size: 0x%x and states: %08x:%08x\n", __func__, cpu, ecx, edx, eax); if ( ((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE) || ((eax & XSTATE_YMM) && !(eax & XSTATE_SSE)) ) { BUG(); } /* FP/SSE, XSAVE.HEADER, YMM */ min_size = 512 + 64 + ((eax & XSTATE_YMM) ? XSTATE_YMM_SIZE : 0); BUG_ON(ecx < min_size); /* * We will only enable the features we know for hvm guest. Here we use * set/clear CR4_OSXSAVE and re-run cpuid to get xsave_cntxt_size. */ set_in_cr4(X86_CR4_OSXSAVE); set_xcr0(eax & XCNTXT_MASK); cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx); clear_in_cr4(X86_CR4_OSXSAVE); if ( cpu == 0 ) { /* * xsave_cntxt_size is the max size required by enabled features. * We know FP/SSE and YMM about eax, and nothing about edx at present. */ xsave_cntxt_size = ebx; xfeature_low = eax & XCNTXT_MASK; xfeature_high = 0; printk("%s: using cntxt_size: 0x%x and states: %08x:%08x\n", __func__, xsave_cntxt_size, xfeature_high, xfeature_low); } else { BUG_ON(xsave_cntxt_size != ebx); BUG_ON(xfeature_low != (eax & XCNTXT_MASK)); } } void xsave_init_save_area(void *save_area) { memset(save_area, 0, xsave_cntxt_size); ((u16 *)save_area)[0] = 0x37f; /* FCW */ ((u16 *)save_area)[2] = 0xffff; /* FTW */ ((u32 *)save_area)[6] = 0x1f80; /* MXCSR */ ((struct xsave_struct *)save_area)->xsave_hdr.xstate_bv = XSTATE_FP_SSE; } /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */