Shop OBEX P1 Docs P2 Docs Learn Events
Addressing bytes of a buffer referenced by bits from another byte in the buffer — Parallax Forums

Addressing bytes of a buffer referenced by bits from another byte in the buffer

Sounds like a crazy title but didn't know how else to write it.

I have a 12 byte buffer. In that buffer are the following:

02 00 01 05 02 00 07 01 02 05 14 14 indexed from 0 to 11 starting at the left end.

My question is how can I point to bytes 7 through 11 (01 02 05 14 14) by virtue of the 2 bytes 5 & 6 (00 07)?

I know that in bit form the 00 07 would be 0000 0111. So how do I reference byte 7 (01) from bit 0 of byte 6? Then bit 1 of byte 6 represents byte 8 and so on.

Maybe said another way- my "mask" from bytes 5 & 6 somehow references bytes 7, 8 & 9.

Sorry for my ignorance here. But thanks for any help.

Don

Comments

  • What do you mean by "reference" ... and what programming language do you plan to use?

    In most cases, you'd fetch the word at bytes 5 and 6 ... probably one byte at a time because it's byte-aligned. Now you have the mask. Your starting address for referencing is 7. Do you want to pick up the bytes selected by the mask and shift them into a 32-bit word? There's not yet enough information about what you want to do.
  • Don MDon M Posts: 1,652
    In spin. I'm having trouble trying to intelligently ask this...

    Since bytes 5 & 6 equal 00 07 (or 0000 0111) I'd like to be able to point to bytes 7, 8 & 9. Similarly if bytes 5 & 6 were 00 04 (0000 0100) then I'd want to point to byte 9. Make sense?
  • Mike GreenMike Green Posts: 23,101
    edited 2016-06-29 02:39
    What do you mean by point? Produce the address of the first byte referenced ... or what?
    mask := (buffer[ 6 ] << 8) | buffer[ 5 ]   ' gets the mask
    pointer := @buffer[ 7 ]   ' initial pointer
    repeat 5
       if mask & 1 == 1   ' first 1 bit ... quit
          quit
       mask >>= 1   ' shift mask
       pointer++   ' advance pointer
    ' Note: if mask is initially zero, pointer will be left at @buffer[ 12 ]
    ' This could be written with some other default exit value
    
  • kwinnkwinn Posts: 8,697
    Do you mean that you want one bit of the 16 bits in bytes 7 and 8 to select one of the 12 bytes in the buffer if it is set? If so you need to specify how the bits are aligned to the bytes (lsbit to lsByte?).
  • Don MDon M Posts: 1,652
    edited 2016-06-29 14:10
    Ok so here's a little more explanation and a graphical representation attached.

    This is a 23 byte message received from a coin accepter / changer during it's initialization and setup. I'll explain what each area of the message represents.


    1 is the MDB level at which the changer operates
    2 is the country currency code. 00 01 is USA
    3 is the scaling factor. In this case it's 5 or $0.05
    4 is the number of decimal points 2
    5 is the representation of coin tubes available to store coins. 16 maximum. 00 07 is this in binary -> MSB 0000 0000 0000 0111 LSB What this is saying is that there are 3 tubes in this device that will hold coins 1, 2 & 3 (or 3, 2 & 1 as you look at it)
    6 is the 16 coin channels and their hex value of each. Goes from LSB to MSB from coin 1 to coin 16 so the 01 means that channel 1 is worth 1 x the scaling factor which is a nickel. The next channel shows a 02 so that times the scaling factor equals a dime. The third is a 05 x scaling factor equals a quarter. The fourth and fifth are both 14H which is 20 decimal x scaling factor equals $1. The reason there are 2 channels the same value is for old type dollar coin and new.

    So where am I going with this. There is another message received that indicates the inventory in each coin tube. The message is 18 bytes long (max). First 2 bytes indicate which tube is full by way of a binary representation. 2 bytes = 16 bits = 16 coin channels. If one of the bits is set then that coin tube is reported as full. The next 16 bytes report (in HEX) the number of coins in each tube. Different manufacturers of changers report in different ways. By that I mean 1 manufacturer might report the whole 18 byte string even though they only accept 5 coins whereas another may only report the first 2 bytes (mandatory) plus only the number of bytes that represent the number of different coins that it will accept. So in the case of my example above it only accepts nickel, dime, quarter, dollar1 and dollar2 so it's message is only 7 bytes long.

    What I'm trying to do programatically is when the coin inventory message is received to truncate it to only show the actual tubes available. Then do some calculations based on the various byte values (scaling factor, decimal places and coin value) to get a dollar value.

    So my question is how do I deal with the portion of the message (#5) and correlate the bits from bytes 6 & 7 which are MSB to LSB to the bytes 8 through 23 in #6 that are LSB to MSB?

    Hope this helps. Thanks.
    480 x 371 - 5K
  • Don MDon M Posts: 1,652
    Something such as converting bytes 6 & 7 to a word and then test the bits somehow to find out which ones are set. So if bit 0 is set then byte 8 is value x, if bit 1 is set then byte 9 is value x and so on...
  • ChrisGaddChrisGadd Posts: 310
    edited 2016-06-29 17:35
    I think I get the gist of it. This displays the elements of the byte array referenced by bits in the first two bytes, most-significant bit first. You'll have to adjust it to make it work with your array, but this should at least serve as an example.
    VAR
      byte    array[18]
    
    OBJ
      fds : "FullDuplexSerial"
    
    PUB Main | i
      fds.start(31,30,0,115200)
      waitcnt(clkfreq + cnt)
      fds.tx($00)
    
      repeat i from 1 to 16            ' fill array
        array [i + 1] := i
      array[0] := %0000_0000           ' select which elements to display
      array[1] := %0001_0101            
    
      decode
    
    PUB decode | index
      index := array[0] << 8 | array[1]
      repeat until index == 0
        fds.str(string("Index "))
        fds.dec(>| index)                        ' display high bit
        fds.str(string(" contains "))
        fds.hex(array[>| index + 1],2)
        index := index & !(|< (>| index - 1))    ' remove high bit from index
        fds.tx($0D)
    


  • Don MDon M Posts: 1,652
    Thanks Chris. I'll have to study it a bit. I added some real data to see what it will do.
    var
      
      byte  CH_Tubes[19], CH_Setup[24]
      byte  array[18]
                  
    pub Start | idx
    
      term.start(31, 30, %0000, 115_200)                    ' start terminal (use PST)
    
     
      pause(4000)
    
      term.str(string("BitWise Testing", 13, 13))
    
      term.str(string("Changer Setup: "))
      repeat idx from 0 to 22
        CH_Setup[idx] := changersetup[idx]
    
      repeat idx from 0 to 22
        term.hex(CH_Setup[idx], 2)
        term.tx(32)
      term.tx(13)    
    
      term.str(string("Tube Status: "))
      repeat idx from 0 to 15
        CH_Tubes[idx] := tubemessage[idx]
    
      repeat idx from 0 to 15
        term.hex(CH_Tubes[idx], 2)
        term.tx(32)
      term.tx(13)
     
      array[0] := CH_Setup[5]       ' select which elements to display
      array[1] := CH_Setup[6]               
    
      decode         
               
    PUB decode | index
    
      index := array[0] << 8 | array[1]
      
      repeat until index == 0
        term.str(string("Index "))
        term.dec(>| index)                        ' display high bit
        term.str(string(" contains "))
        term.hex(CH_Tubes[>| index + 1],2)
        index := index & !(|< (>| index - 1))    ' remove high bit from index
        term.tx($0D)
                   
    pub pause(ms) | t
    
      t := cnt
      repeat ms
        waitcnt(t += MS_001)
        
    dat
    
      changersetup  byte  $02, $00, $01, $05, $01, $00, $07, $01, $02, $05, $14, $14, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
      tubemessage   byte  $00, $00, $06, $08, $0A, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    
  • Don MDon M Posts: 1,652
    Well thanks again Chris! I've been playing with this and here's a working demo along with a screen shot of the result. Seems to work correctly. I changed the tube mask and coin values and it all seems to track correctly.
    con
    
      _clkmode = xtal1 + pll16x
      _clkfreq = 80_000_000
    
      MS_001   = 80_000_000 / 1_000
    
    obj
    
    '  term   : "fullduplexserialplusdecn256"                ' for terminal output
      term   : "FullDuplexSerialDP_1"
      
    var
      
      byte  CH_Tubes[19], CH_Setup[24], CH_Coins[16]
      byte  array[18]
                  
    pub Start | idx
    
      term.start(31, 30, %0000, 115_200)                    ' start terminal (use PST)
    
     
      pause(4000)
    
      term.str(string("BitWise Testing", 13, 13))
    
      term.str(string("Changer Setup: "))
      repeat idx from 0 to 22
        CH_Setup[idx] := changersetup[idx]
    
      repeat idx from 0 to 22
        term.hex(CH_Setup[idx], 2)
        term.tx(32)
      term.tx(13)
    
      term.str(string("Coin Values: "))
      repeat idx from 0 to 15
        CH_Coins[idx] := changersetup[idx + 7]
    
      repeat idx from 0 to 15
        term.hex(CH_Coins[idx], 2)
        term.tx(32)
      term.tx(13)  
    
      term.str(string("Tube Status: "))
      repeat idx from 0 to 17
        CH_Tubes[idx] := tubemessage[idx]
    
      repeat idx from 0 to 17
        term.hex(CH_Tubes[idx], 2)
        term.tx(32)
      term.tx(13)
     
      array[0] := CH_Setup[5]       ' select which elements to display
      array[1] := CH_Setup[6]               
    
      decode1
    
      decode2         
               
    PUB decode1 | index
    
      index := array[0] << 8 | array[1]
      
      repeat until index == 0
        term.str(string("Coin Value "))
        term.dec(>| index)                        ' display high bit
        term.str(string(" is "))
        term.decdp((CH_Coins[>| index - 1] * CH_Setup[3]), CH_Setup[4])             ' Coin x scale factor. Used decimal place
        index := index & !(|< (>| index - 1))    ' remove high bit from index
        term.tx($0D)
    
    PUB decode2 | index, coin, coins, value
    
      index := array[0] << 8 | array[1]
      
      repeat until index == 0
        term.str(string("Coin Tube "))
        term.dec(>| index)                                  ' display high bit
        term.str(string(" contains "))
        coins := CH_Tubes[>| index + 1]                     ' Number of coins
        term.dec(coins)
        value := coins * (CH_Coins[>| index - 1] * CH_Setup[3])
        term.str(string(" coins with a value of "))
        term.decdp(value, CH_Setup[4])  
        index := index & !(|< (>| index - 1))               ' remove high bit from index
        term.tx($0D)
                                  
    pub pause(ms) | t
    
      t := cnt
      repeat ms
        waitcnt(t += MS_001)
        
    dat
    
      changersetup  byte  $02, $00, $01, $05, $02, $00, $07, $01, $02, $05, $14, $14, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
      tubemessage   byte  $00, $00, $06, $08, $0A, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    
    772 x 405 - 86K
Sign In or Register to comment.