Add apu driver

This commit is contained in:
zhaozhongxiang 2019-02-01 18:14:19 +08:00
parent 91d4ca5fc1
commit 8c7a974c12
2 changed files with 762 additions and 0 deletions

443
lib/drivers/apu.c Normal file
View File

@ -0,0 +1,443 @@
#include <stddef.h>
#include <stdint.h>
#include "encoding.h"
#include "syscalls.h"
#include "sysctl.h"
#include "apu.h"
#define BEAFORMING_BASE_ADDR (0x50250200U)
volatile struct apu_reg_t *const apu = (volatile struct apu_reg_t *)BEAFORMING_BASE_ADDR;
/*
*
Voice strength average value right shift factor. When performing sound direction detect,
the average value of samples from different channels is required, this right shift factor
is used to perform division.
0x0: no right shift; 0x1: right shift by 1-bit;
. . . . . .
0xF: right shift by 14-bit.
*/
void apu_set_audio_gain(uint16_t gain)
{
struct apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
ch_cfg.we_bf_target_dir = 0;
ch_cfg.we_bf_sound_ch_en = 0;
ch_cfg.we_data_src_mode = 0;
ch_cfg.we_audio_gain = 1;
ch_cfg.audio_gain = gain;
apu->bf_ch_cfg_reg = ch_cfg;
}
// set sampling shift
void apu_set_smpl_shift(uint8_t smpl_shift)
{
struct apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
tmp.smpl_shift_bits = smpl_shift;
apu->bf_dwsz_cfg_reg = tmp;
}
// get sampling shift
uint8_t apu_get_smpl_shift(void)
{
struct apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
return tmp.smpl_shift_bits;
}
/*
*
* BF unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). BF sound channels are related with I2S host RX channels.
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0; BF channel 2/3 correspond
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
* channel and hardware automatically clear the bit after the sample buffers used for direction
* searching is filled full.
* 0x1: writing '1' to enable the corresponding BF sound channel.
*/
void apu_set_channel_enabled(uint8_t channel_bit)
{
struct apu_ch_cfg_t ch_cfg;
ch_cfg.we_audio_gain = 0;
ch_cfg.we_bf_target_dir = 0;
ch_cfg.we_bf_sound_ch_en = 1;
ch_cfg.bf_sound_ch_en = channel_bit;
apu->bf_ch_cfg_reg = ch_cfg;
}
/*
*
* BF unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). BF sound channels are related with I2S host RX channels.
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0; BF channel 2/3 correspond
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
* channel and hardware automatically clear the bit after the sample buffers used for direction
* searching is filled full.
* 0x1: writing '1' to enable the corresponding BF sound channel.
*/
void apu_channel_enable(uint8_t channel_bit)
{
struct apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
ch_cfg.we_audio_gain = 0;
ch_cfg.we_bf_target_dir = 0;
ch_cfg.we_data_src_mode = 0;
ch_cfg.we_bf_sound_ch_en = 1;
ch_cfg.bf_sound_ch_en = channel_bit;
apu->bf_ch_cfg_reg = ch_cfg;
}
/**
* audio data source configure parameter. This parameter controls where the audio data source comes from.
* 0x0: audio data directly sourcing from apu internal buffer;
* 0x1: audio data sourcing from FFT result buffer.
*/
void apu_set_src_mode(uint8_t src_mode)
{
struct apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
ch_cfg.we_audio_gain = 0;
ch_cfg.we_bf_target_dir = 0;
ch_cfg.we_bf_sound_ch_en = 0;
ch_cfg.we_data_src_mode = 1;
ch_cfg.data_src_mode = src_mode;
apu->bf_ch_cfg_reg = ch_cfg;
}
/*
* I2S host beam-forming direction sample ibuffer read index configure register
*/
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx)
{
apu->bf_dir_bidx[dir_num][0] =
(struct apu_dir_bidx_t){
.dir_rd_idx0 = dir_bidx[0],
.dir_rd_idx1 = dir_bidx[1],
.dir_rd_idx2 = dir_bidx[2],
.dir_rd_idx3 = dir_bidx[3]
};
apu->bf_dir_bidx[dir_num][1] =
(struct apu_dir_bidx_t){
.dir_rd_idx0 = dir_bidx[4],
.dir_rd_idx1 = dir_bidx[5],
.dir_rd_idx2 = dir_bidx[6],
.dir_rd_idx3 = dir_bidx[7]
};
}
/*
*
S *ound direction searching enable bit. Software writes '1' to start sound direction searching function.
When all the sound sample buffers are filled full, this bit is cleared by hardware (this sample buffers
are used for direction detect only).
0x1: enable direction searching.
*/
void apu_dir_enable(void)
{
struct apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
bf_en_tmp.we_bf_dir_search_en = 1;
bf_en_tmp.bf_dir_search_en = 1;
apu->bf_ctl_reg = bf_en_tmp;
}
void apu_dir_reset(void)
{
struct apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
bf_en_tmp.we_search_path_rst = 1;
bf_en_tmp.search_path_reset = 1;
apu->bf_ctl_reg = bf_en_tmp;
}
/*
*
V *alid voice sample stream generation enable bit. After sound direction searching is done, software can
configure this bit to generate a stream of voice samples for voice recognition.
0x1: enable output of voice sample stream.
0x0: stop the voice samlpe stream output.
*/
void apu_voc_enable(uint8_t enable_flag)
{
struct apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
bf_en_tmp.we_bf_stream_gen = 1;
bf_en_tmp.bf_stream_gen_en = enable_flag;
apu->bf_ctl_reg = bf_en_tmp;
}
void apu_voc_reset(void)
{
struct apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
bf_en_tmp.we_voice_gen_path_rst = 1;
bf_en_tmp.voice_gen_path_reset = 1;
apu->bf_ctl_reg = bf_en_tmp;
}
/*
*
Target direction select for valid voice output. When the source voice direaction searching
is done, software can use this field to select one from 16 sound directions for the following
voice recognition
0x0: select sound direction 0; 0x1: select sound direction 1;
. . . . . .
0xF: select sound direction 15.
*/
void apu_voc_set_direction(enum en_bf_dir direction)
{
struct apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
ch_cfg.we_bf_sound_ch_en = 0;
ch_cfg.we_audio_gain = 0;
ch_cfg.we_data_src_mode = 0;
ch_cfg.we_bf_target_dir = 1;
ch_cfg.bf_target_dir = direction;
apu->bf_ch_cfg_reg = ch_cfg;
struct apu_ctl_t bf_en_tmp = apu->bf_ctl_reg;
bf_en_tmp.we_update_voice_dir = 1;
bf_en_tmp.update_voice_dir = 1;
apu->bf_ctl_reg = bf_en_tmp;
}
/*
*I2S host beam-forming Filter FIR16 Coefficient Register
*/
void apu_dir_set_prev_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
for (i = 0; i < 9; i++) {
apu->bf_pre_fir0_coef[i] =
(struct apu_fir_coef_t){
.fir_tap0 = fir_coef[i * 2],
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
};
}
}
void apu_dir_set_post_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
for (i = 0; i < 9; i++) {
apu->bf_post_fir0_coef[i] =
(struct apu_fir_coef_t){
.fir_tap0 = fir_coef[i * 2],
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
};
}
}
void apu_voc_set_prev_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
for (i = 0; i < 9; i++) {
apu->bf_pre_fir1_coef[i] =
(struct apu_fir_coef_t){
.fir_tap0 = fir_coef[i * 2],
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
};
}
}
void apu_voc_set_post_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
for (i = 0; i < 9; i++) {
apu->bf_post_fir1_coef[i] =
(struct apu_fir_coef_t){
.fir_tap0 = fir_coef[i * 2],
.fir_tap1 = i == 8 ? 0 : fir_coef[i * 2 + 1]
};
}
}
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor)
{
apu->bf_fft_cfg_reg =
(struct apu_fft_cfg_t){
.fft_enable = enable_flag,
.fft_shift_factor = shift_factor
};
struct apu_ch_cfg_t ch_cfg = apu->bf_ch_cfg_reg;
ch_cfg.we_data_src_mode = 1;
ch_cfg.data_src_mode = enable_flag;
apu->bf_ch_cfg_reg = ch_cfg;
}
void apu_dir_set_down_size(uint8_t dir_dwn_size)
{
struct apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
tmp.dir_dwn_siz_rate = dir_dwn_size;
apu->bf_dwsz_cfg_reg = tmp;
}
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask)
{
struct apu_int_mask_t tmp = apu->bf_int_mask_reg;
tmp.dir_data_rdy_msk = dir_int_mask;
apu->bf_int_mask_reg = tmp;
}
void apu_voc_set_down_size(uint8_t voc_dwn_size)
{
struct apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
tmp.voc_dwn_siz_rate = voc_dwn_size;
apu->bf_dwsz_cfg_reg = tmp;
}
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask)
{
struct apu_int_mask_t tmp = apu->bf_int_mask_reg;
tmp.voc_buf_rdy_msk = voc_int_mask;
apu->bf_int_mask_reg = tmp;
}
void apu_set_down_size(uint8_t dir_dwn_size, uint8_t voc_dwn_size)
{
struct apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;
tmp.dir_dwn_siz_rate = dir_dwn_size;
tmp.voc_dwn_siz_rate = voc_dwn_size;
apu->bf_dwsz_cfg_reg = tmp;
}
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask)
{
apu->bf_int_mask_reg =
(struct apu_int_mask_t){
.dir_data_rdy_msk = dir_int_mask,
.voc_buf_rdy_msk = voc_int_mask
};
}
void apu_dir_clear_int_state(void)
{
apu->bf_int_stat_reg =
(struct apu_int_stat_t){
.dir_search_data_rdy = 1
};
}
void apu_voc_clear_int_state(void)
{
apu->bf_int_stat_reg =
(struct apu_int_stat_t){
.voc_buf_data_rdy = 1
};
}
// reset saturation_counter
void apu_voc_reset_saturation_counter(void)
{
apu->saturation_counter = 1<<31;
}
// get saturation counter
// heigh 16 bit is counter, low 16 bit is total.
uint32_t apu_voc_get_saturation_counter(void)
{
return apu->saturation_counter;
}
// set saturation limit
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom)
{
apu->saturation_limits = (uint32_t)bottom<<16 | upper;
}
// get saturation limit
// heigh 16 bit is counter, low 16 bit is total.
uint32_t apu_voc_get_saturation_limit(void)
{
return apu->saturation_limits;
}
static void print_fir(const char *member_name, volatile struct apu_fir_coef_t *pfir)
{
printf(" for(int i = 0; i < 9; i++){\n");
for (int i = 0; i < 9; i++) {
struct apu_fir_coef_t fir = pfir[i];
printf(" apu->%s[%d] = (struct apu_fir_coef_t){\n", member_name, i);
printf(" .fir_tap0 = 0x%x,\n", fir.fir_tap0);
printf(" .fir_tap1 = 0x%x\n", fir.fir_tap1);
printf(" };\n");
}
printf(" }\n");
}
void apu_print_setting(void)
{
printf("void apu_setting(void) {\n");
struct apu_ch_cfg_t bf_ch_cfg_reg = apu->bf_ch_cfg_reg;
printf(" apu->bf_ch_cfg_reg = (struct apu_ch_cfg_t){\n");
printf(" .we_audio_gain = 1, .we_bf_target_dir = 1, .we_bf_sound_ch_en = 1,\n");
printf(" .audio_gain = 0x%x, .bf_target_dir = %d, .bf_sound_ch_en = %d, .data_src_mode = %d\n",
bf_ch_cfg_reg.audio_gain, bf_ch_cfg_reg.bf_target_dir, bf_ch_cfg_reg.bf_sound_ch_en, bf_ch_cfg_reg.data_src_mode);
printf(" };\n");
struct apu_ctl_t bf_ctl_reg = apu->bf_ctl_reg;
printf(" apu->bf_ctl_reg = (struct apu_ctl_t){\n");
printf(" .we_bf_stream_gen = 1, .we_bf_dir_search_en = 1,\n");
printf(" .bf_stream_gen_en = %d, .bf_dir_search_en = %d\n",
bf_ctl_reg.bf_stream_gen_en, bf_ctl_reg.bf_dir_search_en);
printf(" };\n");
printf(" for(int i = 0; i < 16; i++){\n");
for (int i = 0; i < 16; i++) {
struct apu_dir_bidx_t bidx0 = apu->bf_dir_bidx[i][0];
struct apu_dir_bidx_t bidx1 = apu->bf_dir_bidx[i][1];
printf(" apu->bf_dir_bidx[%d][0] = (struct apu_dir_bidx_t){\n", i);
printf(" .dir_rd_idx0 = 0x%x,\n", bidx0.dir_rd_idx0);
printf(" .dir_rd_idx1 = 0x%x,\n", bidx0.dir_rd_idx1);
printf(" .dir_rd_idx2 = 0x%x,\n", bidx0.dir_rd_idx2);
printf(" .dir_rd_idx3 = 0x%x\n", bidx0.dir_rd_idx3);
printf(" };\n");
printf(" apu->bf_dir_bidx[%d][1] = (struct apu_dir_bidx_t){\n", i);
printf(" .dir_rd_idx0 = 0x%x,\n", bidx1.dir_rd_idx0);
printf(" .dir_rd_idx1 = 0x%x,\n", bidx1.dir_rd_idx1);
printf(" .dir_rd_idx2 = 0x%x,\n", bidx1.dir_rd_idx2);
printf(" .dir_rd_idx3 = 0x%x\n", bidx1.dir_rd_idx3);
printf(" };\n");
}
printf(" }\n");
print_fir("bf_pre_fir0_coef", apu->bf_pre_fir0_coef);
print_fir("bf_post_fir0_coef", apu->bf_post_fir0_coef);
print_fir("bf_pre_fir1_coef", apu->bf_pre_fir1_coef);
print_fir("bf_post_fir1_coef", apu->bf_post_fir1_coef);
struct apu_dwsz_cfg_t bf_dwsz_cfg_reg = apu->bf_dwsz_cfg_reg;
printf(" apu->bf_dwsz_cfg_reg = (struct apu_dwsz_cfg_t){\n");
printf(" .dir_dwn_siz_rate = %d, .voc_dwn_siz_rate = %d\n",
bf_dwsz_cfg_reg.dir_dwn_siz_rate, bf_dwsz_cfg_reg.voc_dwn_siz_rate);
printf(" };\n");
struct apu_fft_cfg_t bf_fft_cfg_reg = apu->bf_fft_cfg_reg;
printf(" apu->bf_fft_cfg_reg = (struct apu_fft_cfg_t){\n");
printf(" .fft_enable = %d, .fft_shift_factor = 0x%x\n",
bf_fft_cfg_reg.fft_enable, bf_fft_cfg_reg.fft_shift_factor);
printf(" };\n");
struct apu_int_mask_t bf_int_mask_reg = apu->bf_int_mask_reg;
printf(" apu->bf_int_mask_reg = (struct apu_int_mask_t){\n");
printf(" .dir_data_rdy_msk = %d, .voc_buf_rdy_msk = %d\n",
bf_int_mask_reg.dir_data_rdy_msk, bf_int_mask_reg.voc_buf_rdy_msk);
printf(" };\n");
printf("}\n");
}

319
lib/drivers/include/apu.h Normal file
View File

@ -0,0 +1,319 @@
#ifndef _apu_H_
#define _apu_H_
#if defined(__cplusplus)
extern C {
#endif
extern volatile struct apu_reg_t *const apu;
enum en_bf_dir
{
APU_DIR0 = 0,
APU_DIR1,
APU_DIR2,
APU_DIR3,
APU_DIR4,
APU_DIR5,
APU_DIR6,
APU_DIR7,
APU_DIR8,
APU_DIR9,
APU_DIR10,
APU_DIR11,
APU_DIR12,
APU_DIR13,
APU_DIR14,
APU_DIR15,
};
struct apu_ch_cfg_t
{
/**
* BF unit sound channel enable control bits.
* Bit 'x' corresponds to enable bit for sound channel 'x' (x = 0, 1, 2,
* . . ., 7). BF sound channels are related with I2S host RX channels.
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0;
* BF channel 2/3 correspond to left/right channels of I2S RX1; and
* things like that. 0x1: writing '1' to enable the corresponding BF
* sound channel. 0x0: writing '0' to close the corresponding BF sound
* channel.
*/
uint32_t bf_sound_ch_en : 8;
/**
* Target direction select for valid voice output.
* When the source voice direaction searching is done, software can use
* this field to select one from 16 sound directions for the following
* voice recognition. 0x0: select sound direction 0; 0x1: select sound
* direction 1; . . . . . . 0xF: select sound direction 15.
*/
uint32_t bf_target_dir : 4;
/**
* This is the audio sample gain factor. Using this gain factor to
* enhance or reduce the stength of the sum of at most 8 source
* sound channel outputs. This is a unsigned 11-bit fix-point number,
* bit 10 is integer part and bit 9~0 are the fractional part.
*/
uint32_t audio_gain : 11;
uint32_t reserved1 : 1;
/**
* audio data source configure parameter. This parameter controls where
* the audio data source comes from. 0x0: audio data directly sourcing
* from apu internal buffer; 0x1: audio data sourcing from
* FFT result buffer.
*/
uint32_t data_src_mode : 1;
uint32_t reserved2 : 3;
/**
* write enable for bf_sound_ch_en parameter.
* 0x1: allowing updates made to 'bf_sound_ch_en'.
* Access Mode: write only
*/
uint32_t we_bf_sound_ch_en : 1;
/**
* write enable for bf_target_dir parameter.
* 0x1: allowing updates made to 'bf_target_dir'.
* Access Mode: write only
*/
uint32_t we_bf_target_dir : 1;
/**
* write enable for audio_gain parameter.
* 0x1: allowing updates made to 'audio_gain'.
* Access Mode: write only
*/
uint32_t we_audio_gain : 1;
/**
* write enable for data_out_mode parameter.
* 0x1: allowing updates made to 'data_src_mode'.
*/
uint32_t we_data_src_mode : 1;
} __attribute__((packed, aligned(4)));
struct apu_ctl_t
{
/**
* Sound direction searching enable bit.
* Software writes '1' to start sound direction searching function.
* When all the sound sample buffers are filled full, this bit is
* cleared by hardware (this sample buffers are used for direction
* detect only). 0x1: enable direction searching.
*/
uint32_t bf_dir_search_en : 1;
/*
*use this parameter to reset all the control logic on direction search processing path. This bit is self-clearing.
* 0x1: apply reset to direction searching control logic;
* 0x0: No operation.
*/
uint32_t search_path_reset : 1;
uint32_t reserved : 2;
/**
* Valid voice sample stream generation enable bit.
* After sound direction searching is done, software can configure this
* bit to generate a stream of voice samples for voice recognition. 0x1:
* enable output of voice sample stream. 0x0: stop the voice samlpe
* stream output.
*/
uint32_t bf_stream_gen_en : 1;
/*
*use this parameter to reset all the control logic on voice stream generating path. This bit is self-clearing.
* 0x1: apply reset to voice stream generating control logic;
* 0x0: No operation.
*/
uint32_t voice_gen_path_reset : 1;
/*
*use this parameter to switch to a new voice source direction. Software write '1' here and hardware will automatically clear it.
* 0x1: write '1' here to request switching to new voice source direction.
*/
uint32_t update_voice_dir : 1;
uint32_t reserved1 : 1;
//write enable for 'bf_dir_search_en' parameter.
uint32_t we_bf_dir_search_en : 1;
uint32_t we_search_path_rst : 1;
uint32_t we_bf_stream_gen : 1;
uint32_t we_voice_gen_path_rst : 1;
uint32_t we_update_voice_dir : 1;
uint32_t reserved2 : 19;
} __attribute__((packed, aligned(4)));
struct apu_dir_bidx_t
{
uint32_t dir_rd_idx0 : 6;
uint32_t reserved : 2;
uint32_t dir_rd_idx1 : 6;
uint32_t reserved1 : 2;
uint32_t dir_rd_idx2 : 6;
uint32_t reserved2 : 2;
uint32_t dir_rd_idx3 : 6;
uint32_t reserved3 : 2;
} __attribute__((packed, aligned(4)));
struct apu_fir_coef_t
{
uint32_t fir_tap0 : 16;
uint32_t fir_tap1 : 16;
} __attribute__((packed, aligned(4)));
struct apu_dwsz_cfg_t
{
/**
* TThe down-sizing ratio used for direction searching.
* 0x0: no down-sizing;
* 0x1: 1/2 down sizing;
* 0x2: 1/3 down sizing;
* . . . . . .
* 0xF: 1/16 down sizing.
*/
uint32_t dir_dwn_siz_rate : 4;
/**
* The down-sizing ratio used for voice stream generation.
* 0x0: no down-sizing;
* 0x1: 1/2 down sizing;
* 0x2: 1/3 down sizing;
* . . . . . .
* 0xF: 1/16 down sizing.
*/
uint32_t voc_dwn_siz_rate : 4;
/**
* This bit field is used to perform sample precision reduction when
* the source sound sample (from I2S0 host receiving channels)
* precision is 20/24/32 bits.
* 0x0: take bits 15~0 from the source sound sample;
* 0x1: take bits 16~1 from the source sound sample;
* 0x2: take bits 17~2 from the source sound sample;
* . . . . . .
* 0x10: take bits 31~16 from the source sound sample;
*/
uint32_t smpl_shift_bits : 5;
uint32_t reserved : 19;
} __attribute__((packed, aligned(4)));
//0x31c
struct apu_fft_cfg_t
{
uint32_t fft_shift_factor : 9;
uint32_t reserved1 : 3;
uint32_t fft_enable : 1;
uint32_t reserved2 : 19;
} __attribute__((packed, aligned(4)));
//0x328
struct apu_int_stat_t
{
/**
* sound direction searching data ready interrupt event.
* Writing '1' to clear this interrupt event.
* 0x1: data is ready for sound direction detect;
* 0x0: no event.
*/
uint32_t dir_search_data_rdy : 1;
/**
* voice output stream buffer data ready interrupt event.
* When a block of 512 voice samples are collected, this interrupt event
* is asserted. Writing '1' to clear this interrupt event. 0x1: voice
* output stream buffer data is ready; 0x0: no event.
*/
uint32_t voc_buf_data_rdy : 1;
uint32_t reserved : 30;
} __attribute__((packed, aligned(4)));
/*
*/
//0x32c
struct apu_int_mask_t
{
/**
* This is the interrupt mask to dir searching data ready interrupt.
* 0x1: mask off this interrupt;
* 0x0: enable this interrupt.
*/
uint32_t dir_data_rdy_msk : 1;
/**
* This is the interrupt mask to voice output stream buffer ready
* interrupt. 0x1: mask off this interrupt; 0x0: enable this interrupt.
*/
uint32_t voc_buf_rdy_msk : 1;
uint32_t reserved : 30;
} __attribute__((packed, aligned(4)));
struct apu_reg_t
{
//0x200
struct apu_ch_cfg_t bf_ch_cfg_reg;
//0x204
struct apu_ctl_t bf_ctl_reg;
//0x208
struct apu_dir_bidx_t bf_dir_bidx[16][2];
//0x288
struct apu_fir_coef_t bf_pre_fir0_coef[9];
//0x2ac
struct apu_fir_coef_t bf_post_fir0_coef[9];
//0x2d0
struct apu_fir_coef_t bf_pre_fir1_coef[9];
//0x2f4
struct apu_fir_coef_t bf_post_fir1_coef[9];
//0x318
struct apu_dwsz_cfg_t bf_dwsz_cfg_reg;
//0x31c
struct apu_fft_cfg_t bf_fft_cfg_reg;
// 0x320
/**
* This is the read register for system DMA to read data stored in
* sample out buffers (the sample out buffers are used for sound
* direction detect). Each data contains two sound samples.
*/
volatile uint32_t sobuf_dma_rdata;
// 0x324
/**
* This is the read register for system DMA to read data stored in voice
* out buffers (the voice out buffers are used for voice recognition).
* Each data contains two sound samples.
*/
volatile uint32_t vobuf_dma_rdata;
//0x328
struct apu_int_stat_t bf_int_stat_reg;
//0x32c
struct apu_int_mask_t bf_int_mask_reg;
//0x330
uint32_t saturation_counter;
//0x334
uint32_t saturation_limits;
} __attribute__((packed, aligned(4)));
void apu_set_audio_gain(uint16_t gain);
void apu_set_smpl_shift(uint8_t smpl_shift);
uint8_t apu_get_smpl_shift(void);
void apu_set_channel_enabled(uint8_t channel_bit);
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx);
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor);
void apu_set_down_size(uint8_t dir_dwn_siz, uint8_t voc_dwn_siz); //split to 2 functions
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask); //split to 2 functions
void apu_dir_enable(void);
void apu_dir_reset(void);
void apu_dir_set_prev_fir(uint16_t *fir_coef);
void apu_dir_set_post_fir(uint16_t *fir_coef);
void apu_dir_set_down_size(uint8_t dir_dwn_size);
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask);
void apu_dir_clear_int_state(void);
void apu_voc_enable(uint8_t enable_flag);
void apu_voc_reset(void);
void apu_voc_set_direction(enum en_bf_dir direction);
void apu_voc_set_prev_fir(uint16_t *fir_coef);
void apu_voc_set_post_fir(uint16_t *fir_coef);
void apu_voc_set_down_size(uint8_t voc_dwn_size);
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask);
void apu_voc_clear_int_state(void);
void apu_voc_reset_saturation_counter(void);
uint32_t apu_voc_get_saturation_counter(void);
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom);
uint32_t apu_voc_get_saturation_limit(void);
void apu_print_setting(void);
#if defined(__cplusplus)
}
#endif
#endif