KIK 01 Prototype 05

Dependencies:   AverageMCP3008 mbed-rtos mbed mcp3008

Fork of KIK01_Proto03 by Ryo Od

Committer:
ryood
Date:
Thu Jul 06 05:15:17 2017 +0000
Revision:
15:8f674acdac03
Parent:
14:8e96f97e261b
Child:
16:30cb822e072f
1 SPI bus

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