• AVR Freaks

Hot!PIC 18f Assembly

Author
HOODEY
Super Member
  • Total Posts : 576
  • Reward points : 0
  • Joined: 2005/02/08 06:06:31
  • Status: offline
2019/01/03 07:01:50 (permalink)
0

PIC 18f Assembly

What is the best way to implement the calculations attached. Try to stay away from floating point stuff.

Attached Image(s)

#1

16 Replies Related Threads

    pcbbc
    Super Member
    • Total Posts : 996
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC 18f Assembly 2019/01/03 11:27:27 (permalink)
    0
    If all the values you give are runtime dependant, rearrange as:
    TOFn = TIMEn x (CALIBRATION2_PERIODS - 1) x 1000000 / ((CALIBRATION2 - CALIBRATION1) * 8)
    This probably requires at least 32-bit integer maths and yields an answer in whole picoseconds (247061).
     
    Depending on the accuracy you require in the result, you can remove zeros from the 1000000 on the top.  For example:
    TOFn = TIMEn x (CALIBRATION2_PERIODS - 1) x 1000 / ((CALIBRATION2 - CALIBRATION1) * 8)
    Gives a result in whole nanoseconds (247) and might enable you to get away with 24-bit maths.
     
    If you require accurate results over a large range (i.e. picoseconds to milliseconds) then you can check the range of TIMEn and pick a clock speed multiplier for the top of the equation accordingly.  The objective should be to ensure that the top of the equation never exceeds the size of the integers you are working with.  If it does, you need to use a smaller multiplier which scales the result accordingly.
     
    If your clock rate (8MHz) is constant, which it probably is, you can further optimise by pre-dividing by the 8 on the top and removing it from the bottom:
    TOFn = TIMEn x (CALIBRATION2_PERIODS - 1) x 125000 / (CALIBRATION2 - CALIBRATION1)
    Again results in picoseconds.
    #2
    1and0
    Access is Denied
    • Total Posts : 9206
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC 18f Assembly 2019/01/03 11:34:14 (permalink)
    +1 (1)
    The trick is to do multiplication before division, as shown above, and at the same time avoid any overflow.
    #3
    NorthGuy
    Super Member
    • Total Posts : 5431
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: online
    Re: PIC 18f Assembly 2019/01/03 12:27:28 (permalink)
    +1 (1)
    You also can pre-calculate (CALIBRATION2_PERIODS - 1) x 125000 / (CALIBRATION2 - CALIBRATION1) once these values are available, then all you have left is one multiplication.
    #4
    pcbbc
    Super Member
    • Total Posts : 996
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC 18f Assembly 2019/01/03 22:41:19 (permalink)
    +1 (1)
    NorthGuyYou also can pre-calculate (CALIBRATION2_PERIODS - 1) x 125000 / (CALIBRATION2 - CALIBRATION1) once these values are available, then all you have left is one multiplication.
    Not if you are using integer maths and you want to maintain your accuracy.

    Doing the division in advance will only be accurate in cases where A / B meets condition A mod B = 0

    For integer maths the divide must always be the last step, because accuracy is lost when you discard the remainder (unless you can guarantee the remainder is always zero, as for example when A mod B = 0).
    #5
    HOODEY
    Super Member
    • Total Posts : 576
    • Reward points : 0
    • Joined: 2005/02/08 06:06:31
    • Status: offline
    Re: PIC 18f Assembly 2019/01/06 08:55:08 (permalink)
    0
    pcbbc brilliant solution. Thank you very much...
     
    TOFn = TIMEn x (CALIBRATION2_PERIODS - 1) x 125000 / (CALIBRATION2 - CALIBRATION1)
     
    I will implement in code. 
    #6
    NorthGuy
    Super Member
    • Total Posts : 5431
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: online
    Re: PIC 18f Assembly 2019/01/06 09:22:14 (permalink)
    +1 (1)
    pcbbc
    NorthGuyYou also can pre-calculate (CALIBRATION2_PERIODS - 1) x 125000 / (CALIBRATION2 - CALIBRATION1) once these values are available, then all you have left is one multiplication.
    Not if you are using integer maths and you want to maintain your accuracy.

     
    Integer division can always be replaced with integer multiplication (followed by appropriate shift). You just need to pre-calculate 1/x and then you can do multiplications as much as you want as long as 1/x stays the same.
     
    BTW: GCC always does this when dividing by a constant.
     
    #7
    HOODEY
    Super Member
    • Total Posts : 576
    • Reward points : 0
    • Joined: 2005/02/08 06:06:31
    • Status: offline
    Re: PIC 18f Assembly 2019/01/11 13:21:28 (permalink)
    0
    Implemted the code but some strange things are happening in the simulator. I move stuff to Dividend0  using MOVFF but 
    the clrf instruction is not clearing the register.
     
     
    post edited by HOODEY - 2019/01/11 13:24:52

    Attached Image(s)

    #8
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC 18f Assembly 2019/01/11 13:31:58 (permalink)
    0
    MOVFF can address anywhere in RAM, but CLRF can only access the 256 bytes bank selected by the BSR register.
    Try adding
        BANKSEL Dividend0

    before the clrf instruction. If you know all those variables are in one bank, you only need it once for that block of code.
     

    Nearly there...
    #9
    HOODEY
    Super Member
    • Total Posts : 576
    • Reward points : 0
    • Joined: 2005/02/08 06:06:31
    • Status: offline
    Re: PIC 18f Assembly 2019/01/12 07:32:48 (permalink)
    0
    That workedmr green: mr green.Much appreciate qhb . I thought I had moved a way from the dreadful banksel.
    Swore the clrf xxxx,1 notation would have taken care of this.
     
    #10
    1and0
    Access is Denied
    • Total Posts : 9206
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC 18f Assembly 2019/01/12 09:14:19 (permalink)
    0
    HOODEY
    I thought I had moved a way from the dreadful banksel.
    Swore the clrf xxxx,1 notation would have taken care of this.

    Look at the addresses of those variables. They are located in Bank 2. If the current bank in the BSR register is not of Bank 2, then you will need BANKSEL.
    #11
    HOODEY
    Super Member
    • Total Posts : 576
    • Reward points : 0
    • Joined: 2005/02/08 06:06:31
    • Status: offline
    Re: PIC 18f Assembly 2019/01/12 10:35:16 (permalink)
    0
    Division routine on piclist is full or errors. Proceeded to another one and compile error on  SKPC.
     
    Is this the equivalent of btsfsc  STATUS,C? If that is the case why no simply use the pic instruction.
     
      MOVF    Divisor+2,W     ; get LSB of divisor
    btfsc Temp2, 7
    goto Div48by24_add

    ; subtract 24 bit divisor from 24 bit temp
    SUBWF Temp+2,F ; subtract

    MOVF Divisor+1,W ; get middle byte
    SKPC ; if overflow ( from prev.
     
    #12
    1and0
    Access is Denied
    • Total Posts : 9206
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC 18f Assembly 2019/01/12 10:59:55 (permalink)
    0
    HOODEY
    Division routine on piclist is full or errors. Proceeded to another one and compile error on  SKPC.
     
    Is this the equivalent of btsfsc  STATUS,C? If that is the case why no simply use the pic instruction.

    SKPC is a pseudo-instruction for the 12-bit and 14-bit instruction word PIC devices; no idea why Microchip does not support these for the PIC18, but you can create macros for them if you like. To me, these macros are more readable and less typing than a, for example, BTFSS STATUS,C instruction. ;)
     
     
    #13
    1and0
    Access is Denied
    • Total Posts : 9206
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC 18f Assembly 2019/01/12 11:11:26 (permalink)
    +2 (2)
    HOODEY
     MOVF Divisor+2,W ; get LSB of divisor
     
    btfsc Temp2, 7
    goto Div48by24_add

    ; subtract 24 bit divisor from 24 bit temp
    SUBWF Temp+2,F ; subtract

    MOVF Divisor+1,W ; get middle byte
    SKPC ; if overflow ( from prev.


    That snippet looks like part of a multi-bytes subtraction. Learn to use the SUBWFB instruction on your PIC18 device. ;)  That is, don't blindly copy and use others code, implement the algorithm yourself instead. ;)
     
    #14
    HOODEY
    Super Member
    • Total Posts : 576
    • Reward points : 0
    • Joined: 2005/02/08 06:06:31
    • Status: offline
    Re: PIC 18f Assembly 2019/01/17 18:08:56 (permalink)
    0
    Got it sorted just did not want to spend my effort understanding the wheel when I have an engine to build.
    #15
    1and0
    Access is Denied
    • Total Posts : 9206
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC 18f Assembly 2019/01/18 14:14:56 (permalink)
    +1 (1)
    HOODEY
    Got it sorted just did not want to spend my effort understanding the wheel when I have an engine to build.

    So you want inferior parts for your engine?  The additional instructions will make it a more efficient engine. ;)
     
    #16
    Denge
    Super Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2016/03/03 07:23:12
    • Location: belgium
    • Status: offline
    Re: PIC 18f Assembly 2019/01/18 15:54:40 (permalink)
    0
    I suggest to switch to PIC 24 or even PIC33 for this kind of calculations. Far more simpler to do fixed point calculations.
    #17
    Jump to:
    © 2019 APG vNext Commercial Version 4.5