nkeynes@263 | 1 | /**
|
nkeynes@263 | 2 | * $Id: testdisp.c,v 1.1 2007-01-03 09:05:13 nkeynes Exp $
|
nkeynes@263 | 3 | *
|
nkeynes@263 | 4 | * Display (2D) tests. Mainly tests video timing / sync (obviously
|
nkeynes@263 | 5 | * it can't actually test display output since there's no way of
|
nkeynes@263 | 6 | * reading the results)
|
nkeynes@263 | 7 | *
|
nkeynes@263 | 8 | * These tests use TMU2 to determine absolute time
|
nkeynes@263 | 9 | * Copyright (c) 2006 Nathan Keynes.
|
nkeynes@263 | 10 | *
|
nkeynes@263 | 11 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@263 | 12 | * it under the terms of the GNU General Public License as published by
|
nkeynes@263 | 13 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@263 | 14 | * (at your option) any later version.
|
nkeynes@263 | 15 | *
|
nkeynes@263 | 16 | * This program is distributed in the hope that it will be useful,
|
nkeynes@263 | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@263 | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@263 | 19 | * GNU General Public License for more details.
|
nkeynes@263 | 20 | */
|
nkeynes@263 | 21 | #include <stdlib.h>
|
nkeynes@263 | 22 | #include <stdio.h>
|
nkeynes@263 | 23 | #include "lib.h"
|
nkeynes@263 | 24 | #include "asic.h"
|
nkeynes@263 | 25 |
|
nkeynes@263 | 26 | #define PVR_BASE 0xA05F8000
|
nkeynes@263 | 27 |
|
nkeynes@263 | 28 | #define BORDERCOL (PVR_BASE+0x040)
|
nkeynes@263 | 29 | #define DISPCFG1 (PVR_BASE+0x044)
|
nkeynes@263 | 30 | #define DISPADDR1 (PVR_BASE+0x050)
|
nkeynes@263 | 31 | #define DISPADDR2 (PVR_BASE+0x054)
|
nkeynes@263 | 32 | #define DISPSIZE (PVR_BASE+0x05C)
|
nkeynes@263 | 33 | #define HPOSEVENT (PVR_BASE+0x0C8)
|
nkeynes@263 | 34 | #define VPOSEVENT (PVR_BASE+0x0CC)
|
nkeynes@263 | 35 | #define DISPCFG2 (PVR_BASE+0x0D0)
|
nkeynes@263 | 36 | #define HBORDER (PVR_BASE+0x0D4)
|
nkeynes@263 | 37 | #define VSYNC (PVR_BASE+0x0D8)
|
nkeynes@263 | 38 | #define VBORDER (PVR_BASE+0x0DC)
|
nkeynes@263 | 39 | #define HSYNC (PVR_BASE+0x0E0)
|
nkeynes@263 | 40 | #define DISPCFG3 (PVR_BASE+0x0E8)
|
nkeynes@263 | 41 | #define HPOS (PVR_BASE+0x0EC)
|
nkeynes@263 | 42 | #define VPOS (PVR_BASE+0x0F0)
|
nkeynes@263 | 43 | #define SYNCSTAT (PVR_BASE+0x10C)
|
nkeynes@263 | 44 |
|
nkeynes@263 | 45 | #define MAX_FRAME_WAIT 0x10000000
|
nkeynes@263 | 46 |
|
nkeynes@263 | 47 | #define WAIT_LINE( a ) if( wait_line(a) != 0 ) { fprintf(stderr, "Timeout at %s:%d:%s() waiting for line %d\n", __FILE__, __LINE__, __func__, a ); return -1; }
|
nkeynes@263 | 48 | #define WAIT_LASTLINE( a ) if( wait_lastline(a) != 0 ) { fprintf(stderr, "Last line check failed at %s:%d:%s() waiting for line %d\n", __FILE__, __LINE__, __func__, a ); return -1; }
|
nkeynes@263 | 49 |
|
nkeynes@263 | 50 | void dump_display_regs( FILE *out )
|
nkeynes@263 | 51 | {
|
nkeynes@263 | 52 | fprintf( out, "%08X DISPCFG1: %08X\n", DISPCFG1, long_read(DISPCFG1) );
|
nkeynes@263 | 53 | fprintf( out, "%08X DISPCFG2: %08X\n", DISPCFG2, long_read(DISPCFG2) );
|
nkeynes@263 | 54 | fprintf( out, "%08X DISPCFG3: %08X\n", DISPCFG3, long_read(DISPCFG3) );
|
nkeynes@263 | 55 | fprintf( out, "%08X DISPSIZE: %08X\n", DISPSIZE, long_read(DISPSIZE) );
|
nkeynes@263 | 56 | fprintf( out, "%08X HBORDER: %08X\n", HBORDER, long_read(HBORDER) );
|
nkeynes@263 | 57 | fprintf( out, "%08X VBORDER: %08X\n", VBORDER, long_read(VBORDER) );
|
nkeynes@263 | 58 | fprintf( out, "%08X HSYNC: %08X\n", HSYNC, long_read(HSYNC) );
|
nkeynes@263 | 59 | fprintf( out, "%08X VSYNC: %08X\n", VSYNC, long_read(VSYNC) );
|
nkeynes@263 | 60 | fprintf( out, "%08X DISPADDR1: %08X\n", DISPADDR1, long_read(DISPADDR1) );
|
nkeynes@263 | 61 | fprintf( out, "%08X DISPADDR2: %08X\n", DISPADDR2, long_read(DISPADDR2) );
|
nkeynes@263 | 62 | fprintf( out, "%08X HPOSEVENT: %08X\n", HPOSEVENT, long_read(HPOSEVENT) );
|
nkeynes@263 | 63 | fprintf( out, "%08X VPOSEVENT: %08X\n", VPOSEVENT, long_read(VPOSEVENT) );
|
nkeynes@263 | 64 | fprintf( out, "%08X HPOS: %08X\n", HPOS, long_read(HPOS) );
|
nkeynes@263 | 65 | fprintf( out, "%08X VPOS: %08X\n", VPOS, long_read(VPOS) );
|
nkeynes@263 | 66 | fprintf( out, "%08X SYNCSTAT: %08X\n", SYNCSTAT, long_read(SYNCSTAT) );
|
nkeynes@263 | 67 | }
|
nkeynes@263 | 68 |
|
nkeynes@263 | 69 | uint32_t pal_settings[] = {
|
nkeynes@263 | 70 | DISPCFG1, 0x00000001,
|
nkeynes@263 | 71 | DISPCFG2, 0x00000150,
|
nkeynes@263 | 72 | DISPCFG3, 0x00160000,
|
nkeynes@263 | 73 | DISPSIZE, 0x1413BD3F,
|
nkeynes@263 | 74 | HBORDER, 0x008D034B,
|
nkeynes@263 | 75 | VBORDER, 0x00120102,
|
nkeynes@263 | 76 | VSYNC, 0x0270035F,
|
nkeynes@263 | 77 | HSYNC, 0x07D6A53F,
|
nkeynes@263 | 78 | HPOS, 0x000000A4,
|
nkeynes@263 | 79 | VPOS, 0x00120012,
|
nkeynes@263 | 80 | 0, 0 };
|
nkeynes@263 | 81 |
|
nkeynes@263 | 82 | void apply_display_settings( uint32_t *regs ) {
|
nkeynes@263 | 83 | int i;
|
nkeynes@263 | 84 | for( i=0; regs[i] != 0; i+=2 ) {
|
nkeynes@263 | 85 | long_write( regs[i], regs[i+1] );
|
nkeynes@263 | 86 | }
|
nkeynes@263 | 87 | }
|
nkeynes@263 | 88 |
|
nkeynes@263 | 89 | /**
|
nkeynes@263 | 90 | * Wait until the given line is being displayed (ie is set in the syncstat
|
nkeynes@263 | 91 | * register).
|
nkeynes@263 | 92 | * @return 0 if the line is reached before timeout, otherwise -1.
|
nkeynes@263 | 93 | */
|
nkeynes@263 | 94 | int wait_line( int line )
|
nkeynes@263 | 95 | {
|
nkeynes@263 | 96 | int i;
|
nkeynes@263 | 97 | for( i=0; i< MAX_FRAME_WAIT; i++ ) {
|
nkeynes@263 | 98 | uint32_t sync = long_read(SYNCSTAT) & 0x03FF;
|
nkeynes@263 | 99 | if( sync == line ) {
|
nkeynes@263 | 100 | return 0;
|
nkeynes@263 | 101 | }
|
nkeynes@263 | 102 | }
|
nkeynes@263 | 103 | return -1;
|
nkeynes@263 | 104 | }
|
nkeynes@263 | 105 |
|
nkeynes@263 | 106 | /**
|
nkeynes@263 | 107 | * Wait until just after the last line of the frame is being displayed (according
|
nkeynes@263 | 108 | * to the syncstat register). After this function the current line will be 0.
|
nkeynes@263 | 109 | * @return 0 if the last line is the given line, otherwise -1.
|
nkeynes@263 | 110 | */
|
nkeynes@263 | 111 | int wait_lastline( int line )
|
nkeynes@263 | 112 | {
|
nkeynes@263 | 113 | int lastline = -1, i;
|
nkeynes@263 | 114 | for( i=0; i< MAX_FRAME_WAIT; i++ ) {
|
nkeynes@263 | 115 | uint32_t sync = long_read(SYNCSTAT) & 0x03FF;
|
nkeynes@263 | 116 | if( sync == 0 && lastline != -1 ) {
|
nkeynes@263 | 117 | CHECK_IEQUALS( line, lastline );
|
nkeynes@263 | 118 | return 0;
|
nkeynes@263 | 119 | }
|
nkeynes@263 | 120 | lastline = sync;
|
nkeynes@263 | 121 | }
|
nkeynes@263 | 122 | fprintf( stderr, "Timeout waiting for line %d\n", line );
|
nkeynes@263 | 123 | return -1;
|
nkeynes@263 | 124 | }
|
nkeynes@263 | 125 |
|
nkeynes@263 | 126 | int test_ntsc_timing() {
|
nkeynes@263 | 127 |
|
nkeynes@263 | 128 | return 0;
|
nkeynes@263 | 129 | }
|
nkeynes@263 | 130 |
|
nkeynes@263 | 131 |
|
nkeynes@263 | 132 | int test_pal_timing()
|
nkeynes@263 | 133 | {
|
nkeynes@263 | 134 | uint32_t line_time, field_time;
|
nkeynes@263 | 135 | /* Set PAL display mode */
|
nkeynes@263 | 136 | apply_display_settings( pal_settings );
|
nkeynes@263 | 137 |
|
nkeynes@263 | 138 | asic_clear();
|
nkeynes@263 | 139 |
|
nkeynes@263 | 140 | /* Check basic frame timings: 31.919 us per line, 19.945 ms per field */
|
nkeynes@263 | 141 | /* Wait for a line 0 (either frame) */
|
nkeynes@263 | 142 | WAIT_LINE(0);
|
nkeynes@263 | 143 | timer_start();
|
nkeynes@263 | 144 | WAIT_LINE(1);
|
nkeynes@263 | 145 | line_time = timer_gettime_us();
|
nkeynes@263 | 146 | WAIT_LASTLINE(624);
|
nkeynes@263 | 147 | field_time = timer_gettime_us();
|
nkeynes@263 | 148 | fprintf( stdout, "Line time: %dus, frame time: %dus\n", line_time, field_time );
|
nkeynes@263 | 149 | // CHECK_IEQUALS( 31, line_time );
|
nkeynes@263 | 150 | CHECK_IEQUALS( 19949, field_time );
|
nkeynes@263 | 151 | dump_display_regs( stdout );
|
nkeynes@263 | 152 | return 0;
|
nkeynes@263 | 153 | }
|
nkeynes@263 | 154 |
|
nkeynes@263 | 155 |
|
nkeynes@263 | 156 | /********************************* Main **************************************/
|
nkeynes@263 | 157 |
|
nkeynes@263 | 158 | typedef int (*test_func_t)();
|
nkeynes@263 | 159 |
|
nkeynes@263 | 160 | test_func_t test_fns[] = { test_ntsc_timing, test_pal_timing,
|
nkeynes@263 | 161 | NULL };
|
nkeynes@263 | 162 |
|
nkeynes@263 | 163 | int main()
|
nkeynes@263 | 164 | {
|
nkeynes@263 | 165 | return run_tests( test_fns );
|
nkeynes@263 | 166 | }
|