kopia lustrzana https://github.com/Wren6991/PicoDVI
List nearest bit clock frequency in kHz with each dvi_timing parameter set
rodzic
3d4389ecac
commit
51e47b7874
|
@ -20,7 +20,6 @@
|
||||||
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
||||||
#define FRAME_WIDTH 1280
|
#define FRAME_WIDTH 1280
|
||||||
#define FRAME_HEIGHT 720
|
#define FRAME_HEIGHT 720
|
||||||
#define BIT_CLOCK_MHZ 372
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_25
|
#define VREG_VSEL VREG_VOLTAGE_1_25
|
||||||
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ int main() {
|
||||||
vreg_set_voltage(VREG_VSEL);
|
vreg_set_voltage(VREG_VSEL);
|
||||||
sleep_ms(10);
|
sleep_ms(10);
|
||||||
// Run system at TMDS bit clock
|
// Run system at TMDS bit clock
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 640
|
#define FRAME_WIDTH 640
|
||||||
#define FRAME_HEIGHT 480
|
#define FRAME_HEIGHT 480
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
|
@ -121,8 +120,7 @@ void core1_main() {
|
||||||
int main() {
|
int main() {
|
||||||
vreg_set_voltage(VREG_VSEL);
|
vreg_set_voltage(VREG_VSEL);
|
||||||
sleep_ms(10);
|
sleep_ms(10);
|
||||||
// Run system at TMDS bit clock
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 320
|
#define FRAME_WIDTH 320
|
||||||
#define FRAME_HEIGHT 240
|
#define FRAME_HEIGHT 240
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@ int main() {
|
||||||
vreg_set_voltage(VREG_VSEL);
|
vreg_set_voltage(VREG_VSEL);
|
||||||
sleep_ms(10);
|
sleep_ms(10);
|
||||||
// Run system at TMDS bit clock
|
// Run system at TMDS bit clock
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 320
|
#define FRAME_WIDTH 320
|
||||||
#define FRAME_HEIGHT 240
|
#define FRAME_HEIGHT 240
|
||||||
#if RUN_FROM_CRYSTAL
|
|
||||||
#define BIT_CLOCK_MHZ 12
|
|
||||||
#else
|
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#endif
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
|
@ -38,8 +33,7 @@ void core1_main() {
|
||||||
int main() {
|
int main() {
|
||||||
vreg_set_voltage(VREG_VSEL);
|
vreg_set_voltage(VREG_VSEL);
|
||||||
sleep_ms(10);
|
sleep_ms(10);
|
||||||
// Run system at TMDS bit clock
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 320
|
#define FRAME_WIDTH 320
|
||||||
#define FRAME_HEIGHT 240
|
#define FRAME_HEIGHT 240
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ int main() {
|
||||||
set_sys_clock_khz(12000, true);
|
set_sys_clock_khz(12000, true);
|
||||||
#else
|
#else
|
||||||
// Run system at TMDS bit clock
|
// Run system at TMDS bit clock
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 640
|
#define FRAME_WIDTH 640
|
||||||
#define FRAME_HEIGHT 480
|
#define FRAME_HEIGHT 480
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
#include "moon_1bpp_640x480.h"
|
#include "moon_1bpp_640x480.h"
|
||||||
|
@ -31,7 +30,6 @@
|
||||||
#elif defined(MODE_1280x720_30Hz)
|
#elif defined(MODE_1280x720_30Hz)
|
||||||
#define FRAME_WIDTH 1280
|
#define FRAME_WIDTH 1280
|
||||||
#define FRAME_HEIGHT 720
|
#define FRAME_HEIGHT 720
|
||||||
#define BIT_CLOCK_MHZ 372
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_25
|
#define VREG_VSEL VREG_VOLTAGE_1_25
|
||||||
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
||||||
#include "moon_1bpp_1280x720.h"
|
#include "moon_1bpp_1280x720.h"
|
||||||
|
@ -46,7 +44,7 @@ struct dvi_inst dvi0;
|
||||||
int main() {
|
int main() {
|
||||||
vreg_set_voltage(VREG_VSEL);
|
vreg_set_voltage(VREG_VSEL);
|
||||||
sleep_ms(10);
|
sleep_ms(10);
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
||||||
dvi0.timing = &DVI_TIMING;
|
dvi0.timing = &DVI_TIMING;
|
||||||
|
@ -55,6 +53,8 @@ int main() {
|
||||||
dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0);
|
dvi_register_irqs_this_core(&dvi0, DMA_IRQ_0);
|
||||||
|
|
||||||
// Set up extra SM, and DMA channels, to offload TMDS encode if necessary
|
// Set up extra SM, and DMA channels, to offload TMDS encode if necessary
|
||||||
|
// (note there are two build targets for this app, called `moon` and
|
||||||
|
// `moon_pio_encode`, so a simple `make all` will get you both binaries)
|
||||||
#ifdef USE_PIO_TMDS_ENCODE
|
#ifdef USE_PIO_TMDS_ENCODE
|
||||||
PIO encode_pio = dvi0.ser_cfg.pio;
|
PIO encode_pio = dvi0.ser_cfg.pio;
|
||||||
uint encode_sm = pio_claim_unused_sm(encode_pio, true);
|
uint encode_sm = pio_claim_unused_sm(encode_pio, true);
|
||||||
|
|
|
@ -28,14 +28,12 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 320
|
#define FRAME_WIDTH 320
|
||||||
#define FRAME_HEIGHT 240
|
#define FRAME_HEIGHT 240
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
#elif defined(MODE_800x480_60Hz)
|
#elif defined(MODE_800x480_60Hz)
|
||||||
#define FRAME_WIDTH 400
|
#define FRAME_WIDTH 400
|
||||||
#define FRAME_HEIGHT 240
|
#define FRAME_HEIGHT 240
|
||||||
#define BIT_CLOCK_MHZ 296
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_800x480p_60hz
|
#define DVI_TIMING dvi_timing_800x480p_60hz
|
||||||
|
|
||||||
|
@ -43,7 +41,6 @@
|
||||||
// DVDD 1.3V, going downhill with a tailwind
|
// DVDD 1.3V, going downhill with a tailwind
|
||||||
#define FRAME_WIDTH 400
|
#define FRAME_WIDTH 400
|
||||||
#define FRAME_HEIGHT 300
|
#define FRAME_HEIGHT 300
|
||||||
#define BIT_CLOCK_MHZ 400
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_30
|
#define VREG_VSEL VREG_VOLTAGE_1_30
|
||||||
#define DVI_TIMING dvi_timing_800x600p_60hz
|
#define DVI_TIMING dvi_timing_800x600p_60hz
|
||||||
|
|
||||||
|
@ -52,7 +49,6 @@
|
||||||
// Frame resolution is almost the same as a PSP :)
|
// Frame resolution is almost the same as a PSP :)
|
||||||
#define FRAME_WIDTH 480
|
#define FRAME_WIDTH 480
|
||||||
#define FRAME_HEIGHT 270
|
#define FRAME_HEIGHT 270
|
||||||
#define BIT_CLOCK_MHZ 372
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_25
|
#define VREG_VSEL VREG_VOLTAGE_1_25
|
||||||
#define DVI_TIMING dvi_timing_960x540p_60hz
|
#define DVI_TIMING dvi_timing_960x540p_60hz
|
||||||
|
|
||||||
|
@ -61,7 +57,6 @@
|
||||||
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
||||||
#define FRAME_WIDTH 640
|
#define FRAME_WIDTH 640
|
||||||
#define FRAME_HEIGHT 360
|
#define FRAME_HEIGHT 360
|
||||||
#define BIT_CLOCK_MHZ 372
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_25
|
#define VREG_VSEL VREG_VOLTAGE_1_25
|
||||||
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
||||||
|
|
||||||
|
@ -156,7 +151,7 @@ int main() {
|
||||||
set_sys_clock_khz(12000, true);
|
set_sys_clock_khz(12000, true);
|
||||||
#else
|
#else
|
||||||
// Run system at TMDS bit clock
|
// Run system at TMDS bit clock
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 640
|
#define FRAME_WIDTH 640
|
||||||
#define FRAME_HEIGHT 480
|
#define FRAME_HEIGHT 480
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_20
|
#define VREG_VSEL VREG_VOLTAGE_1_20
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
|
@ -42,7 +41,6 @@
|
||||||
// DVDD 1.3V, going downhill with a tailwind
|
// DVDD 1.3V, going downhill with a tailwind
|
||||||
#define FRAME_WIDTH 800
|
#define FRAME_WIDTH 800
|
||||||
#define FRAME_HEIGHT 600
|
#define FRAME_HEIGHT 600
|
||||||
#define BIT_CLOCK_MHZ 400
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_30
|
#define VREG_VSEL VREG_VOLTAGE_1_30
|
||||||
#define DVI_TIMING dvi_timing_800x600p_60hz
|
#define DVI_TIMING dvi_timing_800x600p_60hz
|
||||||
|
|
||||||
|
@ -51,7 +49,6 @@
|
||||||
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
||||||
#define FRAME_WIDTH 960
|
#define FRAME_WIDTH 960
|
||||||
#define FRAME_HEIGHT 540
|
#define FRAME_HEIGHT 540
|
||||||
#define BIT_CLOCK_MHZ 372
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_25
|
#define VREG_VSEL VREG_VOLTAGE_1_25
|
||||||
#define DVI_TIMING dvi_timing_960x540p_60hz
|
#define DVI_TIMING dvi_timing_960x540p_60hz
|
||||||
|
|
||||||
|
@ -60,7 +57,6 @@
|
||||||
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
// DVDD 1.25V (slower silicon may need the full 1.3, or just not work)
|
||||||
#define FRAME_WIDTH 1280
|
#define FRAME_WIDTH 1280
|
||||||
#define FRAME_HEIGHT 720
|
#define FRAME_HEIGHT 720
|
||||||
#define BIT_CLOCK_MHZ 372
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_25
|
#define VREG_VSEL VREG_VOLTAGE_1_25
|
||||||
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
#define DVI_TIMING dvi_timing_1280x720p_30hz
|
||||||
|
|
||||||
|
@ -115,7 +111,7 @@ int __not_in_flash("main") main() {
|
||||||
set_sys_clock_khz(12000, true);
|
set_sys_clock_khz(12000, true);
|
||||||
#else
|
#else
|
||||||
// Run system at TMDS bit clock
|
// Run system at TMDS bit clock
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
// DVDD 1.2V (1.1V seems ok too)
|
// DVDD 1.2V (1.1V seems ok too)
|
||||||
#define FRAME_WIDTH 320
|
#define FRAME_WIDTH 320
|
||||||
#define FRAME_HEIGHT 240
|
#define FRAME_HEIGHT 240
|
||||||
#define BIT_CLOCK_MHZ 252
|
|
||||||
#define VREG_VSEL VREG_VOLTAGE_1_15
|
#define VREG_VSEL VREG_VOLTAGE_1_15
|
||||||
#define DVI_TIMING dvi_timing_640x480p_60hz
|
#define DVI_TIMING dvi_timing_640x480p_60hz
|
||||||
|
|
||||||
|
@ -136,8 +135,7 @@ uint8_t img_buf[2][2 * IMAGE_SCANLINE_SIZE];
|
||||||
int __not_in_flash("main") main() {
|
int __not_in_flash("main") main() {
|
||||||
vreg_set_voltage(VREG_VSEL);
|
vreg_set_voltage(VREG_VSEL);
|
||||||
sleep_ms(10);
|
sleep_ms(10);
|
||||||
// Run system at TMDS bit clock
|
set_sys_clock_khz(DVI_TIMING.bit_clk_khz, true);
|
||||||
set_sys_clock_khz(BIT_CLOCK_MHZ * 1000, true);
|
|
||||||
|
|
||||||
setup_default_uart();
|
setup_default_uart();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
#include "dvi_timing.h"
|
#include "dvi_timing.h"
|
||||||
#include "hardware/dma.h"
|
#include "hardware/dma.h"
|
||||||
|
|
||||||
#include <string.h>
|
// This file contains:
|
||||||
|
// - Timing parameters for DVI modes (horizontal + vertical counts, best
|
||||||
|
// achievable bit clock from 12 MHz crystal)
|
||||||
|
// - Helper functions for generating DMA lists based on these timings
|
||||||
|
|
||||||
// Pull into RAM but apply unique section suffix to allow linker GC
|
// Pull into RAM but apply unique section suffix to allow linker GC
|
||||||
#define __dvi_func(x) __not_in_flash_func(x)
|
#define __dvi_func(x) __not_in_flash_func(x)
|
||||||
|
@ -20,7 +23,9 @@ const struct dvi_timing __dvi_const(dvi_timing_640x480p_60hz) = {
|
||||||
.v_front_porch = 10,
|
.v_front_porch = 10,
|
||||||
.v_sync_width = 2,
|
.v_sync_width = 2,
|
||||||
.v_back_porch = 33,
|
.v_back_porch = 33,
|
||||||
.v_active_lines = 480
|
.v_active_lines = 480,
|
||||||
|
|
||||||
|
.bit_clk_khz = 252000
|
||||||
};
|
};
|
||||||
|
|
||||||
// SVGA -- completely by-the-book but requires 400 MHz clk_sys
|
// SVGA -- completely by-the-book but requires 400 MHz clk_sys
|
||||||
|
@ -35,7 +40,9 @@ const struct dvi_timing __dvi_const(dvi_timing_800x600p_60hz) = {
|
||||||
.v_front_porch = 1,
|
.v_front_porch = 1,
|
||||||
.v_sync_width = 4,
|
.v_sync_width = 4,
|
||||||
.v_back_porch = 23,
|
.v_back_porch = 23,
|
||||||
.v_active_lines = 600
|
.v_active_lines = 600,
|
||||||
|
|
||||||
|
.bit_clk_khz = 400000
|
||||||
};
|
};
|
||||||
|
|
||||||
// 800x480p 60 Hz (note this doesn't seem to be a CEA mode, I just used the
|
// 800x480p 60 Hz (note this doesn't seem to be a CEA mode, I just used the
|
||||||
|
@ -51,7 +58,9 @@ const struct dvi_timing __dvi_const(dvi_timing_800x480p_60hz) = {
|
||||||
.v_front_porch = 3,
|
.v_front_porch = 3,
|
||||||
.v_sync_width = 10,
|
.v_sync_width = 10,
|
||||||
.v_back_porch = 7,
|
.v_back_porch = 7,
|
||||||
.v_active_lines = 480
|
.v_active_lines = 480,
|
||||||
|
|
||||||
|
.bit_clk_khz = 295200
|
||||||
};
|
};
|
||||||
|
|
||||||
// SVGA reduced blanking (355 MHz bit clock) -- valid CVT mode, less common
|
// SVGA reduced blanking (355 MHz bit clock) -- valid CVT mode, less common
|
||||||
|
@ -67,7 +76,9 @@ const struct dvi_timing __dvi_const(dvi_timing_800x600p_reduced_60hz) = {
|
||||||
.v_front_porch = 3,
|
.v_front_porch = 3,
|
||||||
.v_sync_width = 4,
|
.v_sync_width = 4,
|
||||||
.v_back_porch = 11,
|
.v_back_porch = 11,
|
||||||
.v_active_lines = 600
|
.v_active_lines = 600,
|
||||||
|
|
||||||
|
.bit_clk_khz = 354000
|
||||||
};
|
};
|
||||||
|
|
||||||
// Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9
|
// Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9
|
||||||
|
@ -83,7 +94,9 @@ const struct dvi_timing __dvi_const(dvi_timing_960x540p_60hz) = {
|
||||||
.v_front_porch = 2,
|
.v_front_porch = 2,
|
||||||
.v_sync_width = 6,
|
.v_sync_width = 6,
|
||||||
.v_back_porch = 15,
|
.v_back_porch = 15,
|
||||||
.v_active_lines = 540
|
.v_active_lines = 540,
|
||||||
|
|
||||||
|
.bit_clk_khz = 372000
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note this is NOT the correct 720p30 CEA mode, but rather 720p60 run at half
|
// Note this is NOT the correct 720p30 CEA mode, but rather 720p60 run at half
|
||||||
|
@ -101,7 +114,9 @@ const struct dvi_timing __dvi_const(dvi_timing_1280x720p_30hz) = {
|
||||||
.v_front_porch = 5,
|
.v_front_porch = 5,
|
||||||
.v_sync_width = 5,
|
.v_sync_width = 5,
|
||||||
.v_back_porch = 20,
|
.v_back_porch = 20,
|
||||||
.v_active_lines = 720
|
.v_active_lines = 720,
|
||||||
|
|
||||||
|
.bit_clk_khz = 372000
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reduced-blanking (CVT) 720p. You aren't supposed to use reduced blanking
|
// Reduced-blanking (CVT) 720p. You aren't supposed to use reduced blanking
|
||||||
|
@ -118,11 +133,14 @@ const struct dvi_timing __dvi_const(dvi_timing_1280x720p_reduced_30hz) = {
|
||||||
.v_front_porch = 3,
|
.v_front_porch = 3,
|
||||||
.v_sync_width = 5,
|
.v_sync_width = 5,
|
||||||
.v_back_porch = 13,
|
.v_back_porch = 13,
|
||||||
.v_active_lines = 720
|
.v_active_lines = 720,
|
||||||
|
|
||||||
|
.bit_clk_khz = 319200
|
||||||
};
|
};
|
||||||
|
|
||||||
// This requires a spicy 488 MHz system clock and is illegal in most countries
|
// This requires a spicy 488 MHz system clock and is illegal in most countries
|
||||||
// (you need to have a very lucky piece of silicon to run this at 1.3 V)
|
// (you need to have a very lucky piece of silicon to run this at 1.3 V, or
|
||||||
|
// connect an external supply and give it a bit more juice)
|
||||||
const struct dvi_timing __dvi_const(dvi_timing_1600x900p_reduced_30hz) = {
|
const struct dvi_timing __dvi_const(dvi_timing_1600x900p_reduced_30hz) = {
|
||||||
.h_sync_polarity = true,
|
.h_sync_polarity = true,
|
||||||
.h_front_porch = 48,
|
.h_front_porch = 48,
|
||||||
|
@ -134,9 +152,44 @@ const struct dvi_timing __dvi_const(dvi_timing_1600x900p_reduced_30hz) = {
|
||||||
.v_front_porch = 3,
|
.v_front_porch = 3,
|
||||||
.v_sync_width = 5,
|
.v_sync_width = 5,
|
||||||
.v_back_porch = 13,
|
.v_back_porch = 13,
|
||||||
.v_active_lines = 720
|
.v_active_lines = 720,
|
||||||
|
|
||||||
|
.bit_clk_khz = 488000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The DMA scheme is:
|
||||||
|
//
|
||||||
|
// - One channel transferring data to each of the three PIO state machines
|
||||||
|
// performing TMDS serialisation
|
||||||
|
//
|
||||||
|
// - One channel programming the registers of each of these data channels,
|
||||||
|
// triggered (CHAIN_TO) each time the corresponding data channel completes
|
||||||
|
//
|
||||||
|
// - Lanes 1 and 2 have one block for blanking and one for video data
|
||||||
|
//
|
||||||
|
// - Lane 0 has one block for each horizontal region (front porch, hsync, back
|
||||||
|
// porch, active)
|
||||||
|
//
|
||||||
|
// - The IRQ_QUIET flag is used to select which data block on the sync lane is
|
||||||
|
// allowed to generate an IRQ upon completion. This is the block immediately
|
||||||
|
// before the horizontal active region. The IRQ is entered at ~the same time
|
||||||
|
// as the last data transfer starts
|
||||||
|
//
|
||||||
|
// - The IRQ points the control channels at new blocklists for next scanline.
|
||||||
|
// The DMA starts the new list automatically at end-of-scanline, via
|
||||||
|
// CHAIN_TO.
|
||||||
|
//
|
||||||
|
// The horizontal active region is the longest continuous transfer, so this
|
||||||
|
// gives the most time to handle the IRQ and load new blocklists.
|
||||||
|
//
|
||||||
|
// Note a null trigger IRQ is not suitable because we get that *after* the
|
||||||
|
// last data transfer finishes, and the FIFOs bottom out very shortly
|
||||||
|
// afterward. For pure DVI (four blocks per scanline), it works ok to take
|
||||||
|
// four regular IRQs per scanline and return early from 3 of them, but this
|
||||||
|
// breaks down when you have very short scanline sections like guard bands.
|
||||||
|
|
||||||
// Note we particularly want these to be in memory because these addresses get
|
// Note we particularly want these to be in memory because these addresses get
|
||||||
// a LOT of DMA traffic!
|
// a LOT of DMA traffic!
|
||||||
const uint32_t __dvi_const(dvi_ctrl_syms)[4] = {
|
const uint32_t __dvi_const(dvi_ctrl_syms)[4] = {
|
||||||
|
@ -171,41 +224,9 @@ void __dvi_func(dvi_timing_state_advance)(const struct dvi_timing *t, struct dvi
|
||||||
}
|
}
|
||||||
|
|
||||||
void dvi_scanline_dma_list_init(struct dvi_scanline_dma_list *dma_list) {
|
void dvi_scanline_dma_list_init(struct dvi_scanline_dma_list *dma_list) {
|
||||||
// This used to be more interesting
|
*dma_list = (struct dvi_scanline_dma_list){};
|
||||||
memset(dma_list, 0, sizeof(struct dvi_scanline_dma_list));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The DMA scheme is:
|
|
||||||
//
|
|
||||||
// - One channel transferring data to each of the three PIO state machines
|
|
||||||
// performing TMDS serialisation
|
|
||||||
//
|
|
||||||
// - One channel programming the registers of each of these data channels,
|
|
||||||
// triggered (CHAIN_TO) each time the corresponding data channel completes
|
|
||||||
//
|
|
||||||
// - Lanes 1 and 2 have one block for blanking and one for video data
|
|
||||||
//
|
|
||||||
// - Lane 0 has one block for each horizontal region (front porch, hsync, back
|
|
||||||
// porch, active)
|
|
||||||
//
|
|
||||||
// - The IRQ_QUIET flag is used to select which data block on the sync lane is
|
|
||||||
// allowed to generate an IRQ upon completion. This is the block immediately
|
|
||||||
// before the horizontal active region. The IRQ is entered at ~the same time
|
|
||||||
// as the last data transfer starts
|
|
||||||
//
|
|
||||||
// - The IRQ points the control channels at new blocklists for next scanline.
|
|
||||||
// The DMA starts the new list automatically at end-of-scanline, via
|
|
||||||
// CHAIN_TO.
|
|
||||||
//
|
|
||||||
// The horizontal active region is the longest continuous transfer, so this
|
|
||||||
// gives the most time to handle the IRQ and load new blocklists.
|
|
||||||
//
|
|
||||||
// Note a null trigger IRQ is not suitable because we get that *after* the
|
|
||||||
// last data transfer finishes, and the FIFOs bottom out very shortly
|
|
||||||
// afterward. For pure DVI (four blocks per scanline), it works ok to take
|
|
||||||
// four regular IRQs per scanline and return early from 3 of them, but this
|
|
||||||
// breaks down when you have very short scanline sections like guard bands.
|
|
||||||
|
|
||||||
static const uint32_t *get_ctrl_sym(bool vsync, bool hsync) {
|
static const uint32_t *get_ctrl_sym(bool vsync, bool hsync) {
|
||||||
return &dvi_ctrl_syms[!!vsync << 1 | !!hsync];
|
return &dvi_ctrl_syms[!!vsync << 1 | !!hsync];
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ struct dvi_timing {
|
||||||
uint v_sync_width;
|
uint v_sync_width;
|
||||||
uint v_back_porch;
|
uint v_back_porch;
|
||||||
uint v_active_lines;
|
uint v_active_lines;
|
||||||
|
|
||||||
|
uint bit_clk_khz;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dvi_line_state {
|
enum dvi_line_state {
|
||||||
|
|
Ładowanie…
Reference in New Issue