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