Skip to content

Commit baa5e8a

Browse files
committed
Jason: Added temperature diagnostics and porch callback fo rscanline number
1 parent 512e4dc commit baa5e8a

File tree

5 files changed

+134
-50
lines changed

5 files changed

+134
-50
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ target_link_libraries(${PROGRAM} PUBLIC
8888
pico_multicore
8989
hardware_dma
9090
hardware_pio
91+
hardware_adc
9192
pico9918-vga
9293
vrEmuTms9918)
9394

src/main.c

Lines changed: 102 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
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)
@@ -71,7 +72,11 @@
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
@@ -107,11 +112,17 @@
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
@@ -122,8 +133,8 @@
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

163174
static __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

167178
const uint tmsWriteSm = 0;
168179
const 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+
346381
static 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 */
433472
void __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
*/
530570
static 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
*/
788841
int 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

src/vga/vga.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ int roundflt(float x)
6262
#define SYNC_SM 0 // vga sync state machine index
6363
#define RGB_SM 1 // vga rgb state machine index
6464

65+
#define FRONT_PORCH_MSG 0x20000000
6566
#define END_OF_SCANLINE_MSG 0x40000000
6667
#define END_OF_FRAME_MSG 0x80000000
6768

@@ -141,7 +142,7 @@ static bool buildSyncData()
141142
rgbDataBuffer[2][i] = 0x0f00;
142143
#endif
143144

144-
vgaParams.params.pioDivider = (sysClockKHz / (float)minClockKHz);
145+
vgaParams.params.pioDivider = /*roundflt*/(sysClockKHz / (float)minClockKHz);
145146
vgaParams.params.pioFreqKHz = sysClockKHz / vgaParams.params.pioDivider;
146147

147148
vgaParams.params.pioClocksPerPixel = vgaParams.params.pioFreqKHz / (float)vgaParams.params.pixelClockKHz;
@@ -325,6 +326,10 @@ static void __isr __time_critical_func(dmaIrqHandler)(void)
325326
else if (currentTimingLine < (vgaParams.params.vSyncParams.syncPixels + vgaParams.params.vSyncParams.backPorchPixels))
326327
{
327328
dma_channel_set_read_addr(syncDmaChan, syncDataPorch, true);
329+
if (currentTimingLine + 2 == (vgaParams.params.vSyncParams.syncPixels + vgaParams.params.vSyncParams.backPorchPixels))
330+
{
331+
multicore_fifo_push_timeout_us(0, 0);
332+
}
328333
}
329334
else if (currentTimingLine < (vgaParams.params.vSyncParams.totalPixels - vgaParams.params.vSyncParams.frontPorchPixels))
330335
{
@@ -333,6 +338,10 @@ static void __isr __time_critical_func(dmaIrqHandler)(void)
333338
else
334339
{
335340
dma_channel_set_read_addr(syncDmaChan, syncDataPorch, true);
341+
if (currentTimingLine == (vgaParams.params.vSyncParams.totalPixels - vgaParams.params.vSyncParams.frontPorchPixels) + 2)
342+
{
343+
multicore_fifo_push_timeout_us(FRONT_PORCH_MSG | 1, 0);
344+
}
336345
}
337346
#if VGA_SCANLINE_CB_ENABLE
338347
multicore_fifo_push_timeout_us(END_OF_SCANLINE_MSG | currentTimingLine, 0);
@@ -373,16 +382,22 @@ static void __isr __time_critical_func(dmaIrqHandler)(void)
373382
}
374383
#endif
375384

376-
385+
if (currentDisplayLine == VIRTUAL_PIXELS_Y * 2)
386+
{
387+
currentBuffer [0] = 0;
388+
currentBuffer [1] = 0;
389+
currentBuffer [2] = 0;
390+
currentBuffer [3] = 0;
391+
currentBuffer [4] = 0;
392+
}
377393
dma_channel_set_read_addr(rgbDmaChan, currentBuffer, true);
378394

379395
// need a new line every X display lines
380396
if ((pxLineRpt == 0))
381397
{
382398
uint32_t requestLine = pxLine + 1;
383-
if (requestLine >= VIRTUAL_PIXELS_Y) requestLine -= VIRTUAL_PIXELS_Y;
384-
385-
multicore_fifo_push_timeout_us(requestLine, 0);
399+
if (requestLine < VIRTUAL_PIXELS_Y)
400+
multicore_fifo_push_timeout_us(requestLine, 0);
386401

387402
#if VGA_SCANLINE_TIME_DEBUG
388403
hasRenderedNext = false;
@@ -434,7 +449,14 @@ void __time_critical_func(vgaLoop)()
434449
{
435450
uint32_t message = multicore_fifo_pop_blocking();
436451

437-
if (message == END_OF_FRAME_MSG)
452+
if ((message & ~1) == FRONT_PORCH_MSG)
453+
{
454+
if (vgaParams.porchFn)
455+
{
456+
vgaParams.porchFn(rgbDataBuffer[message & 1]);
457+
}
458+
}
459+
else if (message == END_OF_FRAME_MSG)
438460
{
439461
if (vgaParams.endOfFrameFn)
440462
{

0 commit comments

Comments
 (0)