diff --git a/README.md b/README.md index 0f023f7..643b0c0 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Name|Description [render](scanvideo/render)| A very dated rendering library used by [demo1](scanvideo/demo1) - avoid! [sprite](scanvideo/sprite)| A small sprite library used by [sprite_demo](scanvideo/scanvideo_minimal) [sprite_demo](scanvideo/sprite_demo)| Some bouncing Eben heads +[test_pattern](scanvideo/test_pattern)| Display color bars [textmode](scanvideo/textmode)| Shows off chained DMA to generate scanlines out of glyph fragments via DMA/PIO diff --git a/scanvideo/CMakeLists.txt b/scanvideo/CMakeLists.txt index 51f6b0a..1168ca2 100644 --- a/scanvideo/CMakeLists.txt +++ b/scanvideo/CMakeLists.txt @@ -10,5 +10,6 @@ if (TARGET pico_scanvideo) # not all build types support it add_subdirectory(mario_tiles) add_subdirectory(scanvideo_minimal) add_subdirectory(sprite_demo) + add_subdirectory(test_pattern) add_subdirectory(textmode) endif() \ No newline at end of file diff --git a/scanvideo/scanvideo_minimal/scanvideo_minimal.c b/scanvideo/scanvideo_minimal/scanvideo_minimal.c index fd8c6f9..6d95e93 100644 --- a/scanvideo/scanvideo_minimal/scanvideo_minimal.c +++ b/scanvideo/scanvideo_minimal/scanvideo_minimal.c @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + #include <stdio.h> #include "pico.h" diff --git a/scanvideo/test_pattern/CMakeLists.txt b/scanvideo/test_pattern/CMakeLists.txt new file mode 100644 index 0000000..dc73144 --- /dev/null +++ b/scanvideo/test_pattern/CMakeLists.txt @@ -0,0 +1,15 @@ +if (TARGET pico_scanvideo_dpi) + add_executable(test_pattern + test_pattern.c + ) + + target_link_libraries(test_pattern PRIVATE + pico_multicore + pico_stdlib + pico_scanvideo_dpi) + + pico_add_extra_outputs(test_pattern) + + pico_enable_stdio_uart(test_pattern 1) + pico_enable_stdio_usb(test_pattern 1) +endif () diff --git a/scanvideo/test_pattern/test_pattern.c b/scanvideo/test_pattern/test_pattern.c new file mode 100644 index 0000000..d189920 --- /dev/null +++ b/scanvideo/test_pattern/test_pattern.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdio.h> + +#include "pico.h" +#include "pico/stdlib.h" +#include "pico/multicore.h" +#include "pico/scanvideo.h" +#include "pico/scanvideo/composable_scanline.h" +#include "pico/sync.h" + +#define vga_mode vga_mode_320x240_60 + +void core1_func(); + +// Simple color bar program, which draws 7 colored bars: red, green, yellow, blow, magenta, cyan, white +// Can be used to check resister DAC correctness. +// +// Note this program also demonstrates running video on core 1, leaving core 0 free. It supports +// user input over USB or UART stdin, although all it does with it is invert the colors when you press SPACE + +static semaphore_t video_initted; +static bool invert; + +int main(void) { + set_sys_clock_48mhz(); + stdio_init_all(); + + // create a semaphore to be posted when video init is complete + sem_init(&video_initted, 0, 1); + + // launch all the video on core 1, so it isn't affected by USB handling on core 0 + multicore_launch_core1(core1_func); + + // wait for initialization of video to be complete + sem_acquire_blocking(&video_initted); + + puts("Color bars ready, press SPACE to invert..."); + + while (true) { + // prevent tearing when we invert - if you're astute you'll notice this actually causes + // a fixed tear a number of scanlines from the top. this is caused by pre-buffering of scanlines + // and is too detailed a topic to fix here. + scanvideo_wait_for_vblank(); + int c = getchar_timeout_us(0); + switch (c) { + case ' ': + invert = !invert; + printf("Inverted: %d\n", invert); + break; + } + } +} + +void draw_color_bar(scanvideo_scanline_buffer_t *buffer) { + // figure out 1/32 of the color value + uint line_num = scanvideo_scanline_number(buffer->scanline_id); + int32_t color_step = 1 + (line_num * 7 / vga_mode.height); + color_step = PICO_SCANVIDEO_PIXEL_FROM_RGB5(color_step & 1u, (color_step >> 1u) & 1u, (color_step >> 2u) & 1u); + if (invert) color_step = -color_step; + uint bar_width = vga_mode.width / 32; + + uint16_t *p = (uint16_t *) buffer->data; + int32_t color = invert ? PICO_SCANVIDEO_PIXEL_FROM_RGB8(255, 255, 255) : 0; + + for (uint bar = 0; bar < 32; bar++) { + *p++ = COMPOSABLE_COLOR_RUN; + *p++ = color; + *p++ = bar_width - 3; + color += color_step; + } + + // 32 * 3, so we should be word aligned + assert(!(3u & (uintptr_t) p)); + + // black pixel to end line + *p++ = COMPOSABLE_RAW_1P; + *p++ = 0; + // end of line with alignment padding + *p++ = COMPOSABLE_EOL_SKIP_ALIGN; + *p++ = 0; + + buffer->data_used = ((uint32_t *) p) - buffer->data; + assert(buffer->data_used < buffer->data_max); + + buffer->status = SCANLINE_OK; +} + +void core1_func() { + // initialize video and interrupts on core 1 + scanvideo_setup(&vga_mode); + scanvideo_timing_enable(true); + sem_release(&video_initted); + + while (true) { + scanvideo_scanline_buffer_t *scanline_buffer = scanvideo_begin_scanline_generation(true); + draw_color_bar(scanline_buffer); + scanvideo_end_scanline_generation(scanline_buffer); + } +}