Skip to content
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

Create App for Scope using fullscreen #76

Open
wants to merge 7 commits into
base: production
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
225 changes: 225 additions & 0 deletions software/o_c_REV/APP_BIGSCOPE.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#include "HSApplication.h"
#include "HSMIDI.h"

#define HEMISPHERE_MAX_CV 7680
#define HEMISPHERE_CENTER_CV 0
#define SCOPE_WIDTH 128

class BigScope : public HSApplication, public SystemExclusiveHandler {
public:
void Start() {
last_bpm_tick = OC::CORE::ticks;
bpm = 0;
sample_ticks = 320;
freeze = 0;
last_scope_tick = 0;
}

void Resume() {
}

void Controller() {
if (Clock(0)) {
int this_tick = OC::CORE::ticks;
int time = this_tick - last_bpm_tick;
last_bpm_tick = this_tick;
bpm = 1000000 / time;
if (bpm > 9999) bpm = 9999;

if (last_scope_tick) {
int cycle_ticks = OC::CORE::ticks - last_scope_tick;
sample_ticks = cycle_ticks / 64;
sample_ticks = constrain(sample_ticks, 2, 64000);
}
last_scope_tick = OC::CORE::ticks;
}

if (!freeze) {
last_cv = In(0);

if (--sample_countdown < 1) {
sample_countdown = sample_ticks;
if (++sample_num > 127) sample_num = 0;
int sample = Proportion(In(0), HEMISPHERE_MAX_CV, 128);
sample = constrain(sample, -128, 127) + 127;
snapshot[sample_num] = (uint8_t) sample;
}

Out(0, In(0));
}
}

void View() {
gfxHeader("Scope");
//gfxPrint(1, 2, "Scope");
//DrawTicks();
DrawVoltage();
DrawBPM();
DrawInput1();
if (freeze) {
gfxInvert(0, 24, 128, 40);
}
}

void OnSendSysEx() {
}

void OnReceiveSysEx() {
}

/////////////////////////////////////////////////////////////////
// Control handlers
/////////////////////////////////////////////////////////////////
void OnLeftButtonPress() {
freeze = 1 - freeze;
}

void OnLeftButtonLongPress() {

}

void OnRightButtonPress() {
}

void OnUpButtonPress() {
}

void OnDownButtonPress() {
}

void OnDownButtonLongPress() {
}
Comment on lines +77 to +91

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these methods have to be defined in order to prevent null references down the line? Or is it just common practice in this repo to define all the possible event handlers?


void OnLeftEncoderMove(int direction) {
if (sample_ticks < 32) sample_ticks += direction;
else sample_ticks += direction * 10;
sample_ticks = constrain(sample_ticks, 2, 64000);
last_encoder_move = OC::CORE::ticks;
}

void OnRightEncoderMove(int direction) {
}

private:
// BPM Calcultion
int last_bpm_tick;
int bpm;

// CV monitor
int last_cv;
bool freeze;

// Scope
uint8_t snapshot[128];
int sample_ticks; // Ticks between samples
int sample_countdown; // Last time a sample was taken
int sample_num; // Current sample number at the start
int last_encoder_move; // The last the the sample_ticks value was changed
int last_scope_tick; // Used to auto-calculate sample countdown

void DrawBPM() {
gfxPrint(110, 1, bpm / 4);
gfxBitmap(102, 1, 8, CLOCK_ICON);
}

// void DrawTicks() {
// gfxPrint(40, 1, sample_ticks);
// }
Comment on lines +125 to +127

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Please remove any commented out code or uncomment this if it's needed.
If this has to stay, please leave a comment on why it's commented out and when it should be uncommented.



void gfxPrintVoltage(int cv) {
int v = (cv * 100) / (12 << 7);
bool neg = v < 0 ? 1 : 0;
if (v < 0) v = -v;
int wv = v / 100; // whole volts
int dv = v - (wv * 100); // decimal
gfxPrint(neg ? "-" : "+");
gfxPrint(wv);
gfxPrint(".");
if (dv < 10) gfxPrint("0");
gfxPrint(dv);
gfxPrint("V");
Comment on lines +131 to +141

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Could you get some formatting done in here? Obviously it's of zero importance in the grand scheme of things, but readability is king 👑

}

void DrawVoltage() {
gfxBitmap(45, 3, 8, CV_ICON);
gfxPos(55, 1);
gfxPrintVoltage(last_cv);
}

void DrawInput1() {
for (int s = 0; s < 128; s++)
{
int x = s + sample_num;
if (x > 127) x -= 128;
int l = Proportion(snapshot[x], 255, 48);
gfxPixel(x, (48 - l) + 14);
}

}

};

BigScope BigScope_instance;

// App stubs
void BigScope_init() {
BigScope_instance.BaseStart();
}

// Not using O_C Storage
size_t BigScope_storageSize() { return 0; }

size_t BigScope_save(void *storage) { return 0; }

size_t BigScope_restore(const void *storage) { return 0; }

void BigScope_isr() {
return BigScope_instance.BaseController();
}

void BigScope_handleAppEvent(OC::AppEvent event) {
if (event == OC::APP_EVENT_RESUME) {
BigScope_instance.Resume();
}
if (event == OC::APP_EVENT_SUSPEND) {
BigScope_instance.OnSendSysEx();
}
}

void BigScope_loop() {} // Deprecated

void BigScope_menu() {
BigScope_instance.BaseView();
}

void BigScope_screensaver() {} // Deprecated

void BigScope_handleButtonEvent(const UI::Event &event) {
// For left encoder, handle press and long press
if (event.control == OC::CONTROL_BUTTON_L) {
if (event.type == UI::EVENT_BUTTON_LONG_PRESS) BigScope_instance.OnLeftButtonLongPress();
else BigScope_instance.OnLeftButtonPress();
}

// For right encoder, only handle press (long press is reserved)
if (event.control == OC::CONTROL_BUTTON_R && event.type == UI::EVENT_BUTTON_PRESS)
BigScope_instance.OnRightButtonPress();

// For up button, handle only press (long press is reserved)
if (event.control == OC::CONTROL_BUTTON_UP) BigScope_instance.OnUpButtonPress();

// For down button, handle press and long press
if (event.control == OC::CONTROL_BUTTON_DOWN) {
if (event.type == UI::EVENT_BUTTON_PRESS) BigScope_instance.OnDownButtonPress();
if (event.type == UI::EVENT_BUTTON_LONG_PRESS) BigScope_instance.OnDownButtonLongPress();
}
}
Comment on lines +198 to +217

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pristine 🛀 Great Job!


void BigScope_handleEncoderEvent(const UI::Event &event) {
// Left encoder turned
if (event.control == OC::CONTROL_ENCODER_L) BigScope_instance.OnLeftEncoderMove(event.value);

// Right encoder turned
if (event.control == OC::CONTROL_ENCODER_R) BigScope_instance.OnRightEncoderMove(event.value);
}
1 change: 1 addition & 0 deletions software/o_c_REV/OC_apps.ino
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ OC::App available_apps[] = {
DECLARE_APP('H','S', "Hemisphere", HEMISPHERE),
DECLARE_APP('M','I', "Captain MIDI", MIDI),
DECLARE_APP('D','2', "Darkest Timeline", TheDarkestTimeline),
DECLARE_APP('B','S', "Scope", BigScope),
DECLARE_APP('E','N', "Enigma", EnigmaTMWS),
DECLARE_APP('N','N', "Neural Net", NeuralNetwork),
DECLARE_APP('S','C', "Scale Editor", SCALEEDITOR),
Expand Down