You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.6KB

  1. // Copyright 2013 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // CV scaling functions.
  28. #ifndef TIDES_CV_SCALER_H_
  29. #define TIDES_CV_SCALER_H_
  30. #include "stmlib/stmlib.h"
  31. #include "stmlib/utils/dsp.h"
  32. #include "tides/resources.h"
  33. namespace tides {
  34. enum AdcChannel {
  35. ADC_CHANNEL_LEVEL,
  36. ADC_CHANNEL_V_OCT,
  37. ADC_CHANNEL_FM,
  38. ADC_CHANNEL_FM_ATTENUVERTER,
  39. ADC_CHANNEL_SHAPE,
  40. ADC_CHANNEL_SLOPE,
  41. ADC_CHANNEL_SMOOTHNESS,
  42. ADC_CHANNEL_LAST
  43. };
  44. class CvScaler {
  45. public:
  46. struct CalibrationData {
  47. int32_t level_offset;
  48. int32_t v_oct_offset;
  49. int32_t v_oct_scale;
  50. int32_t fm_offset;
  51. int32_t fm_scale;
  52. int32_t padding[3];
  53. };
  54. CvScaler() { }
  55. ~CvScaler() { }
  56. void Init();
  57. inline void ProcessSampleRate(const uint16_t* raw_adc_data) {
  58. level_raw_ = (level_raw_ * 15 + raw_adc_data[ADC_CHANNEL_LEVEL]) >> 4;
  59. level_ = -level_raw_ + calibration_data_.level_offset;
  60. if (level_ < 32) { // 2 LSB of ADC noise.
  61. level_ = 0;
  62. }
  63. }
  64. inline void ProcessControlRate(const uint16_t* raw_adc_data) {
  65. int32_t scaled_value;
  66. scaled_value = 32767 - static_cast<int32_t>(
  67. raw_adc_data[ADC_CHANNEL_SHAPE]);
  68. shape_ = (shape_ * 7 + scaled_value) >> 3;
  69. scaled_value = 32767 - static_cast<int32_t>(
  70. raw_adc_data[ADC_CHANNEL_SLOPE]);
  71. slope_ = (slope_ * 7 + scaled_value) >> 3;
  72. scaled_value = 32767 - static_cast<int32_t>(
  73. raw_adc_data[ADC_CHANNEL_SMOOTHNESS]);
  74. smoothness_ = (smoothness_ * 7 + scaled_value) >> 3;
  75. scaled_value = static_cast<int32_t>(raw_adc_data[ADC_CHANNEL_V_OCT]);
  76. v_oct_ = (v_oct_ * 3 + scaled_value) >> 2;
  77. scaled_value = static_cast<int32_t>(raw_adc_data[ADC_CHANNEL_FM]);
  78. fm_ = (fm_ * 3 + scaled_value) >> 2;
  79. scaled_value = static_cast<int32_t>(
  80. raw_adc_data[ADC_CHANNEL_FM_ATTENUVERTER]);
  81. attenuverter_ = (attenuverter_ * 15 + scaled_value) >> 4;
  82. }
  83. inline uint16_t level() const { return level_; }
  84. inline int16_t shape() const { return shape_; }
  85. inline int16_t slope() const { return slope_; }
  86. inline int16_t smoothness() const { return smoothness_; }
  87. inline int16_t pitch() const {
  88. int32_t pitch;
  89. int32_t attenuverter_value = attenuverter_ - 32768;
  90. int32_t attenuverter_sign = 1;
  91. if (attenuverter_value < 0) {
  92. attenuverter_value = -attenuverter_value - 1;
  93. attenuverter_sign = - 1;
  94. }
  95. attenuverter_value = attenuverter_sign * static_cast<int32_t>(
  96. stmlib::Interpolate88(lut_attenuverter_curve, attenuverter_value << 1));
  97. pitch = (fm_ - calibration_data_.fm_offset) * \
  98. calibration_data_.fm_scale >> 15;
  99. pitch = pitch * attenuverter_value >> 16;
  100. pitch += (v_oct_ - calibration_data_.v_oct_offset) * \
  101. calibration_data_.v_oct_scale >> 15;
  102. pitch += 60 << 7;
  103. return pitch;
  104. }
  105. void CaptureCalibrationValues() {
  106. v_oct_c2_ = v_oct_;
  107. }
  108. void Calibrate();
  109. inline bool can_enter_calibration() const {
  110. return level_raw_ >= 49152;
  111. }
  112. private:
  113. void SaveCalibrationData();
  114. CalibrationData calibration_data_;
  115. int32_t level_raw_;
  116. int32_t level_;
  117. int32_t v_oct_;
  118. int32_t fm_;
  119. int32_t attenuverter_;
  120. int32_t shape_;
  121. int32_t slope_;
  122. int32_t smoothness_;
  123. int32_t v_oct_c2_;
  124. static const CalibrationData init_calibration_data_;
  125. uint16_t version_token_;
  126. DISALLOW_COPY_AND_ASSIGN(CvScaler);
  127. };
  128. } // namespace tides
  129. #endif // TIDES_CV_SCALER_H_