BaseMachine UI Controllerに分離
Dependencies: AverageAnalogIn PinDetect RotaryEncoder Sequence SequencerDisplay mbed-rtos mbed st7567LCD BaseMachineComon
Fork of BaseMachine_Sequencer by
main.cpp
- Committer:
- ryood
- Date:
- 2016-10-28
- Revision:
- 55:ab24d74eb0e6
- Parent:
- 54:38187ac44253
File content as of revision 55:ab24d74eb0e6:
/* * main.cpp * SpiSequencerSender_test * * 2016.10.02 UI Controllerに分割 * 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 "BaseMachineCommon.h" #include "Sequence.h" #include "ST7565_SequencerDisplay.h" #define TITLE_STR1 ("BaseMachine UI Controller") #define TITLE_STR2 ("20161028") #define SPI2_RATE (1000000) #define POT_RESOLUTION (7) // bit #define AIN_AVERAGE (16) // AnalogInを移動平均する要素数 #define POLLING_POTS_WAIT (20) // POT読み取りThreadのWait値(ミリ秒) const int bpmMax = 240; const int bpmMin = 60; const int octaveMax = 2; const int octaveMin = -2; const int waveShapeMax = 1; const int UImodeMax = 2; // Devices // //RESET Line //DigitalOut ResetLine(); //SPI (PinName mosi, PinName miso, PinName sclk, PinName ssel=NC) SPI SpiMaster(PA_7, PA_6, PA_5); DigitalOut SpiMasterCs(PB_6); InterruptIn StepChangeInterrupt(PC_7); DigitalOut SlaveReset(PB_9); //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, AIN_AVERAGE); AverageAnalogIn AinCutOff(PB_0, AIN_AVERAGE); AverageAnalogIn AinResonance(PC_1, AIN_AVERAGE); AverageAnalogIn AinLevel(PC_0, AIN_AVERAGE); AverageAnalogIn AinDuration(PA_4, AIN_AVERAGE); AverageAnalogIn AinDecay(PA_1, AIN_AVERAGE); AverageAnalogIn AinSustain(PA_0, AIN_AVERAGE); AverageAnalogIn AinAccentLevel(PC_3, AIN_AVERAGE); RotaryEncoder RotEncStep(PA_11, PA_12, 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); // Grobal Variables // Sequence sequences[SEQUENCE_N]; ST7565_SequencerDisplay sequencerDisplay(&gLCD, sequences, SEQUENCE_N); struct OscillatorParam { uint8_t waveShape; uint8_t pulseWidth; } oscillatorParam; struct FilterParam { uint8_t cutoff; uint8_t resonance; } filterParam; struct EnvelopeParam { uint8_t level; uint8_t length; uint8_t duration; uint8_t decay; uint8_t sustain; } envelopeParam; uint8_t bpm = 120; uint8_t accentLevel = 127; int currentStep = 0; int playingStep = 0; bool isRunning = false; bool isDirty = true; int UImode = 0; volatile bool isStepChanged = false; volatile uint8_t pinFlag = 0x00; enum PinBit { bWaveShape = 0x01, bUIMode = 0x02, bOctaveUp = 0x04, bOctaveDown = 0x08, bNoteOnOff = 0x10, bTie = 0x20, bAccent = 0x40, bRunStop = 0x80 }; //------------------------------------------------------------------------ // InterruptIn ISR //------------------------------------------------------------------------ void updateStep() { isStepChanged = true; } //------------------------------------------------------------------------ // 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 //------------------------------------------------------------------------ uint8_t getNoteData(uint8_t step) { uint8_t noteData = 0; noteData |= (step << 4); noteData |= (sequences[step].isAccent() ? 4 : 0); noteData |= (sequences[step].isTie() ? 2 : 0); noteData |= (sequences[step].isNoteOn() ? 1 : 0); return noteData; } uint16_t SpiSendParams(uint8_t cmd, uint8_t data) { SpiMasterCs = 0; SpiMaster.write(cmd); uint8_t rv = SpiMaster.write(data); SpiMasterCs = 1; //Thread::wait(1); return rv; } uint16_t SpiSendAllParams() { SpiSendParams(CMD_BPM, bpm); SpiSendParams(CMD_ACCENT_LEVEL, accentLevel); SpiSendParams(CMD_WAVE_SHAPE , oscillatorParam.waveShape); SpiSendParams(CMD_PULSE_WIDTH, oscillatorParam.pulseWidth); SpiSendParams(CMD_CUTOFF, filterParam.cutoff); SpiSendParams(CMD_RESONANCE, filterParam.resonance); SpiSendParams(CMD_LEVEL, envelopeParam.level); SpiSendParams(CMD_DURATION, envelopeParam.duration); SpiSendParams(CMD_DECAY, envelopeParam.decay); SpiSendParams(CMD_SUSTAIN, envelopeParam.sustain); for (int i = 0; i < SEQUENCE_N; i++) { SpiSendParams(CMD_NOTE, getNoteData(i)); SpiSendParams(CMD_PITCH, sequences[i].getPitch()); } uint16_t retVal = SpiSendParams(CMD_RCV_PLAYING_STEP, 0xaa); // Send dummy data return retVal; } void pollingRotEncs() { int _bpm = RotEncBpm.getVal(); if (_bpm != bpm) { bpm = _bpm; sequencerDisplay.setBpm(_bpm); SpiSendParams(CMD_BPM, _bpm); isDirty = true; } int _step = RotEncStep.getVal(); if (_step != currentStep) { currentStep = _step; // syncronize sequence value & Rotary Encoder's value RotEncPitch.setVal(sequences[currentStep].getPitch()); SpiSendParams(CMD_NOTE, getNoteData(_step)); SpiSendParams(CMD_PITCH, sequences[_step].getPitch()); isDirty = true; } int _pitch = RotEncPitch.getVal(); if (_pitch != sequences[currentStep].getPitch()) { sequences[currentStep].setPitch(_pitch); SpiSendParams(CMD_NOTE, getNoteData(currentStep)); SpiSendParams(CMD_PITCH, _pitch); isDirty = true; } } void pollingPins() { if (pinFlag & bWaveShape) { #if (UART_TRACE) printf("PinWaveShape Pushed\r\n"); #endif uint8_t _waveShape = oscillatorParam.waveShape; _waveShape++; if (_waveShape > waveShapeMax) { _waveShape = 0; } oscillatorParam.waveShape = _waveShape; sequencerDisplay.setWaveShape(_waveShape); pinFlag &= ~bWaveShape; SpiSendParams(CMD_WAVE_SHAPE, _waveShape); 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 if (sequencerDisplay.getOctave() < octaveMax) { sequencerDisplay.setOctave(sequencerDisplay.getOctave() + 1); isDirty = true; } pinFlag &= ~bOctaveUp; } if (pinFlag & bOctaveDown) { #if (UART_TRACE) printf("PinOctaveDown Pushed\r\n"); #endif if (sequencerDisplay.getOctave () > octaveMin) { sequencerDisplay.setOctave(sequencerDisplay.getOctave() - 1); isDirty = true; } pinFlag &= ~bOctaveDown; } if (pinFlag & bNoteOnOff) { #if (UART_TRACE) printf("PinNoteOnOff Pushed\r\n"); #endif sequences[currentStep].setNoteOn(!sequences[currentStep].isNoteOn()); pinFlag &= ~bNoteOnOff; SpiSendParams(CMD_NOTE, getNoteData(currentStep)); isDirty = true; } if (pinFlag & bTie) { #if (UART_TRACE) printf("PinTie Pushed\r\n"); #endif sequences[currentStep].setTie(!sequences[currentStep].isTie()); pinFlag &= ~bTie; SpiSendParams(CMD_NOTE, getNoteData(currentStep)); isDirty = true; } if (pinFlag & bAccent) { #if (UART_TRACE) printf("PinAccent Pushed\r\n"); #endif sequences[currentStep].setAccent(!sequences[currentStep].isAccent()); pinFlag &= ~bAccent; SpiSendParams(CMD_NOTE, getNoteData(currentStep)); isDirty = true; } if (pinFlag & bRunStop) { #if (UART_TRACE) printf("PinRunStop Pushed\r\n"); #endif if (isRunning) { isRunning = false; } else { isRunning = true; } pinFlag &= ~bRunStop; SpiSendParams(CMD_RUN, isRunning); isDirty = true; } } void dumpToLCD00() { char buff[64]; int col = 0; gLCD.clear(); sprintf(buff, "Run:%d BPM:%03d", isRunning, bpm); 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 pStp:%d", oscillatorParam.waveShape, UImode, playingStep); gLCD.drawstring(0, col++, buff); sprintf(buff, "PW :%4d CO :%4d", oscillatorParam.pulseWidth, filterParam.cutoff); gLCD.drawstring(0, col++, buff); sprintf(buff, "RSO:%4d ACL:%4d", filterParam.resonance, accentLevel); gLCD.drawstring(0, col++, buff); sprintf(buff, "LVL:%4d DUR:%4d", envelopeParam.level, envelopeParam.duration); gLCD.drawstring(0, col++, buff); sprintf(buff, "DCY:%4d SUS:%4d", envelopeParam.decay, envelopeParam.sustain); gLCD.drawstring(0, col++, buff); gLCD.display(); } void dumpToLCD01() { static int errCutoff = 0; static int errDuration = 0; static int errDecay = 0; static int errSustain = 0; static int errResonace = 0; static int errLevel = 0; static int errPulseWidth = 0; static int errAccentLevel = 0; uint8_t v; char buff[64]; v = AinCutOff.read_u16() >> (16 - POT_RESOLUTION); if (v != filterParam.cutoff) { errCutoff++; filterParam.cutoff = v; } v = AinDuration.read_u16() >> (16 - POT_RESOLUTION); if (v != envelopeParam.duration) { errDuration++; envelopeParam.duration = v; } v = AinDecay.read_u16() >> (16 - POT_RESOLUTION); if (v != envelopeParam.decay) { errDecay++; envelopeParam.decay = v; } v = AinSustain.read_u16() >> (16 - POT_RESOLUTION); if (v != envelopeParam.sustain) { errSustain++; envelopeParam.sustain = v; } v = AinResonance.read_u16() >> (16 - POT_RESOLUTION); if (v != filterParam.resonance) { errResonace++; filterParam.resonance = v; } v = AinLevel.read_u16() >> (16 - POT_RESOLUTION); if (v != envelopeParam.level) { errLevel++; envelopeParam.level = v; } v = AinPulseWidth.read_u16() >> (16 - POT_RESOLUTION); if (v != oscillatorParam.pulseWidth) { errPulseWidth++; oscillatorParam.pulseWidth = v; } v = AinAccentLevel.read_u16() >> (16 - POT_RESOLUTION); if (v != accentLevel) { errAccentLevel++; accentLevel = v; } gLCD.clear(); sprintf(buff, "Cutoff %3d %5d", filterParam.cutoff, errCutoff); gLCD.drawstring(0, 0, buff); sprintf(buff, "Duration %3d %5d", envelopeParam.duration, errDuration); gLCD.drawstring(0, 1, buff); sprintf(buff, "Decay %3d %5d", envelopeParam.decay, errDecay); gLCD.drawstring(0, 2, buff); sprintf(buff, "Sustain %3d %5d", envelopeParam.sustain, errSustain); gLCD.drawstring(0, 3, buff); sprintf(buff, "Resonance %3d %5d", filterParam.resonance, errResonace); gLCD.drawstring(0, 4, buff); sprintf(buff, "Level %3d %5d", envelopeParam.level, errLevel); gLCD.drawstring(0, 5, buff); sprintf(buff, "PulseWidth %3d %5d", oscillatorParam.pulseWidth, errPulseWidth); gLCD.drawstring(0, 6, buff); sprintf(buff, "AccentLvl %3d %5d", accentLevel, errAccentLevel); gLCD.drawstring(0, 7, buff); gLCD.display(); Thread::wait(10); } //------------------------------------------------------------------------ // Threads //------------------------------------------------------------------------ void pollingPots(void const *args) { for (;;) { uint8_t pulseWidth = AinPulseWidth.read_u16() >> (16 - POT_RESOLUTION); if (pulseWidth != oscillatorParam.pulseWidth) { oscillatorParam.pulseWidth = pulseWidth; SpiSendParams(CMD_PULSE_WIDTH, pulseWidth); isDirty = true; } uint8_t cutoff = AinCutOff.read_u16() >> (16 - POT_RESOLUTION); if (cutoff != filterParam.cutoff) { filterParam.cutoff = cutoff; SpiSendParams(CMD_CUTOFF, cutoff); isDirty = true; } uint8_t resonance = AinResonance.read_u16() >> (16 - POT_RESOLUTION); if (resonance != filterParam.resonance) { filterParam.resonance = resonance; SpiSendParams(CMD_RESONANCE, resonance); isDirty = true; } uint8_t level = AinLevel.read_u16() >> (16 - POT_RESOLUTION); if (level != envelopeParam.level) { envelopeParam.level = level; SpiSendParams(CMD_LEVEL, level); isDirty = true; } uint8_t duration = AinDuration.read_u16() >> (16 - POT_RESOLUTION); if (duration != envelopeParam.duration) { envelopeParam.duration = duration; SpiSendParams(CMD_DURATION, duration); isDirty = true; } uint8_t decay = AinDecay.read_u16() >> (16 - POT_RESOLUTION); if (decay != envelopeParam.decay) { envelopeParam.decay = decay; SpiSendParams(CMD_DECAY, decay); isDirty = true; } uint8_t sustain = AinSustain.read_u16() >> (16 - POT_RESOLUTION); if (sustain != envelopeParam.sustain) { envelopeParam.sustain = sustain; SpiSendParams(CMD_SUSTAIN, sustain); isDirty = true; } uint8_t _accentLevel = AinAccentLevel.read_u16() >> (16 - POT_RESOLUTION); if (_accentLevel != accentLevel) { accentLevel = _accentLevel; SpiSendParams(CMD_ACCENT_LEVEL, accentLevel); isDirty = true; } Thread::wait(POLLING_POTS_WAIT); } } //------------------------------------------------------------------------ // Main routine //------------------------------------------------------------------------ int main() { #if (UART_TRACE) printf("*** BaseMachine UI Controller ***\r\n"); #endif //-------------------------------------------------------------------- // Setup Devices // gLCD.set_spi_frequency(SPI2_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 SPI Master // SpiMasterCs = 1; SpiMaster.format(SPI_UI_TO_SEQUENCER_BITS, SPI_UI_TO_SEQUENCER_MODE); SpiMaster.frequency(SPI_UI_TO_SEQUENCER_RATE); StepChangeInterrupt.fall(&updateStep); //-------------------------------------------------------------------- // Initialize objects // Sequence::setBaseNoteNumber(baseNoteNumber); for (int i = 0; i < SEQUENCE_N; i++) { Sequence& seq = sequences[i]; seq.setPitch(pitch[i]); seq.setNoteOn(noteOn[i]); seq.setTie(tie[i]); seq.setAccent(accent[i]); } RotEncPitch.setVal(sequences[0].getPitch()); //-------------------------------------------------------------------- // Initialize threads // Thread thPollingPots(pollingPots); //-------------------------------------------------------------------- // Synchronize with Slave // SlaveReset = 0; SlaveReset = 1; Thread::wait(1000); SpiSendAllParams(); //-------------------------------------------------------------------- // Main loop // for (;;) { // Polling Devices /* if (UImode != 2) { pollingPots(); } */ pollingRotEncs(); pollingPins(); // Recieve playing step from SPI slave if (isStepChanged) { playingStep = SpiSendParams(CMD_RCV_PLAYING_STEP, 0x55); // Send dummy data isStepChanged = false; isDirty = true; } // Display /* if (!isRunning) { */ if (isDirty) { switch (UImode) { case 0: sequencerDisplay.update(SequencerDisplay::stop, currentStep, playingStep); break; case 1: dumpToLCD00(); break; } isDirty = false; } if (UImode == 2) { dumpToLCD01(); } /* } else { */ if (isDirty) { sequencerDisplay.update(SequencerDisplay::run, currentStep, playingStep); isDirty = false; } /* } */ } }