3.1 --- a/vga.S Sat Nov 04 21:47:48 2017 +0100
3.2 +++ b/vga.S Sat Nov 04 23:13:30 2017 +0100
3.3 @@ -28,7 +28,7 @@
3.4
3.5 /*
3.6 Set the oscillator to be the FRC oscillator with PLL, with peripheral clock
3.7 -divided by 2, and FRCDIV+PLL selected.
3.8 +divided by 1, and FRCDIV+PLL selected.
3.9
3.10 The watchdog timer (FWDTEN) is also disabled.
3.11
3.12 @@ -37,7 +37,7 @@
3.13 */
3.14
3.15 .section .devcfg1, "a"
3.16 -.word 0xff7fdfd9 /* DEVCFG1<23> = FWDTEN = 0; DEVCFG1<13:12> = FPBDIV<1:0> = 1;
3.17 +.word 0xff7fcfd9 /* DEVCFG1<23> = FWDTEN = 0; DEVCFG1<13:12> = FPBDIV<1:0> = 0;
3.18 DEVCFG1<5> = FSOSCEN = 0; DEVCFG1<2:0> = FNOSC<2:0> = 001 */
3.19
3.20 /*
3.21 @@ -112,7 +112,7 @@
3.22 nop
3.23
3.24 la $t0, PORTA
3.25 - li $t1, (1 << 3) /* PORTA<3> = RA3 */
3.26 + li $t1, (1 << 2) /* PORTA<2> = RA2 */
3.27 sw $t1, CLR($t0)
3.28
3.29 jal init_oc_pins
3.30 @@ -133,7 +133,7 @@
3.31
3.32 /* Initialise timer. */
3.33
3.34 - jal init_timer2
3.35 + jal init_timers
3.36 nop
3.37
3.38 /* Initialise DMA. */
3.39 @@ -141,7 +141,7 @@
3.40 jal init_dma
3.41 nop
3.42
3.43 - /* Initialise OC1 and OC2. */
3.44 + /* Initialise Output Compare peripherals. */
3.45
3.46 jal init_oc
3.47 nop
3.48 @@ -183,7 +183,7 @@
3.49 nop
3.50
3.51 la $t0, PORTA
3.52 - li $t1, (1 << 3) /* PORTA<3> = RA3 */
3.53 + li $t1, (1 << 2) /* PORTA<2> = RA2 */
3.54 sw $t1, INV($t0)
3.55
3.56 bnez $a1, loop /* until counter == 0 */
3.57 @@ -260,7 +260,7 @@
3.58
3.59 /* Initialisation routines. */
3.60
3.61 -init_timer2:
3.62 +init_timers:
3.63
3.64 /* Initialise Timer2 for sync pulses. */
3.65
3.66 @@ -299,6 +299,25 @@
3.67 li $v1, (1 << 15)
3.68 sw $v1, SET($v0) /* ON = 1 */
3.69
3.70 + /* Initialise Timer3 for line DMA cell transfer. */
3.71 +
3.72 + la $v0, T3CON
3.73 + sw $zero, 0($v0) /* T3CON = 0 */
3.74 + nop
3.75 +
3.76 + la $v0, TMR3
3.77 + sw $zero, 0($v0) /* TMR3 = 0 */
3.78 +
3.79 + la $v0, PR3
3.80 + li $v1, 1
3.81 + sw $v1, 0($v0) /* PR3 = 1 */
3.82 +
3.83 + /* Start timer. */
3.84 +
3.85 + la $v0, T3CON
3.86 + li $v1, (1 << 15)
3.87 + sw $v1, SET($v0) /* ON = 1 */
3.88 +
3.89 jr $ra
3.90 nop
3.91
3.92 @@ -315,6 +334,11 @@
3.93 Using OC2, Timer2 triggers a level shifting event and OC2 is reconfigured to
3.94 reverse the level at a later point. In this way, the vsync pulse is generated
3.95 and is synchronised to the display lines.
3.96 +
3.97 +Timer3 is used to trigger two events using OC3: one driving a clock pulse high,
3.98 +propagating pixel data into a flip-flop, one driving the clock pulse low again.
3.99 +
3.100 +Using OC3, an interrupt condition also drives line DMA channel transfers.
3.101 */
3.102
3.103 init_oc:
3.104 @@ -373,6 +397,38 @@
3.105
3.106 /* Enable OC2 later. */
3.107
3.108 + /* Disable OC3 interrupts. */
3.109 +
3.110 + la $v0, IEC0
3.111 + li $v1, (1 << 17) /* IEC0<17> = OC3IE = 0 */
3.112 + sw $v1, CLR($v0)
3.113 +
3.114 + la $v0, IFS0
3.115 + li $v1, (1 << 17) /* IFS0<17> = OC3IF = 0 */
3.116 + sw $v1, CLR($v0)
3.117 +
3.118 + /* Initialise OC3. */
3.119 +
3.120 + la $v0, OC3CON
3.121 + li $v1, 0b1101 /* OC3CON<3> = OCTSEL = 1 (Timer3); OC3CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */
3.122 + sw $v1, 0($v0)
3.123 +
3.124 + /* Pulse start and end. */
3.125 +
3.126 + la $v0, OC3R
3.127 + li $v1, 0
3.128 + sw $v1, 0($v0)
3.129 +
3.130 + la $v0, OC3RS
3.131 + li $v1, 1
3.132 + sw $v1, 0($v0)
3.133 +
3.134 + /* OC3 is enabled. */
3.135 +
3.136 + la $v0, OC3CON
3.137 + li $v1, (1 << 15)
3.138 + sw $v1, SET($v0)
3.139 +
3.140 jr $ra
3.141 nop
3.142
3.143 @@ -403,6 +459,14 @@
3.144 li $v1, 0b0101 /* RPA1R<3:0> = 0101 (OC2) */
3.145 sw $v1, 0($v0)
3.146
3.147 + /* Map OC3 to RPA3. */
3.148 +
3.149 + la $v0, RPA3R
3.150 + li $v1, 0b0101 /* RPA3R<3:0> = 0101 (OC3) */
3.151 + sw $v1, 0($v0)
3.152 +
3.153 + /* Restore CFGCON. */
3.154 +
3.155 la $v0, CFGCON
3.156 sw $t8, 0($v0)
3.157
3.158 @@ -496,14 +560,14 @@
3.159 sw $v1, 0($v0)
3.160
3.161 /*
3.162 - Initiate line channel transfer when channel 0 is finished:
3.163 + Initiate line channel transfer when OC3 condition occurs:
3.164 Initiate reset channel transfer when channel 1 is finished:
3.165 DCHxECON<15:8> = CHSIRQ<7:0> = channel 0 or 1 interrupt
3.166 DCHxECON<4> = SIRQEN = 1
3.167 */
3.168
3.169 la $v0, DCH1ECON
3.170 - li $v1, (60 << 8) | (1 << 4)
3.171 + li $v1, (17 << 8) | (1 << 4)
3.172 sw $v1, 0($v0)
3.173
3.174 la $v0, DCH2ECON
3.175 @@ -511,16 +575,7 @@
3.176 sw $v1, 0($v0)
3.177
3.178 /*
3.179 - The line channel has a cell size of the number bytes in a line:
3.180 - DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LENGTH
3.181 - */
3.182 -
3.183 - la $v0, DCH1CSIZ
3.184 - li $v1, LINE_LENGTH
3.185 - sw $v1, 0($v0)
3.186 -
3.187 - /*
3.188 - The start and reset channels have a cell size of a single zero byte:
3.189 + The channels have a cell size of a single byte:
3.190 DCHxCSIZ<15:0> = CHCSIZ<15:0> = 1
3.191 */
3.192
3.193 @@ -529,11 +584,14 @@
3.194 la $v0, DCH0CSIZ
3.195 sw $v1, 0($v0)
3.196
3.197 + la $v0, DCH1CSIZ
3.198 + sw $v1, 0($v0)
3.199 +
3.200 la $v0, DCH2CSIZ
3.201 sw $v1, 0($v0)
3.202
3.203 /*
3.204 - The source has a size identical to the cell size:
3.205 + The source has a size appropriate for the data:
3.206 DCHxSSIZ<15:0> = CHSSIZ<15:0> = LINE_LENGTH or 1
3.207 */
3.208
3.209 @@ -612,10 +670,6 @@
3.210 address can be updated.
3.211 */
3.212
3.213 - la $v0, DCH0INT
3.214 - li $v1, (1 << 19) /* CHBCIE = 1 */
3.215 - sw $v1, 0($v0)
3.216 -
3.217 la $v0, DCH1INT
3.218 li $v1, (1 << 19) /* CHBCIE = 1 */
3.219 sw $v1, 0($v0)
3.220 @@ -623,15 +677,15 @@
3.221 /* Enable interrupt for address updating. */
3.222
3.223 la $v0, IPC10
3.224 - li $v1, 0b1111100011111 /* DMA1IP, DMA1IS, DMA0IP, DMA0IS = 0 */
3.225 + li $v1, 0b1111100000000 /* DMA1IP, DMA1IS = 0 */
3.226 sw $v1, CLR($v0)
3.227
3.228 la $v0, IPC10
3.229 - li $v1, 0b1111100011111 /* DMA1IP, DMA0IP = 7, DMA1IS, DMA0IS = 3 */
3.230 + li $v1, 0b1111100000000 /* DMA1IP = 7, DMA1IS = 3 */
3.231 sw $v1, SET($v0)
3.232
3.233 la $v0, IEC1
3.234 - li $v1, (0b11 << 28) /* IEC1<29:28> = DMA1IE, DMA0IE = 1 */
3.235 + li $v1, (1 << 29) /* IEC1<29> = DMA1IE = 1 */
3.236 sw $v1, SET($v0)
3.237
3.238 /* Enable start channel. */
3.239 @@ -785,7 +839,7 @@
3.240
3.241 la $v0, IFS1
3.242 lw $v1, 0($v0)
3.243 - li $t8, (0b11 << 28) /* DMA1IF, DMA0IF */
3.244 + li $t8, (1 << 29) /* DMA1IF */
3.245 and $v1, $v1, $t8
3.246 beqz $v1, irq_exit
3.247 nop
3.248 @@ -796,19 +850,6 @@
3.249
3.250 /* Test the block transfer completion interrupt flag. */
3.251
3.252 - la $v0, DCH0INT
3.253 - lw $v1, 0($v0)
3.254 - andi $v1, $v1, (1 << 3) /* CHBCIF */
3.255 - beqz $v1, irq_dma_next
3.256 - nop
3.257 -
3.258 - /* Clear the block transfer completion interrupt flag. */
3.259 -
3.260 - sw $v1, CLR($v0)
3.261 -
3.262 -irq_dma_next:
3.263 - /* Test the block transfer completion interrupt flag. */
3.264 -
3.265 la $v0, DCH1INT
3.266 lw $v1, 0($v0)
3.267 andi $v1, $v1, (1 << 3) /* CHBCIF */