|
11 | 11 | #include <zephyr/drivers/video-controls.h>
|
12 | 12 | #include <zephyr/logging/log.h>
|
13 | 13 | #include <zephyr/sys/util.h>
|
| 14 | +#include <zephyr/sys/byteorder.h> |
14 | 15 |
|
15 | 16 | #include "video_ctrls.h"
|
16 | 17 | #include "video_device.h"
|
@@ -116,29 +117,50 @@ uint32_t xrgb32_colorbar_value[] = {
|
116 | 117 | 0xFF00FF00, 0xFF00FFFF, 0xFFFFFF00, 0xFFFFFFFF,
|
117 | 118 | };
|
118 | 119 |
|
| 120 | +static inline int video_sw_generator_get_color_idx(uint16_t w, uint16_t width, bool hflip) |
| 121 | +{ |
| 122 | + /* If hflip is on, start from the right instead */ |
| 123 | + w = (hflip) ? (width - w - 1) : (w); |
| 124 | + |
| 125 | + /* Downscale from w/width to #/8 */ |
| 126 | + return 8 * w / width; |
| 127 | +} |
| 128 | + |
119 | 129 | static void video_sw_generator_fill_colorbar(struct video_sw_generator_data *data,
|
120 | 130 | struct video_buffer *vbuf)
|
121 | 131 | {
|
122 | 132 | int bw = data->fmt.width / 8;
|
123 |
| - int h, w, i = 0; |
124 |
| - |
125 |
| - for (h = 0; h < data->fmt.height; h++) { |
126 |
| - for (w = 0; w < data->fmt.width; w++) { |
127 |
| - int color_idx = data->ctrls.hflip.val ? 7 - w / bw : w / bw; |
128 |
| - if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) { |
129 |
| - uint16_t *pixel = (uint16_t *)&vbuf->buffer[i]; |
130 |
| - *pixel = rgb565_colorbar_value[color_idx]; |
131 |
| - i += 2; |
132 |
| - } else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) { |
133 |
| - uint32_t *pixel = (uint32_t *)&vbuf->buffer[i]; |
134 |
| - *pixel = xrgb32_colorbar_value[color_idx]; |
135 |
| - i += 4; |
136 |
| - } |
| 133 | + struct video_format *fmt = &data->fmt; |
| 134 | + size_t pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE; |
| 135 | + bool hflip = data->ctrls.hflip.val; |
| 136 | + |
| 137 | + vbuf->bytesused = 0; |
| 138 | + |
| 139 | + /* Generate the first line of data */ |
| 140 | + for (int w = 0, i = 0; w < data->fmt.width; w++) { |
| 141 | + int color_idx = video_sw_generator_get_color_idx(w, width, hflip); |
| 142 | + |
| 143 | + if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) { |
| 144 | + uint16_t *pixel = (uint16_t *)&vbuf->buffer[i]; |
| 145 | + *pixel = sys_cpu_to_le16(rgb565_colorbar_value[color_idx]); |
| 146 | + } else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) { |
| 147 | + uint32_t *pixel = (uint32_t *)&vbuf->buffer[i]; |
| 148 | + *pixel = sys_cpu_to_le32(xrgb32_colorbar_value[color_idx]); |
137 | 149 | }
|
| 150 | + i += video_bits_per_pixel(data->fmt.pixelformat) / BITS_PER_BYTE; |
| 151 | + } |
| 152 | + |
| 153 | + /* Duplicate the first line all over the buffer */ |
| 154 | + for (int h = 1; h < data->fmt.height; h++) { |
| 155 | + if (vbuf->size < vbuf->bytesused + pitch) { |
| 156 | + break; |
| 157 | + } |
| 158 | + |
| 159 | + memcpy(vbuf->buffer + h * pitch, vbuf->buffer, pitch); |
| 160 | + vbuf->bytesused += pitch; |
138 | 161 | }
|
139 | 162 |
|
140 | 163 | vbuf->timestamp = k_uptime_get_32();
|
141 |
| - vbuf->bytesused = i; |
142 | 164 | vbuf->line_offset = 0;
|
143 | 165 | }
|
144 | 166 |
|
|
0 commit comments