2929#include "hardware/pio.h"
3030#include "hardware/clocks.h"
3131#include "hardware/vreg.h"
32+ #include "hardware/adc.h"
3233
3334 /*
3435 * Pin mapping (PCB v0.3)
7172
7273#if !PICO9918_NO_SPLASH
7374#include "splash.h"
74- #include "font.h"
75+ #endif
76+
77+
78+ #if PICO9918_DIAG
79+ #include "font.h"
7580#endif
7681
7782#define TIMING_DIAG PICO9918_DIAG
107112
108113#define TMS_CRYSTAL_FREQ_HZ 10738635.0f
109114
115+ //#define PICO_CLOCK_PLL 756000000 // 252MHz - standard voltage
116+ //#define PICO_CLOCK_PLL_DIV1 3
117+
118+ //#define PICO_CLOCK_PLL 828000000 // 276MHz - standard voltage
119+ //#define PICO_CLOCK_PLL_DIV1 3
120+
110121//#define PICO_CLOCK_PLL 1512000000 // 302.4MHz - standard voltage
111122//#define PICO_CLOCK_PLL_DIV1 5
112123
113- #define PICO_CLOCK_PLL 1308000000 // 327MHz - 1.15v
114- #define PICO_CLOCK_PLL_DIV1 4
124+ // #define PICO_CLOCK_PLL 1308000000 // 327MHz - 1.15v
125+ // #define PICO_CLOCK_PLL_DIV1 4
115126
116127//#define PICO_CLOCK_PLL 984000000 // 328MHz - 1.15v
117128//#define PICO_CLOCK_PLL_DIV1 3
122133//#define PICO_CLOCK_PLL 1128000000 // 376MHz - 1.3v
123134//#define PICO_CLOCK_PLL_DIV1 3
124135
125- // #define PICO_CLOCK_PLL 1512000000 // 378MHz - 1.3v
126- // #define PICO_CLOCK_PLL_DIV1 4
136+ #define PICO_CLOCK_PLL 1512000000 // 378MHz - 1.3v
137+ #define PICO_CLOCK_PLL_DIV1 4
127138
128139//#define PICO_CLOCK_PLL 804000000 // 402MHz - DOES NOT WORK
129140//#define PICO_CLOCK_PLL_DIV1 2
@@ -162,7 +173,7 @@ static uint8_t currentStatus = 0x1f; /* current status register value */
162173
163174static __attribute__((section (".scratch_y.buffer" ))) uint32_t bg ;
164175
165- static __attribute__((section (".scratch_x.buffer" ))) uint8_t __aligned (8 ) tmsScanlineBuffer [TMS9918_PIXELS_X + 8 ];
176+ static __attribute__((section (".scratch_x.buffer" ))) uint8_t __aligned (4 ) tmsScanlineBuffer [TMS9918_PIXELS_X + 8 ];
166177
167178const uint tmsWriteSm = 0 ;
168179const uint tmsReadSm = 1 ;
@@ -235,7 +246,7 @@ void __not_in_flash_func(pio_irq_handler)()
235246 }
236247 break ;
237248 case 1 :
238- if (( readVal << 31 ) >> 31 ) // & 0x01
249+ if (readVal << 31 )
239250 tms9918 -> status [0x01 ] &= ~0x01 ;
240251 break ;
241252 }
@@ -343,6 +354,30 @@ static __attribute__ ((noinline)) uint32_t toBcd(uint32_t number)
343354}
344355
345356
357+ /* F18A palette entries are big-endian 0x0RGB which looks like
358+ 0xGB0R to our RP2040. our vga code is expecting 0x0BGR
359+ so we've got B and R correct by pure chance. just need to shift G
360+ over. this function does that. note: msbs are ignore so... */
361+
362+ inline uint32_t bigRgb2LittleBgr (uint32_t val )
363+ {
364+ return val | ((val >> 12 ) << 4 );
365+ }
366+
367+ static void tmsPorch (uint16_t * pixels )
368+ {
369+ uint32_t * dPixels = (uint32_t * )pixels ;
370+ //bg = bigRgb2LittleBgr(tms9918->pram[vrEmuTms9918RegValue(TMS_REG_FG_BG_COLOR) & 0x0f]);
371+ bg = 0 ;//bg | (bg << 16);
372+ dma_channel_wait_for_finish_blocking (dma32 );
373+ dma_channel_set_write_addr (dma32 , dPixels , false);
374+ dma_channel_set_trans_count (dma32 , VIRTUAL_PIXELS_X / 2 , true);
375+
376+ tms9918 -> blanking = 1 ; // V
377+ tms9918 -> scanline = 255 ; // F18A value for vsync
378+ tms9918 -> status [0x03 ] = 255 ;
379+ }
380+
346381static void tmsEndOfFrame (uint32_t frameNumber )
347382{
348383 ++ frameCount ;
@@ -369,16 +404,6 @@ static void tmsEndOfFrame(uint32_t frameNumber)
369404 }
370405}
371406
372- /* F18A palette entries are big-endian 0x0RGB which looks like
373- 0xGB0R to our RP2040. our vga code is expecting 0x0BGR
374- so we've got B and R correct by pure chance. just need to shift G
375- over. this function does that. note: msbs are ignore so... */
376-
377- inline uint32_t bigRgb2LittleBgr (uint32_t val )
378- {
379- return val | ((val >> 12 ) << 4 );
380- }
381-
382407/*
383408 * output the PICO9918 splash logo / firmware version at the bottom of the screen
384409 */
@@ -429,6 +454,20 @@ static void outputSplash(uint16_t y, uint32_t vBorder, uint32_t vPixels, uint16_
429454
430455#if PICO9918_DIAG
431456
457+ uint32_t temperature = 0 ;
458+
459+ static void analogReadTempSetup () {
460+ adc_init ();
461+ adc_set_temp_sensor_enabled (true);
462+ adc_select_input (4 ); // Temperature sensor
463+ }
464+
465+ static float analogReadTemp (float vref ) {
466+ int v = adc_read ();
467+ float t = 27.0f - ((v * vref / 4096.0f ) - 0.706f ) / 0.001721f ; // From the datasheet
468+ return t ;
469+ }
470+
432471/* render a bcd value scanline */
433472void __attribute__ ((noinline )) renderBcd (uint16_t scanline , uint32_t bcd , uint16_t x , uint16_t y , uint16_t color , uint16_t * pixels )
434473{
@@ -474,6 +513,7 @@ void renderDiagnostics(uint16_t y, uint16_t* pixels)
474513 renderBcd (y , renderTimeBcd , xPos , yPos , 0x0f40 , pixels );
475514 renderBcd (y , renderTimePerScanlineBcd , xPos + 28 , yPos , 0x004f , pixels ); yPos += 8 ;
476515
516+ renderBcd (y , temperature , xPos , yPos , 0x004f , pixels );
477517#endif
478518
479519#if REG_DIAG
@@ -529,7 +569,7 @@ void renderDiagnostics(uint16_t y, uint16_t* pixels)
529569 */
530570static void __time_critical_func (tmsScanline )(uint16_t y , VgaParams * params , uint16_t * pixels )
531571{
532- int vPixels = (tms9918 -> registers [0x31 ] & 0x40 ) ? 30 * 8 - 1 : 24 * 8 ;
572+ int vPixels = (tms9918 -> registers [0x31 ] & 0x40 ) ? 30 * 8 /* - 1*/ : 24 * 8 ;
533573
534574 const uint32_t vBorder = (VIRTUAL_PIXELS_Y - vPixels ) / 2 ;
535575 const uint32_t hBorder = (VIRTUAL_PIXELS_X - TMS9918_PIXELS_X * 2 ) / 2 ;
@@ -538,16 +578,25 @@ static void __time_critical_func(tmsScanline)(uint16_t y, VgaParams* params, uin
538578 bg = bigRgb2LittleBgr (tms9918 -> pram [vrEmuTms9918RegValue (TMS_REG_FG_BG_COLOR ) & 0x0f ]);
539579 bg = bg | (bg << 16 );
540580
541- if (y == 0 ) doneInt = false;
581+ if (y == 0 )
582+ {
583+ #if PICO9918_DIAG
584+ uint32_t t = (int )(analogReadTemp (3.3f ) * 10.0f );
585+ uint32_t i = (t / 100 );
586+ t -= (i * 100 );
587+ temperature = (i << 12 ) | ((t / 10 ) << 8 ) | (0x0A << 4 ) | (t % 10 );
588+ #endif
589+ doneInt = false;
590+ }
542591
543592 /*** top and bottom borders ***/
544593 if (y < vBorder || y >= (vBorder + vPixels ))
545594 {
546595 dma_channel_set_write_addr (dma32 , dPixels , false);
547596 dma_channel_set_trans_count (dma32 , VIRTUAL_PIXELS_X / 2 , true);
548- tms9918 -> scanline = 0 ;
549- tms9918 -> blanking = 1 ;
550- tms9918 -> status [0x03 ] = 0 ;
597+ tms9918 -> blanking = 1 ; // V
598+ tms9918 -> scanline = 255 ; // F18A value for vsync
599+ tms9918 -> status [0x03 ] = 255 ;
551600 dma_channel_wait_for_finish_blocking (dma32 );
552601
553602#if PICO9918_DIAG
@@ -562,11 +611,15 @@ static void __time_critical_func(tmsScanline)(uint16_t y, VgaParams* params, uin
562611
563612 uint32_t frameStart = time_us_32 ();
564613
614+ y -= vBorder ;
615+ tms9918 -> blanking = 0 ;
616+ tms9918 -> scanline = y ;
617+ tms9918 -> status [0x03 ] = y ;
618+
565619 /*** left border ***/
566620 dma_channel_set_write_addr (dma32 , dPixels , false);
567621 dma_channel_set_trans_count (dma32 , hBorder / 2 , true);
568622
569- y -= vBorder ;
570623 /*** main display region ***/
571624
572625 /* generate the scanline */
@@ -612,12 +665,14 @@ static void __time_critical_func(tmsScanline)(uint16_t y, VgaParams* params, uin
612665 uint32_t data ;
613666 for (int i = 0 , x = 0 ; i < 16 ; ++ i )
614667 {
615- uint32_t c = tms9918 -> pram [i ];
668+ uint32_t c = tms9918 -> pram [i ] & 0xFF0F ;
616669 for (int j = 0 ; j < 16 ; ++ j , ++ x )
617670 {
618- data = (tms9918 -> pram [j ] << 16 ) | c ; data |= ((data >> 8 ) & 0x00f000f0 ); pram [x ] = data ;
671+ data = (( tms9918 -> pram [j ] & 0xFF0F ) << 16 ) | c ; data |= ((data >> 8 ) & 0x00f000f0 ); pram [x ] = data ;
619672 }
620673 }
674+ tms9918 -> blanking = 1 ; // H
675+
621676 uint8_t * src = & (tmsScanlineBuffer [0 ]);
622677 uint8_t * end = & (tmsScanlineBuffer [TMS9918_PIXELS_X ]);
623678 uint32_t * dP = (uint32_t * )& (pixels [hBorder ]);
@@ -645,15 +700,17 @@ static void __time_critical_func(tmsScanline)(uint16_t y, VgaParams* params, uin
645700 uint32_t data ;
646701 for (int i = 0 ; i < 64 ; i += 8 )
647702 {
648- data = tms9918 -> pram [i + 0 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 0 ] = data | (data << 16 );
649- data = tms9918 -> pram [i + 1 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 1 ] = data | (data << 16 );
650- data = tms9918 -> pram [i + 2 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 2 ] = data | (data << 16 );
651- data = tms9918 -> pram [i + 3 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 3 ] = data | (data << 16 );
652- data = tms9918 -> pram [i + 4 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 4 ] = data | (data << 16 );
653- data = tms9918 -> pram [i + 5 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 5 ] = data | (data << 16 );
654- data = tms9918 -> pram [i + 6 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 6 ] = data | (data << 16 );
655- data = tms9918 -> pram [i + 7 ]; data = data | ((data >> 12 ) << 4 ); pram [i + 7 ] = data | (data << 16 );
703+ data = tms9918 -> pram [i + 0 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 0 ] = data | (data << 16 );
704+ data = tms9918 -> pram [i + 1 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 1 ] = data | (data << 16 );
705+ data = tms9918 -> pram [i + 2 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 2 ] = data | (data << 16 );
706+ data = tms9918 -> pram [i + 3 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 3 ] = data | (data << 16 );
707+ data = tms9918 -> pram [i + 4 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 4 ] = data | (data << 16 );
708+ data = tms9918 -> pram [i + 5 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 5 ] = data | (data << 16 );
709+ data = tms9918 -> pram [i + 6 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 6 ] = data | (data << 16 );
710+ data = tms9918 -> pram [i + 7 ] & 0xFF0F ; data = data | ((data >> 12 ) << 4 ); pram [i + 7 ] = data | (data << 16 );
656711 }
712+ tms9918 -> blanking = 1 ; // H
713+
657714 while (src < end )
658715 {
659716 dP [0 ] = pram [src [0 ]];
@@ -673,10 +730,6 @@ static void __time_critical_func(tmsScanline)(uint16_t y, VgaParams* params, uin
673730 //dma_channel_wait_for_finish_blocking(dma32);
674731 dma_channel_set_write_addr (dma32 , & (dPixels [(hBorder + TMS9918_PIXELS_X * 2 ) / 2 ]), true);
675732
676- tms9918 -> scanline = y + 1 ;
677- tms9918 -> blanking = 0 ; // Is it even possible to support H blanking?
678- tms9918 -> status [0x03 ] = tms9918 -> scanline ;
679-
680733 accumulatedFrameTime += time_us_32 () - frameStart ;
681734
682735#if PICO9918_DIAG
@@ -787,11 +840,12 @@ void proc1Entry()
787840 */
788841int main (void )
789842{
790- vreg_set_voltage (VREG_VOLTAGE_1_30 );
791843 /* currently, VGA hard-coded to 640x480@60Hz. We want a high clock frequency
792844 * that comes close to being divisible by 25.175MHz. 302.0 is close... enough :)
793845 * I do have code which sets the best clock baased on the chosen VGA mode,
794846 * but this'll do for now. */
847+ //vreg_set_voltage(VREG_VOLTAGE_1_15);
848+ vreg_set_voltage (VREG_VOLTAGE_1_30 );
795849 set_sys_clock_pll (PICO_CLOCK_PLL , PICO_CLOCK_PLL_DIV1 , PICO_CLOCK_PLL_DIV2 );
796850
797851 /* we need one of these. it's the main guy */
@@ -800,11 +854,11 @@ int main(void)
800854 /* launch core 1 which handles TMS9918<->CPU and rendering scanlines */
801855 multicore_launch_core1 (proc1Entry );
802856
803- dma_channel_config cfg = dma_channel_get_default_config (dma32 );
804- channel_config_set_read_increment (& cfg , false);
805- channel_config_set_write_increment (& cfg , true);
806- channel_config_set_transfer_data_size (& cfg , DMA_SIZE_32 );
807- dma_channel_set_config (dma32 , & cfg , false);
857+ dma_channel_config cfg = dma_channel_get_default_config (dma32 );
858+ channel_config_set_read_increment (& cfg , false);
859+ channel_config_set_write_increment (& cfg , true);
860+ channel_config_set_transfer_data_size (& cfg , DMA_SIZE_32 );
861+ dma_channel_set_config (dma32 , & cfg , false);
808862
809863 dma_channel_set_read_addr (dma32 , & bg , false);
810864
@@ -820,11 +874,16 @@ int main(void)
820874 params .scanlines = PICO9918_SCANLINES ;
821875 params .scanlineFn = tmsScanline ;
822876 params .endOfFrameFn = tmsEndOfFrame ;
877+ params .porchFn = tmsPorch ;
823878
824879 const char * version = PICO9918_VERSION ;
825880
826881 vgaInit (params );
827882
883+ #if PICO9918_DIAG
884+ analogReadTempSetup ();
885+ #endif
886+
828887 /* signal proc1 that we're ready to start the display */
829888 multicore_fifo_push_blocking (0 );
830889
0 commit comments