First Publish. Works fine.

Dependents:   unzen_sample_LPC4088_quickstart

Revision:
14:bdf11487a94b
Parent:
3:707608830793
Child:
15:0db847496bb9
--- a/unzen_hal.cpp	Sat May 14 21:37:42 2016 +0000
+++ b/unzen_hal.cpp	Sun May 15 07:00:34 2016 +0000
@@ -8,40 +8,37 @@
         // - clock must be ready
     void hal_i2s_setup(void)
     {
-                // Setup Audio Clock. Feed the core clock (PLL1, 204Mhz) to audio.
-        LPC_CGU->BASE_CLK[CLK_BASE_APLL] = 
-                            0 << 1 |    // Power down. 1:Power Down, 0:Enabled
-                            1 <<11 |    // Enable auto clocking. 1:Enable.
-                            9 <<24 ;    // 9: PLL1
+                // Setup Audio Power
+        LPC_SC->PCONP |=( 1<<27 );     // set PCOMP.I2S
             
             // Assert DAI reset
-        LPC_I2S0->DAO |= 1 << 4;    // I2S_DAI_RESET;
-        LPC_I2S0->DAI |= 1 << 4;    // I2S_DAI_RESET;
+        LPC_I2S->DAO |= 1 << 4;    // I2S_DAI_RESET;
+        LPC_I2S->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;
+        LPC_I2S->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET;
+        LPC_I2S->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;
+        LPC_I2S->DAO |= 1 << 3;    // I2S_DAI_STOP;
+        LPC_I2S->DAI |= 1 << 3;    // I2S_DAI_STOP;
                 
             // Kill all DMA
-        LPC_I2S0->DMA2 = 0;
-        LPC_I2S0->DMA1 = 0;
+        LPC_I2S->DMA2 = 0;
+        LPC_I2S->DMA1 = 0;
             // Kill all IRQ
-        LPC_I2S0->IRQ = 0;
+        LPC_I2S->IRQ = 0;
             // Kill all clocks
-        LPC_I2S0->RXRATE = 0;
-        LPC_I2S0->TXRATE = 0;
+        LPC_I2S->RXRATE = 0;
+        LPC_I2S->TXRATE = 0;
             // Bit rate must be 0 for slave mode.
-        LPC_I2S0->RXBITRATE = 0;    
-        LPC_I2S0->TXBITRATE = 0;
+        LPC_I2S->RXBITRATE = 0;    
+        LPC_I2S->TXBITRATE = 0;
             // Clear mode setting
-        LPC_I2S0->TXMODE = 0;
-        LPC_I2S0->RXMODE = 0;
+        LPC_I2S->TXMODE = 0;
+        LPC_I2S->RXMODE = 0;
 
 
             // Configure DA0
-        LPC_I2S0->DAO =
+        LPC_I2S->DAO =
                 3 <<  0 |   // word width, 3:32bit mode        
                 0 <<  2 |   // Mono, 1:mono, 0:stereo
                 1 <<  3 |   // STOP, 1:stop
@@ -50,7 +47,7 @@
                 1 <<  6 ;   // MUTE, 1:mute, 0:normal 
 
             // Configure DAI
-        LPC_I2S0->DAI =
+        LPC_I2S->DAI =
                 3 <<  0 |   // word width, 3:32bit mode        
                 0 <<  2 |   // Mono, 1:mono, 0:stereo
                 1 <<  3 |   // STOP, 1:stop
@@ -59,20 +56,20 @@
                 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 =
+        LPC_I2S->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 =
+        LPC_I2S->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->TXMODE =
+        LPC_I2S->TXMODE =
                 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
@@ -91,31 +88,82 @@
         // Pin configuration and sync with WS signal
     void hal_i2s_pin_config_and_wait_ws(void)
     {
-            // See UM10503 LPC4300 UM Rev 2.1 section 16.2.3, chapter 19
-            // See https://developer.mbed.org/platforms/LPCXpresso4337/
-            // See mbed src lpc43xx.h http://preview.tinyurl.com/lpc43xxh
+            // See UM10562 LPC408x UM Rev 3 section 7.4.1
+            // See https://developer.mbed.org/platforms/EA-LPC4088/#pinout
+            // See mbed src lpc43xx.h http://preview.tinyurl.com/lpc408xh
+            
+            // P0_4 RS_CLK ( P34 of QS LPC4088 )
+            // P0_5 RX_WS  ( P33 of QS LPC4088 )
+            // P0_6 RX_SDA ( P14 of QS LPC4088 )
+            // P0_9 TX_SDA ( P11 of QS LPC4088 )
             
-            
+        unsigned int reserved_p0_mask; 
+        
             // setup WS pin as GPIO input
-        LPC_SCU->SFSP[6][1] = SCU_MODE_INBUFF_EN;       // P6_1, function 0. GPIO3[0]
+        LPC_IOCON->P0_5 = 
+                    0 << 0 |    // FUNC : GPIO
+                    0 << 3 |    // MODE : No pull up
+                    0 << 5 |    // HYS : No hysterisys
+                    0 << 6 |    // INV : Not invereted input
+                    0 << 9 |    // SLEW : NORMA
+                    0 << 10 ;   // OD : NO Open Drain
+                    
+            // save the mask register of GPIO 0
+        reserved_p0_mask = LPC_GPIO0->MASK;
+        
+            // set the P0_5 as input
+        LPC_GPIO0->DIR &= ~(1<<5);      // GPIO0.DIR.bit5 = 0
+
+            // set the mask register to mask out not relevant bits
+        LPC_GPIO0->MASK = ~ ( 1<<5 );    // only bit 5 is enabled. P0_5 is I2S\RX_WS
         
             // if WS is 1, wait for WS (GPIO3_0) becomes 0
-        while ( LPC_GPIO_PORT->B[3][0] == 1 )
+        while ( LPC_GPIO0->PIN )
             ;
             
             // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1
-        while ( LPC_GPIO_PORT->B[3][0] == 0 )
+        while ( ! LPC_GPIO0->PIN )
             ;
+
+            // restore the mask register of GPIO 0
+        LPC_GPIO0->MASK = reserved_p0_mask;
             
         // Now, we are at the rising edge of WS. 
         // We can setup the I2S without worry of the TX/RX shift.
 
             // setup I2S pin configuration.
-            // for input, bit 6 have to be 1 ( input buffer enable )
-        LPC_SCU->SFSP[3][5] = 5;                        // P3_5, function 5. IS20_TX_SDA
-        LPC_SCU->SFSP[6][0] = 4 | SCU_MODE_INBUFF_EN;   // P6_0, function 4. IS20_RX_SCK
-        LPC_SCU->SFSP[6][1] = 3 | SCU_MODE_INBUFF_EN;   // P6_1, function 3. IS20_RX_WS
-        LPC_SCU->SFSP[3][2] = 1 | SCU_MODE_INBUFF_EN;   // P3_2, function 1. IS20_RX_SDA
+        LPC_IOCON->P0_4 = 
+                    1 << 0 |    // FUNC : I2S_RX_SCK
+                    0 << 3 |    // MODE : No pull up
+                    0 << 5 |    // HYS : No hysterisys
+                    0 << 6 |    // INV : Not invereted input
+                    0 << 9 |    // SLEW : NORMAL
+                    0 << 10 ;   // OD : NO Open Drain
+        LPC_IOCON->P0_5 = 
+                    1 << 0 |    // FUNC : I2S_RX_WS
+                    0 << 3 |    // MODE : No pull up
+                    0 << 5 |    // HYS : No hysterisys
+                    0 << 6 |    // INV : Not invereted input
+                    0 << 9 |    // SLEW : NORMAL
+                    0 << 10 ;   // OD : NO Open Drain
+        LPC_IOCON->P0_6 = 
+                    1 << 0 |    // FUNC : I2S_RX_SDA
+                    0 << 3 |    // MODE : No pull up
+                    0 << 5 |    // HYS : No hysterisys
+                    0 << 6 |    // INV : Not invereted input
+                    0 << 9 |    // SLEW : NORMAL
+                    0 << 10 ;   // OD : NO Open Drain
+        LPC_IOCON->P0_9 = 
+                    1 << 0 |    // FUNC : I2S_TX_SDA
+                    0 << 3 |    // MODE : No pull up
+                    0 << 5 |    // HYS : No hysterisys
+                    0 << 6 |    // INV : Not invereted input
+                    1 << 7 |    // AMODE : 1:Digital mode
+                    1 << 8 |    // FILTER : 1:No filter
+                    0 << 9 |    // SLEW : NORMAL
+                    0 << 10 ;   // OD : NO Open Drain
+                    
+        
     }
 
     
@@ -123,22 +171,22 @@
     void hal_i2s_start(void)
     {
             //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_I2S->DAO &= ~(1 << 3);    // release I2S_DAO_STOP;
+        LPC_I2S->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
+        LPC_I2S->DAO &= ~(1 << 6);    // release I2S_DAO_MUTE;
+        LPC_I2S->IRQ |= 1 << 0;       // set I2S RX IRQ enable
     }
  
     IRQn_Type hal_get_i2s_irq_id(void)
     {
-        return I2S0_IRQn;
+        return I2S_IRQn;
     }
     
     
     IRQn_Type hal_get_process_irq_id(void)
     {
-        return ( IRQn_Type )30;   // LPC4300's unsed interrupt
+        return Reserved0_IRQn;   // LPC4088's unsed interrupt
     }
     
     
@@ -175,13 +223,13 @@
         // return false when the sample is not ready to read.
     void hal_get_i2s_rx_data( int & sample)
     {
-        sample = LPC_I2S0->RXFIFO;
+        sample = LPC_I2S->RXFIFO;
     }
     
         // put a sample to I2S TX data regisger
     void hal_put_i2s_tx_data( int sample )
     {
-        LPC_I2S0->TXFIFO = sample;
+        LPC_I2S->TXFIFO = sample;
     }
 }