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