Compare commits

..

No commits in common. "4e7985273b3cb7813d3a303299616e17ff51c7c1" and "6785261d08783efcf93f65dc9353a5918b136983" have entirely different histories.

10 changed files with 202 additions and 414 deletions

View File

@ -3,8 +3,6 @@
* GAT Addon Firmware * GAT Addon Firmware
* by true * by true
* *
* version 0.0.1
*
* code was made for different random addons I designed for dc32, * code was made for different random addons I designed for dc32,
* then adapted to each one. so things might be a mess. * then adapted to each one. so things might be a mess.
* *
@ -54,12 +52,8 @@ void gpio_init()
gpio.GPIO_Pin = GPIO_Pin_1; gpio.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOA, &gpio); GPIO_Init(GPIOA, &gpio);
// lightsense LED cathode
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOA, &gpio);
// lightsense LED anode // lightsense LED anode
gpio.GPIO_Mode = GPIO_Mode_Out_OD;
gpio.GPIO_Pin = GPIO_Pin_0; gpio.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOD, &gpio); GPIO_Init(GPIOD, &gpio);
@ -99,16 +93,16 @@ int main(void)
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM1, ENABLE); RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM1, ENABLE);
// configure gpio pins, hard buttons (used for settings reset) // configure gpio pins
gpio_init(); gpio_init();
btn_init();
// get saved settings, or reset if BTN1 is pushed // get saved settings
i2c_init(); i2c_init();
userconf_load((BTN_PORT->INDR & (1 << BTN1_PIN)) ? 0 : 1); userconf_load();
// configure hardware // configure hardware
adc_init(); adc_init();
btn_init();
led_init(); led_init();
// configure random // configure random

View File

@ -16,7 +16,6 @@ struct Btn btn[BTN_COUNT] = {0};
void btn_init() void btn_init()
{ {
uint8_t i; uint8_t i;
uint8_t r;
// configure GPIO // configure GPIO
BTN_PORT->BSHR = (BTN1_PUPD << BTN1_PIN) | (BTN2_PUPD << BTN2_PIN); BTN_PORT->BSHR = (BTN1_PUPD << BTN1_PIN) | (BTN2_PUPD << BTN2_PIN);
@ -30,11 +29,6 @@ void btn_init()
btn[0]._pintype = BTN1_PIN | BTN_ACTIVE_LO; btn[0]._pintype = BTN1_PIN | BTN_ACTIVE_LO;
btn[1]._pintype = BTN2_PIN; btn[1]._pintype = BTN2_PIN;
// check button, and ignore if held
if (!(BTN_PORT->INDR & (1 << BTN1_PIN))) {
btn[0]._mask |= BTN_IGNORE;
}
} }
void btn_poll() void btn_poll()
@ -65,8 +59,8 @@ void btn_poll()
// first push? // first push?
if (!(btn[i]._mask & BTN_PUSH)) { if (!(btn[i]._mask & BTN_PUSH)) {
btn[i]._mask = BTN_PUSH | ignore; btn[i]._mask = BTN_PUSH;
if (btn[i].cb_push && !ignore) { if (btn[i].cb_push) {
btn[i].cb_push(i); btn[i].cb_push(i);
btn[i]._mask |= (BTN_PUSH << 4); btn[i]._mask |= (BTN_PUSH << 4);
} }
@ -91,7 +85,6 @@ void btn_poll()
} else { } else {
// is not pushed // is not pushed
if (!(btn[i]._mask & BTN_RELEASE)) { if (!(btn[i]._mask & BTN_RELEASE)) {
// note: release will remove ignore status
btn[i]._mask = BTN_RELEASE; btn[i]._mask = BTN_RELEASE;
btn[i]._count = 0; btn[i]._count = 0;
// call callback only if not in ignore state // call callback only if not in ignore state

View File

@ -29,14 +29,14 @@ static uint16_t checksum()
return sum; return sum;
} }
void userconf_load(uint8_t force_reset) void userconf_load()
{ {
uint16_t csum; uint8_t csum;
eeprom_read_bytes(0, 0, (uint8_t *)&userconf, sizeof(userconf)); eeprom_read_bytes(0, 0, (uint8_t *)&userconf, sizeof(userconf));
csum = checksum(); csum = checksum();
if ((userconf.checkval != CHECKVAL) || (userconf.checksum != csum) || force_reset) { if ((userconf.checkval != CHECKVAL) || (userconf.checksum != csum)) {
// config is invalid; reset to default // config is invalid; reset to default
userconf.cursor_color = CONF_CURSOR_WHITE; userconf.cursor_color = CONF_CURSOR_WHITE;
userconf.cursor_flash = 4; // default flash rate userconf.cursor_flash = 4; // default flash rate
@ -48,8 +48,8 @@ void userconf_load(uint8_t force_reset)
userconf.ledprog_setting[1][0] = 8; // lite then fade: fade rate userconf.ledprog_setting[1][0] = 8; // lite then fade: fade rate
userconf.ledprog_setting[1][1] = 192; // lite then fade: hue userconf.ledprog_setting[1][1] = 192; // lite then fade: hue
userconf.ledprog_setting[2][0] = 127; // twinkle: saturation userconf.ledprog_setting[2][0] = 255; // twinkle: saturation
userconf.ledprog_setting[2][1] = 6; // twinkle: intensity userconf.ledprog_setting[2][1] = 4; // twinkle: intensity
userconf.ledprog_setting[3][0] = 5; // alternate: offset in 22.5deg increments userconf.ledprog_setting[3][0] = 5; // alternate: offset in 22.5deg increments
userconf.ledprog_setting[3][1] = 244; // alternate: hue userconf.ledprog_setting[3][1] = 244; // alternate: hue

View File

@ -42,7 +42,7 @@ extern struct UserConf userconf;
void userconf_load(uint8_t force_reset); void userconf_load();
void userconf_save(); void userconf_save();

View File

@ -8,7 +8,7 @@
* ensure i2c bus has been configured before using these functions. * ensure i2c bus has been configured before using these functions.
*/ */
#define EEPROM_BASE_ADDR 0xa0 #define EEPROM_BASE_ADDR (0xa0 >> 1)
#include <ch32v00x.h> #include <ch32v00x.h>
@ -18,17 +18,6 @@
#include "i2c.h" #include "i2c.h"
static inline uint8_t page_to_i2caddr(uint8_t page)
{
page &= 0x7; // limit page to 3 bits (8 pages)
page <<= 1; // shift page to required position
page |= EEPROM_BASE_ADDR; // merge top address bits to form address
return page;
}
/********************************************************************* /*********************************************************************
* @fn eeprom_read_byte * @fn eeprom_read_byte
* *
@ -40,7 +29,9 @@ static inline uint8_t page_to_i2caddr(uint8_t page)
*/ */
void eeprom_read_bytes(uint8_t page, uint8_t addr, uint8_t *data, uint8_t len) void eeprom_read_bytes(uint8_t page, uint8_t addr, uint8_t *data, uint8_t len)
{ {
page = page_to_i2caddr(page); page &= 0x7; // limit page to 3 bits (8 pages)
page |= EEPROM_BASE_ADDR; // add address to page
page <<= 1; // make i2c address from page
i2c_read_addr1b(page, addr, data, len); i2c_read_addr1b(page, addr, data, len);
} }
@ -48,17 +39,19 @@ void eeprom_read_bytes(uint8_t page, uint8_t addr, uint8_t *data, uint8_t len)
/********************************************************************* /*********************************************************************
* @fn eeprom_write_bytes * @fn eeprom_write_bytes
* *
* @brief Write data to EEPROM. * @brief Write one data to EEPROM.
* Note that some EEPROMs have buffers smaller than the page size. * Note that some EEPROMs have buffers smaller than the page size.
* *
* @param page - Which 256-byte EEPROM page. * @param page - Which 256-byte EEPROM page.
* @param addr - Starting write address. * @param addr - Starting write address.
* @param data - Pointer to byte(s) to write. * @param data - Pointer to byte(s) to write.
* @param len - Count of data to write. * @param len - Count of data to write.
*/ */
void eeprom_write_bytes(uint8_t page, uint8_t addr, uint8_t *data, uint8_t len) void eeprom_write_bytes(uint8_t page, uint8_t addr, uint8_t *data, uint8_t len)
{ {
page = page_to_i2caddr(page); page &= 0x7; // limit page to 3 bits (8 pages)
page |= EEPROM_BASE_ADDR; // add address to page
page <<= 1; // make i2c address from page
// disable systick interrupt // disable systick interrupt
NVIC_DisableIRQ(SysTicK_IRQn); NVIC_DisableIRQ(SysTicK_IRQn);
@ -68,9 +61,9 @@ void eeprom_write_bytes(uint8_t page, uint8_t addr, uint8_t *data, uint8_t len)
EEPROM_WP_PORT->BCR = EEPROM_WP_PIN; EEPROM_WP_PORT->BCR = EEPROM_WP_PIN;
#endif #endif
while (!i2c_addr_scan(page)); while (i2c_ack_poll(page));
i2c_write_addr1b(page, addr, data, len); i2c_write_addr1b(page, addr, data, len);
while (!i2c_addr_scan(page)); while (i2c_ack_poll(page));
#ifdef EEPROM_WP_PORT #ifdef EEPROM_WP_PORT
EEPROM_WP_PORT->BSHR = EEPROM_WP_PIN; EEPROM_WP_PORT->BSHR = EEPROM_WP_PIN;

View File

@ -15,7 +15,7 @@
#define EEPROM_WP_PORT GPIOC #define EEPROM_WP_PORT GPIOC
#define EEPROM_WP_PIN GPIO_Pin_6 #define EEPROM_WP_PIN GPIO_Pin_7

View File

@ -29,7 +29,8 @@ void i2c_init()
i2c.I2C_ClockSpeed = 666666; i2c.I2C_ClockSpeed = 666666;
i2c.I2C_Mode = I2C_Mode_I2C; i2c.I2C_Mode = I2C_Mode_I2C;
i2c.I2C_DutyCycle = I2C_DutyCycle_2; // 16_9; i2c.I2C_DutyCycle = I2C_DutyCycle_16_9;
i2c.I2C_OwnAddress1 = 0x7f;
i2c.I2C_Ack = I2C_Ack_Enable; i2c.I2C_Ack = I2C_Ack_Enable;
i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &i2c); I2C_Init(I2C1, &i2c);
@ -56,13 +57,11 @@ int8_t i2c_read_addr1b(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len)
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && timeout--); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && timeout--);
if (!timeout) return -3; if (!timeout) return -3;
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_SendData(I2C1, reg); I2C_SendData(I2C1, reg);
timeout = I2C_TIMEOUT; timeout = I2C_TIMEOUT;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout--); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout--);
if (!timeout) return -4; if (!timeout) return -4;
I2C_AcknowledgeConfig(I2C1, ENABLE);
I2C_GenerateSTART(I2C1, ENABLE); I2C_GenerateSTART(I2C1, ENABLE);
timeout = I2C_TIMEOUT; timeout = I2C_TIMEOUT;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--);
@ -103,8 +102,6 @@ int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, const uint8_t *data, uint8_t
while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--); while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--);
if (!timeout) return -1; if (!timeout) return -1;
I2C_AcknowledgeConfig(I2C1, ENABLE);
I2C_GenerateSTART(I2C1, ENABLE); I2C_GenerateSTART(I2C1, ENABLE);
timeout = I2C_TIMEOUT; timeout = I2C_TIMEOUT;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--);
@ -127,11 +124,6 @@ int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, const uint8_t *data, uint8_t
I2C_SendData(I2C1, *data++); I2C_SendData(I2C1, *data++);
len--; len--;
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
continue;
}
// failed to acknowledge...
if (I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)) {
break;
} }
} }
@ -145,15 +137,9 @@ void i2c_write_reg_8b(uint8_t addr, uint8_t reg, const uint8_t dat)
i2c_write_addr1b(addr, reg, &dat, 1); i2c_write_addr1b(addr, reg, &dat, 1);
} }
uint8_t i2c_addr_scan(uint8_t addr) int8_t i2c_ack_poll(uint8_t addr)
{ {
uint8_t found = 1; int8_t addr_match = 0;
uint32_t event;
// no low addresses
if ((addr >> 4) == 0) return 0;
// no high addresses
if ((addr & 0xf8) == 0xf8) return 0;
timeout = I2C_TIMEOUT; timeout = I2C_TIMEOUT;
while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--); while((I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET) && timeout--);
@ -164,32 +150,14 @@ uint8_t i2c_addr_scan(uint8_t addr)
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout--);
if (!timeout) return -2; if (!timeout) return -2;
I2C_Send7bitAddress(I2C1, addr, (addr & 1)); I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Receiver);
timeout = I2C_TIMEOUT_ACK_POLL; timeout = I2C_TIMEOUT_ACK_POLL;
if (addr & 1) event = I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED; while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) && timeout--);
else event = I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED;
while (I2C_CheckEvent(I2C1, event) && timeout--) {
if (I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)) {
found = 0;
break;
}
}
if (!timeout) { if (!timeout) {
found = 0; addr_match = -128;
} }
// reset flags; it might be in a fucked state
I2C1->STAR1 = 0;
// send a stop to make sure anything listening knows to stfu
I2C_GenerateSTOP(I2C1, ENABLE); I2C_GenerateSTOP(I2C1, ENABLE);
if (!found) { return addr_match;
return 0;
}
return addr;
} }

View File

@ -19,7 +19,7 @@ int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, const uint8_t *data, uint8_t
uint8_t i2c_read_reg_8b(uint8_t addr, uint8_t reg); uint8_t i2c_read_reg_8b(uint8_t addr, uint8_t reg);
void i2c_write_reg_8b(uint8_t addr, uint8_t reg, const uint8_t dat); void i2c_write_reg_8b(uint8_t addr, uint8_t reg, const uint8_t dat);
uint8_t i2c_addr_scan(uint8_t addr); int8_t i2c_ack_poll(uint8_t devaddr);

View File

@ -71,8 +71,6 @@ void led_rgb_0_rainbow(uint8_t preview, uint8_t tick)
uint8_t max; // max number of iterations for this angle uint8_t max; // max number of iterations for this angle
uint8_t angle; // fill direction from LUT uint8_t angle; // fill direction from LUT
uint8_t output = 1;
uint16_t hoff; uint16_t hoff;
// run at half framerate // run at half framerate
@ -104,19 +102,15 @@ void led_rgb_0_rainbow(uint8_t preview, uint8_t tick)
if (i == idx) { // is this LED part of this pattern at this index? if (i == idx) { // is this LED part of this pattern at this index?
if (preview) { // are we in preview mode? if (preview) { // are we in preview mode?
output = 1;
if (j != 0) { // is the first letter not the one selected? if (j != 0) { // is the first letter not the one selected?
if ((preview & 0xf) == 0) {// is this preview selected? if ((preview & 0x7f) == 0) {// is this preview selected?
if (j < 5) output = 0; // pass over any outputs that are not "TECH" letters if (j < 5) continue; // pass over any outputs that are not "TECH" letters
} else output = 0; }
} } else return; // preview is not selected, so we're done here
}
if (output) {
rgb[j][0] = prog_rgb[0]; // if so, copy the values
rgb[j][1] = prog_rgb[1];
rgb[j][2] = prog_rgb[2];
} }
rgb[j][0] = prog_rgb[0]; // if so, copy the values
rgb[j][1] = prog_rgb[1];
rgb[j][2] = prog_rgb[2];
} }
n++; // nybble index n++; // nybble index
@ -170,16 +164,6 @@ void led_rgb_1_lite_then_fade(uint8_t preview, uint8_t tick)
// fade out anything that's already lit at user's rate // fade out anything that's already lit at user's rate
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
if (preview) {
if (i <= 4) {
if (i != 1) {
continue;
}
} else if ((preview & 0xf) != 1) {
continue;
}
}
if (lite_persist[i]) lite_persist[i]--; if (lite_persist[i]) lite_persist[i]--;
else for (j = 0; j < 3; j++) { else for (j = 0; j < 3; j++) {
if (rgb[i][j] > rate) rgb[i][j] -= rate; else rgb[i][j] = 0; if (rgb[i][j] > rate) rgb[i][j] -= rate; else rgb[i][j] = 0;
@ -190,42 +174,29 @@ void led_rgb_1_lite_then_fade(uint8_t preview, uint8_t tick)
if (!lite_timeout) { if (!lite_timeout) {
if (!lite_direction) { if (!lite_direction) {
// left to right // left to right
if (!preview || (preview && (lite_idx == 1))) { // light RETRO
if (lite_idx < 5) { if (lite_idx < 5) {
// light RETRO rgb[lite_idx][0] = prog_rgb[0];
rgb[lite_idx][0] = prog_rgb[0]; rgb[lite_idx][1] = prog_rgb[1];
rgb[lite_idx][1] = prog_rgb[1]; rgb[lite_idx][2] = prog_rgb[2];
rgb[lite_idx][2] = prog_rgb[2]; lite_persist[lite_idx] = LITE_PERSIST;
lite_persist[lite_idx] = LITE_PERSIST;
}
} }
if (!preview || ((preview & 0xf) == 1)) { // light TECH
// light TECH if (lite_idx < 4) {
if (lite_idx < 4) { rgb[lite_idx + 5][0] = prog_rgb[0];
rgb[lite_idx + 5][0] = prog_rgb[0]; rgb[lite_idx + 5][1] = prog_rgb[1];
rgb[lite_idx + 5][1] = prog_rgb[1]; rgb[lite_idx + 5][2] = prog_rgb[2];
rgb[lite_idx + 5][2] = prog_rgb[2]; lite_persist[lite_idx + 5] = LITE_PERSIST;
lite_persist[lite_idx + 5] = LITE_PERSIST;
}
} }
} else { } else {
// up to down // up to down
if (lite_idx < 2) { if (lite_idx < 2) {
if (!lite_idx) { if (!lite_idx) {
if (preview) { start = 0;
start = 1; end = 5;
end = 2;
} else {
start = 0;
end = 5;
}
} else { } else {
if (preview && ((preview & 0xf) != 1)) { start = 5;
start = 9;
} else {
start = 5;
}
end = 9; end = 9;
} }
@ -281,20 +252,11 @@ void led_rgb_2_twinkle(uint8_t preview, uint8_t tick)
uint32_t rnd; uint32_t rnd;
uint8_t sat; uint8_t sat;
uint8_t show;
// set // set
if ((tick & 3) == 0) { if ((tick & 3) == 0) {
rnd = prng_get8(); rnd = prng_get8();
if (preview && (preview & 0xf) != 2) {
// possibly increase chances to flash for top icon
rnd >>= 2;
}
if (rnd < userconf.ledprog_setting[2][1]) { if (rnd < userconf.ledprog_setting[2][1]) {
// yup, we're doing it // yup, we're doing it
show = 1;
rnd = prng_get16(); rnd = prng_get16();
rnd *= 1536; rnd *= 1536;
rnd >>= 16; rnd >>= 16;
@ -308,46 +270,23 @@ void led_rgb_2_twinkle(uint8_t preview, uint8_t tick)
rnd = prng_get16() & 0xfff; rnd = prng_get16() & 0xfff;
rnd /= 455; rnd /= 455;
if (preview) { rgb[rnd][0] = prog_rgb[0];
show = 0; rgb[rnd][1] = prog_rgb[1];
if (rnd == 2) show = 1; rgb[rnd][2] = prog_rgb[2];
else if (((preview & 0xf) == 2) && (rnd >= 5)) { twinkle_set[rnd] = TWINKLE_PERSIST;
show = 1;
}
}
if (show) {
rgb[rnd][0] = prog_rgb[0];
rgb[rnd][1] = prog_rgb[1];
rgb[rnd][2] = prog_rgb[2];
twinkle_set[rnd] = TWINKLE_PERSIST;
}
}
for (i = 0; i < 9; i++) {
show = 1;
// kinda bad but no fucking time to finish this code
if (preview) {
show = 0;
if (i == 2) show = 1;
else if (((preview & 0xf) == 2) && (i >= 5)) {
show = 1;
}
}
if (show) {
if (twinkle_set[i]) twinkle_set[i]--;
for (j = 0; j < 3; j++) {
if (twinkle_set[i]) rgb[i][j]--;
else rgb[i][j] >>= 1;
}
}
led_is_updated();
} }
} }
// decay
for (i = 0; i < 9; i++) {
twinkle_set[i]--;
for (j = 0; j < 2; j++) {
if (twinkle_set[i]) rgb[i][j]--;
else rgb[i][j] >>= 1;
}
}
led_is_updated();
} }
/* /*
@ -366,7 +305,7 @@ void led_rgb_3_alternate(uint8_t preview, uint8_t tick)
uint8_t is_flashing = 0; uint8_t is_flashing = 0;
if ((userconf.cursor_color == CONF_CURSOR_OFF) || preview) { if (userconf.cursor_color == CONF_CURSOR_OFF) {
// flash at ~2Hz // flash at ~2Hz
tick >>= 5; tick >>= 5;
if (tick & 1) is_flashing = 1; if (tick & 1) is_flashing = 1;
@ -387,25 +326,17 @@ void led_rgb_3_alternate(uint8_t preview, uint8_t tick)
if (is_flashing) { if (is_flashing) {
// set TECH // set TECH
if (!preview || ((preview & 0xf) == 3)) { for (j = 5; j < 9; j++) {
for (j = 5; j < 9; j++) { rgb[j][0] = prog_rgb[0];
rgb[j][0] = prog_rgb[0]; rgb[j][1] = prog_rgb[1];
rgb[j][1] = prog_rgb[1]; rgb[j][2] = prog_rgb[2];
rgb[j][2] = prog_rgb[2];
}
} }
} else { } else {
// set RETRO // set RETRO
if (!preview) { for (j = 0; j < 5; j++) {
for (j = 0; j < 5; j++) { rgb[j][0] = prog_rgb[0];
rgb[j][0] = prog_rgb[0]; rgb[j][1] = prog_rgb[1];
rgb[j][1] = prog_rgb[1]; rgb[j][2] = prog_rgb[2];
rgb[j][2] = prog_rgb[2];
}
} else {
rgb[3][0] = prog_rgb[0];
rgb[3][1] = prog_rgb[1];
rgb[3][2] = prog_rgb[2];
} }
} }
@ -436,7 +367,7 @@ static const uint8_t idle_glow[3] = {0, 0, 0}; // {12, 8, 8};
static const uint8_t typing[3][3] = { static const uint8_t typing[3][3] = {
{255, 240, 240}, // white {255, 240, 240}, // white
{ 0, 240, 0}, // green { 0, 240, 0}, // green
{255, 16, 4}, // orange {255, 96, 12}, // orange
}; };
static uint8_t typing_idx = 255; static uint8_t typing_idx = 255;
@ -476,42 +407,34 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
for (j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
if ((i < typing_idx) || ((i == typing_idx) && typing_flash_state)) { if ((i < typing_idx) || ((i == typing_idx) && typing_flash_state)) {
// these are on // these are on
if (!preview || (i == 4) || (((preview & 0xf) == 4) && i >= 5)) { rgb[i][j] = typing[color][j];
rgb[i][j] = typing[color][j];
}
} else } else
if (i > typing_idx) { // || ((i == typing_idx) && !typing_flash_state)) { if (i > typing_idx) { // || ((i == typing_idx) && !typing_flash_state)) {
// these are idle // these are idle
if (!preview || (i == 4) || (((preview & 0xf) == 4) && i >= 5)) { rgb[i][j] = idle_glow[j];
rgb[i][j] = idle_glow[j];
}
} else } else
// flashing cursor fadeout // flashing cursor fadeout
if (!preview || (i == 4) || (((preview & 0xf) == 4) && i >= 5)) { if ((i == typing_idx) && !typing_flash_state) {
if ((i == typing_idx) && !typing_flash_state) { if (rgb[i][j] > 32) rgb[i][j] -= 32; else rgb[i][j] = 0;
if (rgb[i][j] > 32) rgb[i][j] -= 32; else rgb[i][j] = 0; update = 1;
update = 1;
}
} }
} }
} }
// set cursor as appropriate // set cursor as appropriate
if (!preview) { for (i = 0; i < 3; i++) {
for (i = 0; i < 3; i++) { cursor[i] = 0;
cursor[i] = 0; }
}
// at the cursor // at the cursor
if (typing_idx >= 9) { if (typing_idx >= 9) {
cursor[color] = typing_flash_state ? 240 : 12; cursor[color] = typing_flash_state ? 240 : 12;
if (typing_flash_delay <= 8) { if (typing_flash_delay <= 8) {
w = 8 - typing_flash_delay; w = 8 - typing_flash_delay;
cursor[color] >>= w; cursor[color] >>= w;
if (cursor[color] < 12) cursor[color] = 0; // idle value if (cursor[color] < 12) cursor[color] = 0; // idle value
}
} }
} }
@ -520,27 +443,21 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
if (typing_fadeout >= 3) typing_fadeout--; if (typing_fadeout >= 3) typing_fadeout--;
else typing_fadeout = 0; else typing_fadeout = 0;
if (!preview || (i == 4) || (((preview & 0xf) == 4) && i >= 5)) { for (j = 0; j < 3; j++) {
for (j = 0; j < 3; j++) { s = rgb[0][j];
s = rgb[8][j];
s *= typing_fadeout;
rgb[8][j] = s >> 8;
}
}
w = ((preview & 0xf) == 4) ? 5 : 0;
for (i = w; i < 8; i++) {
rgb[i][0] = rgb[8][0];
rgb[i][1] = rgb[8][1];
rgb[i][2] = rgb[8][2];
}
if (!preview) {
s = cursor[color];
s *= typing_fadeout; s *= typing_fadeout;
cursor[color] = s >> 8; rgb[0][j] = s >> 8;
} }
for (i = 1; i < 9; i++) {
rgb[i][0] = rgb[0][0];
rgb[i][1] = rgb[0][1];
rgb[i][2] = rgb[0][2];
}
s = cursor[color];
s *= typing_fadeout;
cursor[color] = s >> 8;
} }
// are we on the next character? // are we on the next character?
@ -548,11 +465,6 @@ void led_rgb_4_typing(uint8_t preview, uint8_t tick)
// next character // next character
typing_idx++; typing_idx++;
// start at this character in preview mode
if (preview && typing_idx < 4) {
typing_idx = 4;
}
if (typing_idx == 9) { if (typing_idx == 9) {
// at the cursor, we wait two max periods // at the cursor, we wait two max periods
typing_char_delay = TYPING_CHAR_DELAY_MAX << 1; typing_char_delay = TYPING_CHAR_DELAY_MAX << 1;

View File

@ -23,7 +23,7 @@
#define MIN_GC 2 #define MIN_GC 2
#define MAX_GC 26 #define MAX_GC 26
#define UI_CONF_SAVE_TIMEOUT 192 #define UI_CONF_SAVE_TIMEOUT 160
#define UI_PROG_RUNTIME_MIN (128*15) // 15 seconds #define UI_PROG_RUNTIME_MIN (128*15) // 15 seconds
#define UI_PROG_RUNTIME_MAX (128*120) // 120 seconds #define UI_PROG_RUNTIME_MAX (128*120) // 120 seconds
@ -60,7 +60,8 @@ static uint8_t config_save_timer;
void ui_btn_push_cb(uint8_t idx) void ui_btn_push_cb(uint8_t idx)
{ {
uint8_t i, w; uint8_t i;
// are both buttons pushed? // are both buttons pushed?
if ((btn[0]._mask & BTN_PUSH) && (btn[1]._mask & BTN_PUSH)) { if ((btn[0]._mask & BTN_PUSH) && (btn[1]._mask & BTN_PUSH)) {
// are none held? // are none held?
@ -75,29 +76,10 @@ void ui_btn_push_cb(uint8_t idx)
// both buttons are pushed at the same time quickly, and not held // both buttons are pushed at the same time quickly, and not held
// this will toggle modes // this will toggle modes
mode++; mode++;
// parameter mode only works if a program is enabled to adjust
if (mode == MODE_PARAMETER) {
if (!userconf.ledprog_ena_mask) mode = MODE_RUN;
}
// parameter mode is the last mode
if (mode > MODE_PARAMETER) { if (mode > MODE_PARAMETER) {
mode = MODE_RUN; mode = MODE_RUN;
} }
// ensure a valid program is selected
if (mode == MODE_PARAMETER) {
w = preview_idx;
for (i = 0; i < 8; i++) {
w &= 0x7;
if (userconf.ledprog_ena_mask & (1 << w)) {
preview_idx = w;
break;
}
w++;
}
}
// reset any LED program // reset any LED program
led_rgb_firstrun(); led_rgb_firstrun();
@ -105,7 +87,6 @@ void ui_btn_push_cb(uint8_t idx)
// depending on the mode // depending on the mode
if (mode == MODE_PROGRAM) preview_idx = 0; if (mode == MODE_PROGRAM) preview_idx = 0;
if (mode == MODE_PARAMETER) { if (mode == MODE_PARAMETER) {
/*
preview_idx = 0; preview_idx = 0;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
if (userconf.ledprog_ena_mask & (1 << preview_idx)) { if (userconf.ledprog_ena_mask & (1 << preview_idx)) {
@ -113,7 +94,6 @@ void ui_btn_push_cb(uint8_t idx)
break; break;
} }
} }
*/
} }
return; return;
@ -179,17 +159,7 @@ void ui_btn_push_cb(uint8_t idx)
void ui_btn_hold_cb(uint8_t idx) void ui_btn_hold_cb(uint8_t idx)
{ {
switch (mode) {
case MODE_PARAMETER: {
switch (idx) {
case 0: {
if (rgb_prog_is_editing) {
userconf.ledprog_setting[preview_idx][0]++;
}
}
}
}
}
} }
void ui_btn_release_cb(uint8_t idx) void ui_btn_release_cb(uint8_t idx)
@ -219,9 +189,8 @@ void ui_btn_release_cb(uint8_t idx)
userconf.cursor_color++; userconf.cursor_color++;
userconf.cursor_color &= 0x3; userconf.cursor_color &= 0x3;
// force cursor to change immediately, force cursor on // force cursor to change immediately
cursor_flash = 0; cursor_flash = 0;
cursor_state = 0;
config_save_timer = UI_CONF_SAVE_TIMEOUT; config_save_timer = UI_CONF_SAVE_TIMEOUT;
@ -246,7 +215,8 @@ void ui_btn_release_cb(uint8_t idx)
* PROGRAM CHANGE MODE: cursor is on. * PROGRAM CHANGE MODE: cursor is on.
* *
* letters in RETRO show programs. by default, all are disabled. * letters in RETRO show programs. by default, all are disabled.
* selected program will flash. * enabled programs are bright. disabled programs are dim.
* selected program will flash. if program is on, will flash brightly. if off, it will flash dimly.
* *
* letters in TECH preview the currently selected program. * letters in TECH preview the currently selected program.
* letters in RETRO will each preview their own program (any flash / twinkle will always have idle light) * letters in RETRO will each preview their own program (any flash / twinkle will always have idle light)
@ -288,25 +258,32 @@ void ui_btn_release_cb(uint8_t idx)
*/ */
case MODE_PARAMETER: { case MODE_PARAMETER: {
switch (idx) { switch (idx) {
case 0: { // - top button: when editing disabled: selects the next program case 0: { // - top button: tapped or held: increment some parameter, with loop (speed, etc)
// when editing enabled: tapped or held: increments a value, with loop userconf.ledprog_setting[preview_idx][0]++;
break;
}
case 1: { // - bot button: when editing disabled: selects the next program
// when editing enabled: decrements some parameter, with loop (speed, etc)
// held: enables / disables editing the program (done in other callback)
if (rgb_prog_is_editing) { if (rgb_prog_is_editing) {
userconf.ledprog_setting[preview_idx][0]++; if (userconf.ledprog_setting[preview_idx][0]) {
userconf.ledprog_setting[preview_idx][0]--;
} else {
userconf.ledprog_setting[preview_idx][0] = 0xff;
}
} else { } else {
// select new program, except the last program, since that doesn't have a user editable config
w = preview_idx; w = preview_idx;
for (i = 0; i < 8; i++) { for (i = 0; i < 4; i++) {
w++; w++;
w &= 0x7; if (w > 4) w = 0;
if (userconf.ledprog_ena_mask & (1 << w)) { if (userconf.ledprog_ena_mask & (1 << w)) {
preview_idx = w; preview_idx = w;
break; break;
} }
} }
} }
break;
}
case 1: { // - bot button: enables / disables editing of selected program
rgb_prog_is_editing = !rgb_prog_is_editing;
break; break;
} }
@ -333,7 +310,7 @@ static void ui_cursor_flash()
cursor_state++; cursor_state++;
cursor_state &= 1; cursor_state &= 1;
// set new cursor rate, force cursor on // set new cursor rate
cursor_flash = cursor_flash_rates[flash] >> 1; cursor_flash = cursor_flash_rates[flash] >> 1;
// set all colors off // set all colors off
@ -344,41 +321,34 @@ static void ui_cursor_flash()
cursor_flash--; cursor_flash--;
// set brightness of led, if we're in an on state // set brightness of led, if we're in an on state
if (color < CONF_CURSOR_OFF) { if (cursor_state && (color < CONF_CURSOR_OFF)) {
if (cursor_state) { // first frame of on = not quite full brightness
// first frame of on = not quite full brightness level = (cursor_flash == cursor_flash_rates[flash] - 1) ? 160 : 255;
level = (cursor_flash == cursor_flash_rates[flash] - 1) ? 160 : 255;
// at final frames, dim // at final frames, dim
if (cursor_flash <= 4) { if (cursor_flash <= 4) {
level >>= (4 - cursor_flash); level >>= (4 - cursor_flash);
}
} }
}
// set the level on the cursor // set the level on the cursor
if (cursor[color] != level) { if (cursor[color] != level) {
cursor[color] = led_gamma(level); cursor[color] = led_gamma(level);
led_is_updated(); led_is_updated();
}
} else {
// clear any cursors that may have been left on
cursor[0] = 0;
cursor[1] = 0;
cursor[2] = 0;
} }
} }
break; break;
} }
case MODE_PROGRAM: { case MODE_PROGRAM: {
// cursor is on if this program is flagged as on // cursor is always off
cursor[0] = (userconf.ledprog_ena_mask & (1 << preview_idx)) ? 127 : 0; cursor[color] = 0;
break; break;
} }
case MODE_PARAMETER: { case MODE_PARAMETER: {
// cursor is on when program is being edited // cursor is always off
cursor[0] = rgb_prog_is_editing ? 127 : 0; cursor[color] = 0;
break; break;
} }
@ -388,7 +358,7 @@ static void ui_cursor_flash()
void ui_init() void ui_init()
{ {
btn[0].hold = 330 >> 1; btn[0].hold = 330 >> 1;
btn[0].repeat = (1000 / 20) >> 1; btn[0].repeat = 0; // (1000 / 20) >> 1;
btn[0].cb_push = ui_btn_push_cb; btn[0].cb_push = ui_btn_push_cb;
btn[0].cb_hold = ui_btn_hold_cb; btn[0].cb_hold = ui_btn_hold_cb;
btn[0].cb_release = ui_btn_release_cb; btn[0].cb_release = ui_btn_release_cb;
@ -400,30 +370,20 @@ void ui_init()
btn[1].cb_release = ui_btn_release_cb; btn[1].cb_release = ui_btn_release_cb;
} }
static void rgb_prog_timer_generate() {
uint32_t t;
t = prng_get16();
t *= (UI_PROG_RUNTIME_MAX - UI_PROG_RUNTIME_MIN);
t >>= 16;
rgb_prog_timer = t + UI_PROG_RUNTIME_MIN;
}
void ui_render() void ui_render()
{ {
uint8_t i; uint8_t i;
uint16_t w; uint16_t w;
uint32_t t;
uint8_t flash; uint8_t flash;
uint8_t new;
// deal with eeprom // deal with eeprom
if (config_save_timer) { if (config_save_timer) {
config_save_timer--; config_save_timer--;
if (!config_save_timer) { if (config_save_timer) {
userconf_save(); userconf_save();
} }
} }
@ -442,12 +402,9 @@ void ui_render()
} }
} }
tick++;
switch (mode) { switch (mode) {
case MODE_RUN: { // render an existing program case MODE_RUN: { // render an existing program
// ensure rear LED is not on tick++;
GPIOD->BCR = GPIO_Pin_0;
// set brightness from knob 32 times/second // set brightness from knob 32 times/second
// (the knob value updates less frequently, but we need to fade nicely) // (the knob value updates less frequently, but we need to fade nicely)
@ -474,48 +431,32 @@ void ui_render()
if (userconf.ledprog_ena_mask) { if (userconf.ledprog_ena_mask) {
// fade and change programs depending on the timer // fade and change programs depending on the timer
rgb_prog_timer--; rgb_prog_timer--;
if (rgb_prog_timer) {
// actually run the program
led_rgbprog[rgb_prog_idx](LED_RGBPROG_NORMAL, tick);
}
// todo: the fade goes way too fast and looks bad
// make it look nicer
if (rgb_prog_timer <= 17) { if (rgb_prog_timer <= 17) {
led_is_updated(); if (rgb_prog_timer > 9) {
// fade out current program
if (rgb_prog_timer == 17) { w = (rgb_prog_timer & 0x1f) - 10;
w = prng_get8(); for (i = 0; i < 9; i++) {
w &= 0x7; rgb[i][0] >>= w;
for (i = 0; i < 8; i++) { rgb[i][1] >>= w;
new = (w + i) & 0x7; rgb[i][2] >>= w;
if (userconf.ledprog_ena_mask & (1 << new)) {
// bias selecting a new program
if (rgb_prog_idx != new) {
rgb_prog_idx = new;
led_rgb_firstrun();
break;
}
}
}
// no new program was selected (likely only one program selected?)
// so just reset the timer
if (i == 8) {
rgb_prog_timer_generate();
}
}
else if (rgb_prog_timer > 9) {
// fade out current program
w = 7 - (rgb_prog_timer - 10);
for (i = 0; i < 9; i++) {
rgb[i][0] >>= w;
rgb[i][1] >>= w;
rgb[i][2] >>= w;
} }
} else if (rgb_prog_timer > 7) { } else if (rgb_prog_timer > 7) {
// select a new random program
if (rgb_prog_timer == 8) {
w = prng_get8();
w &= 0x3;
if (w == rgb_prog_idx) w++;
for (i = 0; i < 7; i++) {
if (userconf.ledprog_ena_mask & (1 << ((w + i) & 0x7))) {
rgb_prog_idx = w;
break;
}
}
led_rgb_firstrun();
}
// clear out for now, since new program hasn't actually been run // clear out for now, since new program hasn't actually been run
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
rgb[i][0] = 0; rgb[i][0] = 0;
@ -524,7 +465,7 @@ void ui_render()
} }
} else if (rgb_prog_timer >= 1) { } else if (rgb_prog_timer >= 1) {
// fade in new program // fade in new program
w = (rgb_prog_timer & 0x7); w = 8 - (rgb_prog_timer & 0x1f);
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
rgb[i][0] >>= w; rgb[i][0] >>= w;
rgb[i][1] >>= w; rgb[i][1] >>= w;
@ -532,14 +473,21 @@ void ui_render()
} }
} else { // 0 } else { // 0
// randomize next program timing // randomize next program timing
rgb_prog_timer_generate(); t = prng_get16();
t *= (UI_PROG_RUNTIME_MAX - UI_PROG_RUNTIME_MIN);
t >>= 16;
rgb_prog_timer = t + UI_PROG_RUNTIME_MIN;
} }
// actually run the program
led_rgbprog[rgb_prog_idx](LED_RGBPROG_NORMAL, tick);
} }
} }
// temp: remove me once buttons are tested and working // temp: remove me once buttons are tested and working
//rgb_prog_idx = 0; rgb_prog_idx = 0;
//led_rgbprog[rgb_prog_idx](LED_RGBPROG_NORMAL, tick); led_rgbprog[rgb_prog_idx](LED_RGBPROG_NORMAL, tick);
break; break;
} }
@ -548,11 +496,6 @@ void ui_render()
// always postpone config saving // always postpone config saving
config_save_timer = UI_CONF_SAVE_TIMEOUT; config_save_timer = UI_CONF_SAVE_TIMEOUT;
// rapidly flash lsens
if ((tick >> 3) & 1) {
GPIOD->OUTDR ^= GPIO_Pin_0;
}
// always increase brightness of LEDs while editing // always increase brightness of LEDs while editing
is31fl3729_set_global_current(FL3729_ADDR, FL3729_GCC_MAX); is31fl3729_set_global_current(FL3729_ADDR, FL3729_GCC_MAX);
@ -561,27 +504,22 @@ void ui_render()
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
// render // render
if (led_rgbprog[i]) { led_rgbprog[i](LED_RGBPROG_PREVIEW | preview_idx, tick);
led_rgbprog[i](LED_RGBPROG_PREVIEW | preview_idx, tick);
}
if (preview_idx == i) { if (preview_idx == i) {
// flash the selected output // flash the selected output
if (flash & 1) { if (flash & 1) {
rgb[i][0] = 16; rgb[i][0] >>= 5;
rgb[i][1] = 16; rgb[i][1] >>= 5;
rgb[i][2] = 16; rgb[i][2] >>= 5;
//rgb[i][0] >>= 3;
//rgb[i][1] >>= 3;
//rgb[i][2] >>= 3;
} }
} else { } else {
// dim inactive outputs // dim inactive outputs
//if (!(userconf.ledprog_ena_mask & (1 << i))) { if (!(userconf.ledprog_ena_mask & (1 << i))) {
// rgb[i][0] >>= 1; rgb[i][0] >>= 3;
// rgb[i][1] >>= 1; rgb[i][1] >>= 3;
// rgb[i][2] >>= 1; rgb[i][2] >>= 3;
//} }
} }
} }
@ -592,11 +530,6 @@ void ui_render()
// always postpone config saving // always postpone config saving
config_save_timer = UI_CONF_SAVE_TIMEOUT; config_save_timer = UI_CONF_SAVE_TIMEOUT;
// slowly flash lsnes
if ((tick >> 5) & 1) {
GPIOD->OUTDR ^= GPIO_Pin_0;
}
// always increase brightness of LEDs while editing // always increase brightness of LEDs while editing
is31fl3729_set_global_current(FL3729_ADDR, FL3729_GCC_MAX); is31fl3729_set_global_current(FL3729_ADDR, FL3729_GCC_MAX);
@ -611,25 +544,20 @@ void ui_render()
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
// render // render
if (userconf.ledprog_ena_mask & (1 << i)) { if (userconf.ledprog_ena_mask & (1 << i)) {
if (led_rgbprog[i]) { led_rgbprog[i](LED_RGBPROG_PREVIEW | preview_idx, tick);
led_rgbprog[i](LED_RGBPROG_PREVIEW | preview_idx, tick);
}
if (preview_idx == i) { if (preview_idx == i) {
// flash the selected output // flash the selected output
if (flash & 1) { if (flash & 1) {
rgb[i][0] = 32; rgb[i][0] >>= 5;
rgb[i][1] = 32; rgb[i][1] >>= 5;
rgb[i][2] = 32; rgb[i][2] >>= 5;
//rgb[i][0] >>= 5;
//rgb[i][1] >>= 5;
//rgb[i][2] >>= 5;
} }
} else { } else {
// dim the other outputs // dim the other outputs
// rgb[i][0] >>= 2; rgb[i][0] >>= 2;
// rgb[i][1] >>= 2; rgb[i][1] >>= 2;
// rgb[i][2] >>= 2; rgb[i][2] >>= 2;
} }
} else { } else {
// clear the output if it isn't enabled // clear the output if it isn't enabled