From 99701f0b576f573f7fd33e942ebc77a3ad133358 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 13 Oct 2023 05:30:21 -0700 Subject: [PATCH] main: initial vga mode setting This feels very hacky, and I'd like to make this better. --- holly.h | 176 +++++++++++++++--------------- main.c | 265 +++++++++++++++++++++++++++++++++++++++++----- regs/gen/holly.py | 2 +- sh7091_bits.h | 6 ++ 4 files changed, 333 insertions(+), 116 deletions(-) diff --git a/holly.h b/holly.h index bd3a9f4..e1f1b7c 100644 --- a/holly.h +++ b/holly.h @@ -1,93 +1,95 @@ #include #include +#include "type.h" + struct holly_reg { - uint32_t ID; /* Device ID */ - uint32_t REVISION; /* Revision Number */ - uint32_t SOFTRESET; /* CORE & TA software reset */ - uint8_t _pad0[8]; - uint32_t STARTRENDER; /* Drawing start */ - uint32_t TEST_SELECT; /* Test (writing this register is prohibited) */ - uint8_t _pad1[4]; - uint32_t PARAM_BASE; /* Base address for ISP parameters */ - uint8_t _pad2[8]; - uint32_t REGION_BASE; /* Base address for Region Array */ - uint32_t SPAN_SORT_CFG; /* Span Sorter control */ - uint8_t _pad3[12]; - uint32_t VO_BORDER_COL; /* Border area color */ - uint32_t FB_R_CTRL; /* Frame buffer read control */ - uint32_t FB_W_CTRL; /* Frame buffer write control */ - uint32_t FB_W_LINESTRIDE;/* Frame buffer line stride */ - uint32_t FB_R_SOF1; /* Read start address for field - 1/strip - 1 */ - uint32_t FB_R_SOF2; /* Read start address for field - 2/strip - 2 */ - uint8_t _pad4[4]; - uint32_t FB_R_SIZE; /* Frame buffer XY size */ - uint32_t FB_W_SOF1; /* Write start address for field - 1/strip - 1 */ - uint32_t FB_W_SOF2; /* Write start address for field - 2/strip - 2 */ - uint32_t FB_X_CLIP; /* Pixel clip X coordinate */ - uint32_t FB_Y_CLIP; /* Pixel clip Y coordinate */ - uint8_t _pad5[4]; - uint32_t FPU_SHAD_SCALE; /* Intensity Volume mode */ - uint32_t FPU_CULL_VAL; /* Comparison value for culling */ - uint32_t FPU_PARAM_CFG; /* Parameter read control */ - uint32_t HALF_OFFSET; /* Pixel sampling control */ - uint32_t FPU_PERP_VAL; /* Comparison value for perpendicular polygons */ - uint32_t ISP_BACKGND_D; /* Background surface depth */ - uint32_t ISP_BACKGND_T; /* Background surface tag */ - uint8_t _pad6[8]; - uint32_t ISP_FEED_CFG; /* Translucent polygon sort mode */ - uint8_t _pad7[4]; - uint32_t SDRAM_REFRESH; /* Texture memory refresh counter */ - uint32_t SDRAM_ARB_CFG; /* Texture memory arbiter control */ - uint32_t SDRAM_CFG; /* Texture memory control */ - uint8_t _pad8[4]; - uint32_t FOG_COL_RAM; /* Color for Look Up table Fog */ - uint32_t FOG_COL_VERT; /* Color for vertex Fog */ - uint32_t FOG_DENSITY; /* Fog scale value */ - uint32_t FOG_CLAMP_MAX; /* Color clamping maximum value */ - uint32_t FOG_CLAMP_MIN; /* Color clamping minimum value */ - uint32_t SPG_TRIGGER_POS;/* External trigger signal HV counter value */ - uint32_t SPG_HBLANK_INT; /* H-blank interrupt control */ - uint32_t SPG_VBLANK_INT; /* V-blank interrupt control */ - uint32_t SPG_CONTROL; /* Sync pulse generator control */ - uint32_t SPG_HBLANK; /* H-blank control */ - uint32_t SPG_LOAD; /* HV counter load value */ - uint32_t SPG_VBLANK; /* V-blank control */ - uint32_t SPG_WIDTH; /* Sync width control */ - uint32_t TEXT_CONTROL; /* Texturing control */ - uint32_t VO_CONTROL; /* Video output control */ - uint32_t VO_STARTX; /* Video output start X position */ - uint32_t VO_STARTY; /* Video output start Y position */ - uint32_t SCALER_CTL; /* X & Y scaler control */ - uint8_t _pad9[16]; - uint32_t PAL_RAM_CTRL; /* Palette RAM control */ - uint32_t SPG_STATUS; /* Sync pulse generator status */ - uint32_t FB_BURSTCTRL; /* Frame buffer burst control */ - uint32_t FB_C_SOF; /* Current frame buffer start address */ - uint32_t Y_COEFF; /* Y scaling coefficent */ - uint32_t PT_ALPHA_REF; /* Alpha value for Punch Through polygon comparison */ - uint8_t _pad10[4]; - uint32_t TA_OL_BASE; /* Object List write start address */ - uint32_t TA_ISP_BASE; /* ISP/TSP Parameter write start address */ - uint32_t TA_OL_LIMIT; /* Object List write limit address */ - uint32_t TA_ISP_LIMIT; /* ISP/TSP Parameter limit address */ - uint32_t TA_NEXT_OPB; /* Start address for the Object Pointer Block */ - uint32_t TA_ITP_CURRENT; /* Starting address where the next ISP/TSP Parameters are stored */ - uint32_t TA_GLOB_TILE_CLIP;/* Global Tile Clip control */ - uint32_t TA_ALLOC_CTRL; /* Object list control */ - uint32_t TA_LIST_INIT; /* TA initialization */ - uint32_t TA_YUV_TEX_BASE;/* YUV422 texture write start address */ - uint32_t TA_YUV_TEX_CTRL;/* YUV converter control */ - uint32_t TA_YUV_TEX_CNT; /* YUV converter macro block counter value */ - uint8_t _pad11[12]; - uint32_t TA_LIST_CONT; /* TA continuation processing */ - uint32_t TA_NEXT_OPB_INIT;/* Additional OPB starting address */ - uint8_t _pad12[152]; - uint8_t FOG_TABLE[512]; /* Look-up table fog data */ - uint8_t _pad13[512]; - uint8_t TA_OL_POINTERS[2400];/* TA Object List Pointer data */ - uint8_t _pad14[160]; - uint8_t PALETTE_RAM[4096];/* Palette RAM */ + reg32 ID; /* Device ID */ + reg32 REVISION; /* Revision Number */ + reg32 SOFTRESET; /* CORE & TA software reset */ + reg8 _pad0[8]; + reg32 STARTRENDER; /* Drawing start */ + reg32 TEST_SELECT; /* Test (writing this register is prohibited) */ + reg8 _pad1[4]; + reg32 PARAM_BASE; /* Base address for ISP parameters */ + reg8 _pad2[8]; + reg32 REGION_BASE; /* Base address for Region Array */ + reg32 SPAN_SORT_CFG; /* Span Sorter control */ + reg8 _pad3[12]; + reg32 VO_BORDER_COL; /* Border area color */ + reg32 FB_R_CTRL; /* Frame buffer read control */ + reg32 FB_W_CTRL; /* Frame buffer write control */ + reg32 FB_W_LINESTRIDE; /* Frame buffer line stride */ + reg32 FB_R_SOF1; /* Read start address for field - 1/strip - 1 */ + reg32 FB_R_SOF2; /* Read start address for field - 2/strip - 2 */ + reg8 _pad4[4]; + reg32 FB_R_SIZE; /* Frame buffer XY size */ + reg32 FB_W_SOF1; /* Write start address for field - 1/strip - 1 */ + reg32 FB_W_SOF2; /* Write start address for field - 2/strip - 2 */ + reg32 FB_X_CLIP; /* Pixel clip X coordinate */ + reg32 FB_Y_CLIP; /* Pixel clip Y coordinate */ + reg8 _pad5[4]; + reg32 FPU_SHAD_SCALE; /* Intensity Volume mode */ + reg32 FPU_CULL_VAL; /* Comparison value for culling */ + reg32 FPU_PARAM_CFG; /* Parameter read control */ + reg32 HALF_OFFSET; /* Pixel sampling control */ + reg32 FPU_PERP_VAL; /* Comparison value for perpendicular polygons */ + reg32 ISP_BACKGND_D; /* Background surface depth */ + reg32 ISP_BACKGND_T; /* Background surface tag */ + reg8 _pad6[8]; + reg32 ISP_FEED_CFG; /* Translucent polygon sort mode */ + reg8 _pad7[4]; + reg32 SDRAM_REFRESH; /* Texture memory refresh counter */ + reg32 SDRAM_ARB_CFG; /* Texture memory arbiter control */ + reg32 SDRAM_CFG; /* Texture memory control */ + reg8 _pad8[4]; + reg32 FOG_COL_RAM; /* Color for Look Up table Fog */ + reg32 FOG_COL_VERT; /* Color for vertex Fog */ + reg32 FOG_DENSITY; /* Fog scale value */ + reg32 FOG_CLAMP_MAX; /* Color clamping maximum value */ + reg32 FOG_CLAMP_MIN; /* Color clamping minimum value */ + reg32 SPG_TRIGGER_POS; /* External trigger signal HV counter value */ + reg32 SPG_HBLANK_INT; /* H-blank interrupt control */ + reg32 SPG_VBLANK_INT; /* V-blank interrupt control */ + reg32 SPG_CONTROL; /* Sync pulse generator control */ + reg32 SPG_HBLANK; /* H-blank control */ + reg32 SPG_LOAD; /* HV counter load value */ + reg32 SPG_VBLANK; /* V-blank control */ + reg32 SPG_WIDTH; /* Sync width control */ + reg32 TEXT_CONTROL; /* Texturing control */ + reg32 VO_CONTROL; /* Video output control */ + reg32 VO_STARTX; /* Video output start X position */ + reg32 VO_STARTY; /* Video output start Y position */ + reg32 SCALER_CTL; /* X & Y scaler control */ + reg8 _pad9[16]; + reg32 PAL_RAM_CTRL; /* Palette RAM control */ + reg32 SPG_STATUS; /* Sync pulse generator status */ + reg32 FB_BURSTCTRL; /* Frame buffer burst control */ + reg32 FB_C_SOF; /* Current frame buffer start address */ + reg32 Y_COEFF; /* Y scaling coefficent */ + reg32 PT_ALPHA_REF; /* Alpha value for Punch Through polygon comparison */ + reg8 _pad10[4]; + reg32 TA_OL_BASE; /* Object List write start address */ + reg32 TA_ISP_BASE; /* ISP/TSP Parameter write start address */ + reg32 TA_OL_LIMIT; /* Object List write limit address */ + reg32 TA_ISP_LIMIT; /* ISP/TSP Parameter limit address */ + reg32 TA_NEXT_OPB; /* Start address for the Object Pointer Block */ + reg32 TA_ITP_CURRENT; /* Starting address where the next ISP/TSP Parameters are stored */ + reg32 TA_GLOB_TILE_CLIP; /* Global Tile Clip control */ + reg32 TA_ALLOC_CTRL; /* Object list control */ + reg32 TA_LIST_INIT; /* TA initialization */ + reg32 TA_YUV_TEX_BASE; /* YUV422 texture write start address */ + reg32 TA_YUV_TEX_CTRL; /* YUV converter control */ + reg32 TA_YUV_TEX_CNT; /* YUV converter macro block counter value */ + reg8 _pad11[12]; + reg32 TA_LIST_CONT; /* TA continuation processing */ + reg32 TA_NEXT_OPB_INIT; /* Additional OPB starting address */ + reg8 _pad12[152]; + reg8 FOG_TABLE[512]; /* Look-up table fog data */ + reg8 _pad13[512]; + reg8 TA_OL_POINTERS[2400];/* TA Object List Pointer data */ + reg8 _pad14[160]; + reg8 PALETTE_RAM[4096]; /* Palette RAM */ }; static_assert((offsetof (struct holly_reg, ID)) == 0x0); @@ -162,5 +164,5 @@ static_assert((offsetof (struct holly_reg, FOG_TABLE)) == 0x200); static_assert((offsetof (struct holly_reg, TA_OL_POINTERS)) == 0x600); static_assert((offsetof (struct holly_reg, PALETTE_RAM)) == 0x1000); -extern holly_reg HOLLY; +extern struct holly_reg HOLLY __asm("HOLLY"); diff --git a/main.c b/main.c index 0d9cd6d..9b6783a 100644 --- a/main.c +++ b/main.c @@ -3,51 +3,260 @@ #include "cache.h" #include "sh7091.h" +#include "sh7091_bits.h" +#include "holly.h" volatile uint32_t * RAM = (volatile uint32_t *)0xa5000000; volatile uint32_t * SPG_STATUS = (volatile uint32_t *)0xa05f810; +uint32_t get_cable_type() +{ + /* set all pins to input */ + SH7091.BSC.PCTRA = 0; + + /* get cable type from pins 9 + 8 */ + return SH7091.BSC.PDTRA & PDTRA__MASK; +} + +void vga1() +{ + uint16_t pclk_delay = 0x0016; + uint32_t fb_r_ctrl = HOLLY.FB_R_CTRL; + HOLLY.FB_R_CTRL = fb_r_ctrl & ~(1 << 0); // fb_enable = 0 + HOLLY.VO_CONTROL = pclk_delay << 16 | (1 << 3); // blank_video + HOLLY.FB_R_CTRL = fb_r_ctrl & (1<<23); // vclk_div, for VGA + + HOLLY.FB_R_SIZE = 0; + + uint16_t vblank_in = 0x0208; + uint16_t vblank_out = 0x0015; + HOLLY.SPG_VBLANK_INT = (vblank_out << 16) | (vblank_in << 0); + + HOLLY.SPG_CONTROL = (1 << 8); // sync_direction__output ; non-default + + uint16_t hbstart = 0x0345; // default + uint16_t hbend = 0x007e; // default + HOLLY.SPG_HBLANK = (hbend << 16) | (hbstart << 0); + + uint16_t hcount = 0x0359; // default + uint16_t vcount = 0x020c; // non-default + HOLLY.SPG_LOAD = (vcount << 16) | (hcount << 0); + + uint16_t vbstart = 0x0208; // non-default + uint16_t vbend = 0x0028; // non-default + HOLLY.SPG_VBLANK = (vbend << 16) | (vbstart << 0); + + uint16_t hswidth = 0x003f; + uint16_t vswidth = 0x0003; + uint16_t bpwidth = 0x0319; + uint16_t eqwidth = 0x000f; + HOLLY.SPG_WIDTH = + (hswidth << 0) + | (vswidth << 8) + | (bpwidth << 12) + | (eqwidth << 22); + + uint16_t startx = 0x0a8; + uint16_t starty = 0x028; + HOLLY.VO_STARTX = startx; + HOLLY.VO_STARTY = (starty << 16) | (starty << 0); + + HOLLY.SPG_HBLANK_INT = hbstart << 16; +} + +void vga2() +{ + uint16_t xsize = 640; + uint16_t ysize = 480; + + uint16_t fb_xclip_min = 0; + uint16_t fb_xclip_max = xsize-1; + HOLLY.FB_X_CLIP = (fb_xclip_max << 16) | (fb_xclip_min << 0); + uint16_t fb_yclip_min = 0; + uint16_t fb_yclip_max = ysize-1; + HOLLY.FB_Y_CLIP = (fb_yclip_max << 16) | (fb_yclip_min << 0); + + uint16_t fb_latency = 0x09; + uint16_t fb_burstctrl = 15 - fb_latency; + uint16_t wr_burst = 0x08; + HOLLY.FB_BURSTCTRL = 0 + | (fb_burstctrl << 0) + | (fb_latency << 4) + | (wr_burst << 9) + ; + + uint32_t fb_xsize = (xsize * 16)/(32) - 1; + uint32_t fb_ysize = ysize - 3; + uint32_t fb_mod = 1; + HOLLY.FB_R_SIZE = 0 + | (fb_xsize << 0) + | (fb_ysize << 10) + | (fb_mod << 20); + + uint16_t coeff0 = 0x40; + uint16_t coeff1 = 0x80; + HOLLY.Y_COEFF = (coeff1 << 8) | (coeff0 << 0); + + uint16_t vscale_factor = 0x0400; + HOLLY.SCALER_CTL = (vscale_factor << 0); + + uint32_t fb_linestride = (xsize * 16) / 64; + HOLLY.FB_W_LINESTRIDE = fb_linestride; + + HOLLY.FB_W_CTRL = 0 + | 0b001 << 0 // fb_packmode: RGB 565 + ; + + HOLLY.FB_W_SOF1 = 0; + HOLLY.FB_W_SOF2 = 0; + HOLLY.FB_R_SOF1 = 0; + HOLLY.FB_R_SOF2 = 0; + + HOLLY.FB_R_CTRL = 0 + | 1 << 23 // vclk_div + | 0 << 22 // fb_strip_buf_en + | 0 << 16 // fb_strip_size + | 0 << 8 // fb_chroma_threshold + | 0 << 4 // fb_concat + | 1 << 2 // fb_depth + | 0 << 1 // fb_line_double + | 1 << 0 // fb_enable + ; + + *((reg32 *)0xa0702c00) = 0; +} + +void v_sync_in() +{ +#define V_SYNC (1<<13) + while (!(V_SYNC & HOLLY.SPG_STATUS)) { + asm volatile ("nop"); + } + while ((V_SYNC & HOLLY.SPG_STATUS)) { + asm volatile ("nop"); + } +#undef V_SYNC +} + +void vga() +{ + get_cable_type(); + + HOLLY.SOFTRESET = 0; + HOLLY.TEXT_CONTROL = 3; + HOLLY.FB_W_CTRL = 9; + + SH7091.SCIF.SCFTDR2 = 'g'; + /* + */ + SH7091.SCIF.SCFTDR2 = 'v'; + vga1(); + vga2(); + + v_sync_in(); + + HOLLY.VO_BORDER_COL = 31; + HOLLY.VO_CONTROL = 0x0016; +} + +extern uint32_t __bss_link_start __asm("__bss_link_start"); +extern uint32_t __bss_link_end __asm("__bss_link_end"); + +struct rgb +{ + unsigned char r; + unsigned char g; + unsigned char b; +}; + +struct hsv +{ + unsigned char h; + unsigned char s; + unsigned char v; +}; + +struct rgb hsv_to_rgb(struct hsv hsv) +{ + struct rgb rgb; + unsigned char region, remainder, p, q, t; + + if (hsv.s == 0) { + rgb.r = hsv.v; + rgb.g = hsv.v; + rgb.b = hsv.v; + return rgb; + } + + region = hsv.h / 43; + remainder = (hsv.h - (region * 43)) * 6; + + p = (hsv.v * (255 - hsv.s)) >> 8; + q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8; + t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8; + + switch (region) { + case 0: rgb.r = hsv.v; rgb.g = t; rgb.b = p; break; + case 1: rgb.r = q; rgb.g = hsv.v; rgb.b = p; break; + case 2: rgb.r = p; rgb.g = hsv.v; rgb.b = t; break; + case 3: rgb.r = p; rgb.g = q; rgb.b = hsv.v; break; + case 4: rgb.r = t; rgb.g = p; rgb.b = hsv.v; break; + default: rgb.r = hsv.v; rgb.g = p; rgb.b = q; break; + } + + return rgb; +} + void main() { cache_init(); + uint32_t * start = &__bss_link_start; + uint32_t * end = &__bss_link_end; + while (start < end) { + *start++ = 0; + } + // clear BSS +#define SCSCR2__TE (1 << 5) +#define SCSCR2__RE (1 << 4) + SH7091.SCIF.SCSCR2 = 0; + SH7091.SCIF.SCSMR2 = 0; + SH7091.SCIF.SCBRR2 = 12; + + SH7091.SCIF.SCFCR2 = (1 << 2) | (1 << 1); // tfrst rfrst + SH7091.SCIF.SCFCR2 = 0; + + SH7091.SCIF.SCSPTR2 = 0; + SH7091.SCIF.SCLSR2 = 0; + + SH7091.SCIF.SCSCR2 = SCSCR2__TE | SCSCR2__RE; + SH7091.SCIF.SCFTDR2 = 'H'; SH7091.SCIF.SCFTDR2 = 'e'; SH7091.SCIF.SCFTDR2 = 'l'; SH7091.SCIF.SCFTDR2 = 'o'; - /* - *SOFT_RESET = 0b111; - *SOFT_RESET = 0b000; - - *VO_CONTROL |= 1 << 3; - *VO_BORDER_COL = 31; - - for (int i = 0; i < (2*1024*1024 + 1024 * 2 + 512 + 4) / 4; i++) { - RAM[i] = 0x1; - } - */ + vga(); while (1) { + v_sync_in(); + SH7091.SCIF.SCFTDR2 = 'v'; + SH7091.SCIF.SCFTDR2 = 'g'; + SH7091.SCIF.SCFTDR2 = 'a'; + + reg16 * vram = (reg16 *)0xa5000000; + for (int y = 0; y < 480; y++) { + for (int x = 0; x < 640; x++) { + struct hsv hsv = {(y * 255) / 480, 255, 255}; + struct rgb rgb = hsv_to_rgb(hsv); + vram[y * 640 + x] = (rgb.r >> 3) | ((rgb.g >> 2) << 5) | ((rgb.b >> 3) << 11); + } + } + vram[0] = 0xf000; + vram[10] = 0xf0ff; + vram[11] = 0xf0ab; } } - -/* - { - DM_640x480, - 640, 480, - VID_INTERLACE, // flags - CT_VGA, // cable type - 0, // pixel mode - 0x20C, 0x359, // scanlines, clocks per scanline - 0xAC, 0x28, // bitmap x, bitmap y - 0x15, 0x104, // first scanline interrupt, second scanline interrupt - 0x7E, 0x345, // border x start, border x stop - 0x24, 0x204, // border y start, border y stop - 0, 1, // current framebuffer, number of framebuffers - { 0, 0, 0, 0 } // offset to framebuffers - }, -*/ diff --git a/regs/gen/holly.py b/regs/gen/holly.py index c42d9f1..7aad1aa 100644 --- a/regs/gen/holly.py +++ b/regs/gen/holly.py @@ -6,7 +6,7 @@ from sh7091 import headers from generate import renderer def block(): - yield "extern holly_reg HOLLY;" + yield 'extern struct holly_reg HOLLY __asm("HOLLY");' input_file = sys.argv[1] rows = read_input(input_file) diff --git a/sh7091_bits.h b/sh7091_bits.h index a83a129..f5b6d28 100644 --- a/sh7091_bits.h +++ b/sh7091_bits.h @@ -7,3 +7,9 @@ #define CCR__CB (1 << 2) #define CCR__WT (1 << 1) #define CCR__OCE (1 << 0) + +#define PDTRA__MASK (0b11 << 8) +#define PDTRA__VGA (0b00 << 8) +#define PDTRA__RESERVED (0b01 << 8) +#define PDTRA__RGB (0b10 << 8) +#define PDTRA__AV (0b11 << 8)