Nucleo Sequencer of my Base Machine
Dependencies: Amp AverageAnalogIn Envelope FilterController Sequence BaseMachineComon mbed-rtos mbed
Fork of SpiSequenceSender_Test by
main.cpp
- Committer:
- ryood
- Date:
- 2016-09-08
- Revision:
- 34:602ee5e771e3
- Parent:
- 33:a24a4c435973
- Child:
- 35:0165b610796d
File content as of revision 34:602ee5e771e3:
/* * main.cpp * SpiSequencerSender_test * * 2016.08.20 mbed Rev 121 / mbed-rtos Rev 117で動作確認 * */ #include "mbed.h" #include "rtos.h" #include "st7565LCD.h" #include "PinDetect.h" #include "RotaryEncoder.h" #include "AverageAnalogIn.h" #define UART_TRACE (0) #include "SpiSequenceSender.h" #include "EnvelopeGenerator.h" #include "SpiAmpController.h" #include "SpiFilterController.h" #include "ST7565_SequencerDisplay.h" #define TITLE_STR1 ("BaseMachine Sequencer") #define TITLE_STR2 ("20160908") #define SEQUENCE_N (16) #define SPI_RATE (16000000) // Actual frequency about 5MHz const int samplingPeriod = 1; // ms const int bpm = 120; const int envelopeLength = (60 * 1000 / (bpm * 4)) / samplingPeriod; const int waveShape = SpiSequenceSender::WAVESHAPE_SQUARE; const int baseNoteNumber = 36; const int bpmMax = 240; const int bpmMin = 60; const int UImodeMax = 2; // Initial Sequence const int noteOn[SEQUENCE_N] = { 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 }; const int pitch[SEQUENCE_N] = {36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36 }; const int tie[SEQUENCE_N] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const int accent[SEQUENCE_N] = { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }; // Devices // //SPI (PinName mosi, PinName miso, PinName sclk, PinName ssel=NC) SPI spiMaster(PA_7, PA_6, PA_5); //ST7565(PinName mosi, PinName sclk, PinName cs, PinName rst, PinName a0); ST7565 gLCD(PB_15, PB_13, PB_12, PB_2, PB_1); AverageAnalogIn AinPulseWidth(PC_2); AverageAnalogIn AinCutOff(PB_0); AverageAnalogIn AinResonance(PC_1); AverageAnalogIn AinEnvMod(PC_3); AverageAnalogIn AinLevel(PC_0); AverageAnalogIn AinDuration(PA_4); AverageAnalogIn AinDecay(PA_1); AverageAnalogIn AinSustain(PA_0); RotaryEncoder RotEncStep(PB_9, PB_8, 0, SEQUENCE_N - 1, 0); RotaryEncoder RotEncPitch(PB_5, PB_4, 0, Sequence::getMaxPitch() - 1, 0); RotaryEncoder RotEncBpm(PC_12, PC_10, bpmMin, bpmMax, 120); PinDetect PinWaveShape(PD_2, PullUp); PinDetect PinUIMode(PC_11, PullUp); PinDetect PinOctaveUp(PB_3, PullUp); PinDetect PinOctaveDown(PA_10, PullUp); PinDetect PinNoteOnOff(PC_5, PullUp); PinDetect PinTie(PC_6, PullUp); PinDetect PinAccent(PC_8, PullUp); PinDetect PinRunStop(PC_9, PullUp); PwmOut LCDBackLight(PA_11); // 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); ST7565_SequencerDisplay sequencerDisplay(&gLCD, sequences, SEQUENCE_N); volatile int currentStep = 0; volatile bool isRunning = false; volatile bool isDirty = true; volatile uint8_t pinFlag = 0x00; volatile int UImode = 0; enum PinBit { bWaveShape = 0x01, bUIMode = 0x02, bOctaveUp = 0x04, bOctaveDown = 0x08, bNoteOnOff = 0x10, bTie = 0x20, bAccent = 0x40, bRunStop = 0x80 }; // とりあえずの変数(後でClassのメンバ変数に格納) volatile uint8_t envMod = 127; //------------------------------------------------------------------------ // Callback functions //------------------------------------------------------------------------ void updateFunction(int ticks) { if (ticks == 0) { envelopeGenerator.init(envelope); } if (sequences[sequenceSender.getStep()].isNoteOn()) { uint16_t level = envelopeGenerator.getModLevel(); if (!sequences[sequenceSender.getStep()].isAccent()) { level = level * 3 / 4; } ampController.outDca(level); } else { ampController.outDca(0); } envelopeGenerator.update(); filterController.outDcf(); // ToDo: 再生中のLCD表示を検討→SPI1とSPI2の信号のタイミングを調査 //sequencerDisplay.update(SequencerDisplay::run, sequenceSender.getStep()); } //------------------------------------------------------------------------ // PinDetect ISR //------------------------------------------------------------------------ void swWaveShapePressed() { pinFlag |= bWaveShape; } void swUIModePressed() { pinFlag |= bUIMode; } void swOctaveUpPressed() { pinFlag |= bOctaveUp; } void swOctaveDownPressed() { pinFlag |= bOctaveDown; } void swNoteOnOffPressed() { pinFlag |= bNoteOnOff; } void swTiePressed() { pinFlag |= bTie; } void swAccentPressed() { pinFlag |= bAccent; } void swRunStopPressed() { pinFlag |= bRunStop; } //------------------------------------------------------------------------ // Functions //------------------------------------------------------------------------ void pollingPots() { sequenceSender.setPulseWidth(AinPulseWidth.read_u16() >> 8); filterController.setCutoff(AinCutOff.read_u16() >> 8); filterController.setResonance(AinResonance.read_u16() >> 8); // テスト用にバックライトの調整に使用 LCDBackLight = AinEnvMod.read(); envelope.setLevel(AinLevel.read_u16() >> 4); envelope.setDuration(AinDuration.read() * envelopeLength); envelope.setDecay(AinDecay.read() * envelopeLength); envelope.setSustain(AinSustain.read() * 4095); } void pollingRotEncs() { int _bpm = RotEncBpm.getVal(); if (_bpm != sequenceSender.getBpm()) { sequenceSender.setBpm(_bpm); sequencerDisplay.setBpm(_bpm); isDirty = true; } int _step = RotEncStep.getVal(); if (_step != currentStep) { currentStep = _step; // syncronize sequence value & Rotary Encoder's value RotEncPitch.setVal(sequences[currentStep].getPitch()); isDirty = true; } int _pitch = RotEncPitch.getVal(); if (_pitch != sequences[currentStep].getPitch()) { sequences[currentStep].setPitch(_pitch); isDirty = true; } } void pollingPins() { if (pinFlag & bWaveShape) { #if (UART_TRACE) printf("PinWaveShape Pushed\r\n"); #endif uint8_t waveShape = sequenceSender.getWaveShape(); waveShape++; if (waveShape == SpiSequenceSender::WAVESHAPE_N) { waveShape = 0; } sequenceSender.setWaveShape(waveShape); sequencerDisplay.setWaveShape(waveShape); pinFlag &= ~bWaveShape; isDirty = true; } if (pinFlag & bUIMode) { #if (UART_TRACE) printf("PinUIMode Pushed\r\n"); #endif UImode++; if (UImode > UImodeMax) { UImode = 0; } pinFlag &= ~bUIMode; isDirty = true; } if (pinFlag & bOctaveUp) { #if (UART_TRACE) printf("PinOctaveUp Pushed\r\n"); #endif //sequences[currentStep].setOctave(sequences[currentStep].getOctave() + 1); sequencerDisplay.setOctave(sequencerDisplay.getOctave() + 1); pinFlag &= ~bOctaveUp; isDirty = true; } if (pinFlag & bOctaveDown) { #if (UART_TRACE) printf("PinOctaveDown Pushed\r\n"); #endif //sequences[currentStep].setOctave(sequences[currentStep].getOctave() - 1); sequencerDisplay.setOctave(sequencerDisplay.getOctave() - 1); pinFlag &= ~bOctaveDown; isDirty = true; } if (pinFlag & bNoteOnOff) { #if (UART_TRACE) printf("PinNoteOnOff Pushed\r\n"); #endif sequences[currentStep].setNoteOn(!sequences[currentStep].isNoteOn()); pinFlag &= ~bNoteOnOff; isDirty = true; } if (pinFlag & bTie) { #if (UART_TRACE) printf("PinTie Pushed\r\n"); #endif sequences[currentStep].setTie(!sequences[currentStep].isTie()); pinFlag &= ~bTie; isDirty = true; } if (pinFlag & bAccent) { #if (UART_TRACE) printf("PinAccent Pushed\r\n"); #endif sequences[currentStep].setAccent(!sequences[currentStep].isAccent()); pinFlag &= ~bAccent; isDirty = true; } if (pinFlag & bRunStop) { #if (UART_TRACE) printf("PinRunStop Pushed\r\n"); #endif if (isRunning) { ampController.outDca(0); sequenceSender.stop(); isRunning = false; } else { sequenceSender.run(currentStep); isRunning = true; } pinFlag &= ~bRunStop; isDirty = true; } } void dumpToLCD00() { char buff[64]; int col = 0; gLCD.clear(); sprintf(buff, "Run:%d BPM:%03d", isRunning, sequenceSender.getBpm()); gLCD.drawstring(0, col++, buff); sprintf(buff, "Stp:%02d Nto:%d Pch:%02d", currentStep, sequences[currentStep].isNoteOn(), sequences[currentStep].getPitch()); gLCD.drawstring(0, col++, buff); sprintf(buff, "Oct:%-2d Tie:%d Acc:%d", sequencerDisplay.getOctave(), sequences[currentStep].isTie(),sequences[currentStep].isAccent()); gLCD.drawstring(0, col++, buff); sprintf(buff, "Wsp:%d Mod:%d", sequenceSender.getWaveShape(), UImode); gLCD.drawstring(0, col++, buff); sprintf(buff, "PW :%4d CO :%4d", sequenceSender.getPulseWidth(), filterController.getCutoff()); gLCD.drawstring(0, col++, buff); sprintf(buff, "RSO:%4d ENV:%4d", filterController.getResonance(), envMod); gLCD.drawstring(0, col++, buff); sprintf(buff, "LVL:%4d DUR:%4d", envelope.getLevel(), envelope.getDuration()); gLCD.drawstring(0, col++, buff); sprintf(buff, "DCY:%4d SUS:%4d", envelope.getDecay(), envelope.getSustain()); gLCD.drawstring(0, col++, buff); gLCD.display(); } void dumpToLCD01() { char buff[64]; int col = 0; gLCD.clear(); sprintf(buff, "Cutoff %5d", AinCutOff.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "Duration %5d", AinDuration.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "Decay %5d", AinDecay.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "Sustain %5d", AinSustain.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "Resonance %5d", AinResonance.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "Level %5d", AinLevel.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "PulseWidth %5d", AinPulseWidth.read_u16() >> 8); gLCD.drawstring(0, col++, buff); sprintf(buff, "EnvMod %5d", AinEnvMod.read_u16() >> 8); gLCD.drawstring(0, col++, buff); gLCD.display(); } //------------------------------------------------------------------------ // Main routine //------------------------------------------------------------------------ int main() { #if (UART_TRACE) printf("*** BaseMachine Sequencer ***\r\n"); #endif //-------------------------------------------------------------------- // Setup Devices // spiMaster.format(8, 0); spiMaster.frequency(SPI_RATE); // Mute output ampController.outDca(0); LCDBackLight.period_ms(10); LCDBackLight = 0.6f; gLCD.set_spi_frequency(SPI_RATE); gLCD.begin(0x12); gLCD.clear(); gLCD.drawstring(0, 0, TITLE_STR1); gLCD.drawstring(0, 1, TITLE_STR2); gLCD.display(); Thread::wait(1000); RotEncStep.setInterval(100); RotEncPitch.setInterval(100); RotEncBpm.setInterval(100); PinWaveShape.attach_asserted(&swWaveShapePressed); PinWaveShape.setAssertValue(0); PinWaveShape.setSampleFrequency(); PinUIMode.attach_asserted(&swUIModePressed); PinUIMode.setAssertValue(0); PinUIMode.setSampleFrequency(); PinOctaveUp.attach_asserted(&swOctaveUpPressed); PinOctaveUp.setAssertValue(0); PinOctaveUp.setSampleFrequency(); PinOctaveDown.attach_asserted(&swOctaveDownPressed); PinOctaveDown.setAssertValue(0); PinOctaveDown.setSampleFrequency(); PinNoteOnOff.attach_asserted(&swNoteOnOffPressed); PinNoteOnOff.setAssertValue(0); PinNoteOnOff.setSampleFrequency(); PinTie.attach_asserted(&swTiePressed); PinTie.setAssertValue(0); PinTie.setSampleFrequency(); PinAccent.attach_asserted(&swAccentPressed); PinAccent.setAssertValue(0); PinAccent.setSampleFrequency(); PinRunStop.attach_asserted(&swRunStopPressed); PinRunStop.setAssertValue(0); PinRunStop.setSampleFrequency(); //-------------------------------------------------------------------- // 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]); } RotEncPitch.setVal(sequences[0].getPitch()); envelopeGenerator.init(envelope); sequenceSender.attachUpdate(&updateFunction); sequenceSender.setWaveShape(waveShape); //-------------------------------------------------------------------- // Main loop // for (;;) { pollingPots(); pollingRotEncs(); pollingPins(); if (!isRunning) { if (isDirty) { switch (UImode) { case 0: sequencerDisplay.update(SequencerDisplay::stop, currentStep); break; case 1: dumpToLCD00(); break; } isDirty = false; } if (UImode == 2) { dumpToLCD01(); } } else { if (isDirty) { //sequencerDisplay.update(SequencerDisplay::run, currentStep); static int cnt = 0; char buffer[32]; sprintf(buffer, "%d", cnt); cnt++; gLCD.clear(); gLCD.drawstring(0, 0, buffer); gLCD.display(); isDirty = false; } } } }