KIK 01 Prototype 05

Dependencies:   AverageMCP3008 mbed-rtos mbed mcp3008

Fork of KIK01_Proto03 by Ryo Od

Committer:
ryood
Date:
Sat Sep 16 00:10:18 2017 +0000
Revision:
20:70a05941db8c
Parent:
19:d9e4c66cb49b
Child:
21:a527f51381d6
constrain the value of R

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