44// PicoDVI class encapsulates some of the libdvi functionality -------------
55// Subclasses then implement specific display types.
66
7+ static struct {
8+ const dvi_timing &timing;
9+ vreg_voltage v;
10+ uint16_t width;
11+ uint16_t height;
12+ uint8_t v_rep;
13+ } dvispec[] = {
14+ {dvi_timing_640x480p_60hz, VREG_VOLTAGE_1_20, 320 , 240 , 2 },
15+ {dvi_timing_800x480p_60hz, VREG_VOLTAGE_1_20, 400 , 240 , 2 },
16+ {dvi_timing_640x480p_60hz, VREG_VOLTAGE_1_20, 640 , 480 , 1 },
17+ {dvi_timing_800x480p_60hz, VREG_VOLTAGE_1_20, 800 , 480 , 1 },
18+ // Additional resolutions might get added here if the overclock issue can
19+ // be sorted out. Regardless, always keep this list 1:1 in sync with the
20+ // DVIresolution enum in PicoDVI.h.
21+ {dvi_timing_1280x720p_30hz, VREG_VOLTAGE_1_30, 1280 , 720 , 1 },
22+ };
23+
724static PicoDVI *dviptr = NULL ; // For C access to active C++ object
825// Semaphore might be preferable, but this seems to work for now...
926static volatile bool wait_begin = true ;
1027
1128// Runs on core 1 on startup
12- void __not_in_flash ( " main " ) setup1(void ) {
29+ void setup1 (void ) {
1330 while (wait_begin)
1431 ; // Wait for DVIGFX*::begin() to do its thing on core 0
1532 dviptr->_setup ();
@@ -22,8 +39,8 @@ void PicoDVI::_setup(void) {
2239 (*mainloop)(&dvi0);
2340}
2441
25- PicoDVI::PicoDVI (const struct dvi_timing &t, vreg_voltage v ,
26- const struct dvi_serialiser_cfg &c )
42+ PicoDVI::PicoDVI (const struct dvi_timing &t, const struct dvi_serialiser_cfg &c ,
43+ vreg_voltage v )
2744 : voltage(v) {
2845 dvi0.timing = &t;
2946 memcpy (&dvi0.ser_cfg , &c, sizeof dvi0.ser_cfg );
@@ -46,11 +63,11 @@ void PicoDVI::begin(void) {
4663
4764static void *gfxptr = NULL ; // For C access to active C++ object
4865
49- DVIGFX16::DVIGFX16 (const uint16_t w , const uint16_t h ,
50- const struct dvi_timing &t, vreg_voltage v,
51- const struct dvi_serialiser_cfg &c)
52- : PicoDVI(t, v, c), GFXcanvas16(w, h ) {
53- dvi_vertical_repeat = 2 ;
66+ DVIGFX16::DVIGFX16 (const DVIresolution r , const struct dvi_serialiser_cfg &c ,
67+ vreg_voltage v)
68+ : PicoDVI(dvispec[r].timing, c, v),
69+ GFXcanvas16(dvispec[r].width, dvispec[r].height ) {
70+ dvi_vertical_repeat = dvispec[r]. v_rep ;
5471 dvi_monochrome_tmds = false ;
5572}
5673
@@ -103,11 +120,12 @@ bool DVIGFX16::begin(void) {
103120// HEIGHT value is de-tweaked to the original value so clipping won't allow
104121// any drawing operations to spill into the 16-bit scanlines.
105122
106- DVIGFX8::DVIGFX8 (const uint16_t w, const uint16_t h, const struct dvi_timing &t,
107- vreg_voltage v, const struct dvi_serialiser_cfg &c)
108- : PicoDVI(t, v, c), GFXcanvas8(w, ((h + 1 ) & ~1) + 4) {
109- HEIGHT = _height = h;
110- dvi_vertical_repeat = 2 ;
123+ DVIGFX8::DVIGFX8 (const DVIresolution r, const struct dvi_serialiser_cfg &c,
124+ vreg_voltage v)
125+ : PicoDVI(dvispec[r].timing, c, v),
126+ GFXcanvas8(dvispec[r].width, ((dvispec[r].height + 1 ) & ~1) + 4) {
127+ HEIGHT = _height = dvispec[r].height ;
128+ dvi_vertical_repeat = dvispec[r].v_rep ;
111129 dvi_monochrome_tmds = false ;
112130}
113131
@@ -163,13 +181,13 @@ bool DVIGFX8::begin(void) {
163181// "back" state. Call swap() to switch the front/back buffers at the next
164182// vertical sync, for flicker-free and tear-free animation.
165183
166- DVIGFX8x2::DVIGFX8x2 (const uint16_t w , const uint16_t h ,
167- const struct dvi_timing &t, vreg_voltage v,
168- const struct dvi_serialiser_cfg &c)
169- : PicoDVI(t, v, c), GFXcanvas8(w, h * 2 + 4 ) {
170- HEIGHT = _height = h ;
184+ DVIGFX8x2::DVIGFX8x2 (const DVIresolution r , const struct dvi_serialiser_cfg &c ,
185+ vreg_voltage v)
186+ : PicoDVI(dvispec[r].timing, c, v),
187+ GFXcanvas8(dvispec[r].width, dvispec[r].height * 2 + 4 ) {
188+ HEIGHT = _height = dvispec[r]. height ;
171189 buffer_save = buffer;
172- dvi_vertical_repeat = 2 ;
190+ dvi_vertical_repeat = dvispec[r]. v_rep ;
173191 dvi_monochrome_tmds = false ;
174192}
175193
@@ -249,13 +267,15 @@ void DVIGFX8x2::swap(bool copy_framebuffer, bool copy_palette) {
249267
250268// 1-bit WIP --------
251269
252- DVIGFX1::DVIGFX1 (const uint16_t w, const uint16_t h, const bool d,
253- const struct dvi_timing &t, vreg_voltage v,
254- const struct dvi_serialiser_cfg &c)
255- : PicoDVI(t, v, c), GFXcanvas1(w, d ? (h * 2 ) : h), dbuf(d) {
256- dvi_vertical_repeat = 1 ;
270+ DVIGFX1::DVIGFX1 (const DVIresolution r, const bool d,
271+ const struct dvi_serialiser_cfg &c, vreg_voltage v)
272+ : PicoDVI(dvispec[r].timing, c, v),
273+ GFXcanvas1(dvispec[r].width,
274+ d ? (dvispec[r].height * 2 ) : dvispec[r].height),
275+ dbuf(d) {
276+ dvi_vertical_repeat = dvispec[r].v_rep ;
257277 dvi_monochrome_tmds = true ;
258- HEIGHT = _height = h ;
278+ HEIGHT = _height = dvispec[r]. height ;
259279 buffer_save = buffer;
260280}
261281
@@ -320,21 +340,20 @@ void DVIGFX1::swap(bool copy_framebuffer) {
320340#define FONT_FIRST_ASCII 32
321341#include " font_8x8.h"
322342
323- DVIterm1::DVIterm1 (const uint16_t w , const uint16_t h ,
324- const struct dvi_timing &t, vreg_voltage v,
325- const struct dvi_serialiser_cfg &c)
326- : PicoDVI(t, v, c), GFXcanvas16(w / 8 , h / 8 ) {
327- dvi_vertical_repeat = 1 ;
343+ DVIterm1::DVIterm1 (const DVIresolution r , const struct dvi_serialiser_cfg &c ,
344+ vreg_voltage v)
345+ : PicoDVI(dvispec[r].timing, c, v),
346+ GFXcanvas16(dvispec[r].width / 8 , dvispec[r].height / 8 ) {
347+ dvi_vertical_repeat = dvispec[r]. v_rep ;
328348 dvi_monochrome_tmds = true ;
329349}
330350
331- DVIterm1::~DVIterm1 (void ) {
332- gfxptr = NULL ;
333- }
351+ DVIterm1::~DVIterm1 (void ) { gfxptr = NULL ; }
334352
335- // static uint8_t scanbuf[1280 / 8] __attribute__ ((aligned (4)));
336353// TO DO: alloc this dynamically as part of object (maybe part of canvas)
337- static uint8_t scanbuf[1280 / 8 ];
354+ static uint8_t scanbuf[1280 / 8 ] __attribute__((aligned(4 )));
355+
356+ #ifdef TERM_USE_INTERRUPT
338357
339358void inline __not_in_flash_func (DVIterm1::_prepare_scanline)(uint16_t y) {
340359 uint16_t *row = getBuffer () + (y / FONT_CHAR_HEIGHT) * WIDTH;
@@ -348,7 +367,7 @@ void inline __not_in_flash_func(DVIterm1::_prepare_scanline)(uint16_t y) {
348367 }
349368 uint32_t *tmdsbuf;
350369 queue_remove_blocking_u32 (&dvi0.q_tmds_free , &tmdsbuf);
351- tmds_encode_1bpp ((const uint32_t *)scanbuf, tmdsbuf, WIDTH * 8 );
370+ tmds_encode_1bpp ((const uint32_t *)scanbuf, tmdsbuf, WIDTH * 8 );
352371 queue_add_blocking_u32 (&dvi0.q_tmds_valid , &tmdsbuf);
353372}
354373
@@ -360,10 +379,12 @@ void __not_in_flash_func(term1_scanline_callback)(void) {
360379
361380static void mainloopterm1 (struct dvi_inst *inst) {
362381 // Idle func, everything happens in interrupt
363- for (;;) delay (1000 );
382+ for (;;)
383+ delay (1000 );
364384}
365385
366- #if 0
386+ #else
387+
367388// Old way, without interrupt
368389// This is a little simpler and might stick with it
369390// since nothing important to do in idle func above.
@@ -373,11 +394,10 @@ static void mainloopterm1(struct dvi_inst *inst) {
373394}
374395
375396void __not_in_flash_func (DVIterm1::_mainloop)(void ) {
376- static uint8_t scanbuf[1280 / 8] __attribute__ ((aligned (4)));
377397 for (;;) {
378398 for (uint16_t y = 0 ; y < HEIGHT; y++) {
379399 uint16_t *row = getBuffer () + y * WIDTH;
380- for (uint8_t y1= 0; y1< 8; y1++) {
400+ for (uint8_t y1 = 0 ; y1 < 8 ; y1++) {
381401 uint32_t offset = y1 * FONT_N_CHARS;
382402 for (uint16_t x = 0 ; x < WIDTH; x++) {
383403 uint8_t mask = row[x] >> 8 ;
@@ -392,17 +412,23 @@ void __not_in_flash_func(DVIterm1::_mainloop)(void) {
392412 }
393413 }
394414}
395- #endif
396415
397- bool __not_in_flash_func (DVIterm1::begin)(void ) {
416+ #endif // end TERM_USE_INTERRUPT
417+
418+ bool DVIterm1::begin (void ) {
398419 if ((getBuffer ())) {
399420 gfxptr = this ;
421+ #ifdef TERM_USE_INTERRUPT
400422 dvi0.scanline_callback = term1_scanline_callback;
423+ #endif
401424 mainloop = mainloopterm1;
402425 PicoDVI::begin ();
426+
403427 // Must do this AFTER begin because tmdsbuf (accessed in func)
404428 // doesn't exist yet until dvi_init (in begin) is called.
429+ #ifdef TERM_USE_INTERRUPT
405430 _prepare_scanline (0 );
431+ #endif
406432
407433 wait_begin = false ; // Set core 1 in motion
408434 return true ;
0 commit comments