Retrieving 32bit Multiply Result


Closed Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 43
  1. #1
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Lightbulb Retrieving 32bit Multiply Result

    Here's an example that I find rather useful from time to time.
    You may have seen in the manual that when you multiply two 16bit numbers together, the result is a 32bit number that can then be used with the DIV32 command. But the 32bit multiply result is not available to the user, it's only in PBP system variables where you can't get at it.

    This little routine let's you retrieve that 32 bit result.
    Code:
    A32bitVar       var word[2]
    Dummy           var word
    
    ASM
    GetMulResult macro Dword
        MOVE?WW    R2, Dword         ; Low Word
        MOVE?WW    R0, Dword + 2   ; High Word
        endm
    ENDASM
    
    Dummy = 1000
    Dummy = Dummy * Dummy
    @ GetMulResult  _A32bitVar
    
    end
    The 32 bit result for 1,000,000 is now contained in the two words of A32bitVar.

    HTH,
    Darrel Taylor

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Arrow

    And here's the other side of the coin.

    Suppose you want to put a 32 bit number in the PBP system vars where it can be used by DIV32.
    But you don't want to have to multiply two numbers together to get it.

    This allows you to enter a constant, up to 2,147,483,648 which can then be used by DIV32.

    Code:
    W1   var  word
    
    ASM
    PutMulResult macro Const32
        MOVE?CB   low Const32, R2
        MOVE?CB   low (Const32 >> 8), R2 + 1
        MOVE?CB   low (Const32 >> 16), R0
        MOVE?CB   low (Const32 >> 24), R0 + 1
      endm
    ENDASM
    
    @ PutMulResult 1000000   ; Load PBP internal vars  -  Max= 2,147,483,648
    W1 = DIV32 300           ; Divide 1000000/300
    
    '  W1 will now contain 3333
    
    @ PutMulResult 10562010
    W1 = DiV32 1000        ; Divide 10562010/1000
    
    '  W1 is now 10562
    -OR-

    If the number is contained in a 2 word variable. You can load the "MUL result" like this...
    Code:
    Asm
    PutMulResult?D macro Din
        MOVE?BB   Din, R2
        MOVE?BB   Din + 1 , R2 + 1
        MOVE?BB   Din + 2, R0
        MOVE?BB   Din + 3, R0 + 1
        RST?RP
      endm
    EndAsm
    
    DWord  VAR  WORD[2]  ; holds a 31-bit value
    
    @ PutMulResult?D _DWord   ; Load PBP internal vars  -  Max= 2,147,483,648
    W1 = DIV32 10000           ; 31-bit value / 10,000
    The possibilties, are endless

    HTH,
    Darrel Taylor

  3. #3
    kasapo's Avatar
    kasapo Guest


    Did you find this post helpful? Yes | No

    Question Math problem

    Hi darel,

    i have a motor control application. in my application pic 16f877 is reading 2 position and then take the ratio of these values and multiply with the constant velocity. for example
    x=5 y=10 then Vy = Vc (constan velocity) , Vx = Vc*x/y
    so two motor begin and stop at the same time. i wrote some code by using Div32 but sometimes i cannot get the values thet it must be.

    // for Trial i give posy greater than posx
    POSX VAR WORD
    POSX1 VAR POSX.BYTE1
    POSX0 VAR POSX.BYTE0

    POSY VAR WORD
    POSY1 VAR POSY.BYTE1
    POSY0 VAR POSY.BYTE0

    V VAR WORD
    V0 VAR V.BYTE0
    V1 VAR V.BYTE1

    HV VAR WORD
    HV0 VAR HV.BYTE0
    HV1 VAR HV.BYTE1

    A VAR WORD
    A0 VAR A.BYTE0
    A1 VAR A.BYTE1


    C VAR WORD
    C1 VAR C.BYTE1
    C0 VAR C.BYTE0

    DUMMY VAR WORD


    Asm
    PutMulResult macro Const32
    MOVE?CB Low Const32, R2
    MOVE?CB Low (Const32 >> 8), R2 + 1
    MOVE?CB Low (Const32 >> 16), R0
    MOVE?CB Low (Const32 >> 24), R0 + 1
    endm
    EndAsm

    GoSub USBREAD
    POSX1=HB
    POSX0=LB
    GoSub USBREAD
    POSY1=HB
    POSY0=LB

    IF POSY > 6554 Then
    DUMMY = POSY * 10 // i scale posy by 10
    C= Div32 POSX
    @ PutMulResult 2236920 // i also enter here the scaled c constant velocity by 10
    V= Div32 C
    HV = 34 / C
    Else
    DUMMY = POSY * 10
    C = DUMMY / POSX
    @ PutMulResult 2236920
    V= Div32 C // when this is greter than 16 bits it returns ffff
    HV = 34 / C
    EndIF

    how can i get the V when it is greater than 16 bit ?
    thanks

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    There's no way to do that with DIV32. The Quotient must be less than 65535.

    You would need a TRUE 32 bit divide routine.

    Or you could use the Floating Point Math routines from melabs.
    http://www.melabs.com/resources/fp.htm

    Darrel

  5. #5
    kasapo's Avatar
    kasapo Guest


    Did you find this post helpful? Yes | No

    Question

    hi darrel ,
    do you have some example about the usage of floating point numbers.

    after i do my multiplication and division how can i use aint variable?
    i have to send the aint to my motor controller byte by byte.

    thanks

  6. #6
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Question Any way to use a variable for DIV32 divisor?

    Hi Darrel,

    I like your ideas about getting at DIV32 system variables, but I have a slightly different situation. How do I use a variable for the divisor that wont violate the 15 bit rule?

    I tried the following example, but it don't work (I get: Error Bad expression):
    Code:
    divisor var word
    dummy var word
    
    dummy = DIV32 divisor
    I really need the ability to alter the divisor via program control, and at times it will need to be bigger then an 8-Bit value. Any ideas?

    Thanks,

    Edit: Opps! my mistake. It does work properly with a word variable as the divisor, just so long as you stay with the 15 bit rule (32767). This is good news.
    Last edited by mytekcontrols; - 18th June 2005 at 00:24.

  7. #7
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    hehe,

    DT

  8. #8


    Did you find this post helpful? Yes | No

    Default Adding 2 Dwords

    I just saw this link. it is of great interest to me right now...

    I have this question... how do you add two of these Dwords?

    how do i know if the add of two words overflows?
    i.e. $1FFFE + $2E

    my guess is to add the lower words $FFFE+$2E. But how do i know if there is an overflow? so that i can add one to the higher WORD? even worse..

    i.e. $EFFF8 + $6FFE4

    My guess again: add two lower words... if over flow add two higher words +1, else add two higher words....

    I think i can manage myself once i am sure abour the overflow

    Thanks,

  9. #9
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    For words and bytes, you can detect an overflow by testing if the result is less than what you added.

    Due to trucation of a 16-bit word ...
    $FF00 + $0180 = $0080

    So the result will always be less than either of the values added if an overflow occurs.

    I think i can manage myself once i am sure abour the overflow
    I'm sure you could. But that's just not my way ...

    Code:
    ;Initialize your hardware first
    
    A         VAR WORD[2]
    B         VAR WORD[2]
    Result    VAR WORD[2]
    OVRFLOW32 VAR BIT
    
    ASM
    ; ===== Load 32bit Constant into DWORD =============================
    MOVE?CD macro C32in, Dout                      ; Max= 4,294,967,296
        MOVE?CB   low C32in, Dout
        MOVE?CB   low (C32in >> 8), Dout + 1
        MOVE?CB   low (C32in >> 16), Dout + 2
        MOVE?CB   low (C32in >> 24), Dout + 3
      endm
    ENDASM
    
    @  MOVE?CD  0xEFFF8, _A  ; Load 983,032 into A
    @  MOVE?CD  0x6FFE4, _B  ; Load 458,724 into B
    
    GOSUB Add32
    
    LCDOUT  $FE,1,  "A=   ",HEX4 A[1],":",HEX4 A[0]
    LCDOUT  $FE,$C0,"B=   ",HEX4 B[1],":",HEX4 B[0]
    LCDOUT  $FE,$90,"Res= ",HEX4 Result[1],":",HEX4 Result[0]
    LCDOUT  $FE,$D0,"OVRFLOW32 = ", BIN1 OVRFLOW32
    stop
    
    ; ===== Add 2 32bit variables ======================================
    Add32:
        OVRFLOW32 = 0
        Result[0] = A[0] + B[0]
        IF Result[0] < B[0] then Result[1] = 1
        Result[1] = Result[1] + A[1]
        IF Result[1] < A[1] then OVRFLOW32 = 1
        Result[1] = Result[1] + B[1]
        IF Result[1] < B[1] then OVRFLOW32 = 1
    RETURN
    Which displays ...
    Code:
    A=   000E:FFF8
    B=   0006:FFE4
    Res= 0015:FFDC
    OVRFLOW32 = 0
    HTH,
    DT

  10. #10


    Did you find this post helpful? Yes | No

    Default Checking for a smaller result

    Checking for a smaller result is a simple trick, thanks,

    right now my code is never suposed to exced the Max= 4,294,967,296
    so i am ignoring the OVRFLOW32 = 0.

    This is the code that i am using
    Code:
    Bigword   var word [2]
    BigwordL  var BigWord(0)
    BigwordH  var BigWord(1)
    Bigword1  var word [2]
    Bigword1L var BigWord(0)
    Bigword1H var BigWord(1)
    
    
    AddTwoBigWords:   'Adds Bigword1 and BigWord2 result in BigWord
       BigWordH = BigWordH + BigWord1H  ;ignoring any overflow
       BigWordL = BigWordL + BigWord1L
       if BigWordL < BigWord1L then
             BigWordH = BigWordH+1          ;ignoring any overflow
       endif
    return
    Would this be ok? i made some tests and it seems ok but your experience might see anything wrong here.
    Last edited by Josuetas; - 28th July 2007 at 15:03.

  11. #11
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Thumbs up

    Yup,

    Looks great to me.

    Nice reduction.
    <br>
    DT

  12. #12


    Did you find this post helpful? Yes | No

    Red face Another trick?

    I was so confused about the Multiply operation that i posted here but.... i am now just using ** and * :s sorry
    Last edited by Josuetas; - 31st July 2007 at 20:11.

  13. #13


    Did you find this post helpful? Yes | No

    Smile Divide BigWord by Word

    Well i am really proud of this, i Hope its ok.

    For anyone in need of a Division of a BigWord by some number i found this problem:

    Lets think of a BigWord as considered before ^

    Now you might want to Divide a value stored in tBigWord1 by some other value, in this case (EXAMPLE CODE) the value is stored in factoriva.

    One could use the DIV32 function as proposed by Darrel in this or other post BUT if factoriva is too small the result CAN be higher than a word size FFFF, and the the result is no good.

    For example:

    4:01F5 DIV32 2 the result of DIV32 is

    Result = FFFF, Remainder = 01F7 !! Wrong i guess

    This code is possible just thanks to Darrel`s @ PutMulResult?D MACRO

    Code:
    Bigword   var word [2]
    BigwordL  var BigWord(0)
    BigwordH  var BigWord(1)
    Bigword1  var word [2]
    Bigword1L var BigWord(0)
    Bigword1H var BigWord(1)
    
    MainLoop:
        lcdout $fe,1
        tbigword1H = 4         ' My Dollars Value High Word
        tbigword1L = 501      ' My Dollars value Low Word
        cents = 24              ' My cents value
    
        GOSUB DIVBIGWORD
        HSEROUT [#FactorIva," ",HEX4 tBigWordH,":", HEX4 tBigWordHL,10,13]
    
        FactorIva= FactorIva+ 1
        IF FactorIva= 101 THEN
             END
        ENDIF    
        GOTO MainLoop
    
    'This SUB receives  tBigWord1(Dword) a value to be divided by
    'FactorIva (word), Result in tBigWord, works for any value of FactorIva
    'and tBigWord1 in their limits.
    DIVBigWord:  
        tBigWordH= tBigWord1H / FactorIva
        tBigWord1H = tBigWord1H // FactorIva
        @ PutMulResult?D  _tBigWord1
        tBigWordL = DIV32 FactorIva
        Remainder = R2
        RETURN
    This code in the serial port os The value tBigWord1 Divided for Factors 1 to 100
    Seems to work.
    Factor Result
    2 0002:00FA

    Remember to Add the @ PutMulResult?D MACRO posted by Darrel at the begining of the Code.

  14. #14


    Did you find this post helpful? Yes | No

    Default

    Hello everyone,

    I was wandering if it is possible to implement the extended 32 bit idea to something as simple as for / next loop.
    How will this simple loop look like if I need to deal with more than word size index:

    For index =0 to big_number
    Hserout [record(index),13,10]
    Pause 100
    Next

    Is it possible to have a big_number = 1,000,000 – 2,000,000?

    Thank you for your input.

    Nick

  15. #15
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Nicmus View Post
    Is it possible to have a big_number = 1,000,000 – 2,000,000?
    Nick
    It's directly possible if you have the PBP 2.50a upgrade, which supports signed/32 bit LONG variables...

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


    Did you find this post helpful? Yes | No

    Default

    for PIC18 only !
    Steve

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

  17. #17
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Thumbs up

    Quote Originally Posted by mister_e View Post
    for PIC18 only !
    Got my back everywhere, dontcha?

  18. #18


    Did you find this post helpful? Yes | No

    Default

    Thank you gents for your replies.
    Unfortunately for me I’m dealing with a old application which employs a PIC16F876A and needs an upgrade to be able to handle a larger number of records.
    The code space is not a problem so I guess I will have to figure a way to get around this problem.
    Basically I receive a 8 bytes decimal number which is the total number of records. What I’m planning to do is create two loops.
    First I will separate the incoming Big_number in Big_number_low (last four bytes (max 9999)) and Big_number_high (first four MS bytes (max 9999)).
    The code in my last post should change to:

    For index_1=0 to Big_number_low
    HSEOUT [sentence(index_1)]
    Next
    For index_2=0 to Big_number_high
    For index_3=0 to 9999
    HSEROUT [sentence(index_3)]
    Next
    Next

    I’m wandering if this will do or I need to look deeper into the problem.
    Any comments will be appreciated.

    Regards,

    Nick

  19. #19
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Not sure how you're going to get a 1,000,000 element array with a PIC ...
    Even with PBP 2.50

    Code:
    For index =0 to big_number
        Hserout [record(index),13,10]
        Pause 100
    Next
    Not enough RAM.
    <br>
    DT

  20. #20


    Did you find this post helpful? Yes | No

    Default

    Thank you gents for your replies.
    I’m sorry for not making it clear. I’m receiving each sentence one at the time and send them out. My problem is that I know how many I will receive (Big_number) and I need to keep track on how many I send out to match the Big_number. So it gets down to only handling a 6digi number.
    Unfortunately for me I’m dealing with a old application which employs a PIC16F876A and needs an upgrade to be able to handle a larger number of records.
    The code space is not a problem so I guess I will have to figure a way to get around this problem.
    Basically I receive a 8 bytes decimal number which is the total number of records. What I’m planning to do is create two loops.
    First I will separate the incoming Big_number in Big_number_low (last four bytes (max 9999)) and Big_number_high (first four MS bytes (max 9999)).
    The code in my last post should change to:

    For index_1=0 to Big_number_low
    HSEOUT [sentence(index_1)]
    Next
    For index_2=0 to Big_number_high
    For index_3=0 to 9999
    HSEROUT [sentence(index_3)]
    Next
    Next

    I’m wandering if this will do or I need to look deeper into the problem.
    Any comments will be appreciated.

    Regards,


    Nick
    Last edited by Nicmus; - 25th January 2008 at 01:36. Reason: To clarify the problem

  21. #21
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    How are you going to get a 1,000,000 element array with a PIC?

    Code:
    For index_1=0 to Big_number_low
        HSEROUT [sentence(index_1)]
    Next
    Not enough RAM.
    <br>
    DT

  22. #22


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,
    I’m sorry for not presenting the complete picture.
    I’m reading a .txt file from a USB media. The first line of this file gives me the total number of records in the file.
    I’m reading the records one by one in a big loop:

    Read Big_number
    For index = 0 to Big_number
    Read record
    HSEROUT [record}
    If index => Big_number then quit
    Next

    It all works fine if Big_number is limited to word size.
    Now the requirement changed for larger number of records so I thought that your trick might apply here.
    At the time I did that because I did not know, and I still don’t, to detect EOF.
    Trying to read the device over the EOF will freeze the system.

    Thank you for your interest.

    Nick

  23. #23
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    That makes things a bit easier ...
    Code:
    big_number  VAR WORD[2]   ; 32-bit variable 
    
    
    ASM  
    ;---[load a 32-bit constant into a 32-bit variable]-----------------
    MOVE?CN  macro Cin, Nout
        MOVE?CW  Cin & 0xFFFF, Nout     ; Low Word
        MOVE?CW  (Cin >> 16), Nout + 2  ; High Word
      endm
    ENDASM
    
    
    ;-------------------------------------------------------------------
    @  MOVE?CN  1000000, big_number
    
    WHILE (big_number[1] > 0) OR (big_number[0] > 0)
        Read record
        HSEROUT [record]
        
        big_number[0] = big_number[0] - 1
        IF big_number[0] = $ffff THEN big_number[1] = big_number[1] - 1
    WEND
    Last edited by Darrel Taylor; - 25th January 2008 at 09:09. Reason: Changed AND to OR
    DT

  24. #24


    Did you find this post helpful? Yes | No

    Default

    Thank you Darrel,
    I knew it can be done. I just did not know how, and your example turns few lights on in my brain.
    I will give it a shot after work, today, and post the results.
    Thanks again,

    Nick

  25. #25


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,

    I have a PBP copy installed on my work computer so I tried your code in a simple program to send out numbers (if I understood you correctly) from Big_number to 0.

    I am using:
    MCS 2.3.0.0
    PBP 2.47
    MPASM 5.03

    This is the small program I’m trying to compile but I get a warning and an error:

    INCLUDE "modedefs.bas"
    DEFINE OSC 16
    DEFINE LOADER_USED 1
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 20h
    DEFINE HSER_BAUD 4800
    DEFINE HSER_CLROERR 1

    big_number VAR WORD[2] ; 32-bit variable

    ADCON1=6
    CMCON=7

    main:

    @ MOVE?CN 1000000, big_number
    WHILE (big_number[1] > 0) OR (big_number[0] > 0)
    HSEROUT [#big_number[1],#big_number[0]]
    big_number[0] = big_number[0] - 1
    IF big_number[0] = $ffff THEN big_number[1] = big_number[1] - 1
    WEND
    pause 5000
    goto main
    ASM
    ;---[load a 32-bit constant into a 32-bit variable]-----------------
    MOVE?CN macro Cin, Nout
    MOVE?CW Cin & 0xFFFF, Nout ; Low Word
    MOVE?CW (Cin >> 16), Nout + 2 ; High Word
    endm
    ENDASM
    End


    The messages I get are:

    Warning[207] c:\big_num.asm 99: Found label after column 1.(MOVE?CN)
    Error[108] c:\big_num.asm : Illegal character (1)

    Any idea?

    Regards,

    Nick

  26. #26
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Put the macro in the source code BEFORE the actual usage.

    INCLUDE "modedefs.bas"
    DEFINE OSC 16
    DEFINE LOADER_USED 1
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 20h
    DEFINE HSER_BAUD 4800
    DEFINE HSER_CLROERR 1
    big_number VAR WORD[2] ; 32-bit variable
    ADCON1=6
    CMCON=7
    goto main
    ASM
    ;---[load a 32-bit constant into a 32-bit variable]-----------------
    MOVE?CN macro Cin, Nout
    MOVE?CW Cin & 0xFFFF, Nout ; Low Word
    MOVE?CW (Cin >> 16), Nout + 2 ; High Word
    endm
    ENDASM
    main:
    @ MOVE?CN 1000000, big_number
    WHILE (big_number[1] > 0) OR (big_number[0] > 0)
    HSEROUT [#big_number[1],#big_number[0]]
    big_number[0] = big_number[0] - 1
    IF big_number[0] = $ffff THEN big_number[1] = big_number[1] - 1
    WEND
    pause 5000
    goto main
    End
    [/code]

  27. #27


    Did you find this post helpful? Yes | No

    Default

    Hi Skimask,

    I tried that first but I got 12 errors:

    Error[113] c:\pbp\pbppicbasic14.lib428 : Symbol not previously defined (big_number).
    Should I do any changes in pbppicbasic14.lib?
    Thanks,

    Nick

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


    Did you find this post helpful? Yes | No

    Default

    edit this line
    Code:
    @ MOVE?CN 1000000, big_number
    to
    Code:
    @ MOVE?CN 1000000, _big_number
    Steve

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

  29. #29
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    OOps!

    Thanks Steve.
    DT

  30. #30


    Did you find this post helpful? Yes | No

    Default

    Thank you Darrel, Steve and Skimask,

    No more errors.
    One more clarification on the line:
    @ MOVE?CN 1000000, _big_number
    Does it make my big_number=1000000 in decimal?
    If that is true should I see the counter going down from 1000000 to 0?
    Am I processing the big_number right in my HSEROUT statement because when I run the program it starts counting down from 1516960.
    How do I insert a new big_number

    I will be away from the computer for the next 2 hours.
    Thanks in advance for all the help.

    Nick

  31. #31
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Yes, it loads 1 million into big_number.
    But it's a 32-bit binary number, so you can't just display the high/low WORDs with DEC.

    The hex representation of 1 million is F:4240.
    Then change each word to Decimal F=15, 4240=16960
    So it looks like it starts counting from 1516960

    To convert the big_number to a readable decimal output takes a little more work.

    Code:
    HighDigits  VAR WORD
    LowDigits   VAR WORD
    
    ;---[add this with the other macro's]---------------
    ASM
    PutMulResult?N  macro Nin
        MOVE?WW  Nin, R2
        MOVE?WW  Nin + 2, R0
      endm
    ENDASM
    
    
    ;---[add this to your main loop]--------------------
    @   PutMulResult?N  _big_number
        GOSUB SendBigNum
    ;---------------------------------------------------
    
    SendBigNum:
        HighDigits = DIV32 10000
        LowDigits  = R2
        IF (HighDigits > 0) THEN
            HSEROUT [DEC HighDigits, DEC4 LowDigits]
        ELSE
            HSEROUT [DEC LowDigits]
        ENDIF
    RETURN
    How do I insert a new big_number
    That depends on where the new big_number is coming from.

    You said you're reading the file length from the USB device.
    What format is it in, what variables are you storing it in.
    DT

  32. #32


    Did you find this post helpful? Yes | No

    Default

    Thank you Darrel,

    I will add the new code to my program and report the results.

    On the refreshing the big_number question:
    I’m using a Viniculun device to read an USB storage media that lets me read one byte at the time, n bytes or the entire file in one shot.
    The very first line in my data .txt file is the total number of records, 0 - 2,000,000, in fixed length (10 digit left padded with zeros.I used 10 digits to allow for up to 31 bit numbers if need be in the future), decimal format. The rest of the file are the records in fixed length (78 bytes) starting with "#" character, right padded with "~" character and ending with CR/LF. The data is only numerical and I do not process it, I just pass it to the Hserout. Every few records I must pause about 1 second to let the receiver process the information.

    I can read the 10 digit number byte by byte, strip the leading zeros and transfer into my big_number variable. How am I going to do it? This is the $10,000,000 question.

    I will fix my code right the way and work on the other problem.

    I must commend you guys for taking my “what if?” question and make sure I get the best solution. I learned a lot with your help.

    Regards,

    Nick
    Last edited by Nicmus; - 26th January 2008 at 00:55. Reason: Add more info

  33. #33


    Did you find this post helpful? Yes | No

    Default

    I added the changes Darrel suggested and it all works fine.
    I need to make small changes to the code to better fit my application and i will post it tomorrow.

    Thanks again and good night!

    Nick

  34. #34
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    If you come back and have it counting from 0 to <strike>1,000,000</strike> File Length ...

    I will ..., uh ...,

    oh hell, I don't know what I'd do.
    <br>
    DT

  35. #35


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,

    Sorry for the delay. I had some hardware problems which I had to fix.
    Also I’m using a USB to serial interface to communicate with HT and every now and then Windows will see my device as a mouse.
    Here is what I have so far:
    I am able to count down and send out the big_number. I made few changes to your code to format the output as a 8 digit number (kept the leading zeros).
    I’m also receiving the big_number as two 4 digit decimal numbers.
    The only thing left is to make one big_number from the two word size variable (in_high and in_low).
    I was thinking to use your PutMultResult?D macro Din but I’m not quite sure how to do it.
    Here is the latest working code:

    INCLUDE "modedefs.bas"
    @ device pic16F876a,hs_osc,pwrt_on, protect_on
    DEFINE OSC 16
    DEFINE LOADER_USED 1
    DEFIne HSER_RCSTA 90h
    DEFINE HSER_TXSTA 20h
    DEFINE HSER_BAUD 4800
    define HSER_CLROERR 1

    HighDigits VAR WORD
    LowDigits VAR WORD
    big_number VAR WORD[2] ; 32-bit variable
    in_low var word
    in_high var word
    led var PORTA.2

    ADCON1=6
    CMCON=7

    ASM
    MOVE?CN macro Cin, Nout
    MOVE?CW Cin & 0xFFFF, Nout ; Low Word
    MOVE?CW (Cin >> 16), Nout + 2 ; High Word
    endm
    ENDASM
    ASM
    PutMulResult?N macro Nin
    MOVE?WW Nin, R2
    MOVE?WW Nin + 2, R0
    endm
    ENDASM
    pause 10000 ' Allow for the USB device to enumerate
    hserout [13,10,"Waiting for Big_number",13,10] ' Add time out later
    hserin [dec4 in_high,dec4 in_low]
    main:
    @ MOVE?CN 20000, _big_number
    WHILE (big_number[1] > 0) OR (big_number[0] > 0)
    big_number[0] = big_number[0] - 1
    IF big_number[0] = $ffff THEN big_number[1] = big_number[1] - 1
    @ PutMulResult?N _big_number
    GOSUB SendBigNum
    toggle led ' Show if any action
    WEND
    pause 5000
    goto main
    SendBigNum:
    HighDigits = DIV32 10000
    LowDigits = R2
    'IF (HighDigits > 0) THEN
    HSEROUT [DEC4 HighDigits, DEC4 LowDigits," and ",dec4 in_high,dec4 in_low,13,10]
    'ELSE
    'HSEROUT [DEC4 LowDigits,13,10]
    'ENDIF
    RETURN

    End

    Thanks again for your patience.

    Nick

    BTW: I'm practising to post code the right way.
    Last edited by Nicmus; - 26th January 2008 at 16:02. Reason: Posting code practice

  36. #36
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    I’m also receiving the big_number as two 4 digit decimal numbers.
    The only thing left is to make one big_number from the two word size variable (in_high and in_low).
    This one I'm not so sure about. And I don't have anything handy to test it on.
    I'm pretty sure it will work, but not Positive...
    Code:
    HighDigits = 100   ; Simulating File Length of 1,000,000
    LowDigits  = 0000
    
    big_number[0] = HighDigits * 10000
    big_number[1] = R0
    big_number[0] = big_number[0] + LowDigits
    IF (big_number[0] < LowDigits) THEN big_number[1] = big_number[1] + 1
    P.S. To put code in a scrolling box that doesn't scrunch it all to the left, use ...
    [code]' --- code goes here ---[/code]

    oops, nevermind. I see you're even using colors in the test area.
    <br>
    Last edited by Darrel Taylor; - 26th January 2008 at 21:39. Reason: oops
    DT

  37. #37


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,

    I’m a bit confused by your last post.
    I’m not sure were to add this code. Also I have the feeling that the big_number[0] and big_number[1] are switched from the way they are in my code.

    Here is the code in “colors” format:

    Code:
    <font color="#000000"><b>INCLUDE </b><font color="#FF0000">&quot;modedefs.bas&quot;
    </font><font color="#008000">@	device  pic16F876a,hs_osc,pwrt_on, protect_on
    </font><b>DEFINE </b>OSC 16
    <b>DEFINE</b>	LOADER_USED	1
    <b>DEFINE </b>HSER_RCSTA 90h
    <b>DEFINE </b>HSER_TXSTA 20h
    <b>DEFINE </b>HSER_BAUD 4800
    <b>DEFINE </b>HSER_CLROERR 1
    
    HighDigits  <b>VAR     WORD
    </b>LowDigits   <b>VAR     WORD
    </b>big_number  <b>VAR     WORD</b>[2]   <font color="#000080"><i>; 32-bit varia
    </i></font>in_low      <b>VAR     WORD
    </b>in_high     <b>VAR     WORD
    </b>led         <b>VAR     </b>PORTA.2
    
    ADCON1=6
    CMCON=7	
    
    <b>ASM  
    </b><font color="#008000">MOVE?CN  macro Cin, Nout
        MOVE?CW  Cin &amp; 0xFFFF, Nout     </font><font color="#000080"><i>; Low Word
        </i></font><font color="#008000">MOVE?CW  (Cin &gt;&gt; 16), Nout + 2  </font><font color="#000080"><i>; High Word
      </i></font><font color="#008000">endm
    </font><b>ENDASM
    ASM
    </b><font color="#008000">PutMulResult?N  macro Nin
        MOVE?WW  Nin, R2
        MOVE?WW  Nin + 2, R0
      endm
    </font><b>ENDASM
        PAUSE </b>1000
        <b>HSEROUT </b>[13,10,<font color="#FF0000">&quot;Waiting for Big_number&quot;</font>,13,10]
        <b>HSERIN </b>[<b>DEC4 </b>in_high,<b>DEC4 </b>in_low]
    
    main:
    <font color="#008000">@   MOVE?CN  20000, _big_number
    </font><b>WHILE </b>(big_number[1] &gt; 0) <b>OR </b>(big_number[0] &gt; 0)
        big_number[0] = big_number[0] - 1
        <b>IF </b>big_number[0] = $ffff <b>THEN </b>big_number[1] = big_number[1] - 1
    <font color="#008000">@   PutMulResult?N  _big_number
        </font><b>GOSUB </b>SendBigNum
        <b>TOGGLE </b>led
    <b>WEND
        PAUSE </b>5000
        <b>GOTO </b>main
    SendBigNum:
        HighDigits = <b>DIV32 </b>10000
        LowDigits  = R2
        <font color="#000080"><i>'IF (HighDigits &gt; 0) THEN
            </i></font><b>HSEROUT </b>[<b>DEC4 </b>HighDigits, <b>DEC4 </b>LowDigits,<font color="#FF0000">&quot; and &quot;</font>,<b>DEC4 </b>in_high,<b>DEC4 </b>in_low,13,10]
        <font color="#000080"><i>'ELSE
            'HSEROUT [DEC4 LowDigits,13,10]
        'ENDIF
    </i></font><b>RETURN
    
    END
    </b>
    How do I process the in_low and in_high variables to get the big_number before entering the main loop?
    Am I pulling them right as DEC4 or should I do it differently?

    Regards,

    Nick

  38. #38
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Sorry. Should have used your variable names ...
    Code:
    big_number[0] = in_high * 10000
    big_number[1] = R0
    big_number[0] = big_number[0] + in_low
    IF (big_number[0] < in_low) THEN big_number[1] = big_number[1] + 1
    Just stick it after the HSERIN.

    P.S. Nice "Colors".
    DT

  39. #39


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,

    I added your last lines and had to REM the line:

    Code:
    @   MOVE?CN  1000000, _big_number
    After that everything works as intended.
    I guess the macro this line was pointing to is no longer needed.
    I will open an other thread with a question on detecting EOF.
    There are no words to thank you enough for your help.

    Best Regards,

    Nick

  40. #40
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Yup, that statement/macro is no longer needed.

    EOF marker for a .txt file is usually 26. That's a byte with the decimal value 26.
    In hex it's 1A, ASCII it's ctrl-Z, whichever way you want to look at it.

    Of course that ruins everything we just did.

    And you're welcome.
    <br>
    DT

Similar Threads

  1. Strugling without floating point
    By pjsmith in forum mel PIC BASIC Pro
    Replies: 15
    Last Post: - 27th March 2011, 06:29
  2. Math help please!!!
    By jbirnsch in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 10th August 2007, 14:45
  3. 32-bit Variables and DIV32, Hourmeter 99999.9
    By Darrel Taylor in forum Code Examples
    Replies: 9
    Last Post: - 23rd November 2006, 07:23
  4. PBP 16-bit ADC result math
    By sonic in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 13th March 2005, 14:21
  5. Retrieving Div32 Remainder
    By Darrel Taylor in forum Code Examples
    Replies: 4
    Last Post: - 20th August 2003, 03:53

Members who have read this thread : 3

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