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.
This commit is contained in:
true 2024-10-16 00:10:05 -07:00
parent 9afb5e6ecd
commit db44d3dbab
16 changed files with 493 additions and 155 deletions

View File

@ -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)
{
}

View File

@ -9,5 +9,16 @@
#define USER_HW_LIGHTSENSE_H_
#include <stdint.h>
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_ */

View File

@ -8,8 +8,11 @@
#include <CH59x_common.h>
#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);
}
}

View File

@ -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);

View File

@ -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},
};

View File

@ -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();
}
}

View File

@ -10,12 +10,14 @@
#include "hw/lis2dw12_reg.h"
#include "comm/i2c.h"
#include "misc/i8atan2.h"
#include <stdio.h>
// 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, &reg);
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()

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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: {

View File

@ -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);

View File

@ -0,0 +1,15 @@
/*
* oled.c
*
* Created on: Oct 15, 2024
* Author: true
*/
#include "oled.h"
void oled_init()
{
}

View File

@ -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 <stdint.h>
#endif /* USER_UI_OLED_H_ */

View File

@ -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;
}

View File

@ -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