text: #undef V1_COMPAT
  #include <string.h>
  #include "../FrozenWasteland.hpp"
  #include "dsp/digital.hpp"
  #define NUM_RULERS 10
  #define MAX_DIVISIONS 6
  #define TRACK_COUNT 4
  #define MAX_STEPS 18
  
  namespace old {
  
  struct QuadGolombRulerRhythm : Module {
  	enum ParamIds {
  		STEPS_1_PARAM,
  		DIVISIONS_1_PARAM,
  		OFFSET_1_PARAM,
  		PAD_1_PARAM,
  		ACCENTS_1_PARAM,
  		ACCENT_ROTATE_1_PARAM,
  		STEPS_2_PARAM,
  		DIVISIONS_2_PARAM,
  		OFFSET_2_PARAM,
  		PAD_2_PARAM,
  		ACCENTS_2_PARAM,
  		ACCENT_ROTATE_2_PARAM,
  		STEPS_3_PARAM,
  		DIVISIONS_3_PARAM,
  		OFFSET_3_PARAM,
  		PAD_3_PARAM,
  		ACCENTS_3_PARAM,
  		ACCENT_ROTATE_3_PARAM,
  		STEPS_4_PARAM,
  		DIVISIONS_4_PARAM,
  		OFFSET_4_PARAM,
  		PAD_4_PARAM,
  		ACCENTS_4_PARAM,
  		ACCENT_ROTATE_4_PARAM,
  		CHAIN_MODE_PARAM,	
  		CONSTANT_TIME_MODE_PARAM,		
  		NUM_PARAMS
  	};
  	enum InputIds {
  		STEPS_1_INPUT,
  		DIVISIONS_1_INPUT,
  		OFFSET_1_INPUT,
  		PAD_1_INPUT,
  		ACCENTS_1_INPUT,
  		ACCENT_ROTATE_1_INPUT,
  		START_1_INPUT,
  		STEPS_2_INPUT,
  		DIVISIONS_2_INPUT,
  		OFFSET_2_INPUT,
  		PAD_2_INPUT,
  		ACCENTS_2_INPUT,
  		ACCENT_ROTATE_2_INPUT,
  		START_2_INPUT,
  		STEPS_3_INPUT,
  		DIVISIONS_3_INPUT,
  		OFFSET_3_INPUT,
  		PAD_3_INPUT,
  		ACCENTS_3_INPUT,
  		ACCENT_ROTATE_3_INPUT,
  		START_3_INPUT,
  		STEPS_4_INPUT,
  		DIVISIONS_4_INPUT,
  		OFFSET_4_INPUT,
  		PAD_4_INPUT,
  		ACCENTS_4_INPUT,
  		ACCENT_ROTATE_4_INPUT,
  		START_4_INPUT,
  		CLOCK_INPUT,
  		RESET_INPUT,
  		MUTE_INPUT,
  		NUM_INPUTS
  	};
  	enum OutputIds {
  		OUTPUT_1,
  		ACCENT_OUTPUT_1,
  		EOC_OUTPUT_1,
  		OUTPUT_2,
  		ACCENT_OUTPUT_2,
  		EOC_OUTPUT_2,
  		OUTPUT_3,
  		ACCENT_OUTPUT_3,
  		EOC_OUTPUT_3,
  		OUTPUT_4,
  		ACCENT_OUTPUT_4,
  		EOC_OUTPUT_4,
  		NUM_OUTPUTS
  	};
  	enum LightIds {
  		CHAIN_MODE_NONE_LIGHT,
  		CHAIN_MODE_BOSS_LIGHT,
  		CHAIN_MODE_EMPLOYEE_LIGHT,
  		MUTED_LIGHT,
  		CONSTANT_TIME_LIGHT,
  		NUM_LIGHTS
  	};
  	enum ChainModes {
  		CHAIN_MODE_NONE,
  		CHAIN_MODE_BOSS,
  		CHAIN_MODE_EMPLOYEE
  	};
  
  
  	bool beatMatrix[TRACK_COUNT][MAX_STEPS];
  	bool accentMatrix[TRACK_COUNT][MAX_STEPS];
  	int beatIndex[TRACK_COUNT];
  	int stepsCount[TRACK_COUNT];
  	float stepDuration[TRACK_COUNT];
  	float lastStepTime[TRACK_COUNT];
  	float maxStepCount;
  
  
  	const int rulerOrders[NUM_RULERS] = {1,2,3,4,5,5,6,6,6,6};
  	const int rulerLengths[NUM_RULERS] = {0,1,3,6,11,11,17,17,17,17};
  	const int rulers[NUM_RULERS][MAX_DIVISIONS] = {{0},
  												   {0,1},
  												   {0,1,3},
  												   {0,1,4,6},
  												   {0,1,4,9,11},
  												   {0,2,7,8,11},
  												   {0,1,4,10,12,17},
  												   {0,1,4,10,15,17},
  												   {0,1,8,11,13,17},
  												   {0,1,8,12,14,17}};
  
  	bool running[TRACK_COUNT];
  	int chainMode = 0;
  	bool initialized = false;
  	bool muted = false;
  	bool constantTime = false;
  
  	float time = 0.0;
  	float duration = 0.0;
  	bool secondClockReceived = false;
  
  	SchmittTrigger clockTrigger,resetTrigger,chainModeTrigger,constantTimeTrigger,muteTrigger,startTrigger[TRACK_COUNT];
  	PulseGenerator beatPulse[TRACK_COUNT],accentPulse[TRACK_COUNT],eocPulse[TRACK_COUNT];
  
  
  	QuadGolombRulerRhythm() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS,NUM_LIGHTS) {
  		for(unsigned i = 0; i < TRACK_COUNT; i++) {
  			beatIndex[i] = 0;
  			stepsCount[i] = MAX_STEPS;
  			lastStepTime[i] = 0.0;
  			stepDuration[i] = 0.0;
  			running[i] = true;
  			for(unsigned j = 0; j < MAX_STEPS; j++) {
  				beatMatrix[i][j] = false;
  				accentMatrix[i][j] = false;
  			}
  		}		
  	}
  	void step() override;
  
  
  	json_t *toJson() override {
  		json_t *rootJ = json_object();
  		json_object_set_new(rootJ, "constantTime", json_integer((bool) constantTime));
  		json_object_set_new(rootJ, "chainMode", json_integer((int) chainMode));
  		json_object_set_new(rootJ, "muted", json_integer((bool) muted));
  		return rootJ;
  	}
  
  	void fromJson(json_t *rootJ) override {
  		json_t *ctJ = json_object_get(rootJ, "constantTime");
  		if (ctJ)
  			constantTime = json_integer_value(ctJ);
  
  		json_t *cmJ = json_object_get(rootJ, "chainMode");
  		if (cmJ)
  			chainMode = json_integer_value(cmJ);
  
  		json_t *mutedJ = json_object_get(rootJ, "muted");
  		if (mutedJ)
  			muted = json_integer_value(mutedJ);
  	}
  
  	void setRunningState() {
  		for(int trackNumber=0;trackNumber<TRACK_COUNT;trackNumber++)
  		{
  			if(chainMode == CHAIN_MODE_EMPLOYEE && inputs[(trackNumber * 7) + 6].active) { //START Input needs to be active
  				running[trackNumber] = false;
  			}
  			else {
  				running[trackNumber] = true;
  			}
  		}
  	}
  
  	void advanceBeat(int trackNumber) {
  		beatIndex[trackNumber]++;
  		lastStepTime[trackNumber] = 0.0;		
  					
  		//End of Cycle
  		if(beatIndex[trackNumber] >= stepsCount[trackNumber]) {
  			beatIndex[trackNumber] = 0;
  			eocPulse[trackNumber].trigger();
  			//If in a chain mode, stop running until start trigger received
  			if(chainMode != CHAIN_MODE_NONE && inputs[(trackNumber * 7) + 6].active) { //START Input needs to be active
  				running[trackNumber] = false;
  			}
  		}
  	}
  
  	// For more advanced Module features, read Rack's engine.hpp header file
  	// - onSampleRateChange: event triggered by a change of sample rate
  	// - onReset, onRandomize, onCreate, onDelete: implements special behavior when user clicks these from the context menu
  };
  
  
  
  void QuadGolombRulerRhythm::step() {
  
  	int accentLevelArray[MAX_STEPS];
  	int beatLocation[MAX_STEPS];
  
  	//Set startup state
  	if(!initialized) {
  		setRunningState();
  		initialized = true;
  	}
  
  	// Modes
  	if (constantTimeTrigger.process(params[CONSTANT_TIME_MODE_PARAM].value)) {
  		constantTime = !constantTime;
  		for(int trackNumber=0;trackNumber<TRACK_COUNT;trackNumber++) {
  			beatIndex[trackNumber] = 0;
  		}
  		setRunningState();
  	}
  	lights[CONSTANT_TIME_LIGHT].value = constantTime;
  
  	if (chainModeTrigger.process(params[CHAIN_MODE_PARAM].value)) {
  		chainMode = (chainMode + 1) % 3;
  		setRunningState();
  	}
  	lights[CHAIN_MODE_NONE_LIGHT].value = chainMode == CHAIN_MODE_NONE ? 1.0 : 0.0;
  	lights[CHAIN_MODE_BOSS_LIGHT].value = chainMode == CHAIN_MODE_BOSS ? 1.0 : 0.0;
  	lights[CHAIN_MODE_EMPLOYEE_LIGHT].value = chainMode == CHAIN_MODE_EMPLOYEE ? 1.0 : 0.0;
  
  	lights[MUTED_LIGHT].value = muted ? 1.0 : 0.0;
  
  
  	for(int trackNumber=0;trackNumber<TRACK_COUNT;trackNumber++) {
  		//clear out the matrix and levels
  		for(int j=0;j<MAX_STEPS;j++)
  		{
  			beatMatrix[trackNumber][j] = false; 
  			accentMatrix[trackNumber][j] = false;
  			accentLevelArray[j] = 0;	
  			beatLocation[j] = 0;
  		}
  
  		float stepsCountf = params[trackNumber * 6].value;
  		if(inputs[trackNumber * 7].active) {
  			stepsCountf += inputs[trackNumber * 7].value;
  		}
  		stepsCountf = clamp(stepsCountf,0.0f,18.0f);
  
  		float divisionf = params[(trackNumber * 6) + 1].value;
  		if(inputs[(trackNumber * 7) + 1].active) {
  			divisionf += inputs[(trackNumber * 7) + 1].value;
  		}		
  		divisionf = clamp(divisionf,0.0f,(float)(NUM_RULERS-1));
  
  		float offsetf = params[(trackNumber * 6) + 2].value;
  		if(inputs[(trackNumber * 7) + 2].active) {
  			offsetf += inputs[(trackNumber * 7) + 2].value;
  		}	
  		offsetf = clamp(offsetf,0.0f,17.0f);
  
  		float padf = params[trackNumber * 6 + 3].value;
  		if(inputs[trackNumber * 7 + 3].active) {
  			padf += inputs[trackNumber * 7 + 3].value;
  		}
  		padf = clamp(padf,0.0f,stepsCountf - divisionf);
  
  
  		//Use this to reduce range of accent params/inputs so the range of motion of knob/modulation is more useful.
  		float divisionScale = 1;
  		if(stepsCountf > 0) {
  			divisionScale = divisionf / stepsCountf;
  		}		
  
  		float accentDivisionf = params[(trackNumber * 6) + 4].value * divisionScale;
  		if(inputs[(trackNumber * 7) + 4].active) {
  			accentDivisionf += inputs[(trackNumber * 7) + 4].value * divisionScale;
  		}
  		accentDivisionf = clamp(accentDivisionf,0.0f,divisionf);
  
  		float accentRotationf = params[(trackNumber * 6) + 5].value * divisionScale;
  		if(inputs[(trackNumber * 7) + 5].active) {
  			accentRotationf += inputs[(trackNumber * 7) + 5].value * divisionScale;
  		}
  		if(divisionf > 0) {
  			accentRotationf = clamp(accentRotationf,0.0f,divisionf-1);			
  		} else {
  			accentRotationf = 0;
  		}
  
  		if(stepsCountf > maxStepCount)
  			maxStepCount = stepsCountf;
  
  		stepsCount[trackNumber] = int(stepsCountf);
  		int division = int(divisionf);
  		int offset = int(offsetf);		
  		int pad = int(padf);
  		int accentDivision = int(accentDivisionf);
  		int accentRotation = int(accentRotationf);
  
  
  		//Calculate Beats if there are divisions to calcuate for	
  		//Ruler Lengths and orders are 0 based, which is why I add 1 here. 	
  		//Yes, I could add 1 to length in the constant array, but I want that to match wikipedia definition				
  		if(stepsCount[trackNumber] > 0 && division > 0) {
  			int rulerToUse = division - 1;
  			int actualStepCount = stepsCount[trackNumber] - pad;
  			while(rulerLengths[rulerToUse] + 1 > actualStepCount && rulerToUse >= 	0) {
  				rulerToUse -=1;
  			} 
  			
  			//Multiply beats so that low division beats fill out entire pattern
  			int spaceMultiplier = (actualStepCount / (rulerLengths[rulerToUse] + 1)) + 1;
  			if(actualStepCount % (rulerLengths[rulerToUse] + 1) == 0) {
  				spaceMultiplier -=1;
  			}			
  
  			
  
  			for (int j = 0; j < rulerOrders[rulerToUse];j++)
  			{
  				int divisionLocation = rulers[rulerToUse][j] * spaceMultiplier;
  				divisionLocation +=pad;
  				if(j > 0) {
  					divisionLocation -=1;
  				}
  				beatMatrix[trackNumber][(divisionLocation + offset) % stepsCount[trackNumber]] = true;
  	            beatLocation[j] = (divisionLocation + offset) % stepsCount[trackNumber];	            
  			}
  
  		
  
  	        //Calculate Accents
  	        int level = 0;
  	        int restsLeft = std::max(0,rulerOrders[rulerToUse]-accentDivision); // just make sure no negatives
  	        do {
  				accentLevelArray[level] = std::min(restsLeft,accentDivision);
  				restsLeft = restsLeft - accentDivision;
  				level += 1;
  			} while (restsLeft > 0 && level < MAX_STEPS);
  
  			int tempIndex =0;
  			for (int j = 0; j < accentDivision; j++) {
  	            accentMatrix[trackNumber][beatLocation[(tempIndex + accentRotation) % rulerOrders[rulerToUse]]] = true;
  	            tempIndex++;
  	            for (int k = 0; k < MAX_STEPS; k++) {
  	                if (accentLevelArray[k] > j) {
  	                    tempIndex++;
  	                }
  	            }
  	        }	
          }	
  	}
  
  	if(inputs[RESET_INPUT].active) {
  		if(resetTrigger.process(inputs[RESET_INPUT].value)) {
  			for(int trackNumber=0;trackNumber<TRACK_COUNT;trackNumber++)
  			{
  				beatIndex[trackNumber] = 0;
  			}
  			setRunningState();
  		}
  	}
  
  	if(inputs[MUTE_INPUT].active) {
  		if(muteTrigger.process(inputs[MUTE_INPUT].value)) {
  			muted = !muted;
  		}
  	}
  
  	//See if need to start up
  	for(int trackNumber=0;trackNumber < TRACK_COUNT;trackNumber++) {
  		if(chainMode != CHAIN_MODE_NONE && inputs[(trackNumber * 7) + 6].active && !running[trackNumber]) {
  			if(startTrigger[trackNumber].process(inputs[(trackNumber * 7) + 6].value)) {
  				running[trackNumber] = true;
  			}
  		}
  	}
  
  	//Advance beat on trigger if not in constant time mode
  	float timeAdvance =1.0 / engineGetSampleRate();
      time += timeAdvance;
  	if(inputs[CLOCK_INPUT].active) {
  		if(clockTrigger.process(inputs[CLOCK_INPUT].value)) {
  			if(secondClockReceived) {
  				duration = time;
  			}
  			time = 0;
  			secondClockReceived = true;			
  
  			for(int trackNumber=0;trackNumber < TRACK_COUNT;trackNumber++)
  			{
  				if(running[trackNumber]) {
  					if(!constantTime) {
  						advanceBeat(trackNumber);
  					}					
  				}
  			}
  		}
  
  		bool resyncAll = false;
  		//For constant time, don't rely on clock trigger to advance beat, use time
  		for(int trackNumber=0;trackNumber < TRACK_COUNT;trackNumber++) {
  			if(stepsCount[trackNumber] > 0)
  				stepDuration[trackNumber] = duration * maxStepCount / (float)stepsCount[trackNumber];
  
  			if(running[trackNumber]) {
  				lastStepTime[trackNumber] +=timeAdvance;
  				if(constantTime && stepDuration[trackNumber] > 0.0 && lastStepTime[trackNumber] >= stepDuration[trackNumber]) {
  					advanceBeat(trackNumber);
  					if(stepsCount[trackNumber] >= (int)maxStepCount && beatIndex[trackNumber] == 0) {
  						resyncAll = true;
  					}
  				}					
  			}
  		}
  		if(resyncAll) {
  			for(int trackNumber=0;trackNumber < TRACK_COUNT;trackNumber++) {
  				lastStepTime[trackNumber] = 0;
  				beatIndex[trackNumber] = 0;
  			}
  		}
  	}
  
  	// Set output to current state		
  	for(int trackNumber=0;trackNumber<TRACK_COUNT;trackNumber++) {
  		float outputValue = (lastStepTime[trackNumber] < stepDuration[trackNumber] / 2) ? 10.0 : 0.0;
  		//Send out beat
  		if(beatMatrix[trackNumber][beatIndex[trackNumber]] == true && running[trackNumber] && !muted) {
  			outputs[trackNumber * 3].value = outputValue;	
  		} else {
  			outputs[trackNumber * 3].value = 0.0;	
  		}
  		//send out accent
  		if(accentMatrix[trackNumber][beatIndex[trackNumber]] == true && running[trackNumber] && !muted) {
  			outputs[trackNumber * 3 + 1].value = outputValue;	
  		} else {
  			outputs[trackNumber * 3 + 1].value = 0.0;	
  		}
  		//Send out End of Cycle
  		outputs[(trackNumber * 3) + 2].value = eocPulse[trackNumber].process(1.0 / engineGetSampleRate()) ? 10.0 : 0;	
  	}
  
  }
  
  struct QBRBeatDisplay : TransparentWidget {
  	QuadGolombRulerRhythm *module;
  	int frame = 0;
  	std::shared_ptr<Font> font;
  
  	QBRBeatDisplay() {
  		font = Font::load(assetPlugin(pluginInstance, "res/fonts/Sudo.ttf"));
  	}
  
  	void drawBox(NVGcontext *vg, float stepNumber, float trackNumber,bool isBeat,bool isAccent,bool isCurrent) {
  		
  		//nvgSave(vg);
  		//Rect b = Rect(Vec(0, 0), box.size);
  		//nvgScissor(vg, b.pos.x, b.pos.y, b.size.x, b.size.y);
  		
  		float boxX = stepNumber * 22.5;
  		float boxY = trackNumber * 22.5;
  
  		float opacity = 0x80; // Testing using opacity for accents
  
  		if(isAccent) {
  			opacity = 0xff;
  		}
  
  
  		NVGcolor strokeColor = nvgRGBA(0, 0xe0, 0xef, 0xff);
  		NVGcolor fillColor = nvgRGBA(0,0xe0,0xef,opacity);
  		if(isCurrent)
  		{
  			strokeColor = nvgRGBA(0x2f, 0xf0, 0, 0xff);
  			fillColor = nvgRGBA(0x2f,0xf0,0,opacity);			
  		}
  
  		nvgStrokeColor(vg, strokeColor);
  		nvgStrokeWidth(vg, 1.0);
  		nvgBeginPath(vg);
  		nvgRect(vg,boxX,boxY,21,21.0);
  		nvgStroke(vg);
  		nvgClosePath(vg);
  		if(isBeat) {
  			nvgFillColor(vg, fillColor);
  			nvgFill(vg);
  		}
  	}
  
  	void draw(NVGcontext *vg) override {
  
  		for(int trackNumber = 0;trackNumber < 4;trackNumber++) {
  			for(int stepNumber = 0;stepNumber < module->stepsCount[trackNumber];stepNumber++) {				
  				bool isBeat = module->beatMatrix[trackNumber][stepNumber];
  				bool isAccent = module->accentMatrix[trackNumber][stepNumber];
  				bool isCurrent = module->beatIndex[trackNumber] == stepNumber && module->running[trackNumber];				
  				drawBox(vg, float(stepNumber), float(trackNumber),isBeat,isAccent,isCurrent);
  			}
  
  		}
  	}
  };
  
  
  struct QuadGolombRulerRhythmWidget : ModuleWidget {
  	QuadGolombRulerRhythmWidget(QuadGolombRulerRhythm *module);
  };
  
  QuadGolombRulerRhythmWidget::QuadGolombRulerRhythmWidget(QuadGolombRulerRhythm *module) : ModuleWidget(module) {
  	box.size = Vec(15*29, RACK_GRID_HEIGHT);
  
  	{
  		SVGPanel *panel = new SVGPanel();
  		panel->box.size = box.size;
  		panel->setBackground(SVG::load(assetPlugin(pluginInstance, "res/old/QuadGolombRulerRhythm.svg")));
  		addChild(panel);
  	}
  
  	addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH - 12, 0)));
  	addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH + 12, 0)));
  	addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH - 12, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  	addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH + 12, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  
  
  	{
  		QBRBeatDisplay *display = new QBRBeatDisplay();
  		display->module = module;
  		display->box.pos = Vec(16, 34);
  		display->box.size = Vec(box.size.x-30, 135);
  		addChild(display);
  	}
  
  
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(22, 138), module, QuadGolombRulerRhythm::STEPS_1_PARAM, 0.0, 18.2, 18.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(61, 138), module, QuadGolombRulerRhythm::DIVISIONS_1_PARAM, 0.0, 10.2, 2.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(100, 138), module, QuadGolombRulerRhythm::OFFSET_1_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(139, 138), module, QuadGolombRulerRhythm::PAD_1_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(178, 138), module, QuadGolombRulerRhythm::ACCENTS_1_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(217, 138), module, QuadGolombRulerRhythm::ACCENT_ROTATE_1_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(22, 195), module, QuadGolombRulerRhythm::STEPS_2_PARAM, 0.0, 18.0, 18.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(61, 195), module, QuadGolombRulerRhythm::DIVISIONS_2_PARAM, 0.0, 10.2, 2.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(100, 195), module, QuadGolombRulerRhythm::OFFSET_2_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(139, 195), module, QuadGolombRulerRhythm::PAD_2_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(178, 195), module, QuadGolombRulerRhythm::ACCENTS_2_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(217, 195), module, QuadGolombRulerRhythm::ACCENT_ROTATE_2_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(22, 252), module, QuadGolombRulerRhythm::STEPS_3_PARAM, 0.0, 18.2, 18.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(61, 252), module, QuadGolombRulerRhythm::DIVISIONS_3_PARAM, 0.0, 10.2, 2.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(100, 252), module, QuadGolombRulerRhythm::OFFSET_3_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(139, 252), module, QuadGolombRulerRhythm::PAD_3_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(178, 252), module, QuadGolombRulerRhythm::ACCENTS_3_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(217, 252), module, QuadGolombRulerRhythm::ACCENT_ROTATE_3_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(22, 309), module, QuadGolombRulerRhythm::STEPS_4_PARAM, 0.0, 18.2, 18.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(61, 309), module, QuadGolombRulerRhythm::DIVISIONS_4_PARAM, 0.0, 10.2, 2.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(100, 309), module, QuadGolombRulerRhythm::OFFSET_4_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(139, 309), module, QuadGolombRulerRhythm::PAD_4_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(178, 309), module, QuadGolombRulerRhythm::ACCENTS_4_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(217, 309), module, QuadGolombRulerRhythm::ACCENT_ROTATE_4_PARAM, 0.0, 17.2, 0.0));
  	addParam(ParamWidget::create<CKD6>(Vec(250, 285), module, QuadGolombRulerRhythm::CHAIN_MODE_PARAM, 0.0, 1.0, 0.0));
  	addParam(ParamWidget::create<CKD6>(Vec(360, 285), module, QuadGolombRulerRhythm::CONSTANT_TIME_MODE_PARAM, 0.0, 1.0, 0.0));
  
  	addInput(Port::create<PJ301MPort>(Vec(23, 163), Port::INPUT, module, QuadGolombRulerRhythm::STEPS_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(62, 163), Port::INPUT, module, QuadGolombRulerRhythm::DIVISIONS_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(101, 163), Port::INPUT, module, QuadGolombRulerRhythm::OFFSET_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(140, 163), Port::INPUT, module, QuadGolombRulerRhythm::PAD_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(179, 163), Port::INPUT, module, QuadGolombRulerRhythm::ACCENTS_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(218, 163), Port::INPUT, module, QuadGolombRulerRhythm::ACCENT_ROTATE_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(23, 220), Port::INPUT, module, QuadGolombRulerRhythm::STEPS_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(62, 220), Port::INPUT, module, QuadGolombRulerRhythm::DIVISIONS_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(101, 220), Port::INPUT, module, QuadGolombRulerRhythm::OFFSET_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(140, 220), Port::INPUT, module, QuadGolombRulerRhythm::PAD_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(179, 220), Port::INPUT, module, QuadGolombRulerRhythm::ACCENTS_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(218, 220), Port::INPUT, module, QuadGolombRulerRhythm::ACCENT_ROTATE_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(23, 277), Port::INPUT, module, QuadGolombRulerRhythm::STEPS_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(62, 277), Port::INPUT, module, QuadGolombRulerRhythm::DIVISIONS_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(101, 277), Port::INPUT, module, QuadGolombRulerRhythm::OFFSET_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(140, 277), Port::INPUT, module, QuadGolombRulerRhythm::PAD_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(179, 277), Port::INPUT, module, QuadGolombRulerRhythm::ACCENTS_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(218, 277), Port::INPUT, module, QuadGolombRulerRhythm::ACCENT_ROTATE_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(23, 334), Port::INPUT, module, QuadGolombRulerRhythm::STEPS_4_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(62, 334), Port::INPUT, module, QuadGolombRulerRhythm::DIVISIONS_4_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(101, 334), Port::INPUT, module, QuadGolombRulerRhythm::OFFSET_4_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(140, 334), Port::INPUT, module, QuadGolombRulerRhythm::PAD_4_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(179, 334), Port::INPUT, module, QuadGolombRulerRhythm::ACCENTS_4_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(218, 334), Port::INPUT, module, QuadGolombRulerRhythm::ACCENT_ROTATE_4_INPUT));
  
  	addInput(Port::create<PJ301MPort>(Vec(262, 343), Port::INPUT, module, QuadGolombRulerRhythm::CLOCK_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(302, 343), Port::INPUT, module, QuadGolombRulerRhythm::RESET_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(335, 343), Port::INPUT, module, QuadGolombRulerRhythm::MUTE_INPUT));
  
  	addInput(Port::create<PJ301MPort>(Vec(322, 145), Port::INPUT, module, QuadGolombRulerRhythm::START_1_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(322, 175), Port::INPUT, module, QuadGolombRulerRhythm::START_2_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(322, 205), Port::INPUT, module, QuadGolombRulerRhythm::START_3_INPUT));
  	addInput(Port::create<PJ301MPort>(Vec(322, 235), Port::INPUT, module, QuadGolombRulerRhythm::START_4_INPUT));
  
  
  	addOutput(Port::create<PJ301MPort>(Vec(255, 145), Port::OUTPUT, module, QuadGolombRulerRhythm::OUTPUT_1));
  	addOutput(Port::create<PJ301MPort>(Vec(286, 145), Port::OUTPUT, module, QuadGolombRulerRhythm::ACCENT_OUTPUT_1));
  	addOutput(Port::create<PJ301MPort>(Vec(354, 145), Port::OUTPUT, module, QuadGolombRulerRhythm::EOC_OUTPUT_1));
  	addOutput(Port::create<PJ301MPort>(Vec(256, 175), Port::OUTPUT, module, QuadGolombRulerRhythm::OUTPUT_2));
  	addOutput(Port::create<PJ301MPort>(Vec(286, 175), Port::OUTPUT, module, QuadGolombRulerRhythm::ACCENT_OUTPUT_2));
  	addOutput(Port::create<PJ301MPort>(Vec(354, 175), Port::OUTPUT, module, QuadGolombRulerRhythm::EOC_OUTPUT_2));
  	addOutput(Port::create<PJ301MPort>(Vec(256, 205), Port::OUTPUT, module, QuadGolombRulerRhythm::OUTPUT_3));
  	addOutput(Port::create<PJ301MPort>(Vec(286, 205), Port::OUTPUT, module, QuadGolombRulerRhythm::ACCENT_OUTPUT_3));
  	addOutput(Port::create<PJ301MPort>(Vec(354, 205), Port::OUTPUT, module, QuadGolombRulerRhythm::EOC_OUTPUT_3));
  	addOutput(Port::create<PJ301MPort>(Vec(256, 235), Port::OUTPUT, module, QuadGolombRulerRhythm::OUTPUT_4));
  	addOutput(Port::create<PJ301MPort>(Vec(286, 235), Port::OUTPUT, module, QuadGolombRulerRhythm::ACCENT_OUTPUT_4));
  	addOutput(Port::create<PJ301MPort>(Vec(354, 235), Port::OUTPUT, module, QuadGolombRulerRhythm::EOC_OUTPUT_4));
  	
  	addChild(ModuleLightWidget::create<SmallLight<BlueLight>>(Vec(282, 285), module, QuadGolombRulerRhythm::CHAIN_MODE_NONE_LIGHT));
  	addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(282, 300), module, QuadGolombRulerRhythm::CHAIN_MODE_BOSS_LIGHT));
  	addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(282, 315), module, QuadGolombRulerRhythm::CHAIN_MODE_EMPLOYEE_LIGHT));
  
  	addChild(ModuleLightWidget::create<LargeLight<RedLight>>(Vec(363, 347), module, QuadGolombRulerRhythm::MUTED_LIGHT));
  	addChild(ModuleLightWidget::create<SmallLight<BlueLight>>(Vec(395, 295), module, QuadGolombRulerRhythm::CONSTANT_TIME_LIGHT));
  }
  
  Model *modelQuadGolombRulerRhythm_old = Model::create<QuadGolombRulerRhythm, QuadGolombRulerRhythmWidget>("Frozen Wasteland", "QuadGolombRulerRhythm", "Quad Golomb Ruler Rhythm (Legacy)", SEQUENCER_TAG);
  
  }
  