1.1 --- a/vga.S Sat Nov 04 21:47:48 2017 +0100
1.2 +++ b/vga.S Sat Nov 04 23:13:30 2017 +0100
1.3 @@ -28,7 +28,7 @@
1.4
1.5 /*
1.6 Set the oscillator to be the FRC oscillator with PLL, with peripheral clock
1.7 -divided by 2, and FRCDIV+PLL selected.
1.8 +divided by 1, and FRCDIV+PLL selected.
1.9
1.10 The watchdog timer (FWDTEN) is also disabled.
1.11
1.12 @@ -37,7 +37,7 @@
1.13 */
1.14
1.15 .section .devcfg1, "a"
1.16 -.word 0xff7fdfd9 /* DEVCFG1<23> = FWDTEN = 0; DEVCFG1<13:12> = FPBDIV<1:0> = 1;
1.17 +.word 0xff7fcfd9 /* DEVCFG1<23> = FWDTEN = 0; DEVCFG1<13:12> = FPBDIV<1:0> = 0;
1.18 DEVCFG1<5> = FSOSCEN = 0; DEVCFG1<2:0> = FNOSC<2:0> = 001 */
1.19
1.20 /*
1.21 @@ -112,7 +112,7 @@
1.22 nop
1.23
1.24 la $t0, PORTA
1.25 - li $t1, (1 << 3) /* PORTA<3> = RA3 */
1.26 + li $t1, (1 << 2) /* PORTA<2> = RA2 */
1.27 sw $t1, CLR($t0)
1.28
1.29 jal init_oc_pins
1.30 @@ -133,7 +133,7 @@
1.31
1.32 /* Initialise timer. */
1.33
1.34 - jal init_timer2
1.35 + jal init_timers
1.36 nop
1.37
1.38 /* Initialise DMA. */
1.39 @@ -141,7 +141,7 @@
1.40 jal init_dma
1.41 nop
1.42
1.43 - /* Initialise OC1 and OC2. */
1.44 + /* Initialise Output Compare peripherals. */
1.45
1.46 jal init_oc
1.47 nop
1.48 @@ -183,7 +183,7 @@
1.49 nop
1.50
1.51 la $t0, PORTA
1.52 - li $t1, (1 << 3) /* PORTA<3> = RA3 */
1.53 + li $t1, (1 << 2) /* PORTA<2> = RA2 */
1.54 sw $t1, INV($t0)
1.55
1.56 bnez $a1, loop /* until counter == 0 */
1.57 @@ -260,7 +260,7 @@
1.58
1.59 /* Initialisation routines. */
1.60
1.61 -init_timer2:
1.62 +init_timers:
1.63
1.64 /* Initialise Timer2 for sync pulses. */
1.65
1.66 @@ -299,6 +299,25 @@
1.67 li $v1, (1 << 15)
1.68 sw $v1, SET($v0) /* ON = 1 */
1.69
1.70 + /* Initialise Timer3 for line DMA cell transfer. */
1.71 +
1.72 + la $v0, T3CON
1.73 + sw $zero, 0($v0) /* T3CON = 0 */
1.74 + nop
1.75 +
1.76 + la $v0, TMR3
1.77 + sw $zero, 0($v0) /* TMR3 = 0 */
1.78 +
1.79 + la $v0, PR3
1.80 + li $v1, 1
1.81 + sw $v1, 0($v0) /* PR3 = 1 */
1.82 +
1.83 + /* Start timer. */
1.84 +
1.85 + la $v0, T3CON
1.86 + li $v1, (1 << 15)
1.87 + sw $v1, SET($v0) /* ON = 1 */
1.88 +
1.89 jr $ra
1.90 nop
1.91
1.92 @@ -315,6 +334,11 @@
1.93 Using OC2, Timer2 triggers a level shifting event and OC2 is reconfigured to
1.94 reverse the level at a later point. In this way, the vsync pulse is generated
1.95 and is synchronised to the display lines.
1.96 +
1.97 +Timer3 is used to trigger two events using OC3: one driving a clock pulse high,
1.98 +propagating pixel data into a flip-flop, one driving the clock pulse low again.
1.99 +
1.100 +Using OC3, an interrupt condition also drives line DMA channel transfers.
1.101 */
1.102
1.103 init_oc:
1.104 @@ -373,6 +397,38 @@
1.105
1.106 /* Enable OC2 later. */
1.107
1.108 + /* Disable OC3 interrupts. */
1.109 +
1.110 + la $v0, IEC0
1.111 + li $v1, (1 << 17) /* IEC0<17> = OC3IE = 0 */
1.112 + sw $v1, CLR($v0)
1.113 +
1.114 + la $v0, IFS0
1.115 + li $v1, (1 << 17) /* IFS0<17> = OC3IF = 0 */
1.116 + sw $v1, CLR($v0)
1.117 +
1.118 + /* Initialise OC3. */
1.119 +
1.120 + la $v0, OC3CON
1.121 + li $v1, 0b1101 /* OC3CON<3> = OCTSEL = 1 (Timer3); OC3CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */
1.122 + sw $v1, 0($v0)
1.123 +
1.124 + /* Pulse start and end. */
1.125 +
1.126 + la $v0, OC3R
1.127 + li $v1, 0
1.128 + sw $v1, 0($v0)
1.129 +
1.130 + la $v0, OC3RS
1.131 + li $v1, 1
1.132 + sw $v1, 0($v0)
1.133 +
1.134 + /* OC3 is enabled. */
1.135 +
1.136 + la $v0, OC3CON
1.137 + li $v1, (1 << 15)
1.138 + sw $v1, SET($v0)
1.139 +
1.140 jr $ra
1.141 nop
1.142
1.143 @@ -403,6 +459,14 @@
1.144 li $v1, 0b0101 /* RPA1R<3:0> = 0101 (OC2) */
1.145 sw $v1, 0($v0)
1.146
1.147 + /* Map OC3 to RPA3. */
1.148 +
1.149 + la $v0, RPA3R
1.150 + li $v1, 0b0101 /* RPA3R<3:0> = 0101 (OC3) */
1.151 + sw $v1, 0($v0)
1.152 +
1.153 + /* Restore CFGCON. */
1.154 +
1.155 la $v0, CFGCON
1.156 sw $t8, 0($v0)
1.157
1.158 @@ -496,14 +560,14 @@
1.159 sw $v1, 0($v0)
1.160
1.161 /*
1.162 - Initiate line channel transfer when channel 0 is finished:
1.163 + Initiate line channel transfer when OC3 condition occurs:
1.164 Initiate reset channel transfer when channel 1 is finished:
1.165 DCHxECON<15:8> = CHSIRQ<7:0> = channel 0 or 1 interrupt
1.166 DCHxECON<4> = SIRQEN = 1
1.167 */
1.168
1.169 la $v0, DCH1ECON
1.170 - li $v1, (60 << 8) | (1 << 4)
1.171 + li $v1, (17 << 8) | (1 << 4)
1.172 sw $v1, 0($v0)
1.173
1.174 la $v0, DCH2ECON
1.175 @@ -511,16 +575,7 @@
1.176 sw $v1, 0($v0)
1.177
1.178 /*
1.179 - The line channel has a cell size of the number bytes in a line:
1.180 - DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LENGTH
1.181 - */
1.182 -
1.183 - la $v0, DCH1CSIZ
1.184 - li $v1, LINE_LENGTH
1.185 - sw $v1, 0($v0)
1.186 -
1.187 - /*
1.188 - The start and reset channels have a cell size of a single zero byte:
1.189 + The channels have a cell size of a single byte:
1.190 DCHxCSIZ<15:0> = CHCSIZ<15:0> = 1
1.191 */
1.192
1.193 @@ -529,11 +584,14 @@
1.194 la $v0, DCH0CSIZ
1.195 sw $v1, 0($v0)
1.196
1.197 + la $v0, DCH1CSIZ
1.198 + sw $v1, 0($v0)
1.199 +
1.200 la $v0, DCH2CSIZ
1.201 sw $v1, 0($v0)
1.202
1.203 /*
1.204 - The source has a size identical to the cell size:
1.205 + The source has a size appropriate for the data:
1.206 DCHxSSIZ<15:0> = CHSSIZ<15:0> = LINE_LENGTH or 1
1.207 */
1.208
1.209 @@ -612,10 +670,6 @@
1.210 address can be updated.
1.211 */
1.212
1.213 - la $v0, DCH0INT
1.214 - li $v1, (1 << 19) /* CHBCIE = 1 */
1.215 - sw $v1, 0($v0)
1.216 -
1.217 la $v0, DCH1INT
1.218 li $v1, (1 << 19) /* CHBCIE = 1 */
1.219 sw $v1, 0($v0)
1.220 @@ -623,15 +677,15 @@
1.221 /* Enable interrupt for address updating. */
1.222
1.223 la $v0, IPC10
1.224 - li $v1, 0b1111100011111 /* DMA1IP, DMA1IS, DMA0IP, DMA0IS = 0 */
1.225 + li $v1, 0b1111100000000 /* DMA1IP, DMA1IS = 0 */
1.226 sw $v1, CLR($v0)
1.227
1.228 la $v0, IPC10
1.229 - li $v1, 0b1111100011111 /* DMA1IP, DMA0IP = 7, DMA1IS, DMA0IS = 3 */
1.230 + li $v1, 0b1111100000000 /* DMA1IP = 7, DMA1IS = 3 */
1.231 sw $v1, SET($v0)
1.232
1.233 la $v0, IEC1
1.234 - li $v1, (0b11 << 28) /* IEC1<29:28> = DMA1IE, DMA0IE = 1 */
1.235 + li $v1, (1 << 29) /* IEC1<29> = DMA1IE = 1 */
1.236 sw $v1, SET($v0)
1.237
1.238 /* Enable start channel. */
1.239 @@ -785,7 +839,7 @@
1.240
1.241 la $v0, IFS1
1.242 lw $v1, 0($v0)
1.243 - li $t8, (0b11 << 28) /* DMA1IF, DMA0IF */
1.244 + li $t8, (1 << 29) /* DMA1IF */
1.245 and $v1, $v1, $t8
1.246 beqz $v1, irq_exit
1.247 nop
1.248 @@ -796,19 +850,6 @@
1.249
1.250 /* Test the block transfer completion interrupt flag. */
1.251
1.252 - la $v0, DCH0INT
1.253 - lw $v1, 0($v0)
1.254 - andi $v1, $v1, (1 << 3) /* CHBCIF */
1.255 - beqz $v1, irq_dma_next
1.256 - nop
1.257 -
1.258 - /* Clear the block transfer completion interrupt flag. */
1.259 -
1.260 - sw $v1, CLR($v0)
1.261 -
1.262 -irq_dma_next:
1.263 - /* Test the block transfer completion interrupt flag. */
1.264 -
1.265 la $v0, DCH1INT
1.266 lw $v1, 0($v0)
1.267 andi $v1, $v1, (1 << 3) /* CHBCIF */