2.1 --- a/vga.S Wed May 10 00:14:50 2017 +0200
2.2 +++ b/vga.S Wed May 10 17:15:25 2017 +0200
2.3 @@ -88,11 +88,14 @@
2.4 lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)
2.5 ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)
2.6
2.7 - /* Set pins for output and set outputs low. */
2.8 + /* Set pins for output. */
2.9
2.10 jal init_pins
2.11 nop
2.12
2.13 + jal init_oc_pins
2.14 + nop
2.15 +
2.16 /* Initialise the status register. */
2.17
2.18 jal init_interrupts
2.19 @@ -113,6 +116,11 @@
2.20 jal init_dma
2.21 nop
2.22
2.23 + /* Initialise OC2. */
2.24 +
2.25 + jal init_oc2
2.26 + nop
2.27 +
2.28 /* Initialise framebuffer. */
2.29
2.30 jal init_framebuffer
2.31 @@ -129,7 +137,6 @@
2.32 /* Main program. */
2.33
2.34 li $a1, 20000000 /* counter = 20000000 */
2.35 - li $a2, 3187 /* test timer scaling */
2.36
2.37 /* Initialise the display state. */
2.38
2.39 @@ -145,7 +152,7 @@
2.40 li $a1, 20000000 /* counter = 20000000 */
2.41
2.42 la $t0, PORTB
2.43 - la $t1, (1 << 10) /* PORTB<10> = RB10 */
2.44 + li $t1, (1 << 10) /* PORTB<10> = RB10 */
2.45 sw $t1, INV($t0)
2.46
2.47 _next:
2.48 @@ -193,13 +200,6 @@
2.49 beqz $v1, irq_next
2.50 nop
2.51
2.52 - /* Timer scaling for testing purposes. */
2.53 -
2.54 - addiu $a2, $a2, -1
2.55 - bnez $a2, irq_clear_timer
2.56 - nop
2.57 - li $a2, 3187
2.58 -
2.59 /* Increment the line counter. */
2.60
2.61 addiu $s0, $s0, 1
2.62 @@ -333,6 +333,12 @@
2.63
2.64 la $s1, visible_start
2.65
2.66 + /* Enable OC2. */
2.67 +
2.68 + la $v0, OC2CON
2.69 + li $v1, (1 << 15)
2.70 + sw $v1, SET($v0)
2.71 +
2.72 _vsync_active_ret:
2.73 jr $ra
2.74 nop
2.75 @@ -353,12 +359,6 @@
2.76 la $s1, visible_active
2.77
2.78 visible_active:
2.79 - /* Initiate hsync transfer and subsequent line transfer. */
2.80 -
2.81 - la $v0, DCH0ECON
2.82 - li $v1, (1 << 7)
2.83 - sw $v1, SET($v0)
2.84 -
2.85 /* Test for back porch. */
2.86
2.87 subu $v0, $s0, VBP_START
2.88 @@ -369,6 +369,12 @@
2.89
2.90 la $s1, vbp_active
2.91
2.92 + /* Disable OC2. */
2.93 +
2.94 + la $v0, OC2CON
2.95 + li $v1, (1 << 15)
2.96 + sw $v1, CLR($v0)
2.97 +
2.98 _visible_active_ret:
2.99 jr $ra
2.100 nop
2.101 @@ -407,6 +413,7 @@
2.102
2.103 la $v0, TMR2
2.104 sw $zero, 0($v0) /* TMR2 = 0 */
2.105 +
2.106 la $v0, PR2
2.107 li $v1, HFREQ_LIMIT
2.108 sw $v1, 0($v0) /* PR2 = HFREQ_LIMIT */
2.109 @@ -415,22 +422,103 @@
2.110
2.111 la $v0, IFS0
2.112 li $v1, (1 << 9)
2.113 - sw $v1, CLR($v0) /* IFS0CLR: T2IF = 0 */
2.114 + sw $v1, CLR($v0) /* T2IF = 0 */
2.115 +
2.116 la $v0, IPC2
2.117 - li $v1, (7 << 2)
2.118 - sw $v1, SET($v0) /* IPC1SET: T2IP = 7 */
2.119 + li $v1, 0b11111
2.120 + sw $v1, CLR($v0) /* T2IP, T2IS = 0 */
2.121 +
2.122 la $v0, IPC2
2.123 - li $v1, 3
2.124 - sw $v1, SET($v0) /* IPC1SET: T2IS = 3 */
2.125 + li $v1, 0b11111
2.126 + sw $v1, SET($v0) /* T2IP = 7; T2IS = 3 */
2.127 +
2.128 la $v0, IEC0
2.129 li $v1, (1 << 9)
2.130 - sw $v1, SET($v0) /* IEC0SET: T2IE = 1 */
2.131 + sw $v1, SET($v0) /* T2IE = 1 */
2.132
2.133 /* Start timer. */
2.134
2.135 la $v0, T2CON
2.136 - li $v1, (1 << 15) /* ON = 1 */
2.137 - sw $v1, SET($v0) /* T1CONSET: ON = 1 */
2.138 + li $v1, (1 << 15)
2.139 + sw $v1, SET($v0) /* ON = 1 */
2.140 +
2.141 + jr $ra
2.142 + nop
2.143 +
2.144 +
2.145 +
2.146 +/*
2.147 +Output compare initialisation.
2.148 +
2.149 +Timer2 will be used to trigger two events: one initiating the hsync pulse, and
2.150 +one terminating the pulse. Upon the termination of the pulse, an interrupt
2.151 +condition will cause the line data to be transferred using DMA.
2.152 +
2.153 +*/
2.154 +
2.155 +init_oc2:
2.156 + /* Disable OC interrupts. */
2.157 +
2.158 + la $v0, IEC0
2.159 + li $v1, (1 << 12) /* IEC0<12> = OC2IE = 0 */
2.160 + sw $v1, CLR($v0)
2.161 +
2.162 + la $v0, IFS0
2.163 + li $v1, (1 << 12) /* IFS0<12> = OC2IF = 0 */
2.164 + sw $v1, CLR($v0)
2.165 +
2.166 + /* Initialise OC2. */
2.167 +
2.168 + la $v0, OC2CON
2.169 + li $v1, 0b101 /* OC2CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */
2.170 + sw $v1, 0($v0)
2.171 +
2.172 + /* Set hsync start and end. */
2.173 +
2.174 + la $v0, OC2R
2.175 + li $v1, 16
2.176 + sw $v1, 0($v0)
2.177 +
2.178 + la $v0, OC2RS
2.179 + li $v1, 32
2.180 + sw $v1, 0($v0)
2.181 +
2.182 + /* OC2 is enabled elsewhere when it needs to operate. */
2.183 +
2.184 + jr $ra
2.185 + nop
2.186 +
2.187 +
2.188 +
2.189 +init_oc_pins:
2.190 + /* Unlock the configuration register bits. */
2.191 +
2.192 + la $v0, SYSKEY
2.193 + sw $zero, 0($v0)
2.194 + li $v1, 0xAA996655
2.195 + sw $v1, 0($v0)
2.196 + li $v1, 0x556699AA
2.197 + sw $v1, 0($v0)
2.198 +
2.199 + la $v0, CFGCON
2.200 + lw $t8, 0($v0)
2.201 + li $v1, (1 << 13) /* IOLOCK = 0 */
2.202 + sw $v1, CLR($v0)
2.203 +
2.204 + /* Map OC2 to RPB5. */
2.205 +
2.206 + la $v0, RPB5R
2.207 + li $v1, 0b0101 /* RPB5R<3:0> = 0101 (OC2) */
2.208 + sw $v1, 0($v0)
2.209 +
2.210 + la $v0, CFGCON
2.211 + sw $t8, 0($v0)
2.212 +
2.213 + /* Lock the oscillator control register again. */
2.214 +
2.215 + la $v0, SYSKEY
2.216 + li $v1, 0x33333333
2.217 + sw $v1, 0($v0)
2.218
2.219 jr $ra
2.220 nop
2.221 @@ -492,16 +580,11 @@
2.222
2.223
2.224
2.225 -/* Direct Memory Access initialisation. */
2.226 +/*
2.227 +Direct Memory Access initialisation.
2.228
2.229 -/*
2.230 -Write 16 pixels to the PMP for a hsync pulse. This channel is invoked
2.231 -explicitly in the interrupt handler for Timer1 since it will not happen on every
2.232 -occurrence of the interrupt, but only on those occurrences within the active
2.233 -region of the display output.
2.234 -
2.235 -Write 160 pixels to the PMP for the line data. This is initiated by the
2.236 -completion of the hsync transfer.
2.237 +Write 160 pixels to the PMP for the line data. This is initiated by an output
2.238 +compare interrupt.
2.239 */
2.240
2.241 init_dma:
2.242 @@ -524,9 +607,8 @@
2.243 sw $v1, SET($v0)
2.244
2.245 /*
2.246 - Initialise a hsync channel and a line channel.
2.247 - The hsync channel will be channel 0 (x = 0).
2.248 - The line channel will be channel 1 (x = 1).
2.249 + Initialise a line channel.
2.250 + The line channel will be channel 0 (x = 0).
2.251
2.252 Once the hsync channel has completed a transfer, the line channel
2.253 transfer is initiated.
2.254 @@ -542,44 +624,22 @@
2.255 li $v1, 0b10011
2.256 sw $v1, 0($v0)
2.257
2.258 - la $v0, DCH1CON
2.259 - li $v1, 0b10011
2.260 - sw $v1, 0($v0)
2.261 -
2.262 - la $v0, DCH2CON
2.263 - li $v1, 0b10011
2.264 - sw $v1, 0($v0)
2.265 -
2.266 - /* Initiate channel transfers when the preceding channel interrupt occurs. */
2.267 + /*
2.268 + Initiate channel transfers when the initiating interrupt condition
2.269 + occurs:
2.270 + DCHxECON<15:8> = CHSIRQ<7:0> = output compare 2 interrupt
2.271 + */
2.272
2.273 la $v0, DCH0ECON
2.274 - sw $zero, 0($v0)
2.275 -
2.276 - la $v0, DCH1ECON
2.277 - li $v1, (60 << 8) | (1 << 4)
2.278 - sw $v1, 0($v0)
2.279 -
2.280 - la $v0, DCH2ECON
2.281 - li $v1, (61 << 8) | (1 << 4)
2.282 + li $v1, (12 << 8) | (1 << 4)
2.283 sw $v1, 0($v0)
2.284
2.285 /*
2.286 - The hsync channels have a cell size of 16 bytes:
2.287 - DCHxCSIZ<15:0> = CHCSIZ<15:0> = HSYNC_LIMIT
2.288 -
2.289 The line channel has a cell size of 160 bytes:
2.290 DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LIMIT
2.291 */
2.292
2.293 la $v0, DCH0CSIZ
2.294 - li $v1, HSYNC_LIMIT
2.295 - sw $v1, 0($v0)
2.296 -
2.297 - la $v0, DCH1CSIZ
2.298 - li $v1, HSYNC_LIMIT
2.299 - sw $v1, 0($v0)
2.300 -
2.301 - la $v0, DCH2CSIZ
2.302 li $v1, LINE_LIMIT
2.303 sw $v1, 0($v0)
2.304
2.305 @@ -589,34 +649,15 @@
2.306 */
2.307
2.308 la $v0, DCH0SSIZ
2.309 - li $v1, HSYNC_LIMIT
2.310 - sw $v1, 0($v0)
2.311 -
2.312 - la $v0, DCH1SSIZ
2.313 - li $v1, HSYNC_LIMIT
2.314 - sw $v1, 0($v0)
2.315 -
2.316 - la $v0, DCH2SSIZ
2.317 li $v1, LINE_LIMIT
2.318 sw $v1, 0($v0)
2.319
2.320 /*
2.321 - The source address is the physical address of either the hsync pulse
2.322 - data or the line data:
2.323 - DCHxSSA = pulse data physical address
2.324 + The source address is the physical address of the line data:
2.325 DCHxSSA = line data physical address
2.326 */
2.327
2.328 la $v0, DCH0SSA
2.329 - la $v1, set_ra2
2.330 - li $t8, KSEG0_BASE
2.331 - subu $v1, $v1, $t8
2.332 - sw $v1, 0($v0)
2.333 -
2.334 - la $v0, DCH1SSA
2.335 - sw $v1, 0($v0)
2.336 -
2.337 - la $v0, DCH2SSA
2.338 sw $zero, 0($v0)
2.339
2.340 /*
2.341 @@ -628,56 +669,18 @@
2.342 li $v1, 1
2.343 sw $v1, 0($v0)
2.344
2.345 - la $v0, DCH1DSIZ
2.346 - sw $v1, 0($v0)
2.347 -
2.348 - la $v0, DCH2DSIZ
2.349 - sw $v1, 0($v0)
2.350 -
2.351 - /*
2.352 - For the hsync channels, the destination address is the physical address
2.353 - for an I/O register that sets the output signal for hsync:
2.354 - DCHxDSA = physical(PORTA)
2.355 - */
2.356 -
2.357 - la $v0, DCH0DSA
2.358 - li $v1, PORTA + INV
2.359 - li $t8, KSEG1_BASE
2.360 - subu $v1, $v1, $t8
2.361 - sw $v1, 0($v0)
2.362 -
2.363 - la $v0, DCH1DSA
2.364 - li $v1, PORTA + CLR
2.365 - li $t8, KSEG1_BASE
2.366 - subu $v1, $v1, $t8
2.367 - sw $v1, 0($v0)
2.368 -
2.369 /*
2.370 For the line channel, the destination address is the physical address of
2.371 PMDIN: DCHxDSA = physical(PMDIN)
2.372 */
2.373
2.374 - la $v0, DCH2DSA
2.375 + la $v0, DCH0DSA
2.376 li $v1, PMDIN
2.377 li $t8, KSEG1_BASE
2.378 subu $v1, $v1, $t8
2.379 sw $v1, 0($v0)
2.380
2.381 - /*
2.382 - The block transfer complete interrupt needs to be enabled, so that upon
2.383 - completion of the transfer, the next transfer can be initiated:
2.384 - DCHxINT<19> = CHBCIE = 1
2.385 - */
2.386 -
2.387 la $v0, DCH0INT
2.388 - li $v1, (1 << 19)
2.389 - sw $v1, 0($v0)
2.390 -
2.391 - la $v0, DCH1INT
2.392 - li $v1, (1 << 19)
2.393 - sw $v1, 0($v0)
2.394 -
2.395 - la $v0, DCH2INT
2.396 sw $zero, 0($v0)
2.397
2.398 /* Enable channels. */
2.399 @@ -686,12 +689,6 @@
2.400 li $v1, 0b10000000
2.401 sw $v1, SET($v0)
2.402
2.403 - la $v0, DCH1CON
2.404 - sw $v1, SET($v0)
2.405 -
2.406 - la $v0, DCH2CON
2.407 - sw $v1, SET($v0)
2.408 -
2.409 jr $ra
2.410 nop
2.411
2.412 @@ -713,25 +710,3 @@
2.413
2.414 jr $ra
2.415 nop
2.416 -
2.417 -
2.418 -
2.419 -/* 16 bytes of pulse data used to set PORTA<2> = RA2. */
2.420 -
2.421 -set_ra2:
2.422 -.byte (1 << 2)
2.423 -.byte (1 << 2)
2.424 -.byte (1 << 2)
2.425 -.byte (1 << 2)
2.426 -.byte (1 << 2)
2.427 -.byte (1 << 2)
2.428 -.byte (1 << 2)
2.429 -.byte (1 << 2)
2.430 -.byte (1 << 2)
2.431 -.byte (1 << 2)
2.432 -.byte (1 << 2)
2.433 -.byte (1 << 2)
2.434 -.byte (1 << 2)
2.435 -.byte (1 << 2)
2.436 -.byte (1 << 2)
2.437 -.byte (1 << 2)