KIK01 Proto 08

Dependencies:   AverageMCP3008 VoltageMonitor mbed-rtos mbed mcp3008

Fork of KIK01_Proto07 by Ryo Od

Committer:
ryood
Date:
Sun Jun 25 15:38:44 2017 +0000
Revision:
14:8e96f97e261b
Parent:
13:43a43da257e3
Child:
15:8f674acdac03
Output Sync Signal

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ryood 3:f89b400cfe57 1 /*
ryood 3:f89b400cfe57 2 * KIK01
ryood 3:f89b400cfe57 3 * Kick Machine
ryood 3:f89b400cfe57 4 *
ryood 13:43a43da257e3 5 * 2017.06.19 Proto02
ryood 3:f89b400cfe57 6 * 2017.06.04 created.
ryood 3:f89b400cfe57 7 *
ryood 3:f89b400cfe57 8 */
ryood 3:f89b400cfe57 9
ryood 0:2dcec10e9199 10 #include "mbed.h"
ryood 0:2dcec10e9199 11 #include "rtos.h"
ryood 13:43a43da257e3 12 #include "mcp3008.h"
ryood 0:2dcec10e9199 13
ryood 10:79134dbb339d 14 #define UART_TRACE (1)
ryood 12:5b498285d121 15 #define PIN_CHECK (1)
ryood 0:2dcec10e9199 16 #define TITLE_STR1 ("KIK01 Kick Machine")
ryood 14:8e96f97e261b 17 #define TITLE_STR2 ("20170625")
ryood 0:2dcec10e9199 18
ryood 0:2dcec10e9199 19 #define PI_F (3.1415926f)
ryood 13:43a43da257e3 20 #define SAMPLING_RATE (48000)
ryood 0:2dcec10e9199 21 #define SAMPLING_PERIOD (1.0f/SAMPLING_RATE)
ryood 13:43a43da257e3 22 #define ENVELOPE_UPDATE_RATE (48000)
ryood 3:f89b400cfe57 23
ryood 13:43a43da257e3 24 AnalogOut Dac1(PA_4);
ryood 0:2dcec10e9199 25
ryood 13:43a43da257e3 26 SPI spiM(SPI_MOSI, SPI_MISO, SPI_SCK);
ryood 13:43a43da257e3 27 MCP3008 Adc0(spiM, D9);
ryood 13:43a43da257e3 28 MCP3008 Adc1(spiM, D10);
ryood 8:bb34a4894337 29
ryood 14:8e96f97e261b 30 // Check pins
ryood 14:8e96f97e261b 31 DigitalOut Dout0(D2);
ryood 14:8e96f97e261b 32 DigitalOut Dout1(D3);
ryood 14:8e96f97e261b 33 DigitalOut Dout2(D4);
ryood 14:8e96f97e261b 34
ryood 14:8e96f97e261b 35 // Sync
ryood 14:8e96f97e261b 36 DigitalOut SyncPin(D7);
ryood 12:5b498285d121 37
ryood 11:7e11404adca0 38 class EnvelopeAR
ryood 11:7e11404adca0 39 {
ryood 0:2dcec10e9199 40 public:
ryood 0:2dcec10e9199 41 EnvelopeAR(int _attack, int _release, float _v0, float _v1, float _v2, float _attackTauRatio=0.36f, float _releaseTauRatio=0.36f) :
ryood 0:2dcec10e9199 42 amplitude(_v0),
ryood 0:2dcec10e9199 43 v0(_v0),
ryood 0:2dcec10e9199 44 v1(_v1),
ryood 0:2dcec10e9199 45 v2(_v2),
ryood 0:2dcec10e9199 46 vLast(_v0),
ryood 0:2dcec10e9199 47 attackTauRatio(_attackTauRatio),
ryood 11:7e11404adca0 48 releaseTauRatio(_releaseTauRatio) {
ryood 0:2dcec10e9199 49 setAttack(_attack);
ryood 0:2dcec10e9199 50 setRelease(_release);
ryood 0:2dcec10e9199 51 }
ryood 0:2dcec10e9199 52
ryood 0:2dcec10e9199 53 ~EnvelopeAR() {}
ryood 0:2dcec10e9199 54
ryood 0:2dcec10e9199 55 void setAttack(int _attack) {
ryood 0:2dcec10e9199 56 attack = _attack;
ryood 0:2dcec10e9199 57 tau0 = attack * attackTauRatio;
ryood 0:2dcec10e9199 58 }
ryood 11:7e11404adca0 59 int getAttack() {
ryood 11:7e11404adca0 60 return attack;
ryood 11:7e11404adca0 61 }
ryood 0:2dcec10e9199 62
ryood 0:2dcec10e9199 63 void setRelease(int _release) {
ryood 0:2dcec10e9199 64 release = _release;
ryood 0:2dcec10e9199 65 tau1 = release * releaseTauRatio;
ryood 0:2dcec10e9199 66 }
ryood 11:7e11404adca0 67 int getRelease() {
ryood 11:7e11404adca0 68 return release;
ryood 11:7e11404adca0 69 }
ryood 0:2dcec10e9199 70
ryood 5:846772a77d33 71 void setAttackTauRatio(float _attackTauRatio) {
ryood 5:846772a77d33 72 attackTauRatio = _attackTauRatio;
ryood 5:846772a77d33 73 tau0 = attack * attackTauRatio;
ryood 5:846772a77d33 74 }
ryood 11:7e11404adca0 75 float getAttackTauRatio() {
ryood 11:7e11404adca0 76 return attackTauRatio;
ryood 11:7e11404adca0 77 }
ryood 0:2dcec10e9199 78
ryood 11:7e11404adca0 79 void setReleaseTauRatio(float _releaseTauRatio) {
ryood 5:846772a77d33 80 releaseTauRatio = _releaseTauRatio;
ryood 5:846772a77d33 81 tau1 = release * releaseTauRatio;
ryood 5:846772a77d33 82 }
ryood 11:7e11404adca0 83 float getReleaseTauRatio() {
ryood 11:7e11404adca0 84 return releaseTauRatio;
ryood 11:7e11404adca0 85 }
ryood 11:7e11404adca0 86
ryood 11:7e11404adca0 87 float getTau0() {
ryood 11:7e11404adca0 88 return tau0;
ryood 11:7e11404adca0 89 }
ryood 11:7e11404adca0 90 float getTau1() {
ryood 11:7e11404adca0 91 return tau1;
ryood 11:7e11404adca0 92 }
ryood 0:2dcec10e9199 93
ryood 11:7e11404adca0 94 void setV0(float _v0) {
ryood 11:7e11404adca0 95 v0 = _v0;
ryood 11:7e11404adca0 96 }
ryood 11:7e11404adca0 97 float getV0() {
ryood 11:7e11404adca0 98 return v0;
ryood 11:7e11404adca0 99 }
ryood 11:7e11404adca0 100 void setV1(float _v1) {
ryood 11:7e11404adca0 101 v1 = _v1;
ryood 11:7e11404adca0 102 }
ryood 11:7e11404adca0 103 float getV1() {
ryood 11:7e11404adca0 104 return v1;
ryood 11:7e11404adca0 105 }
ryood 11:7e11404adca0 106 void setV2(float _v2) {
ryood 11:7e11404adca0 107 v2 = _v2;
ryood 11:7e11404adca0 108 }
ryood 11:7e11404adca0 109 float getV2() {
ryood 11:7e11404adca0 110 return v2;
ryood 11:7e11404adca0 111 }
ryood 0:2dcec10e9199 112
ryood 11:7e11404adca0 113 float getAmplitude() {
ryood 11:7e11404adca0 114 return amplitude;
ryood 11:7e11404adca0 115 }
ryood 0:2dcec10e9199 116 float getAmplitude(int tick) {
ryood 0:2dcec10e9199 117 if (tick < attack) {
ryood 0:2dcec10e9199 118 // attackの処理
ryood 0:2dcec10e9199 119 amplitude = v0 + (v1 - v0) * (1 - expf(-(float)tick / tau0));
ryood 0:2dcec10e9199 120 vLast = amplitude;
ryood 11:7e11404adca0 121 } else {
ryood 0:2dcec10e9199 122 // releaseの処理
ryood 0:2dcec10e9199 123 amplitude = (vLast - v2) * (expf(-(float)(tick - attack) / tau1)) + v2;
ryood 0:2dcec10e9199 124 }
ryood 0:2dcec10e9199 125 return amplitude;
ryood 0:2dcec10e9199 126 }
ryood 0:2dcec10e9199 127
ryood 0:2dcec10e9199 128 private:
ryood 0:2dcec10e9199 129 int attack;
ryood 0:2dcec10e9199 130 int release;
ryood 0:2dcec10e9199 131 float amplitude;
ryood 0:2dcec10e9199 132 float v0;
ryood 0:2dcec10e9199 133 float v1;
ryood 0:2dcec10e9199 134 float v2;
ryood 0:2dcec10e9199 135 float vLast;
ryood 0:2dcec10e9199 136 float tau0;
ryood 0:2dcec10e9199 137 float tau1;
ryood 0:2dcec10e9199 138 float attackTauRatio;
ryood 0:2dcec10e9199 139 float releaseTauRatio;
ryood 0:2dcec10e9199 140 };
ryood 0:2dcec10e9199 141
ryood 11:7e11404adca0 142 class EnvelopeParam
ryood 11:7e11404adca0 143 {
ryood 5:846772a77d33 144 public:
ryood 5:846772a77d33 145 int attack;
ryood 5:846772a77d33 146 int release;
ryood 5:846772a77d33 147 float v0;
ryood 5:846772a77d33 148 float v1;
ryood 5:846772a77d33 149 float v2;
ryood 5:846772a77d33 150 float attackTauRatio;
ryood 5:846772a77d33 151 float releaseTauRatio;
ryood 5:846772a77d33 152 };
ryood 11:7e11404adca0 153
ryood 9:d1e6eae9722b 154 EnvelopeAR envelopeFrequency(5, 300, 880.0f, 120.0f, 40.0f, 0.36f, 0.1f);
ryood 5:846772a77d33 155 EnvelopeAR envelopeAmplitude(50, 200, 0.99f, 1.0f, 0.0f);
ryood 5:846772a77d33 156
ryood 5:846772a77d33 157 volatile EnvelopeParam frequencyParam;
ryood 5:846772a77d33 158 volatile EnvelopeParam amplitudeParam;
ryood 0:2dcec10e9199 159
ryood 3:f89b400cfe57 160 volatile int ticks;
ryood 3:f89b400cfe57 161 volatile int envelopeTicks;
ryood 3:f89b400cfe57 162 volatile float frequency;
ryood 3:f89b400cfe57 163 volatile float phi;
ryood 3:f89b400cfe57 164 volatile float phiDelta;
ryood 3:f89b400cfe57 165 volatile float amplitude;
ryood 3:f89b400cfe57 166
ryood 5:846772a77d33 167 volatile float bpm;
ryood 5:846772a77d33 168 volatile int envelopeLength;
ryood 14:8e96f97e261b 169 volatile int stepLength;
ryood 0:2dcec10e9199 170
ryood 0:2dcec10e9199 171 void generateWave()
ryood 0:2dcec10e9199 172 {
ryood 0:2dcec10e9199 173 phi += phiDelta;
ryood 0:2dcec10e9199 174 if (phi >= 1.0f) {
ryood 0:2dcec10e9199 175 phi -= 2.0f;
ryood 0:2dcec10e9199 176 }
ryood 10:79134dbb339d 177 float level = cosf(PI_F * phi) * amplitude;
ryood 1:f9b967ae26e4 178
ryood 3:f89b400cfe57 179 Dac1.write((level * 0.7f + 1.0f) / 2.0f);
ryood 0:2dcec10e9199 180 }
ryood 0:2dcec10e9199 181
ryood 0:2dcec10e9199 182 void generateEnvelope()
ryood 0:2dcec10e9199 183 {
ryood 0:2dcec10e9199 184 // Frequency Envelope
ryood 0:2dcec10e9199 185 frequency = envelopeFrequency.getAmplitude(envelopeTicks);
ryood 0:2dcec10e9199 186 phiDelta = 2.0f * frequency / SAMPLING_RATE;
ryood 0:2dcec10e9199 187
ryood 0:2dcec10e9199 188 // Amplitude Envelope
ryood 0:2dcec10e9199 189 amplitude = envelopeAmplitude.getAmplitude(envelopeTicks);
ryood 0:2dcec10e9199 190
ryood 0:2dcec10e9199 191 envelopeTicks++;
ryood 7:6735a343780e 192 if (envelopeTicks >= envelopeLength) {
ryood 0:2dcec10e9199 193 envelopeTicks = 0;
ryood 12:5b498285d121 194 phi = PI_F / 2.0f;
ryood 0:2dcec10e9199 195 }
ryood 0:2dcec10e9199 196 }
ryood 0:2dcec10e9199 197
ryood 2:8dff77a1ee4d 198 void update()
ryood 2:8dff77a1ee4d 199 {
ryood 12:5b498285d121 200 #if (PIN_CHECK)
ryood 12:5b498285d121 201 Dout0 = 1;
ryood 12:5b498285d121 202 #endif
ryood 14:8e96f97e261b 203
ryood 14:8e96f97e261b 204 // Output Sync Signal per steps
ryood 14:8e96f97e261b 205 if (envelopeTicks % stepLength == 0) {
ryood 14:8e96f97e261b 206 SyncPin = 1;
ryood 14:8e96f97e261b 207 }
ryood 14:8e96f97e261b 208
ryood 3:f89b400cfe57 209 ticks++;
ryood 12:5b498285d121 210 if (ticks >= SAMPLING_RATE / ENVELOPE_UPDATE_RATE) {
ryood 12:5b498285d121 211 #if (PIN_CHECK)
ryood 12:5b498285d121 212 Dout1 = 1;
ryood 12:5b498285d121 213 #endif
ryood 3:f89b400cfe57 214 ticks = 0;
ryood 11:7e11404adca0 215
ryood 5:846772a77d33 216 // set envelope parameters
ryood 5:846772a77d33 217 envelopeAmplitude.setAttack(amplitudeParam.attack);
ryood 5:846772a77d33 218 envelopeAmplitude.setRelease(amplitudeParam.release);
ryood 5:846772a77d33 219 envelopeAmplitude.setV0(amplitudeParam.v0);
ryood 5:846772a77d33 220 envelopeAmplitude.setV1(amplitudeParam.v1);
ryood 5:846772a77d33 221 envelopeAmplitude.setV2(amplitudeParam.v2);
ryood 5:846772a77d33 222 envelopeAmplitude.setAttackTauRatio(amplitudeParam.attackTauRatio);
ryood 5:846772a77d33 223 envelopeAmplitude.setReleaseTauRatio(amplitudeParam.releaseTauRatio);
ryood 11:7e11404adca0 224
ryood 6:897d6392b408 225 envelopeFrequency.setAttack(frequencyParam.attack);
ryood 6:897d6392b408 226 envelopeFrequency.setRelease(frequencyParam.release);
ryood 5:846772a77d33 227 envelopeFrequency.setV0(frequencyParam.v0);
ryood 6:897d6392b408 228 envelopeFrequency.setV1(frequencyParam.v1);
ryood 6:897d6392b408 229 envelopeFrequency.setV2(frequencyParam.v2);
ryood 6:897d6392b408 230 envelopeFrequency.setAttackTauRatio(frequencyParam.attackTauRatio);
ryood 6:897d6392b408 231 envelopeFrequency.setReleaseTauRatio(frequencyParam.releaseTauRatio);
ryood 11:7e11404adca0 232
ryood 2:8dff77a1ee4d 233 generateEnvelope();
ryood 12:5b498285d121 234 #if (PIN_CHECK)
ryood 12:5b498285d121 235 Dout1 = 0;
ryood 12:5b498285d121 236 #endif
ryood 2:8dff77a1ee4d 237 }
ryood 2:8dff77a1ee4d 238 generateWave();
ryood 14:8e96f97e261b 239
ryood 14:8e96f97e261b 240 // Output SyncSignal
ryood 14:8e96f97e261b 241 SyncPin = 0;
ryood 14:8e96f97e261b 242
ryood 12:5b498285d121 243 #if (PIN_CHECK)
ryood 12:5b498285d121 244 Dout0 = 0;
ryood 12:5b498285d121 245 #endif
ryood 2:8dff77a1ee4d 246 }
ryood 2:8dff77a1ee4d 247
ryood 5:846772a77d33 248 void setParams()
ryood 5:846772a77d33 249 {
ryood 13:43a43da257e3 250 bpm = Adc0.read_input(7) * 180.0f + 60.0f;
ryood 12:5b498285d121 251 envelopeLength = 60 * ENVELOPE_UPDATE_RATE / bpm;
ryood 14:8e96f97e261b 252 stepLength = envelopeLength / 4;
ryood 11:7e11404adca0 253
ryood 13:43a43da257e3 254 amplitudeParam.attack = Adc0.read_input(0) * envelopeLength;
ryood 13:43a43da257e3 255 amplitudeParam.release = Adc0.read_input(1) * envelopeLength;
ryood 13:43a43da257e3 256 amplitudeParam.v0 = Adc0.read_input(4);
ryood 14:8e96f97e261b 257 amplitudeParam.v1 = Adc0.read_input(5);
ryood 14:8e96f97e261b 258 amplitudeParam.v2 = Adc0.read_input(6);
ryood 5:846772a77d33 259 amplitudeParam.attackTauRatio = 0.36f;
ryood 13:43a43da257e3 260 amplitudeParam.releaseTauRatio = Adc0.read_input(3) + 0.01f;
ryood 11:7e11404adca0 261
ryood 13:43a43da257e3 262 frequencyParam.attack = Adc1.read_input(0) * envelopeLength * 0.1f;
ryood 13:43a43da257e3 263 frequencyParam.release = Adc1.read_input(1) * envelopeLength + 1;
ryood 13:43a43da257e3 264 frequencyParam.v0 = Adc1.read_input(4) * 4000.0f;
ryood 13:43a43da257e3 265 frequencyParam.v1 = Adc1.read_input(5) * 400.0f;
ryood 13:43a43da257e3 266 frequencyParam.v2 = Adc1.read_input(6) * 400.0f;
ryood 13:43a43da257e3 267 frequencyParam.attackTauRatio = Adc1.read_input(2) + 0.01f;
ryood 13:43a43da257e3 268 frequencyParam.releaseTauRatio = Adc1.read_input(3) + 0.01f;
ryood 5:846772a77d33 269 }
ryood 5:846772a77d33 270
ryood 0:2dcec10e9199 271 int main()
ryood 0:2dcec10e9199 272 {
ryood 0:2dcec10e9199 273 printf("%s %s\r\n", TITLE_STR1, TITLE_STR2);
ryood 13:43a43da257e3 274
ryood 0:2dcec10e9199 275 frequency = 1000.0f;
ryood 0:2dcec10e9199 276 phiDelta = 2.0f * frequency / SAMPLING_RATE;
ryood 0:2dcec10e9199 277 amplitude = 1.0f;
ryood 11:7e11404adca0 278
ryood 3:f89b400cfe57 279 ticks = 0;
ryood 2:8dff77a1ee4d 280 envelopeTicks = 0;
ryood 11:7e11404adca0 281
ryood 5:846772a77d33 282 bpm = 120.0f;
ryood 5:846772a77d33 283 setParams();
ryood 5:846772a77d33 284
ryood 2:8dff77a1ee4d 285 Ticker samplingTicker;
ryood 2:8dff77a1ee4d 286 samplingTicker.attach(&update, SAMPLING_PERIOD);
ryood 11:7e11404adca0 287
ryood 3:f89b400cfe57 288 for (;;) {
ryood 13:43a43da257e3 289 #if (PIN_CHECK)
ryood 13:43a43da257e3 290 Dout2 = 1;
ryood 13:43a43da257e3 291 #endif
ryood 5:846772a77d33 292 setParams();
ryood 13:43a43da257e3 293 #if (PIN_CHECK)
ryood 13:43a43da257e3 294 Dout2 = 0;
ryood 13:43a43da257e3 295 #endif
ryood 11:7e11404adca0 296
ryood 11:7e11404adca0 297 #if UART_TRACE
ryood 6:897d6392b408 298 printf("%.1f\t%d\t", bpm, envelopeLength);
ryood 11:7e11404adca0 299
ryood 6:897d6392b408 300 printf("%d\t%d\t", amplitudeParam.attack, amplitudeParam.release);
ryood 6:897d6392b408 301 printf("%.2f\t%.2f\t%.2f\t", amplitudeParam.v0, amplitudeParam.v1, amplitudeParam.v2);
ryood 6:897d6392b408 302 printf("%.2f\t%.2f\t", amplitudeParam.attackTauRatio, amplitudeParam.releaseTauRatio);
ryood 6:897d6392b408 303
ryood 6:897d6392b408 304 printf("%d\t%d\t", frequencyParam.attack, frequencyParam.release);
ryood 6:897d6392b408 305 printf("%.2f\t%.2f\t%.2f\t", frequencyParam.v0, frequencyParam.v1, frequencyParam.v2);
ryood 6:897d6392b408 306 printf("%.2f\t%.2f\r\n", frequencyParam.attackTauRatio, frequencyParam.releaseTauRatio);
ryood 11:7e11404adca0 307 #endif
ryood 11:7e11404adca0 308
ryood 13:43a43da257e3 309 Thread::wait(1);
ryood 3:f89b400cfe57 310 }
ryood 0:2dcec10e9199 311 }