Here's how to show what "setting" you're on based on LED tally pattern, (bonus knob to encoder util included)

kylewetton

Active member
Hello! Watch the video for a proper demo, but here's two very helpful utils that I've created.


The first being LedOptionIndicator

C++:
while(1)
    {     
        int rotary_position = GetRotaryPosition(knob1);
        LedOptionIndicator(led2, rotary_position);
        System::Delay(1);
    }

You pass an LED and an int, this int represents what "option" you're on.

The LED will flash this int and then rest for a second, you can look down and see "I'm on position 4", or "I'm on position 10". Whether it's a reverb setting, or a waveform type, whatever it is.

Once it reaches 5 and above, it groups batches of 5 into long blinks. Think of it like tally marks

. . . is three
_ is five
_ . . is seven
_ _ . is eleven

Video probably explained it better

The second util is GetRotaryPosition
C++:
knob1.Init(hw.knob[Terrarium::KNOB_1], 0.f, 1.f, Parameter::LINEAR);
int rotary_position = GetRotaryPosition(knob1);

What you can do with this util is convert a default 0f - 1f knob to a rotary of any count.

The default is 11 positions (based on a Marshal 0 - 10 pot marking)

You can however use a different count based on how many positions you have / need.

C++:
int rotary_position = GetRotaryPosition(knob1, 6);

You'd need to pass that custom position count in each time you get the position, so be sure to set and forget it as a variable instead somewhere.

Any way, here it is

1713934283357.png
Add terrarium_utils.cpp and the header file to your project

Then include it in your main pedal file. You'll then be able to use the above.

1713934330482.png

Add the source to your Makefile

(Instead of the Terrarium folder, I've moved it to it's own Utils folder for git reasons)
C++:
CPP_SOURCES = your_pedal.cpp
CPP_SOURCES += ../Utils/terrarium_utils.cpp

C++:
// terrarium_utils.h

#ifndef TERRARIUM_UTILS_H
#define TERRARIUM_UTILS_H

#include <vector>
#include <utility>
#include <cstdint>

namespace daisy {
    class Led; 
    class Parameter;
}

enum LedOptionIndicatorAction {
    Blink,
    Gap,
    Rest
};

void LedOptionIndicator(daisy::Led& led, int num_blinks);
int GetRotaryPosition(daisy::Parameter& knob, int totalPositions = 11);

#endif // TERRARIUM_UTILS_H


C++:
// terrarium_utils.cpp

#include "terrarium_utils.h"
#include "daisy_petal.h"
#include "daisysp.h"

using namespace daisy;

class LedOptionIndicatorTimer {
public:
    uint32_t start_time;
    LedOptionIndicatorTimer() { reset(); }
    void reset() { start_time = System::GetNow(); }
    uint32_t elapsed() const { return System::GetNow() - start_time; }
};

void LedOptionIndicator(Led& led, int num_blinks) {
    LedOptionIndicatorTimer timer;
    std::vector<std::pair<LedOptionIndicatorAction, uint32_t>> actions;

    int short_rest = 200;
    int long_rest = 1500;
    int short_on = 200;
    int long_on = 600;

    int longBlinkGroups = num_blinks / 5;
    int remainingBlinks = num_blinks % 5;

    for (int i = 0; i < longBlinkGroups; ++i) {
        actions.emplace_back(Blink, long_on);
        actions.emplace_back(Gap, short_rest);
    }

    for (int i = 0; i < remainingBlinks; ++i) {
        actions.emplace_back(Blink, short_on);
        actions.emplace_back(Gap, short_rest);
    }

    if (!actions.empty() && actions.back().first == Gap) {
        actions.pop_back();
    }

    actions.emplace_back(Rest, long_rest);

    for (const auto& action : actions) {
        timer.reset();
        while (timer.elapsed() < action.second) {
            if (action.first == Blink) {
                led.Set(true);
            } else {
                led.Set(false);
            }
        }
    }
    led.Set(false);
}

int GetRotaryPosition(Parameter& knob, int totalPositions) {
    if (totalPositions < 1) totalPositions = 1;

    int position = static_cast<int>(knob.Process() * totalPositions);
  
    if (position == totalPositions) {
        position = totalPositions - 1;
    }

    return position + 1;
}
 
Last edited:
Back
Top