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:
15:76871e578c10
Parent:
14:bdf11487a94b
Child:
16:9db140409038
--- a/unzen_hal.cpp	Sun May 15 07:00:34 2016 +0000
+++ b/unzen_hal.cpp	Sun Jun 05 06:31:00 2016 +0000
@@ -2,77 +2,193 @@
 
 namespace unzen 
 {
+        // for timing control.     
+    volatile unsigned int dummy;
+    
         // Set up I2S peripheral to ready to start.
         // By this HAL, the I2S have to become : 
         // - slave mode
         // - clock must be ready
     void hal_i2s_setup(void)
     {
-                // Setup Audio Power
-        LPC_SC->PCONP |=( 1<<27 );     // set PCOMP.I2S
+            //      STM32F746ZG SAI1 Block A :RX : Slave to the external BCLK/WS
+            //      STM32F746ZG SAI1 Block B :TX : Sync with Block A. 
+            //      See stm32f746xx.h source here : https://developer.mbed.org/teams/Rigado/code/mbed-src-bmd-200/docs/255afbe6270c/stm32f746xx_8h_source.html
+            //      This implementation kills SPI6 interrupt
             
-            // Assert DAI reset
-        LPC_I2S->DAO |= 1 << 4;    // I2S_DAI_RESET;
-        LPC_I2S->DAI |= 1 << 4;    // I2S_DAI_RESET;
-            // Deassert DAI reset
-        LPC_I2S->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET;
-        LPC_I2S->DAI &= ~ ( 1<<4 ); // I2S_DAI_RESET;
-            // Assert DAI stop
-        LPC_I2S->DAO |= 1 << 3;    // I2S_DAI_STOP;
-        LPC_I2S->DAI |= 1 << 3;    // I2S_DAI_STOP;
+                // Setup PLL
+                // RCC_PLLCFGR : Has PLLM ( Division Factor M )
+                // RCC_CIR : PLL clock interrupt register
                 
-            // Kill all DMA
-        LPC_I2S->DMA2 = 0;
-        LPC_I2S->DMA1 = 0;
-            // Kill all IRQ
-        LPC_I2S->IRQ = 0;
-            // Kill all clocks
-        LPC_I2S->RXRATE = 0;
-        LPC_I2S->TXRATE = 0;
-            // Bit rate must be 0 for slave mode.
-        LPC_I2S->RXBITRATE = 0;    
-        LPC_I2S->TXBITRATE = 0;
-            // Clear mode setting
-        LPC_I2S->TXMODE = 0;
-        LPC_I2S->RXMODE = 0;
+                // RCC_PLLSAICFGR : PLLSAI configuration register. mbed set the pre-devider as 8. So, PLL input is 1MHz
+                // The VCO have to be more than 100Mhaz. So, set it 192MHz.
+        RCC->PLLSAICFGR = 
+            4 << 28 |   // PLLSAIR : 4 is dividing by 4 for LCD clock ( 48Mhz )
+            4 << 24 |   // PLLSAIQ : 4 is dividing by 4 for SAI clock ( 48Mhz )
+            1 << 16 |   // PLLSAIR : 1 is dividing by 4 for USB clock ( 48Mhz )
+            192 << 6 ;   // PLLSAIN : 192 is dividing by 192 for vco freq ( 192Mhz )
 
+                // RCC_CR : Starting/Status of PLLSAI
+        RCC->CR |= (1 << 28);     // PLL SAI On
+                // wait while PLL SAI is not ready
+        while ( !( RCC->CR & ( 1<<29 ) ) )
+            ;
+
+                // RCC_CFGR
+                // RCC_DKCFGR1 : RCC Dedicated clocks configuration register
+                // clear the relevant field
+        RCC->DCKCFGR1 &= ~ (
+            3 << 20 |       // SAI1 SEL
+            31 << 8 );      // PLLSAIDIVQ
+                // set the value
+        RCC->DCKCFGR1 |= 
+            0 << 20 |       // SAI1 SEL   : 0, PLLSAI
+            0 << 8 ;        // PLLSAIDIVQ : 0, div by 1
 
-            // Configure DA0
-        LPC_I2S->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_I2S->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.
+                // RCC_APB2ENR : APB2 peripherals clock enable register
+        RCC->APB2ENR |= ( 1 << 22);     // SAI1 enable
+                    
+                // RCC_AHB1ENR : AHB1 peripherals clock enable register
+        RCC->AHB1ENR |= 1<<4;           // GPIOE enable
+                    
+                // Control the stability timing. The STM32F746 reference manual requires
+                // to wait 2 peripheral cylecs, after enabling its clock. 
+                // See chapter 5.2.12
+                // Two guarantee the 2 peripheral cyucles, reading status register twice.
+        dummy = RCC->CR;
+        dummy = RCC->CR;
+                    
+                // RCC_APB2RSTR : APB2 peripherals reset register
+        RCC->APB2RSTR |= ( 1 << 22);     // SAI1 reset
+        RCC->APB2RSTR &= ~( 1 << 22);     // SAI1 reset release
+        
+            
+/*
+RCC_CR         :03078483
+RCC_PLLCFGR    :29406c08
+RCC_CFGR       :0000940a
+RCC_CIR        :00000000
+RCC_APB2RSTR   :00000000
+RCC_CR         :03078483
+RCC_PLLSAICFGR :24003000
+*/
+        
+            // Setup Global Configuraion Register
+        SAI1->GCR = 
+                0 << 0 |    // syncin : ingnored because none of the block is external synch from outside of SAI module 
+                0 << 4 ;    // syncout : 0 : No sync output for other SAI. 1,Block A(RX) is used for input of otehr block
+            
+            // Setup SAI Block configuration register.
+            // Block A : RX
+            // Block B : TX
+        SAI1_Block_A->CR1 = 
+                0 << 20 |   // MCKDIV   : Meaningless because the block is slave mode.
+                0 << 19 |   // NODIV    : Master clock divider is enabled ( perhaps, meaningless in slave mode )
+                0 << 17 |   // DMAEN    : 0, DMA disanble, 1: DMA Enable
+                0 << 16 |   // SAIXEN   : 0, Disable, 1, Enable. Disable at this moment
+                0 << 13 |   // OUTDRIV  : 0, Audio is driven only when SAIXEN is 1. 1, Audio is driven
+                0 << 12 |   // MONO     : 0, Stereo. 1, Mono
+                0 << 10 |   // SYNCEN   : 0, Async mode. The Async mode referes the outside sync signal in slave mode. 
+                0 << 9  |   // CKSTR    : 0, sample by falling edge, 1, sample by rising edge. I2S is sample by falling edge
+                0 << 8  |   // LSBFIRST : 0, MSB first. 1, LSB first. I2S is MSB first
+                7 << 5 |    // DS       : 7, 32bit. 
+                0 << 2 |    // PRTCFG   : 0, Free protocol, 1, SPDIF, 2, AC97. I2S is Free protocol
+                3 << 0 ;    // MODE     : 0, master tx. 1, master rx. 2, slave tx. 3, slave rx
+                
+            // configuration register 2
+        SAI1_Block_A->CR2 = 
+                0 << 14 |   // COMP     : 0, No companding
+                0 << 13 |   // CPL      : Ignoered when no companding
+                0 << 7 |    // MUTECNT  : 0, ignored when no muting
+                0 << 6 |    // MUTEVAL  : 0, meaningless except SPDIF mode
+                0 << 5 |    // MUTE     : 0, No mute. 1, mute
+                0 << 4 |    // TRIS     : 0, Drive all slot. 1, Drive only active slot. Meaningless for I2S and RX
+                1 << 3 |    // FFLUSH   : 0, No FIFO Flush. 1, FIFO Flush
+                1 << 0;     // FTH      : 0, FIFO empty. 1, 1/4 FIFO. 2, 1/2 FIFO. 3, 3/4 FIFO. 4, FIFO full
+                
+            // Frame configuration register
+        SAI1_Block_A->FRCR =
+                1 << 18 |   // FSOFF    : 0, FS is asserted on the first bit. 1, FS is asserted before the first bit.
+                0 << 17 |   // FSPOL    : 0, Active low. 1, active high. I2S in left first operation is actilve low FS.
+                1 << 16 |   // FSDEF    : 0, FS is start frame signal. 1, FS has also channel side info. I2S have to set 1
+                31 << 8 |   // FSALL    : Frame sync active level lenght. Seems to be meaningless in slave mode. Set as to be sure.
+                63 << 0 ;   // FRL      : Frame length. Seems to be meaning less in slave mode. Set as to be sure. 
                 
-            // Configure IRQ At this moment, IRQ is disabled. 
-        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_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
+            // Slot register
+        SAI1_Block_A->SLOTR = 
+                0xFFFF << 16 |   // SLOTEN   : bit mask to specify the active slot. In I2S, 2 slts are active.
+                1 << 8 |    // NBSLOT   : Number of slots - 1 ( Ref manual seems to be wrong )
+                0 << 6 |    // SLOTSZ   : 0, same with data size. 1, 16bit. 2, 32bit
+                0 << 0 ;    // FBOFF    : The manual is not clear. Perhaps, 0 is OK.
+                
+            // interrupt mask. Only FIFO interrupt is allowed.
+        SAI1_Block_A->IMR = 
+                0 << 6 |    // LFSDETIE : Late frame synchronization detection interrupt enable
+                0 << 5 |    // AFSDETIE : Anticipated frame synchronization detection interrupt enable. AC97 only
+                0 << 4 |    // CNDYIE   : CODEC nott ready interrupt. AC97 only
+                1 << 3 |    // FREQIE   : FIFO Interrupt Request. Enable for RX
+                0 << 2 |    // WCKCFGIE : Wrong clock configuration interrupt enable. 
+                0 << 1 |    // MUTEDETIE: Mute detection interrupt enable. 
+                0 << 0;     // OVRUDRIE : Overrun/underrun interrupt enable          
+            
+            // Clear flag register
+        SAI1_Block_A->CLRFR = 0xFFFFFFFF;       // clear all flags
+        
+            // Setup SAI Block configuration register.
+            // Block A : RX
+            // Block B : TX
+        SAI1_Block_B->CR1 = 
+                0 << 20 |   // MCKDIV   : Meaningless because the block is slave mode.
+                0 << 19 |   // NODIV    : Master clock divider is enabled ( perhaps, meaningless in slave mode )
+                0 << 17 |   // DMAEN    : 0, DMA disanble, 1: DMA Enable
+                0 << 16 |   // SAIXEN   : 0, Disable, 1, Enable. Disable at this moment
+                0 << 13 |   // OUTDRIV  : 0, Audio is driven only when SAIXEN is 1. 1, Audio is driven
+                0 << 12 |   // MONO     : 0, Stereo. 1, Mono
+                1 << 10 |   // SYNCEN   : 1, sync with internal audio block. 
+                0 << 9  |   // CKSTR    : 0, sample by falling edge, 1, sample by rising edge. I2S is sample by falling edge
+                0 << 8  |   // LSBFIRST : 0, MSB first. 1, LSB first. I2S is MSB first
+                7 << 5 |    // DS       : 7, 32bit. 
+                0 << 2 |    // PRTCFG   : 0, Free protocol, 1, SPDIF, 2, AC97. I2S is Free protocol
+                2 << 0 ;    // MODE     : 0, master tx. 1, master rx. 2, slave tx. 3, slave rx
                 
-            // SEt TX module as slave operation to the RX module (4PIN mode )
-        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
+            // configuration register 2
+        SAI1_Block_B->CR2 = 
+                0 << 14 |   // COMP     : 0, No companding
+                0 << 13 |   // CPL      : Ignoered when no companding
+                0 << 7 |    // MUTECNT  : 0, ignored when no muting
+                0 << 6 |    // MUTEVAL  : 0, meaningless except SPDIF mode
+                0 << 5 |    // MUTE     : 0, No mute. 1, mute
+                0 << 4 |    // TRIS     : 0, Drive all slot. 1, Drive only active slot. Meaningless for I2S and RX
+                1 << 3 |    // FFLUSH   : 0, No FIFO Flush. 1, FIFO Flush
+                1 << 0;     // FTH      : 0, FIFO empty. 1, 1/4 FIFO. 2, 1/2 FIFO. 3, 3/4 FIFO. 4, FIFO full
+                
+            // Frame configuration register
+        SAI1_Block_B->FRCR =
+                1 << 18 |   // FSOFF    : 0, FS is asserted on the first bit. 1, FS is asserted before the first bit.
+                0 << 17 |   // FSPOL    : 0, Active low. 1, active high. I2S in left first operation is actilve low FS.
+                1 << 16 |   // FSDEF    : 0, FS is start frame signal. 1, FS has also channel side info. I2S have to set 1
+                31 << 8 |   // FSALL    : Frame sync active level lenght. Seems to be meaningless in slave mode. Set as to be sure.
+                63 << 0 ;   // FRL      : Frame length. Seems to be meaning less in slave mode. Set as to be sure. 
+                
+            // Slot register
+        SAI1_Block_B->SLOTR = 
+                0xFFFF << 16 |   // SLOTEN   : bit mask to specify the active slot. In I2S, 2 slts are active.
+                1 << 8 |    // NBSLOT   : Number of slots - 1 ( Ref manual seems to be wrong )
+                0 << 6 |    // SLOTSZ   : 0, same with data size. 1, 16bit. 2, 32bit
+                0 << 0 ;    // FBOFF    : The manual is not clear. Perhaps, 0 is OK.
+                
+            // interrupt mask : TX doesn't trigger interrupt
+        SAI1_Block_B->IMR = 
+                0 << 6 |    // LFSDETIE : Late frame synchronization detection interrupt enable
+                0 << 5 |    // AFSDETIE : Anticipated frame synchronization detection interrupt enable. AC97 only
+                0 << 4 |    // CNDYIE   : CODEC nott ready interrupt. AC97 only
+                0 << 3 |    // FREQIE   : FIFO Interrupt Request. Enable for RX
+                0 << 2 |    // WCKCFGIE : Wrong clock configuration interrupt enable. 
+                0 << 1 |    // MUTEDETIE: Mute detection interrupt enable. 
+                0 << 0;     // OVRUDRIE : Overrun/underrun interrupt enable          
+            
+            // Clear flag register
+        SAI1_Block_B->CLRFR = 0xFFFFFFFF;       // clear all flags
 
 
             //  Fill up tx FIO by 3 stereo samples.
@@ -88,132 +204,132 @@
         // Pin configuration and sync with WS signal
     void hal_i2s_pin_config_and_wait_ws(void)
     {
-            // 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
+            // See DM00166116.pdf ST32F746ZG Datasheet Rev 4 Table 12
+            // See https://developer.mbed.org/platforms/ST-Nucleo-F746ZG/
+            // See stm32f746xx.h source here : https://developer.mbed.org/teams/Rigado/code/mbed-src-bmd-200/docs/255afbe6270c/stm32f746xx_8h_source.html
             
-            // 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 )
+            // PE3  SAI1_SD_B   (AF6) : DAC
+            // PE4  SAI1_FS_A   (AF6) : WS
+            // PE5  SAI1_SCK_A  (AF6) : CLK
+            // PE6  SAI1_SD_A   (AF6) : ADC
             
-        unsigned int reserved_p0_mask; 
-        
-            // setup WS pin as GPIO input
-        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
+            // Clear the mode field of PE3-6
+        GPIOE->MODER &=
+            ~(  3 << 6 |    // PE3
+                3 << 8 |    // PE4
+                3 << 10 |   // PE5
+                3 << 12 );  // PE6 
 
-            // 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_GPIO0->PIN )
-            ;
-            
-            // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1
-        while ( ! LPC_GPIO0->PIN )
-            ;
+            // Set the pin mode
+        GPIOE->MODER |=
+                2 << 6 |    // PE3 is Alternate Function
+                0 << 8 |    // PE4 is input
+                0 << 10 |   // PE5 is input
+                0 << 12;    // PE6 is input
+
+
+            // Clear the OTYPE field of PE3-6  ( Clear is push-pull )
+        GPIOE->OTYPER &=
+            ~(  1 << 3 |    // PE3
+                1 << 4 |    // PE4
+                1 << 5 |    // PE5
+                1 << 6 );   // PE6 
+
 
-            // 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.
+            // Clear the OSPEEDR field of PE3-6
+        GPIOE->OSPEEDR &=
+            ~(  3 << 6 |    // PE3
+                3 << 8 |    // PE4
+                3 << 10 |   // PE5
+                3 << 12 );  // PE6 
+
+            // Set the OSPEEDR
+        GPIOE->OSPEEDR |=
+                1 << 6 |    // PE3 DAC is medium speed
+                0 << 8 |    // PE4 is input
+                0 << 10 |   // PE5 is input
+                0 << 12;    // PE6 is input
+
 
-            // setup I2S pin configuration.
-        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
-                    
-        
+            // Clear the PUPDR field of PE3-6 ( Clear is no pull-up/no pull-down )
+        GPIOE->PUPDR &=
+            ~(  3 << 6 |    // PE3
+                3 << 8 |    // PE4
+                3 << 10 |   // PE5
+                3 << 12 );  // PE6 
+
+
+            // Clear the Alternate funciton of PE3-6 
+        GPIOE->AFR[0] &=
+            ~(  0xF << 12 | // PE3
+                0xF << 16 | // PE4
+                0xF << 20 | // PE5
+                0xF << 24 );// PE6 
+
+            // Set the Alternate function of PE3-6 
+        GPIOE->AFR[0] |=
+                6 << 12 |   // PE3  Alternalte Funciton 6
+                6 << 16 |   // PE4  Alternalte Funciton 6
+                6 << 20 |   // PE5  Alternalte Funciton 6
+                6 << 24 ;   // PE6  Alternalte Funciton 6
+
+        // Now, we set all the pin. We don't need to wait the WS, 
+        // Because SAI has TX/RX sync.
     }
 
     
         // Start I2S transfer. Interrupt starts  
     void hal_i2s_start(void)
     {
-            //Clear STOP,RESET and MUTE bit
-        LPC_I2S->DAO &= ~(1 << 3);    // release I2S_DAO_STOP;
-        LPC_I2S->DAI &= ~(1 << 3);    // release I2S_DAI_STOP;
-        
-        LPC_I2S->DAO &= ~(1 << 6);    // release I2S_DAO_MUTE;
-        LPC_I2S->IRQ |= 1 << 0;       // set I2S RX IRQ enable
+            // Setup SAI Block configuration register.
+            // Block A : RX
+            // Block B : TX
+            
+            // Block B is sync to Block A. So, Block B first.
+        SAI1_Block_B->CR1 |= 
+            1 << 16 ;   // SAIXEN   : 0, Disable, 1, Enable. Disable at this moment
+            // Now, Block A and B start together
+        SAI1_Block_A->CR1 |= 
+            1 << 16 ;   // SAIXEN   : 0, Disable, 1, Enable. Disable at this moment
+
     }
  
     IRQn_Type hal_get_i2s_irq_id(void)
     {
-        return I2S_IRQn;
+        return SAI1_IRQn;
     }
     
     
     IRQn_Type hal_get_process_irq_id(void)
     {
-        return Reserved0_IRQn;   // LPC4088's unsed interrupt
+        return SPI6_IRQn;   // STM32F746 SPI6 is killed. This interrupt is assigned for signal processing in Unzen
     }
     
     
          // 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)
     {
-           // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7.
+           // STM32F746 has 4 bits priority field. So, heighest is 0, lowest is 15.
            // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( F**k! )
-           // So, 7 is heighest, 0 is lowerest in CMSIS.
-           // setting 6 as i2s irq priority allows, some other interrupts are higher 
+           // Then, 15 is heighest, 0 is lowerest in CMSIS.
+           // setting 12 as i2s irq priority allows, some other interrupts are higher 
            // and some others are lower than i2s irq priority.
-        return 6;
+        return 12;
     }
 
 
         // 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.
+           // STM32F746 has 4 bits priority field. So, heighest is 0, lowest is 15.
            // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( S**t! )
-           // So, 7 is heighest, 0 is lowerest in CMSIS.
-           // setting 1 as process priority allows, some other interrupts are higher 
+           // Then 15 is heighest, 0 is lowerest in CMSIS.
+           // setting 4 as process priority allows, some other interrupts are higher 
            // and some other interrupts are lower then process priority.
-        return 1;   
+        return 4;   
     }
  
-        // LPC4337 transferes 2 workd ( left and right ) for each interrupt.
+        // STM32F746 transferes 2 words ( left and right ) for each interrupt.
     unsigned int hal_data_per_sample(void)
     {
         return 2;
@@ -223,13 +339,15 @@
         // return false when the sample is not ready to read.
     void hal_get_i2s_rx_data( int & sample)
     {
-        sample = LPC_I2S->RXFIFO;
+            // RX is SAI1_BlockA. See the comment on top of this file
+        sample = SAI1_Block_A->DR;
     }
     
         // put a sample to I2S TX data regisger
     void hal_put_i2s_tx_data( int sample )
     {
-        LPC_I2S->TXFIFO = sample;
+            // TX is SAI1_Block_B. See the comment on top of this file
+        SAI1_Block_B->DR = sample;
     }
 }