96kHz-16bit USB Audio Output interface with UDA1345 and 24.576MHz Xtal.
Dependencies: I2S USBDevice mbed
Fork of USBAudioPlayback by
main.cpp@7:cfcf37ea571b, 2014-09-16 (annotated)
- Committer:
- edy555
- Date:
- Tue Sep 16 23:24:18 2014 +0000
- Revision:
- 7:cfcf37ea571b
- Parent:
- 6:dc7b32ce4277
first publish
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
samux | 0:eb53799c0b97 | 1 | // Playback example with the USBAUDIO library |
samux | 0:eb53799c0b97 | 2 | |
samux | 0:eb53799c0b97 | 3 | #include "mbed.h" |
samux | 0:eb53799c0b97 | 4 | #include "USBAudio.h" |
edy555 | 3:44343b9dd8b6 | 5 | #include "I2S.h" |
samux | 0:eb53799c0b97 | 6 | |
edy555 | 6:dc7b32ce4277 | 7 | // frequency: 96 kHz |
edy555 | 3:44343b9dd8b6 | 8 | #define FREQ_SPK 96000 |
edy555 | 3:44343b9dd8b6 | 9 | #define FREQ_MIC 8000 |
samux | 0:eb53799c0b97 | 10 | |
samux | 0:eb53799c0b97 | 11 | // 2channels: stereo |
samux | 0:eb53799c0b97 | 12 | #define NB_CHA_SPK 2 |
edy555 | 4:a3aee5fc768a | 13 | #define NB_CHA_MIC 0 |
samux | 0:eb53799c0b97 | 14 | |
samux | 0:eb53799c0b97 | 15 | // length computed: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there are two channels, the length will be 48 * 2 * 2 |
samux | 0:eb53799c0b97 | 16 | #define LENGTH_AUDIO_PACKET_SPK (FREQ_SPK / 500) * NB_CHA_SPK |
samux | 0:eb53799c0b97 | 17 | #define LENGTH_AUDIO_PACKET_MIC (FREQ_MIC / 500) * NB_CHA_MIC |
samux | 0:eb53799c0b97 | 18 | |
samux | 0:eb53799c0b97 | 19 | // USBAudio object |
samux | 0:eb53799c0b97 | 20 | USBAudio audio(FREQ_SPK, NB_CHA_SPK, FREQ_MIC, NB_CHA_MIC, 0xab45, 0x0378); |
samux | 0:eb53799c0b97 | 21 | |
edy555 | 3:44343b9dd8b6 | 22 | DigitalOut myled(LED1); |
edy555 | 3:44343b9dd8b6 | 23 | |
edy555 | 3:44343b9dd8b6 | 24 | I2S i2s(I2S_TRANSMIT, p5, p6, p7); |
edy555 | 3:44343b9dd8b6 | 25 | I2S i2srx(I2S_RECEIVE, p8, p29, p15); |
edy555 | 3:44343b9dd8b6 | 26 | |
edy555 | 6:dc7b32ce4277 | 27 | //SPI spi(p11, p12, p13); // mosi, miso, sclk |
edy555 | 6:dc7b32ce4277 | 28 | DigitalOut mode(p14); |
edy555 | 6:dc7b32ce4277 | 29 | DigitalOut spiout(p11); |
edy555 | 6:dc7b32ce4277 | 30 | DigitalOut spiclk(p13); |
edy555 | 6:dc7b32ce4277 | 31 | |
edy555 | 5:ca2316551f3d | 32 | #define CHUNKS 8 |
edy555 | 3:44343b9dd8b6 | 33 | |
edy555 | 3:44343b9dd8b6 | 34 | int buf_out[LENGTH_AUDIO_PACKET_MIC/sizeof(int)]; |
edy555 | 3:44343b9dd8b6 | 35 | int16_t buf_in[CHUNKS][LENGTH_AUDIO_PACKET_SPK/sizeof(int16_t)]; |
edy555 | 3:44343b9dd8b6 | 36 | int16_t * stream_in = NULL; |
edy555 | 3:44343b9dd8b6 | 37 | int16_t * stream_in_tail = NULL; |
edy555 | 3:44343b9dd8b6 | 38 | int read_pos = 0; |
edy555 | 3:44343b9dd8b6 | 39 | int write_pos = 0; |
edy555 | 3:44343b9dd8b6 | 40 | |
edy555 | 3:44343b9dd8b6 | 41 | void genwave() |
edy555 | 3:44343b9dd8b6 | 42 | { |
edy555 | 3:44343b9dd8b6 | 43 | int buf[8]; |
edy555 | 3:44343b9dd8b6 | 44 | if (stream_in == NULL) { |
edy555 | 3:44343b9dd8b6 | 45 | buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = buf[7] = 0; |
edy555 | 3:44343b9dd8b6 | 46 | i2s.write(buf, 6); |
edy555 | 3:44343b9dd8b6 | 47 | return; |
edy555 | 3:44343b9dd8b6 | 48 | } |
edy555 | 3:44343b9dd8b6 | 49 | |
edy555 | 3:44343b9dd8b6 | 50 | myled = 1; |
edy555 | 3:44343b9dd8b6 | 51 | buf[0] = stream_in[0]; |
edy555 | 3:44343b9dd8b6 | 52 | buf[1] = stream_in[1]; |
edy555 | 3:44343b9dd8b6 | 53 | buf[2] = stream_in[2]; |
edy555 | 3:44343b9dd8b6 | 54 | buf[3] = stream_in[3]; |
edy555 | 3:44343b9dd8b6 | 55 | buf[4] = stream_in[4]; |
edy555 | 3:44343b9dd8b6 | 56 | buf[5] = stream_in[5]; |
edy555 | 3:44343b9dd8b6 | 57 | buf[6] = stream_in[6]; |
edy555 | 3:44343b9dd8b6 | 58 | buf[7] = stream_in[7]; |
edy555 | 3:44343b9dd8b6 | 59 | i2s.write(buf, 8); |
edy555 | 3:44343b9dd8b6 | 60 | stream_in += 8; |
edy555 | 3:44343b9dd8b6 | 61 | if (stream_in >= stream_in_tail) { |
edy555 | 5:ca2316551f3d | 62 | int d = read_pos - write_pos; |
edy555 | 5:ca2316551f3d | 63 | if (d < 0) |
edy555 | 5:ca2316551f3d | 64 | d += CHUNKS; |
edy555 | 5:ca2316551f3d | 65 | if (d > CHUNKS/4) { |
edy555 | 5:ca2316551f3d | 66 | write_pos++; |
edy555 | 5:ca2316551f3d | 67 | write_pos %= CHUNKS; |
edy555 | 5:ca2316551f3d | 68 | } |
edy555 | 3:44343b9dd8b6 | 69 | stream_in = buf_in[write_pos]; |
edy555 | 3:44343b9dd8b6 | 70 | stream_in_tail = &buf_in[write_pos][LENGTH_AUDIO_PACKET_SPK/sizeof(int16_t)]; |
edy555 | 3:44343b9dd8b6 | 71 | } |
edy555 | 3:44343b9dd8b6 | 72 | myled = 0; |
edy555 | 3:44343b9dd8b6 | 73 | } |
edy555 | 3:44343b9dd8b6 | 74 | |
edy555 | 6:dc7b32ce4277 | 75 | void spi_send(int byte) |
edy555 | 6:dc7b32ce4277 | 76 | { |
edy555 | 6:dc7b32ce4277 | 77 | wait_us(10); |
edy555 | 6:dc7b32ce4277 | 78 | for (int i = 0; i < 8; i++) { |
edy555 | 6:dc7b32ce4277 | 79 | if (byte & (1 << i)) |
edy555 | 6:dc7b32ce4277 | 80 | spiout = 1; |
edy555 | 6:dc7b32ce4277 | 81 | else |
edy555 | 6:dc7b32ce4277 | 82 | spiout = 0; |
edy555 | 6:dc7b32ce4277 | 83 | spiclk = 0; |
edy555 | 6:dc7b32ce4277 | 84 | wait_us(10); |
edy555 | 6:dc7b32ce4277 | 85 | spiclk = 1; |
edy555 | 6:dc7b32ce4277 | 86 | wait_us(10); |
edy555 | 6:dc7b32ce4277 | 87 | } |
edy555 | 6:dc7b32ce4277 | 88 | } |
edy555 | 6:dc7b32ce4277 | 89 | |
edy555 | 6:dc7b32ce4277 | 90 | |
edy555 | 6:dc7b32ce4277 | 91 | void init_uda1345() { |
edy555 | 6:dc7b32ce4277 | 92 | spiclk = 1; |
edy555 | 6:dc7b32ce4277 | 93 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 94 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 95 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 96 | spi_send(0x16); |
edy555 | 6:dc7b32ce4277 | 97 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 98 | spi_send(0x21); |
edy555 | 6:dc7b32ce4277 | 99 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 100 | spi_send(0x14); |
edy555 | 6:dc7b32ce4277 | 101 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 102 | spi_send(0x84); |
edy555 | 6:dc7b32ce4277 | 103 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 104 | wait_us(10); |
edy555 | 6:dc7b32ce4277 | 105 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 106 | spi_send(0x02); |
edy555 | 6:dc7b32ce4277 | 107 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 108 | wait_us(10); |
edy555 | 6:dc7b32ce4277 | 109 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 110 | spi_send(0xc3); |
edy555 | 6:dc7b32ce4277 | 111 | |
edy555 | 6:dc7b32ce4277 | 112 | #if 0 |
edy555 | 6:dc7b32ce4277 | 113 | spi.format(8, 3); |
edy555 | 6:dc7b32ce4277 | 114 | spi.frequency(100000); |
edy555 | 6:dc7b32ce4277 | 115 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 116 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 117 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 118 | spi.write(0x68); // 0x16 |
edy555 | 6:dc7b32ce4277 | 119 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 120 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 121 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 122 | spi.write(0x84); // 0x21 |
edy555 | 6:dc7b32ce4277 | 123 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 124 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 125 | spi.write(0x28); // 0x14 |
edy555 | 6:dc7b32ce4277 | 126 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 127 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 128 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 129 | spi.write(0x21); // 0x84 |
edy555 | 6:dc7b32ce4277 | 130 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 131 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 132 | //spi.write(0x28); // 0x14 |
edy555 | 6:dc7b32ce4277 | 133 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 134 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 135 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 136 | spi.write(0x40); // 0x02 |
edy555 | 6:dc7b32ce4277 | 137 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 138 | mode = 0; |
edy555 | 6:dc7b32ce4277 | 139 | //spi.write(0x28); // 0x14 |
edy555 | 6:dc7b32ce4277 | 140 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 141 | mode = 1; |
edy555 | 6:dc7b32ce4277 | 142 | wait_us(100); |
edy555 | 6:dc7b32ce4277 | 143 | spi.write(0xc3); // 0xc3 |
edy555 | 6:dc7b32ce4277 | 144 | //wait_us(100); |
edy555 | 6:dc7b32ce4277 | 145 | //mode = 0; |
edy555 | 6:dc7b32ce4277 | 146 | //wait_us(100); |
edy555 | 6:dc7b32ce4277 | 147 | //mode = 1; |
edy555 | 6:dc7b32ce4277 | 148 | #endif |
edy555 | 6:dc7b32ce4277 | 149 | } |
edy555 | 6:dc7b32ce4277 | 150 | |
samux | 0:eb53799c0b97 | 151 | int main() { |
edy555 | 6:dc7b32ce4277 | 152 | init_uda1345(); |
edy555 | 3:44343b9dd8b6 | 153 | i2srx.masterslave(I2S_SLAVE); |
edy555 | 3:44343b9dd8b6 | 154 | i2srx.frequency(96000); |
edy555 | 3:44343b9dd8b6 | 155 | i2srx.start(); |
edy555 | 3:44343b9dd8b6 | 156 | i2s.attach(genwave); |
edy555 | 3:44343b9dd8b6 | 157 | i2s.masterslave(I2S_MASTER); |
edy555 | 3:44343b9dd8b6 | 158 | i2s.wordsize(16); |
edy555 | 3:44343b9dd8b6 | 159 | i2s.frequency(96000); |
edy555 | 3:44343b9dd8b6 | 160 | i2s.set_interrupt_fifo_level(0); |
edy555 | 3:44343b9dd8b6 | 161 | i2s.start(); |
samux | 0:eb53799c0b97 | 162 | |
samux | 0:eb53799c0b97 | 163 | while (1) { |
edy555 | 4:a3aee5fc768a | 164 | audio.read((uint8_t *)buf_in[read_pos++]); |
edy555 | 3:44343b9dd8b6 | 165 | read_pos %= CHUNKS; |
edy555 | 3:44343b9dd8b6 | 166 | if (stream_in == NULL && read_pos > CHUNKS / 2) { |
edy555 | 3:44343b9dd8b6 | 167 | stream_in = buf_in[write_pos]; |
edy555 | 3:44343b9dd8b6 | 168 | stream_in_tail = &buf_in[write_pos][LENGTH_AUDIO_PACKET_SPK/sizeof(int16_t)]; |
edy555 | 3:44343b9dd8b6 | 169 | } |
samux | 0:eb53799c0b97 | 170 | } |
samux | 0:eb53799c0b97 | 171 | } |