Shop OBEX P1 Docs P2 Docs Learn Events
Internal character ROM — Parallax Forums

Internal character ROM

CobaltCobalt Posts: 31
edited 2006-10-24 20:29 in Propeller 1
I have a graphic LCD that I've been able to interface to, but it doesn't have a built-in character table. No problem since the Propeller does! I want to be able to write from the charater map in the Prop's ROM to the LCD, but I have one little problem:
I don't know how to get the data from the ROM sad.gif
I'm sure it is just very simple code, but I would like some help on how to access the ROM to send it to my LCD. Thanks.

Comments

  • Graham StablerGraham Stabler Posts: 2,510
    edited 2006-10-23 12:12
    Check out page 236 of the manual, the long function can be used to get a long from a given address, the addresses are on page 32

    Graham
  • CobaltCobalt Posts: 31
    edited 2006-10-23 14:58
    Thanks for that bit of into, I didn't know that 'long' would work that way in a PUB/PRI
    Let me see if I am reading this right:

    VAR
    long temp

    PUB Main
    temp := long[noparse][[/noparse]$8000]

    This would put the long from $8000 (the start of the character ROM) into the long var "charlong" I take it? (I ask because I'm at school still, not in front of my stuff) I also assume that when I get a long from the ROM, it is a row of data from left to right... am I correct at this too?

    Also, to clairify the character ROM design, the characters are kind of 'meshed' together into a 32x32 bit square (4 longs x 32)?
    I read the section at the start of the manual (p. 32) with the character map, but it really didn't make 100% sence.

    I need a "Propeller for Dummies" book!
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2006-10-23 15:19
    yes long is a variable type and a function.

    What you have written looks right to me but it would provide you with the first row of the first two characters, each character pair is made up of 32 longs (which are 32bit each).

    The long you read is just a number so its 01010101_01010101_01010101_01010101 or something

    It says the left most pixel is the lowest bit so I assume that means that the lsb is the top left pixel of the first character (which is why the last diagram shows it flipped). The next bit is the top left of the other character and so it goes on. Considering the letters shown it goes:

          (top right pixel) BABABABABABABABABABABABABABABABA(top left pixel,lsb)
    Next long, next row
                            BABABABABABABABABABABABABABABABA
    Next long, next row
                            BABABABABABABABABABABABABABABABA
         .
         .
         .
      32 longs later
            (bottom right)  BABABABABABABABABABABABABABABABA (bottom left, lsb)
    
    



    I think the wording of the manual tends to be correct rather than helpful.

    Graham
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-10-23 15:25
    Cobalt,
    ·
    There is probably an easier way to do this, but here is·the formula·I used to extract the 'meshed' ROM data in·the VGA graphics driver.
    ·
    The Character table is located at $8000
    ·
    Y ranges from 0 to 31
    X·ranges from 0 to 15 and is represented within a word but is interdigitated as a long (see below)
    chr is the ASCII character value
    ·
    ·
    The formula that I used is as follows....
    ·
    X = long[noparse][[/noparse] $8000 + y*4·+ chr*$40 - (chr & 1)*$40 ]
    ···
    convert·interdigitated long to non-interdigitated word:
    ···
    X_Data := 0
    MaskBit := |< (chr & 1)+30 
    repeat 15 '(<--This may need to be 16)
      X_Bit := (X & MaskBit)/ MaskBit
      X_Data := X_Data << 1 | X_Bit 
      MaskBit := MaskBit >> 2
    

    X_Data returnes a non-interdigitated word value
    ·
    ·
    ·
    ·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 10/23/2006 7:01:53 PM GMT
  • CobaltCobalt Posts: 31
    edited 2006-10-23 18:22
    Great stuff, I'm going to throw it at my Propeller as soon as I get home, thanks a million!
  • CobaltCobalt Posts: 31
    edited 2006-10-24 14:28
    Beau Schwabe said...

    Y ranges from 0 to 31
    X ranges from 0 to 15 and is represented within a word but is interdigitated as a long (see below)
    chr is the ASCII character value

    The formula that I used is as follows....
    X = long[noparse][[/noparse] $8000 + y*4 + chr*$40 - (chr & 1)*$40 ]
    convert interdigitated long to non-interdigitated word:

    X_Data := 0
    MaskBit := |< (chr & 1)+30
    repeat 15 '(<--This may need to be 16)
    X_Bit := (X & MaskBit)/ MaskBit
    X_Data := X_Data << 1 | X_Bit
    MaskBit := MaskBit >> 2

    X_Data returnes a non-interdigitated word value

    Wow, ok, for starters I thank you for taking time to help me out on this, and I am really glad that you are trying. I have no doubt in my mind that this code works, but due to my lack of coding syntax abilities, I can honestly say that I understand about 70% of that.
    I can tell that there are multiple variables that need to be defined somehow, but I'm not sure which ones.
    X_Data, X_bit, MaskBit, X, and chr all ovbiously need to be delt with, and I know that 'chr' is the ASCII character I want, and that X_Data is the word value from the ROM. 'X' seems easy enough to get from the niffty little equation you provided. However, the X_bit and MaskBit both seem to just be temporary spots for the method. I want to be able to use this in its own PUB, such that I can call it as needed. I tried this, but it didn't seem to work out too well:

    VAR
        word   X_Data
        word   chr
        word   X
    
    PUB GetChr(chr, X) | MaskBit, X_Bit
        X_Data := 0
        MaskBit := |< (chr & 1)+30
        repeat 15 '(<--This may need to be 16)
            X_Bit := (X & MaskBit)/ MaskBit
            X_Data := X_Data << 1 | X_Bit
            MaskBit := MaskBit >> 2
    
    



    This way, I would just use 'chr' and 'X', and the GetChr method would modify X_Data to what I wanted. I'm not sure if this is a proper way of doing this, I'm quite certain that my code has wonderful errors!

    Also, if I wanted to read only the first or second byte of the X_Data word, what would be the proper command, would "X_Data.byte[noparse][[/noparse]x]" work? (x = the byte)
    Thank you!
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-10-24 17:45
    Cobalt,

    You don't need to define any variables outside of the PUB.· By stating the variables within the PUB in this way...
    PUB GetChr(chr, Y) | MaskBit, X_Bit, X
    


    ...you are already defining chr, Y, MaskBit, X_Bit, and X·as variables.·

    Here is·"tested" code that is a bit more compact.
    PUB GetChr(Chr, Y) | MaskBit, X_Bit,X
        X := (long[noparse][[/noparse]$8000 + Y*4 + Chr*64 - (Chr & 1)*64])<<(1-(Chr & 1))
        Result~
        MaskBit := |<31
        repeat 16
          Result += X & MaskBit
          Result >>= 1
          MaskBit >>= 2
    

    When you call GetChr, you only need to specify the Y location (0-31) and the Character.·
    To get the upper BYTE...
    ByteVar := (GetChr(Chr,Y)>>8) & $FF
    

    To get the lower BYTE...
    ByteVar := GetChr(Chr,Y) & $FF
    

    ..In both cases, you only need to define ByteVar.





    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 10/24/2006 5:55:26 PM GMT
  • CobaltCobalt Posts: 31
    edited 2006-10-24 20:29
    Excellent, that makes things a lot more clear!
    I'll try and post some results later tonight.
    Again, thank you very much!
Sign In or Register to comment.