initial commit of new GridSeq firmware
This commit is contained in:
129
firmware/GridSeq/channel.h
Normal file
129
firmware/GridSeq/channel.h
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @file channel.h
|
||||
* @author Adam Wonak (https://github.com/awonak/)
|
||||
* @brief Grid Sequencer.
|
||||
* @version 1.0.0
|
||||
* @date 2025-08-12
|
||||
*
|
||||
* @copyright MIT - (c) 2025 - Adam Wonak - adam.wonak@gmail.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHANNEL_H
|
||||
#define CHANNEL_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <libGravity.h>
|
||||
|
||||
#include "euclidean.h"
|
||||
|
||||
// Enums for CV Mod destination
|
||||
enum CvDestination : uint8_t {
|
||||
CV_DEST_NONE,
|
||||
CV_DEST_MODE,
|
||||
CV_DEST_LENGTH,
|
||||
CV_DEST_DIV,
|
||||
CV_DEST_PROB,
|
||||
CV_DEST_DENSITY,
|
||||
CV_DEST_LAST,
|
||||
};
|
||||
|
||||
// Enums for GridSeq modes
|
||||
enum Mode : uint8_t {
|
||||
MODE_SEQ,
|
||||
MODE_EUCLIDEAN,
|
||||
MODE_PATTERN,
|
||||
MODE_LAST,
|
||||
};
|
||||
|
||||
|
||||
class Channel {
|
||||
public:
|
||||
Channel() {
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init() {
|
||||
base_probability = 100;
|
||||
|
||||
cv1_dest = CV_DEST_NONE;
|
||||
cv2_dest = CV_DEST_NONE;
|
||||
}
|
||||
|
||||
bool isCvModActive() const { return cv1_dest != CV_DEST_NONE || cv2_dest != CV_DEST_NONE; }
|
||||
|
||||
// Setters (Set the BASE value)
|
||||
|
||||
void setProbability(int prob) {
|
||||
base_probability = constrain(prob, 0, 100);
|
||||
}
|
||||
|
||||
void setCv1Dest(CvDestination dest) {
|
||||
cv1_dest = dest;
|
||||
}
|
||||
void setCv2Dest(CvDestination dest) {
|
||||
cv2_dest = dest;
|
||||
}
|
||||
CvDestination getCv1Dest() const { return cv1_dest; }
|
||||
CvDestination getCv2Dest() const { return cv2_dest; }
|
||||
|
||||
// Getters (Get the BASE value for editing or cv modded value for display)
|
||||
int getProbability() const { return base_probability; }
|
||||
|
||||
// Getters that calculate the value with CV modulation applied.
|
||||
int getProbabilityWithMod(int cv1_val, int cv2_val) {
|
||||
int prob_mod = _calculateMod(CV_DEST_PROB, cv1_val, cv2_val, -50, 50);
|
||||
return constrain(base_probability + prob_mod, 0, 100);
|
||||
}
|
||||
|
||||
void toggleMute() { mute = !mute; }
|
||||
|
||||
/**
|
||||
* @brief Processes a clock tick and determines if the output should be high or low.
|
||||
* Note: this method is called from an ISR and must be kept as simple as possible.
|
||||
* @param tick The current clock tick count.
|
||||
* @param output The output object to be modified.
|
||||
*/
|
||||
void processClockTick(uint32_t tick, DigitalOutput& output) {
|
||||
// Mute check
|
||||
if (mute) {
|
||||
output.Low();
|
||||
return;
|
||||
}
|
||||
|
||||
int cv1 = gravity.cv1.Read();
|
||||
int cv2 = gravity.cv2.Read();
|
||||
int cvmod_probability = getProbabilityWithMod(cv1, cv2);
|
||||
|
||||
// Duty cycle high check logic
|
||||
if (!output.On()) {
|
||||
// Step check
|
||||
bool hit = cvmod_probability >= random(0, 100);
|
||||
if (hit) {
|
||||
output.Trigger();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
int _calculateMod(CvDestination dest, int cv1_val, int cv2_val, int min_range, int max_range) {
|
||||
int mod1 = (cv1_dest == dest) ? map(cv1_val, -512, 512, min_range, max_range) : 0;
|
||||
int mod2 = (cv2_dest == dest) ? map(cv2_val, -512, 512, min_range, max_range) : 0;
|
||||
return mod1 + mod2;
|
||||
}
|
||||
|
||||
// User-settable base values.
|
||||
byte base_probability;
|
||||
|
||||
// CV mod configuration
|
||||
CvDestination cv1_dest;
|
||||
CvDestination cv2_dest;
|
||||
|
||||
// Mute channel flag
|
||||
bool mute;
|
||||
|
||||
uint16_t _duty_pulses;
|
||||
};
|
||||
|
||||
#endif // CHANNEL_H
|
||||
Reference in New Issue
Block a user