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を使う方はここから読み始めると良いでしょう。
unzen_hal.cpp@15:76871e578c10, 2016-06-05 (annotated)
- Committer:
- shorie
- Date:
- Sun Jun 05 06:31:00 2016 +0000
- Revision:
- 15:76871e578c10
- Parent:
- 14:bdf11487a94b
- Child:
- 16:9db140409038
Under development
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
shorie | 0:5ac19c994288 | 1 | #include "unzen_hal.h" |
shorie | 0:5ac19c994288 | 2 | |
shorie | 0:5ac19c994288 | 3 | namespace unzen |
shorie | 0:5ac19c994288 | 4 | { |
shorie | 15:76871e578c10 | 5 | // for timing control. |
shorie | 15:76871e578c10 | 6 | volatile unsigned int dummy; |
shorie | 15:76871e578c10 | 7 | |
shorie | 0:5ac19c994288 | 8 | // Set up I2S peripheral to ready to start. |
shorie | 0:5ac19c994288 | 9 | // By this HAL, the I2S have to become : |
shorie | 0:5ac19c994288 | 10 | // - slave mode |
shorie | 0:5ac19c994288 | 11 | // - clock must be ready |
shorie | 2:6613e62da521 | 12 | void hal_i2s_setup(void) |
shorie | 0:5ac19c994288 | 13 | { |
shorie | 15:76871e578c10 | 14 | // STM32F746ZG SAI1 Block A :RX : Slave to the external BCLK/WS |
shorie | 15:76871e578c10 | 15 | // STM32F746ZG SAI1 Block B :TX : Sync with Block A. |
shorie | 15:76871e578c10 | 16 | // See stm32f746xx.h source here : https://developer.mbed.org/teams/Rigado/code/mbed-src-bmd-200/docs/255afbe6270c/stm32f746xx_8h_source.html |
shorie | 15:76871e578c10 | 17 | // This implementation kills SPI6 interrupt |
shorie | 2:6613e62da521 | 18 | |
shorie | 15:76871e578c10 | 19 | // Setup PLL |
shorie | 15:76871e578c10 | 20 | // RCC_PLLCFGR : Has PLLM ( Division Factor M ) |
shorie | 15:76871e578c10 | 21 | // RCC_CIR : PLL clock interrupt register |
shorie | 0:5ac19c994288 | 22 | |
shorie | 15:76871e578c10 | 23 | // RCC_PLLSAICFGR : PLLSAI configuration register. mbed set the pre-devider as 8. So, PLL input is 1MHz |
shorie | 15:76871e578c10 | 24 | // The VCO have to be more than 100Mhaz. So, set it 192MHz. |
shorie | 15:76871e578c10 | 25 | RCC->PLLSAICFGR = |
shorie | 15:76871e578c10 | 26 | 4 << 28 | // PLLSAIR : 4 is dividing by 4 for LCD clock ( 48Mhz ) |
shorie | 15:76871e578c10 | 27 | 4 << 24 | // PLLSAIQ : 4 is dividing by 4 for SAI clock ( 48Mhz ) |
shorie | 15:76871e578c10 | 28 | 1 << 16 | // PLLSAIR : 1 is dividing by 4 for USB clock ( 48Mhz ) |
shorie | 15:76871e578c10 | 29 | 192 << 6 ; // PLLSAIN : 192 is dividing by 192 for vco freq ( 192Mhz ) |
shorie | 0:5ac19c994288 | 30 | |
shorie | 15:76871e578c10 | 31 | // RCC_CR : Starting/Status of PLLSAI |
shorie | 15:76871e578c10 | 32 | RCC->CR |= (1 << 28); // PLL SAI On |
shorie | 15:76871e578c10 | 33 | // wait while PLL SAI is not ready |
shorie | 15:76871e578c10 | 34 | while ( !( RCC->CR & ( 1<<29 ) ) ) |
shorie | 15:76871e578c10 | 35 | ; |
shorie | 15:76871e578c10 | 36 | |
shorie | 15:76871e578c10 | 37 | // RCC_CFGR |
shorie | 15:76871e578c10 | 38 | // RCC_DKCFGR1 : RCC Dedicated clocks configuration register |
shorie | 15:76871e578c10 | 39 | // clear the relevant field |
shorie | 15:76871e578c10 | 40 | RCC->DCKCFGR1 &= ~ ( |
shorie | 15:76871e578c10 | 41 | 3 << 20 | // SAI1 SEL |
shorie | 15:76871e578c10 | 42 | 31 << 8 ); // PLLSAIDIVQ |
shorie | 15:76871e578c10 | 43 | // set the value |
shorie | 15:76871e578c10 | 44 | RCC->DCKCFGR1 |= |
shorie | 15:76871e578c10 | 45 | 0 << 20 | // SAI1 SEL : 0, PLLSAI |
shorie | 15:76871e578c10 | 46 | 0 << 8 ; // PLLSAIDIVQ : 0, div by 1 |
shorie | 0:5ac19c994288 | 47 | |
shorie | 15:76871e578c10 | 48 | // RCC_APB2ENR : APB2 peripherals clock enable register |
shorie | 15:76871e578c10 | 49 | RCC->APB2ENR |= ( 1 << 22); // SAI1 enable |
shorie | 15:76871e578c10 | 50 | |
shorie | 15:76871e578c10 | 51 | // RCC_AHB1ENR : AHB1 peripherals clock enable register |
shorie | 15:76871e578c10 | 52 | RCC->AHB1ENR |= 1<<4; // GPIOE enable |
shorie | 15:76871e578c10 | 53 | |
shorie | 15:76871e578c10 | 54 | // Control the stability timing. The STM32F746 reference manual requires |
shorie | 15:76871e578c10 | 55 | // to wait 2 peripheral cylecs, after enabling its clock. |
shorie | 15:76871e578c10 | 56 | // See chapter 5.2.12 |
shorie | 15:76871e578c10 | 57 | // Two guarantee the 2 peripheral cyucles, reading status register twice. |
shorie | 15:76871e578c10 | 58 | dummy = RCC->CR; |
shorie | 15:76871e578c10 | 59 | dummy = RCC->CR; |
shorie | 15:76871e578c10 | 60 | |
shorie | 15:76871e578c10 | 61 | // RCC_APB2RSTR : APB2 peripherals reset register |
shorie | 15:76871e578c10 | 62 | RCC->APB2RSTR |= ( 1 << 22); // SAI1 reset |
shorie | 15:76871e578c10 | 63 | RCC->APB2RSTR &= ~( 1 << 22); // SAI1 reset release |
shorie | 15:76871e578c10 | 64 | |
shorie | 15:76871e578c10 | 65 | |
shorie | 15:76871e578c10 | 66 | /* |
shorie | 15:76871e578c10 | 67 | RCC_CR :03078483 |
shorie | 15:76871e578c10 | 68 | RCC_PLLCFGR :29406c08 |
shorie | 15:76871e578c10 | 69 | RCC_CFGR :0000940a |
shorie | 15:76871e578c10 | 70 | RCC_CIR :00000000 |
shorie | 15:76871e578c10 | 71 | RCC_APB2RSTR :00000000 |
shorie | 15:76871e578c10 | 72 | RCC_CR :03078483 |
shorie | 15:76871e578c10 | 73 | RCC_PLLSAICFGR :24003000 |
shorie | 15:76871e578c10 | 74 | */ |
shorie | 15:76871e578c10 | 75 | |
shorie | 15:76871e578c10 | 76 | // Setup Global Configuraion Register |
shorie | 15:76871e578c10 | 77 | SAI1->GCR = |
shorie | 15:76871e578c10 | 78 | 0 << 0 | // syncin : ingnored because none of the block is external synch from outside of SAI module |
shorie | 15:76871e578c10 | 79 | 0 << 4 ; // syncout : 0 : No sync output for other SAI. 1,Block A(RX) is used for input of otehr block |
shorie | 15:76871e578c10 | 80 | |
shorie | 15:76871e578c10 | 81 | // Setup SAI Block configuration register. |
shorie | 15:76871e578c10 | 82 | // Block A : RX |
shorie | 15:76871e578c10 | 83 | // Block B : TX |
shorie | 15:76871e578c10 | 84 | SAI1_Block_A->CR1 = |
shorie | 15:76871e578c10 | 85 | 0 << 20 | // MCKDIV : Meaningless because the block is slave mode. |
shorie | 15:76871e578c10 | 86 | 0 << 19 | // NODIV : Master clock divider is enabled ( perhaps, meaningless in slave mode ) |
shorie | 15:76871e578c10 | 87 | 0 << 17 | // DMAEN : 0, DMA disanble, 1: DMA Enable |
shorie | 15:76871e578c10 | 88 | 0 << 16 | // SAIXEN : 0, Disable, 1, Enable. Disable at this moment |
shorie | 15:76871e578c10 | 89 | 0 << 13 | // OUTDRIV : 0, Audio is driven only when SAIXEN is 1. 1, Audio is driven |
shorie | 15:76871e578c10 | 90 | 0 << 12 | // MONO : 0, Stereo. 1, Mono |
shorie | 15:76871e578c10 | 91 | 0 << 10 | // SYNCEN : 0, Async mode. The Async mode referes the outside sync signal in slave mode. |
shorie | 15:76871e578c10 | 92 | 0 << 9 | // CKSTR : 0, sample by falling edge, 1, sample by rising edge. I2S is sample by falling edge |
shorie | 15:76871e578c10 | 93 | 0 << 8 | // LSBFIRST : 0, MSB first. 1, LSB first. I2S is MSB first |
shorie | 15:76871e578c10 | 94 | 7 << 5 | // DS : 7, 32bit. |
shorie | 15:76871e578c10 | 95 | 0 << 2 | // PRTCFG : 0, Free protocol, 1, SPDIF, 2, AC97. I2S is Free protocol |
shorie | 15:76871e578c10 | 96 | 3 << 0 ; // MODE : 0, master tx. 1, master rx. 2, slave tx. 3, slave rx |
shorie | 15:76871e578c10 | 97 | |
shorie | 15:76871e578c10 | 98 | // configuration register 2 |
shorie | 15:76871e578c10 | 99 | SAI1_Block_A->CR2 = |
shorie | 15:76871e578c10 | 100 | 0 << 14 | // COMP : 0, No companding |
shorie | 15:76871e578c10 | 101 | 0 << 13 | // CPL : Ignoered when no companding |
shorie | 15:76871e578c10 | 102 | 0 << 7 | // MUTECNT : 0, ignored when no muting |
shorie | 15:76871e578c10 | 103 | 0 << 6 | // MUTEVAL : 0, meaningless except SPDIF mode |
shorie | 15:76871e578c10 | 104 | 0 << 5 | // MUTE : 0, No mute. 1, mute |
shorie | 15:76871e578c10 | 105 | 0 << 4 | // TRIS : 0, Drive all slot. 1, Drive only active slot. Meaningless for I2S and RX |
shorie | 15:76871e578c10 | 106 | 1 << 3 | // FFLUSH : 0, No FIFO Flush. 1, FIFO Flush |
shorie | 15:76871e578c10 | 107 | 1 << 0; // FTH : 0, FIFO empty. 1, 1/4 FIFO. 2, 1/2 FIFO. 3, 3/4 FIFO. 4, FIFO full |
shorie | 15:76871e578c10 | 108 | |
shorie | 15:76871e578c10 | 109 | // Frame configuration register |
shorie | 15:76871e578c10 | 110 | SAI1_Block_A->FRCR = |
shorie | 15:76871e578c10 | 111 | 1 << 18 | // FSOFF : 0, FS is asserted on the first bit. 1, FS is asserted before the first bit. |
shorie | 15:76871e578c10 | 112 | 0 << 17 | // FSPOL : 0, Active low. 1, active high. I2S in left first operation is actilve low FS. |
shorie | 15:76871e578c10 | 113 | 1 << 16 | // FSDEF : 0, FS is start frame signal. 1, FS has also channel side info. I2S have to set 1 |
shorie | 15:76871e578c10 | 114 | 31 << 8 | // FSALL : Frame sync active level lenght. Seems to be meaningless in slave mode. Set as to be sure. |
shorie | 15:76871e578c10 | 115 | 63 << 0 ; // FRL : Frame length. Seems to be meaning less in slave mode. Set as to be sure. |
shorie | 0:5ac19c994288 | 116 | |
shorie | 15:76871e578c10 | 117 | // Slot register |
shorie | 15:76871e578c10 | 118 | SAI1_Block_A->SLOTR = |
shorie | 15:76871e578c10 | 119 | 0xFFFF << 16 | // SLOTEN : bit mask to specify the active slot. In I2S, 2 slts are active. |
shorie | 15:76871e578c10 | 120 | 1 << 8 | // NBSLOT : Number of slots - 1 ( Ref manual seems to be wrong ) |
shorie | 15:76871e578c10 | 121 | 0 << 6 | // SLOTSZ : 0, same with data size. 1, 16bit. 2, 32bit |
shorie | 15:76871e578c10 | 122 | 0 << 0 ; // FBOFF : The manual is not clear. Perhaps, 0 is OK. |
shorie | 15:76871e578c10 | 123 | |
shorie | 15:76871e578c10 | 124 | // interrupt mask. Only FIFO interrupt is allowed. |
shorie | 15:76871e578c10 | 125 | SAI1_Block_A->IMR = |
shorie | 15:76871e578c10 | 126 | 0 << 6 | // LFSDETIE : Late frame synchronization detection interrupt enable |
shorie | 15:76871e578c10 | 127 | 0 << 5 | // AFSDETIE : Anticipated frame synchronization detection interrupt enable. AC97 only |
shorie | 15:76871e578c10 | 128 | 0 << 4 | // CNDYIE : CODEC nott ready interrupt. AC97 only |
shorie | 15:76871e578c10 | 129 | 1 << 3 | // FREQIE : FIFO Interrupt Request. Enable for RX |
shorie | 15:76871e578c10 | 130 | 0 << 2 | // WCKCFGIE : Wrong clock configuration interrupt enable. |
shorie | 15:76871e578c10 | 131 | 0 << 1 | // MUTEDETIE: Mute detection interrupt enable. |
shorie | 15:76871e578c10 | 132 | 0 << 0; // OVRUDRIE : Overrun/underrun interrupt enable |
shorie | 15:76871e578c10 | 133 | |
shorie | 15:76871e578c10 | 134 | // Clear flag register |
shorie | 15:76871e578c10 | 135 | SAI1_Block_A->CLRFR = 0xFFFFFFFF; // clear all flags |
shorie | 15:76871e578c10 | 136 | |
shorie | 15:76871e578c10 | 137 | // Setup SAI Block configuration register. |
shorie | 15:76871e578c10 | 138 | // Block A : RX |
shorie | 15:76871e578c10 | 139 | // Block B : TX |
shorie | 15:76871e578c10 | 140 | SAI1_Block_B->CR1 = |
shorie | 15:76871e578c10 | 141 | 0 << 20 | // MCKDIV : Meaningless because the block is slave mode. |
shorie | 15:76871e578c10 | 142 | 0 << 19 | // NODIV : Master clock divider is enabled ( perhaps, meaningless in slave mode ) |
shorie | 15:76871e578c10 | 143 | 0 << 17 | // DMAEN : 0, DMA disanble, 1: DMA Enable |
shorie | 15:76871e578c10 | 144 | 0 << 16 | // SAIXEN : 0, Disable, 1, Enable. Disable at this moment |
shorie | 15:76871e578c10 | 145 | 0 << 13 | // OUTDRIV : 0, Audio is driven only when SAIXEN is 1. 1, Audio is driven |
shorie | 15:76871e578c10 | 146 | 0 << 12 | // MONO : 0, Stereo. 1, Mono |
shorie | 15:76871e578c10 | 147 | 1 << 10 | // SYNCEN : 1, sync with internal audio block. |
shorie | 15:76871e578c10 | 148 | 0 << 9 | // CKSTR : 0, sample by falling edge, 1, sample by rising edge. I2S is sample by falling edge |
shorie | 15:76871e578c10 | 149 | 0 << 8 | // LSBFIRST : 0, MSB first. 1, LSB first. I2S is MSB first |
shorie | 15:76871e578c10 | 150 | 7 << 5 | // DS : 7, 32bit. |
shorie | 15:76871e578c10 | 151 | 0 << 2 | // PRTCFG : 0, Free protocol, 1, SPDIF, 2, AC97. I2S is Free protocol |
shorie | 15:76871e578c10 | 152 | 2 << 0 ; // MODE : 0, master tx. 1, master rx. 2, slave tx. 3, slave rx |
shorie | 0:5ac19c994288 | 153 | |
shorie | 15:76871e578c10 | 154 | // configuration register 2 |
shorie | 15:76871e578c10 | 155 | SAI1_Block_B->CR2 = |
shorie | 15:76871e578c10 | 156 | 0 << 14 | // COMP : 0, No companding |
shorie | 15:76871e578c10 | 157 | 0 << 13 | // CPL : Ignoered when no companding |
shorie | 15:76871e578c10 | 158 | 0 << 7 | // MUTECNT : 0, ignored when no muting |
shorie | 15:76871e578c10 | 159 | 0 << 6 | // MUTEVAL : 0, meaningless except SPDIF mode |
shorie | 15:76871e578c10 | 160 | 0 << 5 | // MUTE : 0, No mute. 1, mute |
shorie | 15:76871e578c10 | 161 | 0 << 4 | // TRIS : 0, Drive all slot. 1, Drive only active slot. Meaningless for I2S and RX |
shorie | 15:76871e578c10 | 162 | 1 << 3 | // FFLUSH : 0, No FIFO Flush. 1, FIFO Flush |
shorie | 15:76871e578c10 | 163 | 1 << 0; // FTH : 0, FIFO empty. 1, 1/4 FIFO. 2, 1/2 FIFO. 3, 3/4 FIFO. 4, FIFO full |
shorie | 15:76871e578c10 | 164 | |
shorie | 15:76871e578c10 | 165 | // Frame configuration register |
shorie | 15:76871e578c10 | 166 | SAI1_Block_B->FRCR = |
shorie | 15:76871e578c10 | 167 | 1 << 18 | // FSOFF : 0, FS is asserted on the first bit. 1, FS is asserted before the first bit. |
shorie | 15:76871e578c10 | 168 | 0 << 17 | // FSPOL : 0, Active low. 1, active high. I2S in left first operation is actilve low FS. |
shorie | 15:76871e578c10 | 169 | 1 << 16 | // FSDEF : 0, FS is start frame signal. 1, FS has also channel side info. I2S have to set 1 |
shorie | 15:76871e578c10 | 170 | 31 << 8 | // FSALL : Frame sync active level lenght. Seems to be meaningless in slave mode. Set as to be sure. |
shorie | 15:76871e578c10 | 171 | 63 << 0 ; // FRL : Frame length. Seems to be meaning less in slave mode. Set as to be sure. |
shorie | 15:76871e578c10 | 172 | |
shorie | 15:76871e578c10 | 173 | // Slot register |
shorie | 15:76871e578c10 | 174 | SAI1_Block_B->SLOTR = |
shorie | 15:76871e578c10 | 175 | 0xFFFF << 16 | // SLOTEN : bit mask to specify the active slot. In I2S, 2 slts are active. |
shorie | 15:76871e578c10 | 176 | 1 << 8 | // NBSLOT : Number of slots - 1 ( Ref manual seems to be wrong ) |
shorie | 15:76871e578c10 | 177 | 0 << 6 | // SLOTSZ : 0, same with data size. 1, 16bit. 2, 32bit |
shorie | 15:76871e578c10 | 178 | 0 << 0 ; // FBOFF : The manual is not clear. Perhaps, 0 is OK. |
shorie | 15:76871e578c10 | 179 | |
shorie | 15:76871e578c10 | 180 | // interrupt mask : TX doesn't trigger interrupt |
shorie | 15:76871e578c10 | 181 | SAI1_Block_B->IMR = |
shorie | 15:76871e578c10 | 182 | 0 << 6 | // LFSDETIE : Late frame synchronization detection interrupt enable |
shorie | 15:76871e578c10 | 183 | 0 << 5 | // AFSDETIE : Anticipated frame synchronization detection interrupt enable. AC97 only |
shorie | 15:76871e578c10 | 184 | 0 << 4 | // CNDYIE : CODEC nott ready interrupt. AC97 only |
shorie | 15:76871e578c10 | 185 | 0 << 3 | // FREQIE : FIFO Interrupt Request. Enable for RX |
shorie | 15:76871e578c10 | 186 | 0 << 2 | // WCKCFGIE : Wrong clock configuration interrupt enable. |
shorie | 15:76871e578c10 | 187 | 0 << 1 | // MUTEDETIE: Mute detection interrupt enable. |
shorie | 15:76871e578c10 | 188 | 0 << 0; // OVRUDRIE : Overrun/underrun interrupt enable |
shorie | 15:76871e578c10 | 189 | |
shorie | 15:76871e578c10 | 190 | // Clear flag register |
shorie | 15:76871e578c10 | 191 | SAI1_Block_B->CLRFR = 0xFFFFFFFF; // clear all flags |
shorie | 0:5ac19c994288 | 192 | |
shorie | 0:5ac19c994288 | 193 | |
shorie | 2:6613e62da521 | 194 | // Fill up tx FIO by 3 stereo samples. |
shorie | 2:6613e62da521 | 195 | hal_put_i2s_tx_data( 0 ); // left |
shorie | 2:6613e62da521 | 196 | hal_put_i2s_tx_data( 0 ); // right |
shorie | 2:6613e62da521 | 197 | hal_put_i2s_tx_data( 0 ); // left |
shorie | 2:6613e62da521 | 198 | hal_put_i2s_tx_data( 0 ); // right |
shorie | 2:6613e62da521 | 199 | hal_put_i2s_tx_data( 0 ); // left |
shorie | 2:6613e62da521 | 200 | hal_put_i2s_tx_data( 0 ); // right |
shorie | 0:5ac19c994288 | 201 | |
shorie | 0:5ac19c994288 | 202 | } |
shorie | 0:5ac19c994288 | 203 | |
shorie | 2:6613e62da521 | 204 | // Pin configuration and sync with WS signal |
shorie | 2:6613e62da521 | 205 | void hal_i2s_pin_config_and_wait_ws(void) |
shorie | 1:9710fb328a08 | 206 | { |
shorie | 15:76871e578c10 | 207 | // See DM00166116.pdf ST32F746ZG Datasheet Rev 4 Table 12 |
shorie | 15:76871e578c10 | 208 | // See https://developer.mbed.org/platforms/ST-Nucleo-F746ZG/ |
shorie | 15:76871e578c10 | 209 | // See stm32f746xx.h source here : https://developer.mbed.org/teams/Rigado/code/mbed-src-bmd-200/docs/255afbe6270c/stm32f746xx_8h_source.html |
shorie | 14:bdf11487a94b | 210 | |
shorie | 15:76871e578c10 | 211 | // PE3 SAI1_SD_B (AF6) : DAC |
shorie | 15:76871e578c10 | 212 | // PE4 SAI1_FS_A (AF6) : WS |
shorie | 15:76871e578c10 | 213 | // PE5 SAI1_SCK_A (AF6) : CLK |
shorie | 15:76871e578c10 | 214 | // PE6 SAI1_SD_A (AF6) : ADC |
shorie | 2:6613e62da521 | 215 | |
shorie | 15:76871e578c10 | 216 | // Clear the mode field of PE3-6 |
shorie | 15:76871e578c10 | 217 | GPIOE->MODER &= |
shorie | 15:76871e578c10 | 218 | ~( 3 << 6 | // PE3 |
shorie | 15:76871e578c10 | 219 | 3 << 8 | // PE4 |
shorie | 15:76871e578c10 | 220 | 3 << 10 | // PE5 |
shorie | 15:76871e578c10 | 221 | 3 << 12 ); // PE6 |
shorie | 14:bdf11487a94b | 222 | |
shorie | 15:76871e578c10 | 223 | // Set the pin mode |
shorie | 15:76871e578c10 | 224 | GPIOE->MODER |= |
shorie | 15:76871e578c10 | 225 | 2 << 6 | // PE3 is Alternate Function |
shorie | 15:76871e578c10 | 226 | 0 << 8 | // PE4 is input |
shorie | 15:76871e578c10 | 227 | 0 << 10 | // PE5 is input |
shorie | 15:76871e578c10 | 228 | 0 << 12; // PE6 is input |
shorie | 15:76871e578c10 | 229 | |
shorie | 15:76871e578c10 | 230 | |
shorie | 15:76871e578c10 | 231 | // Clear the OTYPE field of PE3-6 ( Clear is push-pull ) |
shorie | 15:76871e578c10 | 232 | GPIOE->OTYPER &= |
shorie | 15:76871e578c10 | 233 | ~( 1 << 3 | // PE3 |
shorie | 15:76871e578c10 | 234 | 1 << 4 | // PE4 |
shorie | 15:76871e578c10 | 235 | 1 << 5 | // PE5 |
shorie | 15:76871e578c10 | 236 | 1 << 6 ); // PE6 |
shorie | 15:76871e578c10 | 237 | |
shorie | 14:bdf11487a94b | 238 | |
shorie | 15:76871e578c10 | 239 | // Clear the OSPEEDR field of PE3-6 |
shorie | 15:76871e578c10 | 240 | GPIOE->OSPEEDR &= |
shorie | 15:76871e578c10 | 241 | ~( 3 << 6 | // PE3 |
shorie | 15:76871e578c10 | 242 | 3 << 8 | // PE4 |
shorie | 15:76871e578c10 | 243 | 3 << 10 | // PE5 |
shorie | 15:76871e578c10 | 244 | 3 << 12 ); // PE6 |
shorie | 15:76871e578c10 | 245 | |
shorie | 15:76871e578c10 | 246 | // Set the OSPEEDR |
shorie | 15:76871e578c10 | 247 | GPIOE->OSPEEDR |= |
shorie | 15:76871e578c10 | 248 | 1 << 6 | // PE3 DAC is medium speed |
shorie | 15:76871e578c10 | 249 | 0 << 8 | // PE4 is input |
shorie | 15:76871e578c10 | 250 | 0 << 10 | // PE5 is input |
shorie | 15:76871e578c10 | 251 | 0 << 12; // PE6 is input |
shorie | 15:76871e578c10 | 252 | |
shorie | 2:6613e62da521 | 253 | |
shorie | 15:76871e578c10 | 254 | // Clear the PUPDR field of PE3-6 ( Clear is no pull-up/no pull-down ) |
shorie | 15:76871e578c10 | 255 | GPIOE->PUPDR &= |
shorie | 15:76871e578c10 | 256 | ~( 3 << 6 | // PE3 |
shorie | 15:76871e578c10 | 257 | 3 << 8 | // PE4 |
shorie | 15:76871e578c10 | 258 | 3 << 10 | // PE5 |
shorie | 15:76871e578c10 | 259 | 3 << 12 ); // PE6 |
shorie | 15:76871e578c10 | 260 | |
shorie | 15:76871e578c10 | 261 | |
shorie | 15:76871e578c10 | 262 | // Clear the Alternate funciton of PE3-6 |
shorie | 15:76871e578c10 | 263 | GPIOE->AFR[0] &= |
shorie | 15:76871e578c10 | 264 | ~( 0xF << 12 | // PE3 |
shorie | 15:76871e578c10 | 265 | 0xF << 16 | // PE4 |
shorie | 15:76871e578c10 | 266 | 0xF << 20 | // PE5 |
shorie | 15:76871e578c10 | 267 | 0xF << 24 );// PE6 |
shorie | 15:76871e578c10 | 268 | |
shorie | 15:76871e578c10 | 269 | // Set the Alternate function of PE3-6 |
shorie | 15:76871e578c10 | 270 | GPIOE->AFR[0] |= |
shorie | 15:76871e578c10 | 271 | 6 << 12 | // PE3 Alternalte Funciton 6 |
shorie | 15:76871e578c10 | 272 | 6 << 16 | // PE4 Alternalte Funciton 6 |
shorie | 15:76871e578c10 | 273 | 6 << 20 | // PE5 Alternalte Funciton 6 |
shorie | 15:76871e578c10 | 274 | 6 << 24 ; // PE6 Alternalte Funciton 6 |
shorie | 15:76871e578c10 | 275 | |
shorie | 15:76871e578c10 | 276 | // Now, we set all the pin. We don't need to wait the WS, |
shorie | 15:76871e578c10 | 277 | // Because SAI has TX/RX sync. |
shorie | 1:9710fb328a08 | 278 | } |
shorie | 1:9710fb328a08 | 279 | |
shorie | 1:9710fb328a08 | 280 | |
shorie | 0:5ac19c994288 | 281 | // Start I2S transfer. Interrupt starts |
shorie | 2:6613e62da521 | 282 | void hal_i2s_start(void) |
shorie | 0:5ac19c994288 | 283 | { |
shorie | 15:76871e578c10 | 284 | // Setup SAI Block configuration register. |
shorie | 15:76871e578c10 | 285 | // Block A : RX |
shorie | 15:76871e578c10 | 286 | // Block B : TX |
shorie | 15:76871e578c10 | 287 | |
shorie | 15:76871e578c10 | 288 | // Block B is sync to Block A. So, Block B first. |
shorie | 15:76871e578c10 | 289 | SAI1_Block_B->CR1 |= |
shorie | 15:76871e578c10 | 290 | 1 << 16 ; // SAIXEN : 0, Disable, 1, Enable. Disable at this moment |
shorie | 15:76871e578c10 | 291 | // Now, Block A and B start together |
shorie | 15:76871e578c10 | 292 | SAI1_Block_A->CR1 |= |
shorie | 15:76871e578c10 | 293 | 1 << 16 ; // SAIXEN : 0, Disable, 1, Enable. Disable at this moment |
shorie | 15:76871e578c10 | 294 | |
shorie | 0:5ac19c994288 | 295 | } |
shorie | 0:5ac19c994288 | 296 | |
shorie | 2:6613e62da521 | 297 | IRQn_Type hal_get_i2s_irq_id(void) |
shorie | 0:5ac19c994288 | 298 | { |
shorie | 15:76871e578c10 | 299 | return SAI1_IRQn; |
shorie | 0:5ac19c994288 | 300 | } |
shorie | 0:5ac19c994288 | 301 | |
shorie | 0:5ac19c994288 | 302 | |
shorie | 2:6613e62da521 | 303 | IRQn_Type hal_get_process_irq_id(void) |
shorie | 0:5ac19c994288 | 304 | { |
shorie | 15:76871e578c10 | 305 | return SPI6_IRQn; // STM32F746 SPI6 is killed. This interrupt is assigned for signal processing in Unzen |
shorie | 0:5ac19c994288 | 306 | } |
shorie | 0:5ac19c994288 | 307 | |
shorie | 2:6613e62da521 | 308 | |
shorie | 2:6613e62da521 | 309 | // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2... |
shorie | 2:6613e62da521 | 310 | unsigned int hal_get_i2s_irq_priority_level(void) |
shorie | 0:5ac19c994288 | 311 | { |
shorie | 15:76871e578c10 | 312 | // STM32F746 has 4 bits priority field. So, heighest is 0, lowest is 15. |
shorie | 3:707608830793 | 313 | // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( F**k! ) |
shorie | 15:76871e578c10 | 314 | // Then, 15 is heighest, 0 is lowerest in CMSIS. |
shorie | 15:76871e578c10 | 315 | // setting 12 as i2s irq priority allows, some other interrupts are higher |
shorie | 2:6613e62da521 | 316 | // and some others are lower than i2s irq priority. |
shorie | 15:76871e578c10 | 317 | return 12; |
shorie | 2:6613e62da521 | 318 | } |
shorie | 2:6613e62da521 | 319 | |
shorie | 2:6613e62da521 | 320 | |
shorie | 2:6613e62da521 | 321 | // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2... |
shorie | 2:6613e62da521 | 322 | unsigned int hal_get_process_irq_priority_level(void) |
shorie | 2:6613e62da521 | 323 | { |
shorie | 15:76871e578c10 | 324 | // STM32F746 has 4 bits priority field. So, heighest is 0, lowest is 15. |
shorie | 3:707608830793 | 325 | // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( S**t! ) |
shorie | 15:76871e578c10 | 326 | // Then 15 is heighest, 0 is lowerest in CMSIS. |
shorie | 15:76871e578c10 | 327 | // setting 4 as process priority allows, some other interrupts are higher |
shorie | 2:6613e62da521 | 328 | // and some other interrupts are lower then process priority. |
shorie | 15:76871e578c10 | 329 | return 4; |
shorie | 0:5ac19c994288 | 330 | } |
shorie | 0:5ac19c994288 | 331 | |
shorie | 15:76871e578c10 | 332 | // STM32F746 transferes 2 words ( left and right ) for each interrupt. |
shorie | 2:6613e62da521 | 333 | unsigned int hal_data_per_sample(void) |
shorie | 0:5ac19c994288 | 334 | { |
shorie | 0:5ac19c994288 | 335 | return 2; |
shorie | 0:5ac19c994288 | 336 | } |
shorie | 0:5ac19c994288 | 337 | |
shorie | 0:5ac19c994288 | 338 | // return true when the sample parameter is ready to read. |
shorie | 0:5ac19c994288 | 339 | // return false when the sample is not ready to read. |
shorie | 2:6613e62da521 | 340 | void hal_get_i2s_rx_data( int & sample) |
shorie | 0:5ac19c994288 | 341 | { |
shorie | 15:76871e578c10 | 342 | // RX is SAI1_BlockA. See the comment on top of this file |
shorie | 15:76871e578c10 | 343 | sample = SAI1_Block_A->DR; |
shorie | 0:5ac19c994288 | 344 | } |
shorie | 0:5ac19c994288 | 345 | |
shorie | 0:5ac19c994288 | 346 | // put a sample to I2S TX data regisger |
shorie | 2:6613e62da521 | 347 | void hal_put_i2s_tx_data( int sample ) |
shorie | 0:5ac19c994288 | 348 | { |
shorie | 15:76871e578c10 | 349 | // TX is SAI1_Block_B. See the comment on top of this file |
shorie | 15:76871e578c10 | 350 | SAI1_Block_B->DR = sample; |
shorie | 0:5ac19c994288 | 351 | } |
shorie | 0:5ac19c994288 | 352 | } |
shorie | 0:5ac19c994288 | 353 | |
shorie | 0:5ac19c994288 | 354 |