Compare commits

..

4 Commits

Author SHA1 Message Date
true 5d722f41e8 cleanup is31fl3729 driver; LED updates only when needed now 2024-08-03 05:56:37 -07:00
true 5adce05f84 fix the phosphoric fade effect on program 4 2024-08-02 19:39:01 -07:00
true 6a2de9a6a6 fix incorrect cursor LED indices; fix rgb program 4 2024-08-02 19:27:45 -07:00
true 51239bffa7 fix rgb program 1, 2, and 3 2024-08-02 18:49:47 -07:00
10 changed files with 117 additions and 96 deletions

View File

@ -16,20 +16,17 @@
void is31fl3729_init(uint8_t i2c_addr, uint8_t config, uint8_t global_current)
{
uint8_t buf;
// enable device
#ifdef FL3729_SDB_PORT
FL3729_SDB_PORT->BSHR = FL3729_SDB_PIN;
#endif
// reset config registers
buf = FL3729_RESET_VALUE;
i2c_write_addr1b(i2c_addr, FL3729_REG_RESET, &buf, 1);
i2c_write_reg_8b(i2c_addr, FL3729_REG_CONFIG, FL3729_RESET_VALUE);
// write initial config
i2c_write_addr1b(i2c_addr, FL3729_REG_CONFIG, &config, 1);
i2c_write_addr1b(i2c_addr, FL3729_REG_G_CURRENT, &global_current, 1);
i2c_write_reg_8b(i2c_addr, FL3729_REG_CONFIG, config);
i2c_write_reg_8b(i2c_addr, FL3729_REG_G_CURRENT, global_current);
}
uint8_t is31fl3729_get_addr(uint8_t adpin)
@ -40,21 +37,21 @@ uint8_t is31fl3729_get_addr(uint8_t adpin)
void is31fl3729_set_global_current(uint8_t i2c_addr, uint8_t current)
{
i2c_write_addr1b(i2c_addr, FL3729_REG_G_CURRENT, &current, 1);
i2c_write_reg_8b(i2c_addr, FL3729_REG_G_CURRENT, current);
}
void is31fl3729_set_scaling_current(uint8_t i2c_addr, uint8_t cs, uint8_t current)
{
if (cs > 0xf) return;
i2c_write_addr1b(i2c_addr, FL3729_REG_SCALING + cs, &current, 1);
i2c_write_reg_8b(i2c_addr, FL3729_REG_SCALING + cs, current);
}
/*
* sets current limit of multiple outputs simultaneously, starting from CS1.
* useful for initial register configuration.
*/
void is31fl3729_set_scaling_current_multi(uint8_t i2c_addr, uint8_t *current, uint8_t count)
void is31fl3729_set_scaling_current_multi(uint8_t i2c_addr, const uint8_t *current, uint8_t count)
{
if (!count) return;
count &= 0xf;
@ -67,9 +64,9 @@ void is31fl3729_set_scaling_current_multi(uint8_t i2c_addr, uint8_t *current, ui
* sw: first switch segment to update. usually set this to 1 for the first switch.
* if set to 0, will default to 1.
* *out: output data buffer
* len: length of buffer
* len: length of buffer. up to end user to not exceed writing beyond register 0x90.
*/
void is31fl3729_set_outputs(uint8_t i2c_addr, uint8_t sw, uint8_t *out, uint8_t len)
void is31fl3729_set_outputs(uint8_t i2c_addr, uint8_t sw, const uint8_t *out, uint8_t len)
{
if (!sw) sw = 1;

View File

@ -34,15 +34,15 @@
#define FL3729_GCC_MAX 64 // maximum global current level
#define FL3729_CONF_SHDN_ENA 0
#define FL3729_CONF_SHDN_DIS ((1 << 0) << 0)
#define FL3729_CONF_SSD_SHDN (0 << 0) // software shutdown
#define FL3729_CONF_SSD_NRML (1 << 0) // normal operation
#define FL3729_CONF_OSDE_OFF 0
#define FL3729_CONF_OSDE_OPEN ((1 << 0) << 1)
#define FL3729_CONF_OSDE_SHORT ((1 << 1) << 1)
#define FL3729_CONF_OSDE_OFF (0 << 1)
#define FL3729_CONF_OSDE_OPEN (1 << 1)
#define FL3729_CONF_OSDE_SHORT (2 << 1)
#define FL3729_CONF_LOGIC_LOLEV 0
#define FL3729_CONF_LOGIC_HILEV ((1 << 0) << 3)
#define FL3729_CONF_LOGIC_LOLEV (0 << 3)
#define FL3729_CONF_LOGIC_HILEV (1 << 3)
#define FL3729_CONF_MATRIX_9x15 0x00
#define FL3729_CONF_MATRIX_8x16 0x10
@ -68,25 +68,15 @@
/*
typedef struct IS31FL3729_Conf {
uint8_t ad_pin;
uint8_t config;
uint8_t global_brightness;
} IS31FL3729_Conf;
*/
void is31fl3729_init(uint8_t i2c_addr, uint8_t config, uint8_t global_current);
uint8_t is31fl3729_get_addr(uint8_t adpin);
void is31fl3729_set_global_current(uint8_t i2c_addr, uint8_t current);
void is31fl3729_set_scaling_current(uint8_t i2c_addr, uint8_t cs, uint8_t current);
void is31fl3729_set_scaling_current_multi(uint8_t i2c_addr, uint8_t *current, uint8_t count);
void is31fl3729_set_scaling_current_multi(uint8_t i2c_addr, const uint8_t *current, uint8_t count);
void is31fl3729_set_outputs(uint8_t i2c_addr, uint8_t sw, uint8_t *out, uint8_t len);
void is31fl3729_set_outputs(uint8_t i2c_addr, uint8_t sw, const uint8_t *out, uint8_t len);

View File

@ -45,6 +45,15 @@ void userconf_load()
userconf.ledprog_setting[0][0] = 2; // rainbow: angle top left to bottom right
userconf.ledprog_setting[0][1] = 25; // rainbow: spacing
userconf.ledprog_setting[1][0] = 8; // lite then fade: fade rate
userconf.ledprog_setting[1][1] = 192; // lite then fade: hue
userconf.ledprog_setting[2][0] = 255; // twinkle: saturation
userconf.ledprog_setting[2][1] = 4; // twinkle: intensity
userconf.ledprog_setting[3][0] = 5; // alternate: offset in 22.5deg increments
userconf.ledprog_setting[3][1] = 244; // alternate: hue
userconf.checksum = checksum();
userconf.checkval = CHECKVAL;
}

View File

@ -100,7 +100,7 @@ uint8_t i2c_read_reg_8b(uint8_t addr, uint8_t reg)
return dat;
}
int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len)
int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, const uint8_t *data, uint8_t len)
{
timeout = I2C_TIMEOUT;
while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--);
@ -136,7 +136,7 @@ int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len)
return 0;
}
void i2c_write_reg_8b(uint8_t addr, uint8_t reg, uint8_t dat)
void i2c_write_reg_8b(uint8_t addr, uint8_t reg, const uint8_t dat)
{
i2c_write_addr1b(addr, reg, &dat, 1);
}

View File

@ -14,10 +14,10 @@
void i2c_init();
int8_t i2c_read_addr1b(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, const uint8_t *data, uint8_t len);
uint8_t i2c_read_reg_8b(uint8_t addr, uint8_t reg);
void i2c_write_reg_8b(uint8_t addr, uint8_t reg, uint8_t dat);
void i2c_write_reg_8b(uint8_t addr, uint8_t reg, const uint8_t dat);
int8_t i2c_ack_poll(uint8_t devaddr);

View File

@ -13,7 +13,7 @@
static const uint8_t rgb_map[9] = {0x04, 0x14, 0x01, 0x11, 0x07, 0x0a, 0x1a, 0x0d, 0x1d};
static const uint8_t cursor_map[3] = {0x17, 0x18, 0x19};
static const uint8_t cursor_map[3] = {0x16, 0x17, 0x18};
static const uint8_t LED_CIE_PWM_256I_256O[] = {
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
@ -48,7 +48,7 @@ void led_init()
uint8_t buf[FL3729_CS_OUTPUTS] = {0xff};
is31fl3729_init(FL3729_ADDR,
FL3729_CONF_SHDN_DIS | FL3729_CONF_OSDE_OFF | FL3729_CONF_MATRIX_2x16,
FL3729_CONF_SSD_NRML | FL3729_CONF_OSDE_OFF | FL3729_CONF_MATRIX_2x16,
LED_INIT_CURRENT);
for (i = 0; i < FL3729_CS_OUTPUTS; i++) buf[i] = LED_INIT_SCALING;
@ -83,6 +83,8 @@ void led_send()
out[cursor_map[2]] = cursor[2];
is31fl3729_set_outputs(FL3729_ADDR, 1, out, 16+15);
led_updated = 0;
}
}

View File

@ -10,6 +10,7 @@
#include "hsv2rgb.h"
#include "led.h"
#include "rand.h"
#include "ui.h"
// led programs
@ -154,17 +155,17 @@ void led_rgb_1_lite_then_fade(uint8_t preview, uint8_t tick)
i = 0;
}
hue *= 6;
hsv2rgb_8b(hue, i, 255, &prog_rgb[0], &prog_rgb[1], &prog_rgb[2]);
hsv2rgb_8b(hue * 6, i, 255, &prog_rgb[0], &prog_rgb[1], &prog_rgb[2]);
// make the rate adjustment a bit more intuitive
if (rate >= 254) rate = 255;
else rate >>= 2;
rate++;
// fade out anything that's already lit at user's rate
for (i = 0; i < 9; i++) {
if (lite_persist[i]) lite_persist[i]--;
else for (j = 0; j < 2; j++) {
else for (j = 0; j < 3; j++) {
if (rgb[i][j] > rate) rgb[i][j] -= rate; else rgb[i][j] = 0;
}
}
@ -201,6 +202,8 @@ void led_rgb_1_lite_then_fade(uint8_t preview, uint8_t tick)
for (i = start; i < end; i++) {
rgb[i][0] = prog_rgb[0];
rgb[i][1] = prog_rgb[1];
rgb[i][2] = prog_rgb[2];
lite_persist[i] = LITE_PERSIST;
}
}
@ -224,6 +227,8 @@ void led_rgb_1_lite_then_fade(uint8_t preview, uint8_t tick)
if (lite_idx == end) {
lite_timeout = LITE_IDLE_DWELL;
}
led_is_updated();
}
lite_timeout--;
@ -238,7 +243,7 @@ void led_rgb_1_lite_then_fade(uint8_t preview, uint8_t tick)
*/
#define TWINKLE_PERSIST 3;
#define TWINKLE_RGB_VAL 240
#define TWINKLE_RGB_VAL 255
uint8_t twinkle_set[9] = {0};
void led_rgb_2_twinkle(uint8_t preview, uint8_t tick)
@ -248,12 +253,13 @@ void led_rgb_2_twinkle(uint8_t preview, uint8_t tick)
uint8_t sat;
// set
if ((tick & 3) == 0) {
rnd = prng_get8();
if (rnd >= userconf.ledprog_setting[2][1]) {
if (rnd < userconf.ledprog_setting[2][1]) {
// yup, we're doing it
rnd = prng_get16();
rnd *= 1536;
rnd <<= 16;
rnd >>= 16;
sat = userconf.ledprog_setting[2][0];
if (sat >= 128) sat = 128 - (sat - 128);
@ -269,6 +275,7 @@ void led_rgb_2_twinkle(uint8_t preview, uint8_t tick)
rgb[rnd][2] = prog_rgb[2];
twinkle_set[rnd] = TWINKLE_PERSIST;
}
}
// decay
for (i = 0; i < 9; i++) {
@ -278,6 +285,8 @@ void led_rgb_2_twinkle(uint8_t preview, uint8_t tick)
else rgb[i][j] >>= 1;
}
}
led_is_updated();
}
/*
@ -292,7 +301,7 @@ void led_rgb_3_alternate(uint8_t preview, uint8_t tick)
uint8_t i, j;
uint16_t hue = userconf.ledprog_setting[3][1] * 6;
uint8_t offset = (userconf.ledprog_setting[3][0] & 0xf) * 16 * 6;
uint16_t offset = (userconf.ledprog_setting[3][0] & 0xf) * 16 * 6;
uint8_t is_flashing = 0;
@ -307,6 +316,8 @@ void led_rgb_3_alternate(uint8_t preview, uint8_t tick)
}
}
// don't need to update flashing state. this is handled by the cursor
// set hues
for (i = 0; i < 2; i++) {
hsv2rgb_8b(hue, 255, 255, &prog_rgb[0], &prog_rgb[1], &prog_rgb[2]);
@ -348,18 +359,22 @@ void led_rgb_3_alternate(uint8_t preview, uint8_t tick)
#define TYPING_CHAR_DELAY_MIN 12 // about 1/10 of a second
#define TYPING_CHAR_DELAY_MAX 500 // just shy of 4 seconds
static const uint8_t idle_glow[3] = {12, 8, 8};
// the idle thing looked like shit.
// it's also broken.
// instead of removing, just set to 0 for now,
// and maybe address it later.
static const uint8_t idle_glow[3] = {0, 0, 0}; // {12, 8, 8};
static const uint8_t typing[3][3] = {
{255, 240, 240}, // white
{ 0, 240, 0}, // green
{255, 96, 12}, // orange
};
static uint8_t typing_idx;
static uint16_t typing_char_delay;
static uint8_t typing_idx = 255;
static uint16_t typing_char_delay = 0;
static uint8_t typing_flash_state;
static uint8_t typing_flash_delay;
static uint8_t typing_flash_state = 0;
static uint8_t typing_flash_delay = 0;
static uint8_t typing_fadeout;
@ -370,6 +385,7 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
uint8_t w;
uint16_t s;
uint8_t color;
uint8_t update = 0;
// match cursor color (well, approximate, or go green)
color = userconf.cursor_color;
@ -380,39 +396,35 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
typing_flash_state++;
typing_flash_state &= 1;
typing_flash_delay = userconf.cursor_flash;
typing_flash_delay = cursor_flash_rates[userconf.cursor_flash];
update = 1;
}
typing_flash_delay--;
// set rgb colors as appropriate
for (i = 0; i < 9; i++) {
if (i < typing_idx || ((i == typing_idx) && (typing_flash_state))) {
for (j = 0; j < 3; j++) {
if ((i < typing_idx) || ((i == typing_idx) && typing_flash_state)) {
// these are on
rgb[i][0] = typing[color][0];
rgb[i][1] = typing[color][1];
rgb[i][2] = typing[color][2];
rgb[i][j] = typing[color][j];
}
if (i > typing_idx || ((i == typing_idx) && (!typing_flash_state))) {
if (i > typing_idx) { // || ((i == typing_idx) && !typing_flash_state)) {
// these are idle
rgb[i][0] = idle_glow[0];
rgb[i][1] = idle_glow[1];
rgb[i][2] = idle_glow[2];
rgb[i][j] = idle_glow[j];
}
// flashing cursor fadeout
if (i == typing_idx && typing_flash_state) {
if (typing_flash_delay <= 8) {
w = 8 - typing_flash_delay;
rgb[i][0] >>= w; if (rgb[i][0] < idle_glow[0]) rgb[i][0] = idle_glow[0];
rgb[i][1] >>= w; if (rgb[i][1] < idle_glow[1]) rgb[i][1] = idle_glow[1];
rgb[i][2] >>= w; if (rgb[i][2] < idle_glow[2]) rgb[i][2] = idle_glow[2];
if ((i == typing_idx) && !typing_flash_state) {
if (rgb[i][j] > 32) rgb[i][j] -= 32; else rgb[i][j] = 0;
update = 1;
}
}
}
// set cursor as appropriate
for (i = 0; i < 2; i++) {
for (i = 0; i < 3; i++) {
cursor[i] = 0;
}
@ -432,7 +444,7 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
else typing_fadeout = 0;
for (i = 0; i < 9; i++) {
for (j = 0; j < 2; j++) {
for (j = 0; j < 3; j++) {
s = rgb[i][j];
s *= typing_fadeout;
rgb[i][j] = s >> 8;
@ -445,7 +457,7 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
}
// are we on the next character?
if (!(--typing_char_delay)) {
if (!typing_char_delay) {
// next character
typing_idx++;
@ -453,8 +465,8 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
// at the cursor, we wait two max periods
typing_char_delay = TYPING_CHAR_DELAY_MAX << 1;
} else if (typing_idx == 10) {
// at the end, we wait half of one max period
typing_char_delay = TYPING_CHAR_DELAY_MAX >> 1;
// at the end, we wait one max period
typing_char_delay = TYPING_CHAR_DELAY_MAX;
} else {
typing_char_delay = prng_scale16(TYPING_CHAR_DELAY_MIN, TYPING_CHAR_DELAY_MAX);
}
@ -469,6 +481,12 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
typing_flash_state = 0;
typing_flash_delay = 0;
}
typing_char_delay--;
if (update) {
led_is_updated();
}
}

View File

@ -151,12 +151,12 @@ static uint32_t tinymt32_temper (tinymt32_t* s)
uint16_t prng_scale16(uint16_t min, uint16_t max)
{
uint16_t rnd;
uint32_t rnd;
rnd = prng_get16();
rnd *= (max - min);
rnd >>= 16;
rnd += min;
return rnd;
return (uint16_t)rnd;
}

View File

@ -38,7 +38,7 @@ static uint8_t target_gc = 0;
static uint8_t cursor_flash = 0;
static uint8_t cursor_state = 0xff;
static const uint16_t cursor_flash_rates[] = { // off-to-on flash rates in 1/256 second increments
const uint16_t cursor_flash_rates[8] = { // off-to-on flash rates in 1/256 second increments
255, // (0.5 on-off/second)
191, // (0.75 on-off/second)
127, // (1.0 on-off/second)
@ -485,12 +485,13 @@ void ui_render()
}
// actually run the program
led_rgbprog[rgb_prog_idx - 1](LED_RGBPROG_NORMAL, tick);
led_rgbprog[rgb_prog_idx](LED_RGBPROG_NORMAL, tick);
}
}
// temp: remove me once buttons are tested and working
led_rgbprog[0](LED_RGBPROG_NORMAL, tick);
rgb_prog_idx = 4;
led_rgbprog[rgb_prog_idx](LED_RGBPROG_NORMAL, tick);
break;
}

View File

@ -10,6 +10,10 @@
extern const uint16_t cursor_flash_rates[8];
void ui_init();
void ui_render();