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.

135 lines
3.5KB

  1. #include <global_pre.hpp>
  2. #include <global.hpp>
  3. #include "DS.hpp"
  4. #include <random>
  5. #include <chrono>
  6. namespace rack_plugin_SubmarineFree {
  7. template <int deviceCount>
  8. struct FF_1 : DS_Module {
  9. int doResetFlag = 0;
  10. int doRandomFlag = 0;
  11. enum ParamIds {
  12. NUM_PARAMS
  13. };
  14. enum InputIds {
  15. INPUT,
  16. NUM_INPUTS
  17. };
  18. enum OutputIds {
  19. OUTPUT_1,
  20. NUM_OUTPUTS = deviceCount
  21. };
  22. enum LightIds {
  23. NUM_LIGHTS
  24. };
  25. int state[deviceCount] = {};
  26. DS_Schmitt schmittTrigger[deviceCount];
  27. FF_1() : DS_Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  28. void step() override {
  29. if (doResetFlag) doReset();
  30. if (doRandomFlag) doRandomize();
  31. if (inputs[INPUT].active) {
  32. if (schmittTrigger[0].redge(this, inputs[INPUT].value))
  33. state[0] = !state[0];
  34. }
  35. outputs[OUTPUT_1].value = state[0]?voltage1:voltage0;
  36. for (int i = 1; i < deviceCount; i++) {
  37. if (schmittTrigger[i].fedge(this, state[i-1]?voltage1:voltage0))
  38. state[i] = !state[i];
  39. outputs[OUTPUT_1 + i].value = state[i]?voltage1:voltage0;
  40. }
  41. }
  42. void doRandomize() {
  43. doRandomFlag = 0;
  44. std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());
  45. std::uniform_int_distribution<int> distribution(0,1);
  46. state[0] = distribution(generator);
  47. outputs[OUTPUT_1].value = state[0]?voltage1:voltage0;
  48. for (int i = 1; i < deviceCount; i++) {
  49. state[i] = distribution(generator);
  50. schmittTrigger[i].set(state[i-1]);
  51. outputs[OUTPUT_1 + i].value = state[i]?voltage1:voltage0;
  52. }
  53. }
  54. void doReset() {
  55. doResetFlag = 0;
  56. for (int i = 0; i < deviceCount; i++) {
  57. state[i] = 0;
  58. if (i) schmittTrigger[i].reset();
  59. outputs[OUTPUT_1 + i].value = voltage0;
  60. }
  61. }
  62. void onRandomize() override {
  63. if (rack::global->gPaused) {
  64. doRandomize();
  65. }
  66. else {
  67. doResetFlag = 0;
  68. doRandomFlag = 1;
  69. }
  70. }
  71. void onReset() override {
  72. if (rack::global->gPaused) {
  73. doReset();
  74. }
  75. else {
  76. doRandomFlag = 0;
  77. doResetFlag = 1;
  78. }
  79. }
  80. };
  81. struct FF110 : ModuleWidget {
  82. FF110(FF_1<10> *module) : ModuleWidget(module) {
  83. setPanel(SVG::load(assetPlugin(plugin, "res/FF-110.svg")));
  84. addInput(Port::create<BluePort>(Vec(2.5,19), Port::INPUT, module, FF_1<10>::INPUT));
  85. for (int i = 0; i < 10; i++) {
  86. int offset = 29 * i;
  87. addOutput(Port::create<BluePort>(Vec(2.5,77 + offset), Port::OUTPUT, module, FF_1<10>::OUTPUT_1 + i));
  88. }
  89. }
  90. void appendContextMenu(Menu *menu) override {
  91. ((DS_Module *)module)->appendContextMenu(menu);
  92. }
  93. };
  94. struct FF120 : ModuleWidget {
  95. FF120(FF_1<20> *module) : ModuleWidget(module) {
  96. setPanel(SVG::load(assetPlugin(plugin, "res/FF-120.svg")));
  97. addInput(Port::create<BluePort>(Vec(17.5,19), Port::INPUT, module, FF_1<20>::INPUT));
  98. for (int i = 0; i < 20; i+=2) {
  99. int offset = 15 * i;
  100. addOutput(Port::create<BluePort>(Vec(4,53 + offset), Port::OUTPUT, module, FF_1<20>::OUTPUT_1 + i));
  101. addOutput(Port::create<BluePort>(Vec(31,68 + offset), Port::OUTPUT, module, FF_1<20>::OUTPUT_1 + i + 1));
  102. }
  103. }
  104. void appendContextMenu(Menu *menu) override {
  105. ((DS_Module *)module)->appendContextMenu(menu);
  106. }
  107. };
  108. } // namespace rack_plugin_SubmarineFree
  109. using namespace rack_plugin_SubmarineFree;
  110. RACK_PLUGIN_MODEL_INIT(SubmarineFree, FF110) {
  111. Model *modelFF110 = Model::create<FF_1<10>, FF110>("Submarine (Free)", "FF-110", "FF-110 10-Stage Flip-Flop Counter", LOGIC_TAG, MULTIPLE_TAG);
  112. return modelFF110;
  113. }
  114. RACK_PLUGIN_MODEL_INIT(SubmarineFree, FF120) {
  115. Model *modelFF120 = Model::create<FF_1<20>, FF120>("Submarine (Free)", "FF-120", "FF-120 20-Stage Flip-Flop Counter", LOGIC_TAG, MULTIPLE_TAG);
  116. return modelFF120;
  117. }