Design of FM radio system based on iTop4412 (Part 1)

Publisher:雅意盎然Latest update time:2022-01-29 Source: eefocusKeywords:iTop4412 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Note: The first version of the architecture is: APP+JNI(NDK)+Driver(linux), the advantage is simple development, short cycle, also as my graduation project

   Now updated to the second version, FM service is completely embedded in the Android system and becomes a system service. The architecture is: APP+Frameworks+JNI+HAL+Driver

 

The entire system design is roughly divided into three articles, including:

1. Driver design

2. System API Interface

3. APP Function Implementation

---------------------------------------------------(I) Driver Design-----------------------------------------------------------------

I have previously introduced the method of writing character drivers for iTop4412, so I will not go into detail here about the driver writing process. Here is the link: http://www.cnblogs.com/pngcui/p/4766504.html

 

The FM radio chip here uses the TEA5767HN module and uses I2C for communication, so our first step is to find the chip datasheet and find the device address of the chip, which is 0xC0

At the same time, you need to find the I2C communication protocol in the datasheet

It should be noted here that the standard I2C protocol is not so concise, but it is written in the datasheet, so let's write the code according to it.

Attached is the standard I2C communication protocol:

  Write operation: START+device address+ACK+write register address+ACK+write data+ACK+STOP

  Read operation: START+(device address+write flag)+ACK+write register address+ACK+(device address+read flag)+ACK+read data+STOP

  START signal: When SCL is high, SDA changes from high to low

  STOP signal: When SCL is high, SDA changes from low to high

 

With the I2C communication protocol, we next need to select the pin of the development board to connect the TEA5767HN chip.

Since the camera interface on the board is not occupied, we find the camera interface on the schematic, which is j27

I have selected the CAM_HREF pin and CAM_PCLK pin as the SDA and SCL lines of I2C respectively. Next, we need to find the definition of these two pins in the kernel's gpio configuration file.

    { EXYNOS4212_GPJ0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_D6 by pngcui

    { EXYNOS4212_GPJ0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_D7 by pngcui

    { EXYNOS4212_GPJ0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_PCLK by pngcui

    { EXYNOS4212_GPJ0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_D1 by pngcui

    { EXYNOS4212_GPJ0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_D2 by pngcui

    { EXYNOS4212_GPJ0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_D4 by pngcui

    { EXYNOS4212_GPJ0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_D3 by pngcui

    { EXYNOS4212_GPJ0(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_VSYNC by pngcui


    { EXYNOS4212_GPJ1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //I2C_SCL7 by pngcui

    { EXYNOS4212_GPJ1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM2M_RST by pngcui

    { EXYNOS4212_GPJ1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //CAM_HREF by pngcui

    { EXYNOS4212_GPJ1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE}, //I2C_SDA7 by pngcui

    { EXYNOS4212_GPJ1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //NC-CAM2M_PWDN low=0v high=0.3v bu pngcui


It should be noted here that the comments inside do not correspond to the pins on the board, so it is best to write a test program in advance and then use a multimeter to test whether the pins correspond.


At this point, we can use the gpio_set_value function to control the two I2C lines. Next, we will write the official driver program!!!


1. Configure device information in the platform file


  Reference: http://www.cnblogs.com/pngcui/p/4766504.html


2. Register driver information


 1 struct platform_driver tea5767_driver = {

 2.probe = tea5767_probe,

 3.remove = tea5767_remove,

 4.shutdown = tea5767_shutdown,

 5. suspend = tea5767_suspend,

 6.resume = tea5767_resume,

 7.driver = {

 8.name = DRIVER_NAME,

 9.owner = THIS_MODULE,

10 }

11 };

12 

13 /* init the driver */

14 static int __init tea5767_init(){

15     

16 int err;

17     

18 printk("tea5767 init start...n");

19     

20 err = platform_driver_register(&tea5767_driver);

twenty one     

22 printk("state is %dnn",err);

twenty three     

24 return 0;

25 }

26 

27 /* cleanup the driver */

28 static void __exit tea5767_exit(){

29     

30 int i;

31     

32 printk("tea5767 exit ..and free gpion");

33 gpio_free(SCL);

34 gpio_free(SDA);

35     

36 platform_driver_unregister(&tea5767_driver);

37 }

38 

39 MODULE_LICENSE("Dual BSD/GPL");

40 MODULE_AUTHOR("PNGCUI");

41 

42 module_init(tea5767_init);

43 module_exit(tea5767_exit);


  Note: include/linux/init.h describes the loading order of driver functions, with detailed description link: http://blog.csdn.net/maopig/article/details/7375933


3. When the name configured in the platform file matches the name in the driver successfully, it will automatically enter the probe function of the driver program.


 1 static int tea5767_probe(struct platform_device *pdv){

 2 int ret,i;

 3 printk("tea5767_probe start..n");

 4     

 5 pll = default_pll;

 6     

 7     

 8 for(i=0; i 9         

10 ret = gpio_request(tea5767_gpios[i], "tea5767");

11 if (ret < 0) {

12 printk("%s: request GPIO %d for tea5767 failed, ret = %dn", DEVICE_NAME,i, ret);

13 goto exit;

14 }

15 else{

16 printk("%s: request GPIO %d for tea5767 success, ret = %dn", DEVICE_NAME,i, ret);

17 s3c_gpio_cfgpin(tea5767_gpios[i], S3C_GPIO_OUTPUT);

18 gpio_set_value(tea5767_gpios[i], 0);

19 //gpio_free(tea5767_gpios[i]);

20 }

twenty one         

twenty two }

twenty three     

24 //Enable chip

25 //mute=1&stby=1

26 write_data[0]=0xac;

27 write_data[1]=0x7a;

28 write_data[2]=0xd0;

29 write_data[3]=0x57;

30 write_data[4]=0x00;

31     

32 tea5767_write();

33 tea5767_read();

34     

35 //Initialize the chip

36 //Set to mute=1&freq=87400&stby=0

37 write_data[0]=0xa9;

38 write_data[1]=0x9d;

39 write_data[2]=0xa0;

40 write_data[3]=0x17;

41 write_data[4]=0x00;

42 tea5767_write();

43 tea5767_read();

44     

45 ret = misc_register(&tea5767_dev);

46 if(ret<0)

47 {

48 printk("tea5767:register device failed!n");

49 goto exit;

50 }

51 

52 return 0;

53 

54 exit:

55 misc_deregister(&tea5767_dev);

56 return ret;

57 }


In this function, you can perform some chip initialization operations, enable the chip, etc. Here you need to check the specific registers in the chip datasheet to see what they mean.


Write mode:

Read Mode:

Here I summarize here:


/*

* Read in 5 bytes of data

-----------8---------------4------------------2-----------------1------------|----8----------------4---------------2--------------------1----

*1st byte: MUTE (mute = 1) SM (auto search = 1) PLL13 PLL12 -|- PLL11 PLL10 PLL9 PLL8 

*2nd byte: PLL7 PLL6 PLL5 PLL4 -|— PLL3 PLL2 PLL1 PLL0

*3rd byte: SUD (SearchUp = 1) SSL1 (Search stop) SSL0 (Search stop) HLSI (LO) -|- MS (mono = 1) MR (right channel mute = 1) ML (left channel mute = 1) SWP1 (port 1 is high = 1)

*4th byte: SWP2 (port 2 is high = 1) STBY (standby = 1) BL (US/Europe = 0) XTAL (clock frequency) -|- SMUTE (soft mute) HCC (High Cut) SNC (stereo noise cancellation 1) SI (SWPORT1 ready flag is 1)

*5th byte: PLLREF (clock frequency) DTC (de-emphasis time) - - -|- - - - -

*/


/*

* Read data 5 bytes

-----------8-----------------4------------------2-----------------1----------|----8----------------4---------------2-----------------1------

*1st byte: RF (radio station found = 1) BLF (search end = 1) PLL13 PLL12 -|- PLL11 PLL10 PLL9 PLL8 

*2nd byte: PLL7 PLL6 PLL5 PLL4 -|— PLL3 PLL2 PLL1 PLL0

*3rd byte: STEREO (stereo = 1) IF6 (intermediate frequency count result) IF5 (same as before) IF4 (same as before) -|- IF3 (same as before) IF2 (same as before) IF1 (same as before) IF0 (same as before)

*4th byte: LEV3 (signal ADC) LEV2 (same as before) LEV1 (same as before) LEV0 (same as before) -|- CI3 (chip mark) CI2 (same as before) CI1 (same as before) 0

*5th byte: 0 0 0 0 -|- 0 0 0 0

*/


For more specific instructions, please look up the chip's datasheet.


4. Finally, you can use the ioctl interface to implement specific functions


 1 static int tea5767_ioctl(struct file *files, int cmd, int arg){

 2 int ret;

 3 printk("Hello tea5767 and cmd is %d,arg is %dn",cmd,arg);

 4     

 5 switch(cmd){

 6         

 7 //Turn on mute

 8 case OPENMUTE:

 9 openMute();

10 break;

11         

12 //Turn off mute

13 case CLOSEMUTE:

14 closeMute();

15 break;

16             

17 //Manual search

18 cases Search:

19 search(arg);

20 break;

twenty one             

22 //Automatic search

23 case AutoSearch:

24 return auto_search(arg,1);

25 //break;

26 //Get signal strength

27 case ADC:

28 return getADC();

29         

30 //Get the current channel

31 case FREQ:

32 get_frequency();

33 return Frequency_Read;

34             

35 //Set channel

36 case SETFREQ:

37 return setFreq(arg);

38 //break;

39             

40 //Standby, silent mode

41 case SHUTDOWN:

42 setShutDown();

43 break;

44 

45 default:

46 printk("default--cmd=%d,arg=%dn",cmd,arg);

47 //test(cmd,arg);

48 //break;

49 return -1;

50 }

51     

52 return 0;

53 }


5. Attach the complete drive test program


 1 #include

 2 #include

 3 

 4 

 5 #include

 6 #include

 7 #include

 8 

 9 

10 #define MAXC 10

11 

12 main()

13 {

14 int fd;

15 char state[MAXC],cmd[MAXC];

16 char drv[] = "/dev/tea5767";

17 

18 if((fd = open(drv, O_RDWR|O_NOCTTY|O_NDELAY))<0)

19 printf("open %s failed",drv);   

20 else{

21 while(1){

twenty two             

23 printf("Input cmd state: ");

24 scanf("%s %s",cmd,state);

25 printf("Your Input :cmd = %d,state=%dn",atoi(cmd),atoi(state));

26 if(atoi(state) < 0 || atoi(cmd) < 0)

27 break;

28 ioctl(fd,atoi(cmd),atoi(state));            

29             

30 }

31 }

32 return 0;

33 }


Keywords:iTop4412 Reference address:Design of FM radio system based on iTop4412 (Part 1)

Previous article:Android development process based on Xunwei 4412 development board
Next article:Design of FM radio system based on iTop4412 (Part 2)

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号