First Publish. Works fine.

Dependents:   unzen_sample_nucleo_f746 unzen_delay_sample_nucleo_f746 skeleton_unzen_nucleo_f746 ifmag_noise_canceller ... more

Nucleo F746ZG用のオーディオ・フレームワークです。フレームワーク地震の詳細は『雲仙』オーディオ・フレームワークを参照してください。

参考リンク

  • skeleton_unzen_nucleo_f746 Nucleo F746ZGおよびUI基板を使う場合のスケルトンプログラム。F746を使う方はここから読み始めると良いでしょう。
Revision:
2:6613e62da521
Parent:
1:9710fb328a08
Child:
3:707608830793
--- a/unzen_hal.cpp	Tue Apr 12 05:51:45 2016 +0000
+++ b/unzen_hal.cpp	Tue May 03 01:10:32 2016 +0000
@@ -6,10 +6,14 @@
         // By this HAL, the I2S have to become : 
         // - slave mode
         // - clock must be ready
-        // - pins must be configured.
-        // - Interrupt enable.
-    void hal_i2s_setup()
+    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
+            
             // Assert DAI reset
         LPC_I2S0->DAO |= 1 << 4;    // I2S_DAI_RESET;
         LPC_I2S0->DAI |= 1 << 4;    // I2S_DAI_RESET;
@@ -68,78 +72,112 @@
                 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 =
+        LPC_I2S0->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
 
 
-            //  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
+            //  Fill up tx FIO by 3 stereo samples.
+        hal_put_i2s_tx_data( 0 ); // left
+        hal_put_i2s_tx_data( 0 ); // right
+        hal_put_i2s_tx_data( 0 ); // left
+        hal_put_i2s_tx_data( 0 ); // right
+        hal_put_i2s_tx_data( 0 ); // left
+        hal_put_i2s_tx_data( 0 ); // right
 
     }
     
-    void hal_i2s_pin_config_and_wait_ws()
+        // 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
+            
+            
+            // setup WS pin as GPIO input
+        LPC_SCU->SFSP[6][1] = SCU_MODE_INBUFF_EN;       // P6_1, function 0. GPIO3[0]
         
+            // if WS is 1, wait for WS (GPIO3_0) becomes 0
+        while ( LPC_GPIO_PORT->B[3][0] == 1 )
+            ;
+            
+            // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1
+        while ( LPC_GPIO_PORT->B[3][0] == 0 )
+            ;
+            
+        // 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
     }
 
     
         // Start I2S transfer. Interrupt starts  
-    void hal_i2s_start()
+    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_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()
+    IRQn_Type hal_get_i2s_irq_id(void)
     {
         return I2S0_IRQn;
     }
     
     
-    IRQn_Type hal_get_process_irq_id()
+    IRQn_Type hal_get_process_irq_id(void)
     {
         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()
+    
+         // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2...
+    unsigned int hal_get_i2s_irq_priority_level(void)
     {
-        return ( 7 );   // LPC4300 has 3 bits priority field. So, lowest is 7.
+           // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7.
+           // setting 1 as i2s irq priority allows, some other interrupts are higher 
+           // and some others are lower than i2s irq priority.
+        return 1;
+    }
+
+
+        // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2...
+    unsigned int hal_get_process_irq_priority_level(void)
+    {
+           // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7.
+           // setting 7 as process priority allows, some other interrupts are higher 
+           // and some other interrupts are lower then process priority.
+        return 6;   
     }
  
         // LPC4337 transferes 2 workd ( left and right ) for each interrupt.
-    unsigned int hal_data_per_sample()
+    unsigned int hal_data_per_sample(void)
     {
         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)
+    void 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 )
+    void hal_put_i2s_tx_data( int sample )
     {
         LPC_I2S0->TXFIFO = sample;
-            // always return true for LPC4337
-        return true;
     }
 }