-
Notifications
You must be signed in to change notification settings - Fork 189
Feature - Calibration Helpers #397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
I know I'm being a little annoying, but this class could use some nice unit tests ;-) |
|
@TheSlowGrowth not annoying at all! Thanks for the review! I'll add some tests, and address the stuff you mentioned above. |
… address here as well
|
Addressed the notes from the review, and greatly increased simplicity of the class. Still need to add the unit tests for both PRs, but should be usable now. I removed all of the "state' stuff, except I did leave a To see everything in context, here's an example of a short calibration program for a single input on the new Patch SM board: #include "daisy_patch_sm.h"
#include "daisysp.h"
using namespace daisy;
struct MyCalibrationData
{
float offset, scale;
/** Constructor sets defaults */
MyCalibrationData() : offset(0.f), scale(0.f) {}
/** Simple comparison operators for triggering saves */
bool operator==(const MyCalibrationData &rhs) const
{
return offset == rhs.offset && scale == rhs.scale;
}
bool operator!=(const MyCalibrationData &rhs) const
{
return !operator==(rhs);
}
};
/** Order of events for state machine */
enum CalibrationProcedureState
{
PATCH_1V,
PATCH_3V,
PATCH_DONE_CALIBRATING,
};
/** shorthand for our template-based storage class */
using MyStorageClass = PersistentStorage<MyCalibrationData>;
DaisyPatchSM patch;
/** The pieces related to calibration, and storage. */
CalibrationProcedureState cal_state;
VoctCalibration cal;
MyStorageClass cal_storage(patch.qspi);
MyCalibrationData cal_data;
float value_1v; /**< Temporary value for 1V */
/** UI elements for triggering the calibration */
Switch button;
Led led;
bool trigger_save;
/** Oscillator to "hear" the calibration once it's done. */
daisysp::Oscillator osc;
void AudioCallback(AudioHandle::InputBuffer in,
AudioHandle::OutputBuffer out,
size_t size)
{
patch.ProcessAllControls();
button.Debounce();
/** This is going to be the value we record */
float value = patch.GetAdcValue(patch.CV_1);
float bright = 0.f; /**< LED Brightness */
/** Handle the LED and button depending on the state of the calibration */
switch(cal_state)
{
case PATCH_1V:
if(button.RisingEdge())
{
value_1v = value;
cal_state = PATCH_3V;
}
/** Waiting for 1V, slow blink */
bright = (System::GetNow() & 1023) > 511 ? 1.f : 0.f;
break;
case PATCH_3V:
if(button.RisingEdge())
{
if(cal.Record(value_1v, value))
{
/** Calibration is now complete. Let's trigger a save! */
trigger_save = true;
cal_state = PATCH_DONE_CALIBRATING;
}
}
/** Waiting for 3V, fast blink */
bright = (System::GetNow() & 255) > 127 ? 1.f : 0.f;
break;
case PATCH_DONE_CALIBRATING:
default:
/** Any other state the LED will be a short blip off, but long on */
bright = (System::GetNow() & 2047) > 63 ? 1.f : 0.f;
break;
}
/** Handle the LED */
led.Set(bright);
led.Update();
/** Use the calibration data to set the pitch of an oscillator */
float freq = daisysp::mtof(48.f + cal.ProcessInput(value));
osc.SetFreq(freq);
for(size_t i = 0; i < size; i++)
out[0][i] = out[1][i] = osc.Process();
}
int main(void)
{
/** Initialize the Hardware itself */
patch.Init();
/** And set up the button and LED to match the patch sm eval hardware. */
button.Init(patch.B7, patch.AudioCallbackRate());
led.Init(patch.C1, false);
MyCalibrationData cal_defaults;
cal_storage.Init(cal_defaults);
cal_state = PATCH_1V;
trigger_save = false;
/** Restore settings from previous power cycle */
if(cal_storage.GetState() == MyStorageClass::State::USER)
{
auto &data = cal_storage.GetSettings();
cal.SetData(data.scale, data.offset);
}
/** Oscillator init */
osc.Init(patch.AudioSampleRate());
patch.StartAudio(AudioCallback);
while(1)
{
if(trigger_save)
{
auto &data = cal_storage.GetSettings();
cal.GetData(data.scale, data.offset);
cal_storage.Save();
trigger_save = false;
}
}
} |
|
Added some unit tests, and pending any other changes this might be good to go. One thing that occurred to me is that it might be worth setting the defaults to the "ideal" settings instead of to settings that will essentially kill an input. Having the default |
…QSPI memory (or unit test data structure).
…ed -- fixes unit test issue with mem address changing.
…something in the future.
Based on #396 so merge that first, though this doesn't actually change anything that's used there.
This provides a new class:
VoctCalibrationthat can be used to perform a simple calibration.The idea is that you'll use this either in a separate program, or as part of a more complex application, and then store the
scaleandoffsetvalues within a the PersistentStorage class for recall between power cycles.For convenience there is also a
ProcessInput, though I'm used to managing this data elsewhere (usually the board support file for whatever hardware I'm working on).