acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_math.c (8261B)
1 /** 2 * @file lv_math.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 #include "lv_math.h" 10 11 /********************* 12 * DEFINES 13 *********************/ 14 15 /********************** 16 * TYPEDEFS 17 **********************/ 18 19 /********************** 20 * STATIC PROTOTYPES 21 **********************/ 22 23 /********************** 24 * STATIC VARIABLES 25 **********************/ 26 static const int16_t sin0_90_table[] = { 27 0, 572, 1144, 1715, 2286, 2856, 3425, 3993, 4560, 5126, 5690, 6252, 6813, 7371, 7927, 8481, 28 9032, 9580, 10126, 10668, 11207, 11743, 12275, 12803, 13328, 13848, 14364, 14876, 15383, 15886, 16383, 16876, 29 17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964, 30 24351, 24730, 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 28377, 28659, 28932, 29196, 31 29451, 29697, 29934, 30162, 30381, 30591, 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165, 32 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767 33 }; 34 35 /********************** 36 * MACROS 37 **********************/ 38 39 /********************** 40 * GLOBAL FUNCTIONS 41 **********************/ 42 43 /** 44 * Return with sinus of an angle 45 * @param angle 46 * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 47 */ 48 LV_ATTRIBUTE_FAST_MEM int16_t lv_trigo_sin(int16_t angle) 49 { 50 int16_t ret = 0; 51 angle = angle % 360; 52 53 if(angle < 0) angle = 360 + angle; 54 55 if(angle < 90) { 56 ret = sin0_90_table[angle]; 57 } 58 else if(angle >= 90 && angle < 180) { 59 angle = 180 - angle; 60 ret = sin0_90_table[angle]; 61 } 62 else if(angle >= 180 && angle < 270) { 63 angle = angle - 180; 64 ret = -sin0_90_table[angle]; 65 } 66 else { /*angle >=270*/ 67 angle = 360 - angle; 68 ret = -sin0_90_table[angle]; 69 } 70 71 return ret; 72 } 73 74 /** 75 * Calculate a value of a Cubic Bezier function. 76 * @param t time in range of [0..LV_BEZIER_VAL_MAX] 77 * @param u0 start values in range of [0..LV_BEZIER_VAL_MAX] 78 * @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX] 79 * @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX] 80 * @param u3 end values in range of [0..LV_BEZIER_VAL_MAX] 81 * @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX] 82 */ 83 uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) 84 { 85 uint32_t t_rem = 1024 - t; 86 uint32_t t_rem2 = (t_rem * t_rem) >> 10; 87 uint32_t t_rem3 = (t_rem2 * t_rem) >> 10; 88 uint32_t t2 = (t * t) >> 10; 89 uint32_t t3 = (t2 * t) >> 10; 90 91 uint32_t v1 = (t_rem3 * u0) >> 10; 92 uint32_t v2 = (3 * t_rem2 * t * u1) >> 20; 93 uint32_t v3 = (3 * t_rem * t2 * u2) >> 20; 94 uint32_t v4 = (t3 * u3) >> 10; 95 96 return v1 + v2 + v3 + v4; 97 } 98 99 /** 100 * Get the square root of a number 101 * @param x integer which square root should be calculated 102 * @param q store the result here. q->i: integer part, q->f: fractional part in 1/256 unit 103 * @param mask optional to skip some iterations if the magnitude of the root is known. 104 * Set to 0x8000 by default. 105 * If root < 16: mask = 0x80 106 * If root < 256: mask = 0x800 107 * Else: mask = 0x8000 108 */ 109 LV_ATTRIBUTE_FAST_MEM void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask) 110 { 111 x = x << 8; /*To get 4 bit precision. (sqrt(256) = 16 = 4 bit)*/ 112 113 uint32_t root = 0; 114 uint32_t trial; 115 // http://ww1.microchip.com/...en/AppNotes/91040a.pdf 116 do { 117 trial = root + mask; 118 if(trial * trial <= x) root = trial; 119 mask = mask >> 1; 120 } while(mask); 121 122 q->i = root >> 4; 123 q->f = (root & 0xf) << 4; 124 } 125 126 /** 127 * Calculate the atan2 of a vector. 128 * @param x 129 * @param y 130 * @return the angle in degree calculated from the given parameters in range of [0..360] 131 */ 132 uint16_t lv_atan2(int x, int y) 133 { 134 // Fast XY vector to integer degree algorithm - Jan 2011 www.RomanBlack.com 135 // Converts any XY values including 0 to a degree value that should be 136 // within +/- 1 degree of the accurate value without needing 137 // large slow trig functions like ArcTan() or ArcCos(). 138 // NOTE! at least one of the X or Y values must be non-zero! 139 // This is the full version, for all 4 quadrants and will generate 140 // the angle in integer degrees from 0-360. 141 // Any values of X and Y are usable including negative values provided 142 // they are between -1456 and 1456 so the 16bit multiply does not overflow. 143 144 unsigned char negflag; 145 unsigned char tempdegree; 146 unsigned char comp; 147 unsigned int degree; // this will hold the result 148 unsigned int ux; 149 unsigned int uy; 150 151 // Save the sign flags then remove signs and get XY as unsigned ints 152 negflag = 0; 153 if(x < 0) { 154 negflag += 0x01; // x flag bit 155 x = (0 - x); // is now + 156 } 157 ux = x; // copy to unsigned var before multiply 158 if(y < 0) { 159 negflag += 0x02; // y flag bit 160 y = (0 - y); // is now + 161 } 162 uy = y; // copy to unsigned var before multiply 163 164 // 1. Calc the scaled "degrees" 165 if(ux > uy) { 166 degree = (uy * 45) / ux; // degree result will be 0-45 range 167 negflag += 0x10; // octant flag bit 168 } 169 else { 170 degree = (ux * 45) / uy; // degree result will be 0-45 range 171 } 172 173 // 2. Compensate for the 4 degree error curve 174 comp = 0; 175 tempdegree = degree; // use an unsigned char for speed! 176 if(tempdegree > 22) { // if top half of range 177 if(tempdegree <= 44) comp++; 178 if(tempdegree <= 41) comp++; 179 if(tempdegree <= 37) comp++; 180 if(tempdegree <= 32) comp++; // max is 4 degrees compensated 181 } 182 else { // else is lower half of range 183 if(tempdegree >= 2) comp++; 184 if(tempdegree >= 6) comp++; 185 if(tempdegree >= 10) comp++; 186 if(tempdegree >= 15) comp++; // max is 4 degrees compensated 187 } 188 degree += comp; // degree is now accurate to +/- 1 degree! 189 190 // Invert degree if it was X>Y octant, makes 0-45 into 90-45 191 if(negflag & 0x10) degree = (90 - degree); 192 193 // 3. Degree is now 0-90 range for this quadrant, 194 // need to invert it for whichever quadrant it was in 195 if(negflag & 0x02) { // if -Y 196 if(negflag & 0x01) // if -Y -X 197 degree = (180 + degree); 198 else // else is -Y +X 199 degree = (180 - degree); 200 } 201 else { // else is +Y 202 if(negflag & 0x01) // if +Y -X 203 degree = (360 - degree); 204 } 205 return degree; 206 } 207 208 /** 209 * Calculate the integer exponents. 210 * @param base 211 * @param power 212 * @return base raised to the power exponent 213 */ 214 int64_t lv_pow(int64_t base, int8_t exp) 215 { 216 int64_t result = 1; 217 while(exp) { 218 if(exp & 1) 219 result *= base; 220 exp >>= 1; 221 base *= base; 222 } 223 224 return result; 225 } 226 227 /** 228 * Get the mapped of a number given an input and output range 229 * @param x integer which mapped value should be calculated 230 * @param min_in min input range 231 * @param max_in max input range 232 * @param min_out max output range 233 * @param max_out max output range 234 * @return the mapped number 235 */ 236 int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out) 237 { 238 if(max_in >= min_in && x >= max_in) return max_out; 239 if(max_in >= min_in && x <= min_in) return min_out; 240 241 if(max_in <= min_in && x <= max_in) return max_out; 242 if(max_in <= min_in && x >= min_in) return min_out; 243 244 /** 245 * The equation should be: 246 * ((x - min_in) * delta_out) / delta in) + min_out 247 * To avoid rounding error reorder the operations: 248 * (x - min_in) * (delta_out / delta_min) + min_out 249 */ 250 251 int32_t delta_in = max_in - min_in; 252 int32_t delta_out = max_out - min_out; 253 254 return ((x - min_in) * delta_out) / delta_in + min_out; 255 } 256 257 uint32_t lv_rand(uint32_t min, uint32_t max) 258 { 259 static uint32_t a = 0x1234ABCD; /*Seed*/ 260 261 /*Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs"*/ 262 uint32_t x = a; 263 x ^= x << 13; 264 x ^= x >> 17; 265 x ^= x << 5; 266 a = x; 267 268 return (a % (max - min + 1)) + min; 269 } 270 271 /********************** 272 * STATIC FUNCTIONS 273 **********************/