Nucleo Sequencer of my Base Machine

Dependencies:   Amp AverageAnalogIn Envelope FilterController Sequence BaseMachineComon mbed-rtos mbed

Fork of SpiSequenceSender_Test by Ryo Od

main.cpp

Committer:
ryood
Date:
2016-10-25
Revision:
44:c9c54537a623
Parent:
43:9039cfc027bc

File content as of revision 44:c9c54537a623:

/*
 * main.cpp
 * SpiSequencerSender_test
 *
 * 2016.10.10 UIを分離
 * 2016.08.20 mbed Rev 121 / mbed-rtos Rev 117で動作確認
 *
 */

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

#define UART_TRACE  (0)
#include "BaseMachineCommon.h"
#include "SpiSequenceSender.h"
#include "EnvelopeGenerator.h"
#include "SpiAmpController.h"
#include "SpiFilterController.h"

#define TITLE_STR1  ("BaseMachine Sequencer")
#define TITLE_STR2  ("20161025")

#define SPI1_RATE   (3000000)   // Actual frequency about 2.6MHz

const int samplingPeriod = 1;   // ms
const int bpm = 120;
const int envelopeLength = (60 * 1000 / (bpm * 4)) / samplingPeriod;
const int waveShape = SpiSequenceSender::WAVESHAPE_SQUARE;

// Devices
//
//SPI1 (PinName mosi, PinName miso, PinName sclk, PinName ssel=NC)
SPI SpiMaster(PA_7, PA_6, PA_5);

//SPI2 (PinName mosi, PinName miso, PinName sclk, PinName ssel)
SPISlave SpiSlave(PB_15, PB_14, PB_13, PB_12);
DigitalOut StepChangePin(PB_1);

BusOut Leds(PA_0, PA_1, PA_4, PB_0, PC_1, PC_0, PA_10, PB_3);

// Grobal Variables
//
Sequence sequences[SEQUENCE_N];
SpiSequenceSender sequenceSender(&SpiMaster, D9, sequences, SEQUENCE_N, samplingPeriod, bpm);

Envelope envelope(4095, envelopeLength, envelopeLength*3/4, envelopeLength/2, 2047);
EnvelopeGenerator envelopeGenerator;
SpiAmpController ampController(&SpiMaster, D8, D7);

SpiFilterController filterController(&SpiMaster, D10);

int playingStep = 0;
int editingStep = 0;
bool isRunning = false;

//------------------------------------------------------------------------
// Callback functions
//------------------------------------------------------------------------
void updateTicks(int ticks)
{
    if (ticks == 0) {
        envelopeGenerator.init(envelope);
        playingStep = sequenceSender.getStep();
        // Masterにinterruptをかける。
        StepChangePin.write(1);
        wait_us(1);
        StepChangePin.write(0);
    }

    if (sequences[sequenceSender.getStep()].isNoteOn()) {
        uint16_t level = envelopeGenerator.getModLevel();
        if (!sequences[sequenceSender.getStep()].isAccent()) {
            level = level * 1 / 2;
        }
        ampController.outDca(level);
    } else {
        ampController.outDca(0);
    }
    envelopeGenerator.update();
    
    filterController.outDcf();
}

//------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------

void spiSlaveRecieve()
{
    if (SpiSlave.receive()) {
        SpiSlave.reply(playingStep);
        uint16_t recievedVal = SpiSlave.read();
        uint8_t cmd  = recievedVal >> 8;
        uint8_t data = recievedVal & 0xff;
        
        if (cmd != CMD_RCV_PLAYING_STEP) {
            Leds.write(cmd);
        }
        
        switch(cmd) {
        case CMD_RCV_PLAYING_STEP:
            // Do nothing
            break;
        case CMD_RUN:
            if (data == 0) {
                ampController.outDca(0);
                sequenceSender.stop();
                isRunning = false;
            }
            else {
                sequenceSender.run(playingStep);
                isRunning = true;
            }
            break;
        case CMD_BPM:
            sequenceSender.setBpm(data);
            break;
        case CMD_ACCENT_LEVEL:
            // ToDo: Impl. accentLevel
            break;
        case CMD_WAVE_SHAPE:
            sequenceSender.setWaveShape(data);   
            break;
        case CMD_PULSE_WIDTH:
            sequenceSender.setPulseWidth(data << 1);
            break;
        case CMD_CUTOFF:
            filterController.setCutoff(data << 1);
            break;
        case CMD_RESONANCE:
            filterController.setResonance(data << 1);
            break;
        case CMD_LEVEL:
            envelope.setLevel(data << 5);
            break;
        case CMD_DURATION:
            envelope.setDuration((float)data / 128.0f * envelopeLength);
            break;
        case CMD_DECAY:
            envelope.setDecay((float)data / 128.0f * envelopeLength);
            break;
        case CMD_SUSTAIN:
            envelope.setSustain(data << 5);
            break;
        case CMD_NOTE:
            editingStep = data >> 4;
            sequences[editingStep].setNoteOn(data & 0x01);
            sequences[editingStep].setTie((data & 0x02) >> 1);
            sequences[editingStep].setAccent((data & 0x04) >> 2);
            break;
        case CMD_PITCH:
            sequences[editingStep].setPitch(data);
            break;
        /*
        default:
            Leds.write(cmd);
            error("invalid SPI cmd");
        */
        }
    }
}

//------------------------------------------------------------------------
// Main routine
//------------------------------------------------------------------------
int main()
{
    #if (UART_TRACE)
    printf("*** BaseMachine Sequencer ***\r\n");
    #endif
    
    // Check LED
    for (int i = 0; i < 8; i++) {
        Leds[i].write(1);
        Thread::wait(50);
    }
    Thread::wait(50);
    Leds.write(0x00);
    
    //--------------------------------------------------------------------
    // Setup Devices
    //
    SpiMaster.format(8, 0);
    SpiMaster.frequency(SPI1_RATE);
    
    SpiSlave.format(16, 0);
    SpiSlave.frequency(SPI_UI_TO_SEQUENCER_RATE);
    
    // Mute output
    ampController.outDca(0);
    
    //--------------------------------------------------------------------
    // Initialize objects
    //
    Sequence::setBaseNoteNumber(baseNoteNumber);
    
    for (int i = 0; i < SEQUENCE_N; i++) {
        Sequence& seq = sequenceSender.getSequences()[i];
        seq.setPitch(pitch[i]);
        seq.setNoteOn(noteOn[i]);
        seq.setTie(tie[i]);
        seq.setAccent(accent[i]);
    }
    
    envelopeGenerator.init(envelope);

    sequenceSender.attachUpdate(&updateTicks);
    sequenceSender.setWaveShape(waveShape);
    
    //--------------------------------------------------------------------
    // Main loop
    //
    for (;;) {
        spiSlaveRecieve();
    }
 
}