Skip to content

Commit

Permalink
documenting cvRange
Browse files Browse the repository at this point in the history
  • Loading branch information
patheros committed Oct 31, 2022
1 parent 5f529e3 commit 457a3ef
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/GlassPane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ struct GPRoot : Module {
DEBUG("configNodes B nodeMax %i",nodeMax);
for(int ni = 0; ni < nodeMax; ni++){
configSwitch<ModeParamQuantity>(modeButtonParam + ni, 0.f, 2.f, 0.f, "Mode ", std::vector<std::string>{"Cycle","Random","Ratchet"});
configParam<CVRangeParamQuantity>(cvKnobParam + ni, 0.f, 1.f, 0.5f, "CV", "V")->range = &range;
configCVParam(cvKnobParam + ni, this, &range, "CV");
configInput(modeTriggerInput + ni, "Mode Trigger");
for(int ii = 0 ; ii < NODE_IN_MAX; ii ++){
char alphabet = 'X' + ii;
Expand Down
8 changes: 4 additions & 4 deletions src/OneShot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ struct OneShot : Module {

OneShot() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
configParam<CVRangeParamQuantity>(STEP1_PARAM, 0.f, 1.f, 0.5f, "CV 1", "V")->range = &range;
configParam<CVRangeParamQuantity>(STEP2_PARAM, 0.f, 1.f, 0.5f, "CV 2", "V")->range = &range;
configParam<CVRangeParamQuantity>(STEP3_PARAM, 0.f, 1.f, 0.5f, "CV 3", "V")->range = &range;
configParam<CVRangeParamQuantity>(STEP4_PARAM, 0.f, 1.f, 0.5f, "CV 4", "V")->range = &range;
configCVParam(STEP1_PARAM, this, &range, "CV 1");
configCVParam(STEP2_PARAM, this, &range, "CV 2");
configCVParam(STEP3_PARAM, this, &range, "CV 3");
configCVParam(STEP4_PARAM, this, &range, "CV 4");
configParam(LENGTH_PARAM, 1, 16, 4, "Length");
configSwitch(STABLE_PARAM, 0.f, 1.f, 0.f, "Stable", std::vector<std::string>{"Stable","Unstable"});
configParam(CHANCE_PARAM, 0.f, 1.f, 0.f, "Random", "%", 0.f, 100.f, 0.f);
Expand Down
133 changes: 123 additions & 10 deletions src/cvRange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,90 @@
#define CV_MIN -10.f
#define CV_MAX 10.f

/**
* Stores a configurable Control Voltage (CV) range.
*
* Example use case would be as a field on a Sequencer Module.
*
* `dataToJson` and `dataFromJson` functions to persist the configured range.
*
* `addMenu` adds a configuration option to the drop-down menu.
*/
struct CVRange {

//Settings
/**
* Stores the first voltage value for the range.
*
* In the UI this is labled "Min" for minimum, but if this is the larger of the two values it will funciton as the maximum.
*/
float cv_a;

/**
* Stores the second voltage value for the range.
*
* In the UI this is labled "Max" for maxomum, but if this is the lower of the two balues it will funciton as the minimum.
*/
float cv_b;

//Internal
///Internal snapshot of the range full voltage range.
float range;

///Internal snapshot of the mininum voltage value for this range.
float min;

///Constructs a default CVRange with a range of +/- 1V.
CVRange(){
cv_a = -1;
cv_b = 1;
updateInternal();
}

/**
* Constructs a CVRange with a given mininum and maximum.
*
* Note cv_a is always set to min and cv_b is set to max, but if cv_a is greater than cv_b, cv_a will function as a the maxiumu and cv_b will function as the mininum.
*/
CVRange(float min, float max){
cv_a = min;
cv_b = max;
updateInternal();
}

/**
* Returns a json_t object that stores the information for this CVRange.
*
* Expected use is calling it from inside dataToJson on the module.
*
* Example:
*
* json_t *dataToJson() override{
* json_t *jobj = json_object();
* json_object_set_new(jobj, "range", range.dataToJson());
* return jobj;
* }
*
*/
json_t *dataToJson() {
json_t *jobj = json_object();
json_object_set_new(jobj, "a", json_real(cv_a));
json_object_set_new(jobj, "b", json_real(cv_b));
return jobj;
}

/**
* Sets this CVRange to the data present in a json_t object.
*
* If json_t is not a JSON_OBJECT, then the data on this CVRange is not modified
*
* Expected use is calling it from inside dataFromJson on the module.
*
* Example:
*
* void dataFromJson(json_t *jobj) override {
* range.dataFromJson(json_object_get(jobj, "range"));
* }
*
*/
void dataFromJson(json_t *jobj) {
switch(json_typeof(jobj)){
//Backwards Compatabiltiy Case
Expand Down Expand Up @@ -65,24 +120,38 @@ struct CVRange {
updateInternal();
}

//Must be called after cv_a or cv_b is updated
///Must be called after cv_a or cv_b is updated
void updateInternal(){
range = std::abs(cv_a - cv_b);
min = std::min(cv_a, cv_b);
}

//Converts [0,1] into the CV value
///Converts [0,1] into the CV value
float map(float zero_to_one){
return range * zero_to_one + min;
}

//Converts CV value into [0,1]
///Converts CV value into [0,1]
float invMap(float cv_value){
return (cv_value - min) / range;
}

void addMenu(Module* module, Menu* menu){

/**
* Adds a "Range" menu to the passed in menu
*
* Expected use is calling this from appendContextMenu in the ModuleWidget
*
* Example:
*
* void appendContextMenu(Menu* menu) override {
* auto module = dynamic_cast<MyModule*>(this->module);
* module->range.addMenu(module,menu);
* }
*
*/
void addMenu(Module* module, Menu* menu, std::string menuName = "Range"){

//Wraper for cv_a and cv_b to interface with CVTextFiled amd CVSlider
struct CVQuantity : Quantity {
float* value_pointer;
CVRange* range;
Expand Down Expand Up @@ -110,6 +179,7 @@ struct CVRange {
}
};

//Text Field for editing cv_a or cv_b in the menu
struct CVTextFiled : ui::TextField {
Quantity* quantity;

Expand All @@ -133,7 +203,7 @@ struct CVRange {
}
};


//Slider for editing cv_a or cv_b in the menu
struct CVSlider : ui::Slider {
CVTextFiled* textField;
CVSlider(CVRange* range, float* value_pointer) {
Expand All @@ -153,7 +223,7 @@ struct CVRange {
std::string s_max = std::to_string((int)std::ceil(min+range));
std::string curLabel = s_min + "V to " + s_max + "V";

menu->addChild(createSubmenuItem("Range", curLabel,
menu->addChild(createSubmenuItem(menuName, curLabel,
[=](Menu* menu) {
menu->addChild(createSubmenuItem("Custom", "",
[=](Menu* menu) {
Expand Down Expand Up @@ -187,8 +257,8 @@ struct CVRange {
}
};

//Preset constants for the CVRange menu
const int PRESET_COUNT = 12;

const Preset preset [PRESET_COUNT] = {
Preset("+/-10V",-10,10),
Preset("+/-5V",-5,5),
Expand Down Expand Up @@ -218,6 +288,41 @@ struct CVRange {

};

/**
* ParamQuantity for any CV Knob. Not required, but makes the knob show the selected Voltage in the tooltip and edit menu.
*
* WARNING: the range field on this must explicity be set or this will crash.
*
* A helper function `configCVParam` is provided to make this easier
*
* Helper, One-Line Example:
*
* void appendContextMenu(Menu* menu) override {
* ...
* configCVParam(CV_1_PARAM, this, &range, "CV 1");
* ...
* }
*
* Non-Helper, One-Line Example:
*
* void appendContextMenu(Menu* menu) override {
* ...
* configParam<CVRangeParamQuantity>(CV_PARAM, 0.f, 1.f, 0.5f, "CV", "V")->range = &range;
* ...
* }
*
* Non-Helper, Multiline Example:
*
* void appendContextMenu(Menu* menu) override {
* ...
* {
* auto param = configParam<CVRangeParamQuantity>(CV_PARAM, 0.f, 1.f, 0.5f, "CV", "V");
* param->range = &range;
* }
* ...
* }
*
*/
struct CVRangeParamQuantity : ParamQuantity {
CVRange* range;
float getDisplayValue() override {
Expand All @@ -228,3 +333,11 @@ struct CVRangeParamQuantity : ParamQuantity {
setValue(range->invMap(v));
}
};

///See CVRangeParamQuantity for details
template <class TParamQuantity = CVRangeParamQuantity>
TParamQuantity* configCVParam(int paramId, Module* module, CVRange* range, std::string name = "") {
TParamQuantity* q = module->configParam<TParamQuantity>(paramId,0.0f,1.1f,0.5f,name,"V");
q->range = range;
return q;
}

0 comments on commit 457a3ef

Please sign in to comment.