EXAMPLE How to access the Terrarium toggle / footswitches

Robert

Reverse Engineer
The Terrarium platform was designed to work as seamlessly as possible with the libDaisy Petal API, but because the number of toggle switches (and footswitches) deviates from the Petal interface we need to use a different set of constants to address them.

The Terrarium header file (terrarium.h) can be downloaded from this link.

At the top of our source file we need to include the Terrarium header file and direct the compiler to use the "terrarium" namespace.
C++:
#include "terrarium.h"
using namespace terrarium;

Now we can access the state of the footswitches and toggle switches using the standard Daisy functions by specifying the Terrarium switch constants.

C++:
if (hw.switches[Terrarium::FOOTSWITCH_1].Pressed())
{
    // Footswitch 1 is pressed
}

C++:
if (hw.switches[Terrarium::SWITCH_1].Pressed())
{
    // Toggle switch 1 is ON
}

Here is the code in an example project. In this example the footswitches toggle the Terrarium LEDs on and off.
C++:
// PedalPCB Terrarium Switch Example
#include "daisy_petal.h"
#include "daisysp.h"
#include "terrarium.h"

using namespace daisy;
using namespace daisysp;
using namespace terrarium;

DaisyPetal hw;

dsy_gpio led1;
dsy_gpio led2;

void AudioCallback(float *in, float *out, size_t size)
{
    hw.DebounceControls();
    hw.UpdateAnalogControls();

    if (hw.switches[Terrarium::FOOTSWITCH_1].RisingEdge())
        dsy_gpio_toggle(&led1);

    if (hw.switches[Terrarium::FOOTSWITCH_2].RisingEdge())
        dsy_gpio_toggle(&led2);

}

int main(void)
{
    hw.Init();
    hw.StartAdc();
    hw.StartAudio(AudioCallback);

    led1.pin = hw.seed.GetPin(22);
    led1.mode = DSY_GPIO_MODE_OUTPUT_PP;
    led1.pull = DSY_GPIO_NOPULL;
    dsy_gpio_init(&led1);

    led2.pin = hw.seed.GetPin(23);
    led2.mode = DSY_GPIO_MODE_OUTPUT_PP;
    led2.pull = DSY_GPIO_NOPULL;
    dsy_gpio_init(&led2);
      
    for(;;)
    {
    }
}
 
Last edited by a moderator:
The Terrarium platform was designed to work as seamlessly as possible with the libDaisy Petal API, but because the number of toggle switches (and footswitches) deviates from the Petal interface we need to use a different set of constants to address them.

The Terrarium header file (terrarium.h) can be downloaded from this link.

At the top of our source file we need to include the Terrarium header file and direct the compiler to use the "terrarium" namespace.
C++:
#include "terrarium.h"
using namespace terrarium;

Now we can access the state of the footswitches and toggle switches using the standard Daisy functions by specifying the Terrarium switch constants.

C++:
if (hw.switches[Terrarium::FOOTSWITCH_1].Pressed())
{
    // Footswitch 1 is pressed
}

C++:
if (hw.switches[Terrarium::SWITCH_1].Pressed())
{
    // Toggle switch 1 is ON
}

Here is the code in an example project. In this example the footswitches toggle the Terrarium LEDs on and off.
C++:
// PedalPCB Terrarium Switch Example
#include "daisy_petal.h"
#include "daisysp.h"
#include "terrarium.h"

using namespace daisy;
using namespace daisysp;
using namespace terrarium;

DaisyPetal hw;

dsy_gpio led1;
dsy_gpio led2;

void AudioCallback(float *in, float *out, size_t size)
{
    hw.DebounceControls();
    hw.UpdateAnalogControls();

    if (hw.switches[Terrarium::FOOTSWITCH_1].RisingEdge())
        dsy_gpio_toggle(&led1);

    if (hw.switches[Terrarium::FOOTSWITCH_2].RisingEdge())
        dsy_gpio_toggle(&led2);

}

int main(void)
{
    hw.Init();
    hw.StartAdc();
    hw.StartAudio(AudioCallback);

    led1.pin = hw.seed.GetPin(22);
    led1.mode = DSY_GPIO_MODE_OUTPUT_PP;
    led1.pull = DSY_GPIO_NOPULL;
    dsy_gpio_init(&led1);

    led2.pin = hw.seed.GetPin(23);
    led2.mode = DSY_GPIO_MODE_OUTPUT_PP;
    led2.pull = DSY_GPIO_NOPULL;
    dsy_gpio_init(&led2);
     
    for(;;)
    {
    }
}
I have a general hardware question about the Toggle switches and pots. Is there a specific value range or will it be dependent on what kind of pedal we’re developing? Or should I just get all 500k A or B and call it good?

Are the toggle switches SPDT ON/ON or ON/off/ON?

thanks!
 
The pots on the Daisy Petal were all B10K so that's what I used in the Terrarium prototypes. I would assume B100K would work perfectly fine as well, and probably put less of a load on the voltage regulator in the Seed.

The toggle switches are all SPDT ON/ON.

I'll get the build docs posted in the next day or two.
 
Which way does the Daisy Seed fit on the Terrarium? Is the micro USB jack supposed to be closer to the audio IN or the audio OUT?
 
The Micro USB goes on the left end, closest to the IN.

I'll update the silkscreen to make this more obvious. There's a pin 1 indicator on the board but that gets covered up by the pinheaders.
 
The pots on the Daisy Petal were all B10K so that's what I used in the Terrarium prototypes. I would assume B100K would work perfectly fine as well, and probably put less of a load on the voltage regulator in the Seed.
Has anyone tried pots other than B10k?
 
C++:
if (hw.switches[Terrarium::SWITCH_1].Pressed())
{
    // Toggle switch 1 is ON
}

C++:
    if (hw.switches[Terrarium::FOOTSWITCH_1].RisingEdge())

Is there any difference between how the first example above has Pressed, but most of the other things have RisingEdge? Are the two terms interchangeable or are they specific functions?
 
I used Pressed in the first example just so it was a more intuitive read for folks who aren't familiar with the functions. "Pressed" is obvious, "RisingEdge" might not be so obvious to someone just getting started.

There are three functions for accessing switches, RisingEdge, FallingEdge, and Pressed.

RisingEdge returns true the moment the switch is pressed.
FallingEdge returns true the moment the switch is released.
Pressed returns true for the entire duration that the switch is held down (or switched on, in the case of a toggle switch).

RisingEdge and FallingEdge only return true at the moment the switch transition occurs. This is useful when you want to detect an instantaneous button press.

We use RisingEdge for bypass switching because we only want to toggle from Active/Bypass once when the footswitch is pressed down. If we used Pressed, the algorithm would rapidly switch on and off many times while the footswitch was still pressed down.

You would use Pressed if you wanted to use a footswitch as a momentary control. (momentary kill switch, set delay feedback to max, etc)
 
Where would I put the terrarium.h file? in the folder with the daisy libraries?

Sorry I didn't see this until just now. I've been putting the terrarium.h file in each of my project folders.

You could put it in one of the daisy library folders (libdaisy, daisysp) if you wanted, but I personally like to keep those folders untouched.
 
Last edited by a moderator:
It’s generally not a good idea to have multiple copies of the same file floating around. On Linux and Mac OS, you can use symbolic links to manage this better . On Windows, I don't know.
 
I keep it in the project folder so each project is self contained.

If I zip up the folder and send it to someone else they have everything they need that isn't standard libDaisy / daisySP code, I don't have to include a separate file with instructions on how/where to place the file (which might vary depending on where each person keeps their libraries).

Also the terrarium.h file is a work in progress, so it's a safeguard against any versioning issues.

Eventually it will be moved into it's own folder, but for now it's just a simple include so that would be overkill. In it's current (unpublished) state there is also some function implementation in the header, which of course is frowned upon, but it just makes things easier to work with at the moment.
 
Sorry I didn't see this until just now. I've been putting the terrarium.h file in each of my project folders.

You could put it in one of the daisy library folders (libdaisy, daisysp) if you wanted, but I personally like to keep those folders untouched.
One solution to this would be to make a Terrarium repo on github which contains this file and add it to your projects as a submodule (I am probably going to end up doing this). This would be the same process that happens with the "DaisySP" and "daisyLib" submodules that get pulled down for the DaisyExamples repo.

Also, the file should probably have ifndef/def/endifs

C++:
#ifndef TERRARIUM_HEADER
#define TERRARIUM_HEADER
namespace terrarium
{
    class Terrarium
    {
        public:
            enum Sw
            {
                FOOTSWITCH_1 = 4,
                FOOTSWITCH_2 = 5,
                SWITCH_1 = 2,
                SWITCH_2 = 1,
                SWITCH_3 = 0,
                SWITCH_4 = 6
            };
    };
}
#endif

It might be overkill at this point since it is only this header file ... but ... I imagine perhaps more will be added to this file in the future?
 
One solution to this would be to make a Terrarium repo on github which contains this file and add it to your projects as a submodule (I am probably going to end up doing this). This would be the same process that happens with the "DaisySP" and "daisyLib" submodules that get pulled down for the DaisyExamples repo.

Also, the file should probably have ifndef/def/endifs

C++:
#ifndef TERRARIUM_HEADER
#define TERRARIUM_HEADER
namespace terrarium
{
    class Terrarium
    {
        public:
            enum Sw
            {
                FOOTSWITCH_1 = 4,
                FOOTSWITCH_2 = 5,
                SWITCH_1 = 2,
                SWITCH_2 = 1,
                SWITCH_3 = 0,
                SWITCH_4 = 6
            };
    };
}
#endif

It might be overkill at this point since it is only this header file ... but ... I imagine perhaps more will be added to this file in the future?
See this post:
 
Some minor changes for using the example with the current library:

Old:
void AudioCallback(float *in, float *out, size_t size)
{
hw.Debounce();
hw.UpdateAnalogControls();

New:
void AudioCallback(const float *in, float *out, size_t size)
{
hw.ProcessDigitalControls();
hw.ProcessAnalogControls();
 
Last edited:
Back
Top