line source
;=============================================================================+ −
;+ −
; File aa_wordprocessor.asm+ −
;+ −
; Anti-aliased word processor+ −
;+ −
; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved.+ −
;=============================================================================+ −
; HISTORY+ −
; 2010-11-22 : [jDG] Creation.+ −
; 2010-12-01 : [jDG] Adding 3bits antialiased fonts.+ −
; 2010-12-30 : [jDG] Revised to put temp into ACCESSRAM0+ −
; 2012-08-12 : [mH] Moved font28 into bootloader section 0x1C000+ −
;+ −
; BUGS :+ −
; * If the three fonts are not in the same half of the PROM memory, TBLPTRU+ −
; will be badly set, and font48 or font90 will display giberish...+ −
;=============================================================================+ −
;+ −
; MEMORY FOOTPRINT:+ −
;------------------+ −
;+ −
; wp_wordprocessor : 8KB, including fonts.+ −
; aa_wordprocessor : 0.5KB code+ −
; + 3.5KB aa_font28 (reduced to 99 chars)+ −
; + 1.6KB aa_font48+ −
; + 2.2KB aa_font90+ −
; = 7.9 KB including fonts...+ −
;+ −
; Input registers:+ −
; buffer:26 String to print.+ −
; win_font Font size (0=tiny, 1=small, 2=medium, 3=large)+ −
; win_color1:2 16bits unpacked color+ −
; win_top, win_leftx2 Position on screen+ −
; win_inverse Inverse video mode.+ −
;+ −
; Available general purpose registers:+ −
; PRODH, PRODL (needed for array indexing)+ −
; FSRx 12bits. Usefull as RAM pointers.+ −
;=============================================================================+ −
+ −
#include "ostc3.inc"+ −
#include "tft.inc"+ −
+ −
extern aa_font16_block+ −
extern aa_font28_block+ −
extern aa_font36_block+ −
extern aa_font48_block+ −
extern aa_font90_block+ −
+ −
;=============================================================================+ −
; Temporary variables are overlayed in Bank 1, used also by C-code+ −
; (p2_deco), MPLAB math and stdlib libraries.+ −
+ −
CBLOCK tmp ; Data overlay in reserved tmp area.+ −
aa_flags:1 ; Various flags for aa_wordprocessor+ −
aa_bitlen:1 ; Count of pixels when decoding bitmaps.+ −
aa_start:2 ; PROM ptr to start of encoded bitmap+ −
aa_end:2 ; and end of it.+ −
aa_temp:2 ; Current color, divided by 2 or 4+ −
; Reserved to tmp+0x07...+ −
ENDC+ −
; Flags allocation:+ −
#define aa_antialias aa_flags,0+ −
#define aa_color_quart aa_flags,1+ −
#define aa_color_half aa_flags,2+ −
+ −
;------------------------------------------------------------------------------+ −
; Setup pointers for a char:+ −
; Inputs WREG = char to draw, win_font+ −
; Output aa_start, aa_end, win_height, aa_flags+ −
; Trashed PRODH, PRODL, TBLPTR, TABLAT+ −
;+ −
basic CODE+ −
aa_char_setup:+ −
movwf PRODL ; save char into PROD for now.+ −
+ −
movf win_font,W,BANKED ; Get font number (updates Z flag)+ −
bnz aa_char_1+ −
+ −
; TINY font ---------------------------------------------------------+ −
; Font TINY character folding...+ −
aa_char_0:+ −
movlw LOW aa_font16_block+ −
movwf TBLPTRL+ −
movlw HIGH aa_font16_block+ −
movwf TBLPTRH+ −
movlw UPPER aa_font16_block+ −
movwf TBLPTRU+ −
bra aa_char_99+ −
+ −
; SMALL font ---------------------------------------------------------+ −
; Font SMALL character folding...+ −
aa_char_1:+ −
decfsz WREG ; This is small font ???+ −
bra aa_char_2+ −
+ −
movlw LOW aa_font28_block+ −
movwf TBLPTRL+ −
movlw HIGH aa_font28_block+ −
movwf TBLPTRH+ −
movlw UPPER aa_font28_block+ −
movwf TBLPTRU+ −
bra aa_char_99+ −
+ −
; STD font -----------------------------------------------------------+ −
; Font SMALL character folding...+ −
aa_char_2:+ −
decfsz WREG ; This is small font ???+ −
bra aa_char_3+ −
+ −
movlw LOW aa_font36_block+ −
movwf TBLPTRL+ −
movlw HIGH aa_font36_block+ −
movwf TBLPTRH+ −
movlw UPPER aa_font36_block+ −
movwf TBLPTRU+ −
bra aa_char_99+ −
+ −
; MEDIUM font --------------------------------------------------------+ −
aa_char_3:+ −
decfsz WREG ; This is medium font ???+ −
bra aa_char_4+ −
+ −
; Font MEDIUM block:+ −
movlw LOW aa_font48_block+ −
movwf TBLPTRL+ −
movlw HIGH aa_font48_block+ −
movwf TBLPTRH+ −
movlw UPPER aa_font48_block+ −
movwf TBLPTRU+ −
bra aa_char_99+ −
+ −
; LARGE font ---------------------------------------------------------+ −
aa_char_4:+ −
; Font LARGE block:+ −
movlw LOW aa_font90_block+ −
movwf TBLPTRL+ −
movlw HIGH aa_font90_block+ −
movwf TBLPTRH+ −
movlw UPPER aa_font90_block+ −
movwf TBLPTRU+ −
+ −
; Execute font block -------------------------------------------------+ −
aa_char_99:+ −
; This is safe if the three fonts are in the same code segment+ −
; (and that segment do not span the 64K edge...)+ −
movlw UPPER aa_font16_block+ −
movwf TBLPTRU+ −
+ −
; Proceed to character substitutions+ −
aa_char_30:+ −
tblrd*+ ; Read FROM char+ −
movf TABLAT,W ; Get it, and set Z,N+ −
bz aa_char_32 ; Break at end of translations+ −
+ −
tblrd*+ ; Read TO char+ −
cpfseq PRODL ; FROM == current char ? + −
bra aa_char_30 ; Different: loop+ −
movff TABLAT, PRODL ; make substitution+ −
bra aa_char_30 ; Loop.+ −
+ −
; Make sure char is in the available range+ −
aa_char_32:+ −
tblrd*+ ; Read first char+ −
movf TABLAT,W ; get it.+ −
subwf PRODL,F ; (char - first) --> PRODL+ −
+ −
tblrd*+ ; Read nb chars+ −
movf TABLAT,W ; nbchars --> WREG+ −
tblrd*+ ; Read default char+ −
cpfslt PRODL ; if char > WREG ?+ −
movff TABLAT,PRODL ; replace PRODL+ −
+ −
; Decode font height and anti-aliasing mode+ −
clrf aa_flags ; Default to no AA+ −
tblrd*+ ; Read font height + AA flag+ −
movf TABLAT,W ; into WREG+ −
bnn aa_char_34 ; High bit set ?+ −
bsf aa_antialias ; YES : then the font is AA.+ −
aa_char_34:+ −
andlw 0x7F ; Keep just font height,+ −
movwf win_height,BANKED ; then save it (its a register)+ −
+ −
; Set PROM pointer to the char index+ −
movf PRODL,W ; Read back char+ −
mullw 2 ; PROD = 2*(char - base), TBLPTR=idx+ −
movf PRODL,W+ −
addwf TBLPTRL,F ; Add into TBLPTR (low byte)+ −
movf PRODH,W+ −
addwfc TBLPTRH,F ; and high byte.+ −
+ −
; Read start and stop pointers+ −
tblrd*+ ; aa_start = PROM16(*tblptr++)+ −
movff TABLAT,aa_start+0 ; Read low byte+ −
tblrd*++ −
movff TABLAT,aa_start+1 ; and high byte+ −
+ −
tblrd*+ ; aa_end = PROM16(*tblptr++)+ −
movff TABLAT,aa_end+0 ; Read low byte+ −
tblrd*++ −
movff TABLAT,aa_end+1 ; and high byte+ −
+ −
return+ −
+ −
;------------------------------------------------------------------------------+ −
; Character width+ −
; Inputs aa_start, aa_end, win_width, win_height, aa_flags+ −
; Output width added to win_width+ −
; Trashed aa_bitlen, TBLPTR, TABLAT+ −
;+ −
aa_char_width:+ −
movff aa_start+0, TBLPTRL ; TBLPTR = aa_start+ −
movff aa_start+1, TBLPTRH+ −
clrf aa_bitlen ; clear reminders...+ −
+ −
; Read bitmap byte, and decode length:+ −
aa_char_width_1:+ −
ifdef AA_BYTE_SWAP+ −
btg TBLPTRL,0 ; Toggle low ptr bit.+ −
tblrd*+ −
movf TABLAT,W ; Store to WREG+ −
btg TBLPTRL,0 ; Get is back+ −
tblrd*+ ; then increment (but trash TABLAT)+ −
movwf TABLAT ; Then restore copy to TABLAT.+ −
else+ −
tblrd*+ ; Normal read...+ −
movf TABLAT,W ; Store copy to WREG+ −
endif+ −
btfss aa_antialias ; Antialiased font ?+ −
bra aa_char_width_10 ; No: always 7 bits count+ −
+ −
bn aa_char_width_10 ; Non-white pixels ?+ −
andlw 0x1F ; Yes : 5 bits count.+ −
aa_char_width_10:+ −
andlw 0x7F ; No: 7 bit count.+ −
incf WREG ; WREG = repetition count+ −
addwf aa_bitlen,F ; Add remaining pixels from last code.+ −
+ −
movf win_height,W,BANKED ; WREG = - height+ −
negf WREG+ −
+ −
; This is a hand-made division by successive substraction of height+ −
aa_char_width_2:+ −
addwf aa_bitlen,F ; Try to substract win_height+ −
bn aa_char_width_3 ; If neg it was a bad idea...+ −
+ −
infsnz win_width+0,F ; Succeded: do a 16bit increment+ −
incf win_width+1,F ; on the win_width counter.+ −
bra aa_char_width_2 ; and loop.+ −
+ −
aa_char_width_3:+ −
negf WREG ; WREG = +height+ −
addwf aa_bitlen,F ; Restore true reminder.+ −
+ −
; Are we done ?+ −
movf TBLPTRL,W ; Compare TBLPTR to aa_end+ −
cpfseq aa_end+0 + −
bra aa_char_width_1 ; Loop if LOW is different+ −
movf TBLPTRH,W+ −
cpfseq aa_end+1 ; Loop to if HIGH is different+ −
bra aa_char_width_1+ −
+ −
return+ −
+ −
;------------------------------------------------------------------------------+ −
; String width+ −
; Inputs buffer (SHOULD BE NULL TERMINATED)+ −
; Output win_width, win_height+ −
; Trashed PROD, TBLPTR, FSR2, aa_bitlen, aa_start, aa_end, aa_flags+ −
;+ −
aa_string_width:+ −
lfsr FSR2, buffer ; FSR2 pointer to start of string.+ −
+ −
clrf win_width+0 ; Clear width sum.+ −
clrf win_width+1 ; (16 bit counter)+ −
+ −
aa_string_width_1:+ −
movf POSTINC2,W ; WREG = *FSR2+++ −
bz aa_string_width99 ; Exit if null byte encountered.+ −
+ −
rcall aa_char_setup ; setup aa_start / aa_end+ −
rcall aa_char_width ; sum-up width into win_width+ −
bra aa_string_width_1 ; and loop.+ −
+ −
aa_string_width99:+ −
return+ −
+ −
;------------------------------------------------------------------------------+ −
; Decode a compressed char.+ −
; Inputs aa_start, aa_end, win_height, win_invert, win_color1, win_color2+ −
; Output none+ −
; Trashed TBLPTR, TABLAT, PROD, aa_bitlen, aa_flags, aa_colorDir:2+ −
;+ −
aa_decode_char:+ −
movff aa_start+0, TBLPTRL ; TBLPTR = aa_start+ −
movff aa_start+1, TBLPTRH+ −
+ −
; Read bitmap byte, and decode color & length+ −
aa_decode_1:+ −
ifdef AA_BYTE_SWAP+ −
btg TBLPTRL,0 ; Toggle low ptr bit.+ −
tblrd*+ −
movf TABLAT,W ; Store to WREG+ −
btg TBLPTRL,0 ; Get is back+ −
tblrd*+ ; then increment (but trash TABLAT)+ −
movwf TABLAT ; Then restore copy to TABLAT.+ −
else+ −
tblrd*+ ; Normal read...+ −
movf TABLAT,W ; Store copy to WREG+ −
endif+ −
btfss aa_antialias ; Antialiased font ?+ −
bra aa_decode_10 ; No: always 7 bits count+ −
bn aa_decode_10 ; Non-white pixels ?+ −
andlw 0x1F ; Yes : 5 bits count.+ −
aa_decode_10:+ −
andlw 0x7F ; No: 7 bit count.+ −
incf WREG + −
movwf aa_bitlen ; repetition count --> aa_bitlen+ −
+ −
;---- COLOR DECODING -------------------------------------------------+ −
;+ −
; Code Normal Inverse+ −
; 1xx 0% 100% : Managed by aa_decode_13+ −
; 011 25% 75%+ −
; 010 50% 50%+ −
; 001 75% 25%+ −
; 000 100% 0% : Managed by aa_decode_13 too.+ −
;+ −
movf TABLAT,W ; Get back code+ −
btfss aa_antialias ; Antialiased font ?+ −
bra aa_decode_13 ; NO: 1bit case+ −
+ −
; Asymetry test: 1xx code is another case for 1bit color.+ −
; This have to be done before inverse video, because+ −
; of the asymetric processing !+ −
bn aa_decode_13 ; decode as not-aa+ −
+ −
; Manage 000 special case too:+ −
andlw 0xE0 ; Select color bits+ −
bz aa_decode_13 ; That's a 000 !+ −
+ −
; Apply reverse video, in a reversed way+ −
btfss win_invert,0 ; Inverse video mode ?+ −
sublw 0x80+ −
+ −
; Move the two bits to aa_color_half and aa_color_quarter:+ −
swapf WREG ; --> 0000.0LL0 byte+ −
iorlw b'001' ; We are in AA mode, don't forget it !+ −
movwf aa_flags ; save that to aa_color_(half/quad)/AA flags.+ −
+ −
;---- 2 bit x RGB(16bits) computation --------------------------------+ −
clrf PRODL ; We will accumulate result here...+ −
clrf PRODH+ −
+ −
; Take color div 2 into aa_temp. Max red = 15/31+ −
rrcf win_color1,W,BANKED ; xRRRRxGG+ −
andlw b'01111011' ; 0RRRR0GG (don't change C)+ −
movwf aa_temp+0+ −
rrcf win_color2,W,BANKED ; GGGxBBBB+ −
andlw b'11101111' ; GGG0BBBB+ −
movwf aa_temp+1+ −
+ −
btfss aa_color_half+ −
bra aa_decode_12+ −
+ −
movff aa_temp+0,PRODH ; Add color/2 if bit set.+ −
movff aa_temp+1,PRODL ; TFT is big endian, so swap here.+ −
aa_decode_12:+ −
btfss aa_color_quart+ −
bra aa_decode_3+ −
+ −
; Divide it once again by 2. Max red = 7/31.+ −
rrcf aa_temp+0,W ; xxRRRxxG+ −
andlw b'00111001' ; 00RRR00G (don't change C)+ −
movwf aa_temp+0+ −
rrcf aa_temp+1,W ; GGGxxBBB+ −
andlw b'11100111' ; GGG00BBB+ −
movwf aa_temp+1+ −
+ −
movf aa_temp+1,W ; Add color/4+ −
addwf PRODL,F ; NOTE: 7/31+15/31=22/31,+ −
movf aa_temp+0,W ; hence composants won't overlap.+ −
addwfc PRODH,F ; In right order, to propagate carry.+ −
+ −
bra aa_decode_3 ; Done.+ −
+ −
; ---- Simple BLACK and WHITE cases ------------------------------+ −
aa_decode_13: ; Got a 1xx or a 000 code...+ −
btfsc win_invert,0 ; Inverse video mode ?+ −
xorlw 0x80 ; YES: invert levels.+ −
bn aa_decode_2 ; Then test high bit.+ −
+ −
; WHITE pixel (ie. full color)+ −
bsf tft_rs,0 ; RS_H ; Data+ −
movff win_color1,PORTA ; current draw color+ −
movff win_color2,PORTH ; (rem: TFT is big endian)+ −
bra aa_decode_4+ −
+ −
aa_decode_2:+ −
bsf tft_rs,0 ; RS_H ; Data+ −
clrf PORTA ; BLACK pixel+ −
clrf PORTH+ −
bra aa_decode_4+ −
+ −
aa_decode_3:+ −
bsf tft_rs,0 ; RS_H ; Data+ −
movff PRODH,PORTA ; Move high byte to PORTA+ −
movff PRODL,PORTH ; Move low byte to PORTH+ −
aa_decode_4:+ −
;---- PIXEL WRITE LOOP -----------------------------------------------+ −
bcf tft_nwr,0 ; WR_L+ −
bsf tft_nwr,0 ; WR_H ; Tick+ −
+ −
decf aa_bitlen,F+ −
bnz aa_decode_4+ −
+ −
;---- BYTE-CODE LOOP -------------------------------------------------+ −
; Are we done ?+ −
movf TBLPTRL,W ; Compare TBLPTR to aa_end+ −
cpfseq aa_end+0+ −
bra aa_decode_1 ; Loop if LOW is different+ −
movf TBLPTRH,W+ −
cpfseq aa_end+1 ; Loop to if HIGH is different+ −
bra aa_decode_1+ −
+ −
return+ −
+ −
;------------------------------------------------------------------------------+ −
; Setup pointers for a char:+ −
; Inputs : buffer : string to print (SHOULD BE NULL TERMINATED)+ −
; Output : TFT commands on port D + clocks.+ −
; + −
global aa_wordprocessor ; Callable from C-code.+ −
aa_wordprocessor:+ −
banksel win_font ; Bank1, just to be sure.+ −
rcall aa_string_width ; Set win_height, compute win_width+ −
call TFT_box_write ; Use that for the box.+ −
+ −
; Restart the loop for each char to print+ −
lfsr FSR2, buffer ; FSR2 pointer to start of string.+ −
+ −
; DATA bloc commande:+ −
Index_out 0x22+ −
+ −
aa_wordprocessor_1:+ −
movf POSTINC2,W ; WREG = *FSR2+++ −
bz aa_wordprocessor_99 ; Exit if null byte encountered.+ −
+ −
rcall aa_char_setup ; setup aa_start / aa_end+ −
rcall aa_decode_char ; write pixels to screen+ −
bra aa_wordprocessor_1 ; and loop.+ −
+ −
aa_wordprocessor_99:+ −
; END of bloc commande+ −
Index_out 0x00+ −
+ −
return+ −
END+ −