KT25-1015_AC695x_SDK310/apps/kaotings/kt.c

627 lines
15 KiB
C
Raw Normal View History

#include "kt.h"
#include "key_event_deal.h"
#include "music_player.h"
#include "audio_config.h"
#include "tone_player.h"
#include "update.h"
enum
{
KT_LED_IDLE = 0, /* 空闲慢闪 */
KT_LED_PLAY, /* 播放常亮 */
KT_LED_FAIL, /* 播放失败快闪 */
KT_LED_UPDATE, /* 升级快闪 */
};
/* 定时器 50ms慢闪 1s灭/1s亮快闪 100ms灭/100ms亮 */
#define KT_LED_SLOW_HALF 20
#define KT_LED_FAST_HALF 2
typedef struct _kt_var_
{
int kt_timer;
int t_cnt;
u8 led_mode;
u8 active_ch; /* 1~4 按键播放会话中, 0=无 */
u8 fail_ch; /* 处于失败快闪的通道, 0=无 */
u8 file_idx; /* 当前播放文件序号, 00/01/02... */
} _kt_var;
static _kt_var kt_var;
#define __this (&kt_var)
static void kt_key_led_on(u8 ch)
{
switch (ch)
{
case 1: KEY_LED_OUT_CH1_ON(); break;
case 2: KEY_LED_OUT_CH2_ON(); break;
case 3: KEY_LED_OUT_CH3_ON(); break;
case 4: KEY_LED_OUT_CH4_ON(); break;
default: break;
}
}
static void kt_key_led_all_on(void)
{
KEY_LED_OUT_CH1_ON();
KEY_LED_OUT_CH2_ON();
KEY_LED_OUT_CH3_ON();
KEY_LED_OUT_CH4_ON();
}
static void kt_key_led_all_off(void)
{
KEY_LED_OUT_CH1_OFF();
KEY_LED_OUT_CH2_OFF();
KEY_LED_OUT_CH3_OFF();
KEY_LED_OUT_CH4_OFF();
}
static void kt_led_bar_on(u8 ch)
{
switch (ch)
{
case 1:
LED_BAR_OUT_CH1_ON();
break;
case 2:
LED_BAR_OUT_CH2_ON();
break;
case 3:
LED_BAR_OUT_CH3_ON();
break;
case 4:
LED_BAR_OUT_CH4_ON();
break;
default:
break;
}
}
static void kt_led_bar_all_off(void)
{
LED_BAR_OUT_CH1_OFF();
LED_BAR_OUT_CH2_OFF();
LED_BAR_OUT_CH3_OFF();
LED_BAR_OUT_CH4_OFF();
}
static void kt_led_set_mode(u8 mode)
{
__this->led_mode = mode;
__this->t_cnt = 0;
kt_key_led_all_off();
kt_led_bar_all_off();
KUP_LED_OFF();
KDOWN_LED_OFF();
if (mode == KT_LED_PLAY)
{
SYS_LED_ON();
kt_key_led_on(__this->active_ch);
kt_led_bar_on(__this->active_ch);
KUP_LED_ON();
KDOWN_LED_ON();
}
else
{
SYS_LED_OFF();
}
}
static void kt_clear_fail_to_idle(void)
{
if (__this->fail_ch == 0)
{
return;
}
__this->fail_ch = 0;
kt_led_set_mode(KT_LED_IDLE);
}
static void kt_audio_all_off(void)
{
AUDIO_OUT_CH1_OFF();
AUDIO_OUT_CH2_OFF();
AUDIO_OUT_CH3_OFF();
AUDIO_OUT_CH4_OFF();
}
static void kt_audio_all_on(void)
{
AUDIO_OUT_CH1_ON();
AUDIO_OUT_CH2_ON();
AUDIO_OUT_CH3_ON();
AUDIO_OUT_CH4_ON();
}
/* 升级提示音需要四路音频输出同时打开LED 仍由状态机控制。 */
static void kt_all_channels_on(void)
{
kt_audio_all_on();
}
static void kt_all_channels_off(void)
{
kt_audio_all_off();
}
/* CS8406 复位释放,保证 IIS 通路稳定 */
static void kt_cs8406_reset_release(void)
{
gpio_set_direction(IO_PORTA_06, 0);
gpio_set_output_value(IO_PORTA_06, 0);
os_time_dly(5); /* ~50ms 保持复位 */
gpio_set_output_value(IO_PORTA_06, 1);
os_time_dly(30); /* ~300ms 等待芯片就绪 */
}
static void kt_channel_drive_off(u8 ch)
{
switch (ch)
{
case 1: AUDIO_OUT_CH1_OFF(); break;
case 2: AUDIO_OUT_CH2_OFF(); break;
case 3: AUDIO_OUT_CH3_OFF(); break;
case 4: AUDIO_OUT_CH4_OFF(); break;
default: break;
}
}
/* 音频通道互斥切换;灯光由 kt_led_set_mode() 统一处理。 */
static void kt_channel_outputs_on(u8 ch)
{
kt_audio_all_off();
switch (ch)
{
case 1: AUDIO_OUT_CH1_ON(); break;
case 2: AUDIO_OUT_CH2_ON(); break;
case 3: AUDIO_OUT_CH3_ON(); break;
case 4: AUDIO_OUT_CH4_ON(); break;
default: break;
}
}
static void kt_gpio_out_init(u32 pin)
{
gpio_set_pull_down(pin, 0);
gpio_set_pull_up(pin, 0);
gpio_set_direction(pin, 0);
gpio_set_output_value(pin, 0);
}
void kt_boot_init(void)
{
// CS8406 RST
gpio_set_pull_down(IO_PORTA_06, 0);
gpio_set_pull_up(IO_PORTA_06, 0);
gpio_set_direction(IO_PORTA_06, 0);
gpio_set_output_value(IO_PORTA_06, 0);
// iis 双绑引脚高阻化
gpio_set_pull_down(IO_PORTA_01, 0);
gpio_set_pull_up(IO_PORTA_01, 0);
gpio_set_direction(IO_PORTA_01, 1);
gpio_set_die(IO_PORTA_01, 1);
gpio_set_pull_down(IO_PORTA_05, 0);
gpio_set_pull_up(IO_PORTA_05, 0);
gpio_set_direction(IO_PORTA_05, 1);
gpio_set_die(IO_PORTA_05, 1);
// CS8406 TX EN
kt_gpio_out_init(AUDIO_OUT_CHANNEL1);
kt_gpio_out_init(AUDIO_OUT_CHANNEL2);
kt_gpio_out_init(AUDIO_OUT_CHANNEL3);
kt_gpio_out_init(AUDIO_OUT_CHANNEL4);
// key led output
kt_gpio_out_init(KEY_LED_OUT_CHANNEL1);
kt_gpio_out_init(KEY_LED_OUT_CHANNEL2);
kt_gpio_out_init(KEY_LED_OUT_CHANNEL3);
kt_gpio_out_init(KEY_LED_OUT_CHANNEL4);
// led bar output
kt_gpio_out_init(LED_BAR_OUT_CHANNEL1);
kt_gpio_out_init(LED_BAR_OUT_CHANNEL2);
kt_gpio_out_init(LED_BAR_OUT_CHANNEL3);
kt_gpio_out_init(LED_BAR_OUT_CHANNEL4);
// vol key led output
kt_gpio_out_init(KUP_LED_PIN);
kt_gpio_out_init(KDOWN_LED_PIN);
// sys led
kt_gpio_out_init(SYS_LED_PIN);
}
static void timer_cb(void *priv)
{
u8 half;
u8 on;
(void)priv;
if (__this->led_mode == KT_LED_PLAY)
{
SYS_LED_ON();
kt_key_led_all_off();
kt_key_led_on(__this->active_ch);
kt_led_bar_all_off();
kt_led_bar_on(__this->active_ch);
KUP_LED_ON();
KDOWN_LED_ON();
return;
}
half = (__this->led_mode == KT_LED_FAIL || __this->led_mode == KT_LED_UPDATE)
? KT_LED_FAST_HALF
: KT_LED_SLOW_HALF;
__this->t_cnt++;
if (__this->t_cnt <= half)
{
on = 0;
}
else if (__this->t_cnt <= (half * 2))
{
on = 1;
}
else
{
__this->t_cnt = 0;
on = 0;
}
kt_led_bar_all_off();
KUP_LED_OFF();
KDOWN_LED_OFF();
if (on)
{
SYS_LED_ON();
if (__this->led_mode == KT_LED_IDLE)
{
kt_key_led_all_on();
}
else if (__this->led_mode == KT_LED_FAIL)
{
kt_key_led_on(__this->fail_ch);
}
}
else
{
SYS_LED_OFF();
kt_key_led_all_off();
}
}
static void start_time_base(u32 time_base_ms)
{
if (__this->kt_timer)
{
sys_timer_del(__this->kt_timer);
}
__this->t_cnt = 0;
__this->kt_timer = sys_timer_add(NULL, timer_cb, time_base_ms);
}
/* 音量不记忆:空闲时固定恢复为 SYS_DEFAULT_VOL */
static void kt_vol_reset_default(void)
{
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, SYS_DEFAULT_VOL, 1);
printf("kt vol reset to %d\n", SYS_DEFAULT_VOL);
}
static void kt_update_play_tone(const char *name)
{
int err;
u32 t;
extern u8 get_max_sys_vol(void);
tone_play_stop();
if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY)
{
music_player_stop(0);
os_time_dly(5);
}
kt_cs8406_reset_release();
kt_all_channels_on();
app_audio_output_start();
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_max_sys_vol());
app_audio_set_volume(APP_AUDIO_STATE_WTONE, get_max_sys_vol(), 1);
printf("kt_update_play_tone: %s\n", name);
err = tone_play(name, 1);
printf("kt_update_play_tone err=%d\n", err);
/* 等 DAC 真正启动后再判 START避免 dec 已置位但无声 */
for (t = 0; t < 100; t++)
{
wdt_clear();
if (tone_get_dec_status() == TONE_START)
{
break;
}
os_time_dly(1);
}
printf("kt_tone wait_start=%d dec=%d get=%d\n",
t, tone_get_dec_status(), tone_get_status());
if (tone_get_dec_status() == TONE_START)
{
for (t = 0; t < 1500; t++)
{
wdt_clear();
if (tone_get_dec_status() != TONE_START)
{
break;
}
os_time_dly(1);
}
printf("kt_tone wait_end=%d\n", t);
os_time_dly(20); /* 播完后稍留,避免尾音被截断 */
}
else
{
printf("kt_tone start fail, keep ch on for a while\n");
os_time_dly(200);
}
kt_all_channels_off();
}
void kt_update_led_start(void)
{
printf("kt_update_led_start\n");
if (!__this->kt_timer)
{
start_time_base(50);
}
kt_led_set_mode(KT_LED_UPDATE);
}
void kt_update_led_finish(void)
{
printf("kt_update_led_finish\n");
/* 升级结束:恢复 SYS_LED 正常空闲慢闪 */
__this->fail_ch = 0;
kt_led_set_mode(KT_LED_IDLE);
}
void kt_update_start_remind(void)
{
printf("kt_update_start_remind\n");
kt_update_led_start();
kt_update_play_tone(TONE_SUP);
}
void kt_update_finish_remind(u16 result)
{
printf("kt_update_finish_remind result=0x%x\n", result);
if (result == UPDATA_SUCC)
{
kt_update_play_tone(TONE_EUP);
}
kt_update_led_finish();
}
void kt_init(void)
{
printf("kt_init\n");
__this->active_ch = 0;
__this->fail_ch = 0;
__this->file_idx = 0;
kt_led_set_mode(KT_LED_IDLE);
// CS8406 RST
gpio_set_output_value(IO_PORTA_06, 1);
/* 默认关闭各音频通道,按键播放时再打开对应通道 */
kt_audio_all_off();
kt_key_led_all_off();
kt_led_bar_all_off();
KUP_LED_OFF();
KDOWN_LED_OFF();
kt_vol_reset_default();
start_time_base(50);
printf("kt_init end\n");
}
/* 播放结束/出错/拔卡:关闭音频输出,恢复待机灯态和默认音量 */
int kt_music_play_end_handler(void)
{
if (__this->active_ch == 0)
{
return 0;
}
printf("kt_music_play_end_handler ch=%d\n", __this->active_ch);
kt_channel_drive_off(__this->active_ch);
__this->active_ch = 0;
__this->fail_ch = 0;
/* 必须停解码,否则 get_play_status 仍为 PLAY下次按键会误判 */
music_player_stop(0);
kt_led_set_mode(KT_LED_IDLE);
kt_vol_reset_default();
return 1;
}
static int kt_try_play_path(const char *path)
{
int err;
err = music_player_play_by_path((char *)"sd1", path);
if (err != MUSIC_PLAYER_SUCC)
{
err = music_player_play_by_path((char *)"udisk0", path);
}
return err;
}
static int kt_try_play_first_file(void)
{
int err;
err = music_player_play_first_file((char *)"sd1");
if (err != MUSIC_PLAYER_SUCC)
{
err = music_player_play_first_file((char *)"udisk0");
}
return err;
}
static int kt_play_file_idx(u8 idx)
{
char path[16];
sprintf(path, "/%02d.*", idx);
printf("kt_play_file_idx %s\n", path);
return kt_try_play_path(path);
}
static void kt_play_success(u8 ch)
{
printf("kt_play_success ch=%d\n", ch);
kt_channel_outputs_on(ch);
__this->active_ch = ch;
__this->fail_ch = 0;
kt_led_set_mode(KT_LED_PLAY);
}
static void kt_play_fail(u8 ch)
{
printf("kt_play_fail ch=%d\n", ch);
/* 失败SYS_LED 与对应 KEY_LED 快闪LED_BAR 和音量灯保持熄灭 */
kt_audio_all_off();
kt_key_led_all_off();
kt_led_bar_all_off();
__this->active_ch = 0;
__this->fail_ch = ch;
kt_led_set_mode(KT_LED_FAIL);
}
static void kt_switch_channel_only(u8 ch)
{
printf("kt_switch_channel_only ch=%d\n", ch);
/* 正在播放其它通道:只切音频输出,不改变当前歌曲 */
kt_channel_outputs_on(ch);
__this->active_ch = ch;
__this->fail_ch = 0;
printf("kt_switch_channel_only fail_ch=%d\n", __this->fail_ch);
kt_led_set_mode(KT_LED_PLAY);
}
static int kt_channel_key_handler(u8 ch)
{
int err;
u8 playing;
/* 若之前有通道错误,先恢复为慢闪 */
printf("kt_channel_key_handler ch=%d\n", ch);
kt_clear_fail_to_idle();
playing = (music_player_get_play_status() == FILE_DEC_STATUS_PLAY);
printf("kt_channel_key_handler playing=%d active_ch=%d\n", playing, __this->active_ch);
/* 仅 KT 会话在播active_ch!=0才走同通道 next / 异通道切换;
* active_ch=0便 */
if (playing && (__this->active_ch != 0))
{
if (__this->active_ch == ch)
{
/* 同通道:先尝试播放 idx+1如 01→02失败再用播放器自动下一曲 */
u8 next_idx = __this->file_idx + 1;
printf("kt_channel_key_handler same ch next_idx=%d\n", next_idx);
err = kt_play_file_idx(next_idx);
if (err == MUSIC_PLAYER_SUCC)
{
__this->file_idx = next_idx;
kt_play_success(ch);
return MUSIC_PLAYER_SUCC;
}
err = music_player_play_next();
if (err == MUSIC_PLAYER_SUCC)
{
__this->file_idx = next_idx;
kt_play_success(ch);
return MUSIC_PLAYER_SUCC;
}
kt_play_fail(ch);
return MUSIC_PLAYER_ERR_NULL;
}
/* 正在播放但不是当前通道:只切换音频和对应灯态 */
printf("kt_channel_key_handler switch ch only %d->%d\n", __this->active_ch, ch);
kt_switch_channel_only(ch);
return MUSIC_PLAYER_SUCC;
}
/* 空闲(或播完残留状态):从 00.* 开始 */
if (playing) {
music_player_stop(0);
}
__this->file_idx = 0;
err = kt_play_file_idx(0);
if (err == MUSIC_PLAYER_SUCC)
{
printf("kt_channel_key_handler idle play 00 ch=%d\n", ch);
kt_play_success(ch);
return MUSIC_PLAYER_SUCC;
}
/* 00.* 不存在:回退播放 sd1/udisk0 第一首 */
err = kt_try_play_first_file();
if (err == MUSIC_PLAYER_SUCC)
{
printf("kt_channel_key_handler idle play first ch=%d\n", ch);
kt_play_success(ch);
return MUSIC_PLAYER_SUCC;
}
printf("kt_channel_key_handler kt_play_fail ch=%d\n", ch);
kt_play_fail(ch);
return MUSIC_PLAYER_ERR_NULL;
}
static int kt_vol_key_handler(u16 key)
{
if (key == KEY_USER_KEY_5)
{
/* 音量+,播放状态下两个音量键灯由统一状态机保持常亮 */
//app_audio_volume_up(1);
app_task_put_key_msg(KEY_VOL_UP,0);
printf("kt vol+ %d\n", app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
}
else
{
/* 音量-,播放状态下两个音量键灯由统一状态机保持常亮 */
//app_audio_volume_down(1);
if (app_audio_get_volume(APP_AUDIO_STATE_MUSIC) > 2)
{
app_task_put_key_msg(KEY_VOL_DOWN,0);
}
printf("kt vol- %d\n", app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
}
return MUSIC_PLAYER_ERR_NULL;
}
/*
* KEY1~4 00.* next
*
* KEY5/6 +/-
*/
int kt_key_event_handler(u16 key)
{
u8 ch;
if (key == KEY_USER_KEY_5 || key == KEY_USER_KEY_6)
{
return kt_vol_key_handler(key);
}
if (key < KEY_USER_KEY_1 || key > KEY_USER_KEY_4)
{
return MUSIC_PLAYER_ERR_NULL;
}
ch = (u8)(key - KEY_USER_KEY_1 + 1);
printf("kt_key_event_handler key=%d ch=%d\n", key, ch);
return kt_channel_key_handler(ch);
}