Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
cv_engine.h
1/*
2 * Copyright © 2015-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "model/drum/gate_drum.h"
21#include <cstdint>
22
23#define WHICH_GATE_OUTPUT_IS_RUN 2
24#define WHICH_GATE_OUTPUT_IS_CLOCK 3
25
26const uint8_t gatePort[] = {2, 2, 2, 4};
27const uint8_t gatePin[] = {7, 8, 9, 0};
28
29class CVChannel {
30public:
31 CVChannel() {
32 noteCurrentlyPlaying = -32768;
33 voltsPerOctave = 100;
34 transpose = 0;
35 cents = 0;
36 pitchBend = 0;
37 }
38 int16_t noteCurrentlyPlaying;
39 uint8_t voltsPerOctave;
40 int8_t transpose;
41 int8_t cents;
42 int32_t
43 pitchBend; // (1 << 23) represents one semitone. So full 32-bit range can be +-256 semitones. This is different
44 // to the equivalent calculation in Voice, which needs to get things into a number of octaves.
45};
46
47class GateChannel {
48public:
49 GateChannel() { on = false; }
50 bool on; // Means either on now, or "awaiting" switch-on
51 GateType mode;
52 uint32_t timeLastSwitchedOff;
53};
54
55class CVEngine {
56public:
57 CVEngine();
58 void init();
59 void sendNote(bool on, uint8_t channel, int16_t note = -32768);
60 void setGateType(uint8_t whichGate, GateType value);
61 void setCVVoltsPerOctave(uint8_t channel, uint8_t value);
62 void setCVTranspose(uint8_t channel, int32_t semitones, int32_t cents);
63 void setCVPitchBend(uint8_t channel, int32_t value, bool outputToo = true);
64 int32_t calculateVoltage(int32_t note, uint8_t channel);
65 void physicallySwitchGate(int32_t channel);
66 // defer updating the gate while CV is pending and do it when it's done
67 void cvOutUpdated();
68
69 void analogOutTick();
70 void playbackBegun();
71 void playbackEnded();
73 void updateClockOutput();
74 void updateRunOutput();
75 bool isTriggerClockOutputEnabled();
77 void updateGateOutputs();
78
79 bool isGatePending() const { return gateOutputPending; }
80 bool isRunPending() const { return asapGateOutputPending; }
81 bool isClockPending() const { return clockOutputPending; }
82 bool isAnythingButRunPending() const { return isGatePending() || isClockPending(); }
83 bool isAnythingPending() const { return isGatePending() || isClockPending() || isRunPending(); }
84 GateChannel gateChannels[NUM_GATE_CHANNELS];
85
86 CVChannel cvChannels[NUM_PHYSICAL_CV_CHANNELS];
87
88 uint8_t minGateOffTime; // in 100uS's
89
90 bool clockState;
91
92 // When one or more note-on is pending, this is the latest time that one of them last switched off.
93 // But it seems I only use this very coarsely - more to see if we're still in the same audio frame than to measure
94 // time exactly. This could be improved.
95 uint32_t mostRecentSwitchOffTimeOfPendingNoteOn;
96
97 void sendVoltageOut(uint8_t channel, uint16_t voltage);
98
99 inline bool isNoteOn(int32_t channel, int32_t note) {
100 return (gateChannels[channel].on && cvChannels[channel].noteCurrentlyPlaying == note);
101 }
102
103private:
104 void recalculateCVChannelVoltage(uint8_t channel);
105 void switchGateOff(int32_t channel);
106 void switchGateOn(int32_t channel, int32_t doInstantlyIfPossible = false);
108 bool cvOutPending{false};
110 bool gateOutputPending{false};
115};
116
117extern CVEngine cvEngine;
Definition cv_engine.h:29
Definition cv_engine.h:55
void updateGateOutputs()
physically send all gate outs if any output pending
Definition cv_engine.cpp:94
bool cvOutPending
signifies there's a gate that can't go until the cv is output
Definition cv_engine.h:108
bool clockOutputPending
gate 4 as a clock signal
Definition cv_engine.h:114
bool gateOutputPending
gate 1-4 as synths or drums
Definition cv_engine.h:110
void updateClockOutput()
toggles clock, does not physically update until updateGateOutputs called
Definition cv_engine.cpp:321
bool asapGateOutputPending
gate 3 as a run signal
Definition cv_engine.h:112
Definition cv_engine.h:47