No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

control_ak4558.cpp 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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::initConfig(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. uint8_t 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], BIN);
  29. #endif
  30. }
  31. }
  32. void AudioControlAK4558::readConfig(void)
  33. {
  34. // reads registers values
  35. uint8_t n = 0;
  36. uint8_t c = 0;
  37. Wire.requestFrom(AK4558_I2C_ADDR, 10);
  38. while(Wire.available()) {
  39. Serial.print("Register ");
  40. Serial.print(n++);
  41. Serial.print(" = ");
  42. c = Wire.read();
  43. Serial.println(c, BIN);
  44. }
  45. }
  46. bool AudioControlAK4558::write(unsigned int reg, unsigned int val)
  47. {
  48. Wire.beginTransmission(AK4558_I2C_ADDR);
  49. Wire.write(reg);
  50. Wire.write(val);
  51. return (Wire.endTransmission(true)==0);
  52. }
  53. bool AudioControlAK4558::enableIn(void)
  54. {
  55. // ADC setup (datasheet page 74
  56. #if AK4558_SERIAL_DEBUG > 0
  57. Serial.println("AK4558: Enable ADC");
  58. #endif
  59. // ignore this, leaving default values - ADC: Set up the de-emphasis filter (Addr = 07H).
  60. registers[AK4558_PWR_MNGT] |= AK4558_PMADR | AK4558_PMADL;
  61. write(AK4558_PWR_MNGT, registers[AK4558_PWR_MNGT]);
  62. #if AK4558_SERIAL_DEBUG > 0
  63. Serial.print("AK4558: PWR_MNGT set to ");
  64. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  65. #endif
  66. delay(300);
  67. // Power up the ADC: PMADL = PMADR bits = “0” → “1”
  68. // Initialization cycle of the ADC is 5200/fs @Normal mode. The SDTO pin outputs “L” during initialization.
  69. #if AK4558_SERIAL_DEBUG > 0
  70. Serial.println("AK4558: Enable ADC - Done");
  71. #endif
  72. return true;
  73. }
  74. bool AudioControlAK4558::enableOut(void)
  75. {
  76. #if AK4558_SERIAL_DEBUG > 0
  77. Serial.println("AK4558: Enable DAC");
  78. #endif
  79. // DAC Output setup (datasheet page 75)
  80. registers[AK4558_MODE_CTRL] |= AK4558_LOPS;
  81. write(AK4558_MODE_CTRL, registers[AK4558_MODE_CTRL]);
  82. #if AK4558_SERIAL_DEBUG > 0
  83. Serial.print("AK4558: MODE_CTRL set to ");
  84. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  85. #endif
  86. // Set the DAC output to power-save mode: LOPS bit “0” → “1”
  87. // ignore this, leaving default values - DAC: Set up the digital filter mode.
  88. // ignore this, leaving default values - Set up the digital output volume (Address = 08H, 09H).
  89. registers[AK4558_PWR_MNGT] |= AK4558_PMDAR | AK4558_PMDAL;
  90. write(AK4558_PWR_MNGT, registers[AK4558_PWR_MNGT]);
  91. #if AK4558_SERIAL_DEBUG > 0
  92. Serial.print("AK4558: PWR_MNGT set to ");
  93. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  94. #endif
  95. delay(300);
  96. // Power up the DAC: PMDAL = PMDAR bits = “0” → “1”
  97. // Outputs of the LOUT and ROUT pins start rising. Rise time is 300ms (max.) when C = 1μF.
  98. registers[AK4558_MODE_CTRL] &= ~AK4558_LOPS;
  99. write(AK4558_MODE_CTRL, registers[AK4558_MODE_CTRL]);
  100. #if AK4558_SERIAL_DEBUG > 0
  101. Serial.print("AK4558: MODE_CTRL set to ");
  102. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  103. #endif
  104. // Release power-save mode of the DAC output: LOPS bit = “1” → “0”
  105. // Set LOPS bit to “0” after the LOUT and ROUT pins output “H”. Sound data will be output from the
  106. // LOUT and ROUT pins after this setting.
  107. #if AK4558_SERIAL_DEBUG > 0
  108. Serial.println("AK4558: Enable DAC - Done");
  109. #endif
  110. return true;
  111. }
  112. bool AudioControlAK4558::enable(void)
  113. {
  114. #if AK4558_SERIAL_DEBUG > 0
  115. Serial.println("AK4558: Enable device");
  116. #endif
  117. // Power Up and Reset
  118. // Clock Setup (datasheet page 72)
  119. pinMode(PIN_PDN, OUTPUT);
  120. digitalWrite(0, LOW);
  121. delay(1);
  122. digitalWrite(0, HIGH);
  123. // After Power Up: PDN pin “L” → “H”
  124. // “L” time of 150ns or more is needed to reset the AK4558.
  125. delay(20);
  126. #if AK4558_SERIAL_DEBUG > 0
  127. Serial.println("AK4558: PDN is HIGH (device reset)");
  128. #endif
  129. // Control register settings become available in 10ms (min.) when LDOE pin = “H”
  130. Wire.begin();
  131. initConfig();
  132. // access all registers to store locally their default values
  133. // DIF2-0, DFS1-0 and ACKS bits must be set before MCKI, LRCK and BICK are supplied
  134. // PMPLL = 0 (EXT Slave Mode; disables internal PLL and uses ext. clock) (by DEFAULT)
  135. // ACKS = 0 (Manual Setting Mode; disables automatic clock selection) (by DEFAULT)
  136. // DFS1-0 = 00 (Sampling Speed = Normal Speed Mode) (by DEFAULT)
  137. // TDM1-0 = 00 (Time Division Multiplexing mode OFF) (by DEFAULT)
  138. registers[AK4558_CTRL_1] &= ~AK4558_DIF2;
  139. registers[AK4558_CTRL_1] |= AK4558_DIF1 | AK4558_DIF0;
  140. #if AK4558_SERIAL_DEBUG > 0
  141. Serial.print("AK4558: CTRL_1 set to ");
  142. Serial.println(registers[AK4558_CTRL_1], BIN);
  143. #endif
  144. // DIF2-1-0 = 011 ( 16 bit I2S compatible when BICK = 32fs)
  145. registers[AK4558_CTRL_2] &= ~AK4558_MCKS1;
  146. #if AK4558_SERIAL_DEBUG > 0
  147. Serial.print("AK4558: CTRL_2 set to ");
  148. Serial.println(registers[AK4558_CTRL_2], BIN);
  149. #endif
  150. // MCKS1-0 = 00 (Master Clock Input Frequency Select, set 256fs for Normal Speed Mode -> 11.2896 MHz)
  151. registers[AK4558_MODE_CTRL] &= ~AK4558_BCKO0;
  152. // BCKO1-0 = 00 (BICK Output Frequency at Master Mode = 32fs = 1.4112 MHz)
  153. registers[AK4558_MODE_CTRL] |= AK4558_FS1;
  154. // Set up the sampling frequency (FS3-0 bits). The ADC must be powered-up in consideration of PLL
  155. // lock time. (in this case (ref. table 17): Set clock to mode 5 / 44.100 KHz)
  156. #if AK4558_SERIAL_DEBUG > 0
  157. Serial.print("AK4558: MODE_CTRL set to ");
  158. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  159. #endif
  160. // BCKO1-0 = 00 (BICK Output Frequency at Master Mode = 32fs = 1.4112 MHz)
  161. Wire.beginTransmission(AK4558_I2C_ADDR);
  162. Wire.write(AK4558_CTRL_1);
  163. Wire.write(registers[AK4558_CTRL_1]);
  164. Wire.write(registers[AK4558_CTRL_2]);
  165. Wire.write(registers[AK4558_MODE_CTRL]);
  166. Wire.endTransmission();
  167. // Write configuration registers in a single write operation (datasheet page 81):
  168. // The AK4558 can perform more than one byte write operation per sequence. After receipt of the third byte
  169. // the AK4558 generates an acknowledge and awaits the next data. The master can transmit more than
  170. // one byte instead of terminating the write cycle after the first data byte is transferred. After receiving each
  171. // data packet the internal address counter is incremented by one, and the next data is automatically taken
  172. // into the next address.
  173. #if AK4558_SERIAL_DEBUG > 0
  174. Serial.println("AK4558: Enable device - Done");
  175. #endif
  176. return true;
  177. }
  178. bool AudioControlAK4558::disableIn(void)
  179. {
  180. // ADC power-down (datasheet page 74
  181. registers[AK4558_PWR_MNGT] &= ~AK4558_PMADR | ~AK4558_PMADL;
  182. write(AK4558_PWR_MNGT, registers[AK4558_PWR_MNGT]);
  183. #if AK4558_SERIAL_DEBUG > 0
  184. Serial.print("AK4558: PWR_MNGT set to ");
  185. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  186. #endif
  187. // Power down ADC: PMADL = PMADR bits = “1” → “0”
  188. #if AK4558_SERIAL_DEBUG > 0
  189. Serial.println("AK4558: Enable ADC - Done");
  190. #endif
  191. return true;
  192. }
  193. bool AudioControlAK4558::disableOut(void)
  194. {
  195. #if AK4558_SERIAL_DEBUG > 0
  196. Serial.println("AK4558: Disable DAC");
  197. #endif
  198. // DAC Output power-down (datasheet page 75)
  199. registers[AK4558_MODE_CTRL] |= AK4558_LOPS;
  200. write(AK4558_MODE_CTRL, registers[AK4558_MODE_CTRL]);
  201. #if AK4558_SERIAL_DEBUG > 0
  202. Serial.print("AK4558: MODE_CTRL set to ");
  203. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  204. #endif
  205. // Set the DAC output to power-save mode: LOPS bit “0” → “1”
  206. registers[AK4558_PWR_MNGT] &= ~AK4558_PMDAR | ~AK4558_PMDAL;
  207. write(AK4558_PWR_MNGT, registers[AK4558_PWR_MNGT]);
  208. #if AK4558_SERIAL_DEBUG > 0
  209. Serial.print("AK4558: PWR_MNGT set to ");
  210. Serial.println(registers[AK4558_PWR_MNGT], BIN);
  211. #endif
  212. delay(300);
  213. // Power down the DAC: PMDAL = PMDAR bits = “1” → “0”
  214. // Outputs of the LOUT and ROUT pins start falling. Rise time is 300ms (max.) when C = 1μF.
  215. registers[AK4558_MODE_CTRL] &= ~AK4558_LOPS;
  216. write(AK4558_MODE_CTRL, registers[AK4558_MODE_CTRL]);
  217. #if AK4558_SERIAL_DEBUG > 0
  218. Serial.print("AK4558: MODE_CTRL set to ");
  219. Serial.println(registers[AK4558_MODE_CTRL], BIN);
  220. #endif
  221. // Release power-save mode of the DAC output: LOPS bit = “1” → “0”
  222. // Set LOPS bit to “0” after outputs of the LOUT and ROUT pins fall to “L”.
  223. #if AK4558_SERIAL_DEBUG > 0
  224. Serial.println("AK4558: Disable DAC - Done");
  225. #endif
  226. return true;
  227. }
  228. uint8_t AudioControlAK4558::convertVolume(float vol)
  229. {
  230. // Convert float (range 0.0-1.0) to unsigned char (range 0x00-0xFF)
  231. uint8_t temp = ((uint32_t)vol)>>22;
  232. return temp;
  233. }
  234. bool AudioControlAK4558::volume(float n)
  235. {
  236. // Set DAC output volume
  237. uint8_t vol = convertVolume(n);
  238. registers[AK4558_LOUT_VOL] = vol;
  239. registers[AK4558_ROUT_VOL] = vol;
  240. Wire.beginTransmission(AK4558_I2C_ADDR);
  241. Wire.write(AK4558_LOUT_VOL);
  242. Wire.write(registers[AK4558_LOUT_VOL]);
  243. Wire.write(registers[AK4558_ROUT_VOL]);
  244. #if AK4558_SERIAL_DEBUG > 0
  245. Serial.print("AK4558: LOUT_VOL set to ");
  246. Serial.println(registers[AK4558_LOUT_VOL], BIN);
  247. Serial.print("AK4558: ROUT_VOL set to ");
  248. Serial.println(registers[AK4558_ROUT_VOL], BIN);
  249. #endif
  250. return (Wire.endTransmission(true)==0);
  251. }
  252. bool AudioControlAK4558::volumeLeft(float n)
  253. {
  254. // Set DAC left output volume
  255. uint8_t vol = convertVolume(n);
  256. registers[AK4558_LOUT_VOL] = vol;
  257. bool ret = write(AK4558_LOUT_VOL, registers[AK4558_LOUT_VOL]);
  258. #if AK4558_SERIAL_DEBUG > 0
  259. Serial.print("AK4558: LOUT_VOL set to ");
  260. Serial.println(registers[AK4558_LOUT_VOL], BIN);
  261. #endif
  262. return ret;
  263. }
  264. bool AudioControlAK4558::volumeRight(float n)
  265. {
  266. // Set DAC right output volume
  267. uint8_t vol = convertVolume(n);
  268. registers[AK4558_ROUT_VOL] = vol;
  269. bool ret = write(AK4558_ROUT_VOL, registers[AK4558_ROUT_VOL]);
  270. #if AK4558_SERIAL_DEBUG > 0
  271. Serial.print("AK4558: ROUT_VOL set to ");
  272. Serial.println(registers[AK4558_ROUT_VOL], BIN);
  273. #endif
  274. return ret;
  275. }