583 lines
13 KiB
C
583 lines
13 KiB
C
#include "fm_manage.h"
|
|
#include "device/iic.h"
|
|
#include "server/audio_server.h"
|
|
#include "server/server_core.h"
|
|
#include "os/os_api.h"
|
|
#include "fm_rw.h"
|
|
#include "system/timer.h"
|
|
|
|
#if CONFIG_FM_DEV_ENABLE
|
|
|
|
#define IIC_DELAY_US 1000
|
|
|
|
#define SCANE_DOWN (0x01)
|
|
#define SCANE_UP (0x02)
|
|
|
|
|
|
struct fm_info {
|
|
u8 volume;
|
|
u8 mute;
|
|
u8 on;
|
|
u8 scan_flag;
|
|
int scan_fre;
|
|
int pid;
|
|
FM_INTERFACE *dev;
|
|
void *enc_server;
|
|
void *iic;
|
|
void *pwm;
|
|
u16 fm_freq_cur; // real_freq = fm_freq_cur + 875
|
|
u16 fm_freq_channel_cur;
|
|
u16 fm_total_channel;
|
|
};
|
|
|
|
static struct fm_info *fm_hdl;
|
|
|
|
extern void linein_to_fdac_mute(u8 enable);
|
|
extern int get_app_music_volume(void);
|
|
|
|
void fm_IIC_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len)
|
|
{
|
|
if (!fm_hdl || !fm_hdl->iic) {
|
|
return;
|
|
}
|
|
|
|
void *iic = fm_hdl->iic;
|
|
|
|
dev_ioctl(iic, IIC_IOCTL_START, 0);
|
|
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, w_chip_id)) {
|
|
printf("iic write err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
|
|
if (0xff != register_address) {
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX, register_address)) {
|
|
printf("iic write err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
while (data_len--) {
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX, *buf++)) {
|
|
printf("iic write err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
dev_ioctl(iic, IIC_IOCTL_TX_STOP_BIT, 0);
|
|
|
|
exit:
|
|
dev_ioctl(iic, IIC_IOCTL_STOP, 0);
|
|
delay_us(IIC_DELAY_US);
|
|
}
|
|
|
|
u8 fm_IIC_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len)
|
|
{
|
|
if (!fm_hdl || !fm_hdl->iic) {
|
|
return 0;
|
|
}
|
|
|
|
void *iic = fm_hdl->iic;
|
|
u8 read_len = 0;
|
|
|
|
dev_ioctl(iic, IIC_IOCTL_START, 0);
|
|
|
|
if (0xff != register_address) {
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) {
|
|
printf("iic read err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
|
|
#if 1
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_STOP_BIT, register_address)) {
|
|
printf("iic read err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
|
|
delay_us(IIC_DELAY_US);
|
|
#else
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX, register_address)) {
|
|
printf("iic read err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (dev_ioctl(iic, IIC_IOCTL_TX_WITH_START_BIT, r_chip_id)) {
|
|
printf("iic read err!!! line : %d \n", __LINE__);
|
|
goto exit;
|
|
}
|
|
|
|
while (data_len-- > 1) {
|
|
dev_ioctl(iic, IIC_IOCTL_RX_WITH_ACK, (u32)buf);
|
|
++buf;
|
|
++read_len;
|
|
}
|
|
|
|
dev_ioctl(iic, IIC_IOCTL_RX_WITH_STOP_BIT, (u32)buf);
|
|
|
|
exit:
|
|
dev_ioctl(iic, IIC_IOCTL_STOP, 0);
|
|
delay_us(IIC_DELAY_US);
|
|
|
|
return read_len;
|
|
}
|
|
|
|
static FM_INTERFACE *fm_manage_check_online(void)
|
|
{
|
|
FM_INTERFACE *t_fm_hdl = NULL;
|
|
|
|
list_for_each_fm(t_fm_hdl) {
|
|
if (t_fm_hdl->read_id(NULL) &&
|
|
(memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo)))) {
|
|
printf("fm find dev %s \n", t_fm_hdl->logo);
|
|
return t_fm_hdl;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int fm_manage_init(struct fm_info *fm)
|
|
{
|
|
fm->iic = dev_open("iic0", NULL);
|
|
if (!fm->iic) {
|
|
goto exit;
|
|
}
|
|
|
|
#if 0
|
|
fm->pwm = dev_open("pwm1", NULL);
|
|
if (!fm->pwm) {
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
os_time_dly(5);
|
|
|
|
fm->dev = fm_manage_check_online();
|
|
if (!fm->dev) {
|
|
goto exit;
|
|
}
|
|
|
|
if (0 != fm->dev->init(fm)) {
|
|
goto exit;
|
|
}
|
|
|
|
union audio_req req = {0};
|
|
|
|
fm->enc_server = server_open("audio_server", "enc");
|
|
if (!fm->enc_server) {
|
|
goto exit;
|
|
}
|
|
|
|
req.enc.cmd = AUDIO_ENC_OPEN;
|
|
req.enc.channel = 1;
|
|
req.enc.volume = CONFIG_FM_LINEIN_ADC_GAIN;
|
|
/* req.enc.volume = get_app_music_volume(); */
|
|
req.enc.format = "pcm";
|
|
req.enc.sample_source = "linein";
|
|
req.enc.sample_rate = 44100;
|
|
req.enc.channel_bit_map = BIT(CONFIG_FM_LINEIN_ADC_CHANNEL);
|
|
req.enc.direct2dac = 1;
|
|
req.enc.high_gain = 1;
|
|
|
|
return server_request(fm->enc_server, AUDIO_REQ_ENC, &req);
|
|
|
|
exit:
|
|
if (fm->iic) {
|
|
dev_close(fm->iic);
|
|
fm->iic = NULL;
|
|
}
|
|
if (fm->pwm) {
|
|
dev_close(fm->pwm);
|
|
fm->pwm = NULL;
|
|
}
|
|
if (fm->dev) {
|
|
fm->dev->close(fm);
|
|
fm->dev = NULL;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void fm_manage_close(struct fm_info *fm)
|
|
{
|
|
union audio_req req = {0};
|
|
|
|
if (fm->enc_server) {
|
|
req.enc.cmd = AUDIO_ENC_STOP;
|
|
server_request(fm->enc_server, AUDIO_REQ_ENC, &req);
|
|
server_close(fm->enc_server);
|
|
fm->enc_server = NULL;
|
|
}
|
|
if (fm->dev) {
|
|
fm->dev->close(fm);
|
|
fm->dev = NULL;
|
|
}
|
|
if (fm->iic) {
|
|
dev_close(fm->iic);
|
|
fm->iic = NULL;
|
|
}
|
|
if (fm->pwm) {
|
|
dev_close(fm->pwm);
|
|
fm->pwm = NULL;
|
|
}
|
|
}
|
|
|
|
static void fm_app_mute(struct fm_info *fm, u8 mute)
|
|
{
|
|
if (!fm->on && !mute) {
|
|
return;
|
|
}
|
|
if (fm->mute != mute) {
|
|
fm->dev->mute(fm, mute);
|
|
fm->mute = mute;
|
|
}
|
|
}
|
|
|
|
static int fm_manage_set_fre(struct fm_info *fm, u16 fre)
|
|
{
|
|
return fm->dev->set_fre(fm, fre);
|
|
}
|
|
|
|
static void fm_read_info_init(struct fm_info *fm)
|
|
{
|
|
FM_VM_INFO info = {0};
|
|
|
|
fm_vm_check();
|
|
fm_read_info(&info);
|
|
|
|
fm->fm_freq_cur = info.curFreq;
|
|
printf("fm->fm_freq_cur = %d\n", fm->fm_freq_cur);
|
|
fm->fm_freq_channel_cur = info.curChanel;
|
|
printf("fm->fm_freq_channel_cur = %d\n", fm->fm_freq_channel_cur);
|
|
fm->fm_total_channel = info.total_chanel;
|
|
printf("fm->fm_total_channel = %d\n", fm->fm_total_channel);
|
|
|
|
if (fm->fm_freq_cur == 0 && fm->fm_freq_channel_cur && fm->fm_total_channel) {
|
|
fm->fm_freq_cur = get_fre_via_channel(fm->fm_freq_channel_cur);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
} else {
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
}
|
|
}
|
|
|
|
/*******************fm msg deal*********************/
|
|
static void fm_volume_pp(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag) {
|
|
return;
|
|
}
|
|
fm_app_mute(fm, !fm->mute);
|
|
}
|
|
|
|
static void fm_dec_onoff(struct fm_info *fm, u8 on)
|
|
{
|
|
fm->on = on;
|
|
linein_to_fdac_mute(!on);
|
|
fm_app_mute(fm, !on);
|
|
}
|
|
|
|
static void fm_prev_freq(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag) {
|
|
return;
|
|
}
|
|
|
|
if (fm->fm_freq_cur <= VIRTUAL_FREQ(REAL_FREQ_MIN)) {
|
|
fm->fm_freq_cur = VIRTUAL_FREQ(REAL_FREQ_MAX);
|
|
} else {
|
|
fm->fm_freq_cur -= 1;
|
|
}
|
|
|
|
fm_app_mute(fm, 1);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
fm_last_freq_save(REAL_FREQ(fm->fm_freq_cur));
|
|
fm_app_mute(fm, 0);
|
|
}
|
|
|
|
static void fm_next_freq(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag) {
|
|
return;
|
|
}
|
|
|
|
if (fm->fm_freq_cur >= VIRTUAL_FREQ(REAL_FREQ_MAX)) {
|
|
fm->fm_freq_cur = VIRTUAL_FREQ(REAL_FREQ_MIN);
|
|
} else {
|
|
fm->fm_freq_cur += 1;
|
|
}
|
|
|
|
fm_app_mute(fm, 1);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
fm_last_freq_save(REAL_FREQ(fm->fm_freq_cur));
|
|
fm_app_mute(fm, 0);
|
|
}
|
|
|
|
static void fm_volume_set(struct fm_info *fm)
|
|
{
|
|
union audio_req req = {0};
|
|
|
|
if (fm->enc_server && fm->on) {
|
|
req.enc.cmd = AUDIO_ENC_SET_VOLUME;
|
|
req.enc.volume = get_app_music_volume();
|
|
server_request(fm->enc_server, AUDIO_REQ_ENC, &req);
|
|
linein_to_fdac_mute(0 == get_app_music_volume());
|
|
}
|
|
}
|
|
|
|
static void fm_prev_station(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag || (!fm->fm_total_channel)) {
|
|
return;
|
|
}
|
|
|
|
if (fm->fm_freq_channel_cur <= 1) {
|
|
fm->fm_freq_channel_cur = fm->fm_total_channel;
|
|
} else {
|
|
fm->fm_freq_channel_cur -= 1;
|
|
}
|
|
|
|
fm_app_mute(fm, 1);
|
|
fm->fm_freq_cur = get_fre_via_channel(fm->fm_freq_channel_cur);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
fm_last_ch_save(fm->fm_freq_channel_cur);
|
|
fm_app_mute(fm, 0);
|
|
}
|
|
|
|
static void fm_next_station(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag || (!fm->fm_total_channel)) {
|
|
return;
|
|
}
|
|
|
|
if (fm->fm_freq_channel_cur >= fm->fm_total_channel) {
|
|
fm->fm_freq_channel_cur = 1;
|
|
} else {
|
|
fm->fm_freq_channel_cur += 1;
|
|
}
|
|
|
|
fm_app_mute(fm, 1);
|
|
fm->fm_freq_cur = get_fre_via_channel(fm->fm_freq_channel_cur);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
fm_last_ch_save(fm->fm_freq_channel_cur);
|
|
fm_app_mute(fm, 0);
|
|
}
|
|
|
|
static void fm_timer_handler_down(void *priv)
|
|
{
|
|
struct fm_info *fm = (struct fm_info *)priv;
|
|
|
|
if (fm->scan_flag != SCANE_DOWN) {
|
|
return;
|
|
}
|
|
|
|
if (fm->scan_fre > VIRTUAL_FREQ(REAL_FREQ_MAX)) {
|
|
fm->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MIN);
|
|
fm_app_mute(fm, 1);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
fm->scan_flag = 0;
|
|
fm_app_mute(fm, 0);
|
|
return;
|
|
}
|
|
|
|
fm_app_mute(fm, 1);
|
|
|
|
if (fm_manage_set_fre(fm, REAL_FREQ(fm->scan_fre))) {
|
|
printf("FM FIND %d %d\n", REAL_FREQ(fm->scan_fre), fm->scan_fre);
|
|
fm->fm_freq_cur = fm->scan_fre;
|
|
fm->fm_total_channel++;
|
|
fm->fm_freq_channel_cur = fm->fm_total_channel;//++;
|
|
save_fm_point(REAL_FREQ(fm->scan_fre));
|
|
sys_timeout_add(fm, fm_timer_handler_down, 1500); //播放一秒
|
|
fm_app_mute(fm, 0);
|
|
} else {
|
|
sys_timeout_add(fm, fm_timer_handler_down, 20);
|
|
}
|
|
fm->scan_fre++;
|
|
}
|
|
|
|
static void fm_timer_handler_up(void *priv)
|
|
{
|
|
struct fm_info *fm = (struct fm_info *)priv;
|
|
|
|
if (fm->scan_flag != SCANE_UP) {
|
|
return;
|
|
}
|
|
|
|
if (fm->scan_fre < VIRTUAL_FREQ(REAL_FREQ_MIN)) {
|
|
fm->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MAX);
|
|
fm_app_mute(fm, 1);
|
|
fm_manage_set_fre(fm, REAL_FREQ(fm->fm_freq_cur));
|
|
fm_app_mute(fm, 0);
|
|
fm->scan_flag = 0;
|
|
return;
|
|
}
|
|
|
|
fm_app_mute(fm, 1);
|
|
|
|
if (fm_manage_set_fre(fm, REAL_FREQ(fm->scan_fre))) {
|
|
fm->fm_freq_cur = fm->scan_fre;
|
|
fm->fm_total_channel++;
|
|
fm->fm_freq_channel_cur = 1;//++;
|
|
save_fm_point(REAL_FREQ(fm->scan_fre));
|
|
sys_timeout_add(fm, fm_timer_handler_up, 1500); //播放一秒
|
|
fm_app_mute(fm, 0);
|
|
} else {
|
|
sys_timeout_add(fm, fm_timer_handler_up, 20); //
|
|
}
|
|
fm->scan_fre--;
|
|
}
|
|
|
|
static void fm_scan_all_up(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag) {
|
|
fm->scan_flag = 0;
|
|
os_time_dly(1);
|
|
fm_app_mute(fm, 0);
|
|
return;
|
|
}
|
|
|
|
clear_all_fm_point();
|
|
fm->fm_freq_cur = 1;
|
|
fm->fm_total_channel = 0;
|
|
fm->fm_freq_channel_cur = 0;
|
|
fm->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MAX);
|
|
fm->scan_flag = SCANE_UP;
|
|
|
|
fm_app_mute(fm, 1);
|
|
sys_timeout_add(fm, fm_timer_handler_up, 20);
|
|
}
|
|
|
|
static void fm_scan_all_down(struct fm_info *fm)
|
|
{
|
|
if (fm->scan_flag) {
|
|
fm->scan_flag = 0;
|
|
os_time_dly(1);
|
|
fm_app_mute(fm, 0);
|
|
return;
|
|
}
|
|
|
|
clear_all_fm_point();
|
|
|
|
fm->fm_freq_cur = 1;//fm->scan_fre;
|
|
fm->fm_total_channel = 0;//++;
|
|
fm->fm_freq_channel_cur = 0;//++;
|
|
fm->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MIN);
|
|
fm->scan_flag = SCANE_DOWN;
|
|
|
|
fm_app_mute(fm, 1);
|
|
sys_timeout_add(fm, fm_timer_handler_down, 20);
|
|
}
|
|
|
|
static void fm_msg_deal(struct fm_info *fm, int msg)
|
|
{
|
|
switch (msg) {
|
|
case FM_DEC_ON:
|
|
fm_dec_onoff(fm, 1);
|
|
break;
|
|
case FM_DEC_OFF:
|
|
fm_dec_onoff(fm, 0);
|
|
break;
|
|
case FM_MUSIC_PP:
|
|
fm_volume_pp(fm);
|
|
break;
|
|
case FM_PREV_FREQ:
|
|
fm_prev_freq(fm);
|
|
break;
|
|
case FM_NEXT_FREQ:
|
|
fm_next_freq(fm);
|
|
break;
|
|
case FM_VOLUME_UP:
|
|
case FM_VOLUME_DOWN:
|
|
fm_volume_set(fm);
|
|
break;
|
|
case FM_PREV_STATION:
|
|
fm_prev_station(fm);
|
|
break;
|
|
case FM_NEXT_STATION:
|
|
fm_next_station(fm);
|
|
break;
|
|
case FM_SCAN_ALL_DOWN:
|
|
fm_scan_all_down(fm);
|
|
break;
|
|
case FM_SCAN_ALL_UP:
|
|
fm_scan_all_up(fm);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int fm_server_msg_post(int msg)
|
|
{
|
|
return os_taskq_post("fm_task", 1, msg);
|
|
}
|
|
/****************************************************/
|
|
|
|
static void fm_task(void *priv)
|
|
{
|
|
struct fm_info *fm = (struct fm_info *)priv;
|
|
int err;
|
|
int msg[32];
|
|
|
|
if (0 != fm_manage_init(fm)) {
|
|
return;
|
|
}
|
|
fm_app_mute(fm, 1);
|
|
fm_read_info_init(fm);
|
|
os_time_dly(1);
|
|
fm_app_mute(fm, 0);
|
|
fm_dec_onoff(fm, 1);
|
|
|
|
while (1) {
|
|
err = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
|
|
if (err != OS_TASKQ || msg[0] != Q_USER) {
|
|
continue;
|
|
}
|
|
|
|
switch (msg[1]) {
|
|
case FM_MSG_EXIT:
|
|
fm_manage_close(fm);
|
|
return;
|
|
default:
|
|
fm_msg_deal(fm, msg[1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int fm_server_init(void)
|
|
{
|
|
if (fm_hdl) {
|
|
return 1;
|
|
}
|
|
|
|
fm_hdl = (struct fm_info *)zalloc(sizeof(struct fm_info));
|
|
if (!fm_hdl) {
|
|
return -1;
|
|
}
|
|
|
|
return thread_fork("fm_task", 13, 512, 64, &fm_hdl->pid, fm_task, fm_hdl);
|
|
}
|
|
|
|
void fm_sever_kill(void)
|
|
{
|
|
if (!fm_hdl) {
|
|
return;
|
|
}
|
|
|
|
do {
|
|
if (OS_Q_FULL != os_taskq_post("fm_task", 1, FM_MSG_EXIT)) {
|
|
break;
|
|
}
|
|
os_time_dly(5);
|
|
} while (1);
|
|
|
|
thread_kill(&fm_hdl->pid, KILL_WAIT);
|
|
free(fm_hdl);
|
|
fm_hdl = NULL;
|
|
}
|
|
|
|
#endif
|