Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cuatro DFSDM1 mic demodulation #2077

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions board/boards/cuatro.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ static void cuatro_init(void) {
set_gpio_alternate(GPIOD, 13, GPIO_AF5_FDCAN3);

// C2: SOM GPIO used as input (fan control at boot)
set_gpio_mode(GPIOC, 2, MODE_INPUT);
set_gpio_pullup(GPIOC, 2, PULL_DOWN);
// FIXME: repurposed as mic clock output
// set_gpio_mode(GPIOC, 2, MODE_INPUT);
// set_gpio_pullup(GPIOC, 2, PULL_DOWN);

// SOM bootkick + reset lines
cuatro_set_bootkick(BOOT_BOOTKICK);
Expand Down Expand Up @@ -139,8 +140,8 @@ static void cuatro_init(void) {
set_gpio_alternate(GPIOC, 0, GPIO_AF8_SAI4); // SAI4_FS_B
set_gpio_alternate(GPIOD, 11, GPIO_AF10_SAI4); // SAI4_SD_A
set_gpio_alternate(GPIOE, 3, GPIO_AF8_SAI4); // SAI4_SD_B
set_gpio_alternate(GPIOE, 4, GPIO_AF2_SAI1); // SAI1_D2
set_gpio_alternate(GPIOE, 5, GPIO_AF2_SAI1); // SAI1_CK2
set_gpio_alternate(GPIOE, 4, GPIO_AF3_DFSDM1); // DFSDM1_DATIN3 TODO: move to other pin!
set_gpio_alternate(GPIOC, 2, GPIO_AF6_DFSDM1); // DFSDM1_CKOUT
set_gpio_alternate(GPIOE, 6, GPIO_AF10_SAI4); // SAI4_MCLK_B
sound_init();
}
Expand Down
2 changes: 1 addition & 1 deletion board/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//#define DEBUG_UART
//#define DEBUG_USB
//#define DEBUG_SPI
//#define DEBUG_FAULTS
#define DEBUG_FAULTS
//#define DEBUG_COMMS
//#define DEBUG_FAN

Expand Down
2 changes: 2 additions & 0 deletions board/stm32h7/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ void clock_init(void) {
register_set(&(RCC->D2CCIP2R), RCC_D2CCIP2R_USBSEL_1 | RCC_D2CCIP2R_USBSEL_0, RCC_D2CCIP2R_USBSEL);
// Configure clock source for FDCAN (PLL1Q at 80Mhz)
register_set(&(RCC->D2CCIP1R), RCC_D2CCIP1R_FDCANSEL_0, RCC_D2CCIP1R_FDCANSEL);
// Configure clock source for DFSDM1
register_set_bits(&(RCC->D2CCIP1R), RCC_D2CCIP1R_DFSDM1SEL);
// Configure clock source for ADC1,2,3 (per_ck(currently HSE))
register_set(&(RCC->D3CCIPR), RCC_D3CCIPR_ADCSEL_1, RCC_D3CCIPR_ADCSEL);
//Enable the Clock Security System
Expand Down
1 change: 1 addition & 0 deletions board/stm32h7/peripherals.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ void peripherals_init(void) {
RCC->APB1LENR |= RCC_APB1LENR_DAC12EN; // DAC

// Audio
RCC->APB2ENR |= RCC_APB2ENR_DFSDM1EN; // D/S demodulator for mic
RCC->APB4ENR |= RCC_APB4ENR_SAI4EN; // SAI4

// Timers
Expand Down
61 changes: 60 additions & 1 deletion board/stm32h7/sound.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#define SOUND_RX_BUF_SIZE 2000U
#define SOUND_TX_BUF_SIZE (SOUND_RX_BUF_SIZE/2U)

#define MIC_RX_BUF_SIZE 512U
#define MIC_TX_BUF_SIZE (MIC_RX_BUF_SIZE * 2U)
__attribute__((section(".sram4"))) static uint16_t sound_rx_buf[2][SOUND_RX_BUF_SIZE];
__attribute__((section(".sram4"))) static uint32_t mic_rx_buf[2][MIC_RX_BUF_SIZE];

static uint8_t sound_idle_count;

Expand Down Expand Up @@ -30,6 +32,26 @@ static void BDMA_Channel0_IRQ_Handler(void) {
DMA1_Stream1->CR |= DMA_SxCR_EN;
}

// Recording processing
static void DMA1_Stream0_IRQ_Handler(void) {
__attribute__((section(".sram4"))) static uint16_t tx_buf[MIC_TX_BUF_SIZE];

DMA1->LIFCR |= 0x7D; // clear flags

// process samples
uint8_t buf_idx = ((DMA1_Stream0->CR & DMA_SxCR_CT) >> DMA_SxCR_CT_Pos) == 1U ? 0U : 1U;
for (uint16_t i=0U; i < MIC_RX_BUF_SIZE; i++) {
tx_buf[2U*i] = ((mic_rx_buf[buf_idx][i] >> 16U) & 0xFFFF);
tx_buf[(2U*i)+1U] = tx_buf[2U*i];
}

BDMA->IFCR |= BDMA_IFCR_CGIF1;
BDMA_Channel1->CCR &= ~BDMA_CCR_EN;
register_set(&BDMA_Channel1->CM0AR, (uint32_t) tx_buf, 0xFFFFFFFFU);
BDMA_Channel1->CNDTR = MIC_TX_BUF_SIZE;
BDMA_Channel1->CCR |= BDMA_CCR_EN;
}

void sound_tick(void) {
if (sound_idle_count > 0U) {
sound_idle_count--;
Expand All @@ -41,6 +63,7 @@ void sound_tick(void) {

void sound_init(void) {
REGISTER_INTERRUPT(BDMA_Channel0_IRQn, BDMA_Channel0_IRQ_Handler, 64U, FAULT_INTERRUPT_RATE_SOUND_DMA)
REGISTER_INTERRUPT(DMA1_Stream0_IRQn, DMA1_Stream0_IRQ_Handler, 128U, FAULT_INTERRUPT_RATE_SOUND_DMA)

// Init DAC
register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU);
Expand All @@ -63,6 +86,10 @@ void sound_init(void) {
TIM7->SR = 0U;
TIM7->CR1 |= TIM_CR1_CEN;

// sync both SAIs
register_set(&SAI4->GCR, (0b10 << SAI_GCR_SYNCOUT_Pos), SAI_GCR_SYNCIN_Msk | SAI_GCR_SYNCOUT_Msk);
register_set(&SAI1->GCR, (3U << SAI_GCR_SYNCIN_Pos), SAI_GCR_SYNCIN_Msk | SAI_GCR_SYNCOUT_Msk);

// stereo audio in
register_set(&SAI4_Block_B->CR1, SAI_xCR1_DMAEN | (0b00UL << SAI_xCR1_SYNCEN_Pos) | (0b100U << SAI_xCR1_DS_Pos) | (0b11U << SAI_xCR1_MODE_Pos), 0x0FFB3FEFU);
register_set(&SAI4_Block_B->CR2, (0b001U << SAI_xCR2_FTH_Pos), 0xFFFBU);
Expand All @@ -78,7 +105,39 @@ void sound_init(void) {
register_set(&DMAMUX2_Channel0->CCR, 16U, DMAMUX_CxCR_DMAREQ_ID_Msk); // SAI4_B_DMA
register_set_bits(&BDMA_Channel0->CCR, BDMA_CCR_EN);

// mic output
register_set(&SAI4_Block_A->CR1, SAI_xCR1_DMAEN | (0b01 << SAI_xCR1_SYNCEN_Pos) | (0b100 << SAI_xCR1_DS_Pos) | (0b10 << SAI_xCR1_MODE_Pos), 0x0FFB3FEFU);
register_set(&SAI4_Block_A->CR2, 0U, 0xFFFBU);
register_set(&SAI4_Block_A->FRCR, (31U << SAI_xFRCR_FRL_Pos), 0x7FFFFU);
register_set(&SAI4_Block_A->SLOTR, (0b11 << SAI_xSLOTR_SLOTEN_Pos) | (1U << SAI_xSLOTR_NBSLOT_Pos) | (0b01 << SAI_xSLOTR_SLOTSZ_Pos), 0xFFFF0FDFU); // NBSLOT definition is vague

// init DFSDM for PDM mic
DFSDM1_Channel0->CHCFGR1 = (76U << DFSDM_CHCFGR1_CKOUTDIV_Pos) | DFSDM_CHCFGR1_CHEN; // CH0 controls the clock
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: use register methods here

DFSDM1_Channel3->CHCFGR1 |= (0b01 << DFSDM_CHCFGR1_SPICKSEL_Pos) | (0b00U << DFSDM_CHCFGR1_SITP_Pos) | DFSDM_CHCFGR1_CHEN; // SITP determines sample edge
DFSDM1_Channel3->CHCFGR2 = (2U << DFSDM_CHCFGR2_DTRBS_Pos);
DFSDM1_Filter0->FLTFCR = (0U << DFSDM_FLTFCR_IOSR_Pos) | (64U << DFSDM_FLTFCR_FOSR_Pos) | (4U << DFSDM_FLTFCR_FORD_Pos);
DFSDM1_Filter0->FLTCR1 = DFSDM_FLTCR1_FAST | (3U << DFSDM_FLTCR1_RCH_Pos) | DFSDM_FLTCR1_RDMAEN | DFSDM_FLTCR1_RCONT | DFSDM_FLTCR1_DFEN;
DFSDM1_Channel0->CHCFGR1 |= DFSDM_CHCFGR1_DFSDMEN;
DFSDM1_Filter0->FLTCR1 |= DFSDM_FLTCR1_RSWSTART;

// DMA (DFSDM1 -> memory)
DMA1_Stream0->PAR = (uint32_t)&DFSDM1_Filter0->FLTRDATAR;
DMA1_Stream0->M0AR = (uint32_t)mic_rx_buf[0];
DMA1_Stream0->M1AR = (uint32_t)mic_rx_buf[1];
DMA1_Stream0->NDTR = MIC_RX_BUF_SIZE;
DMA1_Stream0->CR = DMA_SxCR_DBM | (0b10UL << DMA_SxCR_MSIZE_Pos) | (0b10UL << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE;
register_set(&DMAMUX1_Channel0->CCR, 101U, DMAMUX_CxCR_DMAREQ_ID_Msk); // DFSDM1_DMA0
DMA1_Stream0->CR |= DMA_SxCR_EN;
DMA1->LIFCR |= 0x7D; // clear flags

// DMA (memory -> SAI4)
register_set(&BDMA_Channel1->CPAR, (uint32_t) &(SAI4_Block_A->DR), 0xFFFFFFFFU);
register_set(&BDMA_Channel1->CCR, (0b01 << BDMA_CCR_MSIZE_Pos) | (0b01 << BDMA_CCR_PSIZE_Pos) | BDMA_CCR_MINC | (0b1 << BDMA_CCR_DIR_Pos), 0xFFFEU);
register_set(&DMAMUX2_Channel1->CCR, 15U, DMAMUX_CxCR_DMAREQ_ID_Msk); // SAI4_A_DMA

// enable all initted blocks
register_set_bits(&SAI4_Block_A->CR1, SAI_xCR1_SAIEN);
register_set_bits(&SAI4_Block_B->CR1, SAI_xCR1_SAIEN);
NVIC_EnableIRQ(BDMA_Channel0_IRQn);
NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}
Loading