0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027 #include "conversion.h"
0028
0029 #define DIVIDER 10000
0030
0031
0032 #define S2D13_MIN (-3 * DIVIDER)
0033 #define S2D13_MAX (3 * DIVIDER)
0034
0035 uint16_t fixed_point_to_int_frac(
0036 struct fixed31_32 arg,
0037 uint8_t integer_bits,
0038 uint8_t fractional_bits)
0039 {
0040 int32_t numerator;
0041 int32_t divisor = 1 << fractional_bits;
0042
0043 uint16_t result;
0044
0045 uint16_t d = (uint16_t)dc_fixpt_floor(
0046 dc_fixpt_abs(
0047 arg));
0048
0049 if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
0050 numerator = (uint16_t)dc_fixpt_round(
0051 dc_fixpt_mul_int(
0052 arg,
0053 divisor));
0054 else {
0055 numerator = dc_fixpt_floor(
0056 dc_fixpt_sub(
0057 dc_fixpt_from_int(
0058 1LL << integer_bits),
0059 dc_fixpt_recip(
0060 dc_fixpt_from_int(
0061 divisor))));
0062 }
0063
0064 if (numerator >= 0)
0065 result = (uint16_t)numerator;
0066 else
0067 result = (uint16_t)(
0068 (1 << (integer_bits + fractional_bits + 1)) + numerator);
0069
0070 if ((result != 0) && dc_fixpt_lt(
0071 arg, dc_fixpt_zero))
0072 result |= 1 << (integer_bits + fractional_bits);
0073
0074 return result;
0075 }
0076
0077
0078
0079 void convert_float_matrix(
0080 uint16_t *matrix,
0081 struct fixed31_32 *flt,
0082 uint32_t buffer_size)
0083 {
0084 const struct fixed31_32 min_2_13 =
0085 dc_fixpt_from_fraction(S2D13_MIN, DIVIDER);
0086 const struct fixed31_32 max_2_13 =
0087 dc_fixpt_from_fraction(S2D13_MAX, DIVIDER);
0088 uint32_t i;
0089
0090 for (i = 0; i < buffer_size; ++i) {
0091 uint32_t reg_value =
0092 fixed_point_to_int_frac(
0093 dc_fixpt_clamp(
0094 flt[i],
0095 min_2_13,
0096 max_2_13),
0097 2,
0098 13);
0099
0100 matrix[i] = (uint16_t)reg_value;
0101 }
0102 }
0103
0104 static uint32_t find_gcd(uint32_t a, uint32_t b)
0105 {
0106 uint32_t remainder = 0;
0107 while (b != 0) {
0108 remainder = a % b;
0109 a = b;
0110 b = remainder;
0111 }
0112 return a;
0113 }
0114
0115 void reduce_fraction(uint32_t num, uint32_t den,
0116 uint32_t *out_num, uint32_t *out_den)
0117 {
0118 uint32_t gcd = 0;
0119
0120 gcd = find_gcd(num, den);
0121 *out_num = num / gcd;
0122 *out_den = den / gcd;
0123 }