10 #include <xcore/interrupt.h> 
   11 #include <xcore/channel_streaming.h> 
   12 #include <xcore/port.h> 
   14 #include "mic_array.h" 
   18 #if defined(BLOCK_SIZE) || defined(CHANNELS_IN) || defined(CHANNELS_OUT) || defined(SUBBLOCKS) 
   19 # error Application must not define the following as precompiler macros: MIC_COUNT, CHANNELS_IN, CHANNELS_OUT, SUBBLOCKS. 
   35     uint32_t* pdm_buffer[2];
 
   52   void enable_pdm_rx_isr(
 
   53       const port_t p_pdm_mics)
 
   57       "ldap r11, pdm_rx_isr   \n" 
   58       "setv res[%0], r11      \n" 
   61         : 
"r"(p_pdm_mics), 
"r"(XS1_SETC_IE_MODE_INTERRUPT)
 
  100   template <
unsigned BLOCK_SIZE, 
class SubType>
 
  111       static constexpr 
unsigned BlockSize = BLOCK_SIZE;
 
  122       unsigned phase = BLOCK_SIZE;
 
  127       uint32_t block_data[2][BLOCK_SIZE];
 
  136       uint32_t* blocks[2] = {&block_data[0][0], &block_data[1][0]};
 
  248   template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  250                                       StandardPdmRxService<CHANNELS_IN, CHANNELS_OUT, SUBBLOCKS>>
 
  262       streaming_channel_t c_pdm_blocks;
 
  273       unsigned channel_map[CHANNELS_OUT];
 
  283       uint32_t out_block[CHANNELS_OUT][SUBBLOCKS];
 
  300       void SendBlock(uint32_t block[CHANNELS_IN * SUBBLOCKS]);
 
  307       void Init(port_t p_pdm_mics);
 
  323       void MapChannels(
unsigned map[CHANNELS_OUT]);
 
  340       void MapChannel(
unsigned out_channel, 
unsigned in_channel);
 
  365       uint32_t* GetPdmBlock();
 
  379 template <
unsigned BLOCK_SIZE, 
class SubType>
 
  382   this->p_pdm_mics = p_pdm_mics;
 
  386 template <
unsigned BLOCK_SIZE, 
class SubType>
 
  389   this->blocks[0][--phase] =  
static_cast<SubType*
>(
this)->ReadPort();
 
  392     this->phase = BLOCK_SIZE;
 
  393     uint32_t* ready_block = this->blocks[0];
 
  394     this->blocks[0] = this->blocks[1];
 
  395     this->blocks[1] = ready_block;
 
  397     static_cast<SubType*
>(
this)->SendBlock(ready_block);
 
  402 template <
unsigned BLOCK_SIZE, 
class SubType>
 
  417 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  421   return port_in(this->p_pdm_mics);
 
  425 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  429   s_chan_out_word(this->c_pdm_blocks.end_a, 
 
  430                   reinterpret_cast<uint32_t
>( &block[0] ));
 
  434 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  438   for(
int k = 0; k < CHANNELS_OUT; k++)
 
  439     this->channel_map[k] = k;
 
  441   this->c_pdm_blocks = s_chan_alloc();
 
  443   this->SetPort(p_pdm_mics);
 
  447 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  451   for(
int k = 0; k < CHANNELS_OUT; k++)
 
  452     this->channel_map[k] = map[k];
 
  456 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  460   this->channel_map[out_channel] = in_channel;
 
  464 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  468   pdm_rx_isr_context.p_pdm_mics = this->p_pdm_mics;
 
  469   pdm_rx_isr_context.c_pdm_data = this->c_pdm_blocks.end_a;
 
  470   pdm_rx_isr_context.pdm_buffer[0] = &this->block_data[0][0];
 
  471   pdm_rx_isr_context.pdm_buffer[1] = &this->block_data[1][0];
 
  472   pdm_rx_isr_context.phase_reset = CHANNELS_IN*SUBBLOCKS-1;
 
  473   pdm_rx_isr_context.phase = CHANNELS_IN*SUBBLOCKS-1;
 
  475   enable_pdm_rx_isr(this->p_pdm_mics);
 
  479 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  483   interrupt_unmask_all();
 
  487 template <
unsigned CHANNELS_IN, 
unsigned CHANNELS_OUT, 
unsigned SUBBLOCKS>
 
  491   uint32_t* full_block = (uint32_t*) s_chan_in_word(this->c_pdm_blocks.end_b);
 
  492   mic_array::deinterleave_pdm_samples<CHANNELS_IN>(full_block, SUBBLOCKS);
 
  494   uint32_t (*block)[CHANNELS_IN] = (uint32_t (*)[CHANNELS_IN]) full_block;
 
  496   for(
int ch = 0; ch < CHANNELS_OUT; ch++) {
 
  497     for(
int sb = 0; sb < SUBBLOCKS; sb++) {
 
  498       unsigned d = this->channel_map[ch];
 
  499       this->out_block[ch][sb] = block[SUBBLOCKS-1-sb][d];
 
  502   return &this->out_block[0][0];
 
Used to collect PDM sample data from a port.
Definition: PdmRx.hpp:102
void ThreadEntry()
Entry point for PDM processing thread.
Definition: PdmRx.hpp:403
port_t p_pdm_mics
Port from which to collect PDM data.
Definition: PdmRx.hpp:117
void SetPort(port_t p_pdm_mics)
Set the port from which to collect PDM samples.
Definition: PdmRx.hpp:380
void ProcessNext()
Perform a port read and if a new block has completed, signal.
Definition: PdmRx.hpp:387
PDM rx service which uses a streaming channel to send a block of data by pointer.
Definition: PdmRx.hpp:251
uint32_t * GetPdmBlock()
Get a block of PDM data.
Definition: PdmRx.hpp:489
void SendBlock(uint32_t block[CHANNELS_IN *SUBBLOCKS])
Send a block of PDM data to a listener.
Definition: PdmRx.hpp:427
uint32_t ReadPort()
Read a word of PDM data from the port.
Definition: PdmRx.hpp:419
void InstallISR()
Install ISR for PDM reception on the current core.
Definition: PdmRx.hpp:466
void Init(port_t p_pdm_mics)
Initialize this object with a channel and port.
Definition: PdmRx.hpp:436
void MapChannels(unsigned map[CHANNELS_OUT])
Set the input-output mapping for all output channels.
Definition: PdmRx.hpp:449
void MapChannel(unsigned out_channel, unsigned in_channel)
Set the input-output mapping for a single output channel.
Definition: PdmRx.hpp:458
void UnmaskISR()
Unmask interrupts on the current core.
Definition: PdmRx.hpp:481