KIK 01 Prototype 05

Dependencies:   AverageMCP3008 mbed-rtos mbed mcp3008

Fork of KIK01_Proto03 by Ryo Od

main.cpp

Committer:
ryood
Date:
2017-07-06
Revision:
15:8f674acdac03
Parent:
14:8e96f97e261b
Child:
16:30cb822e072f

File content as of revision 15:8f674acdac03:

/*
 * KIK01
 * Kick Machine
 *
 * 2017.07.04 Proto03: MCP4922 DCA
 * 2017.06.19 Proto02
 * 2017.06.04 created.
 *
 */

#include "mbed.h"
#include "rtos.h"
#include "mcp3008.h"

#include "SpiAmpController.h"

#define UART_TRACE      (0)
#define PIN_CHECK       (1)
#define TITLE_STR1      ("KIK01 Kick Machine")
#define TITLE_STR2      ("20170704")

#define PI_F            (3.1415926f)
#define SAMPLING_RATE   (16000)
#define SAMPLING_PERIOD (1.0f/SAMPLING_RATE)
#define ENVELOPE_UPDATE_RATE    SAMPLING_RATE

#define AMP_VREF    0x0fff

AnalogOut Dac1(PA_4);

SPI SpiM(SPI_MOSI, SPI_MISO, SPI_SCK);
MCP3008 Adc0(&SpiM, D10);
MCP3008 Adc1(&SpiM, D9);

SpiAmpController ampController(&SpiM, D8, D7);

// Check pins
DigitalOut Dout0(D2);
DigitalOut Dout1(D3);
DigitalOut Dout2(D4);

// Sync
DigitalOut SyncPin(D7);

class EnvelopeAR
{
public:
    EnvelopeAR(int _attack, int _release, float _v0, float _v1, float _v2, float _attackTauRatio=0.36f, float _releaseTauRatio=0.36f) :
        amplitude(_v0),
        v0(_v0),
        v1(_v1),
        v2(_v2),
        vLast(_v0),
        attackTauRatio(_attackTauRatio),
        releaseTauRatio(_releaseTauRatio) {
        setAttack(_attack);
        setRelease(_release);
    }

    ~EnvelopeAR() {}

    void setAttack(int _attack) {
        attack = _attack;
        tau0 = attack * attackTauRatio;
    }
    int getAttack() {
        return attack;
    }

    void setRelease(int _release) {
        release = _release;
        tau1 = release * releaseTauRatio;
    }
    int getRelease() {
        return release;
    }

    void setAttackTauRatio(float _attackTauRatio) {
        attackTauRatio = _attackTauRatio;
        tau0 = attack * attackTauRatio;
    }
    float getAttackTauRatio() {
        return attackTauRatio;
    }

    void setReleaseTauRatio(float _releaseTauRatio) {
        releaseTauRatio = _releaseTauRatio;
        tau1 = release * releaseTauRatio;
    }
    float getReleaseTauRatio() {
        return releaseTauRatio;
    }

    float getTau0() {
        return tau0;
    }
    float getTau1() {
        return tau1;
    }

    void setV0(float _v0) {
        v0 = _v0;
    }
    float getV0() {
        return v0;
    }
    void setV1(float _v1) {
        v1 = _v1;
    }
    float getV1() {
        return v1;
    }
    void setV2(float _v2) {
        v2 = _v2;
    }
    float getV2() {
        return v2;
    }

    float getAmplitude() {
        return amplitude;
    }
    float getAmplitude(int tick) {
        if (tick < attack) {
            // attackの処理
            amplitude = v0 + (v1 - v0) * (1 - expf(-(float)tick / tau0));
            vLast = amplitude;
        } else {
            // releaseの処理
            amplitude = (vLast - v2) * (expf(-(float)(tick - attack) / tau1)) + v2;
        }
        return amplitude;
    }

private:
    int attack;
    int release;
    float amplitude;
    float v0;
    float v1;
    float v2;
    float vLast;
    float tau0;
    float tau1;
    float attackTauRatio;
    float releaseTauRatio;
};

class EnvelopeParam
{
public:
    int attack;
    int release;
    float v0;
    float v1;
    float v2;
    float attackTauRatio;
    float releaseTauRatio;
};

EnvelopeAR envelopeFrequency(5, 300, 880.0f, 120.0f, 40.0f, 0.36f, 0.1f);
EnvelopeAR envelopeAmplitude(50, 200, 0.99f, 1.0f, 0.0f);

volatile EnvelopeParam frequencyParam;
volatile EnvelopeParam amplitudeParam;

volatile int ticks;
volatile int envelopeTicks;
volatile float frequency;
volatile float phi;
volatile float phiDelta;
volatile float amplitude;

volatile float bpm;
volatile int envelopeLength;
volatile int stepLength;

//-----------------------------------------------------------------------------//
// Internal DCA
//
void generateWave_DcaInternal()
{
    phi += phiDelta;
    if (phi >= 1.0f) {
        phi -= 2.0f;
    }
    float level = cosf(PI_F * phi) * amplitude;

    Dac1.write((level * 0.7f + 1.0f) / 2.0f);
}

void generateEnvelope_DcaInternal()
{
    // Frequency Envelope
    frequency = envelopeFrequency.getAmplitude(envelopeTicks);
    phiDelta = 2.0f * frequency / SAMPLING_RATE;

    // Amplitude Envelope
    amplitude = envelopeAmplitude.getAmplitude(envelopeTicks);

    envelopeTicks++;
    if (envelopeTicks >= envelopeLength) {
        envelopeTicks = 0;
        phi = PI_F / 2.0f;
    }
}

//-----------------------------------------------------------------------------//
// External DCA
//
void generateWave_DcaExternal()
{
    phi += phiDelta;
    if (phi >= 1.0f) {
        phi -= 2.0f;
    }
    //float level = cosf(PI_F * phi) * amplitude;
    float level = cosf(PI_F * phi);

    Dac1.write((level * 0.7f + 1.0f) / 2.0f);
}

void generateEnvelope_DcaExternal()
{
    // Frequency Envelope
    frequency = envelopeFrequency.getAmplitude(envelopeTicks);
    phiDelta = 2.0f * frequency / SAMPLING_RATE;

    // Amplitude Envelope
    amplitude = envelopeAmplitude.getAmplitude(envelopeTicks);

    SpiM.lock();
    SpiM.frequency(16000000);
    ampController.outDca(amplitude * 4096);
    SpiM.frequency(2000000);
    SpiM.unlock();

    envelopeTicks++;
    if (envelopeTicks >= envelopeLength) {
        envelopeTicks = 0;
        phi = PI_F / 2.0f;
    }
}

void update()
{
#if (PIN_CHECK)
    Dout0 = 1;
#endif

    // Output Sync Signal per steps
    if (envelopeTicks % stepLength == 0) {
        SyncPin = 1;
    }

    ticks++;
    if (ticks >= SAMPLING_RATE / ENVELOPE_UPDATE_RATE) {
#if (PIN_CHECK)
        Dout1 = 1;
#endif
        ticks = 0;

        // set envelope parameters
        envelopeAmplitude.setAttack(amplitudeParam.attack);
        envelopeAmplitude.setRelease(amplitudeParam.release);
        envelopeAmplitude.setV0(amplitudeParam.v0);
        envelopeAmplitude.setV1(amplitudeParam.v1);
        envelopeAmplitude.setV2(amplitudeParam.v2);
        envelopeAmplitude.setAttackTauRatio(amplitudeParam.attackTauRatio);
        envelopeAmplitude.setReleaseTauRatio(amplitudeParam.releaseTauRatio);

        envelopeFrequency.setAttack(frequencyParam.attack);
        envelopeFrequency.setRelease(frequencyParam.release);
        envelopeFrequency.setV0(frequencyParam.v0);
        envelopeFrequency.setV1(frequencyParam.v1);
        envelopeFrequency.setV2(frequencyParam.v2);
        envelopeFrequency.setAttackTauRatio(frequencyParam.attackTauRatio);
        envelopeFrequency.setReleaseTauRatio(frequencyParam.releaseTauRatio);

        generateEnvelope_DcaExternal();
#if (PIN_CHECK)
        Dout1 = 0;
#endif
    }
    generateWave_DcaExternal();

    // Output SyncSignal
    SyncPin = 0;

#if (PIN_CHECK)
    Dout0 = 0;
#endif
}

void setParams()
{
    bpm = Adc0.read_input(7) * 180.0f + 60.0f;
    envelopeLength = 60 * ENVELOPE_UPDATE_RATE / bpm;
    stepLength = envelopeLength / 4;

    amplitudeParam.attack = Adc0.read_input(0) * envelopeLength;
    amplitudeParam.release = Adc0.read_input(1) * envelopeLength;
    amplitudeParam.v0 = Adc0.read_input(4);
    amplitudeParam.v1 = Adc0.read_input(5);
    amplitudeParam.v2 = Adc0.read_input(6);
    amplitudeParam.attackTauRatio = 0.36f;
    amplitudeParam.releaseTauRatio = Adc0.read_input(3) + 0.01f;

    frequencyParam.attack = Adc1.read_input(0) * envelopeLength * 0.1f;
    frequencyParam.release = Adc1.read_input(1) * envelopeLength + 1;
    frequencyParam.v0 = Adc1.read_input(4) * 4000.0f;
    frequencyParam.v1 = Adc1.read_input(5) * 400.0f;
    frequencyParam.v2 = Adc1.read_input(6) * 400.0f;
    frequencyParam.attackTauRatio = Adc1.read_input(2) + 0.01f;
    frequencyParam.releaseTauRatio = Adc1.read_input(3) + 0.01f;
}

int main()
{
    printf("%s %s\r\n", TITLE_STR1, TITLE_STR2);

    SpiM.format(0, 0);
    SpiM.frequency(2000000);

    frequency = 1000.0f;
    phiDelta = 2.0f * frequency / SAMPLING_RATE;
    amplitude = 1.0f;

    ticks = 0;
    envelopeTicks = 0;

    bpm = 120.0f;
    setParams();

    Ticker samplingTicker;
    samplingTicker.attach(&update, SAMPLING_PERIOD);

    for (;;) {
#if (PIN_CHECK)
        Dout2 = 1;
#endif
        setParams();
#if (PIN_CHECK)
        Dout2 = 0;
#endif

#if UART_TRACE
        printf("%.1f\t%d\t", bpm, envelopeLength);

        printf("%d\t%d\t", amplitudeParam.attack, amplitudeParam.release);
        printf("%.2f\t%.2f\t%.2f\t", amplitudeParam.v0, amplitudeParam.v1, amplitudeParam.v2);
        printf("%.2f\t%.2f\t", amplitudeParam.attackTauRatio, amplitudeParam.releaseTauRatio);

        printf("%d\t%d\t", frequencyParam.attack, frequencyParam.release);
        printf("%.2f\t%.2f\t%.2f\t", frequencyParam.v0, frequencyParam.v1, frequencyParam.v2);
        printf("%.2f\t%.2f\r\n", frequencyParam.attackTauRatio, frequencyParam.releaseTauRatio);
#endif

        Thread::wait(1);
    }
}