; > TestSrc.VIDC TTL RISC OS 2+ POST video controller ; ; The video outputs cannot be tested directly, and VIDC permits only ; write operations on its registers. ; This module performs two tests to verify VIDC's operation ; ; - measure mode 0 FLBK period against IOC timer ; - check that sound DMA occurs (MEMC reports DMA complete) ; ; This code contains timing loops affected by gross changes in processor ; speed, and will re-initialise MEMC with 4K pages and continous refresh. ; ;------------------------------------------------------------------------ ; History ; ; Date Name Comment ; ---- ---- ------- ; 18-Dec-89 ArtG Initial version ; 04-Apr-90 ArtG Use saved MEMC control register setting ; 20-Jun-93 ArtG Medusa VIDC20 / IOMD changes ; ; ;------------------------------------------------------------------------ VIDC_CLOCK_CONTROL * ts_S5_base :OR: &0048 ; Fox VIDC clock control VIDC_CLOCK_NORMAL * &0 VIDC_VFLYWAIT * 72000 ; 200mS timeout loop VIDC_SOUNDWAIT * 40000 ; 100mS timeout loop MEMC_Sstart * MEMCADR :OR: &80000 MEMC_SendN * MEMCADR :OR: &A0000 MEMC_Sptr * MEMCADR :OR: &C0000 MEMC_Son * &00800 ts_Soundbuf * &200 ; relative to PhysRam ts_Soundbuf_length * &400 [ VIDC_Type = "VIDC20" VIDSTIM0 * &A0000000 ; base VIDC20 register values VIDSTIM1 * &A1000000 VIDSFR * &B0000000 VIDSCR * &B1000005 VIDDMAoff * &94000024 VIDVCOWAIT * &5 VIDVCOFREQ * &D0000404 | VIDSTIM0 * &60000000 ; base VIDC register values VIDSTIM1 * &64000000 VIDSFR * &C0000100 ] SUBT FLBK period test ; ; This test attempts to validate the video timing system by checking for ; the proper period from the vertical flyback pulse. To make life easier, ; the test is performed only in mode 0 - i.e a 20mS period. ; ; This test contains a processor-clock timed loop as an outer limit : ; it assumes that the processor will never run more than a factor of ten ; faster than an 8Mhz ARM2. ; This is valid provided that this code isn't run with an ARM3 cache enabled. ; ; Initialise video clock control (for FOX) ; Initialise VIDC ; Clear IR interrupt request in IOC ; Poll IOC until IR appears (if ever) ; Set IOC timer 0 to 32 mS ; Clear IR interrupt request in IOC ; Poll IOC until IR appears (if ever) ; Check timer 0 has counted down 20 mS (19.8 - 20.2 mS) ; Return zero flag set on OK, clear on test failure. ts_VIDC_period ROUT ; Initialise VIDC clock and VIDC [ VIDC_Type = "VIDC1a" LDR r3, =VIDC_CLOCK_CONTROL ; MOV r1, #VIDC_CLOCK_NORMAL STRB r1, [r3] ] MOV r7, #0 MOV r1, #ts_VIDCPhys ADRL r6, TestVIDCTAB 00 LDR r0, [r6],#4 ; setup using main table CMP r0, #-1 STRNE r0, [r1] BNE %BT00 01 LDR r0, [r6],#4 ; enable DMA using 2nd table CMP r0, #-1 STRNE r0, [r1] BNE %BT01 ; Wait for the start of a flyback period 04 LDR r3, =IOC [ MEMC_Type = "IOMD" LDR r1, [r6] ; get FSIZE value from end of TestVIDCTAB STR r1, [r3, #IOMD_FSIZE] ] MOV r1, #vsync_bit STRB r1, [r3, #IOCIRQCLRA] LDR r2, =VIDC_VFLYWAIT ; long timeout loop - C 200mS 05 LDRB r1, [r3, #IOCIRQSTAA] ANDS r1, r1, #vsync_bit BNE %06 SUBS r2, r2,#1 BNE %05 LDR r0,=&fffff ORRS r0, r0,r7, LSL #20 ; Failed : clear 0 flag MOV pc, r14 ; ... and quit ; Set up IOC timer 0 06 LDR r1, =(32 * 1000 * 2) ; 32mS upper limit STRB r1, [r3, #Timer0LL] MOV r0, r1, LSR #8 STRB r0, [r3, #Timer0LH] MOV r0, #0 STRB r0, [r3, #Timer0GO] ; start the timer ; clear the IR and T0 bits MOV r0, #(vsync_bit :OR: timer0_bit) STRB r0, [r3,#IOCIRQCLRA] ; wait for what should be a complete vflyback period 10 LDR r2, =VIDC_VFLYWAIT ; timeout loop - C 200 msec 11 LDRB r0, [r3,#IOCIRQSTAA] TSTS r0, #vsync_bit BNE %14 ; wait for end of vsync TSTS r0, #timer0_bit ; or timer underflow BNE %13 12 SUBS r2, r2, #1 ; or last-ditch timeout BNE %11 13 ORRS r0, r0,#1 ; Failed : clear 0 flag MOV r0, #0 ; but return a zero MOV pc, r14 ; ... and quit ; finished in reasonable time : check against margins. 14 STRB r0, [r3, #Timer0LR] ; latch the current count LDRB r2, [r3, #Timer0CL] LDRB r0, [r3, #Timer0CH] ADD r2, r2, r0, LSL #8 SUB r2, r1, r2 MOV r0, r2, LSR #1 ; Vertical flyback time in uS LDR r1, =19800 ; inside limits ? SUBS r2, r0, r1 BLE %F20 LDR r1, =400 ; 19.8 -> 20.2 mS CMPS r2, r1 BGE %F20 MOV r1,#0 ; OK - 0 indicates pass ; After success using the 24MHz reference clock, select the ; VCO clock (also at 24MHz) and ensure the test is passed after ; a few cycles to allow the VCO to settle. 20 [ VIDC_Type = "VIDC20" TEQ r7,#0 ; if this is the first loop .. BNE %FT21 TEQ r1,#0 ; and it passed OK .. BNE %FT25 MOV r2,#ts_VIDCPhys LDR r3,=VIDVCOFREQ ; set the vco to 24MHz LDR r4,=&E0000400 ; and use the vco clock STMIA r2,{r3,r4} MOV r7,#VIDVCOWAIT ; set the vco test loop count B %BT04 ; and run around again 21 ORR r0,r0,r7,LSL #20 SUBS r7,r7,#1 ; if all attempts now made BEQ %FT25 ; return final result TEQ r1,#0 ; else repeat until passed BNE %BT04 ] ; return with zero flag set if timers were OK ; measured time (in uS) in r0 if flyback was wrong, ; bits 20+ show fail loop - 0 for refclk, 1 for vcoclk. 25 ORRS r1,r1,r1 MOV pc, r14 SUBT Sound DMA test ; ; This test runs the sound DMA system to prove the operation of VIDC and ; MEMC's sound DMA control and the operation of the SIRQ sound DMA complete ; interrupt. ; To avoid making a noise, set the sound muting bit on. ; ; Initialise MEMC sound DMA ; Initialise VIDC sound channel ; Initialise timer 0 and timer 1 to guard-band 10mS sound duration ; Poll IOC until IL1 (SIRQ interrupt) becomes active ; Check timer 0 has completed and timer 1 has not ; ts_SIRQ_period ROUT ; set up MEMC to point to a buffer near the start of physical RAM, ; labelled in r9_fiq by the early memory size tests (not MemSize) ; Registers are set as (address / 16) ; Register bits are (register * 4) in VIDC address mask ; Hence values written to MEMC + register offset + (pointer / 4) [ MEMC_Type = "IOMD" MOV r3,#IOMD_Base MOV r0,#(IOMD_DMA_C_Bit :OR: IOMD_DMA_E_Bit :OR: 16) STR r0,[r3,#IOMD_SD0CR] MOV_fiq r0,r9 ; zero the DMA buffer ADD r1,r0,#ts_Soundbuf_length MOV r2,#0 02 STR r2,[r0],#4 CMPS r0,r1 BNE %BT02 | MOV_fiq r0,r11_fiq BIC r0, r0, #MEMC_Son ; ensure sound DMA disabled STR r0, [r0] LDR r1, =(MEMC_SendN :OR: ((ts_Soundbuf + ts_Soundbuf_length) / 4)) STR r1, [r1] LDR r2, =(MEMC_Sstart :OR: (ts_Soundbuf / 4)) STR r2, [r2] LDR r0, =MEMC_Sptr ; initialise Sptr and set up again .. STR r0, [r0] STR r1, [r1] STR r2, [r2] ] ; Set up VIDC for 8 channels, 10uS (/8) per sample LDR r0, =ts_VIDCPhys [ VIDC_Type = "VIDC20" LDR r1, =VIDSCR ; VIDC10 mode, 24Mhz clock STR r1, [r0] LDR r1, =VIDDMAoff STR r1, [r0] ] LDR r1, =(VIDSTIM0 + 1) ; channel 0 at 100% left LDR r2, =((VIDSTIM1 - VIDSTIM0) + 1) MOV r3, #7 05 STR r1, [r0] ; .. up to 6 at 100% right ADD r1, r1, r2 SUBS r3, r3, #1 BNE %05 SUB r1, r1, #4 ; finally ch7 at centre again STR r1, [r0] LDR r1, =(VIDSFR + 8) ; 10uS/byte STR r1, [r0] ; Set up the timer to limit at 20 us (10uS/sample, 1024-16 bytes => 10.08 mS) LDR r3, =IOC LDR r1, =(20 * 1000 * 2) ; 20 mS upper limit STRB r1, [r3, #Timer1LL] MOV r0, r1, LSR #8 STRB r0, [r3, #Timer1LH] MOV r0, #-1 STRB r0, [r3, #IOCControl] ; mute sound (on IOC system) STRB r0, [r3, #Timer1GO] ; start the timer [ MEMC_Type = "IOMD" MOV r0, #(IOMD_DMA_E_Bit :OR: 16) ; enable the IOMD DMA STR r0, [r3,#IOMD_SD0CR] MOV_fiq r0,r9 ; set the buffer pointers MOV r4,#((ts_Soundbuf_length/2) - 16) STR r0,[r3,#IOMD_SD0CURA] STR r4,[r3,#IOMD_SD0ENDA] LDR r2,[r3,#IOMD_SD0ST] ORR r4,r4,#IOMD_DMA_S_Bit STR r0,[r3,#IOMD_SD0CURB] STR r4,[r3,#IOMD_SD0ENDB] | MOV_fiq r0, r11_fiq ORR r0, r0, #MEMC_Son STR r0, [r0] ; enable the MEMC1a DMA ] ; set long timeout, clear the IL1, T0 and T1 bits LDR r2, =VIDC_SOUNDWAIT ; lastditch timeout loop LDR r0, =(timer0_bit :OR: timer1_bit) STRB r0, [r3,#IOCIRQCLRA] ; Wait until sound DMA completes (or up to about 100 mS), ; then check timers. 10 [ MEMC_Type = "IOMD" LDRB r0,[r3, #IOMD_SD0ST] AND r0, r0, #(IOMD_DMA_O_Bit :OR: IOMD_DMA_I_Bit) CMPS r0, #(IOMD_DMA_O_Bit :OR: IOMD_DMA_I_Bit) BEQ %12 | LDRB r0, [r3,#IOCIRQSTAB] ANDS r0, r0, #sound_IRQ_bit BNE %12 ] LDR r0, [r3, #IOCIRQSTAA] ANDS r0, r0,#timer1_bit ; timeout if timer 1 expires BNE %11 SUBS r2, r2, #1 ; or counter reaches zero BNE %10 11 ORRS r0, r0, #1 ; Failed : clear 0 flag MOV r2, #0 ; return a timeout value of 0 B %15 ; ... and quit ; finished in reasonable time : check time remaining in t1 ; Time for DMA should be 10.24ms (1024 bytes at 10us/byte) ; less up to the time to use the final 16-byte transfer, 160us. 12 STRB r0, [r3, #Timer1LR] ; latch the current count LDRB r2, [r3, #Timer1CL] LDRB r0, [r3, #Timer1CH] ADD r2, r2, r0, LSL #8 SUB r2, r1, r2 MOV r2, r2, LSR #1 ; Sound DMA time in uS LDR r1, =10030 ; inside limits ? SUBS r0, r2, r1 BLE %F13 LDR r1, =260 ; 10.03 -> 10.29 mS CMPS r0, r1 MOVLT r1,#0 ; inside limits : set Z flag 13 ORRS r1,r1,r1 ; return with zero flag set if time (in r2) was within limits 15 [ MEMC_Type = "IOMD" MOV r0, #IOMD_DMA_C_Bit STR r0, [r3,#IOMD_SD0CR] | BIC r0, r0, #MEMC_Son STR r0, [r0] ] MOV r0, r2 ; return the long time value MOV pc, r14 ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; Data tables: VIDC := mode 0, all palette black TestVIDCTAB [ VIDC_Type = "VIDC1a" & &00000000 & &04000000 & &08000000 & &0C000000 & &10000000 & &14000000 & &18000000 & &1C000000 & &20000000 & &24000000 & &28000000 & &2C000000 & &30000000 & &34000000 & &38000000 & &3C000000 & &40000000 ; Border -> black & &44000000 ; Cursor -> black & &48000000 & &4C000000 ; Palette programmed (avoid messy screen on reset) ; ; standard mode 0 setup (except display area disabled) ; & &807FC000 & &8408C000 & &881B0000 & &8C1EC000 ; HDSR & &906EC000 ; HDER & &94770000 & &9C400000 & &A04DC000 & &A4008000 & &A8050000 ; VBSR & &AC098000 ; VDSR & &B0000000 ; VDER < VDSR to disable screen DMA B0000000 & &B44DC000 ; VBER & &E00000B2 ; ; Additional setup : cursor blanked, sound frequency test bit set ; & &C0000100 ; SFR NB. TEST BIT! - also DFlynn requested value & &98258000 ; HCSR & &B8004000 ; VCSR & &BC400000 ; VCER ; don't mess with the stereo image registers: sound code will set them. & &FFFFFFFF ; That's the lot ; ; Further registers to turn screen DMA on again (border all over) ; Must have a video start register before video end register to get ; a vertical flyback interrupt. ; & &B0494000 ; VDER > VDSR to enable screen DMA & &FFFFFFFF ] [ VIDC_Type = "VIDC20" ; This differs from the default RISC OS VIDCTAB in running from ; the 24MHZ video ref clock. H register contents are increased by 50%. ; Program Control Register first, to clear power-down bit & &E0000402 ; CR: FIFO load 16 words, 1 bpp, ck/1, rclk & &E0000402 ; & &B1000001 ; SCR: sound disabled (+use 24MHz clock) ; Don't bother programming all 256 palette entries, we'll be here all night ; Since we're setting up a 1 bit-per-pixel mode, just do colours 0 and 1 & &10000000 ; Palette address register = 0 & &00000000 ; Colour 0 = black & &00000000 ; Colour 1 = black & &407f7f7f ; Border colour = grey & &50000000 ; Pointer colour 1 = black & &60000000 ; Pointer colour 2 = black & &70000000 ; Pointer colour 3 = black ; Get a stable display up so we get stable signals & &800005F8 ; HCR = 114 + 132 + 144 + 960 + 144 + 42 & &8100006A ; HSWR = 114 & &820000EA ; HBSR = 114 + 132 & &83000174 ; HDSR = 114 + 132 + 144 & &84000534 ; HDER = 114 + 132 + 144 + 960 & &850005CA ; HBER = 114 + 132 + 144 + 960 + 144 & &860000F3 ; HCSR = HDSR & &90000137 ; VCR = 3 + 19 + 16 + 256 + 16 + 2 & &91000002 ; VSWR = 3 & &92000015 ; VBSR = 3 + 19 & &93000025 ; VDSR = 3 + 19 + 16 & &94000024 ; VDER = VDSR -1 to disable sceeen DMA & &95000135 ; VBER = 3 + 19 + 16 + 256 + 16 & &96000025 ; VCSR = VDSR & &97000025 ; VCER = VDSR & &C00F1003 ; EREG = comp sync, DACs on, ereg output ext lut & &D000C385 ; FSYNREG, clk = (3+1)/(5+1) * 24MHz = 16MHz & &F0013000 ; DCR: bus D[31:0], Hdisc & &FFFFFFFF & &94000125 ; VDER > VDSR to enable screen DMA & &FFFFFFFF ; FSIZE is one less than number of rasters in Vflyback & &00000037 ; (3 + 19 + 16 + 0 + 16 + 2) - 1 ; Alternate settings for VGA monitor TestVVIDCTAB & &E0000402 ; CR: FIFO load 16 words, 1 bpp, ck/1, rclk & &E0000402 ; & &B1000001 ; SCR: sound disabled (+use 24MHz clock) & &10000000 ; Palette address register = 0 & &00000000 ; Colour 0 = black & &00000000 ; Colour 1 = black & &407f7f7f ; Border colour = grey & &50000000 ; Pointer colour 1 = black & &60000000 ; Pointer colour 2 = black & &70000000 ; Pointer colour 3 = black & &80000310 ; HCR = 92 + 45 + 0 + 640 + 0 + 16 & &81000054 ; HSWR = 92 & &82000080 ; HBSR = 92 + 45 & &83000080 ; HDSR = 92 + 45 + 0 & &84000300 ; HDER = 92 + 45 + 0 + 640 & &85000300 ; HBER = 92 + 45 + 0 + 640 + 0 & &86000080 ; HCSR = HDSR & &9000020B ; VCR = 2 + 32 + 0 + 480 + 0 + 11 & &91000001 ; VSWR = 2 & &92000021 ; VBSR = 2 + 32 & &93000021 ; VDSR = 2 + 32 + 0 & &94000020 ; VDER = VDSR -1 to disable sceeen DMA & &95000201 ; VBER = 2 + 32 + 0 + 480 + 0 & &96000021 ; VCSR = VDSR & &97000021 ; VCER = VDSR & &C0051003 ; EREG = sep/inv sync, DACs on, ereg output ext lut & &F0013000 ; DCR: bus D[31:0], Hdisc & &FFFFFFFF ] END