diff --git a/firmware/user/ch32v20x_conf.h b/firmware/user/ch32v20x_conf.h index d1eeb38..d379f52 100644 --- a/firmware/user/ch32v20x_conf.h +++ b/firmware/user/ch32v20x_conf.h @@ -14,7 +14,7 @@ #include "ch32v20x_adc.h" #include "ch32v20x_bkp.h" -#include "ch32v20x_can.h" +//#include "ch32v20x_can.h" #include "ch32v20x_crc.h" #include "ch32v20x_dbgmcu.h" #include "ch32v20x_dma.h" @@ -26,7 +26,7 @@ #include "ch32v20x_pwr.h" #include "ch32v20x_rcc.h" #include "ch32v20x_rtc.h" -#include "ch32v20x_spi.h" +//#include "ch32v20x_spi.h" #include "ch32v20x_tim.h" #include "ch32v20x_usart.h" #include "ch32v20x_wwdg.h" diff --git a/firmware/user/main.c b/firmware/user/main.c index d371c54..1d055eb 100644 --- a/firmware/user/main.c +++ b/firmware/user/main.c @@ -50,13 +50,6 @@ void gpio_init() gpio.GPIO_Speed = GPIO_Speed_2MHz; - // per the datasheet, PB8 is an output-only pin on this specific submodel. - // however, the datasheet later conflicts and says this is A/I/O pin. - // so we'll try to use it as an input anyway. - gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; - gpio.GPIO_Pin = GPIO_Pin_8; - GPIO_Init(GPIOB, &gpio); - // unused osc pins gpio.GPIO_Mode = GPIO_Mode_IPD; gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_7; @@ -98,7 +91,7 @@ void gpio_init() gpio.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOA, &gpio); - // I2C on-board comms + // I2C SCL, SCA for on-board devices gpio.GPIO_Mode = GPIO_Mode_AF_OD; gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_Init(GPIOB, &gpio); @@ -139,6 +132,10 @@ int main(void) // configure systick interrupt systick_init(); + rgb[0] = 10; + rgb[1] = 10; + rgb[2] = 10; + // do system shit while(1) { __WFI(); diff --git a/firmware/user/src/31fl3729.c b/firmware/user/src/31fl3729.c index 33a0966..f4f492e 100644 --- a/firmware/user/src/31fl3729.c +++ b/firmware/user/src/31fl3729.c @@ -9,27 +9,36 @@ #include "i2c.h" -/* sends the IS31FL3729 general config. + +void is31fl3729_set_global_current(uint8_t i2c_addr, uint8_t global_current) +{ + i2c_write_reg_8b(i2c_addr, FL3729_REG_G_CURRENT, global_current); +} + +void is31fl3729_set_scaling_current(uint8_t i2c_addr, uint8_t cs, uint8_t current) +{ + if (cs > 0xf) return; + + i2c_write_reg_8b(i2c_addr, FL3729_REG_SCALING + cs, current); +} + +/* sends the IS31FL3729 initial config. * does not configure per-channel current sink limits; do that separately. * does not configure other sane defaults; do that separately. */ - 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); + is31fl3729_set_global_current(i2c_addr, global_current); } uint8_t is31fl3729_get_addr(uint8_t adpin) @@ -38,26 +47,14 @@ 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, ¤t, 1); -} - -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, ¤t, 1); -} - /* * 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; + if (count > 16) count = 16; i2c_write_addr1b(i2c_addr, FL3729_REG_SCALING, current, count); } @@ -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; diff --git a/firmware/user/src/31fl3729.h b/firmware/user/src/31fl3729.h index b320b47..7e02317 100644 --- a/firmware/user/src/31fl3729.h +++ b/firmware/user/src/31fl3729.h @@ -25,24 +25,24 @@ #define FL3729_REG_OUTPUT 0x01 #define FL3729_REG_SCALING 0x90 #define FL3729_REG_CONFIG 0xA0 -#define FL3729_REG_G_CURRENT 0xA1 // global current -#define FL3729_REG_PUPD 0xB0 // pull up / pull down -#define FL3729_REG_SS 0xB1 // spread spectrum +#define FL3729_REG_G_CURRENT 0xA1 // global current +#define FL3729_REG_PUPD 0xB0 // pull up / pull down +#define FL3729_REG_SS 0xB1 // spread spectrum #define FL3729_REG_PWM 0xB2 #define FL3729_REG_RESET 0xCF -#define FL3729_GCC_MAX 64 // maximum global current level +#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_global_current(uint8_t i2c_addr, uint8_t global_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); diff --git a/firmware/user/src/config.c b/firmware/user/src/config.c index 29613b0..53ed9a4 100644 --- a/firmware/user/src/config.c +++ b/firmware/user/src/config.c @@ -90,7 +90,7 @@ static uint16_t checksum() void userconf_load() { - uint8_t valid; + uint8_t valid = 0; uint8_t page = CONF_FLASH_PAGES; diff --git a/firmware/user/src/i2c.c b/firmware/user/src/i2c.c index f4e031b..cdcbf77 100644 --- a/firmware/user/src/i2c.c +++ b/firmware/user/src/i2c.c @@ -15,21 +15,17 @@ -#define I2C_TIMEOUT 0xffff +#define I2C_TIMEOUT 0xefff #define I2C_TIMEOUT_ACK_POLL 0x180 -static uint32_t timeout; +static uint16_t timeout; void i2c_init() { - GPIO_InitTypeDef gpio = {0}; I2C_InitTypeDef i2c = {0}; - gpio.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; - gpio.GPIO_Mode = GPIO_Mode_AF_OD; - gpio.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_Init(GPIOC, &gpio); + // ensure GPIO pins are configured before initializing i2c.I2C_ClockSpeed = 666666; i2c.I2C_Mode = I2C_Mode_I2C; @@ -100,7 +96,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--); @@ -122,7 +118,9 @@ int8_t i2c_write_addr1b(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) if (!timeout) return -4; while (len) { - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) != RESET) { + // fixme: can get stuck here if address isn't found. + // somehow all the above passes but this will fail + if (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) != RESET) { I2C_SendData(I2C1, *data++); len--; while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); diff --git a/firmware/user/src/i2c.h b/firmware/user/src/i2c.h index 78efdb0..a17fe48 100644 --- a/firmware/user/src/i2c.h +++ b/firmware/user/src/i2c.h @@ -17,7 +17,7 @@ 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); diff --git a/firmware/user/src/led.c b/firmware/user/src/led.c index 0047b93..4167c47 100644 --- a/firmware/user/src/led.c +++ b/firmware/user/src/led.c @@ -10,16 +10,16 @@ #define FL3729_SW_COUNT 4 // switches utilized #define FL3729_CS_COUNT 16 // current sink outputs used by chip -#define FL3729_G_CURRENT 16 // initial global current setting +#define FL3729_G_CURRENT 15 // initial global current setting -const uint8_t cs_currents[FL3729_CS_COUNT] = { - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 +static const uint8_t cs_currents[FL3729_CS_COUNT] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; -const uint16_t pwm_cie_256in_1024out[] = { +static const uint16_t pwm_cie_256in_1024out[] = { 0, 0, 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, 15, 16, 17, 17, 18, 19, 19, 20, 21, 22, 22, 23, 24, 25, 26, 27, @@ -70,10 +70,10 @@ void led_init() // configure matrix is31fl3729_init(FL3729_ADDR, - FL3729_CONF_SHDN_DIS | FL3729_CONF_OSDE_OFF | FL3729_CONF_MATRIX_4x16, + FL3729_CONF_SSD_NRML | FL3729_CONF_OSDE_OFF | FL3729_CONF_MATRIX_4x16, FL3729_G_CURRENT); - is31fl3729_set_scaling_current_multi(FL3729_ADDR, (uint8_t *)cs_currents, sizeof(cs_currents)); + is31fl3729_set_scaling_current_multi(FL3729_ADDR, cs_currents, FL3729_CS_COUNT); // configure rear RGBLED @@ -94,7 +94,7 @@ void led_init() TIM_CtrlPWMOutputs(RGB_TIM, ENABLE); TIM_OC1PreloadConfig(RGB_TIM, TIM_OCPreload_Disable); TIM_ARRPreloadConfig(RGB_TIM, ENABLE); - TIM_Cmd(TIM1, ENABLE); + TIM_Cmd(RGB_TIM, ENABLE); } void led_matrix_is_updated() @@ -104,9 +104,41 @@ void led_matrix_is_updated() void led_matrix_send() { + int8_t i, j; + uint8_t out[64]; + // only render when there's something to render if (led_matrix_updated) { - is31fl3729_set_outputs(FL3729_ADDR, 1, (uint8_t *)&led, FL3729_SW_COUNT * FL3729_CS_COUNT); + // convert led matrix + j = 0; + + // the pepper body is linear; starts from top left, + // goes counter-clockwise, and ends at the top part + for (i = 0; i < LED_PEP_COUNT; i += 4) { + out[j + (16*0)] = led.section.pep[i + 0]; + out[j + (16*1)] = led.section.pep[i + 1]; + out[j + (16*2)] = led.section.pep[i + 2]; + out[j + (16*3)] = led.section.pep[i + 3]; + j++; + } + + // pepper hat is a bit more fucked up. I laid this out + // with the elements backwards. rushjob fuckup. oops. + // I would like to start from the bottom right, counter clockwise, + // ending up at pepper's top right. + // for (i = 0; i < LED_HAT_COUNT; i += 4) { // clockwise starting from bottom right + j = 15; + for (i = 0; i < LED_HAT_COUNT; i += 4) { + out[j + (16*0)] = led.section.hat[i + 0]; + out[j + (16*1)] = led.section.hat[i + 1]; + out[j + (16*2)] = led.section.hat[i + 2]; + out[j + (16*3)] = led.section.hat[i + 3]; + j--; + } + + // and send + is31fl3729_set_outputs(FL3729_ADDR, 1, out, FL3729_SW_COUNT * FL3729_CS_COUNT); + led_matrix_updated = 0; } } diff --git a/firmware/user/src/led.h b/firmware/user/src/led.h index e68c379..e5f4702 100644 --- a/firmware/user/src/led.h +++ b/firmware/user/src/led.h @@ -16,7 +16,7 @@ #define FL3729_ADDR (FL3729_BASE_ADDR | FL3729_ADPIN_GND) #define LED_PEP_COUNT 36 // all pepper body LEDs -#define LED_PEP_NOTOP 31 // pepper body LEDs not including the part under the hat +#define LED_PEP_NOTOP 30 // pepper body LEDs not including the part under the hat #define LED_HAT_COUNT 28 // all pepper hat LEDs #define LED_ALL_COUNT (LED_PEP_COUNT + LED_HAT_COUNT) @@ -24,10 +24,13 @@ typedef struct LedMatrix { union { - uint8_t pep[LED_PEP_COUNT]; - uint8_t hat[LED_HAT_COUNT]; + uint8_t all[LED_ALL_COUNT]; + struct section { + uint8_t pep[LED_PEP_COUNT]; + uint8_t hat[LED_HAT_COUNT]; + } section; }; - uint8_t all[LED_ALL_COUNT]; + } LedMatrix; diff --git a/firmware/user/src/ledprog_pep.c b/firmware/user/src/ledprog_pep.c index cac1365..5e6de29 100644 --- a/firmware/user/src/ledprog_pep.c +++ b/firmware/user/src/ledprog_pep.c @@ -57,17 +57,17 @@ static void pep_0_flash(uint8_t tick) pep_work[1] ^= 0x1; if (pep_work[1] & 1) { for (i = 0; i < LED_PEP_COUNT; i++) { - led.pep[i] = out; + led.section.pep[i] = out; } for (i = 0; i < LED_HAT_COUNT; i++) { - led.hat[i] = out; + led.section.hat[i] = out; } } else { for (i = 0; i < LED_PEP_COUNT; i++) { - led.pep[i] = 0; + led.section.pep[i] = 0; } for (i = 0; i < LED_HAT_COUNT; i++) { - led.hat[i] = 0; + led.section.hat[i] = 0; } } @@ -94,7 +94,7 @@ static void pep_1_sizzle(uint8_t tick) rnd2 = prng_get32(); // are we going to spike an LED? - trig = (trig > 0xf2) ? 1 : 0; + trig = (trig > 0xfa) ? 1 : 0; if (trig) { // which LED? @@ -106,13 +106,18 @@ static void pep_1_sizzle(uint8_t tick) for (i = 0; i < LED_PEP_NOTOP; i++) { if (trig && (rnd == i)) { // go bright on this LED - led.pep[i] = 200; + led.section.pep[i] = 0xcf; + // also on the prior LED + if (i) + led.section.pep[i - 1] = 0x80; + else if (i < LED_PEP_NOTOP - 1) + led.section.pep[i + 1] = 0x80; } else { - if (led.pep[i] < 48) led.pep[i]++; - else if (led.pep[i] > 64) led.pep[i]--; + if (led.section.pep[i] < 4) led.section.pep[i]++; + else if (led.section.pep[i] > 36) led.section.pep[i]--; else { - if (rnd2 & 1) led.pep[i]++; - else led.pep[i]--; + if (rnd2 & 1) led.section.pep[i]++; + else led.section.pep[i]--; } rnd2 >>= 1; @@ -121,8 +126,10 @@ static void pep_1_sizzle(uint8_t tick) // the hat just gets lit normally for (i = 0; i < LED_HAT_COUNT; i++) { - led.hat[i] = 200; + led.section.hat[i] = 0x3f; } + + led_matrix_is_updated(); } /* @@ -148,12 +155,12 @@ static void pep_2_loops(uint8_t tick) bot >>= 8; for (i = 0; i < LED_PEP_COUNT; i++) { - if (i == bot) led.pep[i] = 255; - else if (led.pep[i]) led.pep[i]--; + if (i == bot) led.section.pep[i] = 255; + else if (led.section.pep[i]) led.section.pep[i]--; } for (i = 0; i < LED_HAT_COUNT; i++) { - if (i == top) led.hat[i] = 255; - else if (led.hat[i]) led.hat[i]--; + if (i == top) led.section.hat[i] = 255; + else if (led.section.hat[i]) led.section.hat[i]--; } } @@ -169,10 +176,10 @@ static void pep_3_neon_sign(uint8_t tick) // todo: implement flickering on/off for (i = 0; i < LED_PEP_COUNT; i++) { - led.pep[i] = (tick & 1) ? 255 : 200; + led.section.pep[i] = (tick & 1) ? 255 : 200; } for (i = 0; i < LED_HAT_COUNT; i++) { - led.hat[i] = (tick & 1) ? 255 : 200; + led.section.hat[i] = (tick & 1) ? 255 : 200; } led_matrix_is_updated(); @@ -195,10 +202,10 @@ static void pep_4_alternate(uint8_t tick) if (!pep_work[0]) { for (i = 0; i < LED_PEP_COUNT; i++) { - led.pep[i] = (pep_work[1] & 1) ? hi : lo; + led.section.pep[i] = (pep_work[1] & 1) ? hi : lo; } for (i = 0; i < LED_HAT_COUNT; i++) { - led.hat[i] = (pep_work[1] & 1) ? lo : hi; + led.section.hat[i] = (pep_work[1] & 1) ? lo : hi; } pep_work[0] = userconf.pep_conf[PEP_4][PEP_4_CONF_FLASH_RATE]; @@ -270,17 +277,17 @@ static void pep_5_nom(uint8_t tick) // set pepper body LEDs to initial on state (or off if pepper is fully eated) for (i = 0; i < LED_PEP_NOTOP; i++) { - led.pep[i] = end ? 255 : 0; + led.section.pep[i] = end ? 255 : 0; } // in this mode we need to light up the top pepper line for (i = LED_PEP_NOTOP; i < LED_PEP_COUNT; i++) { - led.pep[i] = 200; + led.section.pep[i] = 200; } // clear eated pepper portions, gonna cry if (end) { for (i = start; i < end; i++) { - led.pep[i] = 0; + led.section.pep[i] = 0; } } @@ -294,7 +301,7 @@ static void pep_5_nom(uint8_t tick) } case 3: { // regen the pepper - if (led.pep[pep_work[1]] >= 0xfe) { + if (led.section.pep[pep_work[1]] >= 0xfe) { // next segment pep_work[1]++; if (pep_work[i] >= (LED_PEP_NOTOP - pep_work[i])) { @@ -302,9 +309,9 @@ static void pep_5_nom(uint8_t tick) pep_work[0] = 0; } } else { - led.pep[pep_work[1]] += 2; + led.section.pep[pep_work[1]] += 2; if (pep_work[1]) { - led.pep[LED_PEP_NOTOP - pep_work[1]] = led.pep[pep_work[1]]; + led.section.pep[LED_PEP_NOTOP - pep_work[1]] = led.section.pep[pep_work[1]]; } led_matrix_is_updated(); } @@ -368,10 +375,10 @@ void ledprog_pep_init() // reset LEDs for (i = 0; i < LED_PEP_COUNT; i++) { - led.pep[i] = 0; + led.section.pep[i] = 0; } for (i = 0; i < LED_HAT_COUNT; i++) { - led.hat[i] = 0; + led.section.hat[i] = 0; } // global program initialization diff --git a/firmware/user/src/ui.c b/firmware/user/src/ui.c index 229a180..f0fa26d 100644 --- a/firmware/user/src/ui.c +++ b/firmware/user/src/ui.c @@ -59,9 +59,40 @@ void ui_init() btn[1].cb_release = ui_btn_release_cb; } +uint8_t tmp; + void ui_render() { tick++; - ledprog_pep[0](tick); + switch (mode) { + case MODE_RUN: { + break; + } + + case MODE_PROGRAM: { + break; + } + + case MODE_PARAMETER: { + break; + } + } + + // temporary: testing + ledprog_pep[1](tick); + /* + if ((tick & 3) == 3) { + + tmp++; + tmp &= 0x3f; + + for (uint8_t i = 0; i < 64; i++) { + if (i == tmp) led.all[i] = 255; + else led.all[i] = 0; + } + + led_matrix_is_updated(); + } + */ }