crashtest-r0ket/firmware/applications/final/flame_rgb.c

197 lines
5.5 KiB
C

/*
flame m0dul with RGB (rev c) - https://github.com/schneider42/flame
LED driver is a PCA9633
*/
#include "basic/basic.h"
#include "core/i2c/i2c.h"
#include "basic/config.h"
#include "basic/xxtea.h"
#include "filesystem/util.h"
#define FLAME_I2C_WRITE 0xC6
#define FLAME_I2C_READ 0xC7
#define FLAME_I2C_CR_MODE1 0x00
#define FLAME_I2C_CR_MODE2 0x01
#define FLAME_I2C_CR_PWM0 0x02
#define FLAME_I2C_CR_PWM1 0x03
#define FLAME_I2C_CR_PWM2 0x04
#define FLAME_I2C_CR_PWM3 0x05
#define FLAME_I2C_CR_GRPPWM 0x06
#define FLAME_I2C_CR_GRPFREQ 0x07
#define FLAME_I2C_CR_LEDOUT 0x08
#define FLAME_I2C_LED0_OFF 0x00
#define FLAME_I2C_LED0_FULL 0x01
#define FLAME_I2C_LED0_INDY 0x02
#define FLAME_I2C_LED0_GRP 0x03
#define FLAME_I2C_LED1_OFF 0x00
#define FLAME_I2C_LED1_FULL 0x04
#define FLAME_I2C_LED1_INDY 0x08
#define FLAME_I2C_LED1_GRP 0x0c
#define FLAME_I2C_LED2_OFF 0x00
#define FLAME_I2C_LED2_FULL 0x10
#define FLAME_I2C_LED2_INDY 0x20
#define FLAME_I2C_LED2_GRP 0x30
#define FLAME_I2C_LED3_OFF 0x00
#define FLAME_I2C_LED3_FULL 0x40
#define FLAME_I2C_LED3_INDY 0x80
#define FLAME_I2C_LED3_GRP 0xC0
#define FLAME_OFF 0x00
#define FLAME_UP 0x01
#define FLAME_UP_WAIT 0x02
#define FLAME_DOWN 0x03
#define FLAME_DOWN_WAIT 0x04
/**************************************************************************/
#define flameBrightnessMax GLOBAL(flamemax)
#define flameBrightnessMin GLOBAL(flamemin)
#define flameSpeedUp GLOBAL(flamespeed)
#define flameSpeedDown GLOBAL(flamespeed)
#define flameWaitUp GLOBAL(flamemaxw)
#define flameWaitDown GLOBAL(flameminw)
#define nick GLOBAL(nickname)
static uint32_t flameRGBSetI2C(uint8_t cr, uint8_t value) {
I2CMasterBuffer[0] = FLAME_I2C_WRITE;
I2CMasterBuffer[1] = cr;
I2CMasterBuffer[2] = value;
I2CWriteLength = 3;
I2CReadLength = 0;
return i2cEngine();
}
uint8_t flameRGBEnabled = 0;
uint8_t flameRGBMode = FLAME_OFF;
uint8_t flameRGBI2Cpwm = 0;
uint8_t flameRGBTicks = 0;
uint8_t rgbData[24];
uint8_t rgbDataSize = 0;
uint8_t rgbDataOffset = 0;
void setFlameRGBPWM() {
flameRGBSetI2C(FLAME_I2C_CR_GRPPWM, flameRGBI2Cpwm); // set pwm
}
void setFlameRGBColor() {
if (rgbDataSize > 2) {
flameRGBSetI2C(FLAME_I2C_CR_PWM0, rgbData[rgbDataOffset]);
flameRGBSetI2C(FLAME_I2C_CR_PWM3, rgbData[rgbDataOffset + 1]);
flameRGBSetI2C(FLAME_I2C_CR_PWM2, rgbData[rgbDataOffset + 2]);
if (rgbDataSize >= rgbDataOffset + 5) {
rgbDataOffset += 3;
} else {
rgbDataOffset = 0;
}
} else {
// generate a hash from the nickname
uint32_t hash[4];
uint32_t const key[4] = {0, 0, 0, 0};
xxtea_cbcmac(hash, (uint32_t *)nick, 4, key);
// set color, LED0 = red, LED1 = unused, LED2 = blue, LED3 = green
int i;
uint8_t regs[] = {FLAME_I2C_CR_PWM0, FLAME_I2C_CR_PWM1,
FLAME_I2C_CR_PWM2, FLAME_I2C_CR_PWM3 };
for(i=0; i<4; i++)
flameRGBSetI2C(regs[i], hash[i] & 0xFF);
}
}
void tick_flame_rgb(void) { // every 10ms
static char night=0;
if (!flameRGBEnabled) {
return;
}
if (night != isNight()) {
night = isNight();
if (!night) {
flameRGBMode = FLAME_OFF;
flameRGBI2Cpwm = 0;
push_queue(&setFlameRGBPWM);
};
};
flameRGBTicks++;
if (flameRGBI2Cpwm > flameBrightnessMax) {
flameRGBI2Cpwm = flameBrightnessMax;
}
if (flameRGBI2Cpwm < flameBrightnessMin) {
flameRGBI2Cpwm = flameBrightnessMin;
}
if (flameRGBMode == FLAME_OFF) {
if (isNight()) {
flameRGBTicks = 0;
flameRGBMode = FLAME_UP;
push_queue(&setFlameRGBColor);
}
}
if (flameRGBMode == FLAME_UP) {
if (0xFF - flameRGBI2Cpwm >= flameSpeedUp ) {
flameRGBI2Cpwm += flameSpeedUp;
} else {
flameRGBI2Cpwm = 0xFF;
}
push_queue(&setFlameRGBPWM);
if (flameRGBI2Cpwm >= flameBrightnessMax) {
flameRGBMode = FLAME_UP_WAIT;
flameRGBTicks = 0;
}
}
if (flameRGBMode == FLAME_UP_WAIT) {
if (flameRGBTicks >= flameWaitUp) {
flameRGBMode = FLAME_DOWN;
}
}
if (flameRGBMode == FLAME_DOWN) {
if (flameSpeedDown <= flameRGBI2Cpwm) {
flameRGBI2Cpwm -= flameSpeedDown;
} else {
flameRGBI2Cpwm = 0x00;
}
push_queue(&setFlameRGBPWM);
if (flameRGBI2Cpwm <= flameBrightnessMin) {
flameRGBMode = FLAME_DOWN_WAIT;
flameRGBTicks = 0;
}
}
if (flameRGBMode == FLAME_DOWN_WAIT) {
if (flameRGBTicks >= flameWaitDown) {
flameRGBMode = FLAME_OFF;
}
}
}
void init_flame_rgb(void) {
i2cInit(I2CMASTER); // Init I2C
flameRGBEnabled = (flameRGBSetI2C(FLAME_I2C_CR_MODE1, 0x00) == I2CSTATE_ACK); // probe i2c and enable flame if present
if (!flameRGBEnabled)
return;
// enable individual PWN and group PWN for LED0, LED3 and LED2 and disable LED1
flameRGBSetI2C(FLAME_I2C_CR_LEDOUT, FLAME_I2C_LED0_GRP | FLAME_I2C_LED1_OFF | FLAME_I2C_LED2_GRP | FLAME_I2C_LED3_GRP);
flameRGBSetI2C(FLAME_I2C_CR_GRPPWM, 0x00); // overall dimming
rgbDataSize = readTextFile("FLAME.RGB", rgbData, 24);
enableConfig(CFG_TYPE_FLAME,1);
}