conversion.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright 2012-15 Advanced Micro Devices, Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * Authors: AMD
  23. *
  24. */
  25. #include "dm_services.h"
  26. #define DIVIDER 10000
  27. /* S2D13 value in [-3.00...0.9999] */
  28. #define S2D13_MIN (-3 * DIVIDER)
  29. #define S2D13_MAX (3 * DIVIDER)
  30. uint16_t fixed_point_to_int_frac(
  31. struct fixed31_32 arg,
  32. uint8_t integer_bits,
  33. uint8_t fractional_bits)
  34. {
  35. int32_t numerator;
  36. int32_t divisor = 1 << fractional_bits;
  37. uint16_t result;
  38. uint16_t d = (uint16_t)dal_fixed31_32_floor(
  39. dal_fixed31_32_abs(
  40. arg));
  41. if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
  42. numerator = (uint16_t)dal_fixed31_32_round(
  43. dal_fixed31_32_mul_int(
  44. arg,
  45. divisor));
  46. else {
  47. numerator = dal_fixed31_32_floor(
  48. dal_fixed31_32_sub(
  49. dal_fixed31_32_from_int(
  50. 1LL << integer_bits),
  51. dal_fixed31_32_recip(
  52. dal_fixed31_32_from_int(
  53. divisor))));
  54. }
  55. if (numerator >= 0)
  56. result = (uint16_t)numerator;
  57. else
  58. result = (uint16_t)(
  59. (1 << (integer_bits + fractional_bits + 1)) + numerator);
  60. if ((result != 0) && dal_fixed31_32_lt(
  61. arg, dal_fixed31_32_zero))
  62. result |= 1 << (integer_bits + fractional_bits);
  63. return result;
  64. }
  65. /**
  66. * convert_float_matrix
  67. * This converts a double into HW register spec defined format S2D13.
  68. * @param :
  69. * @return None
  70. */
  71. void convert_float_matrix(
  72. uint16_t *matrix,
  73. struct fixed31_32 *flt,
  74. uint32_t buffer_size)
  75. {
  76. const struct fixed31_32 min_2_13 =
  77. dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
  78. const struct fixed31_32 max_2_13 =
  79. dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
  80. uint32_t i;
  81. for (i = 0; i < buffer_size; ++i) {
  82. uint32_t reg_value =
  83. fixed_point_to_int_frac(
  84. dal_fixed31_32_clamp(
  85. flt[i],
  86. min_2_13,
  87. max_2_13),
  88. 2,
  89. 13);
  90. matrix[i] = (uint16_t)reg_value;
  91. }
  92. }