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.

416 lines
12KB

  1. //**************************************************************************************
  2. //Trigger Sequencer Module for VCV Rack by Autodafe http://www.autodafe.net
  3. //
  4. //Based on code taken from the Fundamentals plugins by Andrew Belt http://www.vcvrack.com
  5. //
  6. //**************************************************************************************
  7. #include "Autodafe.hpp"
  8. #include "dsp/digital.hpp"
  9. namespace rack_plugin_Autodafe {
  10. struct TriggerSeq : Module {
  11. enum ParamIds {
  12. CLOCK_PARAM,
  13. RUN_PARAM,
  14. RESET_PARAM,
  15. STEPS_PARAM,
  16. ROW_PARAM,
  17. COLUMN_PARAM = ROW_PARAM+8,
  18. GATE_PARAM=COLUMN_PARAM+16,
  19. NUM_PARAMS = GATE_PARAM+128
  20. };
  21. enum InputIds {
  22. CLOCK_INPUT,
  23. EXT_CLOCK_INPUT,
  24. START_INPUT,
  25. STOP_INPUT,
  26. RESET_INPUT,
  27. STEPS_INPUT,
  28. NUM_INPUTS
  29. };
  30. enum OutputIds {
  31. CLOCK_OUT,
  32. GATES_OUTPUT,
  33. NUM_OUTPUTS = GATES_OUTPUT + 8
  34. };
  35. enum LightIds {
  36. RUNNING_LIGHT,
  37. RESET_LIGHT,
  38. STEP_LIGHTS,
  39. GATE_LIGHTS=STEP_LIGHTS+16,
  40. GATES_LIGHTS=GATE_LIGHTS+8,
  41. NUM_LIGHTS=GATES_LIGHTS +128
  42. };
  43. bool running = true;
  44. SchmittTrigger clockTrigger; // for external clock
  45. SchmittTrigger runningTrigger;
  46. SchmittTrigger resetTrigger;
  47. SchmittTrigger rowTriggers[8];
  48. SchmittTrigger columnTriggers[16];
  49. bool FullRow[8];
  50. bool FullColumn[16];
  51. float phase = 0.0;
  52. int index = 0;
  53. SchmittTrigger gateTriggers[8][16];
  54. bool gateState[8][16]={};
  55. float stepLights[8][16] ;
  56. float stepLightsTop[16] ;
  57. // Lights
  58. float runningLight = 0.0;
  59. float resetLight = 0.0;
  60. float gatesLight[8];
  61. float rowLights[8][16] ;
  62. float gateLights[8][16];
  63. TriggerSeq() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  64. void step();
  65. json_t *toJson() {
  66. json_t *rootJtrigseq = json_object();
  67. json_t *gatesJtrigSeq = json_array();
  68. for (int z = 0; z < 8; z++) {
  69. for (int i = 0; i < 16; i++) {
  70. json_t *gateJtrigseq = json_integer((int)gateState[z][i]);
  71. json_array_append_new(gatesJtrigSeq, gateJtrigseq);
  72. }
  73. }
  74. json_object_set_new(rootJtrigseq, "gatesTrigSeq", gatesJtrigSeq);
  75. return rootJtrigseq;
  76. }
  77. void fromJson(json_t *rootJtrigseq) {
  78. //EMPTY EVERYTHING
  79. for (int z = 0; z < 8; z++) {
  80. for (int i = 0; i < 16; i++) {
  81. gateState[z][i] = false;
  82. }
  83. }
  84. //LOAD FROM FILE
  85. json_t *gatesJtrigSeq = json_object_get(rootJtrigseq, "gatesTrigSeq");
  86. for (int z = 0; z < 8; z++) {
  87. for (int i = 0; i < 16; i++) {
  88. json_t *gateJtrigseq = json_array_get(gatesJtrigSeq, z*16+i);
  89. gateState[z][i] = !!json_integer_value(gateJtrigseq);
  90. }
  91. }
  92. }
  93. void reset() {
  94. for (int z = 0; z < 8; z++) {
  95. for (int i = 0; i < 16; i++) {
  96. gateState[z][i] = false;
  97. }
  98. }
  99. }
  100. void randomize() {
  101. for (int z = 0; z < 8; z++) {
  102. for (int i = 0; i < 16; i++) {
  103. gateState[z][i] = rand()%2;
  104. }
  105. }
  106. }
  107. };
  108. void TriggerSeq::step() {
  109. float gate[8] = { 0 };
  110. const float lightLambda = 0.05f;
  111. outputs[CLOCK_OUT].value=0;
  112. // Run
  113. if (runningTrigger.process(params[RUN_PARAM].value)) {
  114. running = !running;
  115. }
  116. if(inputs[START_INPUT].value>0){running=true;}
  117. if(inputs[STOP_INPUT].value>0){running=false;}
  118. lights[RUNNING_LIGHT].value = running ? 1.0 : 0.0;
  119. bool nextStep = false;
  120. if (running) {
  121. if (inputs[EXT_CLOCK_INPUT].active) {
  122. // External clock
  123. if (clockTrigger.process(inputs[EXT_CLOCK_INPUT].value)) {
  124. phase = 0.0;
  125. nextStep = true;
  126. outputs[CLOCK_OUT].value=1;
  127. }
  128. }
  129. else {
  130. // Internal clock
  131. float clockTime = powf(2.0, params[CLOCK_PARAM].value+ inputs[CLOCK_INPUT].value);
  132. phase += clockTime / engineGetSampleRate();
  133. if (phase >= 1.0) {
  134. phase -= 1.0;
  135. nextStep = true;
  136. outputs[CLOCK_OUT].value=1;
  137. }
  138. }
  139. }
  140. // Reset
  141. if (resetTrigger.process(params[RESET_PARAM].value + inputs[RESET_INPUT].value)) {
  142. phase = 0.0;
  143. index = 999;
  144. nextStep = true;
  145. resetLight = 1.0;
  146. }
  147. if (nextStep) {
  148. // Advance step
  149. int numSteps = clampi(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value), 1, 16);
  150. index += 1;
  151. if (index >= numSteps) {
  152. index = 0;
  153. }
  154. //for (int z = 0; z < 8; z++) {
  155. // stepLights[z][index] = 1.0;
  156. //}
  157. }
  158. resetLight -= resetLight / lightLambda / engineGetSampleRate();
  159. // Gate buttons
  160. for (int z = 0; z < 8; z++) {
  161. //ROW BUTTONS
  162. if (rowTriggers[z].process(params[ROW_PARAM + z].value)) {
  163. FullRow[z]=!FullRow[z];
  164. if (FullRow[z]){
  165. gateState[z][0] = 1;
  166. gateState[z][1] = 1;
  167. gateState[z][2] = 1;
  168. gateState[z][3] = 1;
  169. gateState[z][4] = 1;
  170. gateState[z][5] = 1;
  171. gateState[z][6] = 1;
  172. gateState[z][7] = 1;
  173. gateState[z][8] = 1;
  174. gateState[z][9] = 1;
  175. gateState[z][10] = 1;
  176. gateState[z][11] = 1;
  177. gateState[z][12] = 1;
  178. gateState[z][13] = 1;
  179. gateState[z][14] = 1;
  180. gateState[z][15] = 1;
  181. }
  182. else
  183. {
  184. gateState[z][0] = 0;
  185. gateState[z][1] = 0;
  186. gateState[z][2] = 0;
  187. gateState[z][3] = 0;
  188. gateState[z][4] = 0;
  189. gateState[z][5] = 0;
  190. gateState[z][6] = 0;
  191. gateState[z][7] = 0;
  192. gateState[z][8] = 0;
  193. gateState[z][9] = 0;
  194. gateState[z][10] = 0;
  195. gateState[z][11] = 0;
  196. gateState[z][12] = 0;
  197. gateState[z][13] = 0;
  198. gateState[z][14] = 0;
  199. gateState[z][15] = 0;
  200. }
  201. }
  202. for (int i = 0; i < 16; i++) {
  203. //COLUMN BUTTONS
  204. if (columnTriggers[i].process(params[COLUMN_PARAM + i].value)) {
  205. FullColumn[i]=!FullColumn[i];
  206. if (FullColumn[i]) {
  207. gateState[0][i] = 1;
  208. gateState[1][i] = 1;
  209. gateState[2][i] = 1;
  210. gateState[3][i] = 1;
  211. gateState[4][i] = 1;
  212. gateState[5][i] = 1;
  213. gateState[6][i] = 1;
  214. gateState[7][i] = 1;
  215. }
  216. else
  217. {
  218. gateState[0][i] = 0;
  219. gateState[1][i] = 0;
  220. gateState[2][i] = 0;
  221. gateState[3][i] = 0;
  222. gateState[4][i] = 0;
  223. gateState[5][i] = 0;
  224. gateState[6][i] = 0;
  225. gateState[7][i] = 0;
  226. }
  227. }
  228. gate[z] = (gateState[z][index] >= 1.0) && !nextStep ? 10.0 : 0.0;
  229. outputs[GATES_OUTPUT + z].value= gate[z];
  230. lights[GATES_LIGHTS +z*16+i].value = (gateState[z][i] >= 1.0) ? 1.0 : 0.0;
  231. if (gateTriggers[z][i].process(params[GATE_PARAM + z*16+i].value)) {
  232. gateState[z][i] = !gateState[z][i];
  233. }
  234. }
  235. lights[RESET_LIGHT].value = resetLight;
  236. lights[GATE_LIGHTS + z].value = (gateState[z][index] >= 1.0) ? 1.0 : 0.0;
  237. for (int y=0; y<16; y++){lights[STEP_LIGHTS + y].value=0;}
  238. lights[STEP_LIGHTS + index].value = 1.0;
  239. }
  240. }
  241. struct AutodafePurpleLight : ModuleLightWidget {
  242. AutodafePurpleLight() {
  243. addBaseColor(nvgRGB(0x89, 0x13, 0xC4));
  244. }
  245. };
  246. struct TriggerSeqWidget : ModuleWidget {
  247. TriggerSeqWidget(TriggerSeq *module);
  248. };
  249. TriggerSeqWidget::TriggerSeqWidget(TriggerSeq *module) : ModuleWidget(module) {
  250. box.size = Vec(15*37, 380);
  251. {
  252. SVGPanel *panel = new SVGPanel();
  253. panel->box.size = box.size;
  254. panel->setBackground(SVG::load(assetPlugin(plugin, "res/TriggerSeq.svg")));
  255. addChild(panel);
  256. }
  257. addChild(createScrew<ScrewSilver>(Vec(5, 0)));
  258. addChild(createScrew<ScrewSilver>(Vec(box.size.x-20, 0)));
  259. addChild(createScrew<ScrewSilver>(Vec(5, 365)));
  260. addChild(createScrew<ScrewSilver>(Vec(box.size.x-20, 365)));
  261. addParam(createParam<AutodafeKnobPurpleSmall>(Vec(17, 56), module, TriggerSeq::CLOCK_PARAM, -2.0, 6.0, 2.0));
  262. addParam(createParam<LEDButton>(Vec(60, 61-1), module, TriggerSeq::RUN_PARAM, 0.0, 1.0, 0.0));
  263. //addChild(createValueLight<SmallLight<GreenValueLight>>(Vec(60+5, 61+4), &module->runningLight));
  264. addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(64.4, 64.4), module, TriggerSeq::RUNNING_LIGHT));
  265. addInput(createInput<PJ301MPort>(Vec(173, 98), module, TriggerSeq::START_INPUT));
  266. addInput(createInput<PJ301MPort>(Vec(211, 98), module, TriggerSeq::STOP_INPUT));
  267. addOutput(createOutput<PJ301MPort>(Vec(250, 98), module, TriggerSeq::CLOCK_OUT));
  268. addParam(createParam<LEDButton>(Vec(98, 61-1), module, TriggerSeq::RESET_PARAM, 0.0, 1.0, 0.0));
  269. //addChild(createValueLight<SmallLight<GreenValueLight>>(Vec(98+5, 61+4), &module->resetLight));
  270. addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(103.4, 64.4), module, TriggerSeq::RESET_LIGHT));
  271. addParam(createParam<AutodafeKnobPurple>(Vec(128, 52), module, TriggerSeq::STEPS_PARAM, 1.0, 16.0, 16.0));
  272. static const float portX[16] = { 19, 57, 96, 134, 173, 211, 250, 288, 326, 364, 402, 440,478,516,554,592};
  273. static const float portX2[16] = { 19, 49, 79, 109, 139, 169, 199, 229, 259, 289, 319, 349,379,409,439,469};
  274. //static const float portX[16] = { 20, 50, 80, 110, 140, 170, 200, 230, 260, 290, 320, 350,380,410,440,470};
  275. addInput(createInput<PJ301MPort>(Vec(portX[0]-1, 99-1), module, TriggerSeq::CLOCK_INPUT));
  276. addInput(createInput<PJ301MPort>(Vec(portX[1]-1, 99-1), module, TriggerSeq::EXT_CLOCK_INPUT));
  277. addInput(createInput<PJ301MPort>(Vec(portX[2]-1, 99-1), module, TriggerSeq::RESET_INPUT));
  278. addInput(createInput<PJ301MPort>(Vec(portX[3]-1, 99-1), module, TriggerSeq::STEPS_INPUT));
  279. for (int k=0;k<16;k++)
  280. {
  281. addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(portX2[k] + 6.4, 125), module, TriggerSeq::STEP_LIGHTS + k));
  282. }
  283. for (int z = 0; z < 8; z++)
  284. {
  285. //Gates Oututs
  286. addOutput(createOutput<PJ301MPort>(Vec(510, 140 + 25 * z - 5), module, TriggerSeq::GATES_OUTPUT+z));
  287. addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(495, 143 + 25 * z), module, TriggerSeq::GATE_LIGHTS+z));
  288. addParam(createParam<BtnTrigSequencerSmall>(Vec(4, 140 + 25 * z +2), module, TriggerSeq::ROW_PARAM + z, 0.0, 1.0, 0.0));
  289. for (int i = 0; i < 16; i++) {
  290. //Lighst and Button Matrix
  291. addParam(createParam<BtnTrigSequencer>(Vec(portX2[i] + 2, 140 + 25 * z - 1), module, TriggerSeq::GATE_PARAM + z*16+i, 0.0, 1.0, 0.0));
  292. addParam(createParam<BtnTrigSequencerSmall>(Vec(portX2[i] + 5, 140 + 25 * 8-4.0), module, TriggerSeq::COLUMN_PARAM + i, 0.0, 1.0, 0.0));
  293. //addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(portX[i] + 2, 140 + 25 * z - 1), module, SEQ16::GATE_LIGHTS + z*16+i));
  294. //addParam(createParam<AutodafeButton>(Vec(portX[i] + 2, 140 + 25 * z - 1), module, TriggerSeq::GATE_PARAM + z*16+i, 0.0, 1.0, 0.0));
  295. //addChild(createValueLight<SmallLight<GreenValueLight>>(Vec(portX[i] + 7, 140 + 25 * z + 4), &module->gateLights[z][i]));
  296. addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(portX2[i] + 6.4, 140 + 25 * z+3.0), module, TriggerSeq::GATES_LIGHTS + z*16+i));
  297. }
  298. }
  299. }
  300. } // namespace rack_plugin_Autodafe
  301. using namespace rack_plugin_Autodafe;
  302. RACK_PLUGIN_MODEL_INIT(Autodafe, TriggerSeq) {
  303. return Model::create<TriggerSeq, TriggerSeqWidget>("Autodafe","8x16 Trigger Sequencer", "8x16 Trigger Sequencer", SEQUENCER_TAG);
  304. }