Search
lxdream.org :: lxdream/test/testdisp.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/testdisp.c
changeset 561:533f6b478071
prev272:fb6be85235e8
author nkeynes
date Wed Dec 02 10:36:49 2009 +1000 (14 years ago)
permissions -rw-r--r--
last change Add missing SUBV instruction to the emulation core (translation core is ok),
along with test cases. Thanks to D. Jeff Dionne for pointing this out.
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Display (2D) tests. Mainly tests video timing / sync (obviously
     5  * it can't actually test display output since there's no way of
     6  * reading the results)
     7  *
     8  * These tests use TMU2 to determine absolute time
     9  * Copyright (c) 2006 Nathan Keynes.
    10  *
    11  * This program is free software; you can redistribute it and/or modify
    12  * it under the terms of the GNU General Public License as published by
    13  * the Free Software Foundation; either version 2 of the License, or
    14  * (at your option) any later version.
    15  *
    16  * This program is distributed in the hope that it will be useful,
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19  * GNU General Public License for more details.
    20  */
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include "lib.h"
    24 #include "asic.h"
    26 #define PVR_BASE 0xA05F8000
    28 #define BORDERCOL   (PVR_BASE+0x040)
    29 #define DISPCFG1 (PVR_BASE+0x044)
    30 #define DISPADDR1 (PVR_BASE+0x050)
    31 #define DISPADDR2 (PVR_BASE+0x054)
    32 #define DISPSIZE (PVR_BASE+0x05C)
    33 #define HPOSEVENT (PVR_BASE+0x0C8)
    34 #define VPOSEVENT (PVR_BASE+0x0CC)
    35 #define DISPCFG2 (PVR_BASE+0x0D0)
    36 #define HBORDER (PVR_BASE+0x0D4)
    37 #define DISPTOTAL (PVR_BASE+0x0D8)
    38 #define VBORDER (PVR_BASE+0x0DC)
    39 #define SYNCTIME (PVR_BASE+0x0E0)
    40 #define DISPCFG3 (PVR_BASE+0x0E8)
    41 #define HPOS     (PVR_BASE+0x0EC)
    42 #define VPOS     (PVR_BASE+0x0F0)
    43 #define SYNCSTAT (PVR_BASE+0x10C)
    45 #define MAX_FRAME_WAIT 0x50000
    47 #define EVENT_RETRACE 5
    49 #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; }
    50 #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; }
    52 void dump_display_regs( FILE *out )
    53 {
    54     fprintf( out, "%08X DISPCFG1:  %08X\n", DISPCFG1, long_read(DISPCFG1) );
    55     fprintf( out, "%08X DISPCFG2:  %08X\n", DISPCFG2, long_read(DISPCFG2) );
    56     fprintf( out, "%08X DISPCFG3:  %08X\n", DISPCFG3, long_read(DISPCFG3) );
    57     fprintf( out, "%08X DISPSIZE:  %08X\n", DISPSIZE, long_read(DISPSIZE) );
    58     fprintf( out, "%08X HBORDER:   %08X\n", HBORDER, long_read(HBORDER) );
    59     fprintf( out, "%08X VBORDER:   %08X\n", VBORDER, long_read(VBORDER) );
    60     fprintf( out, "%08X SYNCTIME:  %08X\n", SYNCTIME, long_read(SYNCTIME) );
    61     fprintf( out, "%08X DISPTOTAL: %08X\n", DISPTOTAL, long_read(DISPTOTAL) );
    62     fprintf( out, "%08X DISPADDR1: %08X\n", DISPADDR1, long_read(DISPADDR1) );
    63     fprintf( out, "%08X DISPADDR2: %08X\n", DISPADDR2, long_read(DISPADDR2) );
    64     fprintf( out, "%08X HPOSEVENT: %08X\n", HPOSEVENT, long_read(HPOSEVENT) );
    65     fprintf( out, "%08X VPOSEVENT: %08X\n", VPOSEVENT, long_read(VPOSEVENT) );
    66     fprintf( out, "%08X HPOS:      %08X\n", HPOS, long_read(HPOS) );
    67     fprintf( out, "%08X VPOS:      %08X\n", VPOS, long_read(VPOS) );
    68     fprintf( out, "%08X SYNCSTAT:  %08X\n", SYNCSTAT, long_read(SYNCSTAT) );
    69 }
    71 uint32_t pal_settings[] = {
    72     DISPCFG1, 0x00000001,
    73     DISPCFG2, 0x00000150,
    74     DISPCFG3, 0x00160000,
    75     DISPSIZE, 0x1413BD3F,
    76     HBORDER, 0x008D034B,
    77     VBORDER, 0x00120102,
    78     DISPTOTAL, 0x0270035F,
    79     SYNCTIME, 0x07D6A53F,
    80     HPOS, 0x000000A4,
    81     VPOS, 0x00120012,
    82     VPOSEVENT, 0x00150136,
    83     0, 0 };
    85 uint32_t ntsc_settings[] = {
    86     DISPCFG1, 0x00000001,
    87     DISPCFG2, 0x00000150,
    88     DISPCFG3, 0x00160000,
    89     DISPSIZE, 0x1413BD3F,
    90     HBORDER, 0x007e0345,
    91     VBORDER, 0x00120102,
    92     DISPTOTAL, 0x020C0359,
    93     SYNCTIME, 0x07d6c63f,
    94     HPOS, 0x000000A4,
    95     VPOS, 0x00120012,
    96     VPOSEVENT, 0x001501FE,
    97     0, 0 };
   100 struct timing {
   101     uint32_t interlaced;
   102     uint32_t total_lines;
   103     uint32_t vsync_lines;
   104     uint32_t line_time_us;
   105     uint32_t field_time_us;
   106     uint32_t hsync_width_us;
   107     uint32_t front_porch_us;
   108     uint32_t back_porch_us;
   109 };
   111 struct timing ntsc_timing = { 1, 525, 6, 31, 16641, 4, 12, 4 };
   112 struct timing pal_timing = { 1, 625, 5, 31, 19949, 4, 12, 4 };
   114 void apply_display_settings( uint32_t *regs ) {
   115     int i;
   116     for( i=0; regs[i] != 0; i+=2 ) {
   117 	long_write( regs[i], regs[i+1] );
   118     }
   119 }
   121 /**
   122  * Wait until the given line is being displayed (ie is set in the syncstat
   123  * register).
   124  * @return 0 if the line is reached before timeout, otherwise -1.
   125  */
   126 int wait_line( int line )
   127 {
   128     int i;
   129     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   130 	uint32_t sync = long_read(SYNCSTAT) & 0x03FF;
   131 	if( sync == line ) {
   132 	    return 0;
   133 	}
   134     }
   135     return -1;
   136 }
   138 /**
   139  * Wait until just after the last line of the frame is being displayed (according
   140  * to the syncstat register). After this function the current line will be 0.
   141  * @return 0 if the last line is the given line, otherwise -1.
   142  */
   143 int wait_lastline( int line )
   144 {
   145     int lastline = 0, i;
   146     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   147 	uint32_t sync = long_read(SYNCSTAT) & 0x03FF;
   148 	if( sync == 0 && lastline != 0 ) {
   149 	    CHECK_IEQUALS( line, lastline );
   150 	    return 0;
   151 	}
   152 	lastline = sync;
   153     }
   154     fprintf( stderr, "Timeout waiting for line %d\n", line );
   155     return -1;
   156 }
   158 int check_events_interlaced( ) 
   159 {
   160     uint32_t status1, status2, status3;
   161     int i;
   162     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   163 	status1 = long_read(SYNCSTAT) & 0x07FF;
   164 	if( status1 == 0x04FF ) {
   165 	    break;
   166 	}
   167     }    
   168     asic_clear();
   169     asic_wait(EVENT_RETRACE);
   170     status1 = long_read(SYNCSTAT);
   171     asic_clear();
   172     asic_wait(EVENT_SCANLINE2);
   173     status2 = long_read(SYNCSTAT);
   174     asic_clear();
   175     asic_wait(EVENT_SCANLINE1);
   176     status3 = long_read(SYNCSTAT);
   177     CHECK_IEQUALS( 0x0000, status1 );
   178     CHECK_IEQUALS( 0x202A, status2 );
   179     CHECK_IEQUALS( 0x226C, status3 );
   181     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   182 	status1 = long_read(SYNCSTAT) & 0x07FF;
   183 	if( status1 == 0x00FF ) {
   184 	    break;
   185 	}
   186     }    
   187     asic_clear();
   188     asic_wait(EVENT_RETRACE);
   189     status1 = long_read(SYNCSTAT);
   190     asic_clear();
   191     asic_wait(EVENT_SCANLINE2);
   192     status2 = long_read(SYNCSTAT);
   193     asic_clear();
   194     asic_wait(EVENT_SCANLINE1);
   195     status3 = long_read(SYNCSTAT);
   196     fprintf( stderr, "%08X, %08X, %08X\n", status1, status2, status3 );
   197     CHECK_IEQUALS( 0x1400, status1 );
   198     CHECK_IEQUALS( 0x242B, status2 );
   199     CHECK_IEQUALS( 0x266D, status3 );
   201     return 0;
   202 }
   204 int check_timing( struct timing *t ) {
   205     uint32_t line_time, field_time;
   206     uint32_t stat;
   207     uint32_t last_line = t->total_lines - 1;
   208     int i;
   210     timer_init();
   211     WAIT_LINE( t->total_lines - 1 );
   212     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   213 	stat = long_read(SYNCSTAT) & 0x07FF;
   214 	if( stat == 0 ) {
   215 	    break;
   216 	} else if( (stat & 0x03FF) != last_line ) {
   217 	    last_line = stat & 0x03FF;
   218 	}
   219     }
   220     if( stat != 0 ) {
   221 	fprintf( stderr, "Timeout waiting for line 0 field 0\n" );
   222 	return -1;
   223     }
   224     timer_run();
   225     CHECK_IEQUALS( stat, 0 ); /* VSYNC, HSYNC, no display */
   227     uint32_t start_of_line = 0;
   228     uint32_t laststat = stat;
   229     uint32_t lastline = 0;
   230     int hsync_count = 0;
   231     while(1) { /* for each line */
   232 	stat = long_read(SYNCSTAT);
   233 	if( stat != laststat ) {
   234 	    uint32_t cur_time = timer_gettime_us();
   235 	    uint32_t time = cur_time - start_of_line;
   236 	    uint32_t line = stat & 0x03FF;
   237 	    if( line != lastline ) {
   238 		if( time != t->line_time_us && /* Allow variance of +1 us */
   239 		    time-1 != t->line_time_us ) {
   240 		    fprintf( stderr, "Assertion failed: Expected line time %dus on line %d but was %dus: %d, %d, %d\n",
   241 			     t->line_time_us, lastline, time, start_of_line, cur_time, line );
   242 		    return -1;
   243 		}
   244 		if( line == 0 ) {
   245 		    CHECK_IEQUALS( t->total_lines-1, lastline );
   246 		    break;
   247 		}
   248 		start_of_line = cur_time;
   249 		lastline = line;
   250 	    } else if( (stat ^ laststat) == 0x1000 && (stat&0x1000) ) {
   251 		hsync_count++;
   252 		if( time != t->hsync_width_us &&
   253 		    time-1 != t->hsync_width_us ) {
   254 		    fprintf( stderr, "Assertion failed: Expected hsync width %dus on line %d but was %dus, stat = %08X, count=%d\n", 
   255 			     t->hsync_width_us, lastline, time, stat, hsync_count );
   256 		    return -1;
   257 		}
   258 	    } else {
   259 		//		fprintf( stderr, "Change %08X to %08X\n", laststat, stat );
   260 	    }
   261 	    laststat = stat;
   262 	}
   263     }
   265     field_time = timer_gettime_us();
   267     if( field_time != t->field_time_us ) {
   268 	fprintf( stderr, "Assertion failed: Expected field time %dus but was %dus\n",
   269 		 t->field_time_us, field_time );
   270 	return -1;
   271     }
   272     return 0;
   273 }
   275 int test_ntsc_timing() {
   276     apply_display_settings( ntsc_settings );
   277     //    check_events_interlaced();
   278     asic_clear();
   279     uint32_t result = check_timing( &ntsc_timing );
   280     dump_display_regs( stdout );
   281     return result;
   282 }
   285 int test_pal_timing() 
   286 {
   287     uint32_t line_time, field_time;
   288     /* Set PAL display mode */
   289     apply_display_settings( pal_settings );
   291     check_events_interlaced();
   292     asic_clear();
   293     uint32_t result = check_timing( &pal_timing );
   294     dump_display_regs( stdout );
   295     return result;
   296 }
   299 /********************************* Main **************************************/
   301 typedef int (*test_func_t)();
   303 test_func_t test_fns[] = { test_ntsc_timing, test_pal_timing,
   304 			   NULL };
   306 int main() 
   307 {
   308     return run_tests( test_fns );
   309 }
.