Library to control and transfer data from NXP SGTL5000. As used on the Teensy Audio Shield. It uses DMA to transfer I2S FIFO data.
The Library now supports dual codecs. Allowing all 4 channels of the Teensy I2S interface to RX and TX data to separate SGTL5000 devices.
The ISR routines that handles pointer swaps for double buffering has been fully coded in assembler to reduce overhead and now takes < 800nS per FIFO transfer when using all 4 channels.
Support added for all typical sample rates and system Clock speeds of 96Mhz or 120Mhz.
Pause and Resume functions added to allow quick and simple suppression of IRQs and stream halting and restart. This required software triggered IRQ, in order to ensure accurate word sync control.
Diff: sgtl5000.cpp
- Revision:
- 7:d65476c153a4
- Parent:
- 6:4ab5aaeaa064
- Child:
- 8:9fdf8501d14b
--- a/sgtl5000.cpp Sat Jul 01 10:20:45 2017 +0000 +++ b/sgtl5000.cpp Wed Jul 05 17:30:08 2017 +0000 @@ -162,20 +162,32 @@ int32_t SGTL5000::read_i2c(uint32_t reg_addr, uint32_t mask) { + if(mask == 0x0 || mask > 0xFFFF) return -1; uint32_t shift; for (shift = 0; !(mask & (1<<shift)); ++shift) {}; uint32_t wire_data; uint32_t wire_addr = __rev(reg_addr) >> 16; - if(mI2C.write(i2c_addr, (char *)&wire_addr, 2, false)) return -1; - if(mI2C.read(i2c_addr, (char *)&wire_data, 2, false)) return -1; + mI2C.lock(); + if(mI2C.write(i2c_addr, (char *)&wire_addr, 2, false)) { + mI2C.unlock(); + return -1; + } + if(mI2C.read(i2c_addr, (char *)&wire_data, 2, false)) { + mI2C.unlock(); + return -1; + } return ((__rev(wire_data) >> 16) & mask) >> shift; } int32_t SGTL5000::write_i2c(uint32_t reg_addr, uint32_t data) { uint32_t wire_data = (__rev(reg_addr) >> 16) | (__rev(data)); - if(mI2C.write(i2c_addr, (char *)&wire_data, 4, false)) return -1; + mI2C.lock(); + if(mI2C.write(i2c_addr, (char *)&wire_data, 4, false)) { + mI2C.unlock(); + return -1; + } return 0; } @@ -185,7 +197,11 @@ uint32_t shift; for (shift = 0; !(mask & (1<<shift)); ++shift) {}; uint32_t wire_data = (__rev(reg_addr) >> 16) | (__rev((read_i2c(reg_addr) & (~mask & 0xFFFF)) | ((data << shift) & mask))); - if(mI2C.write(i2c_addr, (char *)&wire_data, 4, false)) return -1; + mI2C.lock(); + if(mI2C.write(i2c_addr, (char *)&wire_data, 4, false)) { + mI2C.unlock(); + return -1; + } return 0; } @@ -397,7 +413,7 @@ int32_t SGTL5000::start_SYNC(uint32_t BufRX_L_safe, uint32_t BufRX_R_safe, uint32_t BufTX_L_safe, uint32_t BufTX_R_safe, uint32_t block_size, bool _packed_RX, bool _packed_TX, bool _RX_shift, bool _TX_shift, uint32_t _RX_DMAch, uint32_t _TX_DMAch, uint32_t DMA_irq_pri) { - if(!SYNC_attached && !SYNC_attach_type) return -1; // Check we have a handler if using callback + if(!SYNC_attached && !SYNC_attach_type) return -1; // Check we have a handler if using callback if(SYNC_run || TX_run || RX_run ) return -1; // Check if i2s is already started if(_RX_DMAch > 15 || _TX_DMAch > 15) return -1; // Sanity check DMAMUX channels if (!(block_size == 2 || block_size == 4 || block_size == 8)) return -1; // Only accept block size 2^n within range.