main: draw images on framebuffer

This commit is contained in:
Zack Buhman 2025-09-17 09:51:47 -05:00
parent 6825999536
commit 9ae9620c8d
7 changed files with 2373 additions and 8 deletions

2
.gitignore vendored
View File

@ -13,3 +13,5 @@ __pycache__
*.order
*.mod.c
*.out
*.rgb565.inc
main

View File

@ -1,2 +1,8 @@
%.csv: %.ods
libreoffice --headless --convert-to csv:"Text - txt - csv (StarCalc)":44,34,76,,,,true --outdir $(dir $@) $<
%.rgb565.inc: %.rgb565
python gen/rgb_txt.py $< > $@
main: main.c bear.rgb565.inc panda.rgb565.inc
gcc -g -Og -std=c23 $< -o $@

2201
bear.rgb565 Normal file

File diff suppressed because one or more lines are too long

9
gen/rgb_txt.py Normal file
View File

@ -0,0 +1,9 @@
import struct
import sys
with open(sys.argv[1], 'rb') as f:
buf = f.read()
for i in range(len(buf) // 2):
value, = struct.unpack('<H', buf[i*2:i*2+2])
print(f"{value},")

150
main.c
View File

@ -17,7 +17,7 @@ static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2)
{
int cnt = 0;
for (int i = 0; i < 4096; i++) {
if (voodoo2->status & STATUS__GRAPHICS_BUSY) {
if (voodoo2->status & STATUS__CHUCK_BUSY) {
cnt = 0;
} else {
cnt += 1;
@ -183,11 +183,10 @@ int main()
////////////////////////////////////////////////////////////////////////
// reset
////////////////////////////////////////////////////////////////////////
init_enable
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS;
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
//wait_graphics_busy(voodoo2);
wait_graphics_busy(voodoo2);
voodoo2->fbiInit0
= FBIINIT0__CHUCK_GRAPHICS_RESET
@ -208,6 +207,7 @@ int main()
// DAC initialization
////////////////////////////////////////////////////////////////////////
// enable fbiInit2/dacRead remap
init_enable
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS
| INIT_ENABLE__REMAP_FBIINIT2_FBIINIT3_TO_DACREAD_VIDEOCHECKSUM;
@ -243,6 +243,150 @@ int main()
printf("dac read: DAC__PLL_PARAMETER__PLL_CONTROL: m: %02x\n",
pll_control_res.m);
// disable fbiInit2/dacRead remap
init_enable
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS;
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
wait_graphics_busy(voodoo2);
////////////////////////////////////////////////////////////////////////
// framebuffer initialization
////////////////////////////////////////////////////////////////////////
voodoo2->fbiInit0
= FBIINIT0__VGA_PASSTHROUGH // disable VGA passthrough
| FBIINIT0__STALL_PCI_ENABLE_FOR_HIGH_WATER_MARK
| FBIINIT0__PCI_FIFO_EMPTY_ENTRIES_LOW_WATER_MARK(0x10)
;
wait_graphics_busy(voodoo2);
int x_tiles = 832 / 32;
int x_tiles_0 = (x_tiles >> 0) & 0b1;
int x_tiles_4_1 = (x_tiles >> 1) & 0b1111;
int x_tiles_5 = (x_tiles >> 5) & 0b1;
voodoo2->fbiInit1
= FBIINIT1__ENABLE_LINEAR_FRAME_BUFFER_READS
| FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_4_1(x_tiles_4_1)
| FBIINIT1__DRIVE_VIDEO_TIMING_DATA_OUTPUTS
| FBIINIT1__DRIVE_VIDEO_TIMING_BLANK_OUTPUTS
| FBIINIT1__DRIVE_VIDEO_TIMING_HSYNC_VSYNC_OUTPUTS
| FBIINIT1__DRIVE_VIDEO_TIMING_DCLK_OUTPUT
| FBIINIT1__VIDEO_TIMING_VCLK_INPUT_SELECT(0)
| FBIINIT1__VIDEO_TIMING_VCLK_SOURCE_SELECT__VID_CLK_2X_SEL
| FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_5(x_tiles_5)
;
wait_graphics_busy(voodoo2);
voodoo2->fbiInit2
= FBIINIT2__DRAM_BANKING_CONFIGURATION
| FBIINIT2__ENABLE_FAST_RAS_READ_CYCLES
| FBIINIT2__ENABLE_GENERATED_DRAM_OE_SIGNAL
| FBIINIT2__VIDEO_BUFFER_OFFSET(247)
| FBIINIT2__ENABLE_DRAM_READ_AHEAD_FIFO
| FBIINIT2__REFRESH_ENABLE
| FBIINIT2__REFRESH_LOAD_VALUE(0x30)
;
wait_graphics_busy(voodoo2);
voodoo2->fbiInit3
= FBIINIT3__DISABLE_TEXTURE_MAPPING
;
wait_graphics_busy(voodoo2);
voodoo2->fbiInit4
= FBIINIT4__ENABLE_READ_AHEAD_LOGIC_FOR_LINEAR_FRAME_BUFFER_READS
;
wait_graphics_busy(voodoo2);
voodoo2->fbiInit5
= FBIINIT5__INVERT_DAC_HSYNC_OUTPUT_TO_DAC
| FBIINIT5__INVERT_DAC_VSYNC_OUTPUT_TO_DAC
;
wait_graphics_busy(voodoo2);
voodoo2->fbiInit6
= FBIINIT6__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_0(x_tiles_0)
;
wait_graphics_busy(voodoo2);
////////////////////////////////////////////////////////////////////////
// video timing initialization
////////////////////////////////////////////////////////////////////////
int y_height = 600;
int x_width = 800;
int v_back_porch = 628 - 605;
int h_back_porch = 1056 - 968;
int v_sync_on = 605 - 601;
int h_sync_on = 968 - 840;
int v_sync_off = 628 - v_sync_on;
int h_sync_off = 1056 - h_sync_on;
voodoo2->hSync
= HSYNC__H_SYNC_ON(h_sync_on - 1)
| HSYNC__H_SYNC_OFF(h_sync_off)
;
wait_graphics_busy(voodoo2);
voodoo2->vSync
= VSYNC__V_SYNC_ON(v_sync_on)
| VSYNC__V_SYNC_OFF(v_sync_off)
;
wait_graphics_busy(voodoo2);
voodoo2->backPorch
= BACKPORCH__H_BACK_PORCH(h_back_porch - 2)
| BACKPORCH__V_BACK_PORCH(v_back_porch)
;
wait_graphics_busy(voodoo2);
voodoo2->videoDimensions
= VIDEODIMENSIONS__X_WIDTH(x_width - 1)
| VIDEODIMENSIONS__Y_HEIGHT(y_height)
;
wait_graphics_busy(voodoo2);
////////////////////////////////////////////////////////////////////////
// panda
////////////////////////////////////////////////////////////////////////
init_enable
= INIT_ENABLE__ENABLE_WRITES_TO_PCI_FIFO;
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
wait_graphics_busy(voodoo2);
static const uint16_t panda[] __attribute__((aligned(4))) = {
#include "panda.rgb565.inc"
};
static const uint16_t bear[] __attribute__((aligned(4))) = {
#include "bear.rgb565.inc"
};
while (true) {
volatile uint16_t * framebuffer
= (volatile uint16_t * )(((ptrdiff_t)resource0_base) + 0x0400000);
printf("panda\n");
for (int y = 0; y < 600; y++) {
for (int x = 0; x < 800; x++) {
framebuffer[y * 1024 + x] = panda[y * 800 + x];
wait_graphics_busy(voodoo2);
}
}
sleep(1);
printf("bear\n");
for (int y = 0; y < 600; y++) {
for (int x = 0; x < 800; x++) {
framebuffer[y * 1024 + x] = bear[y * 800 + x];
wait_graphics_busy(voodoo2);
}
}
sleep(1);
}
////////////////////////////////////////////////////////////////////////
// cleanup
////////////////////////////////////////////////////////////////////////

BIN
panda.rgb565 Normal file

Binary file not shown.

View File

@ -233,6 +233,9 @@
#define VIDEODIMENSIONS__X_WIDTH(n) (((n) & 0x7ff) << 0)
#define VIDEODIMENSIONS__Y_HEIGHT(n) (((n) & 0x7ff) << 16)
#define BACKPORCH__H_BACK_PORCH(n) (((n) & 0x1ff) << 0)
#define BACKPORCH__V_BACK_PORCH(n) (((n) & 0x1ff) << 16)
#define MAXRGBDELTA__BLUE(n) (((n) & 0xff) << 0)
#define MAXRGBDELTA__GREEN(n) (((n) & 0xff) << 8)
#define MAXRGBDELTA__RED(n) (((n) & 0xff) << 16)
@ -262,7 +265,7 @@
#define FBIINIT1__PCI_DEVICE_FUNCTION_NUMBER (1 << 0)
#define FBIINIT1__WAIT_STATE_CYCLES_FOR_PCI_WRITE_ACCESSES (1 << 1)
#define FBIINIT1__ENABLE_LINEAR_FRAME_BUFFER_READS (1 << 3)
#define FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION(n) (((n) & 0xf) << 4)
#define FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_4_1(n) (((n) & 0xf) << 4)
#define FBIINIT1__VIDEO_TIMING_RESET (1 << 8)
#define FBIINIT1__SOFTWARE_OVERRIDE_OF_HSYNC_VSYNC (1 << 9)
#define FBIINIT1__SOFTWARE_OVERRIDE_HSYNC_VALUE (1 << 10)
@ -272,7 +275,7 @@
#define FBIINIT1__DRIVE_VIDEO_TIMING_BLANK_OUTPUTS (1 << 14)
#define FBIINIT1__DRIVE_VIDEO_TIMING_HSYNC_VSYNC_OUTPUTS (1 << 15)
#define FBIINIT1__DRIVE_VIDEO_TIMING_DCLK_OUTPUT (1 << 16)
#define FBIINIT1__VIDEO_TIMING_VCLK_INPUT_SELECT (1 << 17)
#define FBIINIT1__VIDEO_TIMING_VCLK_INPUT_SELECT(n) (((n) & 1) << 17)
#define FBIINIT1__VID_CLK_2X_DELAY_SELECT__NO_DELAY (0 << 18)
#define FBIINIT1__VID_CLK_2X_DELAY_SELECT__4NS (1 << 18)
#define FBIINIT1__VID_CLK_2X_DELAY_SELECT__6NS (2 << 18)
@ -282,7 +285,7 @@
#define FBIINIT1__VIDEO_TIMING_VCLK_SOURCE_SELECT__VID_CLK_2X_SEL (2 << 20)
#define FBIINIT1__ENABLE_24_BITS_PER_PIXEL_VIDEO_OUTPUT (1 << 22)
#define FBIINIT1__ENABLE_SCAN_LINE_INTERLEAVING (1 << 23)
#define FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_5 (1 << 24)
#define FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_5(n) (((n) & 1) << 24)
#define FBIINIT1__ENABLE_VIDEO_EDGE_DETECTION_FILTERING (1 << 25)
#define FBIINIT1__INVERT_VID_CLK_2X (1 << 26)
#define FBIINIT1__VID_CLK_2X_SEL_DELAY_SELECT__NO_DELAY (0 << 27)
@ -368,7 +371,7 @@
#define FBIINIT6__DAC_WR_OUTPUT_VALUE(n) (((n) & 0x3) << 19)
#define FBIINIT6__PCI_FIFO_EMPTY_ENTRIES_LOW_WATER_MARK(n) (((n) & 0x7f) << 21)
#define FBIINIT6__VGA_PASS_N_OUTPUT_VALUE(n) (((n) & 0x3) << 28)
#define FBIINIT6__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION (1 << 30)
#define FBIINIT6__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_0(n) (((n) & 1) << 30)
#define FBIINIT7__CMDFIFO_ENABLE (1 << 8)
#define FBIINIT7__CMDFIFO_OFFSCREEN_MEMORY_STORE (1 << 9)