Fixed Point Algorithm For STM32


Fixed Point Algorithm For STM32
  • Abstract
  • For You Information
  • Code
  • Good Luck

  • Abstract
    An implementation of Fixed Point algorithm for STM32 or any other MCUs which have no FPU support.
    For You Information
  • Motive When using STM32F10x MCU, the lack of FPU makes the float computation too slow for a time sensitive processing–for example, an interrupt handle which should get job done in milliseconds. Assembly language is a good way but not best, because it involves the learning of another language and less generic. Not sure if others had built the wheels, but I like to reinvent it–for nothing else, just because I can.
  • Compiler The implementation was written in C++ with templates. By now, most embedded GCC compilers should work well.
  • MCU Architecture The implementation is designed to work on a 32-bit MCU. It works on 16-bit MCU too.
  • Limitation of Precision and Range To represent a float number, the implementation uses partial bits of 32-bit/64-bit integer to represent the integer part and fraction part. It also means the precision and the range the fixed point can represent are limited. For 32-bit representation, the integer part uses 21 bits and the fraction uses 11 bits. For 64-bit, the bits are 42 and 22, just doubled. Further more, the situation of overflow is not considered. It’s your responsibility to handle it.Keep this in mind when using the code.
  • Understanding The Fixed Point I assume you already knew the Fixed Point algorithm. If don’t, please teach yourself. It’s very simple.
  • Liability The code is free for using for anyone. In no event shall I be liable for any situation arising in any way out of the use of the code. Take your own risk to use the code.

  • Code
    Enough talk, let’s show the code.
    /*
     * fxfloat.hpp
     *
     *  Created on: Mar 4, 2019
     *      Author: igame
     */
    
    #ifndef FXFLOAT_HPP_
    #define FXFLOAT_HPP_
    
    namespace igame {
    	template<typename T = int64_t>
    	class FxFloat {
    	public:
    		const uint32_t	fixed_point_32bits				= 11;
    		const uint32_t	fixed_point_64bits				= 22;
    		const uint32_t	fixed_point_bits				= sizeof(T) == 8 ? fixed_point_64bits : fixed_point_32bits;
    		const int64_t	fixed_point_scale				=	(int64_t)1 << fixed_point_bits;
    		const uint64_t	fixed_point_fraction_mask 		= ((uint64_t)0xFFFFFFFFFFFFFFFF >> (32 - fixed_point_bits));
    		const int64_t	fixed_point_max					= (int64_t)0x3F3F3F3F3F3F3F3F;
    		const int64_t	fixed_point_min					= -fixed_point_max;
    
    	public:
    		typedef T value_type;
    		typedef const T const_value_type;
    	public:
    		value_type value{ 0 };
    	public:
    		FxFloat() { }
    
    		FxFloat(const float x) {
    			int64_t integer = ((int64_t)x) << fixed_point_bits;
    			int64_t fract = (int64_t)((x - (int64_t)x) * fixed_point_scale);
    			this->value = integer + fract;
    		}
    
    		/// convert back to float
    		INLINE operator float() {
    			return to_float();
    		}
    
    		/// Assignment
    		INLINE FxFloat& operator = (const int64_t& right) {
    			this->value = right;
    			return *this;
    		}
    
    		INLINE FxFloat& operator = (const float& right) {
    			this->value = from_float(right);
    			return *this;
    		}
    
    		INLINE FxFloat& operator = (const FxFloat& right) {
    			return this->operator = (right.value);
    		}
    
    		/// Add
    		INLINE FxFloat& operator += (int64_t right) {
    			this->value += right;
    			return *this;
    		}
    
    		INLINE FxFloat& operator += (const float& right) {
    			return this->operator += (from_float(right));
    		}
    
    		INLINE FxFloat&  operator += (const FxFloat& right) {
    			return this->operator += (right.value);
    		}
    
    		/// Sub
    		INLINE FxFloat& operator -= (const int64_t& right) {
    			this->value -= right;
    			return *this;
    		}
    
    		INLINE FxFloat& operator -= (const float& right) {
    			return this->operator -= (from_float(right));
    		}
    
    		INLINE FxFloat&  operator -= (const FxFloat& right) {
    			return this->operator -= (right.value);
    		}
    
    		/// Mul
    		INLINE FxFloat& operator *= (const int64_t& right) {
    			this->value *= right;
    			this->value >>= fixed_point_bits;
    			return *this;
    		}
    
    		INLINE FxFloat& operator *= (const float& right) {
    			return this->operator *= (from_float(right));
    		}
    
    		INLINE FxFloat&  operator *= (const FxFloat& right) {
    			return this->operator *= (right.value);
    		}
    
    		/// Div
    		INLINE FxFloat& operator /= (const int64_t& right) {
    			if (right == 0) {
    				this->value = fixed_point_max;
    			}
    			else {
    				this->value <<= fixed_point_bits;
    				this->value /= right;
    			}
    
    			return *this;
    		}
    
    		INLINE FxFloat& operator /= (const float& right) {
    			return this->operator /= (from_float(right));
    		}
    
    		INLINE FxFloat&  operator /= (const FxFloat& right) {
    			return this->operator /= (right->value);
    		}
    
    		private:
    			INLINE int64_t from_float(const float& x) {
    				int64_t integer = ((int64_t)x) << fixed_point_bits;
    				int64_t fract = (int64_t)((x - (int64_t)x) * fixed_point_scale);
    
    				return integer + fract;
    			}
    
    			INLINE float to_float() {
    				(float)this->value / fixed_point_scale;
    			}
    	};
    
    	/// Global Operator Overloading
    	template<typename T>
    	INLINE FxFloat<T> operator + (FxFloat<T>& left, FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res += right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator + (const FxFloat<T>& left, const float& right) {
    		FxFloat<T> res{ left };
    
    		res += right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator + (const float&  left, const FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res.value += right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator - (FxFloat<T>& left, FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res -= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator - (const FxFloat<T>& left, const float& right) {
    		FxFloat<T> res{ left };
    
    		res -= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator - (const float&  left, const FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res.value -= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator * (FxFloat<T>& left, FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res *= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator * (const FxFloat<T>& left, const float& right) {
    		FxFloat<T> res{ left };
    
    		res *= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator * (const float&  left, const FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res.value *= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator / (FxFloat<T>& left, FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res /= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator / (const FxFloat<T>& left, const float& right) {
    		FxFloat<T> res{ left };
    
    		res /= right;
    		return res;
    	}
    
    	template<typename T>
    	INLINE FxFloat<T> operator / (const float&  left, const FxFloat<T>& right) {
    		FxFloat<T> res{ left };
    
    		res /= right;
    		return res;
    	}
    } // ns igame
    
    
    #endif /* FXFLOAT_HPP_ */
    
    
    

    Good Luck