Floating point calculation in an 8 bit processor
Floating point calculation in an 8 bit processor
Oh my word this is hair raising. I need to stay away from floating point but cant because I am dividing a number. My processing time is 186us for the calculation but my loop time limit is 360us and my ucontroller still needs to run interrupts, a 16 bit timer, input capture port which is timed, create a PWM signal, refresh a I2C bus and scan 3 buttons without missing anything.
I might be able to make it....
I might be able to make it....
Fixed pt is better than float on 8 bit cpus. It wont solve all your issues but its a start. Playing with int priorities is something else you can do to speed them up. Ive been writing embedded soft professionally for 6 years, those cpus are much faster than most people think.
DFI LanParty X48 LT-2TR
Intel Q9450 @ 3.2Ghz
Dell 24" 2408WFP | Phillips 37" 1080p
Sapphire HD4870 X2 2GB
4GB Corsair DDR-2 1066 | Thermalrite 120 Ultra Extreme | G9 Mouse | G15 Keyboard
Vista Ultimate x64
Intel Q9450 @ 3.2Ghz
Dell 24" 2408WFP | Phillips 37" 1080p
Sapphire HD4870 X2 2GB
4GB Corsair DDR-2 1066 | Thermalrite 120 Ultra Extreme | G9 Mouse | G15 Keyboard
Vista Ultimate x64
-
- Registered User
- Posts: 2412
- Joined: 30 Apr 2003, 02:00
- Location: on a ring, far,far away
- Contact:
completely agree with you, but my design just got out of hand last time, and i had work around alot of timing issues... my code could have simpler and my design less complex, but i was too close to deadline to rework the solution, so i had to cheatHex_Rated wrote:Fixed pt is better than float on 8 bit cpus. It wont solve all your issues but its a start. Playing with int priorities is something else you can do to speed them up. Ive been writing embedded soft professionally for 6 years, those cpus are much faster than most people think.
A lot of my clients have got spaghetti coded overly complex designs (mostly cause they cant make up their fn minds). Its what being an embedded soft eng is all about!
DFI LanParty X48 LT-2TR
Intel Q9450 @ 3.2Ghz
Dell 24" 2408WFP | Phillips 37" 1080p
Sapphire HD4870 X2 2GB
4GB Corsair DDR-2 1066 | Thermalrite 120 Ultra Extreme | G9 Mouse | G15 Keyboard
Vista Ultimate x64
Intel Q9450 @ 3.2Ghz
Dell 24" 2408WFP | Phillips 37" 1080p
Sapphire HD4870 X2 2GB
4GB Corsair DDR-2 1066 | Thermalrite 120 Ultra Extreme | G9 Mouse | G15 Keyboard
Vista Ultimate x64
I am using an Atmel ATmega168 uC. My problem is that I need to use this formula: (X/(Y*0.00005))*3600). It is the only way I can think of to get the values I need. So can you see the floating point? The X value is set only once but the Y value is constantly changing. The Y value can be anything from 0.0000036 to 4294967296. The X value can be anything from 0,1 to 1000 when set. So if you could think of another method of working this out without dividing or using floats, I am all ears...
The range is too much to use a 32bit unsigned long fixed pt calc. You do need to use a float or maybe a 64bit long if the compiler supports it. You could implement your own 64bit integer format by combining 2 32bit ints. Integer division is much faster than floating point division. It is also possible to use bit shifts for multiplication and division on integer calculations which will squeeze even more performance out. eg MUL 3600 at the end would become:
((ans << 8 ) + (ans << 6) + (ans << 5) + (ans <<3) )<<1) + ((ans <<8 ) + (ans << 6) + (ans << 5) + (ans << 3) ) <<3 )
Which works out to be: 320ans x 2 + 320ans x 8 = 10x320ans = 3200ans
Given ans = (X/(Y/20,000))
Have you tried timing the calculation to see if it truly is the bottleneck? It's possible that you're looking in the wrong place.
((ans << 8 ) + (ans << 6) + (ans << 5) + (ans <<3) )<<1) + ((ans <<8 ) + (ans << 6) + (ans << 5) + (ans << 3) ) <<3 )
Which works out to be: 320ans x 2 + 320ans x 8 = 10x320ans = 3200ans
Given ans = (X/(Y/20,000))
Have you tried timing the calculation to see if it truly is the bottleneck? It's possible that you're looking in the wrong place.
DFI LanParty X48 LT-2TR
Intel Q9450 @ 3.2Ghz
Dell 24" 2408WFP | Phillips 37" 1080p
Sapphire HD4870 X2 2GB
4GB Corsair DDR-2 1066 | Thermalrite 120 Ultra Extreme | G9 Mouse | G15 Keyboard
Vista Ultimate x64
Intel Q9450 @ 3.2Ghz
Dell 24" 2408WFP | Phillips 37" 1080p
Sapphire HD4870 X2 2GB
4GB Corsair DDR-2 1066 | Thermalrite 120 Ultra Extreme | G9 Mouse | G15 Keyboard
Vista Ultimate x64
I used the AVR studio simulator and got a processed time of 186us. I also only typed the calculation in the program (about 4 lines of actual code) no other code, So I am pretty sure its the bottle neck.
BUT now this morning things got WAY more complicated. I now have to implement our company protocol in the unit so we can "talk" remotely with the unit. So we decided to throw out the 8-bit and use an 32-bit ARM Thumb uC(AT91SAM7S64). Doesn't make my life any easier though, I still need to do the calculation. I'll look at your suggestion. I forgot I could use bit shifting.
Thanks man.
BUT now this morning things got WAY more complicated. I now have to implement our company protocol in the unit so we can "talk" remotely with the unit. So we decided to throw out the 8-bit and use an 32-bit ARM Thumb uC(AT91SAM7S64). Doesn't make my life any easier though, I still need to do the calculation. I'll look at your suggestion. I forgot I could use bit shifting.
Thanks man.
-
- Registered User
- Posts: 2412
- Joined: 30 Apr 2003, 02:00
- Location: on a ring, far,far away
- Contact:
well, if i understand your problem correctly you have to solve the following:
(X/(Y*0.00005) * 3600)
this can be rewritten as
(X/Y) * (3600/0.00005) = (X/Y)*(72x10^6) = (X/Y)*((64+8 )*10^6)
=(X/Y)*64*10^6 +(X/Y)*8*10^6
the times 64 and times 8 are simple shift right operations (64 = 6 shifts right and 8 = 3 shifts right) and the time 10^6 is a simple addition to a floating points power(unless you are using base 2).
thats how i would streamline the calculate....
(X/(Y*0.00005) * 3600)
this can be rewritten as
(X/Y) * (3600/0.00005) = (X/Y)*(72x10^6) = (X/Y)*((64+8 )*10^6)
=(X/Y)*64*10^6 +(X/Y)*8*10^6
the times 64 and times 8 are simple shift right operations (64 = 6 shifts right and 8 = 3 shifts right) and the time 10^6 is a simple addition to a floating points power(unless you are using base 2).
thats how i would streamline the calculate....