Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

256 lines
8.8KB

  1. /*
  2. * HiFi Audio Codec Module support library for Teensy 3.x
  3. *
  4. * Copyright 2015, Michele Perla
  5. *
  6. */
  7. #include "control_ak4558.h"
  8. #include "Wire.h"
  9. void AudioControlAK4558::readInitConfig(void)
  10. {
  11. // puts all default registers values inside an array
  12. // this allows us to modify registers locally using annotation like follows:
  13. //
  14. // registers[AK4558_CTRL_1] &= ~AK4558_DIF2;
  15. // registers[AK4558_CTRL_1] |= AK4558_DIF1 | AK4558_DIF0;
  16. //
  17. // after manipulation, we can write the entire register value on the CODEC
  18. unsigned int n = 0;
  19. Wire.requestFrom(AK4558_I2C_ADDR, 10);
  20. while(Wire.available()) {
  21. #if AK4558_SERIAL_DEBUG > 0
  22. Serial.print("Register ");
  23. Serial.print(n);
  24. Serial.print(" = ");
  25. #endif
  26. registers[n++] = Wire.read();
  27. #if AK4558_SERIAL_DEBUG > 0
  28. Serial.println(registers[n-1]);
  29. #endif
  30. }
  31. }
  32. bool AudioControlAK4558::write(unsigned int reg, unsigned int val)
  33. {
  34. Wire.beginTransmission(AK4558_I2C_ADDR);
  35. Wire.write(reg);
  36. Wire.write(val);
  37. return (Wire.endTransmission()==0);
  38. }
  39. bool AudioControlAK4558::enableIn(void)
  40. {
  41. // ADC setup (datasheet page 74
  42. #if AK4558_SERIAL_DEBUG > 0
  43. Serial.println("AK4558: Enable ADC");
  44. #endif
  45. registers[AK4558_PLL_CTRL] |= AK4558_PLL2;
  46. registers[AK4558_PLL_CTRL] &= ~AK4558_PLL1;
  47. write(AK4558_I2C_ADDR, registers[AK4558_PLL_CTRL]);
  48. #if AK4558_SERIAL_DEBUG > 0
  49. Serial.print("AK4558: PLL_CTRL set to ");
  50. Serial.println(registers[AK4558_PLL_CTRL], BIN);
  51. #endif
  52. delay(10);
  53. // as per table 16, set PLL_CTRL.PLL3-2-1-0 to 0101 for MICK as PLL Reference, 11.2896 MHz
  54. // also, wait 10 ms for PLL lock
  55. // TODO: IS IT NEEDED?
  56. // ignore this, leaving default values - ADC: Set up the de-emphasis filter (Addr = 07H).
  57. registers[AK4558_PWR_MNGT] |= AK4558_PMADR | AK4558_PMADL;
  58. write(AK4558_I2C_ADDR, registers[AK4558_PWR_MNGT]);
  59. #if AK4558_SERIAL_DEBUG > 0
  60. Serial.print("AK4558: PWR_MNGT set to ");
  61. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  62. #endif
  63. delay(300);
  64. // Power up the ADC: PMADL = PMADR bits = “0” → “1”
  65. // Initialization cycle of the ADC is 5200/fs @Normal mode. The SDTO pin outputs “L” during initialization.
  66. #if AK4558_SERIAL_DEBUG > 0
  67. Serial.println("AK4558: Enable ADC - Done");
  68. #endif
  69. return true;
  70. }
  71. bool AudioControlAK4558::enableOut(void)
  72. {
  73. #if AK4558_SERIAL_DEBUG > 0
  74. Serial.println("AK4558: Enable DAC");
  75. #endif
  76. // DAC Output setup (datasheet page 75)
  77. registers[AK4558_MODE_CTRL] |= AK4558_LOPS;
  78. write(AK4558_I2C_ADDR, registers[AK4558_MODE_CTRL]);
  79. #if AK4558_SERIAL_DEBUG > 0
  80. Serial.print("AK4558: MODE_CTRL set to ");
  81. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  82. #endif
  83. // Set the DAC output to power-save mode: LOPS bit “0” → “1”
  84. // ignore this, leaving default values - DAC: Set up the digital filter mode.
  85. // ignore this, leaving default values - Set up the digital output volume (Address = 08H, 09H).
  86. registers[AK4558_PWR_MNGT] |= AK4558_PMDAR | AK4558_PMDAL;
  87. write(AK4558_I2C_ADDR, registers[AK4558_PWR_MNGT]);
  88. #if AK4558_SERIAL_DEBUG > 0
  89. Serial.print("AK4558: PWR_MNGT set to ");
  90. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  91. #endif
  92. delay(300);
  93. // Power up the DAC: PMDAL = PMDAR bits = “0” → “1”
  94. // Outputs of the LOUT and ROUT pins start rising. Rise time is 300ms (max.) when C = 1μF.
  95. registers[AK4558_MODE_CTRL] &= ~AK4558_LOPS;
  96. write(AK4558_I2C_ADDR, registers[AK4558_MODE_CTRL]);
  97. #if AK4558_SERIAL_DEBUG > 0
  98. Serial.print("AK4558: MODE_CTRL set to ");
  99. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  100. #endif
  101. // Release power-save mode of the DAC output: LOPS bit = “1” → “0”
  102. // Set LOPS bit to “0” after the LOUT and ROUT pins output “H”. Sound data will be output from the
  103. // LOUT and ROUT pins after this setting.
  104. #if AK4558_SERIAL_DEBUG > 0
  105. Serial.println("AK4558: Enable DAC - Done");
  106. #endif
  107. return true;
  108. }
  109. bool AudioControlAK4558::enable(void)
  110. {
  111. #if AK4558_SERIAL_DEBUG > 0
  112. Serial.println("AK4558: Enable device");
  113. #endif
  114. // Power Up and Reset
  115. // Clock Setup (datasheet page 72)
  116. pinMode(PIN_PDN, OUTPUT);
  117. digitalWrite(0, LOW);
  118. delay(1);
  119. digitalWrite(0, HIGH);
  120. // After Power Up: PDN pin “L” → “H”
  121. // “L” time of 150ns or more is needed to reset the AK4558.
  122. delay(20);
  123. #if AK4558_SERIAL_DEBUG > 0
  124. Serial.println("AK4558: PDN is HIGH (device reset)");
  125. #endif
  126. // Control register settings become available in 10ms (min.) when LDOE pin = “H”
  127. Wire.begin();
  128. readInitConfig();
  129. // access all registers to store locally their default values
  130. // DIF2-0, DFS1-0 and ACKS bits must be set before MCKI, LRCK and BICK are supplied
  131. // PMPLL = 0 (EXT Slave Mode; disables internal PLL and uses ext. clock) (by DEFAULT)
  132. // ACKS = 0 (Manual Setting Mode; disables automatic clock selection) (by DEFAULT)
  133. // DFS1-0 = 00 (Sampling Speed = Normal Speed Mode) (by DEFAULT)
  134. // TDM1-0 = 00 (Time Division Multiplexing mode OFF) (by DEFAULT)
  135. registers[AK4558_CTRL_1] &= ~AK4558_DIF2;
  136. registers[AK4558_CTRL_1] |= AK4558_DIF1 | AK4558_DIF0;
  137. #if AK4558_SERIAL_DEBUG > 0
  138. Serial.print("AK4558: CTRL_1 set to ");
  139. Serial.println(registers[AK4558_CTRL_1], BIN);
  140. #endif
  141. // DIF2-1-0 = 011 ( 16 bit I2S compatible when BICK = 32fs)
  142. // Set up the audio format (Addr=03H). (in this case: TDM1-0 = 00 (Time Division Multiplexing mode OFF) by default)
  143. registers[AK4558_CTRL_2] &= ~AK4558_MCKS1;
  144. #if AK4558_SERIAL_DEBUG > 0
  145. Serial.print("AK4558: CTRL_2 set to ");
  146. Serial.println(registers[AK4558_CTRL_2], BIN);
  147. #endif
  148. // MCKS1-0 = 00 (Master Clock Input Frequency Select, set 256fs for Normal Speed Mode -> 11.2896 MHz)
  149. registers[AK4558_MODE_CTRL] &= ~AK4558_BCKO0;
  150. // BCKO1-0 = 00 (BICK Output Frequency at Master Mode = 32fs = 1.4112 MHz)
  151. registers[AK4558_MODE_CTRL] |= AK4558_FS1;
  152. // Set up the sampling frequency (FS3-0 bits). The ADC must be powered-up in consideration of PLL
  153. // lock time. (in this case (ref. table 17): Set clock to mode 5 / 44.100 KHz)
  154. #if AK4558_SERIAL_DEBUG > 0
  155. Serial.print("AK4558: MODE_CTRL set to ");
  156. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  157. #endif
  158. Wire.beginTransmission(AK4558_I2C_ADDR);
  159. Wire.write(AK4558_CTRL_1);
  160. Wire.write(registers[AK4558_CTRL_1]);
  161. Wire.write(registers[AK4558_CTRL_2]);
  162. Wire.write(registers[AK4558_MODE_CTRL]);
  163. Wire.endTransmission();
  164. // Write configuration registers in a single write operation (datasheet page 81):
  165. // The AK4558 can perform more than one byte write operation per sequence. After receipt of the third byte
  166. // the AK4558 generates an acknowledge and awaits the next data. The master can transmit more than
  167. // one byte instead of terminating the write cycle after the first data byte is transferred. After receiving each
  168. // data packet the internal address counter is incremented by one, and the next data is automatically taken
  169. // into the next address.
  170. #if AK4558_SERIAL_DEBUG > 0
  171. Serial.println("AK4558: Enable device - Done");
  172. #endif
  173. return true;
  174. }
  175. bool AudioControlAK4558::disableIn(void)
  176. {
  177. // ADC power-down (datasheet page 74
  178. registers[AK4558_PWR_MNGT] &= ~AK4558_PMADR | ~AK4558_PMADL;
  179. write(AK4558_I2C_ADDR, registers[AK4558_PWR_MNGT]);
  180. #if AK4558_SERIAL_DEBUG > 0
  181. Serial.print("AK4558: PWR_MNGT set to ");
  182. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  183. #endif
  184. // Power down ADC: PMADL = PMADR bits = “1” → “0”
  185. #if AK4558_SERIAL_DEBUG > 0
  186. Serial.println("AK4558: Enable ADC - Done");
  187. #endif
  188. return true;
  189. }
  190. bool AudioControlAK4558::disableOut(void)
  191. {
  192. #if AK4558_SERIAL_DEBUG > 0
  193. Serial.println("AK4558: Disable DAC");
  194. #endif
  195. // DAC Output power-down (datasheet page 75)
  196. registers[AK4558_MODE_CTRL] |= AK4558_LOPS;
  197. write(AK4558_I2C_ADDR, registers[AK4558_MODE_CTRL]);
  198. #if AK4558_SERIAL_DEBUG > 0
  199. Serial.print("AK4558: MODE_CTRL set to ");
  200. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  201. #endif
  202. // Set the DAC output to power-save mode: LOPS bit “0” → “1”
  203. registers[AK4558_PWR_MNGT] &= ~AK4558_PMDAR | ~AK4558_PMDAL;
  204. write(AK4558_I2C_ADDR, registers[AK4558_PWR_MNGT]);
  205. #if AK4558_SERIAL_DEBUG > 0
  206. Serial.print("AK4558: PWR_MNGT set to ");
  207. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  208. #endif
  209. delay(300);
  210. // Power down the DAC: PMDAL = PMDAR bits = “1” → “0”
  211. // Outputs of the LOUT and ROUT pins start falling. Rise time is 300ms (max.) when C = 1μF.
  212. registers[AK4558_MODE_CTRL] &= ~AK4558_LOPS;
  213. write(AK4558_I2C_ADDR, registers[AK4558_MODE_CTRL]);
  214. #if AK4558_SERIAL_DEBUG > 0
  215. Serial.print("AK4558: MODE_CTRL set to ");
  216. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  217. #endif
  218. // Release power-save mode of the DAC output: LOPS bit = “1” → “0”
  219. // Set LOPS bit to “0” after outputs of the LOUT and ROUT pins fall to “L”.
  220. #if AK4558_SERIAL_DEBUG > 0
  221. Serial.println("AK4558: Disable DAC - Done");
  222. #endif
  223. return true;
  224. }
  225. bool AudioControlAK4558:volume(float n)
  226. {
  227. // Set DAC output volume
  228. registers[AK4558_LOUT_VOL] &= ~AK4558_LOPS;
  229. write(AK4558_I2C_ADDR, registers[AK4558_LOUT_VOL]);
  230. #if AK4558_SERIAL_DEBUG > 0
  231. Serial.print("AK4558: LOUT_VOL set to ");
  232. Serial.println(registers[AK4558_LOUT_VOL], BIN);
  233. #endif
  234. }