KIK01 Proto 08

Dependencies:   AverageMCP3008 VoltageMonitor mbed-rtos mbed mcp3008

Fork of KIK01_Proto07 by Ryo Od

Committer:
ryood
Date:
Tue Jun 06 15:31:41 2017 +0000
Revision:
12:5b498285d121
Parent:
11:7e11404adca0
Child:
13:43a43da257e3
phase reset (cosf)

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