# HG changeset patch # User Paul Boddie # Date 1509833610 -3600 # Node ID 045ed8ec216057998e14b812188fdc0a6c13deb4 # Parent ae02a1821af37580a8c176f1b1a706158e35573a A tentative sketch of how OC3 might drive line DMA transfers and the clock pulse of a flip-flop. This does not work, perhaps because the OC3 events might not be causing the DMA transfers. However, if OC3 interrupts are enabled they will most likely cause interruptions that are too frequent and yet cannot be serviced frequently enough for the DMA transfers to occur at the appropriate rate. diff -r ae02a1821af3 -r 045ed8ec2160 README.txt --- a/README.txt Sat Nov 04 21:47:48 2017 +0100 +++ b/README.txt Sat Nov 04 23:13:30 2017 +0100 @@ -39,7 +39,7 @@ D3/RB3 7 22 RB11/PGEC2 8 21 RB10/PGEC3 RA2 9 20 - RA3 10 19 + OC3/RA3 10 19 D4/RB4 11 18 RB9 12 17 RB8 13 16 RB7/D7 @@ -47,6 +47,26 @@ Note that RB6 is not available on pin 15 on this device. +Clock Output Routing +-------------------- + +OC3 is used to drive a 74HC273 flip-flop clock pulse (CP) input, with the data +signals then routed through the flip-flop as follows: + + MR# 1 \/ 20 VCC + out D0/Q0 2 19 Q7/D7 out + in D0/D0 3 18 D7/D7 in + in D1/D1 4 17 D6 + out D1/Q1 5 16 Q6 + out D2/Q2 6 15 Q5/D5 out + in D2/D2 7 14 D5/D5 in + in D3/D3 8 13 D4/D4 in + out D3/Q3 9 12 Q4/D4 out + GND 10 11 CP/OC3 in + +MR# is kept at a high level. All out signals are then supplied to the +analogue circuit provided below. + Data Signal Routing ------------------- diff -r ae02a1821af3 -r 045ed8ec2160 pic32.h --- a/pic32.h Sat Nov 04 21:47:48 2017 +0100 +++ b/pic32.h Sat Nov 04 23:13:30 2017 +0100 @@ -62,6 +62,10 @@ #define IEC1 0xBF881070 #define IPC1 0xBF8810A0 #define IPC2 0xBF8810B0 +#define IPC3 0xBF8810C0 +#define IPC4 0xBF8810D0 +#define IPC5 0xBF8810E0 +#define IPC6 0xBF8810F0 #define IPC7 0xBF881100 #define IPC8 0xBF881110 #define IPC10 0xBF881130 diff -r ae02a1821af3 -r 045ed8ec2160 vga.S --- a/vga.S Sat Nov 04 21:47:48 2017 +0100 +++ b/vga.S Sat Nov 04 23:13:30 2017 +0100 @@ -28,7 +28,7 @@ /* Set the oscillator to be the FRC oscillator with PLL, with peripheral clock -divided by 2, and FRCDIV+PLL selected. +divided by 1, and FRCDIV+PLL selected. The watchdog timer (FWDTEN) is also disabled. @@ -37,7 +37,7 @@ */ .section .devcfg1, "a" -.word 0xff7fdfd9 /* DEVCFG1<23> = FWDTEN = 0; DEVCFG1<13:12> = FPBDIV<1:0> = 1; +.word 0xff7fcfd9 /* DEVCFG1<23> = FWDTEN = 0; DEVCFG1<13:12> = FPBDIV<1:0> = 0; DEVCFG1<5> = FSOSCEN = 0; DEVCFG1<2:0> = FNOSC<2:0> = 001 */ /* @@ -112,7 +112,7 @@ nop la $t0, PORTA - li $t1, (1 << 3) /* PORTA<3> = RA3 */ + li $t1, (1 << 2) /* PORTA<2> = RA2 */ sw $t1, CLR($t0) jal init_oc_pins @@ -133,7 +133,7 @@ /* Initialise timer. */ - jal init_timer2 + jal init_timers nop /* Initialise DMA. */ @@ -141,7 +141,7 @@ jal init_dma nop - /* Initialise OC1 and OC2. */ + /* Initialise Output Compare peripherals. */ jal init_oc nop @@ -183,7 +183,7 @@ nop la $t0, PORTA - li $t1, (1 << 3) /* PORTA<3> = RA3 */ + li $t1, (1 << 2) /* PORTA<2> = RA2 */ sw $t1, INV($t0) bnez $a1, loop /* until counter == 0 */ @@ -260,7 +260,7 @@ /* Initialisation routines. */ -init_timer2: +init_timers: /* Initialise Timer2 for sync pulses. */ @@ -299,6 +299,25 @@ li $v1, (1 << 15) sw $v1, SET($v0) /* ON = 1 */ + /* Initialise Timer3 for line DMA cell transfer. */ + + la $v0, T3CON + sw $zero, 0($v0) /* T3CON = 0 */ + nop + + la $v0, TMR3 + sw $zero, 0($v0) /* TMR3 = 0 */ + + la $v0, PR3 + li $v1, 1 + sw $v1, 0($v0) /* PR3 = 1 */ + + /* Start timer. */ + + la $v0, T3CON + li $v1, (1 << 15) + sw $v1, SET($v0) /* ON = 1 */ + jr $ra nop @@ -315,6 +334,11 @@ Using OC2, Timer2 triggers a level shifting event and OC2 is reconfigured to reverse the level at a later point. In this way, the vsync pulse is generated and is synchronised to the display lines. + +Timer3 is used to trigger two events using OC3: one driving a clock pulse high, +propagating pixel data into a flip-flop, one driving the clock pulse low again. + +Using OC3, an interrupt condition also drives line DMA channel transfers. */ init_oc: @@ -373,6 +397,38 @@ /* Enable OC2 later. */ + /* Disable OC3 interrupts. */ + + la $v0, IEC0 + li $v1, (1 << 17) /* IEC0<17> = OC3IE = 0 */ + sw $v1, CLR($v0) + + la $v0, IFS0 + li $v1, (1 << 17) /* IFS0<17> = OC3IF = 0 */ + sw $v1, CLR($v0) + + /* Initialise OC3. */ + + la $v0, OC3CON + li $v1, 0b1101 /* OC3CON<3> = OCTSEL = 1 (Timer3); OC3CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */ + sw $v1, 0($v0) + + /* Pulse start and end. */ + + la $v0, OC3R + li $v1, 0 + sw $v1, 0($v0) + + la $v0, OC3RS + li $v1, 1 + sw $v1, 0($v0) + + /* OC3 is enabled. */ + + la $v0, OC3CON + li $v1, (1 << 15) + sw $v1, SET($v0) + jr $ra nop @@ -403,6 +459,14 @@ li $v1, 0b0101 /* RPA1R<3:0> = 0101 (OC2) */ sw $v1, 0($v0) + /* Map OC3 to RPA3. */ + + la $v0, RPA3R + li $v1, 0b0101 /* RPA3R<3:0> = 0101 (OC3) */ + sw $v1, 0($v0) + + /* Restore CFGCON. */ + la $v0, CFGCON sw $t8, 0($v0) @@ -496,14 +560,14 @@ sw $v1, 0($v0) /* - Initiate line channel transfer when channel 0 is finished: + Initiate line channel transfer when OC3 condition occurs: Initiate reset channel transfer when channel 1 is finished: DCHxECON<15:8> = CHSIRQ<7:0> = channel 0 or 1 interrupt DCHxECON<4> = SIRQEN = 1 */ la $v0, DCH1ECON - li $v1, (60 << 8) | (1 << 4) + li $v1, (17 << 8) | (1 << 4) sw $v1, 0($v0) la $v0, DCH2ECON @@ -511,16 +575,7 @@ sw $v1, 0($v0) /* - The line channel has a cell size of the number bytes in a line: - DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LENGTH - */ - - la $v0, DCH1CSIZ - li $v1, LINE_LENGTH - sw $v1, 0($v0) - - /* - The start and reset channels have a cell size of a single zero byte: + The channels have a cell size of a single byte: DCHxCSIZ<15:0> = CHCSIZ<15:0> = 1 */ @@ -529,11 +584,14 @@ la $v0, DCH0CSIZ sw $v1, 0($v0) + la $v0, DCH1CSIZ + sw $v1, 0($v0) + la $v0, DCH2CSIZ sw $v1, 0($v0) /* - The source has a size identical to the cell size: + The source has a size appropriate for the data: DCHxSSIZ<15:0> = CHSSIZ<15:0> = LINE_LENGTH or 1 */ @@ -612,10 +670,6 @@ address can be updated. */ - la $v0, DCH0INT - li $v1, (1 << 19) /* CHBCIE = 1 */ - sw $v1, 0($v0) - la $v0, DCH1INT li $v1, (1 << 19) /* CHBCIE = 1 */ sw $v1, 0($v0) @@ -623,15 +677,15 @@ /* Enable interrupt for address updating. */ la $v0, IPC10 - li $v1, 0b1111100011111 /* DMA1IP, DMA1IS, DMA0IP, DMA0IS = 0 */ + li $v1, 0b1111100000000 /* DMA1IP, DMA1IS = 0 */ sw $v1, CLR($v0) la $v0, IPC10 - li $v1, 0b1111100011111 /* DMA1IP, DMA0IP = 7, DMA1IS, DMA0IS = 3 */ + li $v1, 0b1111100000000 /* DMA1IP = 7, DMA1IS = 3 */ sw $v1, SET($v0) la $v0, IEC1 - li $v1, (0b11 << 28) /* IEC1<29:28> = DMA1IE, DMA0IE = 1 */ + li $v1, (1 << 29) /* IEC1<29> = DMA1IE = 1 */ sw $v1, SET($v0) /* Enable start channel. */ @@ -785,7 +839,7 @@ la $v0, IFS1 lw $v1, 0($v0) - li $t8, (0b11 << 28) /* DMA1IF, DMA0IF */ + li $t8, (1 << 29) /* DMA1IF */ and $v1, $v1, $t8 beqz $v1, irq_exit nop @@ -796,19 +850,6 @@ /* Test the block transfer completion interrupt flag. */ - la $v0, DCH0INT - lw $v1, 0($v0) - andi $v1, $v1, (1 << 3) /* CHBCIF */ - beqz $v1, irq_dma_next - nop - - /* Clear the block transfer completion interrupt flag. */ - - sw $v1, CLR($v0) - -irq_dma_next: - /* Test the block transfer completion interrupt flag. */ - la $v0, DCH1INT lw $v1, 0($v0) andi $v1, $v1, (1 << 3) /* CHBCIF */ diff -r ae02a1821af3 -r 045ed8ec2160 vga.h --- a/vga.h Sat Nov 04 21:47:48 2017 +0100 +++ b/vga.h Sat Nov 04 23:13:30 2017 +0100 @@ -4,9 +4,9 @@ #define LINE_LENGTH 160 /* pixels */ #define LINE_COUNT 256 /* distinct display lines */ -#define HFREQ_LIMIT 643 /* 24MHz cycles */ -#define HSYNC_START 460 /* 24MHz cycles */ -#define HSYNC_LIMIT 64 /* 24MHz cycles */ +#define HFREQ_LIMIT 1286 /* 48MHz cycles */ +#define HSYNC_START 920 /* 48MHz cycles */ +#define HSYNC_LIMIT 128 /* 48MHz cycles */ #define HSYNC_END (HSYNC_START + HSYNC_LIMIT) #define VISIBLE_START 70 /* horizontal lines, back porch end */