kopia lustrzana https://github.com/Wren6991/PicoDVI
commit
f5001aef4f
|
|
@ -8,9 +8,11 @@ This repo adds to the following features to PicoDVI
|
|||
+ `moon_double_audio`: A bit doubled version of the `moon` demo that includes audio (spoken voice)
|
||||
+ `sprite_bounce_audio`: Adds an audio sine wave to the `sprite_bounce_demo` - caution this is quite loud!
|
||||
+ `colour_terminal_audio`: Adds spoken voice audio to the `colour_terminal` demo
|
||||
2. 50 Hz DVI modes have been added. Small changes were needed to the base code as a pixel width of 720 is not divisible by 32.
|
||||
3. A board configuration for Olimex. Set `DVI_DEFAULT_SERIAL_CONFIG` equal to `Olimex_RP2040_PICO_PC_cfg`
|
||||
4. Stereo PWM sound for Olimexpc. The supplied PicoDVI code from Olimex uses PWM to generate the DVI clock on pins 12 and 13. The boards audio output is on pins 27 and 28. Pin 28 and pin 12 are on the same PWM channel (6A), so it is not possible to configure different PWM clock frequencies for the two pins. In effect this means that PWM stereo sound does not work with the supplied Olimex PicoDVI code. The code in this repo can optionally generate the DVI clock using a very simple PIO state machine, so that pins 27 and 28 can then be driven to generate PWM audio. To enable this set `DVI_USE_PIO_CLOCK`
|
||||
2. Includes additions made by fruit-bat to gracefully play silence when an HDMI audio buffer underrun occurs
|
||||
3. 50 Hz DVI modes have been added. Small changes were needed to the base code as a pixel width of 720 is not divisible by 32.
|
||||
4. A board configuration for Olimex. Set `DVI_DEFAULT_SERIAL_CONFIG` equal to `Olimex_RP2040_PICO_PC_cfg`
|
||||
5. Stereo PWM sound for Olimexpc. The supplied PicoDVI code from Olimex uses PWM to generate the DVI clock on pins 12 and 13. The boards audio output is on pins 27 and 28. Pin 28 and pin 12 are on the same PWM channel (6A), so it is not possible to configure different PWM clock frequencies for the two pins. In effect this means that PWM stereo sound does not work with the supplied Olimex PicoDVI code. The code in this repo can optionally generate the DVI clock using a very simple PIO state machine, so that pins 27 and 28 can then be driven to generate PWM audio. To enable this set `DVI_USE_PIO_CLOCK`
|
||||
6. Tweak demo apps so they all build without warnings
|
||||
|
||||
From the original Readme
|
||||
========================
|
||||
|
|
|
|||
|
|
@ -55,8 +55,9 @@ int main() {
|
|||
|
||||
int frame = 0;
|
||||
const uint8_t *line = (const uint8_t*)MOVIE_BASE;
|
||||
uint32_t *render_target = 0;
|
||||
|
||||
while (true) {
|
||||
uint32_t *render_target;
|
||||
for (int y = 0; y < FRAME_HEIGHT; ++y) {
|
||||
uint8_t line_len = *line++;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &render_target);
|
||||
|
|
|
|||
|
|
@ -173,9 +173,9 @@ int main() {
|
|||
}
|
||||
|
||||
uint frame_ctr = 0;
|
||||
uint16_t *scanbuf = 0;
|
||||
while (true) {
|
||||
for (uint y = 0; y < FRAME_HEIGHT; ++y) {
|
||||
uint16_t *scanbuf;
|
||||
queue_remove_blocking_u32(&dvi0.q_colour_free, &scanbuf);
|
||||
render_scanline(scanbuf, y);
|
||||
queue_add_blocking_u32(&dvi0.q_colour_valid, &scanbuf);
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ int __not_in_flash("main") main() {
|
|||
// Run system at TMDS bit clock
|
||||
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||
|
||||
// setup_default_uart();
|
||||
// setup_default_uart();
|
||||
|
||||
dvi0.timing = &DVI_TIMING;
|
||||
dvi0.ser_cfg = DVI_DEFAULT_SERIAL_CONFIG;
|
||||
|
|
@ -160,12 +160,12 @@ int __not_in_flash("main") main() {
|
|||
|
||||
hw_set_bits(&bus_ctrl_hw->priority, BUSCTRL_BUS_PRIORITY_PROC1_BITS);
|
||||
|
||||
// HDMI Audio related
|
||||
dvi_get_blank_settings(&dvi0)->top = 4 * 0;
|
||||
dvi_get_blank_settings(&dvi0)->bottom = 4 * 0;
|
||||
dvi_audio_sample_buffer_set(&dvi0, audio_buffer, AUDIO_BUFFER_SIZE);
|
||||
dvi_set_audio_freq(&dvi0, 44100, 28000, 6272);
|
||||
add_repeating_timer_ms(-2, audio_timer_callback, NULL, &audio_timer);
|
||||
// HDMI Audio related
|
||||
dvi_get_blank_settings(&dvi0)->top = 4 * 0;
|
||||
dvi_get_blank_settings(&dvi0)->bottom = 4 * 0;
|
||||
dvi_audio_sample_buffer_set(&dvi0, audio_buffer, AUDIO_BUFFER_SIZE);
|
||||
dvi_set_audio_freq(&dvi0, 44100, 28000, 6272);
|
||||
add_repeating_timer_ms(-2, audio_timer_callback, NULL, &audio_timer);
|
||||
|
||||
printf("starting...\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -99,11 +99,11 @@ uint8_t humidity_history[HISTORY_SIZE];
|
|||
struct dvi_inst dvi0;
|
||||
|
||||
void core1_main() {
|
||||
uint32_t *tmdsbuf = 0;
|
||||
dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0);
|
||||
dvi_start(&dvi0);
|
||||
while (true) {
|
||||
for (uint y = 0; y < FRAME_HEIGHT; ++y) {
|
||||
uint32_t *tmdsbuf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &tmdsbuf);
|
||||
for (uint component = 0; component < 3; ++component) {
|
||||
tmds_encode_1bpp(
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ void display_scrolling_testcard(struct dvi_inst *inst, const uint8_t *img) {
|
|||
const uint blue_lsb = 0;
|
||||
uint pixwidth = inst->timing->h_active_pixels;
|
||||
uint frame_ctr = 0;
|
||||
uint32_t *tmdsbuf = 0;
|
||||
while (true) {
|
||||
for (uint y = 0; y < FRAME_HEIGHT; ++y) {
|
||||
uint y_scroll = (y + frame_ctr) % FRAME_HEIGHT;
|
||||
const uint8_t *colourbuf = &((const uint8_t*)img)[y_scroll * FRAME_WIDTH];
|
||||
uint32_t *tmdsbuf;
|
||||
queue_remove_blocking_u32(&inst->q_tmds_free, &tmdsbuf);
|
||||
// NB the scanline buffers are half-resolution!
|
||||
tmds_encode_data_channel_8bpp((const uint32_t*)colourbuf, tmdsbuf, pixwidth / 2, blue_msb, blue_lsb);
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ int __not_in_flash("main") main() {
|
|||
|
||||
uint heartbeat = 0;
|
||||
uint32_t encode_time = 0;
|
||||
uint32_t *our_tmds_buf = 0, *their_tmds_buf = 0;
|
||||
|
||||
sem_release(&dvi_start_sem);
|
||||
while (1) {
|
||||
|
|
@ -166,7 +167,6 @@ int __not_in_flash("main") main() {
|
|||
if (fractal.done) zoom_mandel();
|
||||
//if (heartbeat & 1) init_palette();
|
||||
for (int y = 0; y < FRAME_HEIGHT / 2; y += 2) {
|
||||
uint32_t *our_tmds_buf, *their_tmds_buf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &their_tmds_buf);
|
||||
multicore_fifo_push_blocking((uint32_t)(&mandel[y*FRAME_WIDTH]));
|
||||
multicore_fifo_push_blocking((uint32_t)their_tmds_buf);
|
||||
|
|
@ -184,7 +184,6 @@ int __not_in_flash("main") main() {
|
|||
queue_add_blocking_u32(&dvi0.q_tmds_valid, &our_tmds_buf);
|
||||
}
|
||||
for (int y = FRAME_HEIGHT / 2 - 2; y >= 0; y -= 2) {
|
||||
uint32_t *our_tmds_buf, *their_tmds_buf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &their_tmds_buf);
|
||||
multicore_fifo_push_blocking((uint32_t)(&mandel[(y+1)*FRAME_WIDTH]));
|
||||
multicore_fifo_push_blocking((uint32_t)their_tmds_buf);
|
||||
|
|
|
|||
|
|
@ -102,10 +102,11 @@ int main() {
|
|||
#endif
|
||||
|
||||
dvi_start(&dvi0);
|
||||
uint32_t *tmdsbuf = 0;
|
||||
|
||||
while (true) {
|
||||
for (uint y = 0; y < FRAME_HEIGHT; ++y) {
|
||||
const uint32_t *colourbuf = &((const uint32_t*)moon_img)[y * IMAGE_WIDTH / 32];
|
||||
uint32_t *tmdsbuf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &tmdsbuf);
|
||||
#ifndef USE_PIO_TMDS_ENCODE
|
||||
tmds_encode_1bpp(colourbuf, tmdsbuf, FRAME_WIDTH);
|
||||
|
|
|
|||
|
|
@ -148,12 +148,13 @@ int main()
|
|||
|
||||
static void __not_in_flash_func(render_loop)()
|
||||
{
|
||||
uint32_t *tmdsbuf = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
for (uint y = 0; y < FRAME_HEIGHT/2; ++y)
|
||||
{
|
||||
const uint32_t *colourbuf = &((const uint32_t*)moon_img)[(y + (FRAME_HEIGHT >> 3))* IMAGE_WIDTH / 32];
|
||||
uint32_t *tmdsbuf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &tmdsbuf);
|
||||
|
||||
// 32 pixels create 8 * 2 32 bit words
|
||||
|
|
|
|||
|
|
@ -251,9 +251,9 @@ int main() {
|
|||
|
||||
printf("Start rendering\n");
|
||||
game_init(&state);
|
||||
uint32_t *tmds0 = 0, *tmds1 = 0;
|
||||
while (1) {
|
||||
for (uint y = 0; y < FRAME_HEIGHT; y += 2) {
|
||||
uint32_t *tmds0, *tmds1;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &tmds0);
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &tmds1);
|
||||
multicore_fifo_push_blocking((uintptr_t)tmds1);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ int __not_in_flash("main") main() {
|
|||
|
||||
uint heartbeat = 0;
|
||||
uint slideshow_ctr = 0;
|
||||
uint32_t *our_tmds_buf = 0, *their_tmds_buf = 0;
|
||||
|
||||
sem_release(&dvi_start_sem);
|
||||
while (1) {
|
||||
|
|
@ -156,7 +157,6 @@ int __not_in_flash("main") main() {
|
|||
img_dma_chan
|
||||
);
|
||||
const uint8_t *img = (const uint8_t*)img_buf[img_buf_front];
|
||||
uint32_t *our_tmds_buf, *their_tmds_buf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &their_tmds_buf);
|
||||
multicore_fifo_push_blocking((uint32_t)(img));
|
||||
multicore_fifo_push_blocking((uint32_t)their_tmds_buf);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ int __not_in_flash("main") main() {
|
|||
uint heartbeat = 0;
|
||||
uint slideshow_ctr = 0;
|
||||
uint32_t current_image_base = IMAGE_BASE;
|
||||
uint32_t *our_tmds_buf = 0, *their_tmds_buf = 0;
|
||||
|
||||
sem_release(&dvi_start_sem);
|
||||
while (1) {
|
||||
|
|
@ -138,7 +139,6 @@ int __not_in_flash("main") main() {
|
|||
img_dma_chan
|
||||
);
|
||||
const uint16_t *img = (const uint16_t*)img_buf[img_buf_front];
|
||||
uint32_t *our_tmds_buf, *their_tmds_buf;
|
||||
queue_remove_blocking_u32(&dvi0.q_tmds_free, &their_tmds_buf);
|
||||
multicore_fifo_push_blocking((uint32_t)(img));
|
||||
multicore_fifo_push_blocking((uint32_t)their_tmds_buf);
|
||||
|
|
|
|||
|
|
@ -71,12 +71,12 @@ static const struct dvi_serialiser_cfg pico_sock_cfg = {
|
|||
|
||||
// pico-RGB2HDMI
|
||||
static const struct dvi_serialiser_cfg pico_rgb2hdmi_cfg = {
|
||||
.pio = pio0,
|
||||
.sm_tmds = {0, 1, 2},
|
||||
.pins_tmds = {5, 7, 9},
|
||||
.pins_clk = 3,
|
||||
.invert_diffpairs = true
|
||||
};
|
||||
.pio = pio0,
|
||||
.sm_tmds = {0, 1, 2},
|
||||
.pins_tmds = {5, 7, 9},
|
||||
.pins_clk = 3,
|
||||
.invert_diffpairs = true
|
||||
};
|
||||
|
||||
// The HDMI socket on Pimoroni Pico Demo HDMI
|
||||
// (we would talk about rev B if we had a rev B...)
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue