Advertisement
manitou

I2C FM maple 27984

Jun 18th, 2012
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.63 KB | None | 0 0
  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 <stdio.h>
  10. #include <string.h>
  11.  
  12.  
  13. // SDA pin is 9   module pin 1     no external pullups OK
  14. // SCL pin is 5   module pin 2    
  15. // grnd to module pin 10    v3.3-5v to module pin 9
  16.  
  17.  
  18. // device ID
  19. #define SLAVE_ID   0x20 >> 1
  20.  
  21. #define CONFIG_WORDS 5
  22. #define STATUS_WORDS 4
  23. static uint16_t Config0[CONFIG_WORDS] = {0xD001, 0, 0x0400, 0x86D3, 0x4000};
  24. static uint16_t Config[CONFIG_WORDS], Status[STATUS_WORDS];
  25.  
  26. // config 0 register 02
  27. #define DHIZ 15
  28. #define DMUTE 14
  29. #define MONO 13
  30. #define BASS 12
  31. #define CLK32_INPUT_ENB 10
  32. #define SEEK 8
  33. #define CLK_MODE 4
  34. #define SOFT_RESET 1
  35. #define ENABLE 0
  36. #define CLK_MODE_MASK (7 << CLK_MODE)
  37. #define SEEK_MASK (3 << SEEK)
  38. #define SEEK_UP (3 << SEEK)
  39. #define SEEK_DOWN (1 << SEEK)
  40.  
  41. // config 1 register 03
  42. #define CHAN 6
  43. #define TUNE 4
  44. #define BAND 2
  45. #define SPACE 0
  46. #define CHAN_MASK (0xff << CHAN)
  47. #define BAND_MASK ( 3 << BAND)
  48. #define SPACE_MASK ( 3 << SPACE)
  49.  
  50. // config 2 register 04
  51. #define STCEIN 14
  52. #define DE 11
  53. #define I2S_ENABLED 6
  54. #define GPIO3 4
  55. #define GPIO2 2
  56. #define GPIO1 0
  57. #define GPIO3_MASK ( 3 << GPIO3)
  58. #define GPIO2_MASK ( 3 << GPIO2)
  59. #define GPIO1_MASK ( 3 << GPIO1)
  60.  
  61. // config 3 register 05
  62. #define INT_MODE 15
  63. #define SEEKTH 8
  64. #define LNA_PORT_SEL 6
  65. #define LNA_ICSEL_BIT 4
  66. #define VOLUME 0
  67. #define SEEKTH_MASK (0x7f << SEEKTH)
  68. #define LNA_PORT_MASK (2 << LNA_PORT_SEL)
  69. #define LNA_ICSEL_MASK (2 << LNA_ICSEL_BIT)
  70. #define VOLUME_MASK (0x0f << VOLUME)
  71.    
  72. // status regs
  73. // status 0  register 0a
  74. #define STC 14
  75. #define SF 13
  76. #define ST 10
  77. #define READCHAN 0
  78. #define READCHAN_MASK (0xff << READCHAN)
  79.  
  80. // status 1  register 0b
  81. #define RSS 9
  82. #define FM_TRUE 8
  83. #define FM_READY 7
  84. #define RSS_MASK (0x7f << RSS)
  85.  
  86. // assume band 0   760 for other   spacing .1 MHz
  87. #define MAX_PRESETS 10
  88. #define MAX_FREQ 1080
  89. #define MIN_FREQ 870
  90. #define MAX_SST  127
  91. #define MAX_VOL  15
  92.  
  93. uint16_t fm_vol=1, fm_chan = 975;   // channel spacing 100KHz
  94. uint16_t fm_rss, fm_readchan,fm_sst=6,fm_st,fm_true,fm_ready,fm_stc,fm_sf;
  95. uint16_t fm_seek, fm_presets[MAX_PRESETS] = {919,975}, fm_presetnext=2;;
  96. bool seeking;
  97.  
  98.  
  99. void setup()
  100. {
  101.  int channel;
  102.  Wire.begin(9,5);                                 // connect I2C
  103.  delay(5);
  104.  SerialUSB.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.     SerialUSB.println();
  123.     SerialUSB.println("Freq +/-  Vol >/<  Seek u/d  Preset 0-9  AddPreset A  Reset R  SST x/y");
  124.     SerialUSB.println("  Enter command character:");
  125.     while(!SerialUSB.available()) delay(1);
  126.     c = SerialUSB.read();
  127.     SerialUSB.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.     SerialUSB.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.     SerialUSB.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.     SerialUSB.println(str);
  311.     chan = fm_seek + MIN_FREQ;
  312.     if(seeking) SerialUSB.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.     SerialUSB.println(str);
  316. }
  317.  
  318. void printPresets() {
  319.     int chan,i;
  320.         char str[128];
  321.        
  322.         SerialUSB.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.           SerialUSB.print(str);
  327.         }
  328.         SerialUSB.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.  SerialUSB.print(addr,HEX); SerialUSB.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.     SerialUSB.print(str);
  348.  }
  349.  SerialUSB.println();
  350. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement