Use of double intead of float

Hello crowd,

I’ve noticed that a lot of usage of double as floating-point types. So many infact that it is probably intended. @Antun_Skuric you do know that not post-fixing floating point constant is interpreted as a double (on most compilers with default settings, at least)?

If you look at foc_utils

I don’t see a single f postfix.

it should read:

#define _sign(a) ( ( (a) < 0 )  ?  -1   : ( (a) > 0 ) )
#define _round(x) ((x)>=0?(long)((x)+0.5f):(long)((x)-0.5f))
#define _constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define _sqrt(a) (_sqrtApprox(a))
#define _isset(a) ( (a) != (NOT_SET) )
#define _UNUSED(v) (void) (v)

// utility defines
#define _2_SQRT3 1.15470053838f
#define _SQRT3 1.73205080757f
#define _1_SQRT3 0.57735026919f
#define _SQRT3_2 0.86602540378f
#define _SQRT2 1.41421356237f
#define _120_D2R 2.09439510239f
#define _PI 3.14159265359f
#define _PI_2 1.57079632679f
#define _PI_3 1.0471975512f
#define _2PI 6.28318530718f
#define _3PI_2 4.71238898038f
#define _PI_6 0.52359877559f

#define NOT_SET -12345.0f

It can have a dramatic impact on performance, especially for 8-bit MCU, but also for M0, M4 and M4F cores. I’ve read somewhere that the M4F reverts to software based floating poins when presented with doubles.

When I have a little free time, I’ll try to throw a benchmark or two on my samd21 and my atmega1280.

For M4F users, you might be interested by this Be aware: Floating Point Operations on ARM Cortex-M4F

Hey @malem,

Another user recently noticed this, and if you look on the GitHub there is a pull request fixing all the double constants to float.
I plan to test it out on SAMD21 tonight if I have time…
I also finally started looking at the current sensing code last night, but I’m still trying to figure out everything you’ve done! You made so much progress!

Hey!

The EVSYS+DMA current sense code is working quite well, but we would need to synchronize all TCCs togheter (if I read your comments correctly, it’s on your TODO list, I think we could source them on the same clock and then start the clock, but I’m missing some details related to dead time insertions, would that de-sync clocks?

I’ve just completed my SPI+DMA encoder readout POC in a test “main.cpp”, I’m about to integrate it . I tried to trigger it from EVSYS, but for that I’d need hardware-controlled SS. On the samd21 HW_SS, pulls high the SS between each 8bits chunks, and the AS5047 doesn’t like it. So I use TCCx_OVF handler to pull SS low and trigger the DMA transfer instead. works well, but took me quite a while to master/debug everything.

With the samd51/same51 there’s a 32bits SPI transfer mode. I’ll try it, maybe tomorrow.

Also, I made this feature table. we could consolidate your TCC code with it. I used it on my new spi class to check pin/sercom/pad assignment, and I’ll soon use it on my ADC code too

ATM I connect all the TCCs to the same GCLK, so that part is covered. What’s missing is stopping, setting the CCs to zero and then restarting the clock all in a synchronised way…

No, HW dead-time is independent of this, and SW dead-time in fact depends on synchronised clocks and therefore currently is only possible if high and low side are on the same TCC (and hence in sync).

The idea here being to make the SPI asynchronous to the main loop? This will be way cool, look forward to seeing it!

I don’t know if it will like this either. It uses 16 bit words, and wants nCS pulled high for >350ns between each 16bit transfer.

I’m not sure I understand this. Do you mean syncing it to the PWM in some way? Or is this its own timer, being used for the purpose of timing the nCS high period?

Your table looks more comprehensive than the one I made - I just have the TC, TCC and WO information. I’d be very happy to consolidate, I think it would be better to have just one SAMD table.

I also think there is a need to link the hardware PWM driver and the current sensing code at some level - since the API is based on pin numbers, the current sensing probably needs to know which TCC channels the PWM driver decided to use for each pin, right?

ATM I connect all the TCCs to the same GCLK, so that part is covered. What’s missing is stopping, setting the CCs to zero and then restarting the clock all in a synchronised way…

Good, doesn’t look too hard!

The idea here being to make the SPI asynchronous to the main loop? This will be way cool, look forward to seeing it!

Exactly. I want the readings to be as close as possible (in time) to the current-sense readings. It was very hard to achieve.

I don’t know if it will like this either. It uses 16 bit words, and wants nCS pulled high for >350ns between each 16bit transfer.

Some premiliminary tests with the samd21 tells me the AS5047 will just ignore the extra 16bits. Little unclean, but maybe a lesser evil.

I also think there is a need to link the hardware PWM driver and the current sensing code at some level - since the API is based on pin numbers, the current sensing probably needs to know which TCC channels the PWM driver decided to use for each pin, right?

Exactly, my sharp-eyed friend!
It will reuquire some generic API at some point, getting there.

[Edit: not exaclty after all. the ADC is configured in input-scan mode. So I only listen to TCC “A” OVF in DSTOP mode, and scan all 3 pins. If the 3 tcc’s are top synchronized, the readings will only be delayed by whatever the ADC sampling time is, iow the best it can get with a single ADC]

Hey @runger

Just pushed a first working POC intergrating evsys+dma current sense (timed/triggered by TCC0) and dma SPI-magnetometer reading also trigeered by TCC0 (no evsys here, had to use a very light IRQ)

I’m also heading towards a “no-surprizes” API where every EVSYS and DMAC channels are configured centrally, instead of hidden in their implementation details.

if you look around here
you might begin to understand how it’s done.

I’m now quite satisfied with the sam[d,e]51 architecture. I’m heading toweards same53, and ethernet. might give a look later to smt and RPI2040, but I love samd/e’s EVSYS and DMAC’s flexibility. daunting but capable

Wow @malem,

You have really dug deep to make this work, we ll done!
These are the same types of issues I was having with the stm32 implementation.
Very very very complicated to do, and it seems even a bit too complicated to do honestly. :smiley:

I’ve first started with interrupt based with regular adc reads, then fast conversion using dma, then sync dma conversion with a pwm timer and at the end I think it will be dma + pwm interrupts instead :smiley:

Glad you like it! It might require some “generic” API changes in the end. For example I spun out a Magnetic Sensor class, SPI, PWM and maybe analog could inherit from it. I tried to postpone/reduce float computations as much as possible. Also, note the uint64_t & timestamp_us api in getRawCount. I think it’s the right way to concilliate interrupt and poll-based apis

On the original topic of this thread: the pull request for float constants has been merged in the dev branch, so @malem you don’t have to do this work.
The speed improvement for SAMD21 seems to be almost 20%. :partying_face:

Not bad at all for such a simple fix