touch buttons set LED programs, added another ribbon LED program

also added PRNG
This commit is contained in:
true
2026-05-09 08:42:57 -07:00
parent b2de3abe08
commit 2c151b1bf4
7 changed files with 343 additions and 6 deletions

View File

@@ -3,7 +3,7 @@
*/
#include "matrix.h"
#include "misc/tinymt.h"
static uint32_t s[8] = {0};
@@ -31,6 +31,17 @@ void lp_ribbon_upward(uint16_t wait, uint16_t rate, uint8_t fade)
1: timeout
2: index
*/
if (fade > 0x80)
fade = 0x80;
// reduce 1-frame bright blip
for (i = 0; i < sizeof(led_set.ribbon); i++) {
if (led_set.ribbon[i] >= 0xd0) {
led_set.ribbon[i] = 0xd0;
}
}
switch (s[0]) {
case 0: { // timeout
if (!s[1]) {
@@ -64,16 +75,62 @@ void lp_ribbon_upward(uint16_t wait, uint16_t rate, uint8_t fade)
// fade in and up
led_set.ribbon[x] = 0x20;
if (x) led_set.ribbon[x - 1] = 0x66;
if (x > 1) led_set.ribbon[x - 2] = 0xd0;
if (x > 1) led_set.ribbon[x - 2] = 0xef;
}
}
// fade out LEDs
for (i = 0; i < sizeof(led_set.ribbon); i++) {
if (led_set.ribbon[i] >= 0x70) {
led_set.ribbon[i] -= fade;
}
if (led_set.ribbon[i] >= fade) {
led_set.ribbon[i] -= fade;
} else {
led_set.ribbon[i] >>= 1;
// led_set.ribbon[i] >>= 1;
if (led_set.ribbon[i])
led_set.ribbon[i]--;
}
}
matrix_flag_update();
}
void lp_ribbon_twinkle(uint8_t idle, uint8_t max, uint8_t thresh_lo, uint8_t thresh_hi)
{
/*
idle: attempted idle target. ideally an odd number not a power of two.
max: maximum brightness. anything higher is clamped to this
thresh_lo: rand must be lower than this to make any adjustment this cycle
thresh_hi: rand must be this or higher to force a bright twinkle
*/
uint32_t i;
uint32_t w, x;
s[1]++;
for (i = 0; i < sizeof(led_set.ribbon); i++) {
x = prng_get8();
if (x < thresh_lo) {
w = (idle > 3) ? 3 : idle;
// swing around idle level
if (led_set.ribbon[i] > idle) {
led_set.ribbon[i] >>= 1;
} else {
led_set.ribbon[i] += (w - 1);
}
}
// only make bright stars every 4 frames
if ((x >= thresh_hi) && ((s[1] & 3) == 0)) {
w = prng_get8();
led_set.ribbon[i] += w;
if (led_set.ribbon[i] > max) {
led_set.ribbon[i] = max;
}
}
}

View File

@@ -9,6 +9,7 @@
void lp_ribbon_init();
void lp_ribbon_upward(uint16_t wait, uint16_t rate, uint8_t fade);
void lp_ribbon_twinkle(uint8_t idle, uint8_t max, uint8_t thresh_lo, uint8_t thresh_hi);

View File

@@ -29,6 +29,8 @@
#include "ui/btn.h"
#include "ui/temp_ui.h"
#include "misc/tinymt.h"
/*
*@Note
***Only PA0--PA15 and PC16--PC17 support input pull-down.
@@ -166,6 +168,9 @@ int main(void)
// set up user interface
tempui_init();
// set up random
tinymt32_init(&tinymt32_s, 1337);
// configure AWU to provide ~997Hz wakeup interrupt for main program
// TODO: confirm if the counter is reset / preloaded
awu_init();
@@ -175,7 +180,7 @@ int main(void)
// rendering next LED program output frame
if (lp_render) {
lp_render = 0;
lp_ribbon_upward(200, 3, 4);
tempui_lp_runprog();
}
// stay a while

162
firmware/app/misc/tinymt.c Normal file
View File

@@ -0,0 +1,162 @@
/**
* Tiny Mersenne Twister: only 127-bit internal state.
* Derived from the reference implementation version 1.1 (2015/04/24)
* by Mutsuo Saito (Hiroshima University) and Makoto Matsumoto
* (Hiroshima University).
*/
#include <stdint.h>
#include "tinymt.h"
static void tinymt32_next_state(tinymt32_t *s);
static uint32_t tinymt32_temper(tinymt32_t *s);
tinymt32_t tinymt32_s;
/**
* Parameter set to use for this IETF specification. Don't change.
* This parameter set is the first entry of the precalculated
* parameter sets in tinymt32dc/tinymt32dc.0.1048576.txt by
* Kenji Rikitake, available at:
* https://github.com/jj1bdx/tinymtdc-longbatch/.
* It is also the parameter set used in:
* Rikitake, K., "TinyMT pseudo random number generator for
* Erlang", Proceedings of the 11th ACM SIGPLAN Erlang Workshop,
* September 2012.
*/
const uint32_t TINYMT32_MAT1_PARAM = UINT32_C(0x8f7011ee);
const uint32_t TINYMT32_MAT2_PARAM = UINT32_C(0xfc78ff1f);
const uint32_t TINYMT32_TMAT_PARAM = UINT32_C(0x3793fdff);
/**
* This function initializes the internal state array with a
* 32-bit unsigned integer seed.
* @param s pointer to tinymt internal state.
* @param seed a 32-bit unsigned integer used as a seed.
*/
void tinymt32_init(tinymt32_t* s, uint32_t seed)
{
const uint32_t MIN_LOOP = 8;
const uint32_t PRE_LOOP = 8;
s->status[0] = seed;
s->status[1] = s->mat1 = TINYMT32_MAT1_PARAM;
s->status[2] = s->mat2 = TINYMT32_MAT2_PARAM;
s->status[3] = s->tmat = TINYMT32_TMAT_PARAM;
for (int i = 1; i < MIN_LOOP; i++) {
s->status[i & 3] ^= i + UINT32_C(1812433253)
* (s->status[(i - 1) & 3]
^ (s->status[(i - 1) & 3] >> 30));
}
/*
* NB: The parameter set of this specification warrants
* that none of the possible 2^^32 seeds leads to an
* all-zero 127-bit internal state. Therefore, the
* period_certification() function of the original
* TinyMT32 source code has been safely removed. If
* another parameter set is used, this function will
* have to be reintroduced here.
*/
for (int i = 0; i < PRE_LOOP; i++) {
tinymt32_next_state(s);
}
}
/**
* This function outputs a 32-bit unsigned integer from
* the internal state.
* @param s pointer to tinymt internal state.
* @return 32-bit unsigned integer r (0 <= r < 2^32).
*/
uint32_t tinymt32_get_uint32(tinymt32_t* s)
{
tinymt32_next_state(s);
return tinymt32_temper(s);
}
/**
* Internal tinymt32 constants and functions.
* Users should not call these functions directly.
*/
const uint32_t TINYMT32_SH0 = 1;
const uint32_t TINYMT32_SH1 = 10;
const uint32_t TINYMT32_SH8 = 8;
const uint32_t TINYMT32_MASK = UINT32_C(0x7fffffff);
/**
* This function changes the internal state of tinymt32.
* @param s pointer to tinymt internal state.
*/
void tinymt32_next_state(tinymt32_t* s)
{
uint32_t x;
uint32_t y;
y = s->status[3];
x = (s->status[0] & TINYMT32_MASK)
^ s->status[1]
^ s->status[2];
x ^= (x << TINYMT32_SH0);
y ^= (y >> TINYMT32_SH0) ^ x;
s->status[0] = s->status[1];
s->status[1] = s->status[2];
s->status[2] = x ^ (y << TINYMT32_SH1);
s->status[3] = y;
/*
* The if (y & 1) {...} block below replaces:
* s->status[1] ^= -((int32_t)(y & 1)) & s->mat1;
* s->status[2] ^= -((int32_t)(y & 1)) & s->mat2;
* The adopted code is equivalent to the original code
* but does not depend on the representation of negative
* integers by 2's complements. It is therefore more
* portable but includes an if branch, which may slow
* down the generation speed.
*/
if (y & 1) {
s->status[1] ^= s->mat1;
s->status[2] ^= s->mat2;
}
}
/**
* This function outputs a 32-bit unsigned integer from
* the internal state.
* @param s pointer to tinymt internal state.
* @return 32-bit unsigned pseudorandom number.
*/
uint32_t tinymt32_temper (tinymt32_t* s)
{
uint32_t t0, t1;
t0 = s->status[3];
t1 = s->status[0] + (s->status[2] >> TINYMT32_SH8);
t0 ^= t1;
/*
* The if (t1 & 1) {...} block below replaces:
* t0 ^= -((int32_t)(t1 & 1)) & s->tmat;
* The adopted code is equivalent to the original code
* but does not depend on the representation of negative
* integers by 2's complements. It is therefore more
* portable but includes an if branch, which may slow
* down the generation speed.
*/
if (t1 & 1) {
t0 ^= s->tmat;
}
return t0;
}
uint16_t prng_scale16(uint16_t min, uint16_t max)
{
uint32_t rnd;
rnd = prng_get16();
rnd *= (max - min);
rnd >>= 16;
rnd += min;
return rnd;
}

View File

@@ -0,0 +1,39 @@
/**
* Tiny Mersenne Twister
*/
#ifndef TINYMT_RAND_H_
#define TINYMT_RAND_H_
/**
* tinymt32 internal state vector and parameters
*/
typedef struct {
uint32_t status[4];
uint32_t mat1;
uint32_t mat2;
uint32_t tmat;
} tinymt32_t;
extern tinymt32_t tinymt32_s;
void tinymt32_init(tinymt32_t *s, uint32_t seed);
uint32_t tinymt32_get_uint32(tinymt32_t* s);
#define prng_get8() (tinymt32_get_uint32(&tinymt32_s) & 0xff)
#define prng_get16() (tinymt32_get_uint32(&tinymt32_s) & 0xffff)
#define prng_get32() tinymt32_get_uint32(&tinymt32_s)
uint16_t prng_scale16(uint16_t min, uint16_t max);
#endif /* TINYMT_RAND_H */

View File

@@ -6,14 +6,19 @@
#include "btn.h"
#include "led/matrix.h"
#include "led/ledprog.h"
static uint32_t brt = 28;
uint8_t ribbon_prog = 0;
uint8_t a_prog = 0;
uint8_t ii_prog = 0;
void brt_set(uint8_t idx)
static void brt_set(uint8_t idx)
{
switch (idx) {
case 1: {
@@ -31,8 +36,48 @@ void brt_set(uint8_t idx)
aw20x_set_dim_global(&awled, brt);
}
static void prog_set(uint8_t idx)
{
switch (idx) {
case 3: { // trio bottom left
ribbon_prog = 0;
lp_ribbon_init();
break;
}
case 4: { // trio upper
ribbon_prog = 1;
lp_ribbon_init();
break;
}
case 5: { // da erf
ribbon_prog = 3;
lp_ribbon_init();
break;
}
case 6: { // big crater
lp_ribbon_init();
break;
}
case 7: { // next to big crater
lp_ribbon_init();
break;
}
case 8: { // bottom crater
lp_ribbon_init();
break;
}
case 9: { // trio right
ribbon_prog = 2;
lp_ribbon_init();
break;
}
}
}
void tempui_init()
{
int i;
btn[2].cb_push = brt_set;
btn[2].cb_hold = brt_set;
btn[2].repeat = 200;
@@ -40,4 +85,30 @@ void tempui_init()
btn[1].cb_push = brt_set;
btn[1].cb_hold = brt_set;
btn[1].repeat = 200;
for (i = 3; i < 10; i++) {
btn[i].cb_push = prog_set;
}
}
void tempui_lp_runprog()
{
switch (ribbon_prog) {
case 0: {
lp_ribbon_upward(400, 3, 4);
break;
}
case 1: {
lp_ribbon_upward(800, 1, 2);
break;
}
case 2: {
lp_ribbon_upward(1500, 4, 7);
break;
}
case 3: {
lp_ribbon_twinkle(3, 0x7f, 0x1f, 0xfd);
break;
}
}
}

View File

@@ -1 +1,3 @@
void tempui_init();
void tempui_lp_runprog();