touch buttons set LED programs, added another ribbon LED program
also added PRNG
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
162
firmware/app/misc/tinymt.c
Normal 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;
|
||||
}
|
||||
39
firmware/app/misc/tinymt.h
Normal file
39
firmware/app/misc/tinymt.h
Normal 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 */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
void tempui_init();
|
||||
|
||||
void tempui_lp_runprog();
|
||||
Reference in New Issue
Block a user