1.1 --- a/vga.S Wed May 10 00:14:50 2017 +0200
1.2 +++ b/vga.S Wed May 10 17:15:25 2017 +0200
1.3 @@ -88,11 +88,14 @@
1.4 lui $gp, %hi(_GLOBAL_OFFSET_TABLE_)
1.5 ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_)
1.6
1.7 - /* Set pins for output and set outputs low. */
1.8 + /* Set pins for output. */
1.9
1.10 jal init_pins
1.11 nop
1.12
1.13 + jal init_oc_pins
1.14 + nop
1.15 +
1.16 /* Initialise the status register. */
1.17
1.18 jal init_interrupts
1.19 @@ -113,6 +116,11 @@
1.20 jal init_dma
1.21 nop
1.22
1.23 + /* Initialise OC2. */
1.24 +
1.25 + jal init_oc2
1.26 + nop
1.27 +
1.28 /* Initialise framebuffer. */
1.29
1.30 jal init_framebuffer
1.31 @@ -129,7 +137,6 @@
1.32 /* Main program. */
1.33
1.34 li $a1, 20000000 /* counter = 20000000 */
1.35 - li $a2, 3187 /* test timer scaling */
1.36
1.37 /* Initialise the display state. */
1.38
1.39 @@ -145,7 +152,7 @@
1.40 li $a1, 20000000 /* counter = 20000000 */
1.41
1.42 la $t0, PORTB
1.43 - la $t1, (1 << 10) /* PORTB<10> = RB10 */
1.44 + li $t1, (1 << 10) /* PORTB<10> = RB10 */
1.45 sw $t1, INV($t0)
1.46
1.47 _next:
1.48 @@ -193,13 +200,6 @@
1.49 beqz $v1, irq_next
1.50 nop
1.51
1.52 - /* Timer scaling for testing purposes. */
1.53 -
1.54 - addiu $a2, $a2, -1
1.55 - bnez $a2, irq_clear_timer
1.56 - nop
1.57 - li $a2, 3187
1.58 -
1.59 /* Increment the line counter. */
1.60
1.61 addiu $s0, $s0, 1
1.62 @@ -333,6 +333,12 @@
1.63
1.64 la $s1, visible_start
1.65
1.66 + /* Enable OC2. */
1.67 +
1.68 + la $v0, OC2CON
1.69 + li $v1, (1 << 15)
1.70 + sw $v1, SET($v0)
1.71 +
1.72 _vsync_active_ret:
1.73 jr $ra
1.74 nop
1.75 @@ -353,12 +359,6 @@
1.76 la $s1, visible_active
1.77
1.78 visible_active:
1.79 - /* Initiate hsync transfer and subsequent line transfer. */
1.80 -
1.81 - la $v0, DCH0ECON
1.82 - li $v1, (1 << 7)
1.83 - sw $v1, SET($v0)
1.84 -
1.85 /* Test for back porch. */
1.86
1.87 subu $v0, $s0, VBP_START
1.88 @@ -369,6 +369,12 @@
1.89
1.90 la $s1, vbp_active
1.91
1.92 + /* Disable OC2. */
1.93 +
1.94 + la $v0, OC2CON
1.95 + li $v1, (1 << 15)
1.96 + sw $v1, CLR($v0)
1.97 +
1.98 _visible_active_ret:
1.99 jr $ra
1.100 nop
1.101 @@ -407,6 +413,7 @@
1.102
1.103 la $v0, TMR2
1.104 sw $zero, 0($v0) /* TMR2 = 0 */
1.105 +
1.106 la $v0, PR2
1.107 li $v1, HFREQ_LIMIT
1.108 sw $v1, 0($v0) /* PR2 = HFREQ_LIMIT */
1.109 @@ -415,22 +422,103 @@
1.110
1.111 la $v0, IFS0
1.112 li $v1, (1 << 9)
1.113 - sw $v1, CLR($v0) /* IFS0CLR: T2IF = 0 */
1.114 + sw $v1, CLR($v0) /* T2IF = 0 */
1.115 +
1.116 la $v0, IPC2
1.117 - li $v1, (7 << 2)
1.118 - sw $v1, SET($v0) /* IPC1SET: T2IP = 7 */
1.119 + li $v1, 0b11111
1.120 + sw $v1, CLR($v0) /* T2IP, T2IS = 0 */
1.121 +
1.122 la $v0, IPC2
1.123 - li $v1, 3
1.124 - sw $v1, SET($v0) /* IPC1SET: T2IS = 3 */
1.125 + li $v1, 0b11111
1.126 + sw $v1, SET($v0) /* T2IP = 7; T2IS = 3 */
1.127 +
1.128 la $v0, IEC0
1.129 li $v1, (1 << 9)
1.130 - sw $v1, SET($v0) /* IEC0SET: T2IE = 1 */
1.131 + sw $v1, SET($v0) /* T2IE = 1 */
1.132
1.133 /* Start timer. */
1.134
1.135 la $v0, T2CON
1.136 - li $v1, (1 << 15) /* ON = 1 */
1.137 - sw $v1, SET($v0) /* T1CONSET: ON = 1 */
1.138 + li $v1, (1 << 15)
1.139 + sw $v1, SET($v0) /* ON = 1 */
1.140 +
1.141 + jr $ra
1.142 + nop
1.143 +
1.144 +
1.145 +
1.146 +/*
1.147 +Output compare initialisation.
1.148 +
1.149 +Timer2 will be used to trigger two events: one initiating the hsync pulse, and
1.150 +one terminating the pulse. Upon the termination of the pulse, an interrupt
1.151 +condition will cause the line data to be transferred using DMA.
1.152 +
1.153 +*/
1.154 +
1.155 +init_oc2:
1.156 + /* Disable OC interrupts. */
1.157 +
1.158 + la $v0, IEC0
1.159 + li $v1, (1 << 12) /* IEC0<12> = OC2IE = 0 */
1.160 + sw $v1, CLR($v0)
1.161 +
1.162 + la $v0, IFS0
1.163 + li $v1, (1 << 12) /* IFS0<12> = OC2IF = 0 */
1.164 + sw $v1, CLR($v0)
1.165 +
1.166 + /* Initialise OC2. */
1.167 +
1.168 + la $v0, OC2CON
1.169 + li $v1, 0b101 /* OC2CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */
1.170 + sw $v1, 0($v0)
1.171 +
1.172 + /* Set hsync start and end. */
1.173 +
1.174 + la $v0, OC2R
1.175 + li $v1, 16
1.176 + sw $v1, 0($v0)
1.177 +
1.178 + la $v0, OC2RS
1.179 + li $v1, 32
1.180 + sw $v1, 0($v0)
1.181 +
1.182 + /* OC2 is enabled elsewhere when it needs to operate. */
1.183 +
1.184 + jr $ra
1.185 + nop
1.186 +
1.187 +
1.188 +
1.189 +init_oc_pins:
1.190 + /* Unlock the configuration register bits. */
1.191 +
1.192 + la $v0, SYSKEY
1.193 + sw $zero, 0($v0)
1.194 + li $v1, 0xAA996655
1.195 + sw $v1, 0($v0)
1.196 + li $v1, 0x556699AA
1.197 + sw $v1, 0($v0)
1.198 +
1.199 + la $v0, CFGCON
1.200 + lw $t8, 0($v0)
1.201 + li $v1, (1 << 13) /* IOLOCK = 0 */
1.202 + sw $v1, CLR($v0)
1.203 +
1.204 + /* Map OC2 to RPB5. */
1.205 +
1.206 + la $v0, RPB5R
1.207 + li $v1, 0b0101 /* RPB5R<3:0> = 0101 (OC2) */
1.208 + sw $v1, 0($v0)
1.209 +
1.210 + la $v0, CFGCON
1.211 + sw $t8, 0($v0)
1.212 +
1.213 + /* Lock the oscillator control register again. */
1.214 +
1.215 + la $v0, SYSKEY
1.216 + li $v1, 0x33333333
1.217 + sw $v1, 0($v0)
1.218
1.219 jr $ra
1.220 nop
1.221 @@ -492,16 +580,11 @@
1.222
1.223
1.224
1.225 -/* Direct Memory Access initialisation. */
1.226 +/*
1.227 +Direct Memory Access initialisation.
1.228
1.229 -/*
1.230 -Write 16 pixels to the PMP for a hsync pulse. This channel is invoked
1.231 -explicitly in the interrupt handler for Timer1 since it will not happen on every
1.232 -occurrence of the interrupt, but only on those occurrences within the active
1.233 -region of the display output.
1.234 -
1.235 -Write 160 pixels to the PMP for the line data. This is initiated by the
1.236 -completion of the hsync transfer.
1.237 +Write 160 pixels to the PMP for the line data. This is initiated by an output
1.238 +compare interrupt.
1.239 */
1.240
1.241 init_dma:
1.242 @@ -524,9 +607,8 @@
1.243 sw $v1, SET($v0)
1.244
1.245 /*
1.246 - Initialise a hsync channel and a line channel.
1.247 - The hsync channel will be channel 0 (x = 0).
1.248 - The line channel will be channel 1 (x = 1).
1.249 + Initialise a line channel.
1.250 + The line channel will be channel 0 (x = 0).
1.251
1.252 Once the hsync channel has completed a transfer, the line channel
1.253 transfer is initiated.
1.254 @@ -542,44 +624,22 @@
1.255 li $v1, 0b10011
1.256 sw $v1, 0($v0)
1.257
1.258 - la $v0, DCH1CON
1.259 - li $v1, 0b10011
1.260 - sw $v1, 0($v0)
1.261 -
1.262 - la $v0, DCH2CON
1.263 - li $v1, 0b10011
1.264 - sw $v1, 0($v0)
1.265 -
1.266 - /* Initiate channel transfers when the preceding channel interrupt occurs. */
1.267 + /*
1.268 + Initiate channel transfers when the initiating interrupt condition
1.269 + occurs:
1.270 + DCHxECON<15:8> = CHSIRQ<7:0> = output compare 2 interrupt
1.271 + */
1.272
1.273 la $v0, DCH0ECON
1.274 - sw $zero, 0($v0)
1.275 -
1.276 - la $v0, DCH1ECON
1.277 - li $v1, (60 << 8) | (1 << 4)
1.278 - sw $v1, 0($v0)
1.279 -
1.280 - la $v0, DCH2ECON
1.281 - li $v1, (61 << 8) | (1 << 4)
1.282 + li $v1, (12 << 8) | (1 << 4)
1.283 sw $v1, 0($v0)
1.284
1.285 /*
1.286 - The hsync channels have a cell size of 16 bytes:
1.287 - DCHxCSIZ<15:0> = CHCSIZ<15:0> = HSYNC_LIMIT
1.288 -
1.289 The line channel has a cell size of 160 bytes:
1.290 DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LIMIT
1.291 */
1.292
1.293 la $v0, DCH0CSIZ
1.294 - li $v1, HSYNC_LIMIT
1.295 - sw $v1, 0($v0)
1.296 -
1.297 - la $v0, DCH1CSIZ
1.298 - li $v1, HSYNC_LIMIT
1.299 - sw $v1, 0($v0)
1.300 -
1.301 - la $v0, DCH2CSIZ
1.302 li $v1, LINE_LIMIT
1.303 sw $v1, 0($v0)
1.304
1.305 @@ -589,34 +649,15 @@
1.306 */
1.307
1.308 la $v0, DCH0SSIZ
1.309 - li $v1, HSYNC_LIMIT
1.310 - sw $v1, 0($v0)
1.311 -
1.312 - la $v0, DCH1SSIZ
1.313 - li $v1, HSYNC_LIMIT
1.314 - sw $v1, 0($v0)
1.315 -
1.316 - la $v0, DCH2SSIZ
1.317 li $v1, LINE_LIMIT
1.318 sw $v1, 0($v0)
1.319
1.320 /*
1.321 - The source address is the physical address of either the hsync pulse
1.322 - data or the line data:
1.323 - DCHxSSA = pulse data physical address
1.324 + The source address is the physical address of the line data:
1.325 DCHxSSA = line data physical address
1.326 */
1.327
1.328 la $v0, DCH0SSA
1.329 - la $v1, set_ra2
1.330 - li $t8, KSEG0_BASE
1.331 - subu $v1, $v1, $t8
1.332 - sw $v1, 0($v0)
1.333 -
1.334 - la $v0, DCH1SSA
1.335 - sw $v1, 0($v0)
1.336 -
1.337 - la $v0, DCH2SSA
1.338 sw $zero, 0($v0)
1.339
1.340 /*
1.341 @@ -628,56 +669,18 @@
1.342 li $v1, 1
1.343 sw $v1, 0($v0)
1.344
1.345 - la $v0, DCH1DSIZ
1.346 - sw $v1, 0($v0)
1.347 -
1.348 - la $v0, DCH2DSIZ
1.349 - sw $v1, 0($v0)
1.350 -
1.351 - /*
1.352 - For the hsync channels, the destination address is the physical address
1.353 - for an I/O register that sets the output signal for hsync:
1.354 - DCHxDSA = physical(PORTA)
1.355 - */
1.356 -
1.357 - la $v0, DCH0DSA
1.358 - li $v1, PORTA + INV
1.359 - li $t8, KSEG1_BASE
1.360 - subu $v1, $v1, $t8
1.361 - sw $v1, 0($v0)
1.362 -
1.363 - la $v0, DCH1DSA
1.364 - li $v1, PORTA + CLR
1.365 - li $t8, KSEG1_BASE
1.366 - subu $v1, $v1, $t8
1.367 - sw $v1, 0($v0)
1.368 -
1.369 /*
1.370 For the line channel, the destination address is the physical address of
1.371 PMDIN: DCHxDSA = physical(PMDIN)
1.372 */
1.373
1.374 - la $v0, DCH2DSA
1.375 + la $v0, DCH0DSA
1.376 li $v1, PMDIN
1.377 li $t8, KSEG1_BASE
1.378 subu $v1, $v1, $t8
1.379 sw $v1, 0($v0)
1.380
1.381 - /*
1.382 - The block transfer complete interrupt needs to be enabled, so that upon
1.383 - completion of the transfer, the next transfer can be initiated:
1.384 - DCHxINT<19> = CHBCIE = 1
1.385 - */
1.386 -
1.387 la $v0, DCH0INT
1.388 - li $v1, (1 << 19)
1.389 - sw $v1, 0($v0)
1.390 -
1.391 - la $v0, DCH1INT
1.392 - li $v1, (1 << 19)
1.393 - sw $v1, 0($v0)
1.394 -
1.395 - la $v0, DCH2INT
1.396 sw $zero, 0($v0)
1.397
1.398 /* Enable channels. */
1.399 @@ -686,12 +689,6 @@
1.400 li $v1, 0b10000000
1.401 sw $v1, SET($v0)
1.402
1.403 - la $v0, DCH1CON
1.404 - sw $v1, SET($v0)
1.405 -
1.406 - la $v0, DCH2CON
1.407 - sw $v1, SET($v0)
1.408 -
1.409 jr $ra
1.410 nop
1.411
1.412 @@ -713,25 +710,3 @@
1.413
1.414 jr $ra
1.415 nop
1.416 -
1.417 -
1.418 -
1.419 -/* 16 bytes of pulse data used to set PORTA<2> = RA2. */
1.420 -
1.421 -set_ra2:
1.422 -.byte (1 << 2)
1.423 -.byte (1 << 2)
1.424 -.byte (1 << 2)
1.425 -.byte (1 << 2)
1.426 -.byte (1 << 2)
1.427 -.byte (1 << 2)
1.428 -.byte (1 << 2)
1.429 -.byte (1 << 2)
1.430 -.byte (1 << 2)
1.431 -.byte (1 << 2)
1.432 -.byte (1 << 2)
1.433 -.byte (1 << 2)
1.434 -.byte (1 << 2)
1.435 -.byte (1 << 2)
1.436 -.byte (1 << 2)
1.437 -.byte (1 << 2)