PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

control_ak4558.cpp 9.8KB

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