Shop OBEX P1 Docs P2 Docs Learn Events
Pulling my hair out... — Parallax Forums

Pulling my hair out...

KaosKiddKaosKidd Posts: 296
edited 2013-05-09 11:15 in Propeller 1
For some one reason, of which I can't figure out, I can't seem to get into the bits of a number correctly...
In the attached archive, I've tried two methods to get the bits (I need them from hi to lo) in correct order, but no luck! While testing, I tried setting it up so I can mirror the CharData bin output, to make it easier, but no matter what direction I go with the loops, I'm getting junk and I can't figure it out. The variable CharData is correct, it is returning the correct HEX and BIN values, but the loops below it, where I start to get into the bit's of the data, it's failing; returning wrong values.

PUB Start | MsgLen, MsgIndex, CharData, BitIndex 
  vga.start(16)                                                             'Start the VGA driver  (32x14)
  MsgLen := STRSIZE(@Message) - 1                                           'Get the length of the message
  repeat MsgIndex from 0 to MsgLen                                          'For each Char in the message
    vga.out(BYTE[@Message][MsgIndex])                                       'output it to the vga screen (Visual Check of the message)
  vga.out($0D)                                                              'CRLF to move to next line
    
  repeat MsgIndex from 0 to MsgLen                                          'For each char in the message
     CharData := WORD[@ChrSet][(BYTE[@Message][MsgIndex] - 32) * 12]        'Using Message[MsgIndex] as index into CharSet, get this char's 1st word
     vga.bin(CharData,16)                                                   'Print the bin so we can see what we are looking for
     vga.out($20)                                                           'and a space
     vga.hex(CharData,4)                                                    'and the hex value (verifies correct value from ChrSet data)
     vga.out($0d)                                                           'CRLF to the next line
    
     repeat BitIndex from 15 to 0                                           'For each bit in CharData
       vga.bin(CharData[BitIndex],1)                                        'output it's value (should mirror BIN above, but nope...

     vga.out($0d)                                                           'Ok, reset for another line
   
     repeat BitIndex from 15 to 0                                           'Try 2, for each bit in CharData
       if CharData[BitIndex] == 0                                           'If it's a 0 then
          vga.out($4F)                                                      'output an O
       else                                                                 'Otherwise
          vga.out($58)                                                      'output an X

     vga.out($0d)                                                           'Reset for next Char

  vga.str(string("DONE"))                                                   'Printed to know we got this far and we're done


Please, someone save what's left of my hair and tell me what I am doing wrong here? IndirAddr - Archive [Date 2013.05.08 Time 11.19].zip
Additionally, if you see anything else that should be different, please share that too!

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-05-08 08:41
    CharData is not an array. It's a single long. When you write "CharData[BitIndex]", you're assuming that CharData is an array of longs. The special notation for accessing individual bits or sequences of bits in a long only applies to the special function registers. You could use that notation by using something like OUTB which exists as a register, but isn't connected to anything. Just use OUTB instead of CharData and the bit access notation will work.

    Alternatively, you could use "(CharData>>BitIndex)&1" instead of "CharData[BitIndex]".
  • KaosKiddKaosKidd Posts: 296
    edited 2013-05-08 09:13
    Mike Green wrote: »
    CharData is not an array. It's a single long. When you write "CharData[BitIndex]", you're assuming that CharData is an array of longs. The special notation for accessing individual bits or sequences of bits in a long only applies to the special function registers. You could use that notation by using something like OUTB which exists as a register, but isn't connected to anything. Just use OUTB instead of CharData and the bit access notation will work.

    Alternatively, you could use "(CharData>>BitIndex)&1" instead of "CharData[BitIndex]".

    The "(CharData>>BitIndex)&1" works like a Charm!!!
    So, I guess the lesson learned here is that I can't access the bits of a long like an array unless I use the bit shift operator >> and an index (BitIndex in this example). what is the & 1 for?
    And Thank you Mike!
  • Mike GreenMike Green Posts: 23,101
    edited 2013-05-08 09:17
    "what is the & 1 for?"

    That's an exercise for the reader (Think about it. Try a few examples).
  • KaosKiddKaosKidd Posts: 296
    edited 2013-05-08 10:08
    Duhhh...
    & 1 AND 1 thus if the bit is 1 & 1, return a 1, other wise 0 & 1 = 0 because both aren't 1...
    I knew that... really I did...

    :) Fred
  • KaosKiddKaosKidd Posts: 296
    edited 2013-05-08 12:07
    Ok, another one... if anyone who has the time:
    [FONT=Fixedsys]
      
      REPEAT Index FROM 5 TO 0
        OUTA[15] := Index >> 2 & 1
        OUTA[14] := Index >> 1 & 1
        OUTA[13] := Index >> 0 & 1
        OUTA[12] := (CharData >> BitIndex & 1)
        OUTA[11] := (CharData >> (BitIndex - 8) & 1)
        WAITCNT (NozzleDelay + CNT)
        OUTA[12..11]~
    
    [/FONT]
    

    Is there a better way of doing this? This works... but appears "clunky"... and I'm not the kind that does clunky.
    The ports P15 ~ P13 are connected to the address pins of a pair 74ls138's (the address pins are shared),
    Pin 12 is connected to the enable of one '138, Pin 13 is connected to the enable of the other '138.
    This is about the best that I could come up with... and I was wondering if there was a faster / better / prefered way.

    This code is the inner most loop of a nested 4 deep repeat set, and I'm trying to make sure it's about as tight as one can get without resulting to ASM.

    PS: Mike, you can see your solution right there... thanks!

    Again, thank you all.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-05-08 14:04
    OUTA[15..13] := Index
    OUTA[12] := CharData >> BitIndex ' Least significant byte of word
    OUTA[11] := CharData >> 8 >> BitIndex ' Most significant byte of word

    The "& 1" isn't needed because OUTA[x] is a single bit which effectively does the "& 1".

    I'm not sure if this does what you need since you haven't quite described anything more than pins 12 and 11 being tied to '138 enables. There may be some alternative way to construct CharData to begin with that would be more efficient here. It might be helpful to precompute the OUTA[12] and OUTA[11] bits in a variable in an outer loop so you just need to put "OUTA[12..11] := savedValue" here.
  • KaosKiddKaosKidd Posts: 296
    edited 2013-05-09 10:33
    Hi Mike:
    Well, what you have here works great. I'm already under the minimum WAITCNT time, so this works great!
    I guess this works because the OUTA starts at the right most bit (13 here), and works left one bit at a time, bit for bit, until it hits the left most bit (15 in this case), right?
    I've tested the heck out of it, and I can see the address's as expected, and I can only assume this is how it works.

    I'm up to the last task for this code, and that is making it so that it runs in a single cog, with a start and "PRINT" public routines. I know the code and DAT space is only 485 longs, under the max size for a cog, but converting this is going to be an exercise. Is there anything "special" I need to do to make sure the code and DAT are loaded into the cog?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-05-09 10:59
    The Spin interpreter does this all at once using shifts, ANDs and ORs, and REV to reverse the order of the bits if you write OUTA[13..15] instead. Read the Propeller Manual for details of this notation.

    I assume your code is in Spin rather than assembly language. If so, there's no 485 long limit on size since the cog actually contains the Spin interpreter, not the code you've written. Spin code and its data is always stored in hub memory which has 32K available. A COGNEW or COGINIT copies the Spin interpreter from ROM into a cog and starts it up with the supplied Spin code as an initial point. If you're writing assembly (PASM), the COGNEW or COGINIT copies the 496 long block of code to the cog instead. As far as the assembly code is concerned, hub memory looks like a special I/O device with special instructions (RDxxxx and WRxxxx) to access it.
  • KaosKiddKaosKidd Posts: 296
    edited 2013-05-09 11:15
    OH WOW...
    I never thought of it like that! That's SUPER cool news!!
    I just have to fit 100% of all my project code into 32K... :)

    Again, Thanks!
    Fred
    PS: I will do more reading!
Sign In or Register to comment.