libpynq  (release 5EID0-2023 version 0.3.0 of 2024-04-25 09:42 )
audio.c
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (c) 2016, Xilinx, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  *****************************************************************************/
32 
33 /******************************************************************************
34  * @file audio_adau1761.c
35  *
36  * Functions to control audio controller.
37  *
38  * <pre>
39  * MODIFICATION HISTORY:
40  *
41  * Ver Who Date Changes
42  * ----- ------------ -------- -----------------------------------------------
43  * 1.00 Yun Rock Qu 12/04/17 Support for audio codec ADAU1761
44  * 1.01 Yun Rock Qu 01/02/18 Enable microphone for CTIA and OMTP standards
45  *
46  * </pre>
47  *
48  *****************************************************************************/
49 #include "audio.h"
50 #include <libpynq.h>
51 #include <stdint.h>
52 
53 #include "i2cps.h"
54 #include "uio.h"
55 #include <fcntl.h>
56 #include <linux/i2c-dev.h>
57 #include <math.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <sys/ioctl.h>
62 #include <sys/mman.h>
63 #include <sys/stat.h>
64 #include <time.h>
65 #include <unistd.h>
66 
67 #define SAMPLE_RATE 48000
68 
69 #undef LOG_DOMAIN
70 #define LOG_DOMAIN "audio"
71 
72 void audio_init(void) {
75 }
76 
77 void audio_select_input(int input) {
78  if (input == MIC) {
79  select_mic();
80  } else if (input == LINE_IN) {
82  } else {
83  pynq_error("audio_select_input: invalid input %d, must be LINE_IN or MIC\n",
84  input);
85  }
86 }
87 
88 // Original ADAU1761 code
89 
90 void write_audio_reg(unsigned char u8RegAddr, unsigned char u8Data,
91  int iic_fd) {
92  unsigned char u8TxData[3];
93  u8TxData[0] = 0x40;
94  u8TxData[1] = u8RegAddr;
95  u8TxData[2] = u8Data;
96  if (writeI2C_asFile(iic_fd, u8TxData, 3) < 0) {
97  pynq_error("write_audio_reg: unable to write audio register, ensure sudo "
98  "chmod 666 /dev/i2c-1 has been executed. \n");
99  }
100 }
101 uint8_t read_audio_reg(unsigned char u8RegAddr, int iic_fd) {
102  unsigned char u8TxData[3];
103  u8TxData[0] = 0x40;
104  u8TxData[1] = u8RegAddr;
105  if (writeI2C_asFile(iic_fd, u8TxData, 2) < 0) {
106  pynq_error("write_audio_reg: unable to write audio register, ensure sudo "
107  "chmod 666 /dev/i2c-1 has been executed. \n");
108  }
109  uint8_t c;
110  if (readI2C_asFile(iic_fd, &c, 1) < 0) {
111  pynq_error("write_audio_reg: unable to write audio register, ensure sudo "
112  "chmod 666 /dev/i2c-1 has been executed. \n");
113  }
114  return c;
115 
116 }
117 
118 void config_audio_pll(void) {
119  int iic_index = 1;
120  unsigned char u8TxData[8], u8RxData[6];
121  int iic_fd;
122  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
123  if (iic_fd < 0) {
124  pynq_error("config_audio_pll: unable to set I2C %d\n", iic_index);
125  }
126 
127  //write_audio_reg(0xEB, 0x00, iic_fd);
128  //write_audio_reg(0xF6, 0x00, iic_fd);
129 
130  // Disable Core Clock
131  // 0x0E
132  write_audio_reg(R0_CLOCK_CONTROL, 0x0E, iic_fd);
133 
134  /* MCLK = 10 MHz
135  * R = 0100 = 4, N = 0x064C = 1612, M = 0x0C35 = 3125
136  * PLL required output = 1024x44.1 KHz = 45.1584 MHz
137  * PLLout/MCLK = 45.1584 MHz/10 MHz = 4.51584 MHz
138  * = R + (N/M)
139  * = 4 + (1612/3125)
140  * Fs = PLL/1024 = 44.1 KHz
141  */
142 
143  // Register write address [15:8]
144  u8TxData[0] = 0x40;
145  // Register write address [7:0]
146  u8TxData[1] = 0x02;
147  // byte 6 - M[15:8]
148  u8TxData[2] = 0x02;
149  // byte 5 - M[7:0]
150  u8TxData[3] = 0x71;
151  // byte 4 - N[15:8]
152  u8TxData[4] = 0x02;
153  // byte 3 - N[7:0]
154  u8TxData[5] = 0x3c;
155  // byte 2 - bits 6:3 = R[3:0], 2:1 = X[1:0], 0 = PLL operation mode
156  u8TxData[6] = 0x21;
157  // byte 1 - 1 = PLL Lock, 0 = Core clock enable
158  u8TxData[7] = 0x03;
159  // Write bytes to PLL control register R1 at 0x4002
160  if (writeI2C_asFile(iic_fd, u8TxData, 8) < 0) {
161  pynq_error("config_audio_pll: unable to write audio register, ensure sudo "
162  "chmod 666 /dev/i2c-1 has been executed. \n");
163  }
164 
165  /* Clock control register: bit 3 CLKSRC = PLL Clock input
166  * bit 2:1 INFREQ = 1024 x fs
167  * bit 0 COREN = Core Clock enabled
168  */
169 // 0x0f
170  // Enable the core clock.
171  write_audio_reg(R0_CLOCK_CONTROL, 0x0F, iic_fd);
172  uint8_t c = read_audio_reg(R0_CLOCK_CONTROL, iic_fd);
173  printf("R0 reg: %02X\r\n", c);
174 
175  // Poll PLL Lock bit
176  u8TxData[0] = 0x40;
177  u8TxData[1] = 0x02;
178  do {
179  if (writeI2C_asFile(iic_fd, u8TxData, 2) < 0) {
180  pynq_error("writeI2C_asFile: unable to write audio register, ensure sudo "
181  "chmod 666 /dev/i2c-1 has been executed. \n");
182  }
183  if (readI2C_asFile(iic_fd, u8RxData, 6) < 0) {
184  pynq_error("readI2C_asFile: unable to write audio register, ensure sudo "
185  "chmod 666 /dev/i2c-1 has been executed. \n");
186  }
187  printf("%02X %02X %02X %02X %02X %02X\r\n", u8RxData[0], u8RxData[1],u8RxData[2],u8RxData[3],u8RxData[4],u8RxData[5]);
188  } while ((u8RxData[5] & 0x02) == 0);
189 
190 
191 // write_audio_reg(0x17, 0x06, iic_fd);
192 // c = read_audio_reg(0x17, iic_fd);
193 // printf("R0 reg: %02X\r\n", c);
194 // write_audio_reg(0xF8, 0x06, iic_fd);
195 // write_audio_reg(0xF6, 0x00, iic_fd);
196 // write_audio_reg(0xEB, 0x00, iic_fd);
197 
198  if (unsetI2C(iic_fd) < 0) {
199  pynq_error("config_audio_pll: unable to set I2C %d\n", iic_fd);
200  }
201 }
202 
203 /******************************************************************************
204  * Function to configure the audio codec.
205  * @param iic_index is the i2c index in /dev list.
206  * @return none.
207  *****************************************************************************/
208 void config_audio_codec(void) {
209  int iic_index = 1;
210  int iic_fd;
211  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
212  if (iic_fd < 0) {
213  pynq_error("config_audio_codec: unable to set I2C %d\n", iic_index);
214  }
215 
216  /*
217  * Input path control registers are configured
218  * in select_mic and select_line_in
219  */
220 
221  // Mute Mixer1 and Mixer2 here, enable when MIC and Line In used
224  // Set LDVOL and RDVOL to 21 dB and Enable left and right differential
227  // Enable MIC bias
229  // Enable ALC control and noise gate
230  write_audio_reg(R14_ALC_CONTROL_3, 0x20, iic_fd);
231  // Put CODEC in Master mode
233  // Enable ADC on both channels, normal polarity and ADC high-pass filter
234  write_audio_reg(R19_ADC_CONTROL, 0x33, iic_fd);
235  // Mute play back Mixer3 and Mixer4 and enable when output is required
238  // Mute left input to mixer3 (R23) and right input to mixer4 (R25)
241  // Mute left and right channels output; enable them when output is needed
244  // Enable play back right and left channels
246  // Enable DAC for both channels
247  write_audio_reg(R36_DAC_CONTROL_0, 0x03, iic_fd);
248  // Set SDATA_In to DAC
250  // Set SDATA_Out to ADC
252  // Enable DSP and DSP Run
253  write_audio_reg(R61_DSP_ENABLE, 0x01, iic_fd);
254  write_audio_reg(R62_DSP_RUN, 0x01, iic_fd);
255  /*
256  * Enable Digital Clock Generator 0 and 1.
257  * Generator 0 generates sample rates for the ADCs, DACs, and DSP.
258  * Generator 1 generates BCLK and LRCLK for the serial port.
259  */
260  write_audio_reg(R65_CLOCK_ENABLE_0, 0x7F, iic_fd);
261  write_audio_reg(R66_CLOCK_ENABLE_1, 0x03, iic_fd);
262 
263  if (unsetI2C(iic_fd) < 0) {
264  pynq_error("config_audio_codec: unable to unset I2C %d\n", iic_index);
265  }
266 }
267 
268 void select_line_in(void) {
269  int iic_index = 1;
270  int iic_fd;
271  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
272  if (iic_fd < 0) {
273  pynq_error("select_line_in: unable to set I2C %d\n", iic_index);
274  }
275 
276  // Mixer 1 (left channel)
278  // Enable LAUX (MX1AUXG)
280 
281  // Mixer 2
283  // Enable RAUX (MX2AUXG)
285 
286  if (unsetI2C(iic_fd) < 0) {
287  pynq_error("select_line_in: unable to unset I2C %d\n", iic_index);
288  }
289 }
290 
291 void select_mic(void) {
292  int iic_index = 1;
293  int iic_fd;
294  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
295  if (iic_fd < 0) {
296  pynq_error("select_mic: unable to set I2C %d, ensure sudo chmod 666 "
297  "/dev/i2c-1 has been executed\n",
298  iic_index);
299  }
300 
301  // Mixer 1 (left channel)
303  // LDBOOST, set to 20 dB
305  // LDVOL, set to 21 dB
307 
308  // Mixer 2 (right channel)
310  // RDBOOST, set to 20 dB
312  // RDVOL, set to 21 dB
314 
315  if (unsetI2C(iic_fd) < 0) {
316  pynq_error("select_mic: unable to unset I2C %d\n", iic_index);
317  }
318 }
319 
320 void deselect(void) {
321  int iic_index = 1;
322  int iic_fd;
323  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
324  if (iic_fd < 0) {
325  pynq_error("deselect: unable to set I2C %d\n", iic_index);
326  }
327 
328  // mute mixer 1 in left channel
330  // mute mixer 2 in right channel
332 
333  if (unsetI2C(iic_fd) < 0) {
334  pynq_error("deselect: unable to unset I2C %d\n", iic_index);
335  }
336 }
337 
338 void audio_bypass(unsigned int audio_mmap_size, unsigned int nsamples,
339  unsigned int volume, int uio_index) {
340  if (uio_index > 2) {
341  pynq_error("audio_bypass: uio_index outside of range. is %d, should be "
342  "below 3. \n",
343  uio_index);
344  }
345  if (volume > 100) {
346  pynq_error("audio_bypass: volume outside allowed range. Is %d, should be "
347  "below 100 \n",
348  volume);
349  }
350 
351  int iic_index = 1;
352  int status;
353  void *uio_ptr;
354  int DataL, DataR;
355  int iic_fd;
356 
357  uio_ptr = setUIO(uio_index, audio_mmap_size);
358  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
359  if (iic_fd < 0) {
360  pynq_error("audio_bypass: unable to set I2C %d, ensure sudo chmod 666 "
361  "/dev/i2c-1 has been executed\n",
362  iic_index);
363  }
364 
365  // Mute mixer1 and mixer2 input
368  // Enable Mixer3 and Mixer4
371 
372  unsigned char vol_register = (unsigned char)volume << 2 | 0x3;
373  // Enable Left/Right Headphone out
375  iic_fd);
377  iic_fd);
379  iic_fd);
381  iic_fd);
382 
383  for (unsigned int i = 0; i < nsamples; i++) {
384  // wait for RX data to become available
385  do {
386  status = *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
387  } while (status == 0);
388  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
389  0x00000001;
390 
391  // Read the sample from the input
392  DataL = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_L_REG));
393  DataR = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_R_REG));
394 
395  // Write the sample to output
396  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_L_REG)) = DataL;
397  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_R_REG)) = DataR;
398  }
399 
406 
407  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
408  pynq_error("audio_bypass: unable to free UIO %d, ensure sudo chmod 666 "
409  "/dev/i2c-1 has been executed\n",
410  uio_index);
411  }
412  if (unsetI2C(iic_fd) < 0) {
413  pynq_error("audio_bypass: unable to unset I2C %d, ensure sudo chmod 666 "
414  "/dev/i2c-1 has been executed\n",
415  iic_index);
416  }
417 }
418 
419 void audio_record(unsigned int audio_mmap_size, unsigned int *BufAddr,
420  unsigned int nsamples, int uio_index) {
421  if (uio_index > 2) {
422  pynq_error("audio_record: uio_index outside of range. is %d, should be "
423  "below 3. \n",
424  uio_index);
425  }
426  int iic_index = 1;
427  unsigned int i, status;
428  void *uio_ptr;
429  int DataL, DataR;
430  int iic_fd;
431 
432  uio_ptr = setUIO(uio_index, audio_mmap_size);
433  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
434  if (iic_fd < 0) {
435  pynq_error("audio_record: unable to set I2C %d, ensure sudo chmod 666 "
436  "/dev/i2c-1 has been executed\n",
437  iic_index);
438  }
439 
440  for (i = 0; i < nsamples; i++) {
441  do {
442  status = *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
443  } while (status == 0);
444  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
445  0x00000001;
446 
447  // Read the sample from the input
448  DataL = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_L_REG));
449  DataR = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_R_REG));
450 
451  // Write the sample into memory
452  *(BufAddr + 2 * i) = DataL;
453  *(BufAddr + 2 * i + 1) = DataR;
454  }
455 
456  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
457  pynq_error("audio_record: unable to free UIO %d, ensure sudo chmod 666 "
458  "/dev/i2c-1 has been executed\n",
459  uio_index);
460  }
461  if (unsetI2C(iic_fd) < 0) {
462  pynq_error("audio_record: unable to unset I2C %d, ensure sudo chmod 666 "
463  "/dev/i2c-1 has been executed\n",
464  iic_index);
465  }
466 }
467 
468 void audio_play(unsigned int audio_mmap_size, unsigned int *BufAddr,
469  unsigned int nsamples, unsigned int volume, int uio_index) {
470  if (uio_index > 2) {
471  pynq_error(
472  "audio_play: uio_index outside of range. is %d, should be below 3. \n",
473  uio_index);
474  }
475  if (volume > 100) {
476  pynq_error("audio_play: volume outside allowed range. Is %d, should be "
477  "below 100 \n",
478  volume);
479  }
480  int iic_index = 1;
481  unsigned int i, status;
482  void *uio_ptr;
483  int DataL, DataR;
484  int iic_fd;
485 
486  uio_ptr = setUIO(uio_index, audio_mmap_size);
487  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
488  if (iic_fd < 0) {
489  pynq_error("audio_play: unable to set I2C %d, ensure sudo chmod 666 "
490  "/dev/i2c-1 has been executed\n",
491  iic_index);
492  }
493 
494  // Unmute left and right DAC, enable Mixer3 and Mixer4
497 
498  unsigned char vol_register = (unsigned char)volume << 2 | 0x3;
499  // Enable Left/Right Headphone out
501  iic_fd);
503  iic_fd);
504 
505  for (i = 0; i < nsamples; i++) {
506  do {
507  status = *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
508  } while (status == 0);
509  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
510  0x00000001;
511 
512  // Read the sample from memory
513  DataL = *(BufAddr + 2 * i);
514  DataR = *(BufAddr + 2 * i + 1);
515 
516  // Write the sample to output
517  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_L_REG)) = DataL;
518  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_R_REG)) = DataR;
519  }
520 
521  // Mute left and right DAC
524  // Mute left input to mixer3 (R23) and right input to mixer4 (R25)
527 
528  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
529  pynq_error("audio_play: unable to free UIO %d, ensure sudo chmod 666 "
530  "/dev/i2c-1 has been executed\n",
531  uio_index);
532  }
533  if (unsetI2C(iic_fd) < 0) {
534  pynq_error("audio_play: unable to unset I2C %d, ensure sudo chmod 666 "
535  "/dev/i2c-1 has been executed\n",
536  iic_index);
537  }
538 }
539 
540 void audio_repeat_play(unsigned int audio_mmap_size, unsigned int *BufAddr,
541  unsigned int nsamples, unsigned int volume,
542  unsigned int repetitions) {
543  if (volume > 100) {
544  pynq_error("audio_repeat_play: volume outside allowed range. Is %d, should "
545  "be below 100 \n",
546  volume);
547  }
548  int iic_index = 1;
549  unsigned int i, status;
550  void *uio_ptr;
551  int DataL, DataR;
552  int iic_fd;
553 
554  uio_ptr = setUIO(0, audio_mmap_size);
555  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
556  if (iic_fd < 0) {
557  pynq_error("audio_repeat_play: unable to set I2C %d, ensure sudo chmod 666 "
558  "/dev/i2c-1 has been executed\n",
559  iic_index);
560  }
561 
562  // Unmute left and right DAC, enable Mixer3 and Mixer4
565 
566  unsigned char vol_register = (unsigned char)volume << 2 | 0x3;
567  // Enable Left/Right Headphone out
569  iic_fd);
571  iic_fd);
572 
573  for (unsigned int repeat = 0; repeat < repetitions; repeat++) {
574  for (i = 0; i < nsamples; i++) {
575  do {
576  status =
577  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
578  } while (status == 0);
579  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
580  0x00000001;
581 
582  // Read the sample from memory
583  DataL = *(BufAddr + 2 * i);
584  DataR = *(BufAddr + 2 * i + 1);
585 
586  // Write the sample to output
587  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_L_REG)) = DataL;
588  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_R_REG)) = DataR;
589  }
590  }
591  // Mute left and right DAC
594  // Mute left input to mixer3 (R23) and right input to mixer4 (R25)
597 
598  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
599  pynq_error("audio_repeat_play: unable to free UIO %d\n", 0);
600  }
601  if (unsetI2C(iic_fd) < 0) {
602  pynq_error("audio_repeat_play: unable to unset I2C %d, ensure sudo chmod "
603  "666 /dev/i2c-1 has been executed\n",
604  iic_index);
605  }
606 }
607 
608 void audio_generate_tone(unsigned int frequency, uint32_t time_ms,
609  unsigned int volume) {
610 
611  if (frequency < 10) {
612  pynq_error("audio_generate_tone: frequency should be 10 or higher, "
613  "frequency is: %d\n",
614  frequency);
615  }
616  if (volume > 100) {
617  pynq_error("audio_generate_tone: volume outside allowed range. Is %d, "
618  "should be below 100 \n",
619  volume);
620  }
621  double period = 1 / ((double)(frequency));
622  unsigned int samplesPerPeriod = (int)(SAMPLE_RATE * period);
623  double time_s = ((double)(time_ms)) / 1000;
624  int totalPeriods = (int)(time_s / period); // Number of times one period must
625  // be played to play for time_ms
626 
627  uint32_t audioBuffer[16 * 1024 + 1] = {0};
628  unsigned int i, status;
629 
630  for (i = 0; i < samplesPerPeriod; i++) {
631  double t = (double)i / SAMPLE_RATE;
632  double value = sin(6.28318531 * frequency * t); // 6.28... = 2pi
633  value = value + 1;
634  value = value * 16000;
635  audioBuffer[2 * i] = (uint32_t)value;
636  audioBuffer[2 * i + 1] = (uint32_t)value;
637  }
638 
639  unsigned int audio_mmap_size = 64 * 1024;
640  unsigned int *BufAddr = audioBuffer;
641  int iic_index = 1;
642  void *uio_ptr;
643  int DataL, DataR;
644  int iic_fd;
645 
646  uio_ptr = setUIO(0, audio_mmap_size);
647  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
648  if (iic_fd < 0) {
649  pynq_error("audio_generate_tone: unable to set I2C %d, ensure sudo chmod "
650  "666 /dev/i2c-1 has been executed\n",
651  iic_index);
652  }
653 
654  // Unmute left and right DAC, enable Mixer3 and Mixer4
657 
658  unsigned char vol_register = (unsigned char)volume << 2 | 0x3;
659  // Enable Left/Right Headphone out
661  iic_fd);
663  iic_fd);
664 
665  for (int period = 0; period < totalPeriods; period++) {
666  for (i = 0; i < samplesPerPeriod; i++) {
667  do {
668  status =
669  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
670  } while (status == 0);
671  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
672  0x00000001;
673 
674  // Read the sample from memory
675  DataL = *(BufAddr + 2 * i);
676  DataR = *(BufAddr + 2 * i + 1);
677 
678  // Write the sample to output
679  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_L_REG)) = DataL;
680  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_R_REG)) = DataR;
681  }
682  }
683  // Mute left and right DAC
686  // Mute left input to mixer3 (R23) and right input to mixer4 (R25)
689 
690  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
691  pynq_error("audio_generate_tone: unable to free UIO %d, ensure sudo chmod "
692  "666 /dev/i2c-1 has been executed\n",
693  0);
694  }
695  if (unsetI2C(iic_fd) < 0) {
696  pynq_error("audio_generate_tone: unable to unset I2C %d, ensure has been "
697  "executed\n",
698  iic_index);
699  }
700 }
701 
702 
704 {
705  unsigned int audio_mmap_size = 64 * 1024;
706  void *uio_ptr;
707  int DataL, DataR;
708  int iic_fd;
709 
710  uio_ptr = setUIO(0, audio_mmap_size);
711  iic_fd = setI2C(1, IIC_SLAVE_ADDR);
712  if (iic_fd < 0) {
713  pynq_error("audio_generate_tone: unable to set I2C %d, ensure sudo chmod "
714  "666 /dev/i2c-1 has been executed\n",
715  1);
716  }
717 
718  int volume = 100;
719  // Mute mixer1 and mixer2 input
722  // Unmute left and right DAC, enable Mixer3 and Mixer4
725 
726  unsigned char vol_register = (unsigned char)58 << 2 | 0x3;
727  // Enable Left/Right Headphone out
729  iic_fd);
731  iic_fd);
732 
733 
734  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
735  pynq_error("audio_generate_tone: unable to free UIO %d, ensure sudo chmod "
736  "666 /dev/i2c-1 has been executed\n",
737  0);
738  }
739  if (unsetI2C(iic_fd) < 0) {
740  pynq_error("audio_generate_tone: unable to unset I2C %d, ensure has been executed\n", 1);
741  }
742 }
743 int32_t *audio_record_response(unsigned int frequency, uint32_t nperiods, unsigned
744 int volume, uint32_t *nsamples) {
745 
746 // if (frequency < 10) {
747 // pynq_error("frequency should be 10 or higher, "
748 // "frequency is: %d\n",
749 // frequency);
750 // }
751 // if (volume > 100) {
752 // pynq_error("volume outside allowed range. Is %d, "
753 // "should be below 100 \n",
754 // volume);
755 // }
756 // if ( nsamples == NULL ){
757 // pynq_error("audio record response, nsamples == NULL");
758 // }
759  const double period = 1 / ((double)(frequency));
760  const unsigned int samplesPerPeriod = (int)(SAMPLE_RATE * period);
761  const unsigned int totalPeriods = nperiods;
762 
763  uint32_t *audioBuffer = malloc((samplesPerPeriod*2*totalPeriods+ 1)*sizeof(uint32_t));
764  unsigned int i, status;
765 
766  int32_t *result_buffer = malloc(samplesPerPeriod*2*totalPeriods*sizeof(uint32_t));
767  int32_t *rb = result_buffer;
768 
769  for (i = 0; i < samplesPerPeriod*totalPeriods; i++) {
770  double t = (double)i / SAMPLE_RATE;
771  double value = sin(M_PI*2* frequency * t); // 6.28... = 2pi
772  value = value + 1.0;
773  value = value * 8388607/2;
774  audioBuffer[2 * i] = (uint32_t)value;
775  audioBuffer[2 * i + 1] = (uint32_t)value;
776  }
777 
778  unsigned int audio_mmap_size = 64 * 1024;
779  unsigned int *BufAddr = audioBuffer;
780  int iic_index = 1;
781  void *uio_ptr;
782  int DataL, DataR;
783  int iic_fd;
784 
785  uio_ptr = setUIO(0, audio_mmap_size);
786  iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);
787  if (iic_fd < 0) {
788  pynq_error("audio_generate_tone: unable to set I2C %d, ensure sudo chmod "
789  "666 /dev/i2c-1 has been executed\n",
790  iic_index);
791  }
792 
793 // // Mute mixer1 and mixer2 input
794 // write_audio_reg(R23_PLAYBACK_MIXER_LEFT_CONTROL_1, 0x00, iic_fd);
795 // write_audio_reg(R25_PLAYBACK_MIXER_RIGHT_CONTROL_1, 0x00, iic_fd);
796 // // Unmute left and right DAC, enable Mixer3 and Mixer4
797 // write_audio_reg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x21, iic_fd);
798 // write_audio_reg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x41, iic_fd);
799 //
800 // unsigned char vol_register = (unsigned char)volume << 2 | 0x3;
801 // // Enable Left/Right Headphone out
802 // write_audio_reg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, vol_register,
803 // iic_fd);
804 // write_audio_reg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, vol_register,
805 // iic_fd);
806 
807  // wait for conversion.
808  do {
809  status =
810  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
811  } while (status == 0);
812  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
813  0x00000001;
814  /*for (unsigned int period = 0; period < totalPeriods; period++)*/ {
815  unsigned int period = 1;
816  for (i = 0; i < totalPeriods*samplesPerPeriod; i++) {
817 //
818 // // Read the sample from memory
819 // DataL = *(BufAddr + 2 * i);
820 // DataR = *(BufAddr + 2 * i + 1);
821 
822  // Write the sample to output
823  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_L_REG)) = audioBuffer[2*i];
824  *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_R_REG)) = audioBuffer[2*i+1];
825  // wait for conversion.
826  do {
827  status =
828  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));
829  } while (status == 0);
830  *((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) =
831  0x00000001;
832  uint32_t l = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_L_REG));
833  uint32_t r = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_R_REG));
834  l<<=8;
835  r<<=8;
836  *(rb++) = *((volatile int *)&l);
837  *(rb++) = *((volatile int *)&r);
838  (*nsamples)++;
839  (*nsamples)++;
840  }
841  }
842  // Mute left and right DAC
843 // write_audio_reg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x01, iic_fd);
844 // write_audio_reg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x01, iic_fd);
845 // // Mute left input to mixer3 (R23) and right input to mixer4 (R25)
846 // write_audio_reg(R23_PLAYBACK_MIXER_LEFT_CONTROL_1, 0x00, iic_fd);
847 // write_audio_reg(R25_PLAYBACK_MIXER_RIGHT_CONTROL_1, 0x00, iic_fd);
848  free(audioBuffer);
849 
850  if (unsetUIO(uio_ptr, audio_mmap_size) < 0) {
851  pynq_error("audio_generate_tone: unable to free UIO %d, ensure sudo chmod "
852  "666 /dev/i2c-1 has been executed\n",
853  0);
854  }
855  if (unsetI2C(iic_fd) < 0) {
856  pynq_error("audio_generate_tone: unable to unset I2C %d, ensure has been "
857  "executed\n",
858  iic_index);
859  }
860  return result_buffer;
861 }
audio_select_input
void audio_select_input(int input)
selects the audio input channel.
Definition: audio.c:77
SAMPLE_RATE
#define SAMPLE_RATE
Definition: audio.c:67
R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL
@ R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL
Definition: audio.h:59
R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL
@ R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL
Definition: audio.h:80
pynq_error
#define pynq_error(...)
Definition: log.h:118
R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL
@ R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL
Definition: audio.h:58
R22_PLAYBACK_MIXER_LEFT_CONTROL_0
@ R22_PLAYBACK_MIXER_LEFT_CONTROL_0
Definition: audio.h:72
R0_CLOCK_CONTROL
@ R0_CLOCK_CONTROL
Definition: audio.h:50
R4_RECORD_MIXER_LEFT_CONTROL_0
@ R4_RECORD_MIXER_LEFT_CONTROL_0
Definition: audio.h:54
MIC
#define MIC
Definition: audio.h:33
audio_record_response_start
void audio_record_response_start(void)
Definition: audio.c:703
R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL
@ R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL
Definition: audio.h:79
R66_CLOCK_ENABLE_1
@ R66_CLOCK_ENABLE_1
Definition: audio.h:101
setUIO
void * setUIO(int uio_index, int length)
Definition: uio.c:2
R36_DAC_CONTROL_0
@ R36_DAC_CONTROL_0
Definition: audio.h:86
unsetI2C
int unsetI2C(int i2c_fd)
Definition: i2cps.c:3
R23_PLAYBACK_MIXER_LEFT_CONTROL_1
@ R23_PLAYBACK_MIXER_LEFT_CONTROL_1
Definition: audio.h:73
I2S_DATA_RX_L_REG
#define I2S_DATA_RX_L_REG
Definition: audio.h:42
i2cps.h
R58_SERIAL_INPUT_ROUTE_CONTROL
@ R58_SERIAL_INPUT_ROUTE_CONTROL
Definition: audio.h:94
R61_DSP_ENABLE
@ R61_DSP_ENABLE
Definition: audio.h:96
read_audio_reg
uint8_t read_audio_reg(unsigned char u8RegAddr, int iic_fd)
Definition: audio.c:101
R19_ADC_CONTROL
@ R19_ADC_CONTROL
Definition: audio.h:69
audio_record
void audio_record(unsigned int audio_mmap_size, unsigned int *BufAddr, unsigned int nsamples, int uio_index)
Function to support audio recording without the audio codec controller.
Definition: audio.c:419
R65_CLOCK_ENABLE_0
@ R65_CLOCK_ENABLE_0
Definition: audio.h:100
uio.h
I2S_DATA_RX_R_REG
#define I2S_DATA_RX_R_REG
Definition: audio.h:43
write_audio_reg
void write_audio_reg(unsigned char u8RegAddr, unsigned char u8Data, int iic_fd)
Definition: audio.c:90
config_audio_pll
void config_audio_pll(void)
Definition: audio.c:118
config_audio_codec
void config_audio_codec(void)
Definition: audio.c:208
audio_generate_tone
void audio_generate_tone(unsigned int frequency, uint32_t time_ms, unsigned int volume)
Definition: audio.c:608
R6_RECORD_MIXER_RIGHT_CONTROL_0
@ R6_RECORD_MIXER_RIGHT_CONTROL_0
Definition: audio.h:56
R14_ALC_CONTROL_3
@ R14_ALC_CONTROL_3
Definition: audio.h:64
select_line_in
void select_line_in(void)
Function to select LINE_IN as input.
Definition: audio.c:268
audio_init
void audio_init(void)
Initializes the audio register. Sets the sampling frequency. defines several values such as audio rec...
Definition: audio.c:72
R10_RECORD_MICROPHONE_BIAS_CONTROL
@ R10_RECORD_MICROPHONE_BIAS_CONTROL
Definition: audio.h:60
LINE_IN
#define LINE_IN
Definition: audio.h:32
I2S_STATUS_REG
#define I2S_STATUS_REG
Definition: audio.h:46
audio_bypass
void audio_bypass(unsigned int audio_mmap_size, unsigned int nsamples, unsigned int volume, int uio_index)
Record and play the audio without storing in DRAM.
Definition: audio.c:338
writeI2C_asFile
int writeI2C_asFile(int i2c_fd, unsigned char writebuffer[], unsigned char bytes)
Definition: i2cps.c:4
IIC_SLAVE_ADDR
#define IIC_SLAVE_ADDR
Definition: audio.h:36
R7_RECORD_MIXER_RIGHT_CONTROL_1
@ R7_RECORD_MIXER_RIGHT_CONTROL_1
Definition: audio.h:57
audio_play
void audio_play(unsigned int audio_mmap_size, unsigned int *BufAddr, unsigned int nsamples, unsigned int volume, int uio_index)
Definition: audio.c:468
R5_RECORD_MIXER_LEFT_CONTROL_1
@ R5_RECORD_MIXER_LEFT_CONTROL_1
Definition: audio.h:55
audio_record_response
int32_t * audio_record_response(unsigned int frequency, uint32_t nperiods, unsigned int volume, uint32_t *nsamples)
Definition: audio.c:743
deselect
void deselect(void)
Function to deselect input, either LINE_IN, or MIC.
Definition: audio.c:320
audio.h
setI2C
int setI2C(unsigned int index, long slave_addr)
Definition: i2cps.c:2
I2S_DATA_TX_L_REG
#define I2S_DATA_TX_L_REG
Definition: audio.h:44
R59_SERIAL_OUTPUT_ROUTE_CONTROL
@ R59_SERIAL_OUTPUT_ROUTE_CONTROL
Definition: audio.h:95
I2S_DATA_TX_R_REG
#define I2S_DATA_TX_R_REG
Definition: audio.h:45
R25_PLAYBACK_MIXER_RIGHT_CONTROL_1
@ R25_PLAYBACK_MIXER_RIGHT_CONTROL_1
Definition: audio.h:75
unsetUIO
int unsetUIO(void *uio_ptr, int length)
Definition: uio.c:3
select_mic
void select_mic(void)
Function to select MIC as input.
Definition: audio.c:291
audio_repeat_play
void audio_repeat_play(unsigned int audio_mmap_size, unsigned int *BufAddr, unsigned int nsamples, unsigned int volume, unsigned int repetitions)
Function to play one audio fragment for multiple repititions.
Definition: audio.c:540
R35_PLAYBACK_POWER_MANAGEMENT
@ R35_PLAYBACK_POWER_MANAGEMENT
Definition: audio.h:85
M_PI
#define M_PI
Definition: display.c:44
libpynq.h
R62_DSP_RUN
@ R62_DSP_RUN
Definition: audio.h:97
R24_PLAYBACK_MIXER_RIGHT_CONTROL_0
@ R24_PLAYBACK_MIXER_RIGHT_CONTROL_0
Definition: audio.h:74
R15_SERIAL_PORT_CONTROL_0
@ R15_SERIAL_PORT_CONTROL_0
Definition: audio.h:65
readI2C_asFile
int readI2C_asFile(int i2c_fd, unsigned char readbuffer[], unsigned char bytes)
Definition: i2cps.c:6