56 #include <linux/i2c-dev.h>
61 #include <sys/ioctl.h>
67 #define SAMPLE_RATE 48000
70 #define LOG_DOMAIN "audio"
83 pynq_error(
"audio_select_input: invalid input %d, must be LINE_IN or MIC\n",
92 unsigned char u8TxData[3];
94 u8TxData[1] = u8RegAddr;
97 pynq_error(
"write_audio_reg: unable to write audio register, ensure sudo "
98 "chmod 666 /dev/i2c-1 has been executed. \n");
102 unsigned char u8TxData[3];
104 u8TxData[1] = u8RegAddr;
106 pynq_error(
"write_audio_reg: unable to write audio register, ensure sudo "
107 "chmod 666 /dev/i2c-1 has been executed. \n");
111 pynq_error(
"write_audio_reg: unable to write audio register, ensure sudo "
112 "chmod 666 /dev/i2c-1 has been executed. \n");
120 unsigned char u8TxData[8], u8RxData[6];
124 pynq_error(
"config_audio_pll: unable to set I2C %d\n", iic_index);
161 pynq_error(
"config_audio_pll: unable to write audio register, ensure sudo "
162 "chmod 666 /dev/i2c-1 has been executed. \n");
173 printf(
"R0 reg: %02X\r\n", c);
180 pynq_error(
"writeI2C_asFile: unable to write audio register, ensure sudo "
181 "chmod 666 /dev/i2c-1 has been executed. \n");
184 pynq_error(
"readI2C_asFile: unable to write audio register, ensure sudo "
185 "chmod 666 /dev/i2c-1 has been executed. \n");
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);
199 pynq_error(
"config_audio_pll: unable to set I2C %d\n", iic_fd);
213 pynq_error(
"config_audio_codec: unable to set I2C %d\n", iic_index);
264 pynq_error(
"config_audio_codec: unable to unset I2C %d\n", iic_index);
273 pynq_error(
"select_line_in: unable to set I2C %d\n", iic_index);
287 pynq_error(
"select_line_in: unable to unset I2C %d\n", iic_index);
296 pynq_error(
"select_mic: unable to set I2C %d, ensure sudo chmod 666 "
297 "/dev/i2c-1 has been executed\n",
316 pynq_error(
"select_mic: unable to unset I2C %d\n", iic_index);
325 pynq_error(
"deselect: unable to set I2C %d\n", iic_index);
334 pynq_error(
"deselect: unable to unset I2C %d\n", iic_index);
339 unsigned int volume,
int uio_index) {
341 pynq_error(
"audio_bypass: uio_index outside of range. is %d, should be "
346 pynq_error(
"audio_bypass: volume outside allowed range. Is %d, should be "
357 uio_ptr =
setUIO(uio_index, audio_mmap_size);
360 pynq_error(
"audio_bypass: unable to set I2C %d, ensure sudo chmod 666 "
361 "/dev/i2c-1 has been executed\n",
372 unsigned char vol_register = (
unsigned char)volume << 2 | 0x3;
383 for (
unsigned int i = 0; i < nsamples; i++) {
386 status = *((
volatile unsigned *)(((uint8_t *)uio_ptr) +
I2S_STATUS_REG));
387 }
while (status == 0);
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",
413 pynq_error(
"audio_bypass: unable to unset I2C %d, ensure sudo chmod 666 "
414 "/dev/i2c-1 has been executed\n",
420 unsigned int nsamples,
int uio_index) {
422 pynq_error(
"audio_record: uio_index outside of range. is %d, should be "
427 unsigned int i, status;
432 uio_ptr =
setUIO(uio_index, audio_mmap_size);
435 pynq_error(
"audio_record: unable to set I2C %d, ensure sudo chmod 666 "
436 "/dev/i2c-1 has been executed\n",
440 for (i = 0; i < nsamples; i++) {
442 status = *((
volatile unsigned *)(((uint8_t *)uio_ptr) +
I2S_STATUS_REG));
443 }
while (status == 0);
452 *(BufAddr + 2 * i) = DataL;
453 *(BufAddr + 2 * i + 1) = DataR;
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",
462 pynq_error(
"audio_record: unable to unset I2C %d, ensure sudo chmod 666 "
463 "/dev/i2c-1 has been executed\n",
468 void audio_play(
unsigned int audio_mmap_size,
unsigned int *BufAddr,
469 unsigned int nsamples,
unsigned int volume,
int uio_index) {
472 "audio_play: uio_index outside of range. is %d, should be below 3. \n",
476 pynq_error(
"audio_play: volume outside allowed range. Is %d, should be "
481 unsigned int i, status;
486 uio_ptr =
setUIO(uio_index, audio_mmap_size);
489 pynq_error(
"audio_play: unable to set I2C %d, ensure sudo chmod 666 "
490 "/dev/i2c-1 has been executed\n",
498 unsigned char vol_register = (
unsigned char)volume << 2 | 0x3;
505 for (i = 0; i < nsamples; i++) {
507 status = *((
volatile unsigned *)(((uint8_t *)uio_ptr) +
I2S_STATUS_REG));
508 }
while (status == 0);
513 DataL = *(BufAddr + 2 * i);
514 DataR = *(BufAddr + 2 * i + 1);
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",
534 pynq_error(
"audio_play: unable to unset I2C %d, ensure sudo chmod 666 "
535 "/dev/i2c-1 has been executed\n",
541 unsigned int nsamples,
unsigned int volume,
542 unsigned int repetitions) {
544 pynq_error(
"audio_repeat_play: volume outside allowed range. Is %d, should "
549 unsigned int i, status;
554 uio_ptr =
setUIO(0, audio_mmap_size);
557 pynq_error(
"audio_repeat_play: unable to set I2C %d, ensure sudo chmod 666 "
558 "/dev/i2c-1 has been executed\n",
566 unsigned char vol_register = (
unsigned char)volume << 2 | 0x3;
573 for (
unsigned int repeat = 0; repeat < repetitions; repeat++) {
574 for (i = 0; i < nsamples; i++) {
578 }
while (status == 0);
583 DataL = *(BufAddr + 2 * i);
584 DataR = *(BufAddr + 2 * i + 1);
598 if (
unsetUIO(uio_ptr, audio_mmap_size) < 0) {
599 pynq_error(
"audio_repeat_play: unable to free UIO %d\n", 0);
602 pynq_error(
"audio_repeat_play: unable to unset I2C %d, ensure sudo chmod "
603 "666 /dev/i2c-1 has been executed\n",
609 unsigned int volume) {
611 if (frequency < 10) {
612 pynq_error(
"audio_generate_tone: frequency should be 10 or higher, "
613 "frequency is: %d\n",
617 pynq_error(
"audio_generate_tone: volume outside allowed range. Is %d, "
618 "should be below 100 \n",
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);
627 uint32_t audioBuffer[16 * 1024 + 1] = {0};
628 unsigned int i, status;
630 for (i = 0; i < samplesPerPeriod; i++) {
632 double value = sin(6.28318531 * frequency * t);
634 value = value * 16000;
635 audioBuffer[2 * i] = (uint32_t)value;
636 audioBuffer[2 * i + 1] = (uint32_t)value;
639 unsigned int audio_mmap_size = 64 * 1024;
640 unsigned int *BufAddr = audioBuffer;
646 uio_ptr =
setUIO(0, audio_mmap_size);
649 pynq_error(
"audio_generate_tone: unable to set I2C %d, ensure sudo chmod "
650 "666 /dev/i2c-1 has been executed\n",
658 unsigned char vol_register = (
unsigned char)volume << 2 | 0x3;
665 for (
int period = 0; period < totalPeriods; period++) {
666 for (i = 0; i < samplesPerPeriod; i++) {
670 }
while (status == 0);
675 DataL = *(BufAddr + 2 * i);
676 DataR = *(BufAddr + 2 * i + 1);
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",
696 pynq_error(
"audio_generate_tone: unable to unset I2C %d, ensure has been "
705 unsigned int audio_mmap_size = 64 * 1024;
710 uio_ptr =
setUIO(0, audio_mmap_size);
713 pynq_error(
"audio_generate_tone: unable to set I2C %d, ensure sudo chmod "
714 "666 /dev/i2c-1 has been executed\n",
726 unsigned char vol_register = (
unsigned char)58 << 2 | 0x3;
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",
740 pynq_error(
"audio_generate_tone: unable to unset I2C %d, ensure has been executed\n", 1);
744 int volume, uint32_t *nsamples) {
759 const double period = 1 / ((double)(frequency));
760 const unsigned int samplesPerPeriod = (int)(
SAMPLE_RATE * period);
761 const unsigned int totalPeriods = nperiods;
763 uint32_t *audioBuffer = malloc((samplesPerPeriod*2*totalPeriods+ 1)*
sizeof(uint32_t));
764 unsigned int i, status;
766 int32_t *result_buffer = malloc(samplesPerPeriod*2*totalPeriods*
sizeof(uint32_t));
767 int32_t *rb = result_buffer;
769 for (i = 0; i < samplesPerPeriod*totalPeriods; i++) {
771 double value = sin(
M_PI*2* frequency * t);
773 value = value * 8388607/2;
774 audioBuffer[2 * i] = (uint32_t)value;
775 audioBuffer[2 * i + 1] = (uint32_t)value;
778 unsigned int audio_mmap_size = 64 * 1024;
779 unsigned int *BufAddr = audioBuffer;
785 uio_ptr =
setUIO(0, audio_mmap_size);
788 pynq_error(
"audio_generate_tone: unable to set I2C %d, ensure sudo chmod "
789 "666 /dev/i2c-1 has been executed\n",
811 }
while (status == 0);
815 unsigned int period = 1;
816 for (i = 0; i < totalPeriods*samplesPerPeriod; i++) {
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];
829 }
while (status == 0);
836 *(rb++) = *((
volatile int *)&l);
837 *(rb++) = *((
volatile int *)&r);
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",
856 pynq_error(
"audio_generate_tone: unable to unset I2C %d, ensure has been "
860 return result_buffer;