scale.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Xytronic LF-1600
  3. * Physical value scaling
  4. *
  5. * Copyright (c) 2015 Michael Buesch <m@bues.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. */
  21. #include "scale.h"
  22. #ifndef SCALE_IMPL
  23. # define SCALE_IMPL 2
  24. #endif
  25. #ifndef UNSCALE_IMPL
  26. # define UNSCALE_IMPL 1
  27. #endif
  28. #ifndef RESCALE_IMPL
  29. # define RESCALE_IMPL 1
  30. #endif
  31. fixpt_t scale(int16_t raw, int16_t raw_lo, int16_t raw_hi,
  32. fixpt_t phys_lo, fixpt_t phys_hi)
  33. {
  34. #if SCALE_IMPL == 1
  35. fixpt_big_t ret, a, b, c;
  36. int16_t tmp;
  37. /* phys_lo * (raw_hi - raw) + phys_hi * (raw - raw_lo)
  38. * ret = -----------------------------------------------------
  39. * raw_hi - raw_lo
  40. */
  41. tmp = (int16_t)(raw_hi - raw);
  42. a = fixpt_big_mul(fixpt_inflate(phys_lo),
  43. int_to_fixpt_big(tmp));
  44. tmp = (int16_t)(raw - raw_lo);
  45. b = fixpt_big_mul(fixpt_inflate(phys_hi),
  46. int_to_fixpt_big(tmp));
  47. c = fixpt_big_add(a, b);
  48. tmp = (int16_t)(raw_hi - raw_lo);
  49. ret = fixpt_big_div(c,
  50. int_to_fixpt_big(tmp));
  51. return fixpt_deflate(ret);
  52. #elif SCALE_IMPL == 2
  53. fixpt_big_t a, b, c, d, ret;
  54. /* (phys_hi - phys_lo) * (raw - raw_lo)
  55. * ret = -------------------------------------- + phys_lo
  56. * raw_hi - raw_lo
  57. */
  58. a = fixpt_big_sub(fixpt_inflate(phys_hi),
  59. fixpt_inflate(phys_lo));
  60. b = int_to_fixpt_big(raw - raw_lo);
  61. c = int_to_fixpt_big(raw_hi - raw_lo);
  62. d = fixpt_big_mul_div(a, b, c);
  63. ret = fixpt_big_add(d, fixpt_inflate(phys_lo));
  64. return fixpt_deflate(ret);
  65. #else
  66. # error
  67. #endif
  68. }
  69. int16_t unscale(fixpt_t phys, fixpt_t phys_lo, fixpt_t phys_hi,
  70. int16_t raw_lo, int16_t raw_hi)
  71. {
  72. #if UNSCALE_IMPL == 1
  73. fixpt_big_t a, b, c;
  74. /* raw_lo * (phys_hi - phys) + raw_hi * (phys - phys_lo)
  75. * ret = -----------------------------------------------------
  76. * phys_hi - phys_lo
  77. */
  78. a = fixpt_big_sub(fixpt_inflate(phys_hi),
  79. fixpt_inflate(phys));
  80. a = fixpt_big_mul(a, int_to_fixpt_big(raw_lo));
  81. b = fixpt_big_sub(fixpt_inflate(phys),
  82. fixpt_inflate(phys_lo));
  83. b = fixpt_big_mul(b, int_to_fixpt_big(raw_hi));
  84. c = fixpt_big_div(fixpt_big_add(a, b),
  85. fixpt_big_sub(phys_hi, phys_lo));
  86. return (int16_t)fixpt_big_to_int(c);
  87. #elif UNSCALE_IMPL == 2
  88. fixpt_big_t a, b, c, d, ret;
  89. /* (raw_hi - raw_lo) * (phys - phys_lo)
  90. * ret = -------------------------------------- + raw_lo
  91. * phys_hi - phys_lo
  92. */
  93. a = int_to_fixpt_big(raw_hi - raw_lo);
  94. b = fixpt_big_sub(fixpt_inflate(phys),
  95. fixpt_inflate(phys_lo));
  96. c = fixpt_big_sub(fixpt_inflate(phys_hi),
  97. fixpt_inflate(phys_lo));
  98. d = fixpt_big_mul_div(a, b, c);
  99. ret = fixpt_big_add(d, int_to_fixpt_big(raw_lo));
  100. return (int16_t)fixpt_to_int(fixpt_deflate(ret));
  101. #else
  102. # error
  103. #endif
  104. }
  105. fixpt_t rescale(fixpt_t phys0, fixpt_t phys0_lo, fixpt_t phys0_hi,
  106. fixpt_t phys1_lo, fixpt_t phys1_hi)
  107. {
  108. #if RESCALE_IMPL == 1
  109. fixpt_big_t a, b, c, d, ret;
  110. /* phys1_lo * (phys0_hi - phys0) + phys1_hi * (phys0 - phys0_lo)
  111. * ret = ---------------------------------------------------------------
  112. * phys0_hi - phys0_lo
  113. */
  114. a = fixpt_big_sub(fixpt_inflate(phys0_hi),
  115. fixpt_inflate(phys0));
  116. a = fixpt_big_mul(fixpt_inflate(phys1_lo), a);
  117. b = fixpt_big_sub(fixpt_inflate(phys0),
  118. fixpt_inflate(phys0_lo));
  119. b = fixpt_big_mul(fixpt_inflate(phys1_hi), b);
  120. c = fixpt_big_add(a, b);
  121. d = fixpt_big_sub(fixpt_inflate(phys0_hi),
  122. fixpt_inflate(phys0_lo));
  123. ret = fixpt_big_div(c, d);
  124. return fixpt_deflate(ret);
  125. #elif RESCALE_IMPL == 2
  126. fixpt_big_t a, b, c, d, ret;
  127. /* (phys1_hi - phys1_lo) * (phys0 - phys0_lo)
  128. * ret = -------------------------------------------- + phys1_lo
  129. * phys0_hi - phys0_lo
  130. */
  131. a = fixpt_big_sub(fixpt_inflate(phys1_hi),
  132. fixpt_inflate(phys1_lo));
  133. b = fixpt_big_sub(fixpt_inflate(phys0),
  134. fixpt_inflate(phys0_lo));
  135. c = fixpt_big_sub(fixpt_inflate(phys0_hi),
  136. fixpt_inflate(phys0_lo));
  137. d = fixpt_big_mul_div(a, b, c);
  138. ret = fixpt_big_add(d, fixpt_inflate(phys1_lo));
  139. return fixpt_deflate(ret);
  140. #else
  141. # error
  142. #endif
  143. }