3.1 --- a/vga.S Mon May 15 14:52:17 2017 +0200
3.2 +++ b/vga.S Tue May 16 16:49:25 2017 +0200
3.3 @@ -119,6 +119,10 @@
3.4 jal init_pins
3.5 nop
3.6
3.7 + la $t0, PORTA
3.8 + li $t1, (1 << 3) /* PORTA<3> = RA3 */
3.9 + sw $t1, CLR($t0)
3.10 +
3.11 jal init_oc_pins
3.12 nop
3.13
3.14 @@ -132,17 +136,12 @@
3.15 jal init_timer2
3.16 nop
3.17
3.18 - /* Initialise PMP. */
3.19 -
3.20 - jal init_pmp
3.21 - nop
3.22 -
3.23 /* Initialise DMA. */
3.24
3.25 jal init_dma
3.26 nop
3.27
3.28 - /* Initialise OC3 and OC2. */
3.29 + /* Initialise OC1 and OC2. */
3.30
3.31 jal init_oc
3.32 nop
3.33 @@ -155,16 +154,6 @@
3.34 jal handle_error_level
3.35 nop
3.36
3.37 - /* Set initial sync conditions. */
3.38 -
3.39 - la $t0, PORTB
3.40 - li $t1, (1 << 5) /* PORTB<5> = RB5 */
3.41 - sw $t1, SET($t0)
3.42 -
3.43 - la $t0, PORTB
3.44 - li $t1, (1 << 10) /* PORTB<10> = RB10 */
3.45 - sw $t1, SET($t0)
3.46 -
3.47 /* Main program. */
3.48
3.49 li $a1, 5000000 /* counter = 5000000 */
3.50 @@ -183,8 +172,8 @@
3.51
3.52 li $a1, 5000000 /* counter = 5000000 */
3.53
3.54 - la $t0, PORTB
3.55 - li $t1, (1 << 11) /* PORTB<11> = RB11 */
3.56 + la $t0, PORTA
3.57 + li $t1, (1 << 3) /* PORTA<3> = RA3 */
3.58 sw $t1, INV($t0)
3.59
3.60 _next:
3.61 @@ -272,7 +261,7 @@
3.62 /*
3.63 Output compare initialisation.
3.64
3.65 -Timer2 will be used to trigger two events using OC3: one initiating the hsync
3.66 +Timer2 will be used to trigger two events using OC1: one initiating the hsync
3.67 pulse, and one terminating the pulse. The pulse should appear after the line
3.68 data has been transferred using DMA, but this is achieved by just choosing
3.69 suitable start and end values.
3.70 @@ -282,35 +271,35 @@
3.71 */
3.72
3.73 init_oc:
3.74 - /* Disable OC3 interrupts. */
3.75 + /* Disable OC1 interrupts. */
3.76
3.77 la $v0, IEC0
3.78 - li $v1, (1 << 17) /* IEC0<17> = OC3IE = 0 */
3.79 + li $v1, (1 << 7) /* IEC0<7> = OC1IE = 0 */
3.80 sw $v1, CLR($v0)
3.81
3.82 la $v0, IFS0
3.83 - li $v1, (1 << 17) /* IFS0<17> = OC3IF = 0 */
3.84 + li $v1, (1 << 7) /* IFS0<7> = OC1IF = 0 */
3.85 sw $v1, CLR($v0)
3.86
3.87 - /* Initialise OC3. */
3.88 + /* Initialise OC1. */
3.89
3.90 - la $v0, OC3CON
3.91 - li $v1, 0b101 /* OC3CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */
3.92 + la $v0, OC1CON
3.93 + li $v1, 0b101 /* OC1CON<2:0> = OCM<2:0> = 101 (dual compare, continuous pulse) */
3.94 sw $v1, 0($v0)
3.95
3.96 /* Pulse start and end. */
3.97
3.98 - la $v0, OC3R
3.99 + la $v0, OC1R
3.100 li $v1, HSYNC_END /* HSYNC_START for positive polarity */
3.101 sw $v1, 0($v0)
3.102
3.103 - la $v0, OC3RS
3.104 + la $v0, OC1RS
3.105 li $v1, HSYNC_START /* HSYNC_END for positive polarity */
3.106 sw $v1, 0($v0)
3.107
3.108 - /* OC3 is enabled. */
3.109 + /* OC1 is enabled. */
3.110
3.111 - la $v0, OC3CON
3.112 + la $v0, OC1CON
3.113 li $v1, (1 << 15)
3.114 sw $v1, SET($v0)
3.115
3.116 @@ -356,16 +345,16 @@
3.117 li $v1, (1 << 13) /* IOLOCK = 0 */
3.118 sw $v1, CLR($v0)
3.119
3.120 - /* Map OC3 to RPB10. */
3.121 + /* Map OC1 to RPA0. */
3.122
3.123 - la $v0, RPB10R
3.124 - li $v1, 0b0101 /* RPB10R<3:0> = 0101 (OC3) */
3.125 + la $v0, RPA0R
3.126 + li $v1, 0b0101 /* RPA0R<3:0> = 0101 (OC1) */
3.127 sw $v1, 0($v0)
3.128
3.129 - /* Map OC2 to RPB5. */
3.130 + /* Map OC2 to RPA1. */
3.131
3.132 - la $v0, RPB5R
3.133 - li $v1, 0b0101 /* RPB5R<3:0> = 0101 (OC2) */
3.134 + la $v0, RPA1R
3.135 + li $v1, 0b0101 /* RPA1R<3:0> = 0101 (OC2) */
3.136 sw $v1, 0($v0)
3.137
3.138 la $v0, CFGCON
3.139 @@ -382,65 +371,10 @@
3.140
3.141
3.142
3.143 -/* Parallel Master Port initialisation. */
3.144 -
3.145 -init_pmp:
3.146 - /* Disable PMP interrupts. */
3.147 -
3.148 - la $v0, IEC1
3.149 - li $v1, (1 << 16) /* IEC1<16> = PMPIE = 0 */
3.150 - sw $v1, CLR($v0)
3.151 -
3.152 - /* Initialise PMP.
3.153 -
3.154 - PMCON<12:11> = ADDRMUX<1:0> = 0; demultiplexed address and data
3.155 - PMCON<9> = PTWREN<0> = 0; no write pin
3.156 - PMCON<8> = PTRDEN<0> = 0; no read pin
3.157 - PMCON<7:6> = CSF<1:0> = 0; no chip select pins
3.158 - */
3.159 -
3.160 - la $v0, PMCON
3.161 - sw $zero, 0($v0)
3.162 -
3.163 - /*
3.164 - PMMODE<14:13> = IRQM<1:0> = 1; interrupt after every read/write
3.165 - PMMODE<12:11> = INCM<1:0> = 0; no increment on every read/write
3.166 - PMMODE<10> = MODE16<0> = 0; 8-bit transfers
3.167 - PMMODE<9:8> = MODE<1:0> = 10; master mode 2
3.168 - PMMODE<5:2> = WAITM<3:0> = 00; single cycle read/write, no chip select wait cycles
3.169 - */
3.170 -
3.171 - la $v0, PMMODE
3.172 - li $v1, 0x2200
3.173 - sw $v1, 0($v0)
3.174 -
3.175 - /* Free non-essential pins for general I/O. */
3.176 -
3.177 - la $v0, PMAEN
3.178 - sw $zero, 0($v0)
3.179 -
3.180 - la $v0, PMADDR
3.181 - sw $zero, 0($v0)
3.182 -
3.183 - la $v0, IFS1
3.184 - li $v1, (3 << 16) /* IFS1<17:16> = PMPEIF, PMPIF = 0 */
3.185 - sw $v1, CLR($v0)
3.186 -
3.187 - /* Start PMP mode. */
3.188 -
3.189 - la $v0, PMCON
3.190 - li $v1, (1 << 15) /* PMCON<15> = ON = 1 */
3.191 - sw $v1, SET($v0)
3.192 -
3.193 - jr $ra
3.194 - nop
3.195 -
3.196 -
3.197 -
3.198 /*
3.199 Direct Memory Access initialisation.
3.200
3.201 -Write 160 pixels to the PMP for the line data. This is initiated by a timer
3.202 +Write 160 pixels to PORTB for the line data. This is initiated by a timer
3.203 interrupt. Upon completion of the transfer, a DMA interrupt initiates the
3.204 address update routine, changing the source address of the DMA channel.
3.205 */
3.206 @@ -449,13 +383,13 @@
3.207 /* Disable DMA interrupts. */
3.208
3.209 la $v0, IEC1
3.210 - li $v1, (1 << 28) /* IEC1<28> = DMA0IE = 0 */
3.211 + li $v1, (3 << 28) /* IEC1<29:28> = DMA1IE, DMA0IE = 0 */
3.212 sw $v1, CLR($v0)
3.213
3.214 /* Clear DMA interrupt flags. */
3.215
3.216 la $v0, IFS1
3.217 - li $v1, (1 << 28) /* IFS1<28> = DMA0IF = 0 */
3.218 + li $v1, (3 << 28) /* IFS1<29:28> = DMA1IF, DMA0IF = 0 */
3.219 sw $v1, CLR($v0)
3.220
3.221 /* Enable DMA. */
3.222 @@ -471,7 +405,7 @@
3.223 Specify a priority of 3:
3.224 DCHxCON<1:0> = CHPRI<1:0> = 3
3.225
3.226 - Auto-enable the channels:
3.227 + Auto-enable the channel:
3.228 DCHxCON<4> = CHAEN = 1
3.229 */
3.230
3.231 @@ -480,6 +414,24 @@
3.232 sw $v1, 0($v0)
3.233
3.234 /*
3.235 + Initialise a level reset channel.
3.236 + The reset channel will be channel 1 (x = 1).
3.237 +
3.238 + Specify a priority of 3:
3.239 + DCHxCON<1:0> = CHPRI<1:0> = 3
3.240 +
3.241 + Chain the channel to channel 0:
3.242 + DCHxCON<5> = CHCHN = 1
3.243 +
3.244 + Allow the channel to receive events when disabled:
3.245 + DCHxCON<6> = CHAED = 1
3.246 + */
3.247 +
3.248 + la $v0, DCH1CON
3.249 + li $v1, 0b1100011
3.250 + sw $v1, 0($v0)
3.251 +
3.252 + /*
3.253 Initiate channel transfers when the initiating interrupt condition
3.254 occurs:
3.255 DCHxECON<15:8> = CHSIRQ<7:0> = timer 2 interrupt
3.256 @@ -491,7 +443,17 @@
3.257 sw $v1, 0($v0)
3.258
3.259 /*
3.260 - The line channel has a cell size as the number bytes in a line:
3.261 + Initiate reset channel transfer when channel 0 is finished:
3.262 + DCHxECON<15:8> = CHSIRQ<7:0> = channel 0 interrupt
3.263 + DCHxECON<4> = SIRQEN = 1
3.264 + */
3.265 +
3.266 + la $v0, DCH1ECON
3.267 + li $v1, (60 << 8) | (1 << 4)
3.268 + sw $v1, 0($v0)
3.269 +
3.270 + /*
3.271 + The line channel has a cell size of the number bytes in a line:
3.272 DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LENGTH
3.273 */
3.274
3.275 @@ -500,6 +462,15 @@
3.276 sw $v1, 0($v0)
3.277
3.278 /*
3.279 + The reset channel has a cell size of a single zero byte:
3.280 + DCHxCSIZ<15:0> = CHCSIZ<15:0> = LINE_LENGTH
3.281 + */
3.282 +
3.283 + la $v0, DCH1CSIZ
3.284 + li $v1, 1
3.285 + sw $v1, 0($v0)
3.286 +
3.287 + /*
3.288 The source has a size identical to the cell size:
3.289 DCHxSSIZ<15:0> = CHSSIZ<15:0> = LINE_LENGTH
3.290 */
3.291 @@ -508,6 +479,10 @@
3.292 li $v1, LINE_LENGTH
3.293 sw $v1, 0($v0)
3.294
3.295 + la $v0, DCH1SSIZ
3.296 + li $v1, 1
3.297 + sw $v1, 0($v0)
3.298 +
3.299 /*
3.300 The source address is the physical address of the line data:
3.301 DCHxSSA = physical(line data address)
3.302 @@ -517,6 +492,17 @@
3.303 sw $zero, 0($v0)
3.304
3.305 /*
3.306 + For the reset channel, a single byte of zero is transferred:
3.307 + DCHxSSA = physical(zero data address)
3.308 + */
3.309 +
3.310 + la $v0, DCH1SSA
3.311 + la $v1, zerodata
3.312 + li $t8, KSEG0_BASE
3.313 + subu $v1, $v1, $t8
3.314 + sw $v1, 0($v0)
3.315 +
3.316 + /*
3.317 The destination has a size of 1 byte:
3.318 DCHxDSIZ<15:0> = CHDSIZ<15:0> = 1
3.319 */
3.320 @@ -525,17 +511,23 @@
3.321 li $v1, 1
3.322 sw $v1, 0($v0)
3.323
3.324 + la $v0, DCH1DSIZ
3.325 + sw $v1, 0($v0)
3.326 +
3.327 /*
3.328 - The destination address is the physical address of PMDIN:
3.329 - DCHxDSA = physical(PMDIN)
3.330 + The destination address is the physical address of PORTB:
3.331 + DCHxDSA = physical(PORTB)
3.332 */
3.333
3.334 la $v0, DCH0DSA
3.335 - li $v1, PMDIN
3.336 + li $v1, PORTB
3.337 li $t8, KSEG1_BASE
3.338 subu $v1, $v1, $t8
3.339 sw $v1, 0($v0)
3.340
3.341 + la $v0, DCH1DSA
3.342 + sw $v1, 0($v0)
3.343 +
3.344 /*
3.345 Use the block transfer completion interrupt to indicate when the source
3.346 address can be updated.
3.347 @@ -559,7 +551,7 @@
3.348 li $v1, (1 << 28) /* IEC1<28> = DMA0IE = 1 */
3.349 sw $v1, SET($v0)
3.350
3.351 - /* Enable channel. */
3.352 + /* Enable line channel. */
3.353
3.354 la $v0, DCH0CON
3.355 li $v1, 0b10000000
3.356 @@ -568,6 +560,9 @@
3.357 jr $ra
3.358 nop
3.359
3.360 +zerodata:
3.361 +.word 0
3.362 +
3.363
3.364
3.365 /* Framebuffer initialisation. */
3.366 @@ -645,8 +640,8 @@
3.367 addiu $t8, $t8, -1
3.368 bnez $t8, exc_loop
3.369 nop
3.370 - la $v0, PORTB
3.371 - li $v1, (1 << 11) /* PORTB<11> = RB11 */
3.372 + la $v0, PORTA
3.373 + li $v1, (1 << 2) /* PORTA<2> = RA2 */
3.374 sw $v1, INV($v0)
3.375 j exception_handler
3.376 nop