From db44d3dbab15f23b1783bf90d8224209548a700b Mon Sep 17 00:00:00 2001 From: true Date: Wed, 16 Oct 2024 00:10:05 -0700 Subject: [PATCH] get oled, menus, rgbled, and most everything else building will it work? almost certainly not. but it does build cleanly now. lightsense is stubbed for the time being. rgbled does _not_ render the programs. I am going to redo how this works. the data (which will be empty) is sent though. --- nametag8_CH592/user/hw/lightsense.c | 22 ++ nametag8_CH592/user/hw/lightsense.h | 11 + nametag8_CH592/user/led/rgbled.c | 53 ++++- nametag8_CH592/user/led/rgbled.h | 11 +- .../user/led/{rgbled_edge.c => rgbled_prog.c} | 204 +++++++++--------- nametag8_CH592/user/main.c | 183 +++++++++++++++- nametag8_CH592/user/misc/accel.c | 51 ++++- nametag8_CH592/user/misc/accel.h | 3 +- nametag8_CH592/user/ui/menu_entry_0.c | 4 +- nametag8_CH592/user/ui/menu_entry_2.c | 16 +- nametag8_CH592/user/ui/menu_entry_5.c | 6 +- nametag8_CH592/user/ui/menu_entry_6.c | 28 +-- nametag8_CH592/user/ui/oled.c | 15 ++ nametag8_CH592/user/ui/oled.h | 19 ++ nametag8_CH592/user/user_config.c | 10 +- nametag8_CH592/user/user_config.h | 12 +- 16 files changed, 493 insertions(+), 155 deletions(-) rename nametag8_CH592/user/led/{rgbled_edge.c => rgbled_prog.c} (73%) create mode 100644 nametag8_CH592/user/ui/oled.c create mode 100644 nametag8_CH592/user/ui/oled.h diff --git a/nametag8_CH592/user/hw/lightsense.c b/nametag8_CH592/user/hw/lightsense.c index 0aba5b9..ba22f8c 100644 --- a/nametag8_CH592/user/hw/lightsense.c +++ b/nametag8_CH592/user/hw/lightsense.c @@ -5,4 +5,26 @@ * Author: true */ +#include "lightsense.h" + + +uint8_t lsens_get_coarse() +{ + return 0; +} + +uint16_t lsens_get_fine() +{ + return 0; +} + +uint16_t lsens_get_dark_threshold() +{ + return 0; +} + +void lsens_set_dark_threshold(uint16_t threshold) +{ + +} diff --git a/nametag8_CH592/user/hw/lightsense.h b/nametag8_CH592/user/hw/lightsense.h index 5c363b9..0a4db09 100644 --- a/nametag8_CH592/user/hw/lightsense.h +++ b/nametag8_CH592/user/hw/lightsense.h @@ -9,5 +9,16 @@ #define USER_HW_LIGHTSENSE_H_ +#include + + + +uint8_t lsens_get_coarse(); +uint16_t lsens_get_fine(); + +uint16_t lsens_get_dark_threshold(); +void lsens_set_dark_threshold(uint16_t threshold); + + #endif /* USER_HW_LIGHTSENSE_H_ */ diff --git a/nametag8_CH592/user/led/rgbled.c b/nametag8_CH592/user/led/rgbled.c index 196ba4f..65d0420 100644 --- a/nametag8_CH592/user/led/rgbled.c +++ b/nametag8_CH592/user/led/rgbled.c @@ -8,8 +8,11 @@ #include #include "rgbled.h" +#include "hsv2rgb.h" -#include "../hw/aw20xxx.h" +#include "hw/aw20xxx.h" + +#include "user_config.h" @@ -21,6 +24,7 @@ +/* static const uint16_t pwm_cie_256in_1024out[] = { 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, @@ -39,12 +43,17 @@ static const uint16_t pwm_cie_256in_1024out[] = { 734, 742, 751, 759, 768, 776, 785, 794, 802, 811, 820, 829, 838, 847, 857, 866, 875, 885, 894, 903, 913, 923, 932, 942, 952, 962, 972, 982, 992, 1002, 1013, 1023, }; +*/ + AW20x awled; static uint8_t awled_fade[AW20X_FADE_COUNT]; -static uint8_t led_matrix_updated = 0; +static uint8_t led_matrix_needs_update = 0; + +struct color_rgb rgb_out[RGBLED_COUNT]; +struct color_hsv hsv_out[RGBLED_COUNT]; @@ -58,5 +67,45 @@ void rgbled_init() x = GetSysClock() / 16384; while (x--); + // clear fade + memset(awled_fade, 0x00, sizeof(awled_fade)); + + // set up RGBLED chip + awled.fade = awled_fade; aw20x_init(&awled, AW20X_ADDR_GND << 1, AW20X_COLS, AW20X_ROWS, AW20X_IMAX_13_3MA); + + aw20x_set_dim_global(&awled, AW20X_DIM); + aw20x_set_fade(&awled); + aw20x_led_enable_range(&awled, 0, 23); +} + +void rgbled_flag_update() +{ + led_matrix_needs_update = 1; +} + +void rgbled_send() +{ + if (led_matrix_needs_update) { + led_matrix_needs_update = 0; + + // leds off? + if ((uconf.flags & UCONF_FLAGS_LEDS_DISABLE) || !(uconf.flags & UCONF_FLAGS_LEDS_DISABLE)) { + // yes, clear the data + memset(awled_fade, 0x00, sizeof(awled_fade)); + } else { + // render our data to output buffer + // todo + } + + aw20x_set_fade(&awled); + } +} + +void rgbled_runprog(uint8_t tick_ctr) +{ + // run program + if (rgb_pgm[uconf.ledprog_rgb_idx].prog) { + rgb_pgm[uconf.ledprog_rgb_idx].prog(uconf.ledprog_rgb_data[uconf.ledprog_rgb_idx], tick_ctr); + } } diff --git a/nametag8_CH592/user/led/rgbled.h b/nametag8_CH592/user/led/rgbled.h index bc741d1..b5f445b 100644 --- a/nametag8_CH592/user/led/rgbled.h +++ b/nametag8_CH592/user/led/rgbled.h @@ -20,7 +20,7 @@ -#define RGB_EDGE_COUNT 10 +#define RGBLED_COUNT 12 @@ -31,16 +31,17 @@ typedef struct LedProgram { -extern const uint8_t edge_map[10]; -extern const LedProgram edge_pgm[6]; +extern const uint8_t rgb_map[RGBLED_COUNT]; +extern const LedProgram rgb_pgm[6]; -extern color_hsv hsv_edge[RGB_EDGE_COUNT]; +extern struct color_hsv hsv_out[RGBLED_COUNT]; void rgbled_init(); -void rgb_edge_update(uint8_t idx); +void rgbled_send(); +void rgbled_runprog(uint8_t tick_ctr); diff --git a/nametag8_CH592/user/led/rgbled_edge.c b/nametag8_CH592/user/led/rgbled_prog.c similarity index 73% rename from nametag8_CH592/user/led/rgbled_edge.c rename to nametag8_CH592/user/led/rgbled_prog.c index 276c143..2a861b6 100644 --- a/nametag8_CH592/user/led/rgbled_edge.c +++ b/nametag8_CH592/user/led/rgbled_prog.c @@ -1,5 +1,5 @@ /* - * $Id: rgbled_edge.c 500 2021-08-08 19:43:38Z true $ + * rgbled_prog.c * begin 20210720 true * * programs to run to show neat shit on the LEDs @@ -24,14 +24,16 @@ #include "user_config.h" -const uint8_t edge_map[10] = {3, 5, 7, 9, 0, 2, 4, 6, 8, 1}; - +const uint8_t rgb_map[RGBLED_COUNT] = { + 3, 5, 7, 9, 0, 1, + 2, 4, 6, 8, 1, 1 +}; static uint8_t timeout; -void edge_solid(uint8_t *a, uint16_t tick) +void rgb_solid(uint8_t *a, uint16_t tick) { // 1=bitfield, 2=timeout-set, 4=state, 5=hue, 6=sat, 7=val // bitfield: @@ -78,20 +80,20 @@ void edge_solid(uint8_t *a, uint16_t tick) } // update - hsv_edge[0].h = hsv.h; - hsv_edge[0].s = hsv.s; - hsv_edge[0].v = hsv.v; + hsv_out[0].h = hsv.h; + hsv_out[0].s = hsv.s; + hsv_out[0].v = hsv.v; - for (i = 1; i < RGB_EDGE_COUNT; i++) { - hsv_edge[i].h = hsv_edge[0].h; - hsv_edge[i].s = hsv_edge[0].s; - hsv_edge[i].v = hsv_edge[0].v; + for (i = 1; i < RGBLED_COUNT; i++) { + hsv_out[i].h = hsv_out[0].h; + hsv_out[i].s = hsv_out[0].s; + hsv_out[i].v = hsv_out[0].v; } } // todo: improve fading smoothness by doing fadeout every callback instead of on timeout // this can be done once LED bit depth is increased -void edge_flicker(uint8_t *a, uint16_t tick) +void rgb_flicker(uint8_t *a, uint16_t tick) { // 0=speed, 1=bitfield, 2=timeout-set, 4=state, 6=max-val, 7=min-val // bitfield: @@ -118,8 +120,8 @@ void edge_flicker(uint8_t *a, uint16_t tick) } // set constants - hsv_edge[0].h = uconf.favcolor_hue * 6; - hsv_edge[0].s = uconf.favcolor_sat; + hsv_out[0].h = uconf.favcolor_hue * 6; + hsv_out[0].s = uconf.favcolor_sat; if (a[6]) max = a[6]; else max = 255; @@ -131,7 +133,7 @@ void edge_flicker(uint8_t *a, uint16_t tick) } // process and update LEDs - for (i = 0; i < RGB_EDGE_COUNT; i++) { + for (i = 0; i < RGBLED_COUNT; i++) { // compute new val on first round or if all-same flicker is disabled if (!(a[1] & 0x08) || i == 0) { new_val = u16_scale((prng_get16() & 0xff), 0, 255, min, max); @@ -142,39 +144,39 @@ void edge_flicker(uint8_t *a, uint16_t tick) if (a[1] & 0x02) { // is it random? if (a[1] & 0x04) { - i = prng_get16() % RGB_EDGE_COUNT; + i = prng_get16() % RGBLED_COUNT; } else { // nope, sequential a[4]++; - a[4] %= RGB_EDGE_COUNT; - i = a[4] % RGB_EDGE_COUNT; + a[4] %= RGBLED_COUNT; + i = a[4] % RGBLED_COUNT; // is it in reverse? if (a[1] & 0x01) { - i = RGB_EDGE_COUNT - 1 - i; + i = RGBLED_COUNT - 1 - i; } // correct position if (!(a[1] & 0x20)) { - i = edge_map[i]; + i = rgb_map[i]; } } } // apply - hsv_edge[i].h = (a[1] & 0x40) ? (prng_get16() & 0x600) : hsv_edge[0].h; - hsv_edge[i].s = hsv_edge[0].s; - hsv_edge[i].v = new_val & 0xff; + hsv_out[i].h = (a[1] & 0x40) ? (prng_get16() & 0x600) : hsv_out[0].h; + hsv_out[i].s = hsv_out[0].s; + hsv_out[i].v = new_val & 0xff; // bail if only doing one LED if (a[1] & 0x02) { // but make sure to fade LEDs if needed if (a[1] & 0x10) { - for (i = 0; i < RGB_EDGE_COUNT; i++) { - if (hsv_edge[i].v <= a[0]) { - hsv_edge[i].v = 0; + for (i = 0; i < RGBLED_COUNT; i++) { + if (hsv_out[i].v <= a[0]) { + hsv_out[i].v = 0; } else { - hsv_edge[i].v -= a[0]; + hsv_out[i].v -= a[0]; } } } @@ -183,9 +185,9 @@ void edge_flicker(uint8_t *a, uint16_t tick) } } -uint8_t edge_circles_divider = 0; -uint8_t edge_circles_sec_ticks = 0; -void edge_circles(uint8_t *a, uint16_t tick) +uint8_t rgb_circles_divider = 0; +uint8_t rgb_circles_sec_ticks = 0; +void rgb_circles(uint8_t *a, uint16_t tick) { // 0=speed, 1=bitfield, 2=timeout-set, 4=state, 5=hue, 6=sat, 7=val // bitfield: @@ -211,22 +213,22 @@ void edge_circles(uint8_t *a, uint16_t tick) uint8_t desatfade = a[1] & 0x20; // fading - edge_circles_divider++; - edge_circles_divider %= 10; - if (!edge_circles_divider && (a[1] & 0x02)) { - for (i = 0; i < RGB_EDGE_COUNT; i++) { - if (hsv_edge[i].v <= trailfade) { - hsv_edge[i].v = 0; + rgb_circles_divider++; + rgb_circles_divider %= 10; + if (!rgb_circles_divider && (a[1] & 0x02)) { + for (i = 0; i < RGBLED_COUNT; i++) { + if (hsv_out[i].v <= trailfade) { + hsv_out[i].v = 0; } else { - hsv_edge[i].v -= trailfade; + hsv_out[i].v -= trailfade; } if (desatfade) { // fade to white too - if (hsv_edge[i].s <= (trailfade >> 1)) { - hsv_edge[i].s = 0; + if (hsv_out[i].s <= (trailfade >> 1)) { + hsv_out[i].s = 0; } else { - hsv_edge[i].s -= (trailfade >> 1); + hsv_out[i].s -= (trailfade >> 1); } } } @@ -264,9 +266,9 @@ void edge_circles(uint8_t *a, uint16_t tick) } else if (srate) { // gradual offset mode srate <<= 2; - edge_circles_sec_ticks++; - if (edge_circles_sec_ticks > srate) { - edge_circles_sec_ticks = 0; + rgb_circles_sec_ticks++; + if (rgb_circles_sec_ticks > srate) { + rgb_circles_sec_ticks = 0; y += 9; } } @@ -307,30 +309,30 @@ void edge_circles(uint8_t *a, uint16_t tick) } // set the next item - hsv_edge[edge_map[x]].h = h; - hsv_edge[edge_map[x]].s = s; - hsv_edge[edge_map[x]].v = v; + hsv_out[rgb_map[x]].h = h; + hsv_out[rgb_map[x]].s = s; + hsv_out[rgb_map[x]].v = v; if (second && x != y) { if (secval) v >>= 1; - hsv_edge[edge_map[y]].h = h2; - hsv_edge[edge_map[y]].s = s2; - hsv_edge[edge_map[y]].v = v; + hsv_out[rgb_map[y]].h = h2; + hsv_out[rgb_map[y]].s = s2; + hsv_out[rgb_map[y]].v = v; } // clear those that are on if trails are not enabled if (!trail) { - for (i = 0; i < RGB_EDGE_COUNT; i++) { + for (i = 0; i < RGBLED_COUNT; i++) { if (i != x || (second && (i != y))) { - hsv_edge[edge_map[i]].v = 0; + hsv_out[rgb_map[i]].v = 0; } } } } -uint8_t edge_waving_divider = 0; -void edge_waving(uint8_t *a, uint16_t tick) +uint8_t rgb_waving_divider = 0; +void rgb_waving(uint8_t *a, uint16_t tick) { // 0=wait-delay, 1=bitfield, 2=timeout-set, 456=work // bitfield: @@ -345,22 +347,22 @@ void edge_waving(uint8_t *a, uint16_t tick) uint8_t trailfade = a[0] >> 4; uint8_t desatfade = a[1] & 0x20; - edge_waving_divider++; - edge_waving_divider %= 10; - if (!edge_waving_divider && (a[1] & 0x02)) { - for (i = 0; i < RGB_EDGE_COUNT; i++) { - if (hsv_edge[i].v <= trailfade) { - hsv_edge[i].v = 0; + rgb_waving_divider++; + rgb_waving_divider %= 10; + if (!rgb_waving_divider && (a[1] & 0x02)) { + for (i = 0; i < RGBLED_COUNT; i++) { + if (hsv_out[i].v <= trailfade) { + hsv_out[i].v = 0; } else { - hsv_edge[i].v -= trailfade; + hsv_out[i].v -= trailfade; } if (desatfade) { // fade to white too - if (hsv_edge[i].s <= (trailfade >> 1)) { - hsv_edge[i].s = 0; + if (hsv_out[i].s <= (trailfade >> 1)) { + hsv_out[i].s = 0; } else { - hsv_edge[i].s -= (trailfade >> 1); + hsv_out[i].s -= (trailfade >> 1); } } } @@ -382,8 +384,8 @@ void edge_waving(uint8_t *a, uint16_t tick) // clear values if trails not enabled if (!(a[1] & 0x02)) { - for (i = 0; i < RGB_EDGE_COUNT; i++) { - hsv_edge[i].v = 0; + for (i = 0; i < RGBLED_COUNT; i++) { + hsv_out[i].v = 0; } } @@ -398,13 +400,13 @@ void edge_waving(uint8_t *a, uint16_t tick) break; } case 1: { // moving down - hsv_edge[edge_map[ a[6]]].h = uconf.favcolor_hue * 6; - hsv_edge[edge_map[ a[6]]].s = uconf.favcolor_sat; - hsv_edge[edge_map[ a[6]]].v = uconf.favcolor_val; + hsv_out[rgb_map[ a[6]]].h = uconf.favcolor_hue * 6; + hsv_out[rgb_map[ a[6]]].s = uconf.favcolor_sat; + hsv_out[rgb_map[ a[6]]].v = uconf.favcolor_val; - hsv_edge[edge_map[9 - a[6]]].h = uconf.favcolor_hue * 6; - hsv_edge[edge_map[9 - a[6]]].s = uconf.favcolor_sat; - hsv_edge[edge_map[9 - a[6]]].v = uconf.favcolor_val; + hsv_out[rgb_map[9 - a[6]]].h = uconf.favcolor_hue * 6; + hsv_out[rgb_map[9 - a[6]]].s = uconf.favcolor_sat; + hsv_out[rgb_map[9 - a[6]]].v = uconf.favcolor_val; a[6]++; if (a[6] >= 5) { @@ -416,13 +418,13 @@ void edge_waving(uint8_t *a, uint16_t tick) break; } case 3: { // moving up - hsv_edge[edge_map[4 - a[6]]].h = uconf.favcolor_hue * 6; - hsv_edge[edge_map[4 - a[6]]].s = uconf.favcolor_sat; - hsv_edge[edge_map[4 - a[6]]].v = uconf.favcolor_val; + hsv_out[rgb_map[4 - a[6]]].h = uconf.favcolor_hue * 6; + hsv_out[rgb_map[4 - a[6]]].s = uconf.favcolor_sat; + hsv_out[rgb_map[4 - a[6]]].v = uconf.favcolor_val; - hsv_edge[edge_map[5 + a[6]]].h = uconf.favcolor_hue * 6; - hsv_edge[edge_map[5 + a[6]]].s = uconf.favcolor_sat; - hsv_edge[edge_map[5 + a[6]]].v = uconf.favcolor_val; + hsv_out[rgb_map[5 + a[6]]].h = uconf.favcolor_hue * 6; + hsv_out[rgb_map[5 + a[6]]].s = uconf.favcolor_sat; + hsv_out[rgb_map[5 + a[6]]].v = uconf.favcolor_val; a[6]++; if (a[6] >= 5) { @@ -436,7 +438,7 @@ void edge_waving(uint8_t *a, uint16_t tick) } } -void edge_rainbow(uint8_t *a, uint16_t tick) +void rgb_rainbow(uint8_t *a, uint16_t tick) { // 0=angle-rate, 1=bitfield, 2=timeout-set, 45=angle-work, 6=sat, 7=val // bitfield: @@ -478,18 +480,18 @@ void edge_rainbow(uint8_t *a, uint16_t tick) } // apply to LEDs - for (i = 0; i < RGB_EDGE_COUNT; i++) { - r = (a[1] & 0x01) ? i : RGB_EDGE_COUNT - 1 - i; - hsv_edge[edge_map[r]].h = angle; - hsv_edge[edge_map[r]].s = a[6]; - hsv_edge[edge_map[r]].v = a[7]; + for (i = 0; i < RGBLED_COUNT; i++) { + r = (a[1] & 0x01) ? i : RGBLED_COUNT - 1 - i; + hsv_out[rgb_map[r]].h = angle; + hsv_out[rgb_map[r]].s = a[6]; + hsv_out[rgb_map[r]].v = a[7]; angle += hoffset; if (angle >= 0x600) angle -= 0x600; } } -void edge_copmode(uint8_t *a, uint16_t tick) +void rgb_copmode(uint8_t *a, uint16_t tick) { // 0=work, 1=bitfield, 2=timeout-set, 3=timeout-work, 4=work, 56=steps, 7=val // bitfield: @@ -661,40 +663,40 @@ void edge_copmode(uint8_t *a, uint16_t tick) a[0] = (pattern << 6) | (iter & 0x3f); // apply to LEDs - w = RGB_EDGE_COUNT/2; + w = RGBLED_COUNT/2; for (i = 0; i < w; i++) { - hsv_edge[edge_map[i]].h = hsv.h; - hsv_edge[edge_map[i]].s = hsv.s; - hsv_edge[edge_map[i]].v = hsv.v; + hsv_out[rgb_map[i]].h = hsv.h; + hsv_out[rgb_map[i]].s = hsv.s; + hsv_out[rgb_map[i]].v = hsv.v; - hsv_edge[edge_map[i+w]].h = hsv2.h; - hsv_edge[edge_map[i+w]].s = hsv2.s; - hsv_edge[edge_map[i+w]].v = hsv.v; + hsv_out[rgb_map[i+w]].h = hsv2.h; + hsv_out[rgb_map[i+w]].s = hsv2.s; + hsv_out[rgb_map[i+w]].v = hsv.v; } } -void edge_fade_from_center(uint8_t *a, uint16_t tick) +void rgb_fade_from_center(uint8_t *a, uint16_t tick) { } -void edge_staticbar(uint8_t *a, uint16_t tick) +void rgb_staticbar(uint8_t *a, uint16_t tick) { } -void edge_gravitycheck(uint8_t *a, uint16_t tick) +void rgb_gravitycheck(uint8_t *a, uint16_t tick) { } // implemented program table -const LedProgram edge_pgm[6] = { - {"Solid Color", edge_solid}, - {"Flicker", edge_flicker}, - {"Circles", edge_circles}, - {"Waving", edge_waving}, - {"Rainbow", edge_rainbow}, - {"Cop Mode", edge_copmode}, +const LedProgram rgb_pgm[6] = { + {"Solid Color", rgb_solid}, + {"Flicker", rgb_flicker}, + {"Circles", rgb_circles}, + {"Waving", rgb_waving}, + {"Rainbow", rgb_rainbow}, + {"Cop Mode", rgb_copmode}, }; diff --git a/nametag8_CH592/user/main.c b/nametag8_CH592/user/main.c index d90e14f..243a2a7 100644 --- a/nametag8_CH592/user/main.c +++ b/nametag8_CH592/user/main.c @@ -34,13 +34,24 @@ #include "misc/accel.h" +#include "ui/menu.h" +#include "ui/oled.h" + #include "global.h" #include "port_intr.h" #include "user_config.h" +// global settings +#define OLED_UPDATE_RATE 64 // framerate of OLED; (256*0.75) / OLED_UPDATE_RATE -const uint8_t vers[] = "241013.01"; +// flags +#define FLAG_OLED_UPDATE (1 << 0) +#define FLAG_RGBLED_RUN_PROG (1 << 1) + + + +const uint8_t vers[] = "241015a"; uint8_t cpu_use = 0; uint8_t cpu_max = 0; @@ -54,6 +65,13 @@ uint32_t idle_time_menu; uint32_t idle_time_still; uint8_t idle_go_sleep; +static volatile uint8_t flags = 0; + +static uint8_t st_tick = 0; // systick loop counter +static uint8_t oled_tick = 0; // oled framerate counter + + + void ch59x_xtal_conf() @@ -62,6 +80,91 @@ void ch59x_xtal_conf() HSECFG_Capacitance(HSECap_14p); } +void systick_init() +{ + +} + +void oled_update_done() +{ + int16_t a; + int8_t rot; + + // reset oled callback, clear screen, and set default pixel mode and font size + oled.callback = 0; + if (!(menu->flags & MENU_FLAG_NO_AUTOCLS)) { + ssd1306_cls(&oled); + } + ssd1306fb_set_color(SSD1306_STATE_SET_PIXEL); + oled.state &= ~SSD1306_STATE_STR_HALFWIDTH; + + + // orientation / flipping flags + rot = accel_get_rotation(&accel); + + if ((rot > (96+4)) || (rot < (32-4))) { + sysflags &= ~SYS_OLED_ROTATE_X; + } else if ((rot > (32+4)) && (rot < (96-4))) { + sysflags |= SYS_OLED_ROTATE_X; + } + + if ((rot > (64+4)) && (rot < 124)) { + sysflags &= ~SYS_OLED_ROTATE_Y; + } else if ((rot > 4) && (rot < (64-4))) { + sysflags |= SYS_OLED_ROTATE_Y; + } + + if ((rot < 21) || (rot > (64 + 24))) { + sysflags &= ~SYS_OLED_REVERSE_CHARS; + } else if (rot > 24 && rot < (64 + 21)){ + sysflags |= SYS_OLED_REVERSE_CHARS; + } + + +#ifdef MENU_TIMEOUT_TO_NAMETAG + // root menu idle counting + if (menu == &menu_0) { + if (!idle_time_menu) { + idle_time_menu = uptime; + } else if ((uptime - idle_time_menu) >= MENU_TIMEOUT_TO_NAMETAG) { + // been at the root menu too long. + // return to nametag + menu_stop(0); + idle_time_menu = 0; + } + } else { + idle_time_menu = 0; + } +#endif + + // do menu operations + menu_tick(); + + // calculate CPU usage + // note: we just consider missed ticks a percent. + // it's actually more like a tenth. fuck it. + // a = missed; + // todo: implement this + a = 0; + + if (uconf.framemod == UCONF_FRAMERATE_HALF) { + // the above calculation is tied to framerate. + // so this will compensate for half framerate mode... + a >>= 1; + } + + if (a > cpu_max) { + cpu_max = a; + } + cpu_use = a; + + + // reset missed interrupt counter + // missed = 0; +} + + + int main() { // configure clock @@ -96,13 +199,85 @@ int main() // configure port-based interrupts (used for ch32sub interrupt) port_intr_init(); - // note that system clock speed is decreased after every use of I2C + // note that system clock speed is decreased after every use of I2C. + + // configure system tick + systick_init(); while(1) { + // sleep when we're doing nothing + __WFI(); + // only care about aux MCU when all other processing is done ch32sub_process(); - // sleep when we're doing nothing - __WFI(); + // send the last oled frame data + if (flags & FLAG_OLED_UPDATE) { + flags &= ~FLAG_OLED_UPDATE; + + /*** oled ***/ + if (oled.callback && !(oled.state & SSD1306_STATE_BUSY)) { + if (ssd1306_cb_get()) { + oled.callback(); + } + } + + // update + // only update this frame if we're not in the middle of starting up + if (uptime) { + // process other tasks + if (oled.state & SSD1306_STATE_INITIALIZED) { + oled.callback = oled_update_done; + } + ssd1306_update(); + } + } + + // render new OLED frame + if (flags & FLAG_RGBLED_RUN_PROG) { + flags &= ~FLAG_RGBLED_RUN_PROG; + rgbled_runprog(st_tick); + } + } +} + + +void SysTick_Handler(void) +{ + st_tick++; + + if (!st_tick) { + uptime++; + uptime_hour = (uint16_t)(uptime / 3600); + uptime_min = (uint8_t)((uptime / 60) % 60); + uptime_sec = (uint8_t)((uptime ) % 60); + } + + // render and update RGBLED at 64Hz + if ((st_tick & 0x3) == 0x3) { + // make sure a valid program is selected + if (uconf.ledprog_rgb_idx > (sizeof(rgb_pgm) / sizeof(rgb_pgm[0]))) { + uconf.ledprog_rgb_idx = 0; + } + + // send any rendered data now + rgbled_send(); + + // defer rendering + flags |= FLAG_RGBLED_RUN_PROG; + } + + // render and update the oled during non-rgbled frames + else { + oled_tick++; + if (oled_tick >= OLED_UPDATE_RATE) { + oled_tick = 0; + flags |= FLAG_OLED_UPDATE; + } + } + + // read accelerometer data + if ((st_tick & 0x7) == 0x7) { + accel_poll(); } } diff --git a/nametag8_CH592/user/misc/accel.c b/nametag8_CH592/user/misc/accel.c index 2ae2f8d..89e93ea 100644 --- a/nametag8_CH592/user/misc/accel.c +++ b/nametag8_CH592/user/misc/accel.c @@ -10,12 +10,14 @@ #include "hw/lis2dw12_reg.h" #include "comm/i2c.h" +#include "misc/i8atan2.h" + +#include + // user data AccelData accel; -AccelData accel_last[4]; -AccelData accel_smoothing; int16_t movement; @@ -66,17 +68,54 @@ void accel_init() lis2dw12_reset_get(&dev_ctx, &reset); } while (reset); + // disable block update + // data in output registers is updated immediately; FIFO is disabled + lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_DISABLE); + // configure scale, power mode lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g); - lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_SINGLE_LOW_PWR_LOW_NOISE_4); + lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_CONT_LOW_PWR_LOW_NOISE_4); + + // configure filter chain + // low pass filter enabled for 6D (not currently used) + lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT); + // digital LPF2 filter of output data + lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_4); // configure output data rate - lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_100Hz); + lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_200Hz); } -int8_t accel_get_rotation() +void accel_poll() { - return 0; + uint8_t reg = 1; + uint16_t xyz[3]; + + while (reg) { + // read output only if new value is available + lis2dw12_flag_data_ready_get(&dev_ctx, ®); + + if (reg) { + // read acceleration data + memset(xyz, 0x00, 3 * sizeof(int16_t)); + lis2dw12_acceleration_raw_get(&dev_ctx, xyz); + } + } +} + +int8_t accel_get_rotation(struct AccelData *a) +{ + int8_t nx, ny, ret; + + nx = -a->x; + ny = a->y; + + ret = i8atan2(nx, ny) >> 1; + if (ret < 0) { + ret += 128; + } + + return ret; } int16_t accel_get_movement() diff --git a/nametag8_CH592/user/misc/accel.h b/nametag8_CH592/user/misc/accel.h index 45e6329..26d727a 100644 --- a/nametag8_CH592/user/misc/accel.h +++ b/nametag8_CH592/user/misc/accel.h @@ -32,8 +32,9 @@ extern uint16_t movement_worst; void accel_init(); +void accel_poll(); -int8_t accel_get_rotation(); +int8_t accel_get_rotation(struct AccelData *a); int16_t accel_get_movement(); diff --git a/nametag8_CH592/user/ui/menu_entry_0.c b/nametag8_CH592/user/ui/menu_entry_0.c index 97d0630..1120086 100644 --- a/nametag8_CH592/user/ui/menu_entry_0.c +++ b/nametag8_CH592/user/ui/menu_entry_0.c @@ -125,7 +125,7 @@ void menu_none_disp(uint8_t idx) top = oled.height - ssd1306fb_get_font_height(font_table[uconf.font_idx].font) - 1; // get rotation - rot = accel_get_rotation(); + rot = accel_get_rotation(&accel); // render modes switch (uconf.nameconf & UCONF_NAME_DISP_MASK) { @@ -233,7 +233,7 @@ MENU_0_DISP_CHAR_ROTATE: ssd1306fb_set_target(&oled); if (uconf.flags & UCONF_FLAGS_SHOW_ACCEL_ANGLE) { - sprintf(txt, "%+3d", accel_get_rotation()); + sprintf(txt, "%+3d", accel_get_rotation(&accel)); ssd1306fb_set_cursor(90, 0); ssd1306fb_draw_str(font_DejaVu_Sans_Mono_Bold_11, txt, 1); } diff --git a/nametag8_CH592/user/ui/menu_entry_2.c b/nametag8_CH592/user/ui/menu_entry_2.c index b7a8a57..208c248 100644 --- a/nametag8_CH592/user/ui/menu_entry_2.c +++ b/nametag8_CH592/user/ui/menu_entry_2.c @@ -60,7 +60,7 @@ void menu_2_btn_next(uint8_t idx) uint8_t *x; uint8_t *s; - s = uconf.ledprog_edge_data[uconf.ledprog_edge_idx]; + s = uconf.ledprog_rgb_data[uconf.ledprog_rgb_idx]; x = &s[prog_data_idx >> 1]; if (prog_data_idx & 0x01) { @@ -107,7 +107,7 @@ void menu_2_btn_prev(uint8_t idx) uint8_t *x; uint8_t *s; - s = uconf.ledprog_edge_data[uconf.ledprog_edge_idx]; + s = uconf.ledprog_rgb_data[uconf.ledprog_rgb_idx]; x = &s[prog_data_idx >> 1]; if (prog_data_idx & 0x01) { @@ -243,7 +243,7 @@ void menu_2_disp(uint8_t idx) case 0: { ssd1306fb_draw_str(font_table[0].font, "Edge Program", 1); ssd1306fb_set_cursor(16, 15); - ssd1306fb_draw_str(font_table[0].font, edge_pgm[uconf.ledprog_edge_idx].name, 1); + ssd1306fb_draw_str(font_table[0].font, rgb_pgm[uconf.ledprog_rgb_idx].name, 1); goto MENU_2_DRAW_TEXT_DONE; } @@ -251,7 +251,7 @@ void menu_2_disp(uint8_t idx) uint8_t *s; sprintf(txt, "Edge"); - s = uconf.ledprog_edge_data[uconf.ledprog_edge_idx]; + s = uconf.ledprog_rgb_data[uconf.ledprog_rgb_idx]; if (edit_mode == MENU_BTNSTYLE_MENU) { ssd1306fb_draw_str(font_table[0].font, txt, 1); @@ -401,10 +401,10 @@ void menu_2_enter(uint8_t idx) switch (idx) { case 0: { - a = (sizeof(edge_pgm) / sizeof(edge_pgm[0])); - uconf.ledprog_edge_idx++; - if (uconf.ledprog_edge_idx >= a) { - uconf.ledprog_edge_idx = 0; + a = (sizeof(rgb_pgm) / sizeof(rgb_pgm[0])); + uconf.ledprog_rgb_idx++; + if (uconf.ledprog_rgb_idx >= a) { + uconf.ledprog_rgb_idx = 0; } break; } diff --git a/nametag8_CH592/user/ui/menu_entry_5.c b/nametag8_CH592/user/ui/menu_entry_5.c index 11773e4..c004556 100644 --- a/nametag8_CH592/user/ui/menu_entry_5.c +++ b/nametag8_CH592/user/ui/menu_entry_5.c @@ -64,12 +64,12 @@ void menu_5_disp(uint8_t idx) } case 4: { // constantly save value at this screen - uconf.lsens_lo_thresh = lsens_get_lo_threshold(); + uconf.lsens_dark_thresh = lsens_get_dark_threshold(); // ensure LEDs are disabled when calibrating uconf.flags |= UCONF_FLAGS_LEDS_DISABLE; ssd1306fb_draw_str(font_table[0].font, "Recal Lightsense DARK RM!", 0); - sprintf(txt, "%d", uconf.lsens_lo_thresh); + sprintf(txt, "%d", uconf.lsens_dark_thresh); break; } case 5: { @@ -131,7 +131,7 @@ void menu_5_enter(uint8_t idx) } case 4: { // reset sensor threshold to recal value - lsens_set_lo_threshold(0xffff); + lsens_set_dark_threshold(0xffff); break; } case 5: { diff --git a/nametag8_CH592/user/ui/menu_entry_6.c b/nametag8_CH592/user/ui/menu_entry_6.c index 637fd4f..2d8b990 100644 --- a/nametag8_CH592/user/ui/menu_entry_6.c +++ b/nametag8_CH592/user/ui/menu_entry_6.c @@ -80,9 +80,10 @@ void menu_6_font_prev(uint8_t idx) */ } -void menu_6_accel_reset() +void menu_6_accel_reset(uint8_t idx) { - movement_worst = 0; + // todo: figure out what this does + // movement_worst = 0; } void menu_6_btn_use() @@ -147,9 +148,9 @@ void menu_6_disp(uint8_t idx) for (i = 0; i < 4; i++) { ssd1306fb_set_cursor(led_pos[i][0], led_pos[i][1]); - sprintf(txt, "R%d h%03X", i + 1, hsv_edge[edge_map[i + 0]].h); + sprintf(txt, "R%d h%03X", i + 1, hsv_out[rgb_map[i + 0]].h); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); - sprintf(txt, "s%02X v%02X", hsv_edge[edge_map[i + 0]].s, hsv_edge[edge_map[i + 0]].v); + sprintf(txt, "s%02X v%02X", hsv_out[rgb_map[i + 0]].s, hsv_out[rgb_map[i + 0]].v); oled.cursor_x = led_pos[i][0]; oled.cursor_y += 7; ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); @@ -164,9 +165,9 @@ void menu_6_disp(uint8_t idx) for (i = 0; i < 4; i++) { ssd1306fb_set_cursor(led_pos[i][0], led_pos[i][1]); - sprintf(txt, "R%d h%03X", i + 5, hsv_edge[edge_map[i + 4]].h); + sprintf(txt, "R%d h%03X", i + 5, hsv_out[rgb_map[i + 4]].h); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); - sprintf(txt, "s%02X v%02X", hsv_edge[edge_map[i + 4]].s, hsv_edge[edge_map[i + 4]].v); + sprintf(txt, "s%02X v%02X", hsv_out[rgb_map[i + 4]].s, hsv_out[rgb_map[i + 4]].v); oled.cursor_x = led_pos[i][0]; oled.cursor_y += 7; ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); @@ -181,9 +182,9 @@ void menu_6_disp(uint8_t idx) for (i = 0; i < 4; i++) { ssd1306fb_set_cursor(led_pos[i][0], led_pos[i][1]); - sprintf(txt, "R%d h%03X", i + 5, hsv_edge[edge_map[i + 8]].h); + sprintf(txt, "R%d h%03X", i + 5, hsv_out[rgb_map[i + 8]].h); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); - sprintf(txt, "s%02X v%02X", hsv_edge[edge_map[i + 8]].s, hsv_edge[edge_map[i + 8]].v); + sprintf(txt, "s%02X v%02X", hsv_out[rgb_map[i + 8]].s, hsv_out[rgb_map[i + 8]].v); oled.cursor_x = led_pos[i][0]; oled.cursor_y += 7; ssd1306fb_draw_str(font_Dialog_plain_8, txt, 1); @@ -206,7 +207,7 @@ void menu_6_disp(uint8_t idx) sprintf(txt, "m%i", abs(accel_get_movement())); ssd1306fb_set_cursor(104, 10); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); - sprintf(txt, "w%d", movement_worst); + sprintf(txt, "w%d", 0); // todo: fix this: movement_worst); ssd1306fb_set_cursor(106, 17); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); @@ -236,18 +237,21 @@ void menu_6_disp(uint8_t idx) ssd1306fb_set_cursor(10, -1); ssd1306fb_draw_str(font_Dialog_plain_8, "Light: ", 1); oled.cursor_x = 39; - sprintf(txt, "%d lo, %02d + %d", lsens_get_lo_threshold(), lsens_get_hi(), lsens_get_lo()); + sprintf(txt, "%d lo, %02d + %d", lsens_get_dark_threshold(), lsens_get_coarse(), lsens_get_fine()); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); ssd1306fb_set_cursor(10, 7); ssd1306fb_draw_str(font_Dialog_plain_8, "Temp: Batt:", 1); oled.cursor_x = 42; - sprintf(txt, "%d.%dC", temp_degc, temp_degc_decimal); + // todo: implement temperature sensing + // sprintf(txt, "%d.%dC", temp_degc, temp_degc_decimal); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); oled.cursor_x = 98; - sprintf(txt, "%d.%02dV", batt_volt, batt_mv); + // battery reading support is not supported on this target + // fill this area in with something else + // sprintf(txt, "%d.%02dV", batt_volt, batt_mv); ssd1306fb_draw_str(font_Dialog_plain_8, txt, 0); ssd1306fb_set_cursor(10, 16); diff --git a/nametag8_CH592/user/ui/oled.c b/nametag8_CH592/user/ui/oled.c new file mode 100644 index 0000000..602cde3 --- /dev/null +++ b/nametag8_CH592/user/ui/oled.c @@ -0,0 +1,15 @@ +/* + * oled.c + * + * Created on: Oct 15, 2024 + * Author: true + */ + +#include "oled.h" + + + +void oled_init() +{ + +} diff --git a/nametag8_CH592/user/ui/oled.h b/nametag8_CH592/user/ui/oled.h new file mode 100644 index 0000000..716e1c2 --- /dev/null +++ b/nametag8_CH592/user/ui/oled.h @@ -0,0 +1,19 @@ +/* + * oled.h + * + * Created on: Oct 15, 2024 + * Author: true + */ + +#ifndef USER_UI_OLED_H_ +#define USER_UI_OLED_H_ + + + +#include "hw/ssd1306.h" + +#include + + + +#endif /* USER_UI_OLED_H_ */ diff --git a/nametag8_CH592/user/user_config.c b/nametag8_CH592/user/user_config.c index f9b121a..42af76b 100644 --- a/nametag8_CH592/user/user_config.c +++ b/nametag8_CH592/user/user_config.c @@ -57,15 +57,15 @@ static void uconf_defaults() uconf.altcolor_sat = 240; uconf.altcolor_val = 32; - uconf.ledprog_edge_idx = 4; + uconf.ledprog_rgb_idx = 4; for (i = 0; i < 8; i++) { - uconf.ledprog_edge[i] = 0; + uconf.ledprog_rgb[i] = 0; } - memcpy(uconf.ledprog_edge_data, uconf_edge_defaults, sizeof(uconf_edge_defaults)); + memcpy(uconf.ledprog_rgb_data, uconf_edge_defaults, sizeof(uconf_edge_defaults)); - uconf.lsens_lo_thresh = 0x6a0; + uconf.lsens_dark_thresh = 0x6a0; // todo: figure out what this should be by testing uconf.sleep_timeout = 20 * 60; uconf.checksum = checksum_gen((uint8_t *)&uconf, sizeof(uconf) - 2); @@ -87,7 +87,7 @@ static int8_t uconf_validate() } // fix any mistakes - if (uconf.ledprog_edge_idx > (sizeof(edge_pgm) / sizeof(edge_pgm[0]))) uconf.ledprog_edge_idx = 0; + if (uconf.ledprog_rgb_idx > (sizeof(rgb_pgm) / sizeof(rgb_pgm[0]))) uconf.ledprog_rgb_idx = 0; return 0; } diff --git a/nametag8_CH592/user/user_config.h b/nametag8_CH592/user/user_config.h index d5367fe..e47e7a2 100644 --- a/nametag8_CH592/user/user_config.h +++ b/nametag8_CH592/user/user_config.h @@ -73,12 +73,12 @@ typedef struct UserConf { uint8_t altcolor_hue; uint8_t altcolor_sat; uint8_t altcolor_val; // 48 - uint8_t ledprog_edge_idx; - uint8_t ledprog_eyes_idx; // 50 - uint8_t ledprog_edge[16]; // 66 - uint8_t ledprog_edge_data[16][8]; // 194 - uint8_t padding[54]; // 248 - uint16_t lsens_lo_thresh; // 250 + uint8_t ledprog_rgb_idx; + uint8_t padding0; // 50 + uint8_t ledprog_rgb[16]; // 66 + uint8_t ledprog_rgb_data[16][8]; // 194 + uint8_t padding1[54]; // 248 + uint16_t lsens_dark_thresh; // 250 uint16_t sleep_timeout; // 252 uint16_t tempcx10_offset; // 253-254 uint16_t checksum; // 255-256