0
+ − 1 ;=============================================================================
+ − 2 ;
+ − 3 ; File aa_wordprocessor.asm
+ − 4 ;
+ − 5 ; Anti-aliased word processor
+ − 6 ;
+ − 7 ; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved.
+ − 8 ;=============================================================================
+ − 9 ; HISTORY
+ − 10 ; 2010-11-22 : [jDG] Creation.
+ − 11 ; 2010-12-01 : [jDG] Adding 3bits antialiased fonts.
+ − 12 ; 2010-12-30 : [jDG] Revised to put temp into ACCESSRAM0
+ − 13 ; 2012-08-12 : [mH] Moved font28 into bootloader section 0x1C000
+ − 14 ;
+ − 15 ; BUGS :
+ − 16 ; * If the three fonts are not in the same half of the PROM memory, TBLPTRU
+ − 17 ; will be badly set, and font48 or font90 will display giberish...
+ − 18 ;=============================================================================
+ − 19 ;
+ − 20 ; MEMORY FOOTPRINT:
+ − 21 ;------------------
+ − 22 ;
+ − 23 ; wp_wordprocessor : 8KB, including fonts.
+ − 24 ; aa_wordprocessor : 0.5KB code
+ − 25 ; + 3.5KB aa_font28 (reduced to 99 chars)
+ − 26 ; + 1.6KB aa_font48
+ − 27 ; + 2.2KB aa_font90
+ − 28 ; = 7.9 KB including fonts...
+ − 29 ;
+ − 30 ; Input registers:
+ − 31 ; buffer:26 String to print.
+ − 32 ; win_font Font size (0=tiny, 1=small, 2=medium, 3=large)
+ − 33 ; win_color1:2 16bits unpacked color
+ − 34 ; win_top, win_leftx2 Position on screen
+ − 35 ; win_inverse Inverse video mode.
+ − 36 ;
+ − 37 ; Available general purpose registers:
+ − 38 ; PRODH, PRODL (needed for array indexing)
+ − 39 ; FSRx 12bits. Usefull as RAM pointers.
+ − 40 ;=============================================================================
+ − 41
275
+ − 42 #include "hwos.inc"
0
+ − 43 #include "tft.inc"
+ − 44
+ − 45 extern aa_font16_block
+ − 46 extern aa_font28_block
+ − 47 extern aa_font36_block
+ − 48 extern aa_font48_block
+ − 49 extern aa_font90_block
+ − 50
+ − 51 ;=============================================================================
+ − 52 ; Temporary variables are overlayed in Bank 1, used also by C-code
+ − 53 ; (p2_deco), MPLAB math and stdlib libraries.
+ − 54
+ − 55 CBLOCK tmp ; Data overlay in reserved tmp area.
+ − 56 aa_flags:1 ; Various flags for aa_wordprocessor
+ − 57 aa_bitlen:1 ; Count of pixels when decoding bitmaps.
+ − 58 aa_start:2 ; PROM ptr to start of encoded bitmap
+ − 59 aa_end:2 ; and end of it.
+ − 60 aa_temp:2 ; Current color, divided by 2 or 4
+ − 61 ; Reserved to tmp+0x07...
+ − 62 ENDC
+ − 63 ; Flags allocation:
+ − 64 #define aa_antialias aa_flags,0
+ − 65 #define aa_color_quart aa_flags,1
+ − 66 #define aa_color_half aa_flags,2
+ − 67
+ − 68 ;------------------------------------------------------------------------------
+ − 69 ; Setup pointers for a char:
+ − 70 ; Inputs WREG = char to draw, win_font
+ − 71 ; Output aa_start, aa_end, win_height, aa_flags
+ − 72 ; Trashed PRODH, PRODL, TBLPTR, TABLAT
+ − 73 ;
+ − 74 basic CODE
+ − 75 aa_char_setup:
+ − 76 movwf PRODL ; save char into PROD for now.
+ − 77
+ − 78 movf win_font,W,BANKED ; Get font number (updates Z flag)
+ − 79 bnz aa_char_1
+ − 80
+ − 81 ; TINY font ---------------------------------------------------------
+ − 82 ; Font TINY character folding...
+ − 83 aa_char_0:
+ − 84 movlw LOW aa_font16_block
+ − 85 movwf TBLPTRL
+ − 86 movlw HIGH aa_font16_block
+ − 87 movwf TBLPTRH
+ − 88 movlw UPPER aa_font16_block
+ − 89 movwf TBLPTRU
+ − 90 bra aa_char_99
+ − 91
+ − 92 ; SMALL font ---------------------------------------------------------
+ − 93 ; Font SMALL character folding...
+ − 94 aa_char_1:
+ − 95 decfsz WREG ; This is small font ???
+ − 96 bra aa_char_2
+ − 97
+ − 98 movlw LOW aa_font28_block
+ − 99 movwf TBLPTRL
+ − 100 movlw HIGH aa_font28_block
+ − 101 movwf TBLPTRH
+ − 102 movlw UPPER aa_font28_block
+ − 103 movwf TBLPTRU
+ − 104 bra aa_char_99
+ − 105
+ − 106 ; STD font -----------------------------------------------------------
+ − 107 ; Font SMALL character folding...
+ − 108 aa_char_2:
+ − 109 decfsz WREG ; This is small font ???
+ − 110 bra aa_char_3
+ − 111
+ − 112 movlw LOW aa_font36_block
+ − 113 movwf TBLPTRL
+ − 114 movlw HIGH aa_font36_block
+ − 115 movwf TBLPTRH
+ − 116 movlw UPPER aa_font36_block
+ − 117 movwf TBLPTRU
+ − 118 bra aa_char_99
+ − 119
+ − 120 ; MEDIUM font --------------------------------------------------------
+ − 121 aa_char_3:
+ − 122 decfsz WREG ; This is medium font ???
+ − 123 bra aa_char_4
+ − 124
+ − 125 ; Font MEDIUM block:
+ − 126 movlw LOW aa_font48_block
+ − 127 movwf TBLPTRL
+ − 128 movlw HIGH aa_font48_block
+ − 129 movwf TBLPTRH
+ − 130 movlw UPPER aa_font48_block
+ − 131 movwf TBLPTRU
+ − 132 bra aa_char_99
+ − 133
+ − 134 ; LARGE font ---------------------------------------------------------
+ − 135 aa_char_4:
+ − 136 ; Font LARGE block:
+ − 137 movlw LOW aa_font90_block
+ − 138 movwf TBLPTRL
+ − 139 movlw HIGH aa_font90_block
+ − 140 movwf TBLPTRH
+ − 141 movlw UPPER aa_font90_block
+ − 142 movwf TBLPTRU
+ − 143
+ − 144 ; Execute font block -------------------------------------------------
+ − 145 aa_char_99:
+ − 146 ; This is safe if the three fonts are in the same code segment
+ − 147 ; (and that segment do not span the 64K edge...)
+ − 148 movlw UPPER aa_font16_block
+ − 149 movwf TBLPTRU
+ − 150
+ − 151 ; Proceed to character substitutions
+ − 152 aa_char_30:
+ − 153 tblrd*+ ; Read FROM char
+ − 154 movf TABLAT,W ; Get it, and set Z,N
+ − 155 bz aa_char_32 ; Break at end of translations
+ − 156
+ − 157 tblrd*+ ; Read TO char
+ − 158 cpfseq PRODL ; FROM == current char ?
+ − 159 bra aa_char_30 ; Different: loop
+ − 160 movff TABLAT, PRODL ; make substitution
+ − 161 bra aa_char_30 ; Loop.
+ − 162
+ − 163 ; Make sure char is in the available range
+ − 164 aa_char_32:
+ − 165 tblrd*+ ; Read first char
+ − 166 movf TABLAT,W ; get it.
+ − 167 subwf PRODL,F ; (char - first) --> PRODL
+ − 168
+ − 169 tblrd*+ ; Read nb chars
+ − 170 movf TABLAT,W ; nbchars --> WREG
+ − 171 tblrd*+ ; Read default char
+ − 172 cpfslt PRODL ; if char > WREG ?
+ − 173 movff TABLAT,PRODL ; replace PRODL
+ − 174
+ − 175 ; Decode font height and anti-aliasing mode
+ − 176 clrf aa_flags ; Default to no AA
+ − 177 tblrd*+ ; Read font height + AA flag
+ − 178 movf TABLAT,W ; into WREG
+ − 179 bnn aa_char_34 ; High bit set ?
+ − 180 bsf aa_antialias ; YES : then the font is AA.
+ − 181 aa_char_34:
+ − 182 andlw 0x7F ; Keep just font height,
+ − 183 movwf win_height,BANKED ; then save it (its a register)
+ − 184
+ − 185 ; Set PROM pointer to the char index
+ − 186 movf PRODL,W ; Read back char
+ − 187 mullw 2 ; PROD = 2*(char - base), TBLPTR=idx
+ − 188 movf PRODL,W
+ − 189 addwf TBLPTRL,F ; Add into TBLPTR (low byte)
+ − 190 movf PRODH,W
+ − 191 addwfc TBLPTRH,F ; and high byte.
+ − 192
+ − 193 ; Read start and stop pointers
+ − 194 tblrd*+ ; aa_start = PROM16(*tblptr++)
+ − 195 movff TABLAT,aa_start+0 ; Read low byte
+ − 196 tblrd*+
+ − 197 movff TABLAT,aa_start+1 ; and high byte
+ − 198
+ − 199 tblrd*+ ; aa_end = PROM16(*tblptr++)
+ − 200 movff TABLAT,aa_end+0 ; Read low byte
+ − 201 tblrd*+
+ − 202 movff TABLAT,aa_end+1 ; and high byte
+ − 203
+ − 204 return
+ − 205
+ − 206 ;------------------------------------------------------------------------------
+ − 207 ; Character width
+ − 208 ; Inputs aa_start, aa_end, win_width, win_height, aa_flags
+ − 209 ; Output width added to win_width
+ − 210 ; Trashed aa_bitlen, TBLPTR, TABLAT
+ − 211 ;
+ − 212 aa_char_width:
+ − 213 movff aa_start+0, TBLPTRL ; TBLPTR = aa_start
+ − 214 movff aa_start+1, TBLPTRH
+ − 215 clrf aa_bitlen ; clear reminders...
+ − 216
+ − 217 ; Read bitmap byte, and decode length:
+ − 218 aa_char_width_1:
+ − 219 ifdef AA_BYTE_SWAP
+ − 220 btg TBLPTRL,0 ; Toggle low ptr bit.
+ − 221 tblrd*
+ − 222 movf TABLAT,W ; Store to WREG
+ − 223 btg TBLPTRL,0 ; Get is back
+ − 224 tblrd*+ ; then increment (but trash TABLAT)
+ − 225 movwf TABLAT ; Then restore copy to TABLAT.
+ − 226 else
+ − 227 tblrd*+ ; Normal read...
+ − 228 movf TABLAT,W ; Store copy to WREG
+ − 229 endif
+ − 230 btfss aa_antialias ; Antialiased font ?
+ − 231 bra aa_char_width_10 ; No: always 7 bits count
+ − 232
+ − 233 bn aa_char_width_10 ; Non-white pixels ?
+ − 234 andlw 0x1F ; Yes : 5 bits count.
+ − 235 aa_char_width_10:
+ − 236 andlw 0x7F ; No: 7 bit count.
+ − 237 incf WREG ; WREG = repetition count
+ − 238 addwf aa_bitlen,F ; Add remaining pixels from last code.
+ − 239
+ − 240 movf win_height,W,BANKED ; WREG = - height
+ − 241 negf WREG
+ − 242
+ − 243 ; This is a hand-made division by successive substraction of height
+ − 244 aa_char_width_2:
+ − 245 addwf aa_bitlen,F ; Try to substract win_height
+ − 246 bn aa_char_width_3 ; If neg it was a bad idea...
+ − 247
+ − 248 infsnz win_width+0,F ; Succeded: do a 16bit increment
+ − 249 incf win_width+1,F ; on the win_width counter.
+ − 250 bra aa_char_width_2 ; and loop.
+ − 251
+ − 252 aa_char_width_3:
+ − 253 negf WREG ; WREG = +height
+ − 254 addwf aa_bitlen,F ; Restore true reminder.
+ − 255
+ − 256 ; Are we done ?
+ − 257 movf TBLPTRL,W ; Compare TBLPTR to aa_end
+ − 258 cpfseq aa_end+0
+ − 259 bra aa_char_width_1 ; Loop if LOW is different
+ − 260 movf TBLPTRH,W
+ − 261 cpfseq aa_end+1 ; Loop to if HIGH is different
+ − 262 bra aa_char_width_1
+ − 263
+ − 264 return
+ − 265
+ − 266 ;------------------------------------------------------------------------------
+ − 267 ; String width
+ − 268 ; Inputs buffer (SHOULD BE NULL TERMINATED)
+ − 269 ; Output win_width, win_height
+ − 270 ; Trashed PROD, TBLPTR, FSR2, aa_bitlen, aa_start, aa_end, aa_flags
+ − 271 ;
+ − 272 aa_string_width:
+ − 273 lfsr FSR2, buffer ; FSR2 pointer to start of string.
+ − 274
+ − 275 clrf win_width+0 ; Clear width sum.
+ − 276 clrf win_width+1 ; (16 bit counter)
+ − 277
+ − 278 aa_string_width_1:
+ − 279 movf POSTINC2,W ; WREG = *FSR2++
+ − 280 bz aa_string_width99 ; Exit if null byte encountered.
+ − 281
+ − 282 rcall aa_char_setup ; setup aa_start / aa_end
+ − 283 rcall aa_char_width ; sum-up width into win_width
+ − 284 bra aa_string_width_1 ; and loop.
+ − 285
+ − 286 aa_string_width99:
+ − 287 return
+ − 288
+ − 289 ;------------------------------------------------------------------------------
+ − 290 ; Decode a compressed char.
+ − 291 ; Inputs aa_start, aa_end, win_height, win_invert, win_color1, win_color2
+ − 292 ; Output none
+ − 293 ; Trashed TBLPTR, TABLAT, PROD, aa_bitlen, aa_flags, aa_colorDir:2
+ − 294 ;
+ − 295 aa_decode_char:
+ − 296 movff aa_start+0, TBLPTRL ; TBLPTR = aa_start
+ − 297 movff aa_start+1, TBLPTRH
+ − 298
+ − 299 ; Read bitmap byte, and decode color & length
+ − 300 aa_decode_1:
+ − 301 ifdef AA_BYTE_SWAP
+ − 302 btg TBLPTRL,0 ; Toggle low ptr bit.
+ − 303 tblrd*
+ − 304 movf TABLAT,W ; Store to WREG
+ − 305 btg TBLPTRL,0 ; Get is back
+ − 306 tblrd*+ ; then increment (but trash TABLAT)
+ − 307 movwf TABLAT ; Then restore copy to TABLAT.
+ − 308 else
+ − 309 tblrd*+ ; Normal read...
+ − 310 movf TABLAT,W ; Store copy to WREG
+ − 311 endif
+ − 312 btfss aa_antialias ; Antialiased font ?
+ − 313 bra aa_decode_10 ; No: always 7 bits count
+ − 314 bn aa_decode_10 ; Non-white pixels ?
+ − 315 andlw 0x1F ; Yes : 5 bits count.
+ − 316 aa_decode_10:
+ − 317 andlw 0x7F ; No: 7 bit count.
+ − 318 incf WREG
+ − 319 movwf aa_bitlen ; repetition count --> aa_bitlen
+ − 320
+ − 321 ;---- COLOR DECODING -------------------------------------------------
+ − 322 ;
+ − 323 ; Code Normal Inverse
+ − 324 ; 1xx 0% 100% : Managed by aa_decode_13
+ − 325 ; 011 25% 75%
+ − 326 ; 010 50% 50%
+ − 327 ; 001 75% 25%
+ − 328 ; 000 100% 0% : Managed by aa_decode_13 too.
+ − 329 ;
+ − 330 movf TABLAT,W ; Get back code
+ − 331 btfss aa_antialias ; Antialiased font ?
+ − 332 bra aa_decode_13 ; NO: 1bit case
+ − 333
+ − 334 ; Asymetry test: 1xx code is another case for 1bit color.
+ − 335 ; This have to be done before inverse video, because
+ − 336 ; of the asymetric processing !
+ − 337 bn aa_decode_13 ; decode as not-aa
+ − 338
+ − 339 ; Manage 000 special case too:
+ − 340 andlw 0xE0 ; Select color bits
+ − 341 bz aa_decode_13 ; That's a 000 !
+ − 342
+ − 343 ; Apply reverse video, in a reversed way
189
+ − 344 btfss win_invert ; Inverse video mode ?
0
+ − 345 sublw 0x80
+ − 346
+ − 347 ; Move the two bits to aa_color_half and aa_color_quarter:
+ − 348 swapf WREG ; --> 0000.0LL0 byte
+ − 349 iorlw b'001' ; We are in AA mode, don't forget it !
+ − 350 movwf aa_flags ; save that to aa_color_(half/quad)/AA flags.
+ − 351
+ − 352 ;---- 2 bit x RGB(16bits) computation --------------------------------
+ − 353 clrf PRODL ; We will accumulate result here...
+ − 354 clrf PRODH
+ − 355
+ − 356 ; Take color div 2 into aa_temp. Max red = 15/31
+ − 357 rrcf win_color1,W,BANKED ; xRRRRxGG
+ − 358 andlw b'01111011' ; 0RRRR0GG (don't change C)
+ − 359 movwf aa_temp+0
+ − 360 rrcf win_color2,W,BANKED ; GGGxBBBB
+ − 361 andlw b'11101111' ; GGG0BBBB
+ − 362 movwf aa_temp+1
+ − 363
+ − 364 btfss aa_color_half
+ − 365 bra aa_decode_12
+ − 366
+ − 367 movff aa_temp+0,PRODH ; Add color/2 if bit set.
+ − 368 movff aa_temp+1,PRODL ; TFT is big endian, so swap here.
+ − 369 aa_decode_12:
+ − 370 btfss aa_color_quart
+ − 371 bra aa_decode_3
+ − 372
+ − 373 ; Divide it once again by 2. Max red = 7/31.
+ − 374 rrcf aa_temp+0,W ; xxRRRxxG
+ − 375 andlw b'00111001' ; 00RRR00G (don't change C)
+ − 376 movwf aa_temp+0
+ − 377 rrcf aa_temp+1,W ; GGGxxBBB
+ − 378 andlw b'11100111' ; GGG00BBB
+ − 379 movwf aa_temp+1
+ − 380
+ − 381 movf aa_temp+1,W ; Add color/4
+ − 382 addwf PRODL,F ; NOTE: 7/31+15/31=22/31,
+ − 383 movf aa_temp+0,W ; hence composants won't overlap.
+ − 384 addwfc PRODH,F ; In right order, to propagate carry.
+ − 385
+ − 386 bra aa_decode_3 ; Done.
+ − 387
+ − 388 ; ---- Simple BLACK and WHITE cases ------------------------------
+ − 389 aa_decode_13: ; Got a 1xx or a 000 code...
189
+ − 390 btfsc win_invert ; Inverse video mode ?
0
+ − 391 xorlw 0x80 ; YES: invert levels.
+ − 392 bn aa_decode_2 ; Then test high bit.
+ − 393
+ − 394 ; WHITE pixel (ie. full color)
+ − 395 bsf tft_rs,0 ; RS_H ; Data
+ − 396 movff win_color1,PORTA ; current draw color
+ − 397 movff win_color2,PORTH ; (rem: TFT is big endian)
+ − 398 bra aa_decode_4
+ − 399
+ − 400 aa_decode_2:
+ − 401 bsf tft_rs,0 ; RS_H ; Data
+ − 402 clrf PORTA ; BLACK pixel
+ − 403 clrf PORTH
+ − 404 bra aa_decode_4
+ − 405
+ − 406 aa_decode_3:
+ − 407 bsf tft_rs,0 ; RS_H ; Data
+ − 408 movff PRODH,PORTA ; Move high byte to PORTA
+ − 409 movff PRODL,PORTH ; Move low byte to PORTH
+ − 410 aa_decode_4:
+ − 411 ;---- PIXEL WRITE LOOP -----------------------------------------------
+ − 412 bcf tft_nwr,0 ; WR_L
+ − 413 bsf tft_nwr,0 ; WR_H ; Tick
+ − 414
+ − 415 decf aa_bitlen,F
+ − 416 bnz aa_decode_4
+ − 417
+ − 418 ;---- BYTE-CODE LOOP -------------------------------------------------
+ − 419 ; Are we done ?
+ − 420 movf TBLPTRL,W ; Compare TBLPTR to aa_end
+ − 421 cpfseq aa_end+0
+ − 422 bra aa_decode_1 ; Loop if LOW is different
+ − 423 movf TBLPTRH,W
+ − 424 cpfseq aa_end+1 ; Loop to if HIGH is different
+ − 425 bra aa_decode_1
+ − 426
+ − 427 return
+ − 428
+ − 429 ;------------------------------------------------------------------------------
+ − 430 ; Setup pointers for a char:
+ − 431 ; Inputs : buffer : string to print (SHOULD BE NULL TERMINATED)
+ − 432 ; Output : TFT commands on port D + clocks.
+ − 433 ;
+ − 434 global aa_wordprocessor ; Callable from C-code.
+ − 435 aa_wordprocessor:
+ − 436 banksel win_font ; Bank1, just to be sure.
+ − 437 rcall aa_string_width ; Set win_height, compute win_width
+ − 438 call TFT_box_write ; Use that for the box.
+ − 439
+ − 440 ; Restart the loop for each char to print
+ − 441 lfsr FSR2, buffer ; FSR2 pointer to start of string.
+ − 442
+ − 443 ; DATA bloc commande:
+ − 444 Index_out 0x22
+ − 445
+ − 446 aa_wordprocessor_1:
+ − 447 movf POSTINC2,W ; WREG = *FSR2++
+ − 448 bz aa_wordprocessor_99 ; Exit if null byte encountered.
+ − 449
+ − 450 rcall aa_char_setup ; setup aa_start / aa_end
+ − 451 rcall aa_decode_char ; write pixels to screen
+ − 452 bra aa_wordprocessor_1 ; and loop.
+ − 453
+ − 454 aa_wordprocessor_99:
+ − 455 ; END of bloc commande
+ − 456 Index_out 0x00
+ − 457
+ − 458 return
+ − 459 END