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.

261 lines
8.3KB

  1. #include "HetrickCV.hpp"
  2. namespace rack_plugin_HetrickCV {
  3. struct AnalogToDigital : Module
  4. {
  5. enum ParamIds
  6. {
  7. SCALE_PARAM,
  8. OFFSET_PARAM,
  9. MODE_PARAM,
  10. RECTIFY_PARAM,
  11. NUM_PARAMS
  12. };
  13. enum InputIds
  14. {
  15. MAIN_INPUT,
  16. SYNC_INPUT,
  17. NUM_INPUTS
  18. };
  19. enum OutputIds
  20. {
  21. OUT1_OUTPUT,
  22. OUT2_OUTPUT,
  23. OUT3_OUTPUT,
  24. OUT4_OUTPUT,
  25. OUT5_OUTPUT,
  26. OUT6_OUTPUT,
  27. OUT7_OUTPUT,
  28. OUT8_OUTPUT,
  29. NUM_OUTPUTS
  30. };
  31. enum LightIds
  32. {
  33. OUT1_LIGHT,
  34. OUT2_LIGHT,
  35. OUT3_LIGHT,
  36. OUT4_LIGHT,
  37. OUT5_LIGHT,
  38. OUT6_LIGHT,
  39. OUT7_LIGHT,
  40. OUT8_LIGHT,
  41. RECT_NONE_LIGHT,
  42. RECT_HALF_LIGHT,
  43. RECT_FULL_LIGHT,
  44. MODE_UNI8_LIGHT,
  45. MODE_BOFF_LIGHT,
  46. MODE_BSIG_LIGHT,
  47. NUM_LIGHTS
  48. };
  49. SchmittTrigger clockTrigger;
  50. SchmittTrigger modeTrigger;
  51. SchmittTrigger rectTrigger;
  52. int mode = 0;
  53. int rectMode = 0;
  54. float outs[8] = {};
  55. AnalogToDigital() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
  56. {
  57. }
  58. void step() override;
  59. void processUni8(float _input);
  60. void processBiOff(float _input);
  61. void processBiSig(float _input);
  62. void reset() override
  63. {
  64. mode = 0;
  65. rectMode = 0;
  66. }
  67. void randomize() override
  68. {
  69. mode = round(randomf() * 2.0f);
  70. rectMode = round(randomf() * 2.0f);
  71. }
  72. json_t *toJson() override
  73. {
  74. json_t *rootJ = json_object();
  75. json_object_set_new(rootJ, "mode", json_integer(mode));
  76. json_object_set_new(rootJ, "rectMode", json_integer(rectMode));
  77. return rootJ;
  78. }
  79. void fromJson(json_t *rootJ) override
  80. {
  81. json_t *modeJ = json_object_get(rootJ, "mode");
  82. if (modeJ)
  83. mode = json_integer_value(modeJ);
  84. json_t *rectModeJ = json_object_get(rootJ, "rectMode");
  85. if (rectModeJ)
  86. rectMode = json_integer_value(rectModeJ);
  87. }
  88. // For more advanced Module features, read Rack's engine.hpp header file
  89. // - toJson, fromJson: serialization of internal data
  90. // - onSampleRateChange: event triggered by a change of sample rate
  91. // - reset, randomize: implements special behavior when user clicks these from the context menu
  92. };
  93. void AnalogToDigital::step()
  94. {
  95. if (modeTrigger.process(params[MODE_PARAM].value)) mode = (mode + 1) % 3;
  96. if (rectTrigger.process(params[RECTIFY_PARAM].value)) rectMode = (rectMode + 1) % 3;
  97. lights[MODE_UNI8_LIGHT].setBrightness(mode == 0 ? 1.0f : 0.0f);
  98. lights[MODE_BOFF_LIGHT].setBrightness(mode == 1 ? 1.0f : 0.0f);
  99. lights[MODE_BSIG_LIGHT].setBrightness(mode == 2 ? 1.0f : 0.0f);
  100. lights[RECT_NONE_LIGHT].setBrightness(rectMode == 0 ? 1.0f : 0.0f);
  101. lights[RECT_HALF_LIGHT].setBrightness(rectMode == 1 ? 1.0f : 0.0f);
  102. lights[RECT_FULL_LIGHT].setBrightness(rectMode == 2 ? 1.0f : 0.0f);
  103. const bool syncModeEnabled = inputs[SYNC_INPUT].active;
  104. const bool readyForProcess = (!syncModeEnabled || (syncModeEnabled && clockTrigger.process(inputs[SYNC_INPUT].value)));
  105. if(readyForProcess)
  106. {
  107. float input = inputs[MAIN_INPUT].value;
  108. input *= params[SCALE_PARAM].value;
  109. input += params[OFFSET_PARAM].value;
  110. if (rectMode == 1) input = input > 0.0f? input : 0.0f;
  111. else if (rectMode == 2) input = std::abs(input);
  112. if(mode == 0) processUni8(input);
  113. else if (mode == 1) processBiOff(input);
  114. else if (mode == 2) processBiSig(input);
  115. }
  116. for(int i = 0; i < 8; i++)
  117. {
  118. outputs[OUT1_OUTPUT + i].value = outs[i];
  119. lights[OUT1_LIGHT + i].value = outs[i];
  120. }
  121. }
  122. void AnalogToDigital::processUni8(float _input)
  123. {
  124. clampf(_input, 0.0f, 1.0f);
  125. uint8_t bits = round(_input * 255);
  126. outs[0] = (bits & 0b00000001) > 0.0f ? 5.0f : 0.0f;
  127. outs[1] = (bits & 0b00000010) > 0.0f ? 5.0f : 0.0f;
  128. outs[2] = (bits & 0b00000100) > 0.0f ? 5.0f : 0.0f;
  129. outs[3] = (bits & 0b00001000) > 0.0f ? 5.0f : 0.0f;
  130. outs[4] = (bits & 0b00010000) > 0.0f ? 5.0f : 0.0f;
  131. outs[5] = (bits & 0b00100000) > 0.0f ? 5.0f : 0.0f;
  132. outs[6] = (bits & 0b01000000) > 0.0f ? 5.0f : 0.0f;
  133. outs[7] = (bits & 0b10000000) > 0.0f ? 5.0f : 0.0f;
  134. }
  135. void AnalogToDigital::processBiOff(float _input)
  136. {
  137. clampf(_input, -1.0f, 1.0f);
  138. _input = (_input + 1.0f) * 0.5f;
  139. uint8_t bits = round(_input * 255);
  140. outs[0] = (bits & 0b00000001) > 0.0f ? 5.0f : 0.0f;
  141. outs[1] = (bits & 0b00000010) > 0.0f ? 5.0f : 0.0f;
  142. outs[2] = (bits & 0b00000100) > 0.0f ? 5.0f : 0.0f;
  143. outs[3] = (bits & 0b00001000) > 0.0f ? 5.0f : 0.0f;
  144. outs[4] = (bits & 0b00010000) > 0.0f ? 5.0f : 0.0f;
  145. outs[5] = (bits & 0b00100000) > 0.0f ? 5.0f : 0.0f;
  146. outs[6] = (bits & 0b01000000) > 0.0f ? 5.0f : 0.0f;
  147. outs[7] = (bits & 0b10000000) > 0.0f ? 5.0f : 0.0f;
  148. }
  149. void AnalogToDigital::processBiSig(float _input)
  150. {
  151. outs[7] = _input < 0.0f ? 5.0f : 0.0f;
  152. clampf(_input, -1.0f, 1.0f);
  153. _input = std::abs(_input);
  154. uint8_t bits = round(_input * 127);
  155. outs[0] = (bits & 0b00000001) > 0.0f ? 5.0f : 0.0f;
  156. outs[1] = (bits & 0b00000010) > 0.0f ? 5.0f : 0.0f;
  157. outs[2] = (bits & 0b00000100) > 0.0f ? 5.0f : 0.0f;
  158. outs[3] = (bits & 0b00001000) > 0.0f ? 5.0f : 0.0f;
  159. outs[4] = (bits & 0b00010000) > 0.0f ? 5.0f : 0.0f;
  160. outs[5] = (bits & 0b00100000) > 0.0f ? 5.0f : 0.0f;
  161. outs[6] = (bits & 0b01000000) > 0.0f ? 5.0f : 0.0f;
  162. }
  163. struct AnalogToDigitalWidget : ModuleWidget { AnalogToDigitalWidget(AnalogToDigital *module); };
  164. AnalogToDigitalWidget::AnalogToDigitalWidget(AnalogToDigital *module) : ModuleWidget(module)
  165. {
  166. box.size = Vec(12 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  167. {
  168. auto *panel = new SVGPanel();
  169. panel->box.size = box.size;
  170. panel->setBackground(SVG::load(assetPlugin(plugin, "res/AToD.svg")));
  171. addChild(panel);
  172. }
  173. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  174. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  175. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  176. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  177. //////PARAMS//////
  178. addParam(ParamWidget::create<CKD6>(Vec(16, 270), module, AnalogToDigital::MODE_PARAM, 0.0, 1.0, 0.0));
  179. addParam(ParamWidget::create<CKD6>(Vec(65, 270), module, AnalogToDigital::RECTIFY_PARAM, 0.0, 1.0, 0.0));
  180. //////BLINKENLIGHTS//////
  181. int modeLightX = 12;
  182. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(modeLightX, 306), module, AnalogToDigital::MODE_UNI8_LIGHT));
  183. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(modeLightX, 319), module, AnalogToDigital::MODE_BOFF_LIGHT));
  184. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(modeLightX, 332), module, AnalogToDigital::MODE_BSIG_LIGHT));
  185. int rectLightX = 64;
  186. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(rectLightX, 306), module, AnalogToDigital::RECT_NONE_LIGHT));
  187. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(rectLightX, 319), module, AnalogToDigital::RECT_HALF_LIGHT));
  188. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(rectLightX, 332), module, AnalogToDigital::RECT_FULL_LIGHT));
  189. //////INPUTS//////
  190. addInput(Port::create<PJ301MPort>(Vec(7, 70), Port::INPUT, module, AnalogToDigital::MAIN_INPUT));
  191. addInput(Port::create<PJ301MPort>(Vec(42, 152), Port::INPUT, module, AnalogToDigital::SYNC_INPUT));
  192. addParam(ParamWidget::create<Trimpot>(Vec(44, 73), module, AnalogToDigital::SCALE_PARAM, -1.0, 1.0, 0.2));
  193. addParam(ParamWidget::create<Trimpot>(Vec(80, 73), module, AnalogToDigital::OFFSET_PARAM, -5.0, 5.0, 0.0));
  194. const int outXPos = 145;
  195. const int outLightX = 120;
  196. for(int i = 0; i < 8; i++)
  197. {
  198. const int yPos = 50 + (40 * i);
  199. const int lightY = 59 + (40 * i);
  200. //////OUTPUTS//////
  201. addOutput(Port::create<PJ301MPort>(Vec(outXPos, yPos), Port::OUTPUT, module, AnalogToDigital::OUT1_OUTPUT + i));
  202. //////BLINKENLIGHTS//////
  203. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(outLightX, lightY), module, AnalogToDigital::OUT1_LIGHT + i));
  204. }
  205. }
  206. } // namespace rack_plugin_HetrickCV
  207. using namespace rack_plugin_HetrickCV;
  208. RACK_PLUGIN_MODEL_INIT(HetrickCV, AnalogToDigital) {
  209. Model *modelAnalogToDigital = Model::create<AnalogToDigital, AnalogToDigitalWidget>("HetrickCV", "AnalogToDigital", "Analog to Digital", LOGIC_TAG);
  210. return modelAnalogToDigital;
  211. }