led working

This commit is contained in:
Steven Dan
2026-05-21 22:48:44 +08:00
parent c722efadaf
commit 6e4ccad258
7 changed files with 932 additions and 76 deletions

View File

@@ -45,8 +45,8 @@
</Tile>
<Tile Number="1" Reference="tile[1]">
<Port Location="XS1_PORT_1A" Name="PORT_UART_RX"/>
<Port Location="XS1_PORT_1K" Name="PORT_UART_TX"/>
<!-- 改动原因:删除原 fosi_c1 的 PORT_UART_RX/TX(1A/1K),与 jok LED/HTR3236 引脚冲突;
UART 曾占用 1K 会导致 SDB 拉低I2C 有应答但 RGB 不亮 -->
<!-- 改动原因:与 jok.xn 对齐,功放静音控制 (tx1_led_helper p_ctl_mute) -->
<Port Location="XS1_PORT_1F" Name="PORT_CTL_MUTE"/>
<!-- HRT3236 -->

View File

@@ -14,6 +14,7 @@
#include "debug_print.h"
#include "user_uart.h"
#include "htr3236.h"
#include "tx1_led_effects.h"
#include "eq_flash_storage.h"
#include "lfs_io.h"
#include "roleswitchflag.h"
@@ -29,6 +30,8 @@ extern "C" {
}
#define TIMER_PERIOD 2000000
/* 改动原因:与 jok TIMER_2_PERIOD 一致50ms 驱动 RGB 灯效/工厂复位 LED */
#define TIMER_2_PERIOD 5000000
#define DISABLE_REBOOT 1
@@ -94,6 +97,8 @@ unsigned g_hid_expand_gain_request = (unsigned)-1;
unsigned g_hid_lmt_threshold_request = (unsigned)-1;
unsigned g_hid_angle_values[C1_EX3D_ANGLE_CHANNELS] = {0};
unsigned g_request_factory_reset = 0;
/* 改动原因HTR3236 bringup 须在 codec_init 完成之后执行,避免与 NAU88 I2C 抢线/阻塞 */
unsigned g_audiohw_codec_init_done = 0;
// CODEC I2C lines
on tile[0]: port p_scl = PORT_I2C_SCL;
@@ -110,13 +115,17 @@ on tile[0]: out port p_led_tile0 = PORT_LED_D10_8_11_9; // 8D bit7-4 = D10/D8/D
// TX1 HTR3236 RGB LED driver control - declared in tx1_led_helper.xc
// TX1 Button bit masks
// TX1 原理图位掩码(与 jok buttons.h BIT_* 一致,接在 4F/4E 端口上)
#define TX1_BIT_FPS_MODE (1<<3) // 4F bit3
#define TX1_BIT_GAME_MODE (1<<2) // 4F bit2
#define TX1_BIT_MIC_MUTE (1<<1) // 4F bit1
#define TX1_BIT_VOL_PLUS (1<<3) // 4E bit3
#define TX1_BIT_VOL_MINUS (1<<2) // 4E bit2
/* 改动原因:与 jok PCB 相同,面板从左到右为 FPS / VOL+ / VOL- / GAME / MIC
* 原理图端口位序不同。采用 lib_board_support buttons.xc #else 映射(非 #if 0 原理图直读)。 */
#define TX1_BUTTON_MAP_PANEL_LAYOUT (0)
// TX1 Button timing thresholds (in 50ms ticks)
#define TX1_SHORT_PRESS_TICKS 1 // 50ms minimum press
#define TX1_LONG_PRESS_TICKS 20 // 1s = 20 * 50ms
@@ -376,75 +385,101 @@ void mic_volume(unsigned level, client interface i2c_master_if i2c)
}
}
/* 改动原因:按 phaten_golden_6ch/audiohw.xc 流程初始化——先 SDB 使能并延时,再 wake/freq/通道配置,
* 带 I2C 重试。xC 禁止 client interface 全局变量SDB 在本函数内直接用 led_if 控制(不经 htr3236_hw_enable。 */
/* 改动原因:jok 默认 10 过暗肉眼难辨;自检/灯效用 80音量条仍可用较低亮度 */
#define TX1_RGB_GLOBAL_BRIGHTNESS 40
#define TX1_RGB_SELFTEST_BRIGHTNESS 200
#define TX1_RGB_SCALE8(c) ((uint8_t)(((unsigned)(c) * TX1_RGB_GLOBAL_BRIGHTNESS) / 255))
/* 改动原因bringup 失败时灯效任务不刷屏 I2C */
static unsigned g_htr3236_ready = 0;
// RGB LED to HTR3236 OUT channel mapping (D1-D12),须在 bringup 自检前定义
static const uint8_t rgb_led_map[13][3] = {
{0, 0, 0},
{24, 23, 22}, {21, 20, 19}, {18, 17, 16}, {15, 14, 13},
{12, 11, 10}, {9, 8, 7}, {6, 5, 4}, {3, 2, 1},
{36, 35, 34}, {33, 32, 31}, {30, 29, 28}, {27, 26, 25}
};
/* 改动原因:与 jok tile1_io_control_task 相同,仅 tile1 1K 拉高 SDB勿动 tile0 8C非 SDB */
static void tx1_htr3236_sdb_enable(client interface tx1_led_if led_if)
{
led_if.set_htr3236_sdb(1);
delay_milliseconds(10);
}
/* 改动原因:按 jok rgb_led 流程 D1-D12 白灯自检,最后统一 UPDATE */
static void tx1_htr3236_self_test_rgb(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t led;
for (led = 1; led <= 12; led++) {
htr3236_set_pwm(dev, i2c, rgb_led_map[led][0], TX1_RGB_SELFTEST_BRIGHTNESS);
htr3236_set_pwm(dev, i2c, rgb_led_map[led][1], TX1_RGB_SELFTEST_BRIGHTNESS);
htr3236_set_pwm(dev, i2c, rgb_led_map[led][2], TX1_RGB_SELFTEST_BRIGHTNESS);
}
htr3236_update(dev, i2c);
}
/* 改动原因:按 jok + golden 流程;避开 AudioHwInit 与 codec 抢 I2C读回 0x00 验证唤醒 */
static void tx1_htr3236_bringup(htr3236_t *dev, client interface i2c_master_if i2c,
client interface tx1_led_if led_if)
{
int ch;
unsigned retry;
uint8_t zeros[36];
int wake_ok = 0;
int freq_ok = 0;
led_if.init();
led_if.set_htr3236_sdb(1);
delay_milliseconds(2);
g_htr3236_ready = 0;
/* 改动原因:上电已在 Remote2 入口拉过 SDB此处仅再脉冲一次确保硬件退出关断 */
tx1_htr3236_sdb_enable(led_if);
htr3236_init(dev, HTR3236_ADDR_GND);
debug_printf("HTR3236 addr 0x%02x (jok same HW)\n", dev->i2c_addr);
retry = 0;
while (htr3236_software_wake(dev, i2c) != I2C_REGOP_SUCCESS && retry < 10) {
retry++;
delay_milliseconds(1);
debug_printf("HTR3236 wake retry %u\n", retry);
for (retry = 0; retry < 10; retry++) {
if (htr3236_software_wake(dev, i2c) == I2C_REGOP_SUCCESS) {
wake_ok = 1;
break;
}
if (retry >= 10) {
debug_printf("HTR3236 LED driver wake failed\n");
} else {
debug_printf("HTR3236 LED driver wake ok\n");
delay_milliseconds(2);
htr3236_software_reset(dev, i2c);
delay_milliseconds(2);
debug_printf("HTR3236 wake retry %u\n", retry + 1);
}
if (!wake_ok) {
debug_printf("HTR3236 wake FAILED (no I2C ACK, check SDB+addr)\n");
return;
}
retry = 0;
while (htr3236_set_frequency(dev, i2c, HTR3236_FREQ_22KHZ) != I2C_REGOP_SUCCESS && retry < 10) {
retry++;
delay_milliseconds(1);
debug_printf("HTR3236 freq retry %u\n", retry);
debug_printf("HTR3236 wake ok\n");
for (retry = 0; retry < 10; retry++) {
if (htr3236_set_frequency(dev, i2c, HTR3236_FREQ_22KHZ) == I2C_REGOP_SUCCESS) {
freq_ok = 1;
break;
}
delay_milliseconds(2);
debug_printf("HTR3236 freq retry %u\n", retry + 1);
}
if (!freq_ok) {
debug_printf("HTR3236 set frequency FAILED\n");
return;
}
if (retry >= 10) {
debug_printf("HTR3236 set frequency failed\n");
} else {
debug_printf("HTR3236 set frequency ok\n");
}
for (ch = 1; ch <= 35; ch++) {
/* 改动原因:与 jok xk_audio_316_mc_ab_board 一致,逐通道配置 LED 电流/使能 */
for (ch = 1; ch <= 36; ch++) {
htr3236_set_led_config(dev, i2c, ch, HTR3236_CURRENT_HALF, 1);
}
htr3236_global_enable(dev, i2c, 1);
for (ch = 0; ch < 36; ch++) {
zeros[ch] = 0;
}
htr3236_set_pwm_bulk(dev, i2c, 1, zeros, 36);
htr3236_update(dev, i2c);
tx1_htr3236_self_test_rgb(dev, i2c);
debug_printf("HTR3236 self-test: D1-D12 white PWM=%u, hold 5s\n", TX1_RGB_SELFTEST_BRIGHTNESS);
delay_milliseconds(5000);
g_htr3236_ready = 1;
}
// RGB LED to HTR3236 OUT channel mapping (D1-D12)
// Each LED: {out_b, out_g, out_r}
static const uint8_t rgb_led_map[13][3] = {
{0, 0, 0}, // [0] invalid
{24, 23, 22}, // D1
{21, 20, 19}, // D2
{18, 17, 16}, // D3
{15, 14, 13}, // D4
{12, 11, 10}, // D5
{9, 8, 7}, // D6
{6, 5, 4}, // D7
{3, 2, 1}, // D8
{36, 35, 34}, // D9
{33, 32, 31}, // D10
{30, 29, 28}, // D11
{27, 26, 25} // D12
};
static void tx1_rgb_led_set(htr3236_t *dev, client interface i2c_master_if i2c,
uint8_t led, uint8_t r, uint8_t g, uint8_t b)
{
@@ -465,6 +500,73 @@ static void tx1_rgb_led_all_off(htr3236_t *dev, client interface i2c_master_if i
htr3236_update(dev, i2c);
}
/* 改动原因:单颗 RGB 只写 PWM 寄存器,最后统一 htr3236_update对照 ui_app 303-336 的 bulk 刷新) */
static void tx1_rgb_pwm_write_led(htr3236_t *dev, client interface i2c_master_if i2c,
uint8_t led, uint8_t r, uint8_t g, uint8_t b)
{
if (led < 1 || led > 12) return;
htr3236_set_pwm(dev, i2c, rgb_led_map[led][0], b);
htr3236_set_pwm(dev, i2c, rgb_led_map[led][1], g);
htr3236_set_pwm(dev, i2c, rgb_led_map[led][2], r);
}
/* 改动原因:按 feature_mode + 音量格数刷新 HTR3236 D1-D12 音量条jok ui_app led_ui 303-336 */
static void tx1_rgb_volume_bar_refresh(htr3236_t *dev, client interface i2c_master_if i2c,
tx1_feature_mode_t mode, unsigned feature_vol_0_12)
{
uint8_t zeros[36];
int i;
uint8_t led;
unsigned bar_level = 0;
uint8_t r = 0, g = 0, b = 0;
for (i = 0; i < 36; i++) zeros[i] = 0;
htr3236_set_pwm_bulk(dev, i2c, 1, zeros, 36);
switch (mode) {
case FEATURE_MODE_SYSTEM_VOLUME: {
unsigned vol_pct;
GET_SHARED_GLOBAL(vol_pct, g_volume_level);
bar_level = (vol_pct * 12u) / 100u;
if (bar_level > 12) bar_level = 12;
r = TX1_RGB_SCALE8(255);
g = TX1_RGB_SCALE8(255);
b = 0;
break;
}
case FEATURE_MODE_GUNSHOT_LEVEL:
bar_level = feature_vol_0_12;
if (bar_level > 12) bar_level = 12;
r = TX1_RGB_SCALE8(128);
g = 0;
b = TX1_RGB_SCALE8(128);
break;
case FEATURE_MODE_FOOTSTEPS_LEVEL:
bar_level = feature_vol_0_12;
if (bar_level > 12) bar_level = 12;
r = TX1_RGB_SCALE8(255);
g = TX1_RGB_SCALE8(165);
b = 0;
break;
case FEATURE_MODE_MIC_LEVEL:
bar_level = feature_vol_0_12;
if (bar_level > 12) bar_level = 12;
r = 0;
g = 0;
b = TX1_RGB_SCALE8(255);
break;
case FEATURE_MODE_NONE:
default:
htr3236_update(dev, i2c);
return;
}
for (led = 1; led <= bar_level; led++) {
tx1_rgb_pwm_write_led(dev, i2c, led, r, g, b);
}
htr3236_update(dev, i2c);
}
void save_value(unsigned char * unsafe path, unsigned char value);
unsigned char load_value(unsigned char * unsafe path);
/* 改动原因c_dfu 仅接收 FIRMWARE_UPGRADE_START在此线程执行 handle_firmware_upgrade_start。
@@ -481,7 +583,8 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
unsigned eq_mode_time = 0;
unsigned se_time = 0;
unsigned se_count = 0;
timer tmr, se_tmr, eq_mode_timer, eq_sync_timer;
timer tmr, se_tmr, eq_mode_timer, eq_sync_timer, led_fx_tmr;
unsigned led_fx_time = 0;
unsigned eq_sync_time = 0;
unsigned old_format = 14;
unsigned unmute_dac_state;
@@ -520,13 +623,19 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
eq_mode_time += EQ_MODE_DELAY;
eq_sync_timer :> eq_sync_time;
eq_sync_time += EQ_SYNC_DELAY;
led_fx_tmr :> led_fx_time;
led_fx_time += TIMER_2_PERIOD;
// TX1: Initialize tile[0] GPIO LEDs (all off, active low)
led_tile0_shadow = 0xF0;
p_led_tile0 <: led_tile0_shadow;
// TX1: tile[1] GPIO + HTR3236 SDB再经 I2C 按 golden 流程配置 HTR3236
tx1_htr3236_bringup(&htr3236_dev, i2c, led_if);
/* 改动原因:仅预拉 SDB完整 bringup 在 codec_init 完成后执行(见 tmr 分支) */
led_if.init();
tx1_htr3236_sdb_enable(led_if);
htr3236_init(&htr3236_dev, HTR3236_ADDR_GND);
unsigned htr3236_bringup_done = 0;
// TX1 button previous state (active low: 0=pressed, 1=released)
unsigned prev_fps = 1, prev_game = 1, prev_mic = 1;
@@ -552,6 +661,7 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
// TX1 LED effect state for game mode indicators
unsigned gpio_leds_dirty = 1; // refresh LEDs on first tick
unsigned led_pattern_step = TX1_EFFECT_RACE; // 改动原因BYPASS 下 RGB 装饰灯效VOL++/VOL- 循环
#if HID_DFU_EN
firmware_upgrade_init();
@@ -594,6 +704,17 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
uint32_t now, old_time;
time += TIMER_PERIOD;
unsigned dac_vol, adc_vol, dac_mode, new_dac_mode;
unsigned codec_init_done;
/* 改动原因codec_init 经 chan 在本任务处理;完成后再做 HTR3236避免假成功 */
if (!htr3236_bringup_done) {
GET_SHARED_GLOBAL(codec_init_done, g_audiohw_codec_init_done);
if (codec_init_done) {
debug_printf("HTR3236 bringup start (after codec)\n");
tx1_htr3236_bringup(&htr3236_dev, i2c, led_if);
htr3236_bringup_done = 1;
}
}
now = get_reference_time();
@@ -1054,15 +1175,27 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
// ========== TX1 BUTTON SCANNING ==========
{
unsigned btn1, btn2;
p_button_fps_game_mic :> btn1; // bit3=FPS, bit2=GAME, bit1=MIC
p_button_vol :> btn2; // bit3=VOL+, bit2=VOL-
unsigned fps, game, mic, vol_plus, vol_minus;
// Extract button states (active low: 0=pressed, 1=released)
unsigned fps = (btn1 & TX1_BIT_FPS_MODE) ? 1 : 0;
unsigned game = (btn1 & TX1_BIT_GAME_MODE) ? 1 : 0;
unsigned mic = (btn1 & TX1_BIT_MIC_MUTE) ? 1 : 0;
unsigned vol_plus = (btn2 & TX1_BIT_VOL_PLUS) ? 1 : 0;
unsigned vol_minus = (btn2 & TX1_BIT_VOL_MINUS) ? 1 : 0;
p_button_fps_game_mic :> btn1;
p_button_vol :> btn2;
/* 改动原因低有效1=弹起 0=按下;逻辑值 1=released 与 jok buttons.xc 一致 */
#if TX1_BUTTON_MAP_PANEL_LAYOUT
/* 面板位映射jok buttons.xc #else左→右 FPS, VOL+, VOL-, GAME, MIC */
vol_minus = (btn1 & TX1_BIT_FPS_MODE) ? 1 : 0;
vol_plus = (btn1 & TX1_BIT_GAME_MODE) ? 1 : 0;
fps = (btn1 & TX1_BIT_MIC_MUTE) ? 1 : 0;
mic = (btn2 & TX1_BIT_VOL_PLUS) ? 1 : 0;
game = (btn2 & TX1_BIT_VOL_MINUS) ? 1 : 0;
#else
/* 原理图直读jok buttons.xc #if 04F=FPS/GAME/MIC, 4E=VOL+/VOL- */
fps = (btn1 & TX1_BIT_FPS_MODE) ? 1 : 0;
game = (btn1 & TX1_BIT_GAME_MODE) ? 1 : 0;
mic = (btn1 & TX1_BIT_MIC_MUTE) ? 1 : 0;
vol_plus = (btn2 & TX1_BIT_VOL_PLUS) ? 1 : 0;
vol_minus = (btn2 & TX1_BIT_VOL_MINUS) ? 1 : 0;
#endif
// Combo key detection (highest priority)
tx1_combo_t new_combo = COMBO_NONE;
@@ -1091,10 +1224,14 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
gpio_leds_dirty = 1;
debug_printf("TX1: GAME+MIC combo - high_perf_mode=%d\n", high_perf_mode);
} else if (current_combo == COMBO_VOL_UP_DOWN) {
// Cycle LED effects in BYPASS mode only
/* 改动原因:对照 jok on_combo_vol_up_downBYPASS 下循环 RGB 灯效 */
if (game_mode == GAME_MODE_BYPASS && feature_mode == FEATURE_MODE_NONE) {
// For now, just toggle feature mode indicator
debug_printf("TX1: VOL++VOL- combo - LED effect cycle\n");
led_pattern_step = (led_pattern_step + 1) % TX1_EFFECT_MAX;
debug_printf("TX1: VOL++VOL- combo - led_pattern_step=%u\n", led_pattern_step);
} else if (feature_mode != FEATURE_MODE_NONE) {
feature_mode = FEATURE_MODE_NONE;
feature_timeout_ticks = 0;
gpio_leds_dirty = 1;
}
}
}
@@ -1114,24 +1251,29 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
factory_reset_6s_fired = 0;
factory_reset_10s_fired = 0;
factory_reset_done = 0;
tx1_factory_reset_countdown_start();
debug_printf("TX1: Factory reset countdown started\n");
} else if (!factory_reset_done) {
unsigned elapsed = now - factory_reset_start_time;
if (elapsed >= 10600000000ull && !factory_reset_done) { // 10.6s
factory_reset_done = 1;
tx1_factory_reset_triggered();
debug_printf("TX1: FACTORY RESET TRIGGERED!\n");
SET_SHARED_GLOBAL(g_request_factory_reset, 1);
} else if (elapsed >= 10000000000ull && !factory_reset_10s_fired) {
factory_reset_10s_fired = 1;
tx1_factory_reset_countdown_10s();
debug_printf("TX1: Factory reset 10s warning\n");
} else if (elapsed >= 6000000000ull && !factory_reset_6s_fired) {
factory_reset_6s_fired = 1;
tx1_factory_reset_countdown_6s();
debug_printf("TX1: Factory reset 6s warning\n");
}
}
} else {
if (factory_reset_counting) {
factory_reset_counting = 0;
tx1_factory_reset_cancel();
debug_printf("TX1: Factory reset cancelled\n");
}
}
@@ -1328,9 +1470,35 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
if (mic_muted) {
led_if.led_on(TX1_GPIO_LED_D2);
}
/* 改动原因HTR3236 RGB D1-D12 音量条;工厂复位灯效占用 RGB 时不刷条 */
if (g_htr3236_ready && !tx1_factory_reset_rgb_active()) {
tx1_rgb_volume_bar_refresh(&htr3236_dev, i2c, feature_mode, feature_volume);
}
}
break;
/* 改动原因:第二定时器 50ms移植 jok led_effects_period_update_task */
case led_fx_tmr when timerafter(led_fx_time) :> void :
if (g_htr3236_ready) {
unsigned gm;
static unsigned led_fx_dbg_cnt;
GET_SHARED_GLOBAL(gm, g_3d_fps);
tx1_led_effects_periodic(&htr3236_dev, i2c,
gm,
(unsigned)feature_mode,
led_pattern_step);
/* 改动原因:确认 50ms 灯效任务在跑;每约 5s 打一次 gm/fm/pattern */
led_fx_dbg_cnt++;
if ((led_fx_dbg_cnt % 100) == 1) {
debug_printf("led_fx gm=%u fm=%u pat=%u ready=%u\n",
gm, (unsigned)feature_mode, led_pattern_step, g_htr3236_ready);
}
}
led_fx_time += TIMER_2_PERIOD;
break;
case se_tmr when timerafter(se_time) :> void :
se_time += SE_DELAY;
se_count ++;
@@ -1426,8 +1594,8 @@ void AudioHwRemote(streaming chanend c, streaming chanend c_dfu, client interfac
par
{
/* 改动原因:与 golden_6ch 一致使用 300kHz I2C原 100kHz HTR3236 失效主因但统一时序 */
i2c_master(i2c, 1, p_scl, p_sda, 300);
/* 改动原因:与 jok xk_audio_316_mc_ab 一致 100kHz300kHz 可能导致 HTR3236 长包异常 */
i2c_master(i2c, 1, p_scl, p_sda, 100);
AudioHwRemote2(c, i2c[0], c_dfu, led_if);
}
}
@@ -1438,8 +1606,8 @@ void AudioHwRemote(streaming chanend c, client interface tx1_led_if led_if)
par
{
/* 改动原因:与 golden_6ch 一致使用 300kHz I2C原 100kHz 非 HTR3236 失效主因但统一时序 */
i2c_master(i2c, 1, p_scl, p_sda, 300);
/* 改动原因:与 jok xk_audio_316_mc_ab 一致 100kHz */
i2c_master(i2c, 1, p_scl, p_sda, 100);
AudioHwRemote2(c, i2c[0], led_if);
}
}
@@ -1478,11 +1646,13 @@ void AudioHwInit()
codec_init();
debug_printf("AudioHwInit completed\n");
CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x0003, 0x0053);
CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002B, 0x4002);
CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002C, 0x0082);
debug_printf("AudioHwInit completed\n");
/* 改动原因:全部 codec 寄存器写完后再置位,触发 HTR3236 bringup */
SET_SHARED_GLOBAL(g_audiohw_codec_init_done, 1);
}
void unmute_dac(void)

View File

@@ -173,7 +173,7 @@ int htr3236_update(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c));
/**
* @brief 全局 LED 使能控制
* @param dev 设备结构体指针
* @param enable 1:关闭所有LED, 0:正常模式
* @param enable 1:正常输出, 0:关闭全部 36 路 LED4Ah G_EN=1
* @return 0:成功, -1:失败
*/
int htr3236_global_enable(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t enable);
@@ -200,4 +200,7 @@ uint8_t htr3236_gamma_32(uint8_t index);
*/
uint8_t htr3236_gamma_64(uint8_t index);
/* 改动原因bringup 读回 0x00 关断寄存器,确认 I2C 真连通且非 NACK 假象 */
int htr3236_read_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, uint8_t *value);
#endif /* HTR3236_H */

View File

@@ -0,0 +1,214 @@
/**
* @file htr3236.xc
* @brief HTR3236 36 路 LED PWM 驱动(与 phaten_golden_6ch 同源)
* @version 1.1
*
* 改动原因:与 jok 相同SDB 仅 tile1 PORT_HTR3236_SDB(1K),由 tx1_led_if 控制,不在此操作 GPIO。
*/
#include "htr3236.h"
#include <xccompat.h>
/*=========================================================================
Gamma 校正查找表
-----------------------------------------------------------------------*/
static const uint8_t gamma_table_32[32] = {
0, 1, 2, 4, 6, 10, 13, 18,
22, 28, 33, 39, 46, 53, 61, 69,
78, 86, 96, 106, 116, 126, 138, 149,
161, 173, 186, 199, 212, 226, 240, 255
};
static const uint8_t gamma_table_64[64] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 10, 12, 14, 16, 18, 20, 22,
24, 26, 29, 32, 35, 38, 41, 44,
47, 50, 53, 57, 61, 65, 69, 73,
77, 81, 85, 89, 94, 99, 104, 109,
114, 119, 124, 129, 134, 140, 146, 152,
158, 164, 170, 176, 182, 188, 195, 202,
209, 216, 223, 230, 237, 244, 251, 255
};
static int write_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, uint8_t data)
{
uint8_t buf[2] = {reg, data};
size_t n;
/* 改动原因:与 jok/htr3236 及 lib_i2c write_reg 一致按字节数判断100kHz 下更稳) */
unsafe {
i2c.write(dev->i2c_addr, buf, 2, n, 1);
}
if (n == 0) {
return I2C_REGOP_DEVICE_NACK;
}
if (n < 2) {
return I2C_REGOP_INCOMPLETE;
}
return I2C_REGOP_SUCCESS;
}
static int write_reg_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_reg,
const uint8_t *data, uint8_t len)
{
uint8_t buf[36 + 1];
size_t n;
buf[0] = start_reg;
for (int i = 0; i < len; i++) {
buf[i + 1] = data[i];
}
unsafe {
i2c.write(dev->i2c_addr, buf, len + 1, n, 1);
}
if (n == 0) {
return I2C_REGOP_DEVICE_NACK;
}
if (n < (len + 1)) {
return I2C_REGOP_INCOMPLETE;
}
return I2C_REGOP_SUCCESS;
}
void htr3236_init(htr3236_t *dev, uint8_t addr)
{
dev->i2c_addr = addr;
}
/* 改动原因jok 在 tile1_io_control_task 拉 SDB此处保持空实现 */
void htr3236_hw_enable(htr3236_t *dev)
{
}
void htr3236_hw_disable(htr3236_t *dev)
{
}
int htr3236_software_wake(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_NORMAL_OP);
}
int htr3236_software_shutdown(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_SHUTDOWN_SOFT);
}
int htr3236_software_reset(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_RESET, 0x00);
}
int htr3236_set_pwm(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel, uint8_t brightness)
{
if (channel < 1 || channel > 36) {
return -1;
}
uint8_t reg = HTR3236_REG_PWM_START + (channel - 1);
return write_reg(dev, i2c, reg, brightness);
}
int htr3236_set_pwm_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch,
const uint8_t *values, uint8_t len)
{
if (start_ch < 1 || start_ch > 36 || len == 0) {
return -1;
}
if (start_ch + len - 1 > 36) {
return -1;
}
uint8_t start_reg = HTR3236_REG_PWM_START + (start_ch - 1);
return write_reg_bulk(dev, i2c, start_reg, values, len);
}
int htr3236_set_led_config(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel,
htr3236_current_t current, uint8_t enable)
{
if (channel < 1 || channel > 36) {
return -1;
}
uint8_t reg = HTR3236_REG_LED_CTRL_START + (channel - 1);
uint8_t data = (enable ? 1 : 0) | (current << 1);
return write_reg(dev, i2c, reg, data);
}
int htr3236_set_led_config_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch,
const uint8_t *configs, uint8_t len)
{
if (start_ch < 1 || start_ch > 36 || len == 0) {
return -1;
}
if (start_ch + len - 1 > 36) {
return -1;
}
uint8_t start_reg = HTR3236_REG_LED_CTRL_START + (start_ch - 1);
return write_reg_bulk(dev, i2c, start_reg, configs, len);
}
int htr3236_update(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_PWM_UPDATE, 0x00);
}
int htr3236_global_enable(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t enable)
{
/* 改动原因:数据手册 4Ah D0——0=正常工作1=关闭全部 LED原 enable?1:0 会误关断 */
uint8_t data = enable ? 0 : 1;
return write_reg(dev, i2c, HTR3236_REG_GLOBAL_CTRL, data);
}
int htr3236_set_frequency(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), htr3236_freq_t freq)
{
uint8_t data = (freq == HTR3236_FREQ_22KHZ) ? 1 : 0;
return write_reg(dev, i2c, HTR3236_REG_FREQ_SET, data);
}
uint8_t htr3236_gamma_32(uint8_t index)
{
if (index >= 32) {
index = 31;
}
return gamma_table_32[index];
}
uint8_t htr3236_gamma_64(uint8_t index)
{
if (index >= 64) {
index = 63;
}
return gamma_table_64[index];
}
/* 改动原因:自检读 shutdown 寄存器区分「I2C 有应答」与「芯片已唤醒」 */
int htr3236_read_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, uint8_t *value)
{
i2c_regop_res_t result;
if (value == NULL) {
return -1;
}
/* 改动原因:使用 lib_i2c 标准 read_reg重复起始与 jok 一致 */
unsafe {
*value = i2c.read_reg(dev->i2c_addr, reg, result);
}
if (result == I2C_REGOP_SUCCESS) {
return I2C_REGOP_SUCCESS;
}
return I2C_REGOP_DEVICE_NACK;
}

View File

@@ -0,0 +1,54 @@
/**
* @file tx1_led_effects.h
* @brief TX1 HTR3236 RGB 灯效与工厂复位 LED移植自 jok led_effects.xc / ui_app.c
*/
#ifndef TX1_LED_EFFECTS_H
#define TX1_LED_EFFECTS_H
#include "htr3236.h"
#include <i2c.h>
#include <stdint.h>
/* 与 jok ui_app.h factory_reset_effect_state_t 一致 */
typedef enum {
TX1_FACTORY_RESET_IDLE = 0,
TX1_FACTORY_RESET_WAITING,
TX1_FACTORY_RESET_COUNTDOWN,
TX1_FACTORY_RESET_COUNTDOWN_2,
TX1_FACTORY_RESET_TRIGGERED
} tx1_factory_reset_state_t;
/* 与 jok led_effect_t 一致 */
typedef enum {
TX1_EFFECT_RACE = 0,
TX1_EFFECT_BREATH_ALL,
TX1_EFFECT_RAINBOW_RACE,
TX1_EFFECT_RAINBOW_FILL,
TX1_EFFECT_COLOR_WAVE,
TX1_EFFECT_STROBE,
TX1_EFFECT_PULSE,
TX1_EFFECT_SPARKLE,
TX1_EFFECT_GRADIENT,
TX1_EFFECT_MAX
} tx1_led_effect_t;
extern tx1_factory_reset_state_t g_tx1_factory_reset_state;
void tx1_factory_reset_countdown_start(void);
void tx1_factory_reset_countdown_6s(void);
void tx1_factory_reset_countdown_10s(void);
void tx1_factory_reset_triggered(void);
void tx1_factory_reset_cancel(void);
/* 改动原因:工厂复位灯效占用 RGB 时gpio_leds_dirty 不应再刷音量条 */
unsigned tx1_factory_reset_rgb_active(void);
void tx1_factory_reset_led_tick(htr3236_t *dev, client interface i2c_master_if i2c);
/* 改动原因50ms 定时器入口,对照 jok led_effects_period_update_task */
void tx1_led_effects_periodic(htr3236_t *dev, client interface i2c_master_if i2c,
unsigned game_mode,
unsigned feature_mode,
unsigned led_pattern_step);
#endif /* TX1_LED_EFFECTS_H */

View File

@@ -0,0 +1,414 @@
/**
* @file tx1_led_effects.xc
* @brief HTR3236 RGB 灯效 + 工厂复位 LED移植自 jok led_effects.xc50ms 步进)
*/
#include "tx1_led_effects.h"
#include <string.h>
#define TX1_RGB_LED_MAX 12
/* 改动原因:与 audiohw 提高后的亮度一致,否则灯效仍几乎不可见 */
/* 改动原因:与 bringup 自检亮度一致,便于肉眼确认灯效 */
#define TX1_FX_RGB_BRIGHTNESS 200
#define TX1_FX_SCALE8(c) ((uint8_t)(((unsigned)(c) * TX1_FX_RGB_BRIGHTNESS) / 255))
/* D1-D12 B,G,R 通道映射(与 audiohw rgb_led_map 相同) */
static const uint8_t tx1_rgb_led_map[13][3] = {
{0, 0, 0},
{24, 23, 22}, {21, 20, 19}, {18, 17, 16}, {15, 14, 13},
{12, 11, 10}, {9, 8, 7}, {6, 5, 4}, {3, 2, 1},
{36, 35, 34}, {33, 32, 31}, {30, 29, 28}, {27, 26, 25}
};
static void tx1_fx_pwm_led(htr3236_t *dev, client interface i2c_master_if i2c,
uint8_t led, uint8_t r, uint8_t g, uint8_t b)
{
if (led < 1 || led > TX1_RGB_LED_MAX) return;
htr3236_set_pwm(dev, i2c, tx1_rgb_led_map[led][0], b);
htr3236_set_pwm(dev, i2c, tx1_rgb_led_map[led][1], g);
htr3236_set_pwm(dev, i2c, tx1_rgb_led_map[led][2], r);
}
static void tx1_fx_update(htr3236_t *dev, client interface i2c_master_if i2c)
{
htr3236_update(dev, i2c);
}
static void tx1_fx_all_off(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t zeros[36];
int i;
for (i = 0; i < 36; i++) zeros[i] = 0;
htr3236_set_pwm_bulk(dev, i2c, 1, zeros, 36);
htr3236_update(dev, i2c);
}
static void tx1_fx_all_color(htr3236_t *dev, client interface i2c_master_if i2c,
uint8_t r, uint8_t g, uint8_t b)
{
uint8_t led;
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
tx1_fx_pwm_led(dev, i2c, led, r, g, b);
}
tx1_fx_update(dev, i2c);
}
/*=========================================================================
灯效状态jok led_effects.xc
-----------------------------------------------------------------------*/
static int head_pos = 0;
static int breath_idx = 0;
static int rainbow_hue = 0;
static int color_wave_pos = 0;
static uint32_t sparkle_seed = 1;
static int gradient_pos = 0;
static const uint8_t breath_curve[] = {
0, 8, 16, 28, 40, 55, 70, 88, 106, 125, 144, 163, 180, 196, 210, 222,
232, 240, 246, 250, 252, 253, 252, 250, 246, 240, 232, 222, 210, 196,
180, 163, 144, 125, 106, 88, 70, 55, 40, 28, 16, 8, 0
};
#define BREATH_STEPS (sizeof(breath_curve) / sizeof(breath_curve[0]))
static const uint8_t trail_table[] = {255, 200, 140, 80, 40, 20, 8};
#define TRAIL_LEN (sizeof(trail_table) / sizeof(trail_table[0]))
static const uint8_t rainbow_trail_table[] = {255, 200, 150, 100, 60, 30, 15};
#define RAINBOW_TRAIL_LEN (sizeof(rainbow_trail_table) / sizeof(rainbow_trail_table[0]))
static uint32_t tx1_simple_rand(void)
{
sparkle_seed = sparkle_seed * 1103515245u + 12345u;
return (sparkle_seed >> 16) & 0x7FFFu;
}
/* 改动原因:移植 jok get_rainbow_color */
static void tx1_get_rainbow_color(int hue, uint8_t *r, uint8_t *g, uint8_t *b)
{
int phase = hue % 240;
if (phase < 40) {
*r = 255; *g = (uint8_t)((phase * 255) / 40); *b = 0;
} else if (phase < 80) {
*r = (uint8_t)(255 - ((phase - 40) * 255) / 40); *g = 255; *b = 0;
} else if (phase < 120) {
*r = 0; *g = 255; *b = (uint8_t)(((phase - 80) * 255) / 40);
} else if (phase < 160) {
*r = 0; *g = (uint8_t)(255 - ((phase - 120) * 255) / 40); *b = 255;
} else if (phase < 200) {
*r = (uint8_t)(((phase - 160) * 255) / 40); *g = 0; *b = 255;
} else {
*r = 255; *g = 0; *b = (uint8_t)(255 - ((phase - 200) * 255) / 40);
}
}
/*=========================================================================
工厂复位 LEDjok factory_reset_led_effect_loop
-----------------------------------------------------------------------*/
tx1_factory_reset_state_t g_tx1_factory_reset_state = TX1_FACTORY_RESET_IDLE;
static int g_tx1_factory_reset_timer_counter = 0;
static int g_tx1_factory_reset_blink_counter = 0;
void tx1_factory_reset_countdown_start(void)
{
g_tx1_factory_reset_state = TX1_FACTORY_RESET_WAITING;
g_tx1_factory_reset_timer_counter = 0;
g_tx1_factory_reset_blink_counter = 0;
}
void tx1_factory_reset_countdown_6s(void)
{
g_tx1_factory_reset_state = TX1_FACTORY_RESET_COUNTDOWN;
g_tx1_factory_reset_timer_counter = 0;
g_tx1_factory_reset_blink_counter = 0;
}
void tx1_factory_reset_countdown_10s(void)
{
g_tx1_factory_reset_state = TX1_FACTORY_RESET_COUNTDOWN_2;
g_tx1_factory_reset_timer_counter = 0;
g_tx1_factory_reset_blink_counter = 0;
}
void tx1_factory_reset_triggered(void)
{
g_tx1_factory_reset_state = TX1_FACTORY_RESET_TRIGGERED;
g_tx1_factory_reset_timer_counter = 0;
g_tx1_factory_reset_blink_counter = 0;
}
void tx1_factory_reset_cancel(void)
{
g_tx1_factory_reset_state = TX1_FACTORY_RESET_IDLE;
g_tx1_factory_reset_timer_counter = 0;
g_tx1_factory_reset_blink_counter = 0;
}
unsigned tx1_factory_reset_rgb_active(void)
{
return (g_tx1_factory_reset_state != TX1_FACTORY_RESET_IDLE
&& g_tx1_factory_reset_state != TX1_FACTORY_RESET_WAITING) ? 1 : 0;
}
void tx1_factory_reset_led_tick(htr3236_t *dev, client interface i2c_master_if i2c)
{
switch (g_tx1_factory_reset_state) {
case TX1_FACTORY_RESET_WAITING:
break;
case TX1_FACTORY_RESET_COUNTDOWN:
g_tx1_factory_reset_timer_counter++;
if (g_tx1_factory_reset_timer_counter >= 10) {
g_tx1_factory_reset_timer_counter = 0;
g_tx1_factory_reset_blink_counter++;
if ((g_tx1_factory_reset_blink_counter % 2) == 0) {
tx1_fx_all_color(dev, i2c,
0, TX1_FX_SCALE8(255), 0);
} else {
tx1_fx_all_color(dev, i2c,
TX1_FX_SCALE8(139), TX1_FX_SCALE8(91), TX1_FX_SCALE8(246));
}
}
break;
case TX1_FACTORY_RESET_COUNTDOWN_2:
g_tx1_factory_reset_timer_counter++;
if (g_tx1_factory_reset_timer_counter >= 2) {
g_tx1_factory_reset_timer_counter = 0;
if (g_tx1_factory_reset_blink_counter == 0) {
g_tx1_factory_reset_blink_counter = 1;
tx1_fx_all_color(dev, i2c, 0, 0, 0);
} else {
g_tx1_factory_reset_blink_counter = 0;
tx1_fx_all_color(dev, i2c, TX1_FX_SCALE8(255), 0, 0);
}
}
break;
case TX1_FACTORY_RESET_TRIGGERED:
tx1_fx_all_color(dev, i2c, 0, 0, 0);
break;
default:
break;
}
}
/*=========================================================================
装饰灯效(每步由 50ms 定时器调用一次)
-----------------------------------------------------------------------*/
static void tx1_effect_race(htr3236_t *dev, client interface i2c_master_if i2c)
{
int i;
for (i = 0; i < TX1_RGB_LED_MAX; i++) {
int dist = (head_pos - i + TX1_RGB_LED_MAX) % TX1_RGB_LED_MAX;
uint8_t br = 0;
if (dist < (int)TRAIL_LEN) {
br = TX1_FX_SCALE8(trail_table[dist]);
}
tx1_fx_pwm_led(dev, i2c, (uint8_t)(i + 1), br, br, br);
}
tx1_fx_update(dev, i2c);
head_pos = (head_pos + 1) % TX1_RGB_LED_MAX;
}
static void tx1_effect_breath_all(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t br = TX1_FX_SCALE8(breath_curve[breath_idx]);
uint8_t led;
breath_idx = (breath_idx + 1) % (int)BREATH_STEPS;
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
tx1_fx_pwm_led(dev, i2c, led, br, br, br);
}
tx1_fx_update(dev, i2c);
}
static void tx1_effect_rainbow_race(htr3236_t *dev, client interface i2c_master_if i2c)
{
int i;
for (i = 0; i < TX1_RGB_LED_MAX; i++) {
int dist = (head_pos - i + TX1_RGB_LED_MAX) % TX1_RGB_LED_MAX;
if (dist < (int)RAINBOW_TRAIL_LEN) {
uint8_t brightness = rainbow_trail_table[dist];
uint8_t r, g, b;
int hue = (head_pos * 20) % 240;
tx1_get_rainbow_color(hue, &r, &g, &b);
r = (uint8_t)((r * brightness) / 255);
g = (uint8_t)((g * brightness) / 255);
b = (uint8_t)((b * brightness) / 255);
tx1_fx_pwm_led(dev, i2c, (uint8_t)(i + 1),
TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
} else {
tx1_fx_pwm_led(dev, i2c, (uint8_t)(i + 1), 0, 0, 0);
}
}
tx1_fx_update(dev, i2c);
head_pos = (head_pos + 1) % TX1_RGB_LED_MAX;
}
static void tx1_effect_rainbow_fill(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t led;
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
int hue = (rainbow_hue + ((int)led * 20)) % 240;
uint8_t r, g, b;
tx1_get_rainbow_color(hue, &r, &g, &b);
tx1_fx_pwm_led(dev, i2c, led, TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
}
tx1_fx_update(dev, i2c);
rainbow_hue = (rainbow_hue + 4) % 240;
}
static void tx1_effect_color_wave(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t led;
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
int hue = (((int)led * 20) + color_wave_pos) % 240;
uint8_t r, g, b;
tx1_get_rainbow_color(hue, &r, &g, &b);
tx1_fx_pwm_led(dev, i2c, led, TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
}
tx1_fx_update(dev, i2c);
color_wave_pos = (color_wave_pos + 8) % 240;
}
static void tx1_effect_strobe(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t r = (uint8_t)(tx1_simple_rand() % 256);
uint8_t g = (uint8_t)(tx1_simple_rand() % 256);
uint8_t b = (uint8_t)(tx1_simple_rand() % 256);
uint8_t led;
if (tx1_simple_rand() % 2) {
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
tx1_fx_pwm_led(dev, i2c, led,
TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
}
} else {
tx1_fx_all_off(dev, i2c);
return;
}
tx1_fx_update(dev, i2c);
}
static void tx1_effect_pulse(htr3236_t *dev, client interface i2c_master_if i2c)
{
uint8_t brightness = breath_curve[breath_idx];
uint8_t r, g, b;
uint8_t led;
breath_idx = (breath_idx + 1) % (int)BREATH_STEPS;
if (brightness < 128) {
r = brightness;
g = (uint8_t)(brightness / 3);
b = 0;
} else {
r = 255; g = 255; b = 255;
}
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
tx1_fx_pwm_led(dev, i2c, led,
TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
}
tx1_fx_update(dev, i2c);
}
static void tx1_effect_sparkle(htr3236_t *dev, client interface i2c_master_if i2c)
{
int sparkle_count = 3 + (int)(tx1_simple_rand() % 3);
int i;
uint8_t led;
tx1_fx_all_off(dev, i2c);
for (i = 0; i < sparkle_count; i++) {
int led_idx = (int)(tx1_simple_rand() % TX1_RGB_LED_MAX);
uint8_t brightness = (uint8_t)(100 + (tx1_simple_rand() % 156));
uint8_t color_choice = (uint8_t)(tx1_simple_rand() % 6);
uint8_t r = 0, g = 0, b = 0;
switch (color_choice) {
case 0: r = brightness; break;
case 1: g = brightness; break;
case 2: b = brightness; break;
case 3: r = brightness; g = brightness; break;
case 4: g = brightness; b = brightness; break;
default: r = brightness; g = brightness; b = brightness; break;
}
tx1_fx_pwm_led(dev, i2c, (uint8_t)(led_idx + 1),
TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
}
tx1_fx_update(dev, i2c);
}
static void tx1_effect_gradient(htr3236_t *dev, client interface i2c_master_if i2c)
{
int progress = gradient_pos;
uint8_t r, g, b;
uint8_t led;
if (progress < 128) {
r = 255; g = 0; b = (uint8_t)((progress * 2) * 255 / 256);
} else {
r = (uint8_t)(255 - ((progress - 128) * 2) * 255 / 256);
g = 0; b = 255;
}
for (led = 1; led <= TX1_RGB_LED_MAX; led++) {
tx1_fx_pwm_led(dev, i2c, led,
TX1_FX_SCALE8(r), TX1_FX_SCALE8(g), TX1_FX_SCALE8(b));
}
tx1_fx_update(dev, i2c);
gradient_pos = (gradient_pos + 2) % 256;
}
/* game_mode / feature_mode 数值与 audiohw tx1_*_t 枚举一致BYPASS=0, FEATURE_NONE=0 */
void tx1_led_effects_periodic(htr3236_t *dev, client interface i2c_master_if i2c,
unsigned game_mode,
unsigned feature_mode,
unsigned led_pattern_step)
{
if (g_tx1_factory_reset_state != TX1_FACTORY_RESET_IDLE) {
tx1_factory_reset_led_tick(dev, i2c);
return;
}
if (feature_mode != 0) {
return;
}
/* 非 BYPASS 时暂不跑方位灯效ex3d 后续可接);熄灭 RGB 装饰 */
if (game_mode != 0) {
return;
}
switch (led_pattern_step) {
case TX1_EFFECT_RACE:
tx1_effect_race(dev, i2c);
break;
case TX1_EFFECT_BREATH_ALL:
tx1_effect_breath_all(dev, i2c);
break;
case TX1_EFFECT_RAINBOW_RACE:
tx1_effect_rainbow_race(dev, i2c);
break;
case TX1_EFFECT_RAINBOW_FILL:
tx1_effect_rainbow_fill(dev, i2c);
break;
case TX1_EFFECT_COLOR_WAVE:
tx1_effect_color_wave(dev, i2c);
break;
case TX1_EFFECT_STROBE:
tx1_effect_strobe(dev, i2c);
break;
case TX1_EFFECT_PULSE:
tx1_effect_pulse(dev, i2c);
break;
case TX1_EFFECT_SPARKLE:
tx1_effect_sparkle(dev, i2c);
break;
case TX1_EFFECT_GRADIENT:
tx1_effect_gradient(dev, i2c);
break;
default:
tx1_fx_all_off(dev, i2c);
break;
}
}

View File

@@ -32,7 +32,8 @@ void tx1_led_helper_task(server interface tx1_led_if led_if)
p_led_d3 <: 0xF;
p_led_d5 <: 1;
p_led_d4_d7_d6 <: 0xF;
p_htr3236_sdb <: 0; // HTR3236 disabled initially
/* 改动原因:上电即拉高 SDB与 jok tile1_io_control_task 一致;勿长期拉低否则 I2C 配置无效 */
p_htr3236_sdb <: 1;
p_ctl_mute <: 1; // Muted initially
while (1)