2 bytes to word array variable - fastest way


Closed Thread
Results 1 to 16 of 16
  1. #1
    Join Date
    Feb 2011
    Location
    Michigan, USA
    Posts
    33

    Default 2 bytes to word array variable - fastest way

    Hello All,
    I would like an "expert check" on this one....
    I need to put 2 ADC bytes into a word variable thats part of an array.

    This is what I have:
    adcData var word[16]
    adcData[index] = (ADRESH << 8) + ADRESL

    Is there a better way (faster) ?

    thanks,
    Mike

    P.S.
    I am modernizing an old dehumidifier whose humidity sensor (tape strip) has
    gone the way of the dodo. I figure get an electronic humidity sensor and I
    would have another excuse for a PIC project.

  2. #2
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Have you tested that? it seems like it will shift ADRESH 8 times, then assign it to the word. DOing it like that would be better I think like this:
    Code:
    adcdata[index] = ADRESH
    adcdata[index] = adcdata[index]<<8
    adcdata[index] = adcdata[index]+ADRESL
    Not sure about that either.

    I think you can do this:
    Code:
    adcdata.highbyte[index] = ADRESH
    adcdata.lowbyte[index] = ADRESL
    I am not certain on this, so my reply is as much a question as an answer. Hmmm, that sounds a little deep

    OK, this I am certain about:
    Code:
    tempword var word
     
    tempword.highbyte = ADRESH
    tempword.lowbyte = ADRESL
    adcdata[index] = tempword
    Last edited by cncmachineguy; - 8th June 2011 at 00:45.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  3. #3
    Join Date
    Feb 2011
    Location
    Michigan, USA
    Posts
    33


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    I have tested the code with VB.Net, and it works, but I haven't tested on the PIC yet.

    I actually tried this code first but it did not compile:
    adcData.highbyte[index] = ADRESH
    adcData.lowbyte[index] = ADRESL
    I guess you can't use the .lowbyte/.highbyte syntax on arrays.

    Using the temp variable is probably the norm but I figure there might be some trick to doing
    the same thing all nice and clean on one line.

  4. #4
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    In your VB test, Was ADRESH a byte or a word?
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  5. #5
    Join Date
    Feb 2011
    Location
    Michigan, USA
    Posts
    33


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Thanks Bert. I see what your getting at. ADRESH was a word.
    I just tried ADRESH as a byte and had an overflow. oops, I missed that one.
    I guess I'll use the temp variable way.

    There is another way I used before:
    adcData[index] = (ADRESH * 256) + ADRESL
    But I would put money on this way is slower than the temp variable way.

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Hi,
    Have you tried:
    Code:
    adcData.lowbyte[index] = ADRESL
    adcData.lowbyte[index+1] = ADRESH
    Take a look at Melanies writeup, specifically section 5, for further details.

    /Henrik.

  7. #7
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Thanks for clearing that up Henrik. I knew there was a way, and I knew my guess was not correct. While I feel like the highbyte/lowbyte should work, I realize it does not. I feel like this is a shortcoming of PBP, adcdata.lowbyte[index+1] feels like it should be the lowbyte of the next word. Anyone agree or do I not have my mind wrapped around this just yet?

    It seems a little un-intuitive, but who cares, thats how it works.
    Last edited by cncmachineguy; - 8th June 2011 at 14:32. Reason: lexicdys
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Actually I may have messed that up myself, based on this post I'm not sure it'll do what the OP wanted - to be honest.

    I agree it's a abit unituitive and I'll admit I haven't sat down and looked into what's really happening - until now. Before I go on I'll point out that I suck at ASM so if this is completely wrong then I applogise before hand and hope that whoever knows/understands better will correct me.

    When you declare an array of words PBP 'calculates' the start adress of that array in memory (where in the RAM memory the first byte in the array is located). If, somewhere in your program, you use the LOWBYTE,HIGHBYTE "modifiers" it also calculates where the lowbyte and highbyte of the first word in the array is. Glancing at the .lst file it might look something like this:
    Code:
    '00038 _myArray                        EQU     RAM_START + 01Dh
    '00043 _myArray??LOWBYTE               EQU     _myArray
    '00044 _myArray??HIGHBYTE              EQU     _myArray + 001h
    So all it really knows (and need to know) is where myArray starts. The .LOWBYTE of myArray is at the very same adress as the array starts and .HIGHBYTE is at the next adress. Makes sense.

    Now, let's say we do something like this:
    Code:
    myArray VAR WORD[3]
    myByte VAR BYTE
     
    myVar = myArray[0]
    myVar = myArray[1]
    What's going on here then? We're actually trying to stuff a WORD from the array into our BYTE-sized variable. The code generated looks like this:
    Code:
    movff   _myArray, _myVAR
    movff   _myArray + 00002h, _myVAR
    First it takes the byte at the start adress of the array (which is the low byte of word 0, right) and puts that in our BYTE-variable. Then it takes start-adress of the array, adds 2 to that adress and grabs the byte at that location. This is the third byte in our WORD-array so it's grabbing the low byte of word 1. This is pretty straight forward and intuitive - it simply truncates the word from the array into our byte variable.

    Now,
    Code:
    myVar = myArray.LowByte
    myVar = myArray.HighByte
    The above PBP code compiles:
    Code:
    movff _myArray??LOWBYTE, _myVAR
    movff _myArray??HIGHBYTE, _myVAR
    As we saw above myArray??LOWBYTE is the very same adress as the start of the array so this IS the low byte of the first word. myArray??HIGHBYTE is at the start adress of the array + 1 so we'll get the high byte of the first word. Still OK, what we wanted, and probably what we expected.

    Now lets start indexing into the array.
    Code:
    myVar = myArray.LowByte[0]
    myVar = myArray.HighByte[0]
    This code compiles to:
    Code:
    movff   ((_myArray??LOWBYTE) + (000h)), _myVAR
    movff   ((_myArray??HIGHBYTE) + (000h)), _myVAR
    As you can see this takes the adress of the lowbyte of the first word in the array, adds nothing (zero) to it, gets the byte at that adress and puts it in our byte variable. Then it takes the address of the highbyte of the first word in the array, adds nothing to that and gets the byte at that adress. This is still fine, what we wanted (perhaps) and what we might expect. But now it starts to get interesting.

    Code:
    myVar = myArray.LowByte[1]
    myVar = myArray.HighByte[1]
    From this we might, intuitively, expect to get the low and high byte of the second word the array but the above code compiles to:
    Code:
    movff   ((_myArray??LOWBYTE) + (001h)), _myVAR
    movff   ((_myArray??HIGHBYTE) + (001h)), _myVAR
    So, what's going on here... It takes the adress of the 'lowbyte' (the very first byte in our array, low byte of word 0), adds one to that address and gets the byte at that adress. What we're getting is actually the second byte in the array which is the high byte of the first word (word 0). Then it takes the adress of 'highbyte', adds one to that and gets the byte at that adress which is now the third byte in the array or the low byte of the second word (word 1). Not what one might expect but when you know what goes on under the hood it kind of makes sense.

    And, to illustrate it one more time:
    Code:
    MyVar = myArray.Lowbyte[2]
    myVar = myArray.HighByte[2]
    Intuitively we'd expect to get the low and high byte of the third word but we now know that ain't what's happening because we're telling it to index an array of words byte by byte. We tell it to get the byte at the adress of myArray.Lowbyte+2. myArray.Lowbyte is the very first byte in the array, add two to that and we'll end up the adress of the third byte in the array which is the low byte of word 1 - not word 2 as we intutively might think. And, obviously the same thing happends with myArray.HighByte[2] - it gets 4th byte in the array which is the high byte if word 1.

    What we need to do when working with word-arrays on a byte-by-byte-basis is to index, or step, thru them in steps of 2. Like....
    Code:
    accData VAR WORD[16]
    Index VAR BYTE
     
    For Index = 0 to 16 STEP 2
      accData[Index] = ADRESL 'Low byte  (bytes 0, 2, 4, 6...)
      accData[Index+1] = ADRESH  'High byte  (bytes 1, 3, 5, 7...)
    NEXT
    So, again, I'm not sure my earlier advice is actually going to work. It might work if the word indexed is first but it kind of screws up as we've seen above.

    /Henrik.
    Last edited by HenrikOlsson; - 8th June 2011 at 18:03.

  9. #9
    Join Date
    Feb 2011
    Location
    Michigan, USA
    Posts
    33


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Hi Henrik,
    I understand your explanation and thank you. But in your last bit of code
    doesn't it need the ".lowbyte" part?
    Code:
     
    For Index = 0 to 16 STEP 2
      accData.lowbyte[Index] = ADRESL 'Low byte  (bytes 0, 2, 4, 6...)
      accData.lowbyte[Index+1] = ADRESH  'High byte  (bytes 1, 3, 5, 7...)
    NEXT

    This is more intuitive though at the cost of a word variable
    Code:
     
    for index = 0 to 16
      tempword.highbyte = ADRESH
      tempword.lowbyte = ADRESL
      adcdata[index] = tempword
    next
    Mike -
    Last edited by MikeWinston; - 8th June 2011 at 18:31.

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Yes, you're quite right, otherwise it'll be as in the first example where the indexing is actually word based and we'll get the low byte of all the words instead of the low and high byte. Thanks for pointing that out!

    /Henrik.

    I wish I could edit my post and correct that but the 10 second window for doing that has passed.... :-(

  11. #11
    Join Date
    Aug 2010
    Location
    Maryland, USA
    Posts
    869


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Again thank you Henrik. Yes knowing what goes on under the hood does make it make sense, But I stand by my statement that this is a shortcomming of PBP. I would almost go so far to call this a work around for word array indexing on a byte level. I think I will add a wish list thread for this. PBP should certainly be able to distinguish the intention. It would be even more intuitive to address it this way:
    Code:
    adcdata[index].lowbyte
    adcdata[index].highbyte
    But knowing is half the battle, again thanks for the very clear explanation.
    -Bert

    The glass is not half full or half empty, Its twice as big as needed for the job!

    http://foamcasualty.com/ - Warbird R/C scratch building with foam!

  12. #12
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    I fully agree, it might be somewhat logical when one understands it but it's certanly not intuitive, your format would be much cleaner for its typical purpose. I'm sure though that there are some clever tricks that can be done (which I'm not clever enough to figure out) with the way it currently is.

    /Henrik.

  13. #13
    Join Date
    Jun 2010
    Location
    Venezuela
    Posts
    12


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    hello, i use this and work:

    read I,b1.HIGHBYTE ' read byte type var from EEprom
    read I+1,b1.LOWBYTE 'read byte type var from EEprom
    TEmpDs18(L) = B1 'word array

  14. #14
    Join Date
    Feb 2011
    Location
    Michigan, USA
    Posts
    33


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    Well it turns out the more intuitive way is also a little faster. That is if I
    have done this correctly.

    I used [view] [program memory] in MPLab and counted the number of
    instructions between the start and end labels.

    This code was 18 lines:
    Code:
     
    StartTest:
      adcData.lowbyte[Index] = ADRESL
      adcData.lowbyte[Index+1] = ADRESH
    EndTest:
    This code was 16 lines:
    Code:
     
    StartTest:
      tempWord.highbyte = ADRESH
      tempWord.lowbyte = ADRESL
      adcdata[index] = tempword
    EndTest:
    So as long as I can afford the extra word variable, I will be using the
    temp variable way...... unless someone else reveals a clever trick.

    thanks all for your replies,
    Mike -

  15. #15
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    If ADRESH & ADRESL are consecutive SFR... then you could use

    Code:
        @ADRESULT = ADRESL
        ADRESULT VAR WORD EXT
    
        MyArray VAR WORD [8]
    
    Start:
        MyArray[0] = ADRESULT
    But I doubt ADRESL/ADRESH are consecutive in many PIC.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  16. #16
    Join Date
    Feb 2011
    Location
    Michigan, USA
    Posts
    33


    Did you find this post helpful? Yes | No

    Default Re: 2 bytes to word array variable - fastest way

    mister_e,
    Thats a good trick. One to remember. And it only produces 9 lines of
    instruction. But your right, the PIC I'm using (16F684), ADRESH/L are not
    next to each other.

    Actually, ACCON0 is after ADRESH. That would give you an interesting result.

    thanks,
    Mike -

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts