First Publish. Works fine.

Dependents:   unzen_sample_lpcxpresso_4337_callbacks

Revision:
0:5ac19c994288
Child:
1:9710fb328a08
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unzen_hal.cpp	Sun Apr 10 12:37:10 2016 +0000
@@ -0,0 +1,140 @@
+#include "unzen_hal.h"
+
+namespace unzen 
+{
+        // Set up I2S peripheral to ready to start.
+        // By this HAL, the I2S have to become : 
+        // - slave mode
+        // - clock must be ready
+        // - pins must be configured.
+        // - Interrupt enable.
+    void hal_i2s_setup()
+    {
+            // Assert DAI reset
+        LPC_I2S0->DAO |= 1 << 4;    // I2S_DAI_RESET;
+        LPC_I2S0->DAI |= 1 << 4;    // I2S_DAI_RESET;
+            // Deassert DAI reset
+        LPC_I2S0->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET;
+        LPC_I2S0->DAI &= ~ ( 1<<4 ); // I2S_DAI_RESET;
+            // Assert DAI stop
+        LPC_I2S0->DAO |= 1 << 3;    // I2S_DAI_STOP;
+        LPC_I2S0->DAI |= 1 << 3;    // I2S_DAI_STOP;
+                
+            // Kill all DMA
+        LPC_I2S0->DMA2 = 0;
+        LPC_I2S0->DMA1 = 0;
+            // Kill all IRQ
+        LPC_I2S0->IRQ = 0;
+            // Kill all clocks
+        LPC_I2S0->RXRATE = 0;
+        LPC_I2S0->TXRATE = 0;
+            // Bit rate must be 0 for slave mode.
+        LPC_I2S0->RXBITRATE = 0;    
+        LPC_I2S0->TXBITRATE = 0;
+            // Clear mode setting
+        LPC_I2S0->TXMODE = 0;
+        LPC_I2S0->RXMODE = 0;
+
+
+            // Configure DA0
+        LPC_I2S0->DAO =
+                3 <<  0 |   // word width, 3:32bit mode        
+                0 <<  2 |   // Mono, 1:mono, 0:stereo
+                1 <<  3 |   // STOP, 1:stop
+                0 <<  4 |   // RESET, 1:reset
+                1 <<  5 |   // WSEL, 1:Slave, 0:Master
+                1 <<  6 ;   // MUTE, 1:mute, 0:normal 
+
+            // Configure DAI
+        LPC_I2S0->DAI =
+                3 <<  0 |   // word width, 3:32bit mode        
+                0 <<  2 |   // Mono, 1:mono, 0:stereo
+                1 <<  3 |   // STOP, 1:stop
+                0 <<  4 |   // RESET, 1:reset
+                1 <<  5 |   // WSEL, 1:Slave, 0:Master
+                31 <<  6;   // WS halfperiod. Not sure what I shoud do when the slave mode.
+                
+            // Configure IRQ At this moment, IRQ is disabled. 
+        LPC_I2S0->IRQ =
+                0 << 0  |   // RX IRQ Enable, 1:Enable, 0:Disable
+                0 << 1  |   // TX IRQ Enable, 1:Enable, 0:Disable
+                2 << 8  |   // RX DEPTH IRQ length for triggering interrupt  
+                0 << 16 ;   // TX DEPTH IRQ length for triggering interrupt
+
+            // Set RX module as slave operation to the external signal
+        LPC_I2S0->RXMODE =
+                0 << 0  |   // RXCLKSEL, 0:SCLK input. The reference manual says this is fractional devider, but in slave mode, it is SCLK.
+                0 << 2  |   // RX4PIN, 1:4pin mode, 0:Clock by RX block itself
+                0 << 3  ;   // RXMCENA, 1:Master clock output, 0:No output
+                
+            // SEt TX module as slave operation to the RX module (4PIN mode )
+        LPC_I2S0->RXMODE =
+                0 << 0  |   // TXCLKSEL, 0:SCLK input. Ignored by 4 pin mode.
+                1 << 2  |   // TX4PIN, 1:4pin mode, 0:Clock by TX block itself
+                0 << 3  ;   // TXMCENA, 1:Master clock output, 0:No output
+
+
+            //  Fill up tx FIO by 3 samples.
+        hal_set_i2s_tx_data( 0 ); // left
+        hal_set_i2s_tx_data( 0 ); // right
+        hal_set_i2s_tx_data( 0 ); // left
+        hal_set_i2s_tx_data( 0 ); // right
+        hal_set_i2s_tx_data( 0 ); // left
+        hal_set_i2s_tx_data( 0 ); // right
+
+    }
+    
+        // Start I2S transfer. Interrupt starts  
+    void hal_i2s_start()
+    {
+            //Clear STOP,RESET and MUTE bit
+        LPC_I2S0->DAO &= ~(1 << 3);    // release I2S_DAO_STOP;
+        LPC_I2S0->DAI &= ~(1 << 3);    // release I2S_DAI_STOP;
+        LPC_I2S0->DAO &= ~(1 << 6);    // release I2S_DAO_MUTE;
+        LPC_I2S0->IRQ |= 1 << 0;       // set I2S RX IRQ enable
+    }
+ 
+    IRQn_Type hal_get_i2s_irq_id()
+    {
+        return I2S0_IRQn;
+    }
+    
+    
+    IRQn_Type hal_get_process_irq_id()
+    {
+        return ( IRQn_Type )30;   // LPC4300's unsed interrupt
+    }
+    
+        // The returned value must be compatible with CMSIS NVIC_SetPriority() API.
+    unsigned int hal_get_lowest_priority_level()
+    {
+        return ( 7 );   // LPC4300 has 3 bits priority field. So, lowest is 7.
+    }
+ 
+        // LPC4337 transferes 2 workd ( left and right ) for each interrupt.
+    unsigned int hal_data_per_sample()
+    {
+        return 2;
+    }
+
+        // return true when the sample parameter is ready to read.
+        // return false when the sample is not ready to read.
+    bool hal_get_i2s_rx_data( int & sample)
+    {
+        sample = LPC_I2S0->RXFIFO;
+            // always return true for LPC4337
+        return ( true );
+    }
+    
+        // put a sample to I2S TX data regisger
+        // return true if the word is transmitted completely.
+        // return false if the word needs another call. In this case, next time same sample will be fed.
+    bool hal_set_i2s_tx_data( int sample )
+    {
+        LPC_I2S0->TXFIFO = sample;
+            // always return true for LPC4337
+        return true;
+    }
+}
+
+