Quick propeller font questions

I'm trying to work out how the propeller font gets read.
I believe this object uses the internal font http://obex.parallax.com/objects/67/
Reading through the code, I can't seem to see where the font gets read. Ascii bytes get moved to a screen buffer, and longs get moved out to the display, and somewhere in there the ascii byte must be translated to font pixels.
I gather the font is stored in internal rom so the code that reads this may only be one or two lines using a jump table based on the ascii value which I suspect is why it is hard to spot.
Another pair of eyes would be most appreciated here!
I believe this object uses the internal font http://obex.parallax.com/objects/67/
Reading through the code, I can't seem to see where the font gets read. Ascii bytes get moved to a screen buffer, and longs get moved out to the display, and somewhere in there the ascii byte must be translated to font pixels.
I gather the font is stored in internal rom so the code that reads this may only be one or two lines using a jump table based on the ascii value which I suspect is why it is hard to spot.
Another pair of eyes would be most appreciated here!
Comments
screen[row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE
Yes there is something clever going on there.
Hmm - screen is a word array rows*cols so that is 40x13*2 bytes. Is that enough to contain the bitmap for the font though? (16 longs per char). Or does that line above now contain an "address" to the bitmap in rom?
I'm working on a little bit of spin code to get the font bitmap out of rom and into an array so I can manipulate the bits (maybe resize the font by averaging the bits etc).
Addit: Do'h *hits head*
It probably is something simple like
address := $8000 myvalue :=long[@address]
and then (reading p32 of the manual) - undo the interleaving.
CON _clkmode = XTAL1|PLL16X _xinfreq = 5_000_000 OBJ serial: "FullDuplexSerial" PUB null : n serial.start(31, 30, %0000, 115200) waitcnt(clkfreq*3 + cnt) repeat serial.tx(0) print(n++) serial.rx PRI print(ch) : n | addr ch &= $FF repeat n from 0 to 31 addr := @long[$8000 + 128 * (ch >> 1)][n] serial.hex(addr, 8) serial.tx(" ") print_line(long[addr], ch) PRI print_line(pattern, ch) : n pattern >>= ch & 1 repeat n from 0 to 15 serial.tx(lookupz(pattern & 1: " ", "#")) pattern >>= 2 serial.tx(13) DAT
Part of the word is left-shifted by 6 in the TV.spin source.
FONT_ROM_ADDRESS = $8000 VAR long BackgroundColor,ActiveColor, ActiveTextColor, InactiveTextColor, Row, Col, RowBorder,ColBorder, WindowX1, WindowX2, WindowY1, WindowY2 long ScreenBuffer PUB WriteActiveCr(Character, PosR, PosC, RBorder, CBorder, BgC, TxC) | characterpointer, odd_even, bitpatern[32], idx, pxlidx, lcdidx, pxlidxdcd, x1, y1, x2, y2 odd_even := character & $0001 characterpointer := character & $fffe characterpointer >>= 1 characterpointer *= 32 repeat idx from RBorder to 31 - RBorder bitpatern[idx] := long[FONT_ROM_ADDRESS][characterpointer + idx] ' this is the line that reads longs off the eprom Row := PosR Col := PosC RowBorder := RBorder ColBorder := CBorder BackgroundColor := BgC ActiveTextColor := Txc y1 := PosC + CBorder y2 := (PosC + 15) - CBorder x1 := PosR + RBorder x2 := (PosR + 31) - RBorder SetWindow(x1, y1, x2, y2) SetGAddress(x1,y1) repeat idx from RBorder to 31 - RBorder repeat pxlidx from odd_even + (CBorder*2) to (odd_even + 30) - (CBorder*2) step 2 pxlidxdcd := |< pxlidx if ((bitpatern[idx] & pxlidxdcd) == pxlidxdcd) Lcd_Write_Com(REG_RAMDATAWRITE) Lcd_Write_Data(TxC) else Lcd_Write_Com(REG_RAMDATAWRITE) Lcd_Write_Data(BgC) if (((Col + 16) > 319 ) and ((Row + 32) > 223)) Row := 0 Col := 0 elseif (((Col + 16) > 319 ) and ((Row + 32) < 223)) Row := Row + 32 Col := 0 else Col := Col + 16 return PUB SetWindow(x1, y1, x2, y2) | HORIZONTALRAMADDRESSPOS WindowX1 := x1 WindowX2 := x2 WindowY1 := y1 WindowY2 := y2 HORIZONTALRAMADDRESSPOS := x1 + (x2 << 8) Lcd_Write_Com (REG_HORIZONTALRAMADDRESSPOS) Lcd_Write_Data(HORIZONTALRAMADDRESSPOS) Lcd_Write_Com (REG_VERTICALRAMADDRESSSTART) Lcd_Write_Data(y1) Lcd_Write_Com (REG_VERTICALRAMADDRESSEND) Lcd_Write_Data(y2) PUB SetGAddress(x,y) Lcd_Write_Com (REG_SETGDDRxADDRESSCOUNTER) ''max %1111_1111, $FF Lcd_Write_Data(x) Lcd_Write_Com (REG_SETGDDRyADDRESSCOUNTER) ''max %1_0011_1111, $13f Lcd_Write_Data(y)
I'm sure there is a better way to do this, but this is what I was able to get working. The prop font is stored in ram starting @ address $8000. Characters are encoded in pairs, with bits30,28,26,24,22,20,18,16,14,12,10,8,6,4,2,0 representing character 0 and bits 31,29,27,25,232,21,19,17,15,13,11,9,7,5,3,1 represent character 1. Each character pair is encoded in 32 longs. This makes each character 16 x 32. I hope this helps. I thing I've got it figured out pretty well. Let me know if you need more info. I am converting this stuff to asm, so i will have that for you later if you want.*edit* BTW. The characters are encoded in ascii, so reading them is real easy. RomAddress+ (character * 32 The propeller tool has a handy font reference.
I think most drivers use 4 color mode, but back-ground and 2 other colors are the same,
you would not have to un-interleave the fonts by using this trick.
But in my VGA font test I do un-interleave the font, the source code is in description.
Font test:
http://youtu.be/dtahz8WwBm0
Smooth scroller:
http://youtu.be/dZZMfN2loAg
screen[row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE
($200+(high 7-bits of c)) << 5 = the address of the character pair.
(color << 1 + (low bit of c)) << 10 = the word portion that selects color for the tile. Color selection is used to choose the high-bit of each pair of bits in the word, or the low bit.
Yes this is for the ILI9325 display. At the moment you need to read a font off the SD card in order to display anything. But you can't print a message like "SD card not found" because you need the font first. So even a simple display (320/16 = 20 chars wide) using the propeller font will be very helpful for startup debugging.
In a way, super fast speed is not so important so Spin will be fine. One you can print a message on the screen saying the SD card has been found, and that it is loading a font, then you can use that loaded font to display things faster using existing pasm.
So it is mainly just to display whether i) an SD card has been found and ii) whether certain essential files like icons and fonts have been found on that SD card.
PUB Propfont ' use propeller font in the rom for bootup messages when debugging sd cards curx := 0 ' set cursor to top left of screen (common variable) cury := 0 Propfont_string(string("Loading SD")) ' string to send Propfont_string(string("Loading Font")) PUB Propfont_string(stringptr) 'print at curx,cury repeat strsize(stringptr) ILI9325.draw(curx,cury,curx+15,cury+31) ' location to start drawing Propfont_out(byte[stringptr++]) curx +=16 curx := 0 cury += 32 ' new line at end of string PUB Propfont_out(ascii) | address,pixels address := $8000 + (ascii >> 1) << 7 ' get rom address repeat 32 ' 32 rows per character, split in two parts pixels := long[address] ' get rom font data pixels := pixels >> (ascii & 1) ' shift for odd characters repeat 16 ' 16 columns if pixels & 1 ILI9325.pixel(%00000111_11100000) ' foreground color RRRRRGGG_GGGBBBBB else ILI9325.pixel(%00000000_00000000) ' background color pixels := pixels >> 2 ' alternate pixels interleaved so shift 2 address += 4 'increment address by 4 bytes
Thanks ++ to everyone who contributed here - this is much appreciated.
Sorry.
{{ Fill romfont with ROM Font[32..127] decoded into separate 16x32 bitmaps }} VAR long romfont[144] PUB FillRomFont cognew(@fillromfont, @romfont) PUB GetChar(c) return @romfont[(c-32)<<4] DAT org 0 fillromfont mov romfaddr, par newchar xor thisline, thisline xor nextline, nextline xor lineidx, lineidx newline rdlong theline, fontline add fontline, #1 mov bitcnt, 16 nextbit shr theline, #1 wc rcr thisline, #1 shr theline, #1 wc rcr nextline, #1 djnz bitcnt, #nextbit rdlong theline, fontline add fontline, #1 mov bitcnt, 16 nextbit2 shr theline, #1 wc rcr thisline, #1 shr theline, #1 wc rcr nextline, #1 djnz bitcnt, #nextbit2 wrlong thisline, romfaddr add romfaddr, 16 wrlong nextline, romfaddr sub romfaddr, 15 djnz lineidx, #newline ' Starting about here is incomplete sub romfaddr, jmp newchar fontline long $8000 ' Address of input for current line bitcnt res 1 ' How many bits to pull from each line theline res 1 ' Buffer for current fontline lineidx res 1 ' Current line number romfaddr res 1 ' Address of output for current line thisline res 1 ' Line of this char nextline res 1 ' Line of next char
Can someone else finish it?クロネコさん、ありがとう。
VAR long command, cog word font[32] PUB null '' This is not a top level object. PUB GetChar(c) ifnot cog ifnot cog := cognew(@fillchar, @command) + 1 ' start cog on demand abort command := $200|c.byte{0} ' query bitmap repeat ' | while command ' wait for completion return @font{0} DAT org 0 fillchar add addr, par ' @font[0] :idle rdlong char, par wz if_z jmp #$-1 mov temp, char ' where to begin shr temp, #1 ' 2 chars/long shl temp, #7 ' 32 longs/char test char, #1 wc muxnc shft, #1 ' even/odd mov lcnt, #32 ' 32 rows :loop rdlong char, temp ' read line from ROM shl char, shft ' adjust for even/odd shl char, #2 wc rcl line, #1 ' bit 15 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 12 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 8 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 4 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 shl char, #2 wc rcl line, #1 ' bit 0 wrword line, addr ' update hub array add addr, #2 ' advance dst add temp, #4 ' advance src djnz lcnt, #:loop ' repeat sub addr, #64 ' rewind wrlong zero, par jmp #:idle ' initialised data and/or presets addr long 8 shft long 0 ' uninitialised data and/or temporaries temp res 1 char res 1 lcnt res 1 line res 1 fit CON zero = $1F0 ' par DAT