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.

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.