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.

359 lines
11KB

  1. #ifndef TSSCOPEMODULEBASE_HPP
  2. #define TSSCOPEMODULEBASE_HPP
  3. #include <string.h>
  4. #include <stdint.h>
  5. #include "trowaSoft.hpp"
  6. #include "trowaSoftComponents.hpp"
  7. #include "trowaSoftUtilities.hpp"
  8. #include "util/math.hpp"
  9. #include "dsp/digital.hpp"
  10. #define BUFFER_SIZE 512
  11. #define TROWA_SCOPE_USE_COLOR_LIGHTS 0
  12. // X and Y Knobs:
  13. #define TROWA_SCOPE_POS_KNOB_MIN -30.0 // Min pos value
  14. #define TROWA_SCOPE_POS_KNOB_MAX 30.0 // Max Pos value
  15. #define TROWA_SCOPE_POS_X_KNOB_DEF 0.0
  16. #define TROWA_SCOPE_POS_Y_KNOB_DEF 0.0
  17. #define TROWA_SCOPE_SCALE_KNOB_MIN -10.0 // Min Scale value
  18. #define TROWA_SCOPE_SCALE_KNOB_MAX 10.0 // Max Scale value
  19. #define TROWA_SCOPE_SCALE_POS_INPUT_MIN_V -10.0 // Min input voltage for Scale & Offset
  20. #define TROWA_SCOPE_SCALE_POS_INPUT_MAX_V 10.0 // Max input voltage for Scale & Offset
  21. // Time Knob:
  22. #define TROWA_SCOPE_TIME_KNOB_MIN -6.0
  23. #define TROWA_SCOPE_TIME_KNOB_MAX -16.0
  24. #define TROWA_SCOPE_TIME_KNOB_DEF -14.0 // Default value
  25. // Effect Knob
  26. // Number of effects (max index is this - 1) for our scope
  27. #define TROWA_SCOPE_NUM_EFFECTS TROWA_NUM_GLOBAL_EFFECTS // 4
  28. // Effect Knob min value (0)
  29. #define TROWA_SCOPE_EFFECT_KNOB_MIN 0
  30. // Effect Knob max value
  31. #define TROWA_SCOPE_EFFECT_KNOB_MAX (TROWA_SCOPE_NUM_EFFECTS-1)
  32. #define TROWA_SCOPE_EFFECT_KNOB_DEF TROWA_SCOPE_EFFECT_KNOB_MIN // Default value
  33. //-- From original multiScope ---
  34. // Hue Knob:
  35. #define TROWA_SCOPE_HUE_KNOB_MIN -10 // Not used anymore
  36. #define TROWA_SCOPE_HUE_KNOB_MAX 10 // Not used anymore
  37. #define TROWA_SCOPE_HUE_INPUT_MIN_V 0 // Not used anymore
  38. #define TROWA_SCOPE_HUE_INPUT_MAX_V 5 // Not used anymore
  39. #define TROWA_SCOPE_COLOR_KNOB_Y_OFFSET 0 // 6
  40. // Opacity:
  41. #define TROWA_SCOPE_MIN_OPACITY 0.0 // Not used anymore
  42. #define TROWA_SCOPE_MAX_OPACITY 1.0 // Not used anymore
  43. #define TROWA_SCOPE_OPACITY_INPUT_MIN 0.0 // (Not used anymore) Min Voltage in
  44. #define TROWA_SCOPE_OPACITY_INPUT_MAX 5.0 // (Not used anymore) Max Voltage in
  45. // Color Knobs and Inputs (HSLA) - All of these components will use the same values. Knobs should use the base value directly.
  46. #define TROWA_SCOPE_HSLA_MIN 0.0 // Min value for Hue, Sat, Lum, or Alpha/Opacity
  47. #define TROWA_SCOPE_HSLA_MAX 1.0 // Max value for Hue, Sat, Lum, or Alpha/Opacity
  48. #define TROWA_SCOPE_HSLA_INPUT_MIN_V -5 // Min Voltage in for Hue, Sat, Lum, or Alpha/Opacity
  49. #define TROWA_SCOPE_HSLA_INPUT_MAX_V 5 // Max Voltage in for Hue, Sat, Lum, or Alpha/Opacity
  50. // Rotation Knob:
  51. #define TROWA_SCOPE_ROT_KNOB_MIN -10
  52. #define TROWA_SCOPE_ROT_KNOB_MAX 10
  53. #define TROWA_SCOPE_ROUND_FORMAT "%.2f" // Output string format
  54. #define TROWA_SCOPE_ROUND_VALUE 100 // Rounding
  55. #define TROWA_SCOPE_ABS_ROT_ON_COLOR COLOR_TS_BLUE // Color to signal Absolute Rotation mode is on.
  56. // Colors:
  57. #define TROWA_SCOPE_LINK_XY_SCALE_ON_COLOR COLOR_MAGENTA
  58. #define TROWA_SCOPE_INFO_DISPLAY_ON_COLOR COLOR_TS_ORANGE
  59. #define TROWA_SCOPE_LISSAJOUS_ON_COLOR COLOR_YELLOW
  60. #define TROWA_SCOPE_FILL_ON_COLOR nvgRGB(0xDD,0xDD,0xDD) // COLOR_WHITE -- Very bright
  61. // Line Thickness
  62. #define TROWA_SCOPE_THICKNESS_MIN 1.0
  63. #define TROWA_SCOPE_THICKNESS_MAX 10.0
  64. #define TROWA_SCOPE_THICKNESS_DEF 3.0
  65. #define TROWA_SCOPE_THICKNESS_INPUT_MIN -5.0
  66. #define TROWA_SCOPE_THICKNESS_INPUT_MAX 5.0
  67. #define POINT_POS_INSIDE 0 // Point is within bounds
  68. #define POINT_POS_LEFT 0b0001 // Point is below min X
  69. #define POINT_POS_RIGHT 0b0010 // Point is above max X
  70. #define POINT_POS_BOTTOM 0b0100 // Point is below min Y
  71. #define POINT_POS_TOP 0b1000 // Point is above max Y
  72. #define POINT_IS_IN_BOUNDS(a) (!a) // The given point is inside our bounds.
  73. #define LINE_OUT_OF_BOUNDS(a,b) (a&b) // The line is completely outside of bounds (and would not cross our region).
  74. #define LINE_IS_IN_BOUNDS(a,b) (!(a|b)) // The line is inside our bounds.
  75. // Gets where the point is.
  76. uint8_t GetPointLocationCode(Vec pt, float minX, float maxX, float minY, float maxY);
  77. // Gets where the point is.
  78. uint8_t GetPointLocationCode(Vec pt, Vec minBounds, Vec maxBounds);
  79. // Global effects array
  80. extern const GlobalEffect* SCOPE_GLOBAL_EFFECTS[TROWA_NUM_GLOBAL_EFFECTS];
  81. /// TODO: Waveform: Thickness control & port (1 knob, 1 port)
  82. /// TODO: Waveform: X&Y Size and position ports (4 ports)
  83. #define TROWA_SCOPE_USE_Z_DIMENSION 0 // If we are using Z also, this will require more transforms and crap
  84. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  85. // TSWaveform
  86. // Store data about a waveform.
  87. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  88. struct TSWaveform
  89. {
  90. float bufferX[BUFFER_SIZE] = {};
  91. float bufferY[BUFFER_SIZE] = {};
  92. bool bufferPenOn[BUFFER_SIZE] = {};
  93. int bufferIndex;
  94. float frameIndex;
  95. // Lissajous mode on
  96. bool lissajous = true;
  97. SchmittTrigger lissajousTrigger;
  98. // Link X and Y scale ::::::::::::::::::::::::::::::::::::::::::::::
  99. // Force aspect ratio lock
  100. bool linkXYScales;
  101. // Trigger for linkXYScales button
  102. SchmittTrigger linkXYScalesTrigger;
  103. // Last value for scale when X and Y were synched.
  104. float lastXYScaleValue;
  105. // Aspect Ratio X/Y:
  106. float aspectRatioXY = 1.0;
  107. #if TROWA_SCOPE_USE_Z_DIMENSION
  108. // Number of axes
  109. int numAxes = 3;
  110. // Z-values
  111. float bufferZ[BUFFER_SIZE] = {};
  112. // Master Buffer pointer
  113. float* buffer[3] = { &(bufferX[0]), &(bufferY[0]), &(bufferZ[0]) };
  114. // Aspect Ratio X/Z:
  115. float aspectRatioXZ = 1.0;
  116. // Scale values (amplitudes for X, Y, Z).
  117. float scaleVals[3] = { 1.0, 1.0, 1.0 };
  118. // Offset values for X, Y, Z
  119. float offsetVals[3] = { 0.0, 0.0, 0.0 };
  120. // If the X, Y, Z inputs are active.
  121. bool inputsActive[3] = { false, false, false };
  122. #else
  123. // Number of axes
  124. int numAxes = 2;
  125. // Master Buffer pointer
  126. float* buffer[2] = { &(bufferX[0]), &(bufferY[0])};
  127. // Scale values (amplitudes for X, Y).
  128. float scaleVals[2] = { 1.0, 1.0 };
  129. // Offset values for X, Y.
  130. float offsetVals[2] = { 0.0, 0.0 };
  131. // If the X, Y inputs are active.
  132. bool inputsActive[2] = { false, false };
  133. #endif
  134. // Rotation ::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  135. SchmittTrigger rotModeTrigger;
  136. // True for absolute angular position, false if constant angular change
  137. bool rotMode;
  138. // Value from rotation knob
  139. float rotKnobValue;
  140. // Translated to ABS position [radians]
  141. float rotAbsValue;
  142. // Translated to differential position [radians] (rate)
  143. float rotDiffValue;
  144. // Colors ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  145. // Actual color
  146. NVGcolor waveColor;
  147. // Color hue 0 to 1
  148. float waveHue = 0;
  149. // Color saturation 0 to 1
  150. float waveSat = 0.5;
  151. // Color light 0 to 1
  152. float waveLght = 0.5;
  153. #if TROWA_SCOPE_USE_COLOR_LIGHTS
  154. // References to our lights (typed)
  155. ColorValueLight* waveLight;
  156. #endif
  157. // If the color has changed.
  158. bool colorChanged;
  159. // Alpha channel 0-1
  160. float waveOpacity = 1.0;
  161. // Fill color::::::::::::::::::::::::
  162. // Fill mode is on
  163. bool doFill = false;
  164. SchmittTrigger fillOnTrigger;
  165. // Color to use for fill.
  166. NVGcolor fillColor;
  167. // Fill hue (0-1)
  168. float fillHue = 0;
  169. // Fill saturation (0-1)
  170. float fillSat = 0.5;
  171. // Fill lum (0-1)
  172. float fillLght = 0.5;
  173. // Alpha channel 0-1.
  174. float fillOpacity = 1.0;
  175. // Rendering properties ::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  176. // Thickness of waveform line.
  177. float lineThickness = 3.0;
  178. // Negative the color.
  179. bool negativeImage = false;
  180. // Index into SCOPE_GLOBAL_EFFECTS for what effect to do.
  181. int gEffectIx = 0;
  182. TSWaveform()
  183. {
  184. bufferIndex = 0;
  185. frameIndex = 0;
  186. memset(bufferPenOn, true, BUFFER_SIZE);
  187. colorChanged = true;
  188. rotMode = false;
  189. rotKnobValue = 0;
  190. rotAbsValue = 0;
  191. rotDiffValue = 0;
  192. linkXYScales = false;
  193. waveOpacity = TROWA_SCOPE_MAX_OPACITY;
  194. lineThickness = 3.0;
  195. waveColor = HueToColor(waveHue, waveSat, waveLght);
  196. fillColor = HueToColor(fillHue, fillSat, fillLght);
  197. #if TROWA_SCOPE_USE_COLOR_LIGHTS
  198. waveLight = NULL;
  199. #endif
  200. return;
  201. }
  202. void setHue(float hue)
  203. {
  204. waveHue = hue;
  205. waveColor = HueToColor(waveHue, waveSat, waveLght);
  206. }
  207. void setHueFromKnob(float hueKnobValue)
  208. {
  209. setHue(rescale(hueKnobValue, TROWA_SCOPE_HUE_KNOB_MIN, TROWA_SCOPE_HUE_KNOB_MAX, 0.0, 1.0));
  210. return;
  211. }
  212. void setFillHue(float hue)
  213. {
  214. fillHue = hue;
  215. fillColor = HueToColor(hue, fillSat, fillLght);
  216. }
  217. void setFillHueFromKnob(float hueKnobValue)
  218. {
  219. setFillHue(rescale(hueKnobValue, TROWA_SCOPE_HUE_KNOB_MIN, TROWA_SCOPE_HUE_KNOB_MAX, 0.0, 1.0));
  220. return;
  221. }
  222. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  223. // toJson(void)
  224. // Save to json.
  225. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  226. json_t *toJson() {
  227. // Really should just serialize the TSWaveForm object.
  228. json_t* rootJ = json_object();
  229. json_t* itemJ;
  230. // Colors
  231. json_t* waveColorJ = json_array();
  232. json_t* fillColorJ = json_array();
  233. // -- RGB
  234. for (int i = 0; i < 3; i++)
  235. {
  236. itemJ = json_real(waveColor.rgba[i]);
  237. json_array_append_new(waveColorJ, itemJ);
  238. itemJ = NULL;
  239. itemJ = json_real(fillColor.rgba[i]);
  240. json_array_append_new(fillColorJ, itemJ);
  241. itemJ = NULL;
  242. }
  243. // -- Alpha (stored separately)
  244. itemJ = json_real(waveOpacity);
  245. json_array_append_new(waveColorJ, itemJ);
  246. itemJ = json_real(fillOpacity);
  247. json_array_append_new(fillColorJ, itemJ);
  248. json_object_set_new(rootJ, "waveColor", waveColorJ);
  249. json_object_set_new(rootJ, "fillColor", fillColorJ);
  250. json_object_set_new(rootJ, "fillOn", json_integer(this->doFill));
  251. json_object_set_new(rootJ, "lissajous", json_integer(this->lissajous));
  252. json_object_set_new(rootJ, "rotMode", json_integer(this->rotMode));
  253. json_object_set_new(rootJ, "linkXYScales", json_integer(this->linkXYScales));
  254. return rootJ;
  255. } // end toJson()
  256. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  257. // fromJson(void)
  258. // Load settings.
  259. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  260. void fromJson(json_t *rootJ) {
  261. json_t* itemJ;
  262. // Colors
  263. json_t* waveColorJ = json_object_get(rootJ, "waveColor");
  264. json_t* fillColorJ = json_object_get(rootJ, "fillColor");
  265. // -- RGB
  266. for (int i = 0; i < 3; i++)
  267. {
  268. if (waveColorJ)
  269. {
  270. itemJ = json_array_get(waveColorJ, i);
  271. if (itemJ)
  272. waveColor.rgba[i] = (float)(json_real_value(itemJ));
  273. itemJ = NULL;
  274. }
  275. if (fillColorJ)
  276. {
  277. itemJ = json_array_get(fillColorJ, i);
  278. if (itemJ)
  279. fillColor.rgba[i] = (float)(json_real_value(itemJ));
  280. itemJ = NULL;
  281. }
  282. }
  283. // -- Alpha
  284. if (waveColorJ)
  285. {
  286. itemJ = json_array_get(waveColorJ, 3);
  287. if (itemJ)
  288. waveOpacity = (float)(json_real_value(itemJ));
  289. itemJ = NULL;
  290. }
  291. if (fillColorJ)
  292. {
  293. itemJ = json_array_get(fillColorJ, 3);
  294. if (itemJ)
  295. fillOpacity = (float)(json_real_value(itemJ));
  296. itemJ = NULL;
  297. }
  298. itemJ = json_object_get(rootJ, "fillOn");
  299. if (itemJ)
  300. {
  301. doFill = (bool)(json_integer_value(itemJ));
  302. itemJ = NULL;
  303. }
  304. itemJ = json_object_get(rootJ, "lissajous");
  305. if (itemJ)
  306. {
  307. lissajous = (bool)(json_integer_value(itemJ));
  308. itemJ = NULL;
  309. }
  310. itemJ = json_object_get(rootJ, "rotMode");
  311. if (itemJ)
  312. {
  313. lissajous = (bool)(json_integer_value(itemJ));
  314. itemJ = NULL;
  315. }
  316. itemJ = json_object_get(rootJ, "linkXYScales");
  317. if (itemJ)
  318. {
  319. linkXYScales = (bool)(json_integer_value(itemJ));
  320. itemJ = NULL;
  321. }
  322. return;
  323. } // end fromJson()
  324. };
  325. #endif // !TSSCOPEMODULEBASE_HPP