// leds.ch.txt (ver 8/13/18) ltc3219 peripheral driver /* ltc3219.h */ #ifndef _ltc3219_h #define _ltc3219_h #define LTC3219_I2C_ADDR 0x1b #define LTC3219_COMMAND 0x00 #define LTC3219_COMMAND_FORCE_2X 0x08 #define LTC3219_COMMAND_FORCE_1P5 0x04 #define LTC3219_COMMAND_QUICK_WRT 0x02 #define LTC3219_COMMAND_GRADATION 0x01 // #define LTC3219_ULED1 0x01 #define LTC3219_ULED2 0x02 #define LTC3219_ULED3 0x03 #define LTC3219_ULED4 0x04 #define LTC3219_ULED5 0x05 #define LTC3219_ULED6 0x06 #define LTC3219_ULED7 0x07 #define LTC3219_ULED8 0x08 #define LTC3219_ULED9 0x09 // #define LTC3219_ULED_DAC_MASK 0x3f #define LTC3219_ULED_MODE_MASK 0xc0 #define LTC3219_ULED_NORMAL 0x00 #define LTC3219_ULED_BLINK 0x40 #define LTC3219_ULED_GRADATION 0x80 #define LTC3219_ULED_GPIO 0xc0 // #define LTC3219_ENABLE 0x0A // #define LTC3219_ULED1_ENU 0x01 #define LTC3219_ULED2_ENU 0x02 #define LTC3219_ULED3_ENU 0x04 #define LTC3219_ULED4_ENU 0x08 #define LTC3219_ULED5_ENU 0x10 #define LTC3219_ULED6_ENU 0x20 #define LTC3219_ULED7_ENU 0x40 #define LTC3219_ULED8_ENU 0x80 // #define LTC3219_TIMING 0x0B #define LTC3219_ULED9_ENU 0x01 #define LTC3219_TIMING_RAMP_MASK 0x06 #define LTC3219_TIMING_RAMP_BLINK 0x18 #endif /* _ltc3219_h */ /* leds.h */ #ifndef _leds_h #define _leds_h #ifdef CONFIG_LEDS void ledsInit(void); void ledsTask(void); void ledsSet(U8 bus, U8 reg, U8 val); U8 ledsReg(U8 bus, U8 reg); #else // satisfy main.c #define ledsInit() #define ledsTask() #endif /* CONFIG_LEDS */ #endif /* _leds_h */ /* leds.c */ #include #include "compiler_defs.h" #include "processor.h" #include "config.h" #include "main.h" #include "i2c.h" #include "ltc3219.h" #include "leds.h" // example ltc3219 configuration // #define CONFIG_LEDS /* bus dev cmd ena cnf led dac */ // #define CONFIG_LEDS_DEVS {0x00, 0x55, 0x00, 0x00, 0x01, 0x09, 0x4a} #ifdef CONFIG_LEDS static struct { U8 bus; // peripheral bus U8 dev; // device select U8 cmd; // led control select U8 ena; // led control select U8 cnf; // gradation behavior U8 led; // initial led mode/dac U8 dac; // settings on power up } code ledsDevs[] = {CONFIG_LEDS_DEVS}; #define LEDS_NUM_DEVS (sizeof(ledsDevs) / sizeof(ledsDevs[0])) static struct { // 0x00 enum {idleLS, waitCmdLS, waitEnaLS, waitCnfLS, waitLedLS} state; U8 index; struct { U8 cmdCur, cmdReq; U8 enaCur, enaReq; U8 cnfCur, cnfReq; U8 ledCur, ledReq; U8 dac[9], dacReq; // shadow settings } dev[LEDS_NUM_DEVS]; struct i2cRequestS i2c; U8 buffer[2]; } xdata leds; void ledsInit(void) { U8 i,j; memset(&leds, 0, sizeof(leds)); for (i = 0; i < LEDS_NUM_DEVS; i++) { leds.dev[i].cmdCur = ~ledsDevs[i].cmd; // force init leds.dev[i].cmdReq = ledsDevs[i].cmd; leds.dev[i].enaCur = ~ledsDevs[i].ena; // force init leds.dev[i].enaReq = ledsDevs[i].ena; leds.dev[i].cnfCur = ~ledsDevs[i].cnf; // force init leds.dev[i].cnfReq = ledsDevs[i].cnf; for (j = 0; j < 9; j++) { // on powerup, init selected if (leds.dev[i].ledReq == j) { // led w/dac mod/val leds.dev[i].ledCur = ~ledsDevs[i].led; leds.dev[i].ledReq = ledsDevs[i].led; leds.dev[i].dacReq = ~ledsDevs[i].dac; leds.dev[i].dac[j] = ledsDevs[i].dac; } else { leds.dev[i].dac[j] = 0x00; } } } leds.index = 0; leds.i2c.tx = leds.buffer; leds.i2c.rx = leds.buffer; leds.state = idleLS; } // set ULED1 to blink at mid current value 0x20 of 0x3f // ledsSet(0, LTC3219_ULED1, LTC3219_ULED_BLINK | 0x20); void ledsSet(U8 bus, U8 reg, U8 val) { if (bus < LEDS_NUM_DEVS && reg < 12) { switch (reg) { case 0 : leds.dev[bus].cmdCur = val; break; case 10 : leds.dev[bus].enaCur = val; break; case 11 : leds.dev[bus].cnfCur = val; break; default : leds.dev[bus].dac[reg] = val; leds.dev[bus].ledReq = reg; break; } } } // read ULED1 shadow value // ledsReg(0, LTC3219_ULED1); U8 ledsReg(U8 bus, U8 reg) { U8 val; switch (reg) { case 0 : val = leds.dev[bus].cmdCur; break; case 10 : val = leds.dev[bus].enaCur; break; case 11 : val = leds.dev[bus].cnfCur; break; default : val = leds.dev[bus].dac[reg]; break; } return val; } void ledsTask(void) { U8 i; switch (leds.state) { case idleLS: if (leds.dev[leds.index].cmdCur != leds.dev[leds.index].cmdReq) { leds.buffer[0] = LTC3219_COMMAND; leds.buffer[1] = leds.dev[leds.index].cmdReq; leds.i2c.addr = ledsDevs[leds.index].dev; leds.i2c.txCount = 2; leds.i2c.rxCount = 0; if (i2cTransfer(ledsDevs[leds.index].bus, &leds.i2c) == I2C_RESULT_OK) leds.state = waitCmdLS; } else if (leds.dev[leds.index].enaCur != leds.dev[leds.index].enaReq) { leds.buffer[0] = LTC3219_ENABLE; leds.buffer[1] = leds.dev[leds.index].enaReq; leds.i2c.addr = ledsDevs[leds.index].dev; leds.i2c.txCount = 2; leds.i2c.rxCount = 0; if (i2cTransfer(ledsDevs[leds.index].bus, &leds.i2c) == I2C_RESULT_OK) leds.state = waitEnaLS; } else if (leds.dev[leds.index].cnfCur != leds.dev[leds.index].cnfReq) { leds.buffer[0] = LTC3219_TIMING; leds.buffer[1] = leds.dev[leds.index].cnfReq; leds.i2c.addr = ledsDevs[leds.index].dev; leds.i2c.txCount = 2; leds.i2c.rxCount = 0; if (i2cTransfer(ledsDevs[leds.index].bus, &leds.i2c) == I2C_RESULT_OK) leds.state = waitCnfLS; } else { i = leds.dev[leds.index].ledReq; // ULED1-9 map to led[0-8] if (leds.dev[leds.index].dac[i] != leds.dev[leds.index].dacReq) { // mode/value leds.buffer[0] = LTC3219_ULED1 + i; // form dac value index leds.buffer[1] = leds.dev[leds.index].dacReq; leds.i2c.txCount = 2; leds.i2c.rxCount = 0; if (i2cTransfer(ledsDevs[leds.index].bus, &leds.i2c) == I2C_RESULT_OK) leds.state = waitLedLS; } } break; case waitCmdLS: if (leds.i2c.result != I2C_RESULT_BUSY) { if (leds.i2c.result == I2C_RESULT_OK) { leds.dev[leds.index].cmdCur = leds.buffer[1]; } leds.state = idleLS; } break; case waitEnaLS: if (leds.i2c.result != I2C_RESULT_BUSY) { if (leds.i2c.result == I2C_RESULT_OK) { leds.dev[leds.index].cnfCur = leds.buffer[1]; } leds.state = idleLS; } break; case waitCnfLS: if (leds.i2c.result != I2C_RESULT_BUSY) { if (leds.i2c.result == I2C_RESULT_OK) { leds.dev[leds.index].cnfCur = leds.buffer[1]; } leds.state = idleLS; } break; case waitLedLS: if (leds.i2c.result != I2C_RESULT_BUSY) { if (leds.i2c.result == I2C_RESULT_OK) { leds.dev[leds.index].ledCur = leds.buffer[0]; leds.dev[leds.index].dac[i] = leds.buffer[1]; } leds.state = idleLS; } break; } } #endif // CONFIG_LEDS