diff options
| -rw-r--r-- | demos/modules/gdisp/gdisp_streaming/gfxconf.h | 10 | ||||
| -rw-r--r-- | demos/modules/gdisp/gdisp_streaming/main.c | 32 | ||||
| -rw-r--r-- | gfxconf.example.h | 3 | ||||
| -rw-r--r-- | include/gmisc/options.h | 27 | ||||
| -rw-r--r-- | src/gmisc/trig.c | 56 | 
5 files changed, 98 insertions, 30 deletions
| diff --git a/demos/modules/gdisp/gdisp_streaming/gfxconf.h b/demos/modules/gdisp/gdisp_streaming/gfxconf.h index 4db07fb9..b38be854 100644 --- a/demos/modules/gdisp/gdisp_streaming/gfxconf.h +++ b/demos/modules/gdisp/gdisp_streaming/gfxconf.h @@ -35,9 +35,11 @@  /* Builtin Fonts */  #define GDISP_INCLUDE_FONT_UI2          FALSE -#define GFX_USE_GMISC			TRUE -#define GMISC_NEED_FIXEDTRIG	FALSE -#define GMISC_NEED_FASTTRIG		FALSE -#define GMISC_NEED_INVSQRT		TRUE +#define GFX_USE_GMISC				TRUE +#define GMISC_NEED_FIXEDTRIG		FALSE +#define GMISC_NEED_FASTTRIG			FALSE +#define GMISC_NEED_INVSQRT			TRUE +//#define GDISP_INVSQRT_MIXED_ENDIAN	TRUE +//#define GDISP_INVSQRT_REAL_SLOW		TRUE  #endif /* _GFXCONF_H */ diff --git a/demos/modules/gdisp/gdisp_streaming/main.c b/demos/modules/gdisp/gdisp_streaming/main.c index 774ee833..5b857eeb 100644 --- a/demos/modules/gdisp/gdisp_streaming/main.c +++ b/demos/modules/gdisp/gdisp_streaming/main.c @@ -31,15 +31,29 @@  #include "gfx.h"  #include <math.h> -#define Lightgrey () -#define Midgrey () -#define Darkgrey (HTML2COLOR(0x303030)) - -#define BALLCOLOR1	Red -#define BALLCOLOR2	Yellow -#define WALLCOLOR	HTML2COLOR(0x303030) -#define BACKCOLOR	HTML2COLOR(0xC0C0C0) -#define FLOORCOLOR	HTML2COLOR(0x606060) +/** + * NOTE: + * + * This demo uses floating point operations. Don't expect it to work with any + * speed unless your processor has an FPU. + * + * If you see garbage inside the ball as it is running rather than the red and yellow + * checkerboard pattern then the fast invsqrt() function in GMISC does not work on + * your processor. + * + * You can modify the implementation of invsqrt() by firstly defining + * 		#define GDISP_INVSQRT_MIXED_ENDIAN	TRUE + * in your gfxconf.h file. + * + * If it still doesn't work then instead define + * 		#define GDISP_INVSQRT_REAL_SLOW		TRUE + * in your gfxconf.h file. This should always work although it will probably be slow. + */ +#define BALLCOLOR1		Red +#define BALLCOLOR2		Yellow +#define WALLCOLOR		HTML2COLOR(0x303030) +#define BACKCOLOR		HTML2COLOR(0xC0C0C0) +#define FLOORCOLOR		HTML2COLOR(0x606060)  #define SHADOWALPHA		(255-255*0.2)  int main(void) { diff --git a/gfxconf.example.h b/gfxconf.example.h index d5b4af5c..1b9faca2 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -181,11 +181,12 @@  	#define GWIN_CONSOLE_USE_BASESTREAM		FALSE  	#define GWIN_CONSOLE_USE_FLOAT			FALSE  	#define GWIN_NEED_IMAGE_ANIMATION		FALSE +	#define GDISP_INVSQRT_MIXED_ENDIAN		FALSE +	#define GDISP_INVSQRT_REAL_SLOW			FALSE  */  /* Optional Low Level Driver Definitions */  /* -	#define GDISP_USE_CUSTOM_BOARD		FALSE  	#define GDISP_SCREEN_WIDTH			320  	#define GDISP_SCREEN_HEIGHT			240  	#define GDISP_USE_FSMC diff --git a/include/gmisc/options.h b/include/gmisc/options.h index 73b41800..9c309487 100644 --- a/include/gmisc/options.h +++ b/include/gmisc/options.h @@ -44,9 +44,34 @@  /**
   * @}
   *
 - * @name    GMISC Optional Sizing Parameters
 + * @name    GMISC Optional Parameters
   * @{
   */
 +	/**
 +	 * @brief	Modifies the @p invsqrt() function to assume a different integer to floating point endianness.
 +	 * @note	Normally the floating point format and the integer format have
 +	 * 			the same endianness. Unfortunately there are some strange
 +	 * 			processors that don't eg. some very early ARM devices.
 +	 * 			For those where the endianness doesn't match you can fix it by
 +	 * 			defining GDISP_INVSQRT_MIXED_ENDIAN.
 +	 * @note	This still assumes the processor is using an ieee floating point format.
 +	 *
 +	 * If you have a software floating point that uses a non-standard
 +	 * floating point format (or very strange hardware) then define
 +	 * GDISP_INVSQRT_REAL_SLOW and it will do it the hard way.
 +	 */
 +	#ifndef GDISP_INVSQRT_MIXED_ENDIAN
 +		#define GDISP_INVSQRT_MIXED_ENDIAN	FALSE
 +	#endif
 +	/**
 +	 * @brief	Modifies the @p invsqrt() function to do things the long slow way.
 +	 * @note	This causes the @p invsqrt() function to work regardless of the
 +	 * 			processor floating point format.
 +	 * @note	This makes the @p invsqrt() function very slow.
 +	 */
 +	#ifndef GDISP_INVSQRT_REAL_SLOW
 +		#define GDISP_INVSQRT_REAL_SLOW		FALSE
 +	#endif
  /** @} */
  #endif /* _GMISC_OPTIONS_H */
 diff --git a/src/gmisc/trig.c b/src/gmisc/trig.c index 00b6365a..cd35bdc0 100644 --- a/src/gmisc/trig.c +++ b/src/gmisc/trig.c @@ -143,21 +143,47 @@  #endif  #if GMISC_NEED_INVSQRT -	// Algorithm based on Quake code -	float invsqrt(float n) { -		long i; -		float x2, y; -		const float threehalfs = 1.5F; - -		x2 = n * 0.5F; -		y  = n; -		i  = * ( long * ) &y;						// evil floating point bit level hacking -		i  = 0x5f3759df - ( i >> 1 );				// what the? -		y  = * ( float * ) &i; -		y  = y * ( threehalfs - ( x2 * y * y ) );	// 1st iteration -		//y  = y * ( threehalfs - ( x2 * y * y ) );	// 2nd iteration for extra precision, this can be removed -		return y; -	} +	// Algorithm based on Quake code. +	#if GDISP_INVSQRT_REAL_SLOW +		#include <math.h> +		float invsqrt(float n) { +			return 1.0/sqrt(n); +		} +	#else +		float invsqrt(float n) { +			int32_t		i; +			float		x2; + +			x2 = n * 0.5F; + +			// Convert into an int32 (no binary format conversion) +			#if GDISP_INVSQRT_MIXED_ENDIAN +				((char *)&i)[0] = ((char *)&n)[3]; +				((char *)&i)[1] = ((char *)&n)[2]; +				((char *)&i)[2] = ((char *)&n)[1]; +				((char *)&i)[3] = ((char *)&n)[0]; +			#else +				i  = *(int32_t *)&n; +			#endif + +			// evil floating point bit level hacking +			i  = 0x5F3759DF - (i >> 1); + +			// Convert back to a float (no binary format conversion) +			#if GDISP_INVSQRT_MIXED_ENDIAN +				((char *)&n)[0] = ((char *)&i)[3]; +				((char *)&n)[1] = ((char *)&i)[2]; +				((char *)&n)[2] = ((char *)&i)[1]; +				((char *)&n)[3] = ((char *)&i)[0]; +			#else +				n  = *(float *)&i; +			#endif + +			n  = n * (1.5F - (x2 * n * n));				// 1st iteration +			//n  = n * (1.5F - (x2 * n * n));			// 2nd iteration for extra precision, this can be removed +			return n; +		} +	#endif  #endif  #endif /* GFX_USE_GMISC */ | 
