Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

I2C FM arduino 27984

By: manitou on Jun 18th, 2012  |  syntax: C  |  size: 7.57 KB  |  views: 206  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // i2c fm  parallax part 27984
  2. //   bs2 and spin code available
  3. //      device has 2 I2C address, ending in 0, no addresses required  Ahhhh
  4. //  write configregs 5x2   read status 2x2
  5. //   have to enable tune to set channel
  6.  
  7. #include <Wire.h>
  8. #include <stdint.h>
  9. #include <string.h>
  10.  
  11.  
  12. // SDA pin is Analog4   module pin 1     internal pullup ok
  13. // SCL pin is Analog5   module pin 2    
  14. // grnd to pin 10    v3.3-5v to pin 9
  15.  
  16.  
  17. // device ID
  18. #define SLAVE_ID   0x20 >> 1
  19.  
  20. #define CONFIG_WORDS 5
  21. #define STATUS_WORDS 4
  22. static uint16_t Config0[CONFIG_WORDS] = {0xD001, 0, 0x0400, 0x86D3, 0x4000};
  23. static uint16_t Config[CONFIG_WORDS], Status[STATUS_WORDS];
  24.  
  25. // config 0 register 02
  26. #define DHIZ 15
  27. #define DMUTE 14
  28. #define MONO 13
  29. #define BASS 12
  30. #define CLK32_INPUT_ENB 10
  31. #define SEEK 8
  32. #define CLK_MODE 4
  33. #define SOFT_RESET 1
  34. #define ENABLE 0
  35. #define CLK_MODE_MASK (7 << CLK_MODE)
  36. #define SEEK_MASK (3 << SEEK)
  37. #define SEEK_UP (3 << SEEK)
  38. #define SEEK_DOWN (1 << SEEK)
  39.  
  40. // config 1 register 03
  41. #define CHAN 6
  42. #define TUNE 4
  43. #define BAND 2
  44. #define SPACE 0
  45. #define CHAN_MASK (0xff << CHAN)
  46. #define BAND_MASK ( 3 << BAND)
  47. #define SPACE_MASK ( 3 << SPACE)
  48.  
  49. // config 2 register 04
  50. #define STCEIN 14
  51. #define DE 11
  52. #define I2S_ENABLED 6
  53. #define GPIO3 4
  54. #define GPIO2 2
  55. #define GPIO1 0
  56. #define GPIO3_MASK ( 3 << GPIO3)
  57. #define GPIO2_MASK ( 3 << GPIO2)
  58. #define GPIO1_MASK ( 3 << GPIO1)
  59.  
  60. // config 3 register 05
  61. #define INT_MODE 15
  62. #define SEEKTH 8
  63. #define LNA_PORT_SEL 6
  64. #define LNA_ICSEL_BIT 4
  65. #define VOLUME 0
  66. #define SEEKTH_MASK (0x7f << SEEKTH)
  67. #define LNA_PORT_MASK (2 << LNA_PORT_SEL)
  68. #define LNA_ICSEL_MASK (2 << LNA_ICSEL_BIT)
  69. #define VOLUME_MASK (0x0f << VOLUME)
  70.        
  71. // status regs
  72. // status 0  register 0a
  73. #define STC 14
  74. #define SF 13
  75. #define ST 10
  76. #define READCHAN 0
  77. #define READCHAN_MASK (0xff << READCHAN)
  78.  
  79. // status 1  register 0b
  80. #define RSS 9
  81. #define FM_TRUE 8
  82. #define FM_READY 7
  83. #define RSS_MASK (0x7f << RSS)
  84.  
  85. // assume band 0   760 for other   spacing .1 MHz
  86. #define MAX_PRESETS 10
  87. #define MAX_FREQ 1080
  88. #define MIN_FREQ 870
  89. #define MAX_SST  127
  90. #define MAX_VOL  15
  91.  
  92. uint16_t fm_vol=1, fm_chan = 975;   // channel spacing 100KHz
  93. uint16_t fm_rss, fm_readchan,fm_sst=6,fm_st,fm_true,fm_ready,fm_stc,fm_sf;
  94. uint16_t fm_seek, fm_presets[MAX_PRESETS] = {919,975}, fm_presetnext=2;;
  95. bool seeking;
  96.  
  97.  
  98. void setup()
  99. {
  100.  int channel;
  101.  Wire.begin();                                 // connect I2C
  102.  Serial.begin(9600);
  103.  delay(5);
  104.  Serial.println("FM Demo");
  105.  
  106.  
  107.  fm_reset();
  108.  
  109.  printConfig();
  110.  printPresets();
  111.  delay(100);
  112.  getStatus();
  113.  printStatus();
  114. }
  115.  
  116.  
  117. void loop()
  118. {
  119.         uint8_t c;
  120.         bool update;
  121.  
  122.         Serial.println();
  123.         Serial.println("Freq +/-  Vol >/<  Seek u/d  Preset 0-9  AddPreset A  Reset R  SST x/y");
  124.         Serial.println("  Enter command character:");
  125.         while(!Serial.available()) delay(1);
  126.         c = Serial.read();
  127.         Serial.println((char)c);
  128.         update = false;
  129.         switch(c) {
  130.                 case '+':
  131.                         update = chan_update(fm_chan+1);
  132.                         break;
  133.                 case '-':
  134.                         update = chan_update(fm_chan-1);
  135.                         break;
  136.                 case '>':
  137.                         update = vol_update(fm_vol+1);
  138.                         break;
  139.                 case '<':
  140.                         update = vol_update(fm_vol-1);
  141.                         break;
  142.                 case 'u':
  143.                         Config[0] &= ~SEEK_MASK;
  144.                         Config[0] |= SEEK_UP;
  145.                         seeking = update = true;
  146.                         break;
  147.                 case 'd':
  148.                         Config[0] &= ~SEEK_MASK;
  149.                         Config[0] |= SEEK_DOWN;
  150.                         seeking = update = true;
  151.                         break;
  152.                 case 'x':
  153.                         update = sst_update(fm_sst+1);
  154.                         break;
  155.                 case 'y':
  156.                         update = sst_update(fm_sst-1);
  157.                         break;
  158.                 case '0':
  159.                 case '1':
  160.                 case '2':
  161.                 case '3':
  162.                 case '4':
  163.                 case '5':
  164.                 case '6':
  165.                 case '7':
  166.                 case '8':
  167.                 case '9':
  168.                         chan_update(fm_presets[c - '0']);
  169.                         update = true;
  170.                         break;
  171.                 case 'A':
  172.                         add_preset();
  173.                         break;
  174.                 case 'R':
  175.                         fm_reset();
  176.                         update = true;
  177.                         break;
  178.                 case '?':
  179.                         getStatus();
  180.                         printConfig();
  181.                         printStatus();
  182.                         printPresets();
  183.                         break;
  184.                 default:
  185.                         break;
  186.         }
  187.         if (update || seeking) {
  188.                 setConfig();
  189.                 delay(800);        // let seek complete ... spin on flags?
  190.                 getStatus();
  191.                 if (seeking && fm_stc) {  
  192.                         seek_disable();
  193.                         chan_update(fm_seek + MIN_FREQ);
  194.                         setConfig();
  195.                 }
  196.                 tune_disable();
  197.                 printConfig();
  198.                 printStatus();
  199.         }
  200. }
  201.  
  202. // config updates
  203.  
  204. void fm_reset() {
  205.  seeking = false;
  206.  fm_vol = 1;
  207.  fm_chan = 975;
  208.  fm_sst = 6;
  209.  memcpy(Config,Config0,CONFIG_WORDS * sizeof(uint16_t));
  210.  Config[1] &= ~CHAN_MASK;
  211.  Config[1] |= (fm_chan - MIN_FREQ) << CHAN;
  212.  Config[3] &= ~VOLUME_MASK;
  213.  Config[3] |= fm_vol  << VOLUME;  
  214.  tune_enable();
  215.  setConfig();
  216.  tune_disable();
  217. }
  218.  
  219. void tune_enable() {
  220.         Config[1] |= (1 << TUNE);
  221. }
  222.  
  223. void tune_disable() {
  224.         Config[1] &= ~(1 << TUNE);
  225. }
  226.  
  227. void seek_disable() {
  228.   seeking = false;
  229.   Config[0] &= ~SEEK_MASK;   // turn off seek
  230. }
  231.  
  232. bool vol_update(int val) {
  233.         if (val < 0 || val > MAX_VOL) return false;
  234.         fm_vol = val;
  235.         Config[3] &= ~VOLUME_MASK;
  236.         Config[3] |= fm_vol  << VOLUME;  
  237.         return true;
  238. }
  239.  
  240. bool chan_update(int val) {
  241.         if (val < MIN_FREQ || val > MAX_FREQ) return false;
  242.         fm_chan = val;
  243.         Config[1] &= ~CHAN_MASK;
  244.         Config[1] |= (fm_chan - MIN_FREQ) << CHAN;
  245.         tune_enable();
  246.         return true;
  247. }
  248.  
  249. bool sst_update(int val) {
  250.         if (val < 0 || val > MAX_SST) return false;
  251.         fm_sst = val;
  252.         Config[3] &= ~SEEKTH_MASK;
  253.         Config[3] |= fm_sst  << SEEKTH;  
  254.         return true;
  255. }
  256.  
  257. void add_preset() {
  258.         if (fm_presetnext >= MAX_PRESETS) return;
  259.         fm_presets[fm_presetnext++] = fm_chan;
  260.         printPresets();
  261. }
  262.  
  263. // Set configuration register
  264. void setConfig()
  265. {
  266.  int i;
  267.  
  268.  Wire.beginTransmission(SLAVE_ID);
  269.  for(i=0; i< CONFIG_WORDS;i++) {
  270.         Wire.send((int)Config[i]>>8);
  271.         Wire.send((int)(Config[i] & 0xff));
  272.  }
  273.  Wire.endTransmission();
  274. }
  275.  
  276.  
  277.  
  278. void getStatus()
  279. {
  280.         int i;
  281.         Wire.requestFrom(SLAVE_ID, STATUS_WORDS*2);
  282.         for(i=0; i< STATUS_WORDS;i++) {
  283.                 Status[i] = Wire.receive();
  284.                 Status[i] = Status[i]<<8 | Wire.receive();
  285.         }
  286.         fm_seek = Status[0] & READCHAN_MASK;
  287.         fm_stc =  Status[0] >> STC  & 1;
  288.         fm_sf =  Status[0] >> SF & 1;
  289.         fm_st =  Status[0] >> ST & 1;
  290.         fm_rss = (Status[1] & RSS_MASK) >> RSS;
  291.         fm_true = Status[1] >> FM_TRUE & 1;
  292.         fm_ready = Status[1] >> FM_READY & 1;
  293. }
  294.  
  295. void printConfig() {
  296.         int chan;
  297.         char str[128];
  298.         sprintf(str,"config %04x %04x %04x %04x",Config[0],Config[1],Config[2],Config[3]);
  299.         Serial.println(str);
  300.         chan = ((Config[1] & CHAN_MASK) >> CHAN ) + MIN_FREQ;
  301.         sprintf(str," fm channel %d.%d  volume %d  ss %d  sst %d",
  302.           chan/10,chan%10,fm_vol,fm_rss,fm_sst);
  303.         Serial.println(str);
  304. }
  305.  
  306. void printStatus() {
  307.         int chan;
  308.         char str[128];
  309.         sprintf(str,"status %04x %04x",Status[0],Status[1]);
  310.         Serial.println(str);
  311.         chan = fm_seek + MIN_FREQ;
  312.     if(seeking) Serial.print("seeking ... ");
  313.         sprintf(str," seek channel %d.%d  ss %d stereo %d complete %d fail %d %d %d",
  314.                 chan/10,chan%10,fm_rss,fm_st,fm_stc,fm_sf,fm_true,fm_ready);
  315.         Serial.println(str);
  316. }
  317.  
  318. void printPresets() {
  319.         int chan,i;
  320.         char str[128];
  321.        
  322.         Serial.print("Presets: ");
  323.         for (i=0;i<fm_presetnext;i++) {
  324.           chan = fm_presets[i];
  325.           sprintf(str,"%d.%d ",chan/10,chan%10);
  326.           Serial.print(str);
  327.         }
  328.         Serial.println();
  329. }
  330.  
  331. #define SID (0x22 >> 1)
  332. void i2cdump(uint8_t addr, int n)
  333. {
  334.  int i;
  335.  uint16_t buff[8];
  336.  char str[128];
  337.  
  338.  Serial.print(addr,HEX); Serial.println(" dump");
  339.  Wire.beginTransmission(SID);
  340.  Wire.send(addr);  // start addr
  341.  Wire.endTransmission();
  342.  Wire.requestFrom(SID, n*2);
  343.  for(i=0; i< n;i++) {
  344.         buff[i] = Wire.receive();
  345.         buff[i] = buff[i]<<8 | Wire.receive();
  346.     sprintf(str,"%04x ",buff[i]);
  347.     Serial.print(str);
  348.  }
  349.  Serial.println();
  350. }