/ software / apps / moon / main.c
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  }