ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_dac.c
Go to the documentation of this file.
1
27
28#include <stdint.h>
29#include <stdio.h>
30
31#include "board_console.h"
32#include "board_periph_block.h"
34
36typedef enum : uint32_t {
40
42typedef enum : uint64_t {
43 k_dac_base = 0x40233000UL,
44 k_dac_stride = 0x100UL,
46 k_dac_span = 0x200UL,
47 k_dac_inst_words = 0x100UL / 4UL,
48 k_dac_off_dadr = 0x00UL,
49 k_dac_off_dacr0 = 0x04UL,
50 k_dac_off_dacr1 = 0x08UL,
51 k_dac_off_dacr2 = 0x0CUL,
52} dac_map_t;
53
55typedef enum : uint32_t {
56 k_dac_dadr_mask = 0x00000FFFUL,
57 k_dac_dacen_mask = 0x00000001UL,
59
61typedef struct {
63 uint16_t last;
64 uint16_t peak;
65 uint32_t writes;
67
69
81RA8_INTERNAL static uint32_t internal_dac_word(uint64_t inst_off)
82{
83 return (uint32_t)(inst_off >> 2U);
84}
85
99RA8_INTERNAL static uint64_t internal_dac_read(uc_engine* uc, uint64_t addr, unsigned size)
100{
101 (void)uc;
102 (void)size;
103 const uint64_t off = addr - (uint64_t)k_dac_base;
104 const uint32_t inst = (uint32_t)(off / (uint64_t)k_dac_stride);
105 if (inst >= (uint32_t)k_dac_count) {
106 return 0U;
107 }
108 const uint64_t inst_off = off % (uint64_t)k_dac_stride;
109 if (inst_off >= (uint64_t)k_dac_stride) {
110 return 0U;
111 }
112 return s_dac[inst].reg[internal_dac_word(inst_off)];
113}
114
127RA8_INTERNAL static void
128internal_dac_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
129{
130 (void)uc;
131 (void)size;
132 const uint64_t off = addr - (uint64_t)k_dac_base;
133 const uint32_t inst = (uint32_t)(off / (uint64_t)k_dac_stride);
134 if (inst >= (uint32_t)k_dac_count) {
135 return;
136 }
137 const uint64_t inst_off = off % (uint64_t)k_dac_stride;
138 if (inst_off >= (uint64_t)k_dac_stride) {
139 return;
140 }
141 s_dac[inst].reg[internal_dac_word(inst_off)] = (uint32_t)value;
142 if (inst_off == (uint64_t)k_dac_off_dadr) {
143 const uint16_t code = (uint16_t)((uint32_t)value & (uint32_t)k_dac_dadr_mask);
144 s_dac[inst].last = code;
145 if (code > s_dac[inst].peak) {
146 s_dac[inst].peak = code;
147 }
148 s_dac[inst].writes++;
149 /* Console DAC tab: anti-flood -- the first update and then every Nth update
150 * (a continuous waveform writes per-sample, so one line per N keeps the ring
151 * readable while still showing the channel is active). */
152 bool should_report = (s_dac[inst].writes == 1U);
153 if ((s_dac[inst].writes % (uint32_t)k_dac_console_every) == 0U) {
154 should_report = true;
155 }
156 if (should_report) {
157 char ln[k_dac_console_line_cap];
158 (void)snprintf(ln,
159 sizeof(ln),
160 "DAC%u code=%u (n=%u)",
161 (unsigned)inst,
162 (unsigned)code,
163 (unsigned)s_dac[inst].writes);
165 }
166 if (board_periph_trace()) {
167 (void)priv_emu_io_errf(" [trace] DAC_B%u <- code=%u\n", inst, code);
168 }
169 }
170}
171
181{
182 for (uint32_t i = 0U; i < (uint32_t)k_dac_count; i++) {
183 s_dac[i] = (dac_inst_t){};
184 }
185}
186
196{
197 for (uint32_t i = 0U; i < (uint32_t)k_dac_count; i++) {
198 if (s_dac[i].writes == 0U) {
199 continue;
200 }
201 (void)priv_emu_io_errf(
202 " DAC_B%u : writes=%u last=%u peak=%u enabled=%s\n",
203 i,
204 s_dac[i].writes,
205 s_dac[i].last,
206 s_dac[i].peak,
207 (s_dac[i].reg[internal_dac_word((uint64_t)k_dac_off_dacr0)] & (uint32_t)k_dac_dacen_mask)
208 ? "yes"
209 : "no");
210 }
211}
212
215 .base = (uint64_t)k_dac_base,
216 .span = (uint64_t)k_dac_span,
217 .order = (uint32_t)k_block_order_i2c, /* After the timers/UART; no tick. */
218 .read = internal_dac_read,
220 .tick = nullptr,
221 .reset = internal_dac_reset,
222 .report = internal_dac_report,
223 .name = "DAC_B",
224};
225
227[[gnu::constructor]] RA8_INTERNAL static void internal_board_periph_dac_register(void)
228{
230}
Multi-channel console log store backing the board view's tabbed console.
void board_console_push(board_console_ch_t ch, const char *line)
Append one completed line to a channel ring and the ALL ring.
@ k_board_console_ch_dac
DAC_B output summaries.
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
@ k_block_order_i2c
I3C/I2C + GT911 (no tick today).
bool board_periph_trace(void)
Whether –trace is active (blocks log transitions when true).
static RA8_INTERNAL void internal_dac_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the DAC window: latch the value; track DADR.
static RA8_INTERNAL void internal_dac_reset(void)
Clear both DAC_B instances' registers and observability state.
static RA8_INTERNAL uint32_t internal_dac_word(uint64_t inst_off)
Word index into an instance's backing store for an in-instance offset.
static RA8_INTERNAL uint64_t internal_dac_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the DAC window: read back the latched register.
static RA8_INTERNAL void internal_board_periph_dac_register(void)
Self-register the DAC_B block before main runs (decentralized).
dac_console_t
Console-tap sizing for DAC output summaries.
@ k_dac_console_every
Push 1 line per N updates (anti-flood).
@ k_dac_console_line_cap
Max chars in a "DAC.. code=.." line.
dac_map_t
DAC_B block geometry (ra8_dac_b_regs.h, FSP R_DAC_B0_Type).
@ k_dac_off_dacr0
DACR0 control (DACEN/DAE/DAOUTDIS).
@ k_dac_off_dacr1
DACR1 control (DPSEL).
@ k_dac_count
DAC_B0 / DAC_B1.
@ k_dac_span
Both instances (2 x 0x100 stride).
@ k_dac_off_dadr
DADR 12-bit data (16-bit reg).
@ k_dac_stride
Bytes between DAC_B0 and DAC_B1.
@ k_dac_inst_words
Backing words per instance.
@ k_dac_off_dacr2
DACR2 control (OFSSEL).
@ k_dac_base
DAC_B0 base.
static RA8_INTERNAL void internal_dac_report(void)
Print one line per DAC_B instance that the firmware drove.
dac_field_t
DAC_B field masks.
@ k_dac_dacen_mask
DACR0.DACEN channel-enable bit.
@ k_dac_dadr_mask
12-bit DADR data field.
static const board_periph_block_t s_k_dac_block
This block's descriptor (static lifetime; the core keeps the pointer).
static dac_inst_t s_dac[k_dac_count]
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.
One DAC_B instance: register backing store + write observability.
uint16_t last
Last DADR code written.
uint16_t peak
Largest DADR code seen.
uint32_t writes
DADR write count.
uint32_t reg[k_dac_inst_words]
Word-addressed register backing.