81 lines
2.3 KiB
C
81 lines
2.3 KiB
C
/*
|
|
* STC8H1K28 board controller, CrowPanel 7" Advance v1.3.
|
|
*
|
|
* A small 8051-class MCU sitting on the I2C bus at 0x30. It drives the LCD
|
|
* backlight and, critically, the GT911 reset line -- there is no ESP32 GPIO
|
|
* for touch reset on this board, so the GT911 stays mute until the sequence
|
|
* below has run.
|
|
*
|
|
* Protocol is single raw bytes, no register addressing:
|
|
* 0x19 wake
|
|
* 0x10, 0x18 configure / release GT911 from reset
|
|
* 0x00 - 0xF5 brightness, INVERTED (0x00 = full, 0xF5 = off)
|
|
*
|
|
* v1.2 boards use a different, narrower range (0x05 = off .. 0x10 = max).
|
|
*/
|
|
|
|
#include "esp_check.h"
|
|
#include "esp_log.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
|
|
#include "backlight.h"
|
|
#include "i2c_bus.h"
|
|
|
|
static const char *TAG = "backlight";
|
|
|
|
#define STC8_ADDR 0x30
|
|
#define STC8_I2C_HZ 100000
|
|
#define STC8_TIMEOUT_MS 100
|
|
|
|
#define STC8_CMD_WAKE 0x19
|
|
#define STC8_CMD_CFG1 0x10
|
|
#define STC8_CMD_CFG2 0x18
|
|
|
|
/* Inverted brightness range. */
|
|
#define STC8_DUTY_MAX_ON 0x00
|
|
#define STC8_DUTY_OFF 0xF5
|
|
|
|
static i2c_master_dev_handle_t dev = NULL;
|
|
|
|
static esp_err_t stc8_cmd(uint8_t cmd)
|
|
{
|
|
return i2c_master_transmit(dev, &cmd, 1, STC8_TIMEOUT_MS);
|
|
}
|
|
|
|
esp_err_t backlight_init(void)
|
|
{
|
|
const i2c_device_config_t cfg = {
|
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
|
.device_address = STC8_ADDR,
|
|
.scl_speed_hz = STC8_I2C_HZ,
|
|
};
|
|
ESP_RETURN_ON_ERROR(i2c_master_bus_add_device(i2c_bus_get(), &cfg, &dev), TAG,
|
|
"could not add STC8H1K28 at 0x%02X", STC8_ADDR);
|
|
|
|
ESP_RETURN_ON_ERROR(stc8_cmd(STC8_CMD_WAKE), TAG, "wake failed");
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
|
|
/* These two also release the GT911 from reset. */
|
|
ESP_RETURN_ON_ERROR(stc8_cmd(STC8_CMD_CFG1), TAG, "config 1 failed");
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
|
|
ESP_RETURN_ON_ERROR(stc8_cmd(STC8_CMD_CFG2), TAG, "config 2 failed");
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
|
|
ESP_LOGI(TAG, "STC8H1K28 initialized (GT911 released from reset)");
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t backlight_set(uint8_t brightness)
|
|
{
|
|
if (dev == NULL) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
/* Map 0..255 (intuitive) onto 0xF5..0x00 (wire, inverted). */
|
|
const uint8_t duty = (uint8_t)(STC8_DUTY_OFF -
|
|
((uint32_t)brightness * STC8_DUTY_OFF) / 255);
|
|
return stc8_cmd(duty);
|
|
}
|