ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_pdm.c File Reference

PDM-IF (digital MEMS microphone) peripheral-block model for ra8_emulator. More...

#include <stdint.h>
#include <stdio.h>
#include "board_console.h"
#include "board_periph_block.h"
#include "emu_host_io_internal.h"
Include dependency graph for board_periph_pdm.c:

Go to the source code of this file.

Data Structures

struct  pdm_channel_t
 One modelled PDM channel: run/enable gates + synthetic-tone state. More...

Enumerations

enum  pdm_map_t : uint64_t {
  k_pdm_base = 0x40256000UL ,
  k_pdm_span = 0x400UL ,
  k_pdm_words = 0x400UL / 4UL ,
  k_pdm_ch_count = 3UL ,
  k_pdm_ch0_off = 0x100UL ,
  k_pdm_ch_stride = 0x100UL ,
  k_pdm_off_cstrtr = 0x00UL ,
  k_pdm_off_cstptr = 0x04UL ,
  k_pdm_off_csr = 0x10UL ,
  k_pdm_ch_pddrcr = 0xE0UL ,
  k_pdm_ch_pddrr = 0xE8UL ,
  k_pdm_ch_pddsr = 0xECUL
}
 PDM-IF register-window geometry (ra8_pdm_regs.h). More...
enum  pdm_field_t : uint32_t {
  k_pdm_pddrcr_datre = 0x1U ,
  k_pdm_pddsr_num = 0x000000FFU ,
  k_pdm_pddrr_mask20 = 0x000FFFFFU ,
  k_pdm_fifo_depth = 32U
}
 PDM-IF register field masks / bits (ra8_pdm_regs.h). More...
enum  pdm_tone_t : uint32_t {
  k_pdm_tone_period = 64U ,
  k_pdm_tone_qmask = 63U ,
  k_pdm_tone_half = 32U
}
 Synthetic-tone shape constants (deterministic, integer-only). More...
enum  pdm_amp_t : int32_t {
  k_pdm_tone_amp = 20000 ,
  k_pdm_tone_step = 1250
}
 Synthetic-tone amplitude / slope (20-bit signed, well below +-524288). More...
enum  pdm_dither_t : uint32_t {
  k_pdm_lcg_mul = 1664525U ,
  k_pdm_lcg_add = 1013904223U ,
  k_pdm_lcg_shift = 16U ,
  k_pdm_dither_mask = 0x3FFU ,
  k_pdm_dither_half = 512U
}
 Per-channel pseudo-random dither (window-to-window variety). More...
enum  pdm_console_t : uint32_t {
  k_pdm_console_line_cap = 48U ,
  k_pdm_console_every = 512U
}
 Console anti-flood cadence for the PDM (I2S/audio) tab. More...

Functions

static RA8_INTERNAL bool internal_pdm_live (uint32_t ch)
 True when channel ch is both started and read-enabled.
static RA8_INTERNAL uint32_t internal_pdm_next_sample (uint32_t ch)
 Next 20-bit two's-complement PCM sample for a live channel.
static RA8_INTERNAL void internal_pdm_console_maybe (uint32_t ch)
 Push an anti-flood "PDMn samples=.." line to the I2S/audio tab.
static RA8_INTERNAL bool internal_pdm_channel_at (uint64_t off, uint32_t *ch, uint64_t *ch_off)
 Compute the channel index + in-bank offset for an in-window address.
static RA8_INTERNAL uint32_t internal_pdm_read_csr (void)
 PDCSR: one run bit per currently-started channel.
static RA8_INTERNAL uint64_t internal_pdm_read (uc_engine *uc, uint64_t addr, unsigned size)
 MMIO read inside the PDM window.
static RA8_INTERNAL void internal_pdm_write (uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
 MMIO write inside the PDM window: latch, then update run/enable gates.
static RA8_INTERNAL void internal_pdm_reset (void)
 Clear all PDM channel + shadow state to power-on.
static RA8_INTERNAL void internal_pdm_report (void)
 Print one line per PDM channel the firmware captured from.
static RA8_INTERNAL void internal_board_periph_pdm_register (void)
 Self-register the PDM-IF block before main runs (decentralized).

Variables

static pdm_channel_t s_pdm [k_pdm_ch_count]
static uint32_t s_pdm_reg [k_pdm_words]
 Reflect-on-read shadow.
static const board_periph_block_t s_k_pdm_block
 This block's descriptor (static lifetime; the core keeps the pointer).

Detailed Description

PDM-IF (digital MEMS microphone) peripheral-block model for ra8_emulator.

Models the single RA8D2 PDM-IF block at 0x4025_6000 (ra8_pdm_regs.h / ra8_pdm.c, the real HUM Ch 49 PDM-IF). The firmware read path (ra8_pdm_read) polls a channel's data-status register PDDSR.NUM for the FIFO fill count, then drains that many 20-bit signed PCM samples out of the data-read register PDDRR. The stop path (ra8_pdm_stop) polls the common channel-status register PDCSR until the channel's run bit clears.

This block turns that register set into a synthetic-audio source. A channel only produces samples once it has been BOTH started (a PDCSTRTR bit for it) AND had its data read enabled (PDDRCR.DATRE) – the honest-model rule from issue #218: an unconfigured / unstarted read yields zero samples (PDDSR.NUM reads 0, PDDRR reads 0), never a faked pass. Once live, PDDSR reports a full FIFO and each PDDRR read yields the next sample of a deterministic low-amplitude triangle tone plus a small pseudo-random dither, so the tone is a genuine non-degenerate signal (non-trivial RMS / peak / span) and drifts window-to-window – exactly what pdm_mic_demo's plausibility check needs to report active=Y on a real signal rather than on the sparse fallback's degenerate 0/-1 toggle.

The value path is synthetic (ra8_emulator has no analog microphone); this is a run-headless enabler, not a claim about a physical mic. Self-registers its descriptor with the board_periph core from a file-scope constructor – see board_periph_block.h.

Since
0.1.0

Definition in file board_periph_pdm.c.

Enumeration Type Documentation

◆ pdm_amp_t

enum pdm_amp_t : int32_t

Synthetic-tone amplitude / slope (20-bit signed, well below +-524288).

Enumerator
k_pdm_tone_amp 

Triangle peak amplitude (+-).

k_pdm_tone_step 

Per-sample slope = 2*amp / (period/2).

Definition at line 74 of file board_periph_pdm.c.

◆ pdm_console_t

enum pdm_console_t : uint32_t

Console anti-flood cadence for the PDM (I2S/audio) tab.

Enumerator
k_pdm_console_line_cap 

Max chars in a "PDM.. samples=.." line.

k_pdm_console_every 

Push one line per N samples per channel.

Definition at line 89 of file board_periph_pdm.c.

◆ pdm_dither_t

enum pdm_dither_t : uint32_t

Per-channel pseudo-random dither (window-to-window variety).

Enumerator
k_pdm_lcg_mul 

LCG multiplier (Numerical Recipes).

k_pdm_lcg_add 

LCG increment (Numerical Recipes).

k_pdm_lcg_shift 

Take the high bits (better spread).

k_pdm_dither_mask 

10-bit dither window (0..1023).

k_pdm_dither_half 

Centre the dither at 0 (+-512).

Definition at line 80 of file board_periph_pdm.c.

◆ pdm_field_t

enum pdm_field_t : uint32_t

PDM-IF register field masks / bits (ra8_pdm_regs.h).

Enumerator
k_pdm_pddrcr_datre 

PDDRCR[0] data-read enable.

k_pdm_pddsr_num 

PDDSR[7:0] FIFO fill count field.

k_pdm_pddrr_mask20 

PDDRR[19:0] 20-bit two's-complement.

k_pdm_fifo_depth 

Samples reported available when live.

Definition at line 59 of file board_periph_pdm.c.

◆ pdm_map_t

enum pdm_map_t : uint64_t

PDM-IF register-window geometry (ra8_pdm_regs.h).

Enumerator
k_pdm_base 

PDM-IF block base (HUM Ch 49).

k_pdm_span 

Common bank + 3 channel banks.

k_pdm_words 

Backing-store word count.

k_pdm_ch_count 

PDM channels (CH0..CH2).

k_pdm_ch0_off 

Offset of the first channel bank.

k_pdm_ch_stride 

Bytes between channel banks.

k_pdm_off_cstrtr 

PDCSTRTR common start trigger.

k_pdm_off_cstptr 

PDCSTPTR common stop trigger.

k_pdm_off_csr 

PDCSR common channel status.

k_pdm_ch_pddrcr 

CHn PDDRCR data-read control.

k_pdm_ch_pddrr 

CHn PDDRR 20-bit PCM data read.

k_pdm_ch_pddsr 

CHn PDDSR data status (fill count).

Definition at line 43 of file board_periph_pdm.c.

◆ pdm_tone_t

enum pdm_tone_t : uint32_t

Synthetic-tone shape constants (deterministic, integer-only).

Enumerator
k_pdm_tone_period 

Samples per triangle cycle (power of two).

k_pdm_tone_qmask 

period-1: phase wrap mask.

k_pdm_tone_half 

period/2: rising-then-falling split point.

Definition at line 67 of file board_periph_pdm.c.

Function Documentation

◆ internal_board_periph_pdm_register()

RA8_INTERNAL void internal_board_periph_pdm_register ( void )
static

Self-register the PDM-IF block before main runs (decentralized).

Definition at line 366 of file board_periph_pdm.c.

References board_periph_register_block(), RA8_INTERNAL, and s_k_pdm_block.

◆ internal_pdm_channel_at()

RA8_INTERNAL bool internal_pdm_channel_at ( uint64_t off,
uint32_t * ch,
uint64_t * ch_off )
static

Compute the channel index + in-bank offset for an in-window address.

Compute the channel index + in-bank offset for an in-window address; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Parameters
[in]offRegister or byte offset addressed by the operation.
[in,out]chSelected channel identifier.
[in,out]ch_offCh off state or storage updated in place by the operation.
Returns
The PDM channel at result produced by the board periph PDM model.
Return values
trueThe PDM channel at condition holds or completed successfully; false otherwise.
Precondition
Arguments satisfy the ranges documented for PDM channel at.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 190 of file board_periph_pdm.c.

References k_pdm_ch0_off, k_pdm_ch_count, k_pdm_ch_stride, and RA8_INTERNAL.

Referenced by internal_pdm_read(), and internal_pdm_write().

◆ internal_pdm_console_maybe()

RA8_INTERNAL void internal_pdm_console_maybe ( uint32_t ch)
static

Push an anti-flood "PDMn samples=.." line to the I2S/audio tab.

Push an anti-flood "pdmn samples=.." line to the i2s/audio tab; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Parameters
[in]chSelected channel identifier.
Precondition
Arguments satisfy the ranges documented for PDM console maybe.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 166 of file board_periph_pdm.c.

References board_console_push(), k_board_console_ch_i2s, k_pdm_console_every, k_pdm_console_line_cap, RA8_INTERNAL, and s_pdm.

Referenced by internal_pdm_read().

◆ internal_pdm_live()

RA8_INTERNAL bool internal_pdm_live ( uint32_t ch)
static

True when channel ch is both started and read-enabled.

True when channel ch is both started and read-enabled; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Parameters
[in]chSelected channel identifier.
Returns
The PDM live result produced by the board periph PDM model.
Return values
trueThe PDM live condition holds or completed successfully; false otherwise.
Precondition
Arguments satisfy the ranges documented for PDM live.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 117 of file board_periph_pdm.c.

References k_pdm_ch_count, RA8_INTERNAL, and s_pdm.

Referenced by internal_pdm_read().

◆ internal_pdm_next_sample()

RA8_INTERNAL uint32_t internal_pdm_next_sample ( uint32_t ch)
static

Next 20-bit two's-complement PCM sample for a live channel.

Next 20-bit two's-complement pcm sample for a live channel; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Parameters
[in]chSelected channel identifier.
Returns
The PDM next sample result produced by the board periph PDM model.
Return values
valueThe operation-specific PDM next sample value.
Precondition
Arguments satisfy the ranges documented for PDM next sample.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 136 of file board_periph_pdm.c.

References k_pdm_dither_half, k_pdm_dither_mask, k_pdm_lcg_add, k_pdm_lcg_mul, k_pdm_lcg_shift, k_pdm_pddrr_mask20, k_pdm_tone_amp, k_pdm_tone_half, k_pdm_tone_qmask, k_pdm_tone_step, pdm_channel_t::lcg, pdm_channel_t::phase, RA8_INTERNAL, s_pdm, and pdm_channel_t::samples.

Referenced by internal_pdm_read().

◆ internal_pdm_read()

RA8_INTERNAL uint64_t internal_pdm_read ( uc_engine * uc,
uint64_t addr,
unsigned size )
static

MMIO read inside the PDM window.

MMIO read inside the pdm window; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]addrGuest address involved in the operation.
[in]sizeSize of the requested region or access in bytes.
Returns
The PDM read result produced by the board periph PDM model.
Return values
valueThe operation-specific PDM read value.
Precondition
Arguments satisfy the ranges documented for PDM read.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 235 of file board_periph_pdm.c.

References internal_pdm_channel_at(), internal_pdm_console_maybe(), internal_pdm_live(), internal_pdm_next_sample(), internal_pdm_read_csr(), k_pdm_base, k_pdm_ch_pddrr, k_pdm_ch_pddsr, k_pdm_fifo_depth, k_pdm_off_csr, k_pdm_pddsr_num, k_pdm_span, RA8_INTERNAL, and s_pdm_reg.

◆ internal_pdm_read_csr()

RA8_INTERNAL uint32_t internal_pdm_read_csr ( void )
static

PDCSR: one run bit per currently-started channel.

Pdcsr: one run bit per currently-started channel; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Returns
The PDM read csr result produced by the board periph PDM model.
Return values
valueThe operation-specific PDM read csr value.
Precondition
Arguments satisfy the ranges documented for PDM read csr.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 211 of file board_periph_pdm.c.

References k_pdm_ch_count, RA8_INTERNAL, and s_pdm.

Referenced by internal_pdm_read().

◆ internal_pdm_report()

RA8_INTERNAL void internal_pdm_report ( void )
static

Print one line per PDM channel the firmware captured from.

Print one line per pdm channel the firmware captured from; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for PDM report.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 338 of file board_periph_pdm.c.

References k_pdm_ch_count, priv_emu_io_errf(), RA8_INTERNAL, and s_pdm.

◆ internal_pdm_reset()

RA8_INTERNAL void internal_pdm_reset ( void )
static

Clear all PDM channel + shadow state to power-on.

Clear all pdm channel + shadow state to power-on; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for PDM reset.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 320 of file board_periph_pdm.c.

References k_pdm_ch_count, k_pdm_words, RA8_INTERNAL, s_pdm, and s_pdm_reg.

◆ internal_pdm_write()

RA8_INTERNAL void internal_pdm_write ( uc_engine * uc,
uint64_t addr,
unsigned size,
uint64_t value )
static

MMIO write inside the PDM window: latch, then update run/enable gates.

MMIO write inside the pdm window: latch, then update run/enable gates; this step is contained within the board periph PDM model and uses bounded caller or module-owned storage.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]addrGuest address involved in the operation.
[in]sizeSize of the requested region or access in bytes.
[in]valueRegister or payload value involved in the operation.
Precondition
Arguments satisfy the ranges documented for PDM write.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph PDM model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 279 of file board_periph_pdm.c.

References internal_pdm_channel_at(), k_pdm_base, k_pdm_ch_count, k_pdm_ch_pddrcr, k_pdm_off_cstptr, k_pdm_off_cstrtr, k_pdm_pddrcr_datre, k_pdm_span, s_pdm, and s_pdm_reg.

Variable Documentation

◆ s_k_pdm_block

const board_periph_block_t s_k_pdm_block
static
Initial value:
= {
.base = (uint64_t)k_pdm_base,
.span = (uint64_t)k_pdm_span,
.order = (uint32_t)k_block_order_i2c,
.tick = nullptr,
.name = "PDM-IF",
}
@ k_block_order_i2c
I3C/I2C + GT911 (no tick today).
static RA8_INTERNAL void internal_pdm_reset(void)
Clear all PDM channel + shadow state to power-on.
static RA8_INTERNAL uint64_t internal_pdm_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the PDM window.
static RA8_INTERNAL void internal_pdm_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the PDM window: latch, then update run/enable gates.
@ k_pdm_base
PDM-IF block base (HUM Ch 49).
@ k_pdm_span
Common bank + 3 channel banks.
static RA8_INTERNAL void internal_pdm_report(void)
Print one line per PDM channel the firmware captured from.
-proof

This block's descriptor (static lifetime; the core keeps the pointer).

Definition at line 353 of file board_periph_pdm.c.

Referenced by internal_board_periph_pdm_register().

◆ s_pdm

◆ s_pdm_reg

uint32_t s_pdm_reg[k_pdm_words]
static

Reflect-on-read shadow.

Definition at line 104 of file board_periph_pdm.c.

Referenced by internal_pdm_read(), internal_pdm_reset(), and internal_pdm_write().