Mercurial > public > mk2
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 |