调试平台 平台:Allwinner

安卓版本:android15

内核版本:linux6.6

FM收音机调试-RDA5807M

1 模组数据手册2 调试记录2.1 硬件2.1.1 寄存器功能说明

2.2 软件2.2.1 I2C读写接口2.2.1.1 读函数2.2.1.2 写函数

2.2.2 驱动2.2.2.1 设备树2.2.2.2 驱动源码2.2.2.3 测试应用源码

1 模组数据手册

2 调试记录

2.1 硬件

原理图

第4.5脚为I2C的SCK和SDA。 第6脚为晶振时钟输入脚。需要根据实际的时钟频率输入,配置寄存器02H[6:4]的CLK_MODE。如果没有时钟输入或者时钟配置错误,会出现无法调谐的情况。 第9.10脚为音频输出脚。

2.1.1 寄存器功能说明

REG_03H [15:6]:设置信道值,在执行seek操作成功后才会更新。 REG_02H [8]:【SEEK位】为1开始寻道,当寻道操作完成时,SEEK位被设置为低电平,STC位被设置为高电平。 REG_03H [4]:【调谐TUNE位】当tune置1时调谐操作开始,调谐操作完成后STC位会被拉高,调谐操作完成时,调谐位自动复位为低。 REG_0AH [9:0]: 读取信道值,在成功调谐或查找之后才会更新。 REG_0BH[15:9]:表示当前信号强度0-127。 REG_0BH[14]:STC位,表示信号调谐是否完成。

寄存器位名称功能默认值00H[15:0]Chip IDChip ID0x580402H[15]DHIZ音频高阻态输出:0:静音 1:正常模式0[14]DMUTE静音:0:静音 1:正常0[13]MONO单声道:0:立体声 1:单声道0[12]BASS增强低音:0:禁用 1:启用0[11]RCLK NON-CALIBRATE MODE晶振启用:0:总是启用1:仅FM工作时启用0[10]RCLK DIRECT INPUT MODE晶振直接输入模式0:正常1:直接输入模式0[9]SEEKUP向上搜索0:向下搜索1:向上搜索0[8]SEEK搜索启用0:停止搜索1:启用搜索0[7]SKMODE搜索模式0:到达边界处从另一边界开始搜索1:到达边界处停止搜索0[6:4]CLK_MODE[2:0]晶振频率000:32.768KHz001:12MHz101:24MHz010:12MHz110:26MHz011:19.2MHz111:38.4MHz0[3]RDS_ENRDS/RBDS启用0:不启用1:启用0[2]NEW_METHOD使用新技术提高信号质量可提高约1dB灵敏度0[1]SOFT_RESET软件复位0:正常1:复位0[0]ENABLE上电启用0:不启用1:启用003H[15:6]CHAN[9:0]信道(用于选择频率)BAND = 0:Frequency = Channel Spacing (kHz) x CHAN+ 87.0 MHzBAND = 1 or 2:Frequency = Channel Spacing (kHz) x CHAN + 76.0 MHzBAND = 3:Frequency = Channel Spacing (kHz) x CHAN + 65.0 MH0x00[5]DIRECT MODE直接控制模式,仅在测试模式使用0[4]TUNE调谐0:禁用1:启用0[3:2]BAND[1:0]波段00:87-108MHz(美国/欧洲)01:76-91MHz(日本)10:76-108MHz(全球)11:65-76MHz或50-65MHz(东欧)(根据0x07寄存器的bit9选择 1:65-76MHz 0:50-76MHz)00[1:0]SPACE[1:0]频率的间隔00:100kHz01:200kHz10:50kHz11:25kHz0004H[15]RSVD保留0[14]STCIEN搜索和调谐中断使能0:禁用1:启用(中断是GPIO2的低脉冲)[13]RBDSRBDS/RDS功能0:仅使用RDS1:RBDS启用0[12]RDS_FIFO_EN1=开启RDS先进先出功能0[11]DE去重0:75us1:50us0[10]RDS_FIFO_CLR清除RDS先进先出1:清除1[9]SOFTMUTE_EN软件静音使能0:关闭软件静音1:开启软件静音0[8]AFCDAFC失能0:AFC启用1:AFK禁用0[7]Rsvd被读取时为00[6]I2S_ENABLEI2S使能0:关闭1:打开0[5:4]GPIO3[1:0]GPIO300:高阻01:单声道/立体声指示10:低电平11:高电平00[3:2]GPIO2[1:0]GPIO200:高阻01:中断10:低电平11:高电平00[1:0]GPIO1[1:0]GPIO100:高阻01:保留10:低电平11:高电平0005H[15]INT_MODE中断模式0:每5ms产生中断1:中断持续到读取了0x0C寄存器1[14:13]Seek_mode搜索模式00:默认10:添加RSSI模式00[12]RSVD保留0[11:8]SEEKTH[3:0]SNK阈值1000[7:6]LNA_PORT_SEL[1:0]低噪声放大器输入端口选择00:无输入01:LNAN10:LNAP11:双输入10[5:4]LNA_ICSEL_BIT[1:0]低噪声放大器工作电流00:1.8mA01:2.1mA10:2.5mA11:3.0mA00[3:0]VOLUME[3:0]音量0-15等级0000=min 1111=max当0000时,输出静音,输出阻抗很大101106H[15]RSVD保留0[14:13]OPEN_MODE[1:0]保留寄存器模式11:打开寄存器后写入其他:仅打开寄存器后读取功能00[12]slave_masterI2S主从0:主机1:从机0[11]ws_lrWs与l/r通道的关系0:ws=0 ->r, ws=1 ->l1:ws=0 ->l, ws=1 ->r0[10]sclk_i_edgeSCLK边沿0:正常1:反相0[9]data_signedI2S数据符号0:无符号16bit1:有符号16bit0[8]WS_I_EDGE0:正常1:反相0[7:4]I2S_SW_CNT[4:0]Only validin master mode波特率只有主机模式有用1000: WS_STEP_48 0111: WS_STEP:44.1kbps;0110: WS_STEP:32kbps;0101: WS_STEP:24kbps;0100: WS_STEP:22.05kbps;0011: WS_STEP:16kbps;0010: WS_STEP:12kbps;0001: WS_STEP:11.025kbps;0000: WS_STEP:8kbps;0000[3]SW_O_EDGEWs输出0:禁用1:启用0[2]SCLK_O_EDGESCLK输出0:禁用1:启用0[1]L_DELY左声道延迟0:不延迟1:延迟1T0[0]R_DELY右声道延迟0:不延迟1:延迟1T007H[15]RSVD保留0[14:10]TH_SOFRBLEND[5:0]噪声软混合设置阈值,单位2dB10000[9]65M_50M MODE选择频率段在0x3[3:2]=11时有效0 :50~76 MHz.1: 65~76 MHz1[8]RSVD保留0[7:2]SEEK_TH_OLD旧搜索模式的搜索阈值, 0x05[14:13]=10时有效0[1]SOFTBLEND_ENSoftblend启用0:禁用1:启用1[0]FREQ_MODE频率模式0:传统模式1:直接写出频率(0x08)008H[15:0]freq_direct[15:0]频率07H[0]=1时有效00000AH[15]RDSRRDS就绪0:没有RDS/RBDS组没有准备就绪1:新的RDS/RBDS组准备就绪0[14]STC调谐搜索完成0:未完成1:完成调谐搜索完成的标志位,在调谐或搜索完成时被置10[13]SF搜索失败0:成功1:失败当寻道操作找不到RSSSI值大于SEEKTH[3:0]的信道时,设置寻道失败标志0[12]RDSSRDS同步0:RDS解码器未同步(默认)1:RDS解码器已同步仅在RDS详细模式下可用0[11]BLK_E当RDS启用时0:没有找到Block E1:找到Block E0[10]ST立体声指示0:单声道1:立体声1[9:0]READCHAN[9:0]信道值00BH[15:9]RSSI[6:0]信号强度0-127RSSI是对数0[8]FM TRUE电台指示0:不是电台1:是电台0[7]FM_READY软件搜索0:没有就绪1:就绪[6:5]reserved保留[4]ABCD_E0x0c,0x0d,0x0e,0x0f功能0:ABCD1:E决定0CH、0DH、0EH、0FH的块id是ABCD还是E0[3:2]BLERA[1:0]纠错级别00:0需要更正的错误01:需要纠正的1~2个错误10:需要纠正的3-5个错误11:6+错误或校验字错误,无法纠正。仅在RDS模式下使用[1:0]BLERB[1:0]纠错级别00:0需要更正的错误01:需要纠正的1~2个错误10:需要纠正的3-5个错误11:6+错误或校验字错误,无法纠正。仅在RDS模式下使用0CH[15:0]RDSA[15:0]BLOCK A ( 在RDS模式) 或BLOCK E (0x0B[4]=1)0x58030DH[15:0]RDSC[15:0]BLOCK B ( 在RDS模式) 或BLOCK E (0x0B[4]=1)0x58040EH[15:0]RDSC[15:0]BLOCK C ( 在RDS模式) 或BLOCK E (0x0B[4]=1)|0x58080FH[15:0]RDSC[15:0]BLOCK D ( 在RDS模式) 或BLOCK E (0x0B[4]=1)0x5804

2.2 软件

2.2.1 I2C读写接口

I2C 7位地址Addr:0x10 (0b0010000) RDA5807M的寄存器地址是8bit而其内容是16bit数据。所以I2C的读写接口需要特别注意。

2.2.1.1 读函数

static uint16_t rda5807m_i2c_read(struct i2c_client* client,uint8_t address) 参数: uint8_t address:想要读取的目的寄存器地址(8bit) 返回值: uint16_t:目的寄存器中的值(16bit)

rda5807m_i2c_read中先发送8位的寄存器地址,然后用char databuf[2]接收16bit的数据,databuf[0]接收到寄存器的高8位数据,databuf[1]接收到寄存器的低8位数据。

/**

* @brief i2c读函数

* @param address:uint8_t address

* @return fail:ret < 0

* @author chenmango

*/

static uint16_t rda5807m_i2c_read(struct i2c_client* client,uint8_t address)

{

int ret = -1;

unsigned char databuf[2] = {0};

struct i2c_msg msgs[] = {

{

.addr = client->addr,

.flags = 0,

.len = 1,

.buf = &address,

},

{

.addr = client->addr,

.flags = I2C_M_RD,

.len = 2,

.buf = databuf,

},

};

ret = i2c_transfer(client->adapter, msgs, 2);

if(ret < 0)

LOG_ERR("rda5807m_i2c_read err!\n");

return (databuf[0]<<8 | databuf[1]);

}

2.2.1.2 写函数

static int rda5807m_i2c_write(struct i2c_client* client,uint8_t address,uint16_t data) 参数: uint8_t address:想要写入的目的寄存器地址(8bit) uint16_t data:想要写入的数据(16bit) 返回值: ret: <0->fail

rda5807m_i2c_write中发送3个databuf,databuf[0]为想要写入的寄存器地址,databuf[1]为写入数据的高8位,databuf[2]为写入数据的低8位

/**

* @brief i2c写函数

* @param databuf:databuf[0]=REG_ADDR databuf[1]=H_DATA databuf[2]=L_DATA

* @return fail:ret < 0

* @author chenmango

*/

static int rda5807m_i2c_write(struct i2c_client* client,uint8_t address,uint16_t data)

{

int ret = -1;

uint8_t databuf[3] = {0};

databuf[0] = address;

databuf[1] = data >> 8;

databuf[2] = data & 0x00FF;

struct i2c_msg msgs[] = {

{

.addr = client->addr,

.flags = 0,

.len = 3,

.buf = databuf,

},

};

ret = i2c_transfer(client->adapter, msgs, 1);

if(ret < 0)

LOG_ERR("rda5807m_i2c_write err!\n");

return ret;

}

2.2.2 驱动

2.2.2.1 设备树

设备树配置如下:

RDA5807M@11{

compatible = "rda,rda5807m";

clocks = <&rtc_ccu CLK_RTC_32K_FANOUT>;//时钟源

clock-names = "32k_fanout";

clk_flag = <1>;//使用外部时钟源则配置1 时钟源常供则配置0

rda_clk_rate = <32768>;//时钟频率

reg = <0x11>;//I2C地址

status = "okay";

};

如果晶振时钟常供无需软件配置,则不需要配置clk_flag/clocks/clock-names/rda_clk_rate 属性

2.2.2.2 驱动源码

在probe中根据clk_flag判断是否需要初始化时钟调用rda5807m_of_get_source解析设备树资源rda5807m_hwinit中初始化设备

读取chip_id 兵判断是否等于0x5804调用rda5807m_reset复位芯片调用rda5807m_enable使能芯片调用rda5807m_setmute解除静音调用rda5807m_set_output_idle退出空闲模式调用rda5807m_set_freqspace设置信道间隔100KHz调用rda5807m_set_freqrange设置波段87-108MHz调用rda5807m_set_freq设置频率9740(97.4MHz) init中已经调用misc_deregister注册了rda5807m_dev设备rda5807m_fm_fops注册了rda5807m_ioctl的接口

在rda5807m_ioctl中实现ioctl接口,方便应用层调用调试

#include

#include

#include

#include

#include

#include

#include

#include

/* insmod rda5807m.ko dbg_level=1/2/3 */

static int dbg_level = 0;

module_param_named(dbg_level, dbg_level, int, 0644);

#define LOG_ERR(fmt,...) \

do { \

if (dbg_level > 0) { \

printk(KERN_ERR fmt,##__VA_ARGS__); \

} \

} while (0)

#define LOG_INFO(fmt,...) \

do { \

if (dbg_level > 1) { \

printk(KERN_INFO fmt,##__VA_ARGS__); \

} \

} while (0)

#define LOG_DBG(fmt,...) \

do { \

if (dbg_level > 2) { \

printk(KERN_DEBUG fmt,##__VA_ARGS__); \

} \

} while (0)

/* @brief ic内部寄存器 */

#define REG_00 0x00

#define REG_01 0x01

#define REG_02 0x02

#define REG_03 0x03

#define REG_04 0x04

#define REG_05 0x05

#define REG_06 0x06

#define REG_07 0x07

#define REG_08 0x08

#define REG_09 0x09

#define REG_0A 0x0A

#define REG_0B 0x0B

#define REG_0C 0x0C

#define REG_0D 0x0D

#define REG_0E 0x0E

/* @brief 步长频率 */

#define FREQ_SPACE_100KHz 0

#define FREQ_SPACE_200KHz 1

#define FREQ_SPACE_50KHz 2

#define FREQ_SPACE_25KHz 3

/* @brief 频率段 */

#define FREQ_RANGE_87_108 0

#define FREQ_RANGE_76_91 1

#define FREQ_RANGE_76_108 2

#define FREQ_RANGE_65_76 3

#define FREQ_RANGE_50_76 4

/* @brief 存放频段数组的大小 */

#define RDA5807M_N_STATION 20

/* @brief ioctl */

#define FMRX_IOCTL_SET_FREQ _IOWR('s', 1, int)

#define FMRX_IOCTL_READ_FREQ _IOWR('r', 2, int)

#define FMRX_IOCTL_SEARCH_FREQ_TURNUP _IOWR('c', 3, int)

#define FMRX_IOCTL_SEARCH_ALL_FREQ _IOWR('c', 4, int)

#define FMRX_IOCTL_SET_VOLUME _IOWR('s', 5, int)

#define FMRX_IOCTL_READ_VOLUME _IOWR('r', 6, int)

#define FMRX_IOCTL_SET_MUTE _IOWR('c', 7, int)

#define FMRX_IOCTL_SET_OUTPUT_IDLE _IOWR('c', 8, int)

#define FMRX_IOCTL_READ_SIGNAL_INTENSITY _IOWR('r', 9, int)

#define FMRX_IOCTL_SET_FREQ_RANGE _IOWR('s', 10, int)

#define FMRX_IOCTL_READ_FREQ_RANGE _IOWR('r', 11, int)

#define FMRX_IOCTL_SET_FREQ_SAPCE _IOWR('s', 12, int)

#define FMRX_IOCTL_READ_FREQ_SAPCE _IOWR('r', 13, int)

#define FMRX_IOCTL_READ_ID _IOWR('r', 14, int)

#define FMRX_IOCTL_PRINT_REG _IOWR('c', 15, int)

#define FMRX_IOCTL_ENABLE _IOWR('c', 16, int)

#define FMRX_IOCTL_DISABLE _IOWR('c', 17, int)

#define FMRX_IOCTL_WRITE_REG _IOWR('s', 18, int)

#define DEF_CLK_FREQ 32768

struct rda5807m_data_s {

struct i2c_client *client;

uint32_t clk_flag;

struct clk *rda_clk;

uint32_t rda_clk_rate;

}rda5807m_data_t;

uint16_t RDA5807M_RadioStation_Freq[RDA5807M_N_STATION] = {0}; //查找到的电台

/**

* @brief i2c写函数

* @param databuf:databuf[0]=REG_ADDR databuf[1]=H_DATA databuf[2]=L_DATA

* @return fail:ret < 0

* @author chenmango

*/

static int rda5807m_i2c_write(struct i2c_client* client,uint8_t address,uint16_t data)

{

int ret = -1;

uint8_t databuf[3] = {0};

databuf[0] = address;

databuf[1] = data >> 8;

databuf[2] = data & 0x00FF;

struct i2c_msg msgs[] = {

{

.addr = client->addr,

.flags = 0,

.len = 3,

.buf = databuf,

},

};

ret = i2c_transfer(client->adapter, msgs, 1);

if(ret < 0)

LOG_ERR("rda5807m_i2c_write err!\n");

return ret;

}

/**

* @brief i2c读函数

* @param address:uint8_t address

* @return fail:ret < 0

* @author chenmango

*/

static uint16_t rda5807m_i2c_read(struct i2c_client* client,uint8_t address)

{

int ret = -1;

unsigned char databuf[2] = {0};

struct i2c_msg msgs[] = {

{

.addr = client->addr,

.flags = 0,

.len = 1,

.buf = &address,

},

{

.addr = client->addr,

.flags = I2C_M_RD,

.len = 2,

.buf = databuf,

},

};

ret = i2c_transfer(client->adapter, msgs, 2);

if(ret < 0)

LOG_ERR("rda5807m_i2c_read err!\n");

return (databuf[0]<<8 | databuf[1]);

}

static void __maybe_unused rda5807m_reg_dump(struct rda5807m_data_s *data)

{

uint16_t print_buf[16] = {0};

print_buf[0] = rda5807m_i2c_read(data->client,REG_00);

print_buf[1] = rda5807m_i2c_read(data->client,REG_01);

print_buf[2] = rda5807m_i2c_read(data->client,REG_02);

print_buf[3] = rda5807m_i2c_read(data->client,REG_03);

print_buf[4] = rda5807m_i2c_read(data->client,REG_04);

print_buf[5] = rda5807m_i2c_read(data->client,REG_05);

print_buf[6] = rda5807m_i2c_read(data->client,REG_06);

print_buf[7] = rda5807m_i2c_read(data->client,REG_07);

print_buf[8] = rda5807m_i2c_read(data->client,REG_08);

print_buf[9] = rda5807m_i2c_read(data->client,REG_09);

print_buf[10] = rda5807m_i2c_read(data->client,REG_0A);

print_buf[11] = rda5807m_i2c_read(data->client,REG_0B);

print_buf[12] = rda5807m_i2c_read(data->client,REG_0C);

print_buf[13] = rda5807m_i2c_read(data->client,REG_0D);

print_buf[14] = rda5807m_i2c_read(data->client,REG_0E);

for(int i = 0;i < 15;i++){

LOG_INFO("[REG_%x]:0x%x\n",i,print_buf[i]);

}

}

/**

* @brief 使能 REG_02[1:0]->0b01

*

*/

static void rda5807m_enable(struct rda5807m_data_s *data)

{

uint16_t result = rda5807m_i2c_read(data->client,REG_02);

result &= ~(0x3);

result |= 0x01;

rda5807m_i2c_write(data->client,REG_02,result);

mdelay(50);

}

/**

* @brief 失能 REG_02[0]->0

*

*/

static void rda5807m_disable(struct rda5807m_data_s *data)

{

uint16_t result = rda5807m_i2c_read(data->client,REG_02);

result &= ~(0x1);

rda5807m_i2c_write(data->client,REG_02,result);

mdelay(50);

}

/**

* @brief 设置步长频率 REG_03[1:0]

* @param FREQ_SPACE_100KHz 0

* FREQ_SPACE_200KHz 1

* FREQ_SPACE_50KHz 2

* FREQ_SPACE_25KHz 3

*/

static void rda5807m_set_freqspace(struct rda5807m_data_s *data,uint8_t space)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_03);

if (space == FREQ_SPACE_100KHz)

{ //0x03[1:0]=00

result &= ~(1 << 1);

result &= ~(1 << 0);

}

else if (space == FREQ_SPACE_200KHz)

{ //0x03[1:0]=01

result &= ~(1 << 1);

result |= 1 << 0;

}

else if (space == FREQ_SPACE_50KHz)

{ //0x03[1:0]=10

result |= 1 << 1;

result &= ~(1 << 0);

}

else if (space == FREQ_SPACE_25KHz)

{ //0x03[1:0]=11

result |= 1 << 1;

result |= 1 << 0;

}

rda5807m_i2c_write(data->client,REG_03,result);

}

/**

* @brief 读取步长频率 REG_03[1:0]

* @param FREQ_SPACE_100KHz 0

* FREQ_SPACE_200KHz 1

* FREQ_SPACE_50KHz 2

* FREQ_SPACE_25KHz 3

*

*/

uint8_t rda5807m_read_freqspace(struct rda5807m_data_s *data)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_03);

result &= 0x3;

switch (result) {

case 0x0:

LOG_DBG("[%s]:read freqrange FREQ_SPACE_100KHz\n",__func__);

return (uint8_t)result;

case 0x1:

LOG_DBG("[%s]:read freqrange FREQ_SPACE_200KHz\n",__func__);

return (uint8_t)result;

case 0x2:

LOG_DBG("[%s]:read freqrange FREQ_SPACE_50KHz\n",__func__);

return (uint8_t)result;

case 0x3:

LOG_DBG("[%s]:read freqrange FREQ_SPACE_25KHz\n",__func__);

return (uint8_t)result;

default:

LOG_ERR("[%s]:read freqrange fail\n",__func__);

return 0;

}

}

/**

* @brief 设置频率段 band REG_03[3:2]

* #define FREQ_RANGE_87_108 0

* #define FREQ_RANGE_76_91 1

* #define FREQ_RANGE_76_108 2

* #define FREQ_RANGE_65_76 3

* #define FREQ_RANGE_50_76 4

*/

static void rda5807m_set_freqrange(struct rda5807m_data_s *data,uint8_t range)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_03);

if (range == FREQ_RANGE_87_108)

{ //0x03[3:2]=00 0x07[9]=x

result &= ~(1 << 3);

result &= ~(1 << 2);

rda5807m_i2c_write(data->client,REG_03,result);

}

else if (range == FREQ_RANGE_76_91)

{ //0x03[3:2]=01 0x07[9]=x

result &= ~(1 << 3);

result |= 1 << 2;

rda5807m_i2c_write(data->client,REG_03,result);

}

else if (range == FREQ_RANGE_76_108)

{ //0x03[3:2]=10 0x07[9]=x

result |= 1 << 3;

result &= ~(1 << 2);

rda5807m_i2c_write(data->client,REG_03,result);

}

else if (range == FREQ_RANGE_65_76)

{ //0x03[3:2]=11 0x07[9]=1

result |= 1 << 2;

result |= 1 << 3;

rda5807m_i2c_write(data->client,REG_03,result);

result = rda5807m_i2c_read(data->client,REG_07);

result |= 1 << 9;

rda5807m_i2c_write(data->client,REG_07,result);

}

else if (range == FREQ_RANGE_50_76)

{ //0x03[3:2]=11 0x07[9]=0

result |= 1 << 2;

result |= 1 << 3;

rda5807m_i2c_write(data->client,REG_03,result);

result = rda5807m_i2c_read(data->client,REG_07);

result &= ~(1 << 9);

rda5807m_i2c_write(data->client,REG_07,result);

}

}

/**

* @brief 读取频率段 band REG_03[3:2]

* #define FREQ_RANGE_87_108 0

* #define FREQ_RANGE_76_91 1

* #define FREQ_RANGE_76_108 2

* #define FREQ_RANGE_65_76 3

* #define FREQ_RANGE_50_76 4

* @return 0x0 -> FREQ_RANGE_87_108

* 0x1 -> FREQ_RANGE_76_91

* 0x2 -> FREQ_RANGE_76_108

* 0x3 -> FREQ_RANGE_65_76

* 0x4 -> FREQ_RANGE_50_76

*/

uint8_t rda5807m_read_freqrange(struct rda5807m_data_s *data)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_03);

result = (result & 0xC) >> 2;

printk("result:0x%x\n",result);

switch (result) {

case 0x0:

LOG_DBG("[%s]:read freqrange FREQ_RANGE_87_108\n",__func__);

return (uint8_t)result;

case 0x1:

LOG_DBG("[%s]:read freqrange FREQ_RANGE_76_91\n",__func__);

return (uint8_t)result;

case 0x2:

LOG_DBG("[%s]:read freqrange FREQ_RANGE_76_108\n",__func__);

return (uint8_t)result;

case 0x3:

result = rda5807m_i2c_read(data->client,REG_07);

result = (result & 0x200) >> 9;

if (result){

result = 0x3;

LOG_DBG("[%s]:read freqrange FREQ_RANGE_65_76\n",__func__);

return (uint8_t)result;

} else {

result = 0x4;

LOG_DBG("[%s]:read freqrange FREQ_RANGE_50_76\n",__func__);

return (uint8_t)result;

}

default:

LOG_ERR("[%s]:read freqrange fail\n",__func__);

return 0;

}

}

/**

* @brief 将频率转为信道值

* @param freq:频率(以MHz为单位*100)(如设置108MHz=>传入freq:10800)

* @return 信道值

* @author chenmango

*/

static uint16_t rda5807m_freqtochan(struct rda5807m_data_s *data,uint16_t freq)

{

uint16_t start = 0; //频率开始

uint16_t end = 0; //频率结束

uint16_t space = 0; //频率间隔

uint16_t band_value;

uint16_t space_value;

band_value = (rda5807m_i2c_read(data->client,REG_03) & 0x000C) >> 2; // 0x03的3,2位(波段)

if (band_value == 0 /*0b00*/)

{

start = 8700;

end = 10800;

}

else if (band_value == 1 /*0b01*/)

{

start = 7600;

end = 9100;

}

else if (band_value == 2 /*0b10*/)

{

start = 7600;

end = 10800;

}

else if (band_value == 3 /*0b11*/)

{

if ((rda5807m_i2c_read(data->client,REG_07) >> 9) & 0x01)

{

start = 6500;

end = 7600;

} else {

start = 5000;

end = 7600;

}

} else {

return 0;

}

space_value = rda5807m_i2c_read(data->client,REG_03) & 0x0003;

if (space_value == 0 /*0b00*/)

space = 10;

else if (space_value == 1 /*0b01*/)

space = 20;

else if (space_value == 2 /*0b10*/)

space = 5;

else if (space_value == 3 /*0b11*/)

space = 3;

else

return 0;

if (freq < start)

return 0;

if (freq > end)

return 0;

LOG_INFO("[%s]chan_value:0x%x\n",__func__,(freq - start) / space);

return ((freq - start) / space);

}

/**

* @brief 将信道值转为频率

* @param chan:信道值

* @return 频率(以MHz为单位*100)(如108MHz=>10800)

* @author chenmango

*/

static uint16_t rda5807m_chantofreq(struct rda5807m_data_s *data,uint16_t chan)

{

uint16_t start = 0; //频率开始

uint16_t end = 0; //频率结束

uint16_t space = 0; //频率间隔

uint16_t band_value;

uint16_t space_value;

band_value = (rda5807m_i2c_read(data->client,REG_03) & 0x000C) >> 2; // 0x03的3,2位(波段)

if (band_value == 0 /*0b00*/)

{

start = 8700;

end = 10800;

}

else if (band_value == 1 /*0b01*/)

{

start = 7600;

end = 9100;

}

else if (band_value == 2 /*0b10*/)

{

start = 7600;

end = 10800;

}

else if (band_value == 3 /*0b11*/)

{

if ((rda5807m_i2c_read(data->client,REG_07) >> 9) & 0x01)

{

start = 6500;

end = 7600;

} else {

start = 5000;

end = 7600;

}

} else {

return 0;

}

space_value = rda5807m_i2c_read(data->client,REG_03) & 0x0003;

if (space_value == 0 /*0b00*/)

space = 10;

else if (space_value == 1 /*0b01*/)

space = 20;

else if (space_value == 2 /*0b10*/)

space = 5;

else if (space_value == 3 /*0b11*/)

space = 3;

else

return 0;

space_value = start + chan * space;

if (space_value > end)

return 0;

if (space_value < start)

return 0;

return space_value;

}

/**

* @brief 设置频率值 REG_03[15:6]

* @param freq:频率(以MHz为单位*100)(如108MHz=>10800)

* @return 无

* @author chenmango

*/

static void rda5807m_set_freq(struct rda5807m_data_s *data,uint16_t freq)

{

uint16_t chan;

uint16_t temp_value;

chan = rda5807m_freqtochan(data,freq); //先转化为信道值

temp_value = rda5807m_i2c_read(data->client,REG_03);

temp_value &= 0x003F; //清空信道值

temp_value |= (chan & 0x03FF) << 6; //写入信道值

temp_value |= (1) << 4; //调频启用

rda5807m_i2c_write(data->client, REG_03, temp_value);

rda5807m_i2c_write(data->client, REG_03, temp_value);

int try_count = 0;

uint16_t stc_value = 0;

do{

stc_value = rda5807m_i2c_read(data->client, REG_0A);

stc_value &= (1 << 14);//bit14:STC

if (stc_value == 0x4000){

LOG_INFO("set freq success!\n");

return;

}

LOG_INFO("count:%d set freq wait!\n",try_count);

try_count++;

mdelay(50);

}while(try_count < 20);

LOG_ERR("set freq fail!\n");

}

/**

* @brief 读取当前频率 REG_0A[9:0]

* @param 无

* @return 频率(以MHz为单位*100)(如108MHz=>10800)

* @author chenmango

*/

uint16_t rda5807m_read_freq(struct rda5807m_data_s *data)

{

uint16_t chan = 0;

chan = rda5807m_i2c_read(data->client,REG_0A) & 0x03FF;

return rda5807m_chantofreq(data,chan);

}

/**

* @brief 设置音量 REG_05[3:0]

* @param Val:音量值(0-15)

* @return 无

* @author chenmango

*/

void rda5807m_set_volume(struct rda5807m_data_s *data,uint8_t val)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_05);

result &= 0xFFF0;

result |= (val & 0x0F);

rda5807m_i2c_write(data->client,REG_05,result);

}

/**

* @brief 读取音量 REG_05[3:0]

* @param Val:音量值(0-15)

* @return 无

* @author chenmango

*/

uint8_t rda5807m_read_volume(struct rda5807m_data_s *data)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_05);

result &= 0xF;

return (uint8_t)result;

}

/**

* @brief 设置静音 REG_02[15:14]

* @param bool:1是静音,0是解除静音

* @return 无

* @author chenmango

*/

static void rda5807m_setmute(struct rda5807m_data_s *data,uint8_t bool)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_02);

if (bool)

{

result &= ~(0x1 << 14);

}

else

{

result |= 0x1 << 14;

}

rda5807m_i2c_write(data->client,REG_02,result);

}

/**

* @brief 将输出设为空闲状态(喇叭高阻)

* @param bool:1是空闲,0是解除空闲

* @return 无

* @author chenmango

* @date 2024-07-21 23:39:07

*/

static void rda5807m_set_output_idle(struct rda5807m_data_s *data,uint8_t bool)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_02);

if (bool)

{

result &= ~(1 << 15);

}

else

{

result |= 1 << 15;

}

rda5807m_i2c_write(data->client,REG_02,result);

}

/**

* @brief 获取当前频率的信号强度

* @param 无

* @return 信号强度(0-127)

* @author chenmango

*/

uint8_t rda5807m_read_signal_intensity(struct rda5807m_data_s *data)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_0B);

result >>= 9;

return (uint8_t)result;

}

/**

* @brief 判断当前频率是否为电台

* @param 无

* @return 返回1则是电台,0则不是电台

* @author HZ12138

* @date 2022-07-21 22:22:30

*/

uint8_t rda5807m_radio_instructions(struct rda5807m_data_s *data)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_0B);

result >>= 8;

result &= 1;

return result;

}

/**

* @brief 向上搜索下一个电台(搜索完成后会设置当前频率为搜到的频率)

* @param 无

* @return 无

* @author chenmango

*/

static void rda5807m_search_freq_turnup(struct rda5807m_data_s *data)

{

uint16_t result;

result = rda5807m_i2c_read(data->client,REG_03);

result &= ~(1 << 4); //禁用调谐

rda5807m_i2c_write(data->client,REG_03,result);

result = rda5807m_i2c_read(data->client,REG_02);

result |= 1 << 9; //向上搜索

result |= 1 << 8; //开启搜索

result |= 1 << 7; //到达最高频率停止

rda5807m_i2c_write(data->client,REG_02,result);

LOG_INFO("search wait!\n");

while ((rda5807m_i2c_read(data->client,REG_0A) & 0x4000) == 0) //等待搜索完成

{

mdelay(1);

}

rda5807m_set_freq(data,rda5807m_read_freq(data)); //将搜索到频率设置为播放频率

LOG_INFO("search success!\n");

}

/**

* @brief 搜索所有电台

* @param 无

* @return 搜到的电台数量

* @author chenmango

*/

uint16_t rda5807m_search_all_freq(struct rda5807m_data_s *data)

{

uint16_t i = 0;

uint16_t band_value = 0;

uint16_t start, end;

band_value = (rda5807m_i2c_read(data->client,REG_03) & 0x000C) >> 2; // 0x03的3,2位(波段)

if (band_value == 0 /*0b00*/)

{

start = 8700;

end = 10800;

}

else if (band_value == 1 /*0b01*/)

{

start = 7600;

end = 9100;

}

else if (band_value == 2 /*0b10*/)

{

start = 7600;

end = 10800;

}

else if (band_value == 3 /*0b11*/)

{

if ((rda5807m_i2c_read(data->client,REG_07) >> 9) & 0x01)

{

start = 6500;

end = 7600;

} else {

start = 5000;

end = 7600;

}

} else {

return 0;

}

rda5807m_set_freq(data,start);

mdelay(100);

while (rda5807m_read_freq(data) != end)

{

rda5807m_search_freq_turnup(data);

mdelay(10);

RDA5807M_RadioStation_Freq[i] = rda5807m_read_freq(data);

i++;

}

mdelay(100);

if (!rda5807m_radio_instructions(data))

RDA5807M_RadioStation_Freq[--i] = 0;

LOG_INFO("rda5807m_search total stations:[%d]\n",i);

return i;

}

static uint16_t __maybe_unused rda5807m_get_chipid(struct rda5807m_data_s *data)

{

/* ic chip id 0x5804*/

return rda5807m_i2c_read(data->client,REG_00);

}

static void __maybe_unused rda5807m_reset(struct rda5807m_data_s *data)

{

rda5807m_i2c_write(data->client,REG_02,0x0002);

LOG_INFO("ic reset\n");

mdelay(100);

}

/**

* @reutrn: success: ret = 0 fail: ret < 0

*/

static int rda5807m_hwinit(struct rda5807m_data_s *data)

{

int ret = 0;

uint16_t chip_id;

chip_id = rda5807m_get_chipid(data);

LOG_INFO("chipid:[0x%x]\n",chip_id);

if(chip_id != 0x5804){

ret = -1;

return ret;

}

/* reset ic */

rda5807m_reset(data);

/* enable ic */

rda5807m_enable(data); //REG_02[1:0]->0b01

/* unmute */

rda5807m_setmute(data,0); //REG_02[14]->0b1

/* not idle */

rda5807m_set_output_idle(data, 0); //REG_02[15]->0b1

mdelay(600);

/* set freqspace */

rda5807m_set_freqspace(data,FREQ_SPACE_100KHz);//100KHz

/* set freqrange */

rda5807m_set_freqrange(data,FREQ_RANGE_87_108);//band 87-108MHz

/* set freq */

rda5807m_set_freq(data,9740); //REG_03[15:6]->freq 97.4Mhz

/* reg all dump */

rda5807m_reg_dump(data);

return ret;

}

static long rda5807m_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

uint16_t val = 0;

struct write_s {

uint8_t addr;

uint16_t val;

}write_t;

struct rda5807m_data_s *data = &rda5807m_data_t;

switch (cmd) {

case FMRX_IOCTL_SET_FREQ:

LOG_DBG("%s FMRX_IOCTL_SET_FREQ\n", __func__);

if (copy_from_user(&val, (const void __user *)arg, sizeof(val))) {

return -EFAULT;

}

rda5807m_set_freq(data,val);

break;

case FMRX_IOCTL_READ_FREQ:

LOG_DBG("%s FMRX_IOCTL_READ_FREQ\n", __func__);

val = rda5807m_read_freq(data);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_SEARCH_FREQ_TURNUP:

LOG_DBG("%s FMRX_IOCTL_SEARCH_FREQ_TURNUP\n", __func__);

rda5807m_search_freq_turnup(data);

break;

case FMRX_IOCTL_SEARCH_ALL_FREQ:

LOG_DBG("%s FMRX_IOCTL_SEARCH_ALL_FREQ\n", __func__);

val = rda5807m_search_all_freq(data);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_SET_VOLUME:

LOG_DBG("%s FMRX_IOCTL_SET_VOLUME\n", __func__);

if (copy_from_user(&val, (const void __user *)arg, sizeof(val))) {

return -EFAULT;

}

if(val > 15 || val < 0)

break;

else{

rda5807m_set_volume(data,val);

break;

}

case FMRX_IOCTL_READ_VOLUME:

LOG_DBG("%s FMRX_IOCTL_READ_VOLUME\n", __func__);

val = rda5807m_read_volume(data);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_SET_MUTE:

LOG_DBG("%s FMRX_IOCTL_SET_MUTE\n", __func__);

if (copy_from_user(&val, (const void __user *)arg, sizeof(val))) {

return -EFAULT;

}

rda5807m_setmute(data, val);

break;

case FMRX_IOCTL_SET_OUTPUT_IDLE:

LOG_DBG("%s FMRX_IOCTL_SET_OUTPUT_IDLE\n", __func__);

if (copy_from_user(&val, (const void __user *)arg, sizeof(val))) {

return -EFAULT;

}

rda5807m_set_output_idle(data, val);

break;

case FMRX_IOCTL_READ_SIGNAL_INTENSITY:

LOG_DBG("%s FMRX_IOCTL_READ_SIGNAL_INTENSITY\n", __func__);

val = rda5807m_read_signal_intensity(data);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_SET_FREQ_RANGE:

LOG_DBG("%s FMRX_IOCTL_SET_FREQ_RANGE\n", __func__);

if (copy_from_user(&val, (const void __user *)arg, sizeof(val))) {

return -EFAULT;

}

rda5807m_set_freqrange(data,val);

break;

case FMRX_IOCTL_READ_FREQ_RANGE:

LOG_DBG("%s FMRX_IOCTL_READ_FREQ_RANGE\n", __func__);

val = rda5807m_read_freqrange(data);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_SET_FREQ_SAPCE:

LOG_DBG("%s FMRX_IOCTL_SET_FREQ_SAPCE\n", __func__);

if (copy_from_user(&val, (const void __user *)arg, sizeof(val))) {

return -EFAULT;

}

rda5807m_set_freqspace(data,val);

break;

case FMRX_IOCTL_READ_FREQ_SAPCE:

val = rda5807m_read_freqspace(data);

LOG_DBG("%s FMRX_IOCTL_READ_FREQ_SAPCE\n", __func__);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_READ_ID:

LOG_DBG("%s FMRX_IOCTL_READ_ID\n", __func__);

val = rda5807m_get_chipid(data);

if (copy_to_user((void __user *)arg, &val, sizeof(val))) {

return -EFAULT;

}

break;

case FMRX_IOCTL_PRINT_REG:

LOG_DBG("%s FMRX_IOCTL_PRINT_REG\n", __func__);

rda5807m_reg_dump(data);

break;

case FMRX_IOCTL_ENABLE:

LOG_DBG("%s FMRX_IOCTL_PRINT_REG\n", __func__);

rda5807m_enable(data);

break;

case FMRX_IOCTL_DISABLE:

LOG_DBG("%s FMRX_IOCTL_PRINT_REG\n", __func__);

rda5807m_disable(data);

break;

case FMRX_IOCTL_WRITE_REG:

LOG_DBG("%s FMRX_IOCTL_WRITE_REG\n", __func__);

if (copy_from_user(&write_t, (const void __user *)arg, sizeof(write_t))) {

return -EFAULT;

}

LOG_DBG("[%s][ioctl_write]addr:0x%x val:0x%x\n",__func__,write_t.addr,write_t.val);

rda5807m_i2c_write(data->client,write_t.addr,write_t.val);

break;

default:

rda5807m_reg_dump(data);

break;

}

return 0;

}

static int rda5807m_clk_init(struct rda5807m_data_s *data)

{

int ret = 0;

/*get clock*/

data->rda_clk = devm_clk_get(&data->client->dev,"32k_fanout");

if(data->rda_clk == NULL){

LOG_ERR("get_clk err!\n");

return -1;

}

ret = clk_prepare(data->rda_clk);

if(ret < 0){

LOG_ERR("clk prepare fail!\n");

return -2;

}

ret = clk_set_rate(data->rda_clk, data->rda_clk_rate);

if (ret) {

LOG_ERR("clk set rate fail!\n");

return -3;

}

ret = clk_enable(data->rda_clk);

if(ret < 0){

LOG_ERR("clk enable fail!\n");

return -4;

}

LOG_INFO("clk init success!\n");

return ret;

}

/**

* @brief: 获取dts资源

* @author: chenmango

*/

static void rda5807m_of_get_source(struct rda5807m_data_s *data){

/* 获取时钟标志位 是否需要单独配置时钟 1->需要 0->不需要 */

struct device_node *np = data->client->dev.of_node;

int ret = -1;

ret = of_property_read_u32(np, "clk_flag",&data->clk_flag);

if (ret) {

LOG_INFO("Failed get clk_flag from dts,set default\n");

data->clk_flag = 0;

} else {

LOG_INFO("clk_flag:%d\n",data->clk_flag);

}

if(data->clk_flag) {

/* 获取时钟频率*/

ret = of_property_read_u32(np, "rda_clk_rate",&data->rda_clk_rate);

if(ret){

LOG_INFO("Failed get rda_clk_rate from dts,set default\n");

data->rda_clk_rate = DEF_CLK_FREQ;

} else {

LOG_INFO("rda_clk_rate:%d\n",data->rda_clk_rate);

}

}

}

static const struct file_operations rda5807m_fm_fops = {

.owner = THIS_MODULE,

.unlocked_ioctl = rda5807m_ioctl,

//.compat_ioctl = rda5807m_ioctl,

};

static struct miscdevice rda5807m_fm_misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = "rda5807m_dev",

.fops = &rda5807m_fm_fops,

};

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0))

static int rda5807m_probe(struct i2c_client *client)

#else

static int rda5807m_probe(struct i2c_client *client,

const struct i2c_device_id *id)

#endif

{

int ret = -1;

struct rda5807m_data_s *data = &rda5807m_data_t;

LOG_INFO("rda5807m probe\n");

data->client = client;

i2c_set_clientdata(client, data);

rda5807m_of_get_source(data);

if(data->clk_flag){

ret = rda5807m_clk_init(data);

if (ret < 0){

LOG_ERR("rda5807m clk init fail\n");

}

}

/* rda5807m init */

ret = rda5807m_hwinit(data);

if(ret < 0){

LOG_ERR("ic init fail\n");

goto OUT;

}

return ret;

OUT:

return ret;

}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))

static void rda5807m_remove(struct i2c_client *client)

#else

static int rda5807m_remove(struct i2c_client *client)

#endif

{

//int result;

clk_disable_unprepare(rda5807m_data_t.rda_clk);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))

return;

#else

return result;

#endif

}

static const struct of_device_id rda5807m_of_match[] = {

{.compatible = "rda,rda5807m"},

{},

};

static struct i2c_driver rda5807m_driver = {

.driver = {

.of_match_table = rda5807m_of_match,

.name = "rda5807m",

.owner = THIS_MODULE,

},

.probe = rda5807m_probe,

.remove = rda5807m_remove,

};

static int __init rda5807m_init(void)

{

int ret = -1;

ret = i2c_add_driver(&rda5807m_driver);

if (ret < 0) {

LOG_DBG("add rda5807m i2c driver failed\n");

return -ENODEV;

}

ret = misc_register(&rda5807m_fm_misc);

if (ret < 0) {

LOG_DBG("rda5807m misc driver register failed\n");

return -ENODEV;

}

return 0;

}

static void __exit rda5807m_exit(void)

{

LOG_DBG("remove rda5807m i2c driver.\n");

i2c_del_driver(&rda5807m_driver);

misc_deregister(&rda5807m_fm_misc);

}

MODULE_AUTHOR("de-07");

MODULE_DESCRIPTION("rda5807m Sensor driver");

MODULE_LICENSE("GPL");

MODULE_VERSION("1.1.0");

module_init(rda5807m_init);

module_exit(rda5807m_exit);

2.2.2.3 测试应用源码

#include

#include

#include

#include

#include

#include

#include

/**

* @brief test fm-rx

* driver ic:rda5807m

* @author chenmango

* @version v1.1.0

* @date 2025.01.06

*/

#define FMRX_IOCTL_SET_FREQ _IOWR('s', 1, int)

#define FMRX_IOCTL_READ_FREQ _IOWR('r', 2, int)

#define FMRX_IOCTL_SEARCH_FREQ_TURNUP _IOWR('c', 3, int)

#define FMRX_IOCTL_SEARCH_ALL_FREQ _IOWR('c', 4, int)

#define FMRX_IOCTL_SET_VOLUME _IOWR('s', 5, int)

#define FMRX_IOCTL_READ_VOLUME _IOWR('r', 6, int)

#define FMRX_IOCTL_SET_MUTE _IOWR('c', 7, int)

#define FMRX_IOCTL_SET_OUTPUT_IDLE _IOWR('c', 8, int)

#define FMRX_IOCTL_READ_SIGNAL_INTENSITY _IOWR('r', 9, int)

#define FMRX_IOCTL_SET_FREQ_RANGE _IOWR('s', 10, int)

#define FMRX_IOCTL_READ_FREQ_RANGE _IOWR('r', 11, int)

#define FMRX_IOCTL_SET_FREQ_SAPCE _IOWR('s', 12, int)

#define FMRX_IOCTL_READ_FREQ_SAPCE _IOWR('r', 13, int)

#define FMRX_IOCTL_READ_ID _IOWR('r', 14, int)

#define FMRX_IOCTL_PRINT_REG _IOWR('c', 15, int)

#define FMRX_IOCTL_ENABLE _IOWR('c', 16, int)

#define FMRX_IOCTL_DISABLE _IOWR('c', 17, int)

#define FMRX_IOCTL_WRITE_REG _IOWR('s', 18, int)

struct write_s {

uint8_t addr;

uint16_t val;

}write_t;

void print_list(void)

{

// 展示可执行的ioctl操作列表给用户

printf("Available ioctl commands:\n");

printf("1. FMRX_IOCTL_SET_FREQ\n");

printf("2. FMRX_IOCTL_READ_FREQ\n");

printf("3. FMRX_IOCTL_SEARCH_FREQ_TURNUP\n");

printf("4. FMRX_IOCTL_SEARCH_ALL_FREQ\n");

printf("5. FMRX_IOCTL_SET_VOLUME\n");

printf("6. FMRX_IOCTL_SET_MUTE\n");

printf("7. FMRX_IOCTL_SET_OUTPUT_IDLE\n");

printf("8. FMRX_IOCTL_READ_SIGNAL_INTENSITY\n");

printf("9. FMRX_IOCTL_SET_FREQ_RANGE\n");

printf("10. FMRX_IOCTL_SET_FREQ_SAPCE\n");

printf("11. FMRX_IOCTL_READ_ID\n");

printf("12. FMRX_IOCTL_PRINT_REG\n");

printf("13. FMRX_IOCTL_ENABLE\n");

printf("14. FMRX_IOCTL_DISABLE\n");

printf("15. FMRX_IOCTL_WRITE_REG\n");

printf("16. FMRX_IOCTL_READ_VOLUME\n");

printf("17. FMRX_IOCTL_READ_FREQ_RANGE\n");

printf("18. FMRX_IOCTL_READ_FREQ_SAPCE\n");

printf("98. help\n");

printf("99. quit\n");

}

int main()

{

int fd;

uint16_t val = 0;

char *device_file = "/dev/rda5807m_dev";

char input[100];

int choice;

char ch;

// 打开设备文件

fd = open(device_file, O_RDWR);

if (fd < 0) {

perror("Failed to open device file");

return -1;

}

print_list();

while(1){

printf("Please enter the number corresponding to the ioctl command you want to execute: ");

fgets(input, sizeof(input), stdin);

choice = atoi(input);

val = 0;

switch (choice) {

case 1:

// 测试 FMRX_IOCTL_SET_FREQ

printf("Please enter a value for FMRX_IOCTL_SET_FREQ: \n");

fgets(input, sizeof(input), stdin);

val = (uint16_t)atoi(input);

if (ioctl(fd, FMRX_IOCTL_SET_FREQ, &val) < 0) {

perror("ioctl FMRX_IOCTL_SET_FREQ failed");

}

break;

case 2:

// 测试 FMRX_IOCTL_READ_FREQ

if (ioctl(fd, FMRX_IOCTL_READ_FREQ, &val) < 0) {

perror("ioctl FMRX_IOCTL_READ_FREQ failed");

} else {

printf("Read frequency value: 0x%x\n", val);

}

break;

case 3:

// 测试 FMRX_IOCTL_SEARCH_FREQ_TURNUP

if (ioctl(fd, FMRX_IOCTL_SEARCH_FREQ_TURNUP, NULL) < 0) {

perror("ioctl FMRX_IOCTL_SEARCH_FREQ_TURNUP failed");

}

break;

case 4:

// 测试 FMRX_IOCTL_SEARCH_ALL_FREQ

if (ioctl(fd, FMRX_IOCTL_SEARCH_ALL_FREQ, &val) < 0) {

perror("ioctl FMRX_IOCTL_SEARCH_ALL_FREQ failed");

} else {

printf("Result of FMRX_IOCTL_SEARCH_ALL_FREQ: 0x%x\n", val);

}

break;

case 5:

// 测试 FMRX_IOCTL_SET_VOLUME

printf("Please enter a value for FMRX_IOCTL_SET_VOLUME: \n");

printf("VOLUME:[0-15] enter:");

fgets(input, sizeof(input), stdin);

val = (uint16_t)atoi(input);

if (ioctl(fd, FMRX_IOCTL_SET_VOLUME, &val) < 0) {

perror("ioctl FMRX_IOCTL_SET_VOLUME failed");

}

break;

case 6:

// 测试 FMRX_IOCTL_SET_MUTE

printf("Please enter a value for FMRX_IOCTL_SET_MUTE: \n");

printf("[mute] enter 1\n");

printf("[cancel mute] enter 0\n");

fgets(input, sizeof(input), stdin);

val = (uint16_t)atoi(input);

if (ioctl(fd, FMRX_IOCTL_SET_MUTE, &val) < 0) {

perror("ioctl FMRX_IOCTL_SET_MUTE failed");

}

break;

case 7:

// 测试 FMRX_IOCTL_SET_OUTPUT_IDLE

printf("Please enter a value for FMRX_IOCTL_SET_OUTPUT_IDLE: \n");

fgets(input, sizeof(input), stdin);

val = (uint16_t)atoi(input);

if (ioctl(fd, FMRX_IOCTL_SET_OUTPUT_IDLE, &val) < 0) {

perror("ioctl FMRX_IOCTL_SET_OUTPUT_IDLE failed");

}

break;

case 8:

// 测试 FMRX_IOCTL_READ_SIGNAL_INTENSITY

if (ioctl(fd, FMRX_IOCTL_READ_SIGNAL_INTENSITY, &val) < 0) {

perror("ioctl FMRX_IOCTL_READ_SIGNAL_INTENSITY failed");

} else {

printf("Signal intensity value: 0x%x\n", val);

}

break;

case 9:

// 测试 FMRX_IOCTL_SET_FREQ_RANGE

printf("Please enter a value for FMRX_IOCTL_SET_FREQ_RANGE: \n");

printf("[FREQ_RANGE_87_108] enter 0\n");

printf("[FREQ_RANGE_76_91 ] enter 1\n");

printf("[FREQ_RANGE_76_108] enter 2\n");

printf("[FREQ_RANGE_65_76 ] enter 3\n");

printf("[FREQ_RANGE_50_76 ] enter 4\n");

fgets(input, sizeof(input), stdin);

val = (uint16_t)atoi(input);

if (ioctl(fd, FMRX_IOCTL_SET_FREQ_RANGE, &val) < 0) {

perror("ioctl FMRX_IOCTL_SET_FREQ_RANGE failed");

}

break;

case 10:

// 测试 FMRX_IOCTL_SET_FREQ_SAPCE

printf("Please enter a value for FMRX_IOCTL_SET_FREQ_SAPCE: \n");

printf("[FREQ_SPACE_100KHz] enter 0\n");

printf("[FREQ_SPACE_200KHz] enter 1\n");

printf("[FREQ_SPACE_50KHz ] enter 2\n");

printf("[FREQ_SPACE_25KHz ] enter 3\n");

fgets(input, sizeof(input), stdin);

val = (uint16_t)atoi(input);

if (ioctl(fd, FMRX_IOCTL_SET_FREQ_SAPCE, &val) < 0) {

perror("ioctl FMRX_IOCTL_SET_FREQ_SAPCE failed");

}

break;

case 11:

// 测试 FMRX_IOCTL_READ_ID

if (ioctl(fd, FMRX_IOCTL_READ_ID, &val) < 0) {

perror("ioctl FMRX_IOCTL_READ_ID failed");

} else {

printf("Chip ID value: 0x%x\n", val);

}

break;

case 12:

// 测试 FMRX_IOCTL_PRINT_REG

if (ioctl(fd, FMRX_IOCTL_PRINT_REG, NULL) < 0) {

perror("ioctl FMRX_IOCTL_PRINT_REG failed");

}

break;

case 13:

// 测试 FMRX_IOCTL_ENABLE

if (ioctl(fd, FMRX_IOCTL_ENABLE, NULL) < 0) {

perror("ioctl FMRX_IOCTL_ENABLE failed");

}

break;

case 14:

// 测试 FMRX_IOCTL_DISABLE

if (ioctl(fd, FMRX_IOCTL_DISABLE, NULL) < 0) {

perror("ioctl FMRX_IOCTL_DISABLE failed");

}

break;

case 15:

// 测试 FMRX_IOCTL_WRITE_REG

printf("Please enter [addr]: \n");

scanf("%x",&write_t.addr);

while ((ch = getchar())!= '\n');

printf("Please enter [val]: \n");

scanf("%x",&write_t.val);

while ((ch = getchar())!= '\n');

if (ioctl(fd, FMRX_IOCTL_WRITE_REG, &write_t) < 0) {

perror("ioctl FMRX_IOCTL_WRITE_REG failed");

}

break;

case 16:

// 测试 FMRX_IOCTL_READ_VOLUME

if (ioctl(fd, FMRX_IOCTL_READ_VOLUME, &val) < 0) {

perror("ioctl FMRX_IOCTL_READ_VOLUME failed");

} else {

printf("Read volume value: 0x%x\n", val);

}

break;

case 17:

// 测试 FMRX_IOCTL_READ_FREQ_RANGE

if (ioctl(fd, FMRX_IOCTL_READ_FREQ_RANGE, &val) < 0) {

perror("ioctl FMRX_IOCTL_READ_FREQ_RANGE failed");

} else {

printf("Read freq range value: 0x%x\n", val);

}

break;

case 18:

// 测试 FMRX_IOCTL_READ_FREQ_SAPCE

if (ioctl(fd, FMRX_IOCTL_READ_FREQ_SAPCE, &val) < 0) {

perror("ioctl FMRX_IOCTL_READ_FREQ_SAPCE failed");

} else {

printf("Read freq sapce value: 0x%x\n", val);

}

break;

case 98:

// help

print_list();

break;

case 99:

break;

default:

printf("Invalid choice. Please enter a valid number from the list.\n");

break;

}

}

// 关闭设备文件

close(fd);

return 0;

}

Copyright © 2088 世界杯乒乓球赛_2014世界杯十佳球 - mz286.com All Rights Reserved.
友情链接