• AVR Freaks

Helpful ReplyHot!C18 48bit addition to form kWh counter. (from page 3)

Page: < 12345.. > >> Showing page 4 of 6
Author
NKurzman
A Guy on the Net
  • Total Posts : 18901
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: online
Re: 64bit addition. 2020/06/13 22:11:26 (permalink)
+3 (3)
There are libraries called “bignum”
To generate numbers of any arbitrary Precision. You can search or here are some links.

https://en.m.wikipedia.or...y-precision_arithmetic

https://en.m.wikipedia.or...ion_Arithmetic_Library

https://gmplib.org/
#61
ric
Super Member
  • Total Posts : 28361
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: 64bit addition. 2020/06/13 22:37:12 (permalink)
+2 (2)
Before we get too far down the rabiit hole, I should just point out that the OP's requirement has been met by 1and0's code in post#46.
All the discussion since has just been optimising the technique.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#62
andy_n
Senior Member
  • Total Posts : 155
  • Reward points : 0
  • Status: offline
Re: 64bit addition. 2020/06/13 22:44:57 (permalink)
0
Morning,
 
Ken: Numbers up to 15,000 should be added over more than 10 years (kWh counter).
Float would be simple but not exact.
 
1and0: my compiler shows 32, for whatever reason.
 
It is an academic discussion, but where is the risk of carry. Immediately after the addition carry should be safe.
Can interrupt destroy it? The compiler must save status bits before the interrupt.
RIC, did you see a warning. Can you send it to me.
 
My project has been working perfectly for 15 years.
I can't risk switching to XC8. Not for 64bit addition only.
I tried many years ago. It was a disaster.
 
 
 
 
#63
ric
Super Member
  • Total Posts : 28361
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: 64bit addition. 2020/06/13 22:56:26 (permalink)
+2 (2)
andy_n
It is an academic discussion, but where is the risk of carry. Immediately after the addition carry should be safe.

It is making use of a CPU resource that is not yours to use. It's like assuming the W register won't be trashed by the compiler.
Yes, you are quite right that carry is almost certainly going to still have the result of the previous addition when you do your test.
If you test that it works, and then NEVER CHANGE THE COMPILER VERSION OR SETTINGS, then you can probably get away with it.
However, the C standard does not require it to work. That is why professional programmers will avoid this technique.
e.g. the compiler may need to do some calculations to work out where to store the result of the calculation. It is perfectly entitled to trash the STATUS register while doing this, before you get a chance to test the carry bit.

Can interrupt destroy it? The compiler must save status bits before the interrupt.

No. All registers are preserved by an interrupt.
 

RIC, did you see a warning. Can you send it to me.

No, the compiler won't issue a warning. You just need to be aware that using registers "owned" by the compiler can cause unexpected problems.
Have a look in the C18 User Guide (hlpC18ug.chm) under "Compiler-Managed Resources" where it says:

Certain special function registers and data sections of the PIC18 PIC microcontrollers are used by MPLAB C18 and are not available for general purpose user code. Table: Compiler-Managed Resources indicates each of these resources and their primary use by the compiler. All compiler-managed resources are automatically preserved across an ISR.

The STATUS register is listed in that table.
 
post edited by ric - 2020/06/13 23:00:33

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#64
JPortici
Super Member
  • Total Posts : 1158
  • Reward points : 0
  • Joined: 2012/11/17 06:27:45
  • Location: Grappaland
  • Status: offline
Re: 64bit addition. 2020/06/13 23:16:55 (permalink)
+1 (3)
See how things are better when you don't "feel lazy" and want a solution handed to you pronto?
you would have this solved at least a week ago if you had a different attitude, this attitude.
 
reply #63 should have been your reply #3
 
but hopefully, this is over and done.
 
In my opinion this way of writing C is not what i would call "elegant", what i would call "elegant" is the original solution: clear and concise C, perfectly portable, easily expandable, meaning of what you're doing is clear to everyone else reading the code. trying to optimize the way you are reminds me of when i though i should always be smarter than the compiler... assembly programmers in C... let's just say i don't do this anymore.
 
Questions: is it really necessary to optimize this routine while staying in C? does it happen this often it's impacting the performance of the program? or do you really really need to squeeze out every possible byte?
 
in the last case, i don't understand why not just implement the addition in assembly and call this routine from C..
(I assume this is posible and easy to do as it is in XC8/16/32.. It's been a long time since i used C18)
post edited by JPortici - 2020/06/13 23:18:31
#65
dan1138
Super Member
  • Total Posts : 3840
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: 64bit addition. 2020/06/14 00:20:05 (permalink)
+4 (4)
andy_n
Wouldn't it be more elegant to use STATUSbits?
 
    addend1.lo += addend2;
    if (STATUSbits.C) addend1.hi++;
 
I tried it. It seems to work and saves 32 bytes of ROM.

If you are going compiler and controller specific why not full on inline assembly:
typedef unsigned short uint16_t;
typedef unsigned long  uint32_t;

typedef struct {
        uint16_t lo;
        uint32_t hi;
} uint48_t;

volatile uint48_t Accumulator_48;

void Accumulate48(uint16_t addend)
{
    PROD = addend;
    _asm  
        movlb   Accumulator_48
        movf    PRODL,0,0
        addwf   Accumulator_48,1,1
        movf    PRODH,0,0
        addwfc  Accumulator_48+1,1,1
        movlw   0
        addwfc  Accumulator_48+2,1,1
        addwfc  Accumulator_48+3,1,1
        addwfc  Accumulator_48+4,1,1
        addwfc  Accumulator_48+5,1,1
    _endasm
}

void main(void)
{
    for(;;)
    {
        Accumulate48(14999);
    }
}

#66
andy_n
Senior Member
  • Total Posts : 155
  • Reward points : 0
  • Status: offline
Re: 64bit addition. 2020/06/14 00:40:45 (permalink)
-4 (6)
Hey JPortici,
 
Can't you leave it?
Can you live out your hate somewhere else!
It is no longer possible to talk here!
 
 
#67
JPortici
Super Member
  • Total Posts : 1158
  • Reward points : 0
  • Joined: 2012/11/17 06:27:45
  • Location: Grappaland
  • Status: offline
Re: 64bit addition. 2020/06/14 01:02:08 (permalink)
+2 (4)
in fact, i can!
this is over and done

 
what about the second part, i'm not the first that has asked, in fact dan did it again just above.
Why the need to optimize every possible byte, sacrificing clarity and possibly letting nasty bugs in?
(altough it don't think it will happen, but still it's not good practice IMHO to use resources reserved by the compiler. We all did it at some point, but i saw it lead to bad habits)
Why not go full assembly for this routine, it will be even faster, will take even less bytes and it will be clearer code?
 
If you already answered, i must have missed it.
#68
Hen
Senior Member
  • Total Posts : 88
  • Reward points : 0
  • Joined: 2018/10/24 04:01:44
  • Location: 0
  • Status: offline
Re: 64bit addition. 2020/06/14 02:23:08 (permalink)
0
dan1138
If you are going compiler and controller specific why not full on inline assembly

I'd done that ages ago LoL: LoL
Tricky and real-timey works may require dirty deeds but I would put inline assys in a separate function.
#69
andy_n
Senior Member
  • Total Posts : 155
  • Reward points : 0
  • Status: offline
Re: 64bit addition. 2020/06/14 03:53:50 (permalink)
0
Dan thanks, very interesting. 
 
JPortici,
If you can, make it, please, please!
 
I have good experience with "optimize every possible byte" so far. 
Compiler makes it too!
 
 
 
 
 
#70
1and0
Access is Denied
  • Total Posts : 11129
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: 64bit addition. 2020/06/14 09:14:28 (permalink)
+2 (2)
dan1138
If you are going compiler and controller specific why not full on inline assembly:
volatile uint48_t Accumulator_48;
 

        movlb   Accumulator_48



Don't think that is correct. Does C18 inline assembly have a BANKSEL directive?
 
 
andy_n
I have good experience with "optimize every possible byte" so far. 


From the C18 User's Guide, "auto parameters are pushed onto the software stack from right to left. For multi-byte data, the low byte is pushed onto the software stack first."
 
So, on the subject of optimization, why not locate Accumulator_48 in the Access Bank and take a step further:
void Accumulate48(uint16_t addend)
{
    _asm
        movf    POSTDEC1,1,0    ; point to high byte of addend
        movf    POSTDEC1,1,0    ; point to low  byte of addend
       
        movf    POSTINC1,0,0
        addwf   Accumulator_48+0,1,0
        movf    POSTINC1,0,0
        addwfc  Accumulator_48+1,1,0
        movlw   0
        addwfc  Accumulator_48+2,1,0
        addwfc  Accumulator_48+3,1,0
        addwfc  Accumulator_48+4,1,0
        addwfc  Accumulator_48+5,1,0
    _endasm
}

 
Edit: A further step would be to locate the "addend" in Access Bank too. ;)
 
post edited by 1and0 - 2020/06/14 09:18:48
#71
dan1138
Super Member
  • Total Posts : 3840
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: 64bit addition. 2020/06/14 13:46:00 (permalink)
+1 (1)
1and0
dan1138
If you are going compiler and controller specific why not full on inline assembly:
volatile uint48_t Accumulator_48;
        movlb   Accumulator_48

Don't think that is correct. Does C18 inline assembly have a BANKSEL directive?

You are correct to be concerned. MPASM does toss its cookies when 'movlb' is used instead of BANKSEL. It would be wrong with XC8 to not use the BANKSEL directive. Now C18 is different, C18 asserts an error when BANKSEL is used, but does select the correct bank when using 'movlb' with the inline assembler.
 
#72
PStechPaul
Super Member
  • Total Posts : 2919
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: 64bit addition. 2020/06/14 14:14:57 (permalink)
+2 (2)
As I understand it, the requirement is to maintain a total of kWh over a period of 10 years, with the total updated with numbers up to 15,000. I assume that this will be updated hourly, and units will actually be in watt-hours. So the maximum will be 15,000 x 24 x 365 x10 = 1,314,000,000. A 32 bit unsigned long is a maximum of 4,294,967,296, so that would be sufficient for over 30 years at maximum constant 15 kW, which is unlikely. It would be simple enough to monitor each addition to determine if overflow occurred, and then increment an 8 bit counter which would give the required 40 bits when added to the 32 bit accumulator.
 
Another issue is that the equipment supplying the W-h values for update has a finite accuracy and resolution, probably no better than 0.1%, and the timing intervals for data accumulation are also likely no better than 10 PPM, or 0.001%, so the resulting total kWh also has limited accuracy. A 32 bit number has resolution of 2e-10, so most of the digits are actually insignificant.
 
These observations and assumptions are based on the limited information that has been supplied, so perhaps there are other considerations that might come into play, but I don't really see the problem with 32 bit numbers.
 
 

 
#73
Ken_Pergola
Super Member
  • Total Posts : 2245
  • Reward points : 0
  • Joined: 2003/11/07 12:48:48
  • Status: offline
Re: 64bit addition. 2020/06/14 14:48:24 (permalink)
+1 (1)
Hello Andy,
 
This is how you arrived at 48-bits, correct?:
You needed the addition to happen every second which requires 43-bit minimum and hence you rounded up the sum variable to the next byte for 48-bits total. I think that is where your 48-bit requirement came from, correct?:
15,000 [max value to add] * (60*60*24) [seconds in day]  * 365.25 days in year * 10 years = 4,733,640,000,000
 
42-bits: 0 to 4,398,046,511,103 (shy of requirements)
43-bits: 0 to 8,796,093,022,207 (minimum to meet requirements)
48-bits: 0 to 281,474,976,710,655 (final implementation in C code)
 
No chance of overflow with the final 48-bit decision (or with 43-bit and higher for that matter) if the above specification requirement is accurate.
 
Best regards,
 
Ken
 
#74
1and0
Access is Denied
  • Total Posts : 11129
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: 64bit addition. 2020/06/14 18:16:41 (permalink)
+2 (2)
Ken_Pergola
This is how you arrived at 48-bits, correct?:

 
You're correct.
 
log(4,733,640,000,000) / log(2) = 42.1
 
So 43 bits is needed and it's rounded up to the nearest byte of 48 bits, which can last over 594 years. ;)
 
post edited by 1and0 - 2020/06/14 18:21:07
#75
1and0
Access is Denied
  • Total Posts : 11129
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: 64bit addition. 2020/06/14 18:39:53 (permalink)
+2 (2)
dan1138
Now C18 is different, C18 asserts an error when BANKSEL is used, but does select the correct bank when using 'movlb' with the inline assembler.

 
Weird but interesting!  It does not fit the syntax in the datasheet; i.e. I'd expect it to be
     movlb   Accumulator_48 >> 8 

 or
        movlb   high(Accumulator_48)

 
#76
andy_n
Senior Member
  • Total Posts : 155
  • Reward points : 0
  • Status: offline
Re: 64bit addition. 2020/06/14 23:11:00 (permalink)
0
Thanks for answers.
 
max 15,000 is calculated Watt from measure device *3,6
230V*16A=3680W*3,6=13248 max  
 
Paul, I think you forgot seconds. 15,000 x 24 (*60*60) x 365 x 10  :)
 
Another think. I like this solution: 'if (STATUSbits.C)' but I'm unsure now. The STATUS bits are 'published' in the compiler. What's the danger?: Disassembly looks great.
 
 
 
#77
ric
Super Member
  • Total Posts : 28361
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: 64bit addition. 2020/06/14 23:12:54 (permalink)
+2 (2)
andy_n
...
Another think. I like this solution: 'if (STATUSbits.C)' but I'm unsure now. The STATUS bits are 'published' in the compiler. What's the danger?: Disassembly looks great.

We've just spent the last two days discussing precisely that point!
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#78
andy_n
Senior Member
  • Total Posts : 155
  • Reward points : 0
  • Status: offline
Re: 64bit addition. 2020/06/14 23:53:54 (permalink)
-1 (1)
ric, i don't want to be rude. Why do you answer when it annoys you? How should your answer help.
ric please ... you have to pay for it. I don't understand.
 
I like STATUS bits. It could make things a lot easier if I can use it.
 
#79
ric
Super Member
  • Total Posts : 28361
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: 64bit addition. 2020/06/14 23:59:54 (permalink)
+2 (2)
I went to a great deal of effort to explain all the pros and cons to you, and you behave as if no-one has answered you.
THAT is why I am a little annoyed.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#80
Page: < 12345.. > >> Showing page 4 of 6
Jump to:
© 2020 APG vNext Commercial Version 4.5