|
|
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
Mod ( % ) and uint64_t |
Posted: Wed Apr 14, 2021 4:20 pm |
|
|
We were updating our ADF4350 code to the latest reference driver and found an issue. This code works on a 32-bit/64-bit PC compiler, but on the 16-bit compiler I am unsure how to make the mod operation behave:
Code: | uint64_t v1 = 732000UL;
uint64_t v2 = 2600UL;
printf ("1) %lu\r\n", 732000UL % 2600UL);
printf ("2) %lu\r\n", v1 % 2600UL);
printf ("3) %lu\r\n", 732000UL % v2);
printf ("4) %lu\r\n", v1 % v2);
|
Results on PIC24:
Code: | Universal 14-Apr-21 17:16:48
1) 1400
2) 66936
3) 66936
4) 66936
|
The 1440 is the matching value from a PC compiler. We did some quick tests trying to cast things, and then tried to use 64-bit fake variables with no luck.
The original uses a 64-bit tmp variable and then does the math with two 32-bit values. I just provided this as a simple example to see if there is a cast or something we can use.
Thoughts appreciated.
NOTE: Using uint32_t it works, for these specific values (none larger than 32-bit). _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Last edited by allenhuffman on Thu Apr 15, 2021 8:52 am; edited 1 time in total |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Apr 14, 2021 4:24 pm |
|
|
For reference, this version produces 1400 for each try:
Code: | uint64_t result = 0;
uint32_t v1 = 732000UL;
uint32_t v2 = 2600UL;
result = 732000UL % 2600UL;
printf ("1) %lu\r\n", result);
result = v1 % 2600UL;
printf ("2) %lu\r\n", result);
result = 732000UL % v2;
printf ("3) %lu\r\n", result);
result = v1 % v2;
printf ("4) %lu\r\n", result); |
_________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Apr 14, 2021 4:28 pm |
|
|
And, for specific reference, here is code that replicates what we are porting:
Code: | uint32_t r0_fract = 0;
uint64_t tmp = 732000UL;
uint32_t r1_mod = 2600UL;
r0_fract = 732000UL % 2600UL;
printf ("1) %lu\r\n", r0_fract);
r0_fract = tmp % 2600UL;
printf ("2) %lu\r\n", r0_fract);
r0_fract = 732000UL % r1_mod;
printf ("3) %lu\r\n", r0_fract);
r0_fract = tmp % r1_mod;
printf ("4) %lu\r\n", r0_fract); |
_________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Apr 15, 2021 2:05 am |
|
|
If you look at the manual 'Basic types', unsigned int64, is listed as 'N/A'.
The compiler allows you to select them, but does not correctly support them.
It is silly that the stdint.h, includes them. Several of the operators go wrong
if these are used. Includes simple division, mod etc... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Apr 15, 2021 4:23 am |
|
|
What is causing it, is a maths error, that I reported a while ago, and
was then fixed but seems to have re-appeared. When the code performs a
int64*int64 sum, it returns twice the value it should.
So if you code mod as:
Code: |
uint64_t mod(uint64_t a, uint64_t b)
{
uint64_t div;
div=(a/b);
b=(b*div)/2; //urgh - have to divide by 2 to get the right result...
return a-b;
}
|
The sum 'b*div' returns twice the value it should.
If you let it return this double value, you get the results you are seeing. So
this is happening inside the supplied function... |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
TIP: I2C standard 7-bit addresses versus CCS 8-bit addresses |
Posted: Thu Apr 15, 2021 8:54 am |
|
|
Thanks for the confirmation. I also had e-mailed CCS so they will be aware if this is an issue previously mitigated.
For the adf4350 drive, the bit of code was made to work just by casting to uint32_t (we can do this since we never use a frequency above the max of a 32-bit value):
Code: | dev->r0_fract = (uint32_t)tmp % (uint32_t)dev->r1_mod; |
We have a similar math issue we should have tracked down in a few and I'll also share the results in case someone else with PIC24 tries to port this driver. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
|
Posted: Thu Apr 15, 2021 9:01 am |
|
|
Ttelmah wrote: | If you look at the manual 'Basic types', unsigned int64, is listed as 'N/A'.
The compiler allows you to select them, but does not correctly support them.
It is silly that the stdint.h, includes them. Several of the operators go wrong
if these are used. Includes simple division, mod etc... |
Interesting. Unsigned is N/A, but signed claims to be supported:
Quote: | Note: All types, default are unsigned. [PCD] All types, except float char, by default are signed. However, may be preceded by unsigned or signed (Except int64 may only be signed) . Short and long may have the keyword INT following them with no effect. Also see #TYPE to change the default size. |
I'll have to see if using an int64_t has different results. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Apr 15, 2021 5:16 pm |
|
|
re: What is causing it, is a maths error, that I reported a while ago, and
was then fixed but seems to have re-appeared. When the code performs a
int64*int64 sum, it returns twice the value it should.
yeesh, poor lil PIC trying to do CRAY computer type math ! I'd like to see lowly humans do a int64 * int64 with pencil and paper !!
quick, what's 12345678 * 87654321 ??
it has got me wondering, if someone's got a 'math coprocessor' for PICs.... |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Thu Apr 15, 2021 11:37 pm |
|
|
temtronic wrote: | re: What is causing it, is a maths error, that I reported a while ago, and
was then fixed but seems to have re-appeared. When the code performs a
int64*int64 sum, it returns twice the value it should.
yeesh, poor lil PIC trying to do CRAY computer type math ! I'd like to see lowly humans do a int64 * int64 with pencil and paper !!
quick, what's 12345678 * 87654321 ??
it has got me wondering , if someone's got a 'math coprocessor' for PICs.... |
The funny thing is that somebody was selling a PIC as a 'maths processor'
for another chip a while ago!...
I've used maths co-processors with a PIC a long time ago. However there
are very few available now.
Remember Allen is using a PIC24, so single cycle 16bit multiply and
divide. Makes the actual work for generating 64bit maths a lot easier. This
is why CCS offer 64bit on these processors, but not on the PIC16/18's.
64bit maths is not even remotely 'Cray' territory. I did 64bit libraries
for the old Z80, something over 40 years ago. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Apr 16, 2021 4:42 am |
|
|
re: the old Z80, something over 40 years ago.
sniff,sniff, great, make me really feel like the dinosaur.....
I still have 2 or 3, Z80 machines here.and they STILL work ! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Apr 16, 2021 6:01 am |
|
|
I know the feeling. Still occasionally having to service some early PIC
systems based on the 16C84. My first ever MicroProcessor was the then
'new' Intel 4004. I did a system based on the Z80, which at the time
was totally 'state of the art' design. Pad-less vias, four layer board, and
hole sizes just 0.4mm. The whole board was less than half the size of a modern mobile phone. Used a brand new ASIC. Military application, and just
three years ago, I had to help in the new redesign of the unit, that was at
that time still in use!... |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Apr 16, 2021 9:45 am |
|
|
The PICAXE is a standard PIC, but has it's own bootstrap loader and
firmware. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Apr 16, 2021 11:31 am |
|
|
gee... the ORIGINAL 'Boris'(late 60s....) used an inductive loop around the room fed by an amplifier output(think there was a 'backwards wired' tranformer. An audio 'antenna' inside Boris picked up the signal, real transistors amplified it, played on a 3" speaker in the skull. With 2 9 volt batteries in parallel, you could carry Boris anywhere in the room ,and he'd 'speak'.....
I'd think today's 'Boris' would be a hologram with voice eminating from it.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|