Shop OBEX P1 Docs P2 Docs Learn Events
DATA @ not available in SX/B only PBASIC ? — Parallax Forums

DATA @ not available in SX/B only PBASIC ?

T&E EngineerT&E Engineer Posts: 1,396
edited 2007-10-09 22:22 in General Discussion
I am trying to convert a PBASIC program to SX/B. However, this program uses DATA addresses that doesn't appear to be in place for SX/B DATA statements.

Is there anyway around this?

PBASIC DATA statements:

CBLOCK CON 8· 'size in bytes of a character bitmap

DATA @· "1"*CBLOCK, 28,30,31,31,28,28,127,127·· '1
DATA @· "2"*CBLOCK, 30,63,51,56,28,14,127,127·· '2
DATA @· "3"*CBLOCK, 62,127,99,120,56,99,127,62· '3

SX/B doesn't accept the @ in it's DATA syntax.

I have attached both the BS2px program and the SX-28 program for clarification.

Also see this link:

http://forums.parallax.com/showthread.php?p=681138

These programs were originally on an SX-28 to control the keypad and then it's keypad character was sent to a BS2px to display the character on an 8x8 LED matrix via SPI (and it's controller board).

Hopefully there is a work around that I'm just not seeing at the moment. Perhaps the obsolete ADDRESS command for SX/B ?

Comments

  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-10-08 05:05
    This definitely falls into the "no brainer" category -- that program is putting things on eight-byte boundaries and each block is eight bytes. Just create a label for the start of the table, then calculate an offset into the table by the character you want to retrieve. The Robolympic badge code does this.
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-10-08 10:15
    JonnyMac,

    Thanks for the information. So what I am understanding is that there is no DATA @ equivalent in SX/B and that the RobOymplics code does something similar. I was thinking of that too but thought I would ask about the DATA @ to·see if there was anything·similar to the original PBASIC code before I look at another way different making it more difficult to see.

    There are 3 types of "Robo" code. There was the original RobOlympics code - a year + back, then the newer RoboGames code then there was your latest·Badge code. Was·there any specific one you were refering?·I·think they all follow the same if not similar·offset process and if so·I think I'm able to follow the routines for characters in this.

    Would it be possible or·worthwhile·to write an SX/B·subroutine or procedure to do this (e.g. DATA @) or just·easier to use the offset DATA character process?

    Thanks.


    Post Edited (T&E Engineer) : 10/8/2007 11:40:51 AM GMT
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-10-08 12:34
    Looking at the original BS2 PBASIC DATA @ statements:

    PBASIC DATA statements:

    CBLOCK CON 8· 'size in bytes of a character bitmap

    DATA @· "1"*CBLOCK, 28,30,31,31,28,28,127,127·· '1
    DATA @· "2"*CBLOCK, 30,63,51,56,28,14,127,127·· '2
    DATA @· "3"*CBLOCK, 62,127,99,120,56,99,127,62· '3


    (written by Zoot)

    What is confusing to me is if DATA @ "1"*CBLOCK is an address meaning the DATA statement starts at address 49 decimal (which is for ascii character "1") and this gets multiplied by 8 so that means the address starts at 49 * 8 = 392. Why this address? Am I understanding this correctly? This means the next 8 bytes are at addresses 392, 393, 394, 395, 396, 397, 398, 399.

    Ok what about "2"*8 means that it would start at 50*8 = 400, etc..
  • ZootZoot Posts: 2,227
    edited 2007-10-08 14:12
    In my particular applications where I need a full set of ASCII character bitmaps, I map the characters in EEPROM by their decimal values, taking into acount how many bytes of data I need for each character.

    Say I need 8 bytes of data for each character (the bitmap). The ASCII value for "A" is 65 (the 65th character). If I need 8 bytes per character, and I build up the data in order, then I would expect to find my "A" data at 8x65 bytes or the 8 bytes starting at 520.

    Why do this? I don't have to do any lookups or parsing of an ASCII character to find the address for that data. By definition the data for "A" will be at "A"*8. The data for "C" will be at "C"*8.

    Note that the quotes around the letter ("F"*8) will give me the numerical value of "F" from the ascii map.

    Note that the mostly non-visual characters preceding "0" in the ASCII map may not be necessary, which would save space.

    Also you don't need DATA @ per se, I just use that on Stamp projects because it lets me build up my character bitmaps without worrying about order, or blanks. You could just easily pack the data in in order.

    I would still define the block size as a constant for retrieval purposes, though. E.g. you could just do:

    DATA %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 'first character bitmap
    DATA %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 '2nd character bitmap
    DATA %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 '3rd character bitmap
    DATA %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000 '4th character bitmap
    And retrieve them in block sized chunks as long as you know which is the first character.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-10-08 15:35
    T&E,

    You would be well-served to simply learn SX/B as it is, and stop trying to copy-and-paste BS2 programs into SX/B -- it was never designed that way. It similar to PBASIC, but is not code compatible in most cases. With the differences come an enormous amount of power that you just can't get with a BASIC Stamp. It's a little more effort, but it's worth it.

    Now, let's say you want to start the character maps -- each with eight bytes -- at ASCII 32 (space char). Perhaps the start of the DATA statements is:

    Char_Maps:
      DATA  $00, $00, $00, $00, $00, $00, $00, $00        ' space
    



    You can the offset (from the start of the table) to the character data with a bit of code:

    offset = myChar - 32
    offset = offset << 3
    



    And now a simple loop can be used to read the character values:

    Read_Char_Data:
      FOR idx = 0 to 7
        READINC Char_Maps + offset, tmpB1
        ' tmpB1 holds character byte -- do something with it
      NEXT
    

    Post Edited (JonnyMac) : 10/8/2007 3:45:11 PM GMT
  • ZootZoot Posts: 2,227
    edited 2007-10-08 16:39
    T&E --

    Yeah, what JonnyMac said. Note his subtraction of 32 from the offset -- this skips you past the first 32 chars of the ASCII table, which are non-alphanumeric characters like line feed, etc. Then instead of multiplying the ASCII value by the block size (as I did in the Pbasic code) he shifts the offset left 3 bits, *which is the same as multiplying by 8*. Generally in any assembly based code (which is really what SX/B is) shifting right/left is very very very compact and fast way to divide/multiply by powers of 2.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-08 16:45
    Thanks guys. I will look through this tonight and try to come up with something.

    One thing that is not clear is: How does it know by Char_maps: that it is refering to the space? Is that what MyChar is? Where does that come in to play?

    Thanks again.


    Post Edited (T&E Engineer) : 10/8/2007 4:59:16 PM GMT
  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-10-08 19:52
    Yes; put the character ASCII code into myChar, then proceed from there. You could fold the whole thing into a subroutine where you pass the table address and the character:

    ' Use: Load_Char table_name, char_code
    ' -- moves character data from table into buf()
    
    SUB Load_Char:
      tmpW1 = __WPARAM12                            ' table address
      tmpW2 = __PARAM3                              ' character (ASCII code)
      
      tmpW2 = tmpW2 - 32                            ' z-offset to " "
      tmpW2 = tmpW2_LSB << 3                        ' x 8
      tmpW1 = tmpW1 + tmpW2                         ' add offset to address
    
      FOR tmpB2 = 0 TO 7
        READINC tmpW1, tmpB1
        buf(tmpB2) = tmpB1
      NEXT
      ENDSUB
    



    To use this you might do something like:

    Load_Char Char_Maps, "*"
    



    Please -- these are just examples; don't plug them in and expect miracles without a bit of massaging on your end.

    Post Edited (JonnyMac) : 10/8/2007 8:31:07 PM GMT
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-08 20:26
    Thanks JonnyMac.

    Isn't tmpB1 = tmpB1 << 8 suposed to be tmpB1 = tmpB1 << 3 as you showed before?

    Also if the table starts with:

    Char_Maps:
    ··DATA··$00,·$00,·$00,·$00,·$00,·$00,·$00,·$00········'·space

    does that mean that I have to get every character from space to ascii 127 ?

    e.g.

    Char_Maps:
    ··DATA··$00,·$00,·$00,·$00,·$00,·$00,·$00,·$00········'·space (32)

    · DATA .......(my char codes here)··························' ! (33)

    · DATA .......(my char codes here)····················· ··· ' " (34)

    · DATA .......(my char codes here)························· ' # (35)

    · :

    · DATA .......(my char codes here)························· ' DEL (127)

    How does it know that the second DATA line refers to a ! and the forth DATA line refers to a # ? I'm just trying to understand this methodology. What if I only want to use Upper and Lower case alphabet letters and numbers and not all 127 - 32 ?

    Thank you for you help.
  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-10-08 20:31
    I fixed the example -- tmpB1 really needs to be tmpW2 so that you have enough room for the whole ASCII set.

    You don't have to map the entire ASCII set, but if you don't you'll have to accommodate for holes in the data.

    If all of your character maps are eight bytes and you start with ASCII 32 (at zero), then it's a matter of simple math ((code - 32) x 8 = offset from start of table) -- you just need to ensure that each map is only eight bytes and that you put them in order by their ASCII code.

    Post Edited (JonnyMac) : 10/8/2007 9:55:52 PM GMT
  • ZootZoot Posts: 2,227
    edited 2007-10-08 20:44
    Somebody said...
    How does it know that the second DATA line refers to a ! and the forth DATA line refers to a # ?

    Put your data down, in order, following the ASCII chart. If the character is " " (space) in ASCII that is the number 32. It's the same thing no matter what. So basically, regardless of platform, or language, you want to grab your bitmaps in 8 byte chunks, using the ALREADY NUMBERED ASCII table.

    E.g., "R" is 82. If I have 8 bytes per character, I better see my "R" data at 82*8 MINUS (32*8) because I'm not making bitmaps for all those other characters.

    On the high side, past 127, you can just error check your character input if you don't want to do all the characters.e.g.

    IF char > 127 THEN
    char = 127
    ENDIF

    If you want to use all "upper" case, you can put the ASCII input through a similar filter -- if the char in is 97-122 (a-z) then SUBTRACT 32 from char, which would change 97 to 65 ("a" to "A"). Check over the ASCII table and you'll see it's pretty well organized into chunks of characters that let you filter and process character and text input.

    I think what might have thrown you in my (original) Stamp code is that if I write:

    x = "A" * 10

    The COMPILER interprets the "A" as the NUMERIC DECIMAL ascii value (well, hex to binary, actually) -- it just saves having to actually open a book and look at the ascii table. Like:

    addr = char - " " ' should equal zero if char = 32 = " "
    addr = addr << 3 'or whatever shift/multiply you need to do based on bytes per bitmap

    The above creates a table address from my char (as a decimal ascii value) and the offset to the space char. It happens that a space char is 32, but they are essentially interchangeable:

    " " = " "
    " " = 32
    " " = $20
    " " = %00100000

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-09 01:49
    I have it working 99% correct !! (see attached) - Same as SX-28 and BS2 combo except now all one 1 SX-28 (no BS2).

    http://forums.parallax.com/showthread.php?p=681138

    There is only 1 slight issue with RANDOM to create a number between 1 and 7.

    The working PBASIC BS2 code is:

    Rand_no·· VAR·· Nib
    seed······· VAR·· Word

    ·RANDOM seed
    ·Rand_no = seed // 7 + 1
    ·color = Rand_no


    The sort of working SX/B code is:

    ·tmpB1··VAR·Byte

    ·tmpB2··VAR·Byte

    ·color··· ·VAR·· ·Byte

    RANDOM tmpB1···· '
    tmpB2 = tmpB1 // 7
    tmpB2 = tmpB2 + 1
    color = tmpB2

    I had to use Byte variable for tmpB1 because the statement "tmpB2 = tmpW1 // 7" was not valid in SX/B.

    I also could not use any more·BYTE or·WORD variables (e.g. Rand_no and seed) as I would run out of RAM so I used the temp byte variables.



    What happens is that the colors are random for the numbers (0-9) and letters (A-F)·but I don't think random enough (e.g. 1 and 2·are green, 3 is blue, 4 is red, 5 & 6 are blue, 7 is light blue, 8 & 9·& 0 are blue,·A & B·are green, C·is·light pink, D & E are green and F is hot pink.

    The code for PBASIC is always random colors depending on how long you held down on the button. The code for SX/B is pretty much the same colors as described above all the time. Occassionally it will change but rarely.

    Any last help? It is very close to the PBASIC version.
  • ZootZoot Posts: 2,227
    edited 2007-10-09 01:53
    If you are using a temp variable for the random seed, you may not get good randomness as the pseudo randomizer will use the value of the temp which will be whatever it was last used for. If it was always last used as a parameter for subroutine, or some kind of IO byte, it may always have the same one or two numbers in it before you randomize again. Why not just use color itself as the "random" seed?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-09 14:31
    Thanks Zoot. I will try something like this tonight:

    RANDOM·Color····
    tmpB1 =·Color // 7
    tmpB1 = tmpB1 + 1
    Color = tmpB1
  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-10-09 14:38
    You'll get better randomness if you'll just keep a spare byte variable, perhaps called "seed", and maintain it through the program. This gives you 256 choices each time through; the code above gives you just eight.
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-09 14:49
    I was running out of variable RAM space so I had to get rid of tmpB1 and tmpB2 and make them into temp1 and temp2. See attached. It compiles ok.

    I also changed the RANDOM routine as follows:

    seed···· VAR···· Byte

    color···· VAR···· Byte

    :

    RANDOM seed
    color = seed // 7
    color·=·color + 1

    color = color MAX 7

    I will try this out tonight.

    Post Edited (T&E Engineer) : 10/9/2007 2:56:55 PM GMT
  • JonnyMacJonnyMac Posts: 9,216
    edited 2007-10-09 15:33
    The MAX statement is a [noparse][[/noparse]small] waste of code as the // operator will never return a value greater than the divisor minus one; in your code the divisor is 7 so the result of // will always be 0..6.
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-09 21:18
    100% complete! - Thanks JonnyMac.

    That did it. It is now virtually identical in operation to the BS2+SX28 combo version:
    http://forums.parallax.com/showthread.php?p=681138

    Amazed at all the colors flashing by holding down on a button - by simply changing a variable with 8 choices to 256 choices of random possiblities - to the 7 colors this display with controller has.

    Sparkfun has more of them in stock today too:

    http://www.sparkfun.com/commerce/product_info.php?products_id=760

    All controlled with 1 SX-28 and a·$5 mini 16 button·keypad:

    http://www.futurlec.com/Mini_Keypad.shtml
    http://www.futurlec.com/Connectors/IDCC10.shtml

    Thanks to all. NEW PROJECT TIME...Perhaps figure out how to make it marquee scroll to the left/right.
  • ZootZoot Posts: 2,227
    edited 2007-10-09 22:16
    Have you checked on JonnyMac's code for the scrolling Robo Medal: www.parallax.com/dl/src/prod/Badge.SXB

    It's pretty nifty. He also uses an approach similar to my long Stamp code -- he keeps the pixel data in RAM (in buffers) so that it can be painted, shifted right/left, etc.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-10-09 22:22
    Yes I saw that. The problem is that the controller needs to only have 64 bytes shifted in and no more to display something. If I start shifting more than the controller displays weird things on it.

    BTW: As I was running my program the 8x8 RGB controller board may have went bad. It does not display anything now. Upon bootup it does scroll (as a default within the controllers programming) LEDs up and down for a second as·a test (as it should) so I know the LEDs are fine just the controller card is bad. Wow thats strange. I will have to contact Sparkfun to see if anything can be done.


    BTW2: I found out the problem with the display/controller. It was a cable that I made had a loose connections. What works good are (2) 3-pin cables for serial LCDs from Parallax. Glad to hear it is working now.

    Post Edited (T&E Engineer) : 10/10/2007 1:02:38 AM GMT
Sign In or Register to comment.