ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
c6_cam_camera.c
Go to the documentation of this file.
1
14
15#include <stdint.h>
16
17#include "c6_camera_server.h"
18#include "ra8_attributes.h"
19#include "ra8_board_ek_ra8d2.h"
20#include "ra8_camera.h"
23#include "ra8_ceu.h"
24#include "ra8_ov5640.h"
25#include "ra8_time.h"
26
34
35typedef enum : uint16_t {
39
54
55typedef enum : uint8_t {
60
62typedef enum : uint8_t {
67
68[[gnu::section(".sdram_data"), gnu::aligned(32)]] static uint8_t s_jpeg[k_sensor_jpeg_buffer_bytes];
76static uint16_t s_last_sccb_reg;
79static bool s_sensor_bound;
81
97static ra8_err_t sensor_sccb_read(void* ctx, uint8_t address, uint16_t reg, uint8_t* out_value)
98{
99 const ra8_err_t err = ra8_board_camera_sccb_read_reg(ctx, address, reg, out_value);
101 s_last_sccb_reg = reg;
102 s_last_sccb_err = err;
103 return err;
104}
105
121static ra8_err_t sensor_sccb_write(void* ctx, uint8_t address, uint16_t reg, uint8_t value)
122{
123 const ra8_err_t err = ra8_board_camera_sccb_write_reg(ctx, address, reg, value);
125 s_last_sccb_reg = reg;
126 s_last_sccb_err = err;
127 return err;
128}
129
144{
145 const ra8_ov5640_bus_t bus = {
146 .read_reg = sensor_sccb_read,
147 .write_reg = sensor_sccb_write,
148 .delay_ms = ra8_board_camera_delay_ms,
149 .ctx = nullptr,
150 };
151 return ra8_ov5640_init(&s_sensor, &bus);
152}
153
167{
168 const ra8_ceu_config_t ceu = {
169 .width_px = (uint16_t)k_sensor_jpeg_width,
170 .height_px = (uint16_t)k_sensor_jpeg_height,
171 .x_capture_px = (uint16_t)k_sensor_jpeg_width,
172 .y_capture_lines = (uint16_t)k_sensor_jpeg_height,
173 .bytes_per_pixel = 1U,
174 .dst_stride = (uint16_t)k_sensor_jpeg_width,
175 .capture_format = k_ra8_ceu_fmt_data_enable,
176 .capture_mode = k_ra8_ceu_capture_single,
177 .data_bus = k_ra8_ceu_bus_8_bit,
178 .hsync_polarity = k_ra8_ceu_pol_high_active,
179 .vsync_polarity = k_ra8_ceu_pol_high_active,
180 .field_polarity = k_ra8_ceu_pol_high_active,
181 .input_order = k_ra8_ceu_input_cb0_y0_cr0_y1,
182 .output_format = k_ra8_ceu_output_ycbcr_422,
183 .byte_swap = {.swap_8_bit = true, .swap_16_bit = true, .swap_32_bit = true},
184 .burst_mode = k_ra8_ceu_burst_256,
185 .first_field = k_ra8_ceu_field_immediate,
186 .edge = {k_ra8_ceu_edge_rising,
190 .image_area_size = (uint32_t)k_sensor_jpeg_buffer_bytes,
191 };
193 .ceu = ceu,
194 .output =
195 {
196 .frame_bytes_max = (uint32_t)k_sensor_jpeg_buffer_bytes,
197 .stride_bytes = 0U,
198 .width = (uint16_t)k_sensor_jpeg_width,
199 .height = (uint16_t)k_sensor_jpeg_height,
200 .format = k_ra8_camera_format_jpeg,
201 },
202 .poll_interval_ms = (uint32_t)k_sensor_jpeg_poll_ms,
203 .poll_attempts = (uint32_t)k_sensor_jpeg_poll_tries,
204 };
205}
206
228
245{
247 if (err == k_ra8_ok) {
249 }
250 if (err == k_ra8_ok) {
253 }
254 if (err == k_ra8_ok) {
255 err = sensor_bind();
256 if (err == k_ra8_ok) {
257 s_sensor_bound = true;
258 }
259 }
260 uint16_t chip_id = 0U;
261 if (err == k_ra8_ok) {
262 err = ra8_ov5640_probe(&s_sensor, &chip_id);
263 }
264 if ((err == k_ra8_ok) && (chip_id != (uint16_t)k_ra8_ov5640_chip_id)) {
266 }
267 if (err == k_ra8_ok) {
269 s_sensor_streaming = (err == k_ra8_ok);
270 }
271 return err;
272}
273
301
303{
306 if (err == k_ra8_ok) {
308 }
310 return err;
311}
312
327static uint32_t jpeg_trim_to_eoi(const uint8_t* jpeg, uint32_t bytes)
328{
329 if ((bytes < 4U) || (jpeg[0] != (uint8_t)k_jpeg_marker_prefix) ||
330 (jpeg[1] != (uint8_t)k_jpeg_marker_soi)) {
331 return 0U;
332 }
333 for (uint32_t i = 1U; i < bytes; i += 1U) {
334 if ((jpeg[i - 1U] == (uint8_t)k_jpeg_marker_prefix) &&
335 (jpeg[i] == (uint8_t)k_jpeg_marker_eoi)) {
336 return i + 1U;
337 }
338 }
339 return 0U;
340}
341
342ra8_err_t c6_cam_camera_capture_jpeg(const uint8_t** out_jpeg,
343 uint32_t* out_bytes,
344 c6_cam_frame_timing_t* out_timing)
345{
346 if ((out_jpeg == nullptr) || (out_bytes == nullptr) || (out_timing == nullptr)) {
347 return k_ra8_err_null_ptr;
348 }
349 *out_jpeg = nullptr;
350 *out_bytes = 0U;
351 *out_timing = (c6_cam_frame_timing_t){};
352 const uint32_t start = ra8_time_ms();
353 out_timing->timestamp_ms = start;
354 const ra8_camera_buffer_t buffer = {
355 .data = s_jpeg,
356 .capacity = (uint32_t)sizeof(s_jpeg),
357 };
358 ra8_err_t stream_err = k_ra8_ok;
359 if (!s_sensor_streaming) {
360 stream_err = ra8_ov5640_stream_set(&s_sensor, true);
361 s_sensor_streaming = (stream_err == k_ra8_ok);
362 }
363 if (stream_err != k_ra8_ok) {
364 return stream_err;
365 }
366 ra8_camera_frame_t frame = {};
367 const ra8_err_t err = ra8_camera_source_capture(&s_source, &buffer, &frame);
368 out_timing->capture_ms = ra8_time_ms() - start;
370 if (err != k_ra8_ok) {
371 return err;
372 }
373 const uint32_t jpeg_bytes = jpeg_trim_to_eoi(frame.data, frame.bytes);
374 if (jpeg_bytes == 0U) {
376 }
377 frame.bytes = jpeg_bytes;
378 const ra8_camera_buffer_t no_output = {};
379 ra8_camera_frame_t jpeg = {};
380 const ra8_err_t codec_err = ra8_camera_codec_encode(&s_codec, &frame, &no_output, &jpeg);
381 if (codec_err != k_ra8_ok) {
382 return codec_err;
383 }
384 *out_jpeg = jpeg.data;
385 *out_bytes = jpeg.bytes;
386 return k_ra8_ok;
387}
388
390{
391 return "frame=640x480 sensor-JPEG CEU data-enable backend";
392}
393
406static void sensor_report_register(const char* label, uint16_t reg)
407{
408 uint8_t value = 0U;
409 const ra8_err_t err = ra8_ov5640_read_reg(&s_sensor, reg, &value);
410 c6_cam_puts(label);
411 if (err == k_ra8_ok) {
412 c6_cam_put_u32(value);
413 } else {
415 }
416}
417
431{
432 c6_cam_puts(" sccb_op=");
434 c6_cam_puts("read");
435 } else if (s_last_sccb_op == k_sccb_op_write) {
436 c6_cam_puts("write");
437 } else {
438 c6_cam_puts("none");
439 }
440 c6_cam_puts(" sccb_reg=");
442 c6_cam_puts(" sccb_err=");
444}
445
459{
460 if (!s_sensor_bound) {
461 return;
462 }
474}
475
488{
489 uint32_t events = 0U;
491 c6_cam_puts(" ceu_events=");
492 c6_cam_put_u32(events);
493 }
494}
495
509{
511 return;
512 }
513 c6_cam_puts(" sensor_jpeg_bytes=");
514 c6_cam_put_u32(s_last_jpeg_status.encoded_bytes);
515 c6_cam_puts(" overflow=");
516 c6_cam_put_u32(s_last_jpeg_status.fifo_overflow ? 1U : 0U);
517 c6_cam_puts(" yuv422=");
518 c6_cam_put_u32(s_last_jpeg_status.input_is_yuv422 ? 1U : 0U);
519 c6_cam_puts(" header=");
520 c6_cam_put_u32(s_last_jpeg_status.header_output ? 1U : 0U);
521 c6_cam_puts(" jpeg_enabled=");
522 c6_cam_put_u32(s_last_jpeg_status.compression_enabled ? 1U : 0U);
523 c6_cam_puts(" width=");
524 c6_cam_put_u32(s_last_jpeg_status.compression_width);
525 c6_cam_puts(" height=");
526 c6_cam_put_u32(s_last_jpeg_status.compression_height);
527 c6_cam_puts(" ctrl01=");
529 c6_cam_puts(" vfifo00=");
531 c6_cam_puts(" href_min=");
532 c6_cam_put_u32(s_last_jpeg_status.href_minimum_blanking);
533}
534
static ra8_camera_codec_t s_codec
ra8_err_t c6_cam_camera_init(void)
Camera image and board-switch initialization, then one CEU capture.
static uint8_t s_jpeg[k_sw_cam_jpeg_bytes]
ra8_err_t c6_cam_camera_capture_jpeg(const uint8_t **out_jpeg, uint32_t *out_bytes, c6_cam_frame_timing_t *out_timing)
static ra8_camera_source_ceu_state_t s_source_state
void c6_cam_camera_report_last_error(void)
Emit backend-specific diagnostics for the last capture failure.
const char * c6_cam_camera_description(void)
Human-readable description of the selected camera backend.
static sccb_operation_t s_last_sccb_op
static uint32_t jpeg_trim_to_eoi(const uint8_t *jpeg, uint32_t bytes)
Locate the first complete JPEG payload in a captured span.
static ra8_ov5640_jpeg_status_t s_last_jpeg_status
static void internal_report_sensor_registers(void)
Report the OV5640 clock and stream registers when the sensor bound.
static ra8_err_t sensor_sccb_read(void *ctx, uint8_t address, uint16_t reg, uint8_t *out_value)
Forward one SCCB read while retaining bounded failure diagnostics.
jpeg_marker_t
@ k_jpeg_marker_soi
JPEG start-of-image marker byte.
@ k_jpeg_marker_prefix
JPEG marker prefix byte.
@ k_jpeg_marker_eoi
JPEG end-of-image marker byte.
static ra8_err_t s_last_sccb_err
static ra8_camera_source_ceu_cfg_t sensor_ceu_config(void)
Build the CEU configuration for bounded hardware JPEG capture.
sensor_jpeg_size_t
@ k_sensor_jpeg_poll_tries
CEU completion poll limit.
@ k_sensor_jpeg_buffer_bytes
Maximum gated frame span.
@ k_sensor_jpeg_poll_ms
CEU completion poll period.
@ k_sensor_jpeg_xclk_hz
OV5640 input clock.
@ k_sensor_jpeg_settle_ms
Sensor routing settle delay.
sccb_operation_t
Last SCCB operation retained for initialization diagnostics.
@ k_sccb_op_write
Last transfer was a write.
@ k_sccb_op_read
Last transfer was a read.
@ k_sccb_op_none
No SCCB transfer has run.
sensor_jpeg_geometry_t
@ k_sensor_jpeg_height
Encoded sensor JPEG height.
@ k_sensor_jpeg_width
Encoded sensor JPEG width.
static void sensor_report_register(const char *label, uint16_t reg)
Emit one named OV5640 register value when it remains readable.
static ra8_err_t internal_bring_up_capture_pipeline(void)
Route the parallel capture pins and bind the CEU source and codec.
static void internal_report_capture_events(void)
Report the CEU event mask observed by the most recent capture.
static void internal_report_sccb_state(void)
Report the most recent SCCB transfer direction, register, and result.
static ra8_err_t s_last_jpeg_status_err
static void internal_reset_camera_diagnostics(void)
Reset every camera diagnostic and lifecycle flag to its cold state.
static bool s_sensor_streaming
static ra8_err_t sensor_sccb_write(void *ctx, uint8_t address, uint16_t reg, uint8_t value)
Forward one SCCB write while retaining bounded failure diagnostics.
static uint16_t s_last_sccb_reg
static ra8_err_t internal_bring_up_sensor(void)
Bring the OV5640 sensor up to streaming hardware-JPEG mode.
static void internal_report_jpeg_status_detail(void)
Report the OV5640 hardware-JPEG status block from the last capture.
sensor_diagnostic_register_t
OV5640 clock and stream registers emitted on initialization failure.
@ k_sensor_reg_pll_ctrl3
PLL pre-divider.
@ k_sensor_reg_system_reset02
JPEG reset control.
@ k_sensor_reg_pll_ctrl2
PLL multiplier.
@ k_sensor_reg_system_ctrl0
Software stream state.
@ k_sensor_reg_pll_ctrl1
PLL system divider.
@ k_sensor_reg_system_reset00
Internal MCU reset control.
@ k_sensor_reg_clock_root
PCLK/SCLK root dividers.
@ k_sensor_reg_pll_ctrl0
PLL bit-mode control.
@ k_sensor_reg_clock_enable02
JPEG clock enables.
@ k_sensor_reg_pclk_divider
DVP pixel-clock divider.
@ k_sensor_reg_system_root
System-clock source.
static bool s_camera_initialized
static ra8_err_t sensor_bind(void)
Bind the hardware-JPEG sensor instance to board SCCB callbacks.
static bool s_sensor_bound
static ra8_ov5640_t s_sensor
Shared contracts for ESP32-C6 browser camera servers.
void c6_cam_put_u32(uint32_t value)
Write one unsigned decimal value to SCI8.
void c6_cam_puts(const char *text)
Write a bounded NUL-terminated string to SCI8.
static uint8_t s_source[k_image_source_bytes]
Complete fetched encoded image.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_camera_reset(void)
Pulse the J35 camera reset input and leave the sensor released.
ra8_err_t ra8_board_camera_sccb_write_reg(void *ctx, uint8_t address, uint16_t reg, uint8_t value)
Write one 16-bit-addressed SCCB register on the J35 camera bus.
ra8_err_t ra8_board_camera_sccb_read_reg(void *ctx, uint8_t address, uint16_t reg, uint8_t *out_value)
Read one 16-bit-addressed SCCB register on the J35 camera bus.
ra8_err_t ra8_board_camera_xclk_start(uint32_t frequency_hz)
Start the J35 camera sensor input clock (XCLK) on P501/GTIOC12A.
ra8_err_t ra8_board_camera_route_parallel_pins(void)
Route J35 D[7:0], VSYNC, HSYNC and PCLK to the CEU peripheral.
ra8_err_t ra8_board_camera_select_parallel(void)
Drive only SW4-6 ON through U15, selecting J35 parallel DVP.
void ra8_board_camera_delay_ms(void *ctx, uint32_t milliseconds)
Millisecond delay adapter for transport-independent camera drivers.
Transport-neutral camera source and image-codec facade.
@ k_ra8_camera_format_jpeg
Complete encoded JPEG byte stream.
Definition ra8_camera.h:66
ra8_err_t ra8_camera_source_capture(ra8_camera_source_t *source, const ra8_camera_buffer_t *buffer, ra8_camera_frame_t *out_frame)
Capture one frame into a caller-owned buffer.
Definition ra8_camera.c:146
ra8_err_t ra8_camera_codec_encode(ra8_camera_codec_t *codec, const ra8_camera_frame_t *input, const ra8_camera_buffer_t *output_buffer, ra8_camera_frame_t *out_frame)
Encode or transform one frame through a bound codec.
Definition ra8_camera.c:187
Zero-copy JPEG passthrough codec backend.
ra8_err_t ra8_camera_codec_passthrough_init(ra8_camera_codec_t *codec)
Bind the zero-copy JPEG passthrough codec.
RA8 CEU capture backend for the transport-neutral camera facade.
ra8_err_t ra8_camera_source_ceu_get_last_events(const ra8_camera_source_ceu_state_t *state, uint32_t *out_events)
Read the most recent CEU event snapshot retained by the backend.
ra8_err_t ra8_camera_source_ceu_init(ra8_camera_source_t *source, ra8_camera_source_ceu_state_t *state, const ra8_camera_source_ceu_cfg_t *cfg)
Initialize the CEU and bind it as a generic camera source.
Capture Engine Unit (CEU) camera-capture driver.
@ k_ra8_ceu_input_cb0_y0_cr0_y1
Cb0 Y0 Cr0 Y1.
@ k_ra8_ceu_burst_256
256-byte bus bursts.
@ k_ra8_ceu_capture_single
CE auto-clears after CPE.
@ k_ra8_ceu_fmt_data_enable
JPEG / data-enable fetch.
@ k_ra8_ceu_field_immediate
Capture starts at next VD.
@ k_ra8_ceu_pol_high_active
Sync signal is active high.
@ k_ra8_ceu_bus_8_bit
VIO_D[7:0] used.
@ k_ra8_ceu_edge_rising
Sample on rising VIO_CLK edge.
@ k_ra8_ceu_output_ycbcr_422
Pass-through (no conversion).
@ k_ra8_err_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
const char * ra8_err_to_str(ra8_err_t err)
Human-readable string for an error code.
Definition ra8_log.c:737
Transport-independent OmniVision OV5640 sensor driver.
ra8_err_t ra8_ov5640_read_reg(ra8_ov5640_t *dev, uint16_t reg, uint8_t *out_value)
Read one sensor register through the bound transport.
Definition ra8_ov5640.c:500
@ k_ra8_ov5640_chip_id
Expected combined chip identifier.
Definition ra8_ov5640.h:31
ra8_err_t ra8_ov5640_stream_set(ra8_ov5640_t *dev, bool enabled)
Enter software standby or resume sensor streaming.
Definition ra8_ov5640.c:971
ra8_err_t ra8_ov5640_configure(ra8_ov5640_t *dev, ra8_ov5640_mode_t mode)
Software-reset and program one validated output mode.
Definition ra8_ov5640.c:801
ra8_err_t ra8_ov5640_jpeg_status_get(ra8_ov5640_t *dev, ra8_ov5640_jpeg_status_t *out_status)
Snapshot sensor JPEG length, overflow, and routing controls.
Definition ra8_ov5640.c:936
ra8_err_t ra8_ov5640_probe(ra8_ov5640_t *dev, uint16_t *out_id)
Probe both legal SCCB addresses and verify chip ID 0x5640.
Definition ra8_ov5640.c:612
@ k_ra8_ov5640_mode_vga_jpeg
Sensor-encoded VGA JPEG stream.
Definition ra8_ov5640.h:42
ra8_err_t ra8_ov5640_init(ra8_ov5640_t *dev, const ra8_ov5640_bus_t *bus)
Bind a caller-supplied SCCB transport without touching the sensor.
Definition ra8_ov5640.c:484
SysTick-based tick counter, delay and timestamp helpers.
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
uint32_t ra8_time_ms(void)
Get the current 1 kHz tick count.
Definition ra8_time.c:108
Per-frame pipeline latency exposed in HTTP Server-Timing headers.
uint32_t timestamp_ms
Capture-start monotonic timestamp.
uint32_t capture_ms
Camera capture latency.
Caller-owned writable byte-buffer description.
Definition ra8_camera.h:80
Caller-owned handle binding one image codec and its context.
Definition ra8_camera.h:145
Immutable view of one captured or encoded image.
Definition ra8_camera.h:96
const uint8_t * data
Borrowed immutable image bytes.
Definition ra8_camera.h:97
uint32_t bytes
Valid bytes beginning at data.
Definition ra8_camera.h:98
Backend configuration, including native CEU register descriptor.
Caller-owned CEU source state.
Caller-owned handle binding one source backend and its context.
Definition ra8_camera.h:131
Full configuration descriptor for ra8_ceu_init.
Injected SCCB and time services.
Definition ra8_ov5640.h:60
Snapshot of the OV5640 JPEG pipeline and its most recent frame.
Definition ra8_ov5640.h:75
Caller-owned sensor instance; supports multiple independent parts.
Definition ra8_ov5640.h:68