comparison code_part1/OSTC_code_asm_part1/aa_wordprocessor.asm @ 83:3e351e25f5d1

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