/*
 * Created on: Jul 27, 2024
 *
 * uses directly polled i2c code. ensure i2c is configured before using.
 *
 * todo: use dma or interrupt based i2c.
*/
#include "31fl3729.h"
#include "i2c.h"



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)
{
    // enable device
#ifdef FL3729_SDB_PORT
    FL3729_SDB_PORT->BSHR = FL3729_SDB_PIN;
#endif

    // reset config registers
    i2c_write_reg_8b(i2c_addr, FL3729_REG_CONFIG, FL3729_RESET_VALUE);

    // write initial config
    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)
{
    return FL3729_BASE_ADDR | (adpin & 0x3);
}


/*
 * 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, const uint8_t *current, uint8_t count)
{
    if (!count) return;
    if (count > 16) count = 16;

    i2c_write_addr1b(i2c_addr, FL3729_REG_SCALING, current, count);
}

/* updates LEDs. data is arranged as 16 bytes per switch output.
 * i2c_addr:    address of endpoint. get with `is31fl3729_get_addr(FL3729_ADPIN_xxx)`
 * 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. up to end user to not exceed writing beyond register 0x90.
 */
void is31fl3729_set_outputs(uint8_t i2c_addr, uint8_t sw, const uint8_t *out, uint8_t len)
{
    if (!sw) sw = 1;

    // calculate start address
    sw--;
    sw <<= 4;
    sw++;

    i2c_write_addr1b(i2c_addr, sw, out, len);
}
