main.c
1 #include "pico/stdlib.h" 2 #include "hardware/clocks.h" 3 #include "hardware/irq.h" 4 #include "hardware/vreg.h" 5 6 #include "dvi.h" 7 #include "dvi_serialiser.h" 8 #include "common_dvi_pin_configs.h" 9 #include "tmds_encode_1bpp.pio.h" 10 #include "tmds_encode.h" 11 12 // Display a full-resolution 1bpp image. By default this uses the fast 1bpp 13 // encode routine from libdvi (which is actually fast enough for bitplaned 14 // RGB111). If USE_PIO_TMDS_ENCODE is defined, the TMDS encode can be 15 // offloaded to a slower encode loop on a spare state machine. 16 17 // Pick one: 18 #define MODE_640x480_60Hz 19 // #define MODE_1280x720_30Hz 20 21 #if defined(MODE_640x480_60Hz) 22 // DVDD 1.2V (1.1V seems ok too) 23 #define FRAME_WIDTH 640 24 #define FRAME_HEIGHT 480 25 #define VREG_VSEL VREG_VOLTAGE_1_20 26 #define DVI_TIMING dvi_timing_640x480p_60hz 27 #include "moon_1bpp_640x480.h" 28 #define moon_img moon_1bpp_640x480 29 30 #elif defined(MODE_1280x720_30Hz) 31 #define FRAME_WIDTH 1280 32 #define FRAME_HEIGHT 720 33 #define VREG_VSEL VREG_VOLTAGE_1_25 34 #define DVI_TIMING dvi_timing_1280x720p_30hz 35 #include "moon_1bpp_1280x720.h" 36 #define moon_img moon_1bpp_1280x720 37 38 #else 39 #error "Select a video mode!" 40 #endif 41 42 struct dvi_inst dvi0; 43 44 int main() { 45 vreg_set_voltage(VREG_VSEL); 46 sleep_ms(10); 47 set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true); 48 setup_default_uart(); 49 50 dvi0.timing = &DVI_TIMING; 51 dvi0.ser_cfg = DVI_DEFAULT_SERIAL_CONFIG; 52 dvi_init(&dvi0, next_striped_spin_lock_num(), next_striped_spin_lock_num()); 53 dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0); 54 55 // Set up extra SM, and DMA channels, to offload TMDS encode if necessary 56 // (note there are two build targets for this app, called `moon` and 57 // `moon_pio_encode`, so a simple `make all` will get you both binaries) 58 #ifdef USE_PIO_TMDS_ENCODE 59 PIO encode_pio = dvi0.ser_cfg.pio; 60 uint encode_sm = pio_claim_unused_sm(encode_pio, true); 61 tmds_encode_1bpp_init(encode_pio, encode_sm); 62 63 uint dma_chan_put = dma_claim_unused_channel(true); 64 dma_channel_config c = dma_channel_get_default_config(dma_chan_put); 65 channel_config_set_dreq(&c, pio_get_dreq(encode_pio, encode_sm, true)); 66 dma_channel_configure(dma_chan_put, &c, 67 &encode_pio->txf[encode_sm], 68 NULL, 69 FRAME_WIDTH / 32, 70 false 71 ); 72 73 uint dma_chan_get = dma_claim_unused_channel(true); 74 c = dma_channel_get_default_config(dma_chan_get); 75 channel_config_set_dreq(&c, pio_get_dreq(encode_pio, encode_sm, false)); 76 channel_config_set_write_increment(&c, true); 77 channel_config_set_read_increment(&c, false); 78 dma_channel_configure(dma_chan_get, &c, 79 NULL, 80 &encode_pio->rxf[encode_sm], 81 FRAME_WIDTH / DVI_SYMBOLS_PER_WORD, 82 false 83 ); 84 #endif 85 86 dvi_start(&dvi0); 87 while (true) { 88 for (uint y = 0; y < FRAME_HEIGHT; ++y) { 89 const uint32_t *colourbuf = &((const uint32_t*)moon_img)[y * FRAME_WIDTH / 32]; 90 uint32_t *tmdsbuf; 91 queue_remove_blocking_u32(&dvi0.q_tmds_free, &tmdsbuf); 92 #ifndef USE_PIO_TMDS_ENCODE 93 tmds_encode_1bpp(colourbuf, tmdsbuf, FRAME_WIDTH); 94 #else 95 dma_channel_set_read_addr(dma_chan_put, colourbuf, true); 96 dma_channel_set_write_addr(dma_chan_get, tmdsbuf, true); 97 dma_channel_wait_for_finish_blocking(dma_chan_get); 98 #endif 99 queue_add_blocking_u32(&dvi0.q_tmds_valid, &tmdsbuf); 100 } 101 } 102 }