custom board driver ma120x0 is broken esp dsp is now IDF managed component mdns is now IDF managed component Signed-off-by: Karl Osterseher <karli_o@gmx.at>
374 lines
12 KiB
C
374 lines
12 KiB
C
/*
|
|
* ESPRESSIF MIT License
|
|
*
|
|
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
|
*
|
|
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in
|
|
* which case, it is free of charge, to any person obtaining a copy of this
|
|
* software and associated documentation files (the "Software"), to deal in the
|
|
* Software without restriction, including without limitation the rights to use,
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
* the Software, and to permit persons to whom the Software is furnished to do
|
|
* so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#include "IS31FL3216.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "audio_mem.h"
|
|
#include "driver/i2c.h"
|
|
#include "esp_log.h"
|
|
#include "i2c_bus.h"
|
|
|
|
#define IS31FL3216_WRITE_BIT 0x00
|
|
|
|
#define I2C_MASTER_SCL_IO 23 /*!< gpio number for I2C master clock */
|
|
#define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
|
|
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */
|
|
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
|
|
|
|
#define IS31FL3216_ADDRESS 0xE8 /*!< I2C Addr*/
|
|
|
|
#define IS31_ERROR_CHECK(con) \
|
|
if (!(con)) { \
|
|
ESP_LOGE(TAG, "err line: %d", __LINE__); \
|
|
}
|
|
#define IS31_PARAM_CHECK(con) \
|
|
if (!(con)) { \
|
|
ESP_LOGE(TAG, "Parameter error: %d", __LINE__); \
|
|
}
|
|
#define IS31_CHECK_I2C_RES(res) \
|
|
if (ret == ESP_FAIL) { \
|
|
ESP_LOGE(TAG, "Is31fl3216[%s]: FAIL\n", __FUNCTION__); \
|
|
} else if (ret == ESP_ERR_TIMEOUT) { \
|
|
ESP_LOGE(TAG, "Is31fl3216[%s]: TIMEOUT\n", __FUNCTION__); \
|
|
}
|
|
typedef struct {
|
|
i2c_bus_handle_t bus;
|
|
uint16_t addr;
|
|
} is31fl3216_dev_t;
|
|
|
|
uint8_t Is31Value[10] = {0x80, 0x00, 0x01, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static char *TAG = "IS31";
|
|
|
|
/**
|
|
* @brief set software shutdown mode
|
|
*/
|
|
static esp_err_t is31fl3216_write_reg(is31fl3216_handle_t handle,
|
|
is31fl3216_reg_t regAddr, uint8_t *data,
|
|
uint8_t data_num) {
|
|
IS31_PARAM_CHECK(NULL != data);
|
|
is31fl3216_dev_t *dev = (is31fl3216_dev_t *)handle;
|
|
esp_err_t ret =
|
|
i2c_bus_write_bytes(dev->bus, IS31FL3216_ADDRESS | IS31FL3216_WRITE_BIT,
|
|
(uint8_t *)®Addr, 1, data, data_num);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief change channels PWM duty cycle data register
|
|
*/
|
|
static esp_err_t is31fl3218S_channel_duty_by_bits(is31fl3216_handle_t handle,
|
|
uint32_t by_bits,
|
|
uint8_t duty) {
|
|
for (int i = 0; i < IS31FL3216_CH_NUM_MAX; i++) {
|
|
if ((by_bits >> i) & 0x1) {
|
|
esp_err_t ret = is31fl3216_write_reg(
|
|
handle, IS31FL3216_REG_PWM_16 + (IS31FL3216_CH_NUM_MAX - i - 1),
|
|
&duty, 1);
|
|
if (ret == ESP_OK) {
|
|
// PASS
|
|
} else {
|
|
IS31_CHECK_I2C_RES(ret);
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Load PWM Register and LED Control Registers data
|
|
*/
|
|
esp_err_t is31fl3216_update_reg(is31fl3216_handle_t handle) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
uint8_t m = 0;
|
|
return is31fl3216_write_reg(handle, IS31FL3216_REG_UPDATE, &m, 1);
|
|
}
|
|
|
|
/**
|
|
* @brief set software shutdown mode
|
|
*/
|
|
esp_err_t is31fl3216_power(is31fl3216_handle_t handle, is31fl3216_pwr_t mode) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
if (IS31FL3216_PWR_SHUTDOWN == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(1 << 7))) | (1 << 7);
|
|
} else if (IS31FL3216_PWR_NORMAL == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(1 << 7)));
|
|
} else {
|
|
return ESP_FAIL;
|
|
}
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_CONFIG,
|
|
(uint8_t *)&Is31Value[IS31FL3216_REG_CONFIG], 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_work_mode_set(is31fl3216_handle_t handle,
|
|
is31fl3216_work_mode_t mode) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
if (IS31FL3216_MODE_PWM == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(3 << 5)));
|
|
} else if (IS31FL3216_MODE_AUTO_FRAME == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(3 << 5))) | (1 << 5);
|
|
} else if (IS31FL3216_MODE_FRAME == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(3 << 5))) | (2 << 5);
|
|
} else {
|
|
return ESP_FAIL;
|
|
}
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_CONFIG,
|
|
(uint8_t *)&Is31Value[IS31FL3216_REG_CONFIG], 1);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief change channels PWM duty cycle data register
|
|
*/
|
|
esp_err_t is31fl3216_ch_duty_set(is31fl3216_handle_t handle,
|
|
is31_pwm_channel_t ch_bits, uint8_t duty) {
|
|
esp_err_t ret = ESP_OK;
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
ret = is31fl3218S_channel_duty_by_bits(handle, ch_bits, duty);
|
|
if (ret != ESP_OK) {
|
|
IS31_CHECK_I2C_RES(ret);
|
|
return ret;
|
|
}
|
|
ret = is31fl3216_update_reg(handle);
|
|
if (ret != ESP_OK) {
|
|
IS31_CHECK_I2C_RES(ret);
|
|
return ret;
|
|
}
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief change channels PWM duty cycle data register
|
|
*/
|
|
esp_err_t is31fl3216_ch_enable(is31fl3216_handle_t handle,
|
|
is31_pwm_channel_t ch_bits) {
|
|
esp_err_t ret = ESP_OK;
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
uint16_t value = 0;
|
|
for (int i = 0; i < IS31FL3216_CH_NUM_MAX; ++i) {
|
|
if ((ch_bits >> i) & 0x01) {
|
|
value |= (1 << i);
|
|
}
|
|
}
|
|
Is31Value[IS31FL3216_REG_LED_CTRL_H] |= value >> 8;
|
|
Is31Value[IS31FL3216_REG_LED_CTRL_L] |= value;
|
|
ret = is31fl3216_write_reg(handle, IS31FL3216_REG_LED_CTRL_H,
|
|
&Is31Value[IS31FL3216_REG_LED_CTRL_H], 2);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief change channels PWM duty cycle data register
|
|
*/
|
|
esp_err_t is31fl3216_ch_disable(is31fl3216_handle_t handle,
|
|
is31_pwm_channel_t ch_bits) {
|
|
esp_err_t ret = ESP_OK;
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
uint16_t value = ((uint16_t)Is31Value[IS31FL3216_REG_LED_CTRL_H]) << 8;
|
|
value |= Is31Value[IS31FL3216_REG_LED_CTRL_L];
|
|
for (int i = 0; i < IS31FL3216_CH_NUM_MAX; ++i) {
|
|
if ((ch_bits >> i) & 0x01) {
|
|
value = value & (~(1 << i));
|
|
}
|
|
}
|
|
Is31Value[IS31FL3216_REG_LED_CTRL_H] = value >> 8;
|
|
Is31Value[IS31FL3216_REG_LED_CTRL_L] = value;
|
|
ret = is31fl3216_write_reg(handle, IS31FL3216_REG_LED_CTRL_H,
|
|
&Is31Value[IS31FL3216_REG_LED_CTRL_H], 2);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_cur_mode_set(is31fl3216_handle_t handle,
|
|
is31fl3216_cur_mode_t mode) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
if (IS31FL3216_CUR_MODE_REXT == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(1 << 4)));
|
|
} else if (IS31FL3216_CUR_MODE_AUDIO == mode) {
|
|
Is31Value[IS31FL3216_REG_CONFIG] =
|
|
(Is31Value[IS31FL3216_REG_CONFIG] & (~(1 << 4))) | (1 << 4);
|
|
} else {
|
|
return ESP_FAIL;
|
|
}
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_CONFIG,
|
|
(uint8_t *)&Is31Value[IS31FL3216_REG_CONFIG], 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_cur_value_set(is31fl3216_handle_t handle,
|
|
is31fl3216_cur_value_t value) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
Is31Value[IS31FL3216_REG_LED_EFFECT] =
|
|
(Is31Value[IS31FL3216_REG_LED_EFFECT] & (~(7 << 4))) | value << 4;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_LED_EFFECT,
|
|
&Is31Value[IS31FL3216_REG_LED_EFFECT], 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_ags_value_set(is31fl3216_handle_t handle,
|
|
is31fl3216_ags_value_t value) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
Is31Value[IS31FL3216_REG_LED_EFFECT] =
|
|
(Is31Value[IS31FL3216_REG_LED_EFFECT] & (~(7 << 0))) | value << 0;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_LED_EFFECT,
|
|
&Is31Value[IS31FL3216_REG_LED_EFFECT], 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_agc_cfg(is31fl3216_handle_t handle, uint32_t en) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
Is31Value[IS31FL3216_REG_LED_EFFECT] =
|
|
(Is31Value[IS31FL3216_REG_LED_EFFECT] & (~(1 << 3))) | en << 3;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_LED_EFFECT,
|
|
&Is31Value[IS31FL3216_REG_LED_EFFECT], 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_cascade_mode_set(is31fl3216_handle_t handle,
|
|
is31fl3216_cascade_mode_t mode) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
Is31Value[IS31FL3216_REG_LED_EFFECT] =
|
|
(Is31Value[IS31FL3216_REG_LED_EFFECT] & (~(1 << 7))) | mode << 7;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_LED_EFFECT,
|
|
&Is31Value[IS31FL3216_REG_LED_EFFECT], 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_sample_rate_set(is31fl3216_handle_t handle,
|
|
uint32_t value) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
uint8_t dat = value;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_ADC_RATE, &dat, 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_frame_time_set(is31fl3216_handle_t handle,
|
|
is31fl3216_delay_time_t time) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
uint8_t dat = time << 5;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_FRAME_DELAY, &dat, 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_first_frame_set(is31fl3216_handle_t handle,
|
|
uint32_t frame) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
uint8_t dat = frame << 5;
|
|
esp_err_t ret =
|
|
is31fl3216_write_reg(handle, IS31FL3216_REG_FRAME_START, &dat, 1);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_frame_value_set(is31fl3216_handle_t handle, uint32_t num,
|
|
uint8_t *data, uint32_t len) {
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
IS31_PARAM_CHECK(NULL != data);
|
|
uint8_t startAddr = IS31FL3216_REG_FRAME1_CTRL + (num - 1) * 18;
|
|
esp_err_t ret = is31fl3216_write_reg(handle, startAddr, data, len);
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t is31fl3216_reset(is31fl3216_handle_t handle) {
|
|
esp_err_t ret = ESP_OK;
|
|
uint8_t dat = 0x00;
|
|
IS31_PARAM_CHECK(NULL != handle);
|
|
ret = is31fl3216_power(handle, IS31FL3216_PWR_NORMAL);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
for (int i = 0; i < IS31FL3216_CH_NUM_MAX; ++i) {
|
|
ret = is31fl3216_ch_duty_set(handle, 1 << i, 0);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
}
|
|
ret = is31fl3216_ch_enable(handle, IS31FL3216_CH_ALL);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
|
|
ret = is31fl3216_write_reg(handle, IS31FL3216_REG_LED_EFFECT, &dat, 1);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
ret = is31fl3216_write_reg(handle, IS31FL3216_REG_CH_CONFIG, &dat, 1);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief i2c master initialization
|
|
*/
|
|
|
|
is31fl3216_handle_t is31fl3216_init(void) {
|
|
i2c_config_t conf = {0};
|
|
conf.mode = I2C_MODE_MASTER;
|
|
conf.sda_io_num = I2C_MASTER_SDA_IO;
|
|
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
|
conf.scl_io_num = I2C_MASTER_SCL_IO;
|
|
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
|
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
|
|
is31fl3216_dev_t *led =
|
|
(is31fl3216_dev_t *)audio_calloc(1, sizeof(is31fl3216_dev_t));
|
|
led->bus = i2c_bus_create(I2C_MASTER_NUM, &conf);
|
|
led->addr = IS31FL3216_ADDRESS;
|
|
IS31_ERROR_CHECK(ESP_OK == is31fl3216_power(led, IS31FL3216_PWR_NORMAL));
|
|
IS31_ERROR_CHECK(ESP_OK ==
|
|
is31fl3216_cur_mode_set(led, IS31FL3216_CUR_MODE_REXT));
|
|
IS31_ERROR_CHECK(ESP_OK ==
|
|
is31fl3216_cur_value_set(led, IS31FL3216_CUR_0_75));
|
|
return (is31fl3216_handle_t)led;
|
|
}
|
|
|
|
esp_err_t is31fl3216_deinit(is31fl3216_handle_t handle) {
|
|
is31fl3216_dev_t *dev = (is31fl3216_dev_t *)handle;
|
|
if (dev->bus) {
|
|
i2c_bus_delete(dev->bus);
|
|
dev->bus = NULL;
|
|
}
|
|
audio_free(dev);
|
|
return ESP_OK;
|
|
}
|