Advertisement
Guest User

RDA5807M i2c radio app

a guest
Apr 3rd, 2014
2,965
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.86 KB | None | 0 0
  1. // RDA5807M Radio App for Raspberry Pi - redhawk 04/04/2014
  2. //
  3. // This code is provided to help with programming the RDA chip.
  4. // Some features like auto scan and RDS/RBDS are not included.
  5. //
  6. // When using i2c for the first please read the following article:
  7. // http://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c
  8. //
  9. // For the required wiringPi library please visit:
  10. // https://projects.drogon.net/raspberry-pi/wiringpi/i2c-library/
  11. //
  12. // To compile save source file as rda.c and run:
  13. // gcc -Wall -o rda rda.c -lwiringPi
  14. //
  15.  
  16. #include <wiringPiI2C.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20.  
  21. void write();
  22. void read();
  23.  
  24. typedef unsigned short int  uint16_t;
  25. typedef unsigned char       uint8_t;
  26.  
  27. uint8_t i2c_write_address = 0x10;
  28. uint8_t i2c_read_address = 0x11;
  29. uint16_t i2c_write_handle;
  30. uint16_t i2c_read_handle;
  31. uint8_t out_buffer[12] = {0};
  32. uint8_t read_bug;
  33.  
  34. // CHIP ID //
  35. # define rda_CHIP_ID    0x58
  36.  
  37. // Timing XTAL //
  38. #define rda_32_768kHz   0b0000000000000000
  39. #define rda_12MHz   0b0000000000010000
  40. #define rda_24MHz   0b0000000001010000
  41. #define rda_13MHz   0b0000000000100000
  42. #define rda_26MHz   0b0000000001100000
  43. #define rda_19_2MHz 0b0000000000110000
  44. #define rda_38_4MHz 0b0000000001110000
  45.  
  46. // Tuning Band //
  47. #define rda_87_108MHz   0b0000000000000000
  48. #define rda_76_91MHz    0b0000000000000100
  49. #define rda_76_108MHz   0b0000000000001000
  50. #define rda_65_76MHz    0b0000000000001100
  51.  
  52. // Tuning Steps //
  53. #define rda_100kHz  0b0000000000000000
  54. #define rda_200kHz  0b0000000000000001 // not US band compatible **//
  55. #define rda_50kHz   0b0000000000000010
  56. #define rda_25kHz   0b0000000000000011
  57. // ** 200kHz spacing works but frequencies are always out by 100kHz from US frequency slots.
  58. // It's not possible to tune to a US station with 200kHz spacing you must use 100kHz instead.
  59.  
  60. // De-emphasis //
  61. #define rda_50us    0b0000100000000000
  62. #define rda_75us    0b0000000000000000
  63.  
  64. // REG 0x02
  65. #define rda_DHIZ    0b1000000000000000
  66. #define rda_DMUTE   0b0100000000000000
  67. #define rda_MONO    0b0010000000000000
  68. #define rda_BASS    0b0001000000000000
  69. #define rda_RCLK    0b0000100000000000
  70. #define rda_RCKL_DIM    0b0000010000000000
  71. #define rda_SEEKUP  0b0000001000000000
  72. #define rda_SEEK    0b0000000100000000
  73. #define rda_SKMODE  0b0000000010000000
  74. #define rda_CLK_MODE    0b0000000001110000
  75. #define rda_RDS_EN  0b0000000000001000
  76. #define rda_NEW_METHOD  0b0000000000000100
  77. #define rda_SOFT_RESET  0b0000000000000010
  78. #define rda_ENABLE  0b0000000000000001
  79. // REG 0x03
  80. #define rda_CHAN    0b1111111111000000
  81. #define rda_DIRECT_MODE 0b0000000000100000
  82. #define rda_TUNE    0b0000000000010000
  83. #define rda_BAND    0b0000000000001100
  84. #define rda_SPACE   0b0000000000000011
  85. // REG 0x04
  86. #define rda_DE      0b0000100000000000
  87. #define rda_SOFTMUTE_EN 0b0000001000000000
  88. #define rda_AFCD    0b0000000100000000
  89. // REG 0x05
  90. #define rda_INT_MODE    0b1000000000000000
  91. #define rda_SEEKTH  0b0000111100000000
  92. #define rda_VOLUME  0b0000000000001111
  93. // REG 0x06
  94. #define rda_OPEN_MODE   0b0110000000000000
  95. // REG 0x07
  96. #define rda_BLEND_TH    0b0111110000000000
  97. #define rda_65_50M_MODE 0b0000001000000000
  98. #define rda_SEEK_TH_OLD 0b0000000011111100
  99. #define rda_BLEND_EN    0b0000000000000010
  100. #define rda_FREQ_MODE   0b0000000000000001
  101. // REG 0x0A
  102. #define rda_RDSR    0b1000000000000000
  103. #define rda_STC     0b0100000000000000
  104. #define rda_SF      0b0010000000000000
  105. #define rda_RDSS    0b0001000000000000
  106. #define rda_BLK_E   0b0000100000000000
  107. #define rda_ST      0b0000010000000000
  108. #define rda_READCHAN    0b0000001111111111
  109. // REG 0x0B
  110. #define rda_RSSI    0b1111110000000000
  111. #define rda_FM_TRUE 0b0000001000000000
  112. #define rda_FM_READY    0b0000000100000000
  113. #define rda_ABCD_E  0b0000000000010000
  114. #define rda_BLERA   0b0000000000001100
  115. #define rda_BLERB   0b0000000000000011
  116.  
  117. //    -        -         -            -             -            -    //
  118.  
  119. uint16_t read_chip(uint8_t offset) {
  120.   uint16_t data = wiringPiI2CReadReg16(i2c_read_handle, offset);
  121.   if (read_bug != 0) {
  122.     data = data>>8|((data<<8)&0xffff); // fix high_byte low_byte swap bug
  123.   }
  124.   return data;
  125. }
  126.  
  127. void write_chip(uint8_t size) {
  128.   write (i2c_write_handle, (unsigned int)out_buffer, size);
  129. }
  130.  
  131. void write_setting(char *name, uint16_t value) {
  132.   uint16_t data;
  133.   uint8_t loop;
  134.   if (strcmp(name, "init") == 0) {
  135.     // REG 02
  136.     // normal output, enable mute, stereo, no bass boost, clock = 32.768kHz, RDS enabled, new demod method, power on
  137.     data = rda_DHIZ|(rda_DMUTE&0)|(rda_MONO&0)|(rda_BASS&0)|rda_32_768kHz|rda_RDS_EN|rda_NEW_METHOD|rda_ENABLE;
  138.     out_buffer[0] = data >>8;
  139.     out_buffer[1] = data &0xff;
  140.     // REG 03 - no auto tune, 76-108 band, 0.1 spacing
  141.     data = (rda_TUNE&0)|rda_76_108MHz|rda_100kHz;
  142.     out_buffer[2] = data >>8;
  143.     out_buffer[3] = data &0xff;
  144.     // REG 04 - audio 50us, no soft mute, disble AFC
  145.     data = rda_50us|(rda_SOFTMUTE_EN&0)|rda_AFCD;
  146.     out_buffer[4] = data >>8;
  147.     out_buffer[5] = data &0xff;
  148.     // REG 05 - max volume
  149.     data = rda_INT_MODE|0x0880|rda_VOLUME;
  150.     out_buffer[6] = data >>8;
  151.     out_buffer[7] = data &0xff;
  152.     // REG 06 - reserved
  153.     out_buffer[8] = 0;
  154.     out_buffer[9] = 0;
  155.     // REG 07
  156.     uint16_t blend_threshold = 0b0011110000000000; // mix L+R with falling signal strength
  157.     data = blend_threshold|rda_65_50M_MODE|0x80|0x40|rda_BLEND_EN|(rda_FREQ_MODE&0);
  158.     out_buffer[10] = data >>8;
  159.     out_buffer[11] = data &0xff;
  160.     write_chip(12);
  161.   }
  162.   if (strcmp(name, "off") == 0) {
  163.     data = (read_chip(2)|rda_ENABLE)^rda_ENABLE;
  164.     out_buffer[0] = data >>8;
  165.     out_buffer[1] = data &0xff;
  166.   }
  167.   if (strcmp(name, "dmute") == 0) {
  168.     data = (read_chip(2)|rda_DMUTE);
  169.     if (value == 0) { data = data^rda_DMUTE; }
  170.     out_buffer[0] = data >> 8;
  171.     out_buffer[1] = data & 0xff;
  172.   }
  173.   if (strcmp(name, "mono") == 0) {
  174.     data = (read_chip(2)|rda_MONO);
  175.     if (value == 0) { data = data^rda_MONO; }
  176.     out_buffer[0] = data >> 8;
  177.     out_buffer[1] = data & 0xff;
  178.   }
  179.   if (strcmp(name, "bass") == 0) {
  180.     data = (read_chip(2)|rda_BASS);
  181.     if (value == 0) { data = data^rda_BASS; }
  182.     out_buffer[0] = data >> 8;
  183.     out_buffer[1] = data & 0xff;
  184.   }
  185.   if (strcmp(name, "chan") == 0) {
  186.     data = (read_chip(3)|rda_CHAN)^rda_CHAN;
  187.     out_buffer[2] = (value / 4)|(data >> 8);
  188.     out_buffer[3] = (value * 64)|(data & 0xff);
  189.   }
  190.   if (strcmp(name, "tune") == 0) {
  191.     data = ((out_buffer[2]<<8)|out_buffer[3])|rda_TUNE;
  192.     if (value == 0) { data = data^rda_TUNE; }
  193.     out_buffer[2] = data >> 8;
  194.     out_buffer[3] = data & 0xff;
  195.   }
  196.   if (strcmp(name, "de") == 0) {
  197.     write_setting("read_chip",0);
  198.     data = (read_chip(4)|rda_DE)^rda_DE;
  199.     if (value == 0) { data = data | rda_50us; }
  200.     if (value == 1) { data = data | rda_75us; }
  201.     out_buffer[4] = data >> 8;
  202.     out_buffer[5] = data & 0xff;
  203.   }
  204.   if (strcmp(name, "volume") == 0) {
  205.     write_setting("read_chip",0);
  206.     data = (read_chip(5)|rda_VOLUME)^rda_VOLUME;
  207.     if (value > rda_VOLUME) { value = rda_VOLUME; }
  208.     data = data|value;
  209.     out_buffer[6] = data >> 8;
  210.     out_buffer[7] = data & 0xff;
  211.  }
  212.   if (strcmp(name, "read_chip") == 0) {
  213.     for (loop = 2; loop < 8; loop++) {
  214.       data = read_chip(loop);
  215.       out_buffer[(loop*2)-4] = data >> 8;
  216.       out_buffer[(loop*2)-3] = data & 0xff;
  217.     }
  218.     write_setting("tune",0); // disable tuning
  219.   }
  220. }
  221.  
  222. uint16_t read_setting(char *name) {
  223.   uint16_t data = 0;
  224.   if (strcmp(name, "dmute") == 0) { data = read_chip(2) & rda_DMUTE; }
  225.   if (strcmp(name, "mono") == 0) { data = read_chip(2) & rda_MONO; }
  226.   if (strcmp(name, "bass") == 0) { data = read_chip(2) & rda_BASS; }
  227.   if (strcmp(name, "band") == 0) { data = read_chip(3) & rda_BAND; }
  228.   if (strcmp(name, "space") == 0) { data = read_chip(3) & rda_SPACE; }
  229.   if (strcmp(name, "de") == 0) { data = read_chip(4) & rda_DE; }
  230.   if (strcmp(name, "volume") == 0) { data = read_chip(5) & rda_VOLUME; }
  231.   if (strcmp(name, "st") == 0) { data = read_chip(10) & rda_ST; }
  232.   if (strcmp(name, "rssi") == 0) { data = ((read_chip(11) & rda_RSSI)>>10); }
  233.   return data;
  234. }
  235.  
  236. uint16_t init_chip() {
  237.   uint16_t data;
  238.   uint8_t found = 0;
  239.   uint8_t result;
  240.   i2c_write_handle = wiringPiI2CSetup(i2c_write_address);
  241.   if (i2c_write_handle < 0){
  242.     printf("i2c device not found\n");
  243.     exit(1);
  244.   }
  245.   i2c_read_handle = wiringPiI2CSetup(i2c_read_address);
  246.   if (i2c_read_handle < 0){
  247.     printf("i2c device not found\n");
  248.     exit(1);
  249.   }
  250.   data = read_chip(0);
  251.   if ((data&0xff) == rda_CHIP_ID) {
  252.     found = 1;
  253.     read_bug = 1;
  254.   }
  255.   data = data<<8;
  256.   if (data == rda_CHIP_ID) {
  257.     found = 1;
  258.     read_bug = 0;
  259.   }
  260.   if (found == 0) {
  261.     printf("i2c device not found\n");
  262.     exit(1);
  263.   }
  264.   if ((read_chip(13) == 0x5804) && (read_chip(15) == 0x5804)) { result = 0; } // not set up
  265.                              else { result = 1; } // already used
  266.   return result;
  267. }
  268.  
  269. void set_frequency(double freq_request) {
  270.   uint8_t spacing;
  271.   uint16_t start_freq;
  272.   uint16_t data;
  273.   uint16_t new_freq;
  274.   uint16_t freq;
  275.   if (freq_request < 760) { freq = freq_request * 10; }
  276.                  else { freq = freq_request; }
  277.   data = read_setting("band");
  278.   if (data == rda_87_108MHz) { start_freq = 870; }
  279.   if (data == rda_76_108MHz) { start_freq = 760; }
  280.   if (data == rda_76_91MHz)  { start_freq = 760; }
  281.   if (data == rda_65_76MHz)  { start_freq = 650; }
  282.   data = read_setting("space");
  283.   if (data == rda_200kHz)  { spacing = 0; }
  284.   if (data == rda_100kHz)  { spacing = 1; }
  285.   if (data == rda_50kHz)   { spacing = 2; }
  286.   if (data == rda_25kHz)   { spacing = 4; }
  287.   if (spacing > 0) { new_freq = (freq - start_freq) * spacing; }
  288.               else { new_freq = (freq - start_freq) / 2; }
  289.   write_setting("dmute",1);
  290.   write_setting("chan",new_freq);
  291.   write_setting("tune",1);
  292.   write_chip(4);
  293. }
  294.  
  295. void help(char *prog) {
  296.   printf("\nRaspberry Pi - RDA5807M radio application\n\n");
  297.   printf("Usage: %s freq (MHz) | off | other options\n",prog);
  298.   printf("other options: mute | unmute\n");
  299.   printf("volume [n] | vol [n] (n = 0 - 15)\n");
  300.   printf("bass [on | off] (bass boost)\n");
  301.   printf("50us | 50 | 75us | 75 (de-emphasis)\n");
  302.   printf("stereo | s | mono | m (channel mode)\n\n");
  303.   exit(0);
  304. }
  305.  
  306. int main( int argc, char *argv[]) {
  307.   if (argc < 2) { help(argv[0]); }
  308.   uint16_t data;
  309.   uint8_t state = init_chip();
  310.   data = atoi(argv[1]);
  311.   if (data > 75) {
  312.     if (state == 0) {
  313.       write_setting("init",0);
  314.       system("sleep 0.2"); // delay next command after init
  315.     }
  316.     double freq_request = strtod(argv[1],NULL);
  317.     set_frequency(freq_request);
  318.   } else {
  319.     if (strcmp(argv[1], "off") == 0) {
  320.       write_setting("off",0);
  321.       write_chip(2);
  322.       exit(0);
  323.     }
  324.     if (state == 0) { printf("Radio is off / not tuned\n"); exit(1); }
  325.     if (strcmp(argv[1], "mute") == 0) {
  326.       write_setting("dmute",0);
  327.       write_chip(2);
  328.     }
  329.     if (strcmp(argv[1], "unmute") == 0) {
  330.       write_setting("dmute",1);
  331.       write_chip(2);
  332.     }
  333.     if ((strcmp(argv[1], "volume") == 0)||(strcmp(argv[1], "vol") == 0)) {
  334.       if (argc > 2) {
  335.         data = atoi(argv[2]);
  336.         write_setting("volume",data);
  337.         write_chip(8);
  338.       }
  339.     }
  340.     if (strcmp(argv[1], "bass") == 0) {
  341.       if (argc > 2) {
  342.         if (strcmp(argv[2], "on")  == 0) {
  343.           write_setting("bass",1);
  344.           write_chip(2);
  345.         }
  346.         if (strcmp(argv[2], "off") == 0) {
  347.           write_setting("bass",0);
  348.           write_chip(2);
  349.         }
  350.       }
  351.     }
  352.     if ((strcmp(argv[1], "stereo") == 0)||(strcmp(argv[1], "s") == 0)) {
  353.       write_setting("mono",0);
  354.       write_chip(2);
  355.     }
  356.     if ((strcmp(argv[1], "mono") == 0)||(strcmp(argv[1], "m") == 0)) {
  357.       write_setting("mono",1);
  358.       write_chip(2);
  359.     }
  360.     if ((strcmp(argv[1], "50us") == 0)||(strcmp(argv[1], "50") == 0)) {
  361.       write_setting("de",0);
  362.       write_chip(6);
  363.     }
  364.     if ((strcmp(argv[1], "75us") == 0)||(strcmp(argv[1], "75") == 0)) {
  365.       write_setting("de",1);
  366.       write_chip(6);
  367.     }
  368.   }
  369.   return 0;
  370. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement