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