Integrated version

Revision:
0:5bc618f6d862
Child:
1:ecae97c65943
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseMachineUIController.h	Sun Nov 06 22:13:43 2016 +0000
@@ -0,0 +1,525 @@
+/*
+ * BaseMachineUIController.h
+ *
+ * 2016.11.06 created
+ *
+ */
+
+#ifndef _UICONTROLLER_H_
+#define _UICONTROLLER_H_
+
+#include "mbed.h"
+#include "rtos.h"
+
+#include "BaseMachineCommon.h"
+
+#include "st7565LCD.h"
+#include "PinDetect.h"
+#include "RotaryEncoder.h"
+#include "AverageAnalogIn.h"
+
+#include "Sequence.h"
+#include "ST7565_SequencerDisplay.h"
+
+#define GLCD_SPI_RATE       (1000000)
+#define POT_RESOLUTION      (7)     // bit
+#define AIN_AVERAGE         (16)    // AnalogInを移動平均する要素数
+
+const int bpmMax = 240;
+const int bpmMin = 60;
+const int octaveMax = 2;
+const int octaveMin = -2;
+const int waveShapeMax = 1;
+const int UImodeMax = 2;
+
+struct OscillatorParam {
+    uint8_t waveShape;
+    uint8_t pulseWidth;
+
+    OscillatorParam() : waveShape(0), pulseWidth(0) {}
+};
+
+struct FilterParam {
+    uint8_t cutoff;
+    uint8_t resonance;
+
+    FilterParam() : cutoff(0), resonance(0) {}
+};
+
+struct EnvelopeParam {
+    uint8_t level;
+    uint8_t length;
+    uint8_t duration;
+    uint8_t decay;
+    uint8_t sustain;
+
+    EnvelopeParam() : level(0), length(0), duration(0), decay(0), sustain(0) {}
+};
+
+class BaseMachineUIController
+{
+public:
+    BaseMachineUIController() :
+        bpm(120),
+        accentLevel(127),
+        editingStep(0),
+        playingStep(0),
+        isRunning(false),
+        isDirty(true),
+        UImode(0),
+        isStepChanged(false),
+        errCutoff(0),
+        errDuration(0),
+        errDecay(0),
+        errSustain(0),
+        errResonance(0),
+        errLevel(0),
+        errPulseWidth(0),
+        errAccentLevel(0) {
+    }
+    
+    ~BaseMachineUIController() {}
+
+    void init() {
+        //--------------------------------------------------------------------
+        // Create Dvices
+        //
+        //ST7565(PinName mosi, PinName sclk, PinName cs, PinName rst, PinName a0);
+        gLCD = new ST7565(PB_15, PB_13, PB_12, PB_2, PB_1);
+        sequencerDisplay = new ST7565_SequencerDisplay(gLCD, sequences, SEQUENCE_N);
+
+        AinPulseWidth = new AverageAnalogIn(PC_2, AIN_AVERAGE);
+        AinCutOff     = new AverageAnalogIn(PB_0, AIN_AVERAGE);
+        AinResonance  = new AverageAnalogIn(PC_1, AIN_AVERAGE);
+        AinLevel      = new AverageAnalogIn(PC_0, AIN_AVERAGE);
+        AinDuration   = new AverageAnalogIn(PA_4, AIN_AVERAGE);
+        AinDecay      = new AverageAnalogIn(PA_1, AIN_AVERAGE);
+        AinSustain    = new AverageAnalogIn(PA_0, AIN_AVERAGE);
+        AinAccentLevel= new AverageAnalogIn(PC_3, AIN_AVERAGE);
+
+        RotEncStep  = new RotaryEncoder(PA_11, PA_12, 0, SEQUENCE_N - 1, 0);
+        RotEncPitch = new RotaryEncoder(PB_5, PB_4, 0, Sequence::getMaxPitch() - 1, 0);
+        RotEncBpm   = new RotaryEncoder(PC_12, PC_10, bpmMin, bpmMax, 120);
+
+        PinWaveShape  = new PinDetect(PD_2, PullUp);
+        PinUIMode     = new PinDetect(PC_11, PullUp);
+        PinOctaveUp   = new PinDetect(PB_3, PullUp);
+        PinOctaveDown = new PinDetect(PA_10, PullUp);
+        PinNoteOnOff  = new PinDetect(PC_5, PullUp);
+        PinTie        = new PinDetect(PC_6, PullUp);
+        PinAccent     = new PinDetect(PC_8, PullUp);
+        PinRunStop    = new PinDetect(PC_9, PullUp);
+
+        //--------------------------------------------------------------------
+        // Setup Devices
+        //
+        gLCD->set_spi_frequency(GLCD_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(this, &BaseMachineUIController::swWaveShapePressed);
+        PinWaveShape->setAssertValue(0);
+        PinWaveShape->setSampleFrequency();
+
+        PinUIMode->attach_asserted(this, &BaseMachineUIController::swUIModePressed);
+        PinUIMode->setAssertValue(0);
+        PinUIMode->setSampleFrequency();
+
+        PinOctaveUp->attach_asserted(this, &BaseMachineUIController::swOctaveUpPressed);
+        PinOctaveUp->setAssertValue(0);
+        PinOctaveUp->setSampleFrequency();
+
+        PinOctaveDown->attach_asserted(this, &BaseMachineUIController::swOctaveDownPressed);
+        PinOctaveDown->setAssertValue(0);
+        PinOctaveDown->setSampleFrequency();
+
+        PinNoteOnOff->attach_asserted(this, &BaseMachineUIController::swNoteOnOffPressed);
+        PinNoteOnOff->setAssertValue(0);
+        PinNoteOnOff->setSampleFrequency();
+
+        PinTie->attach_asserted(this, &BaseMachineUIController::swTiePressed);
+        PinTie->setAssertValue(0);
+        PinTie->setSampleFrequency();
+
+        PinAccent->attach_asserted(this, &BaseMachineUIController::swAccentPressed);
+        PinAccent->setAssertValue(0);
+        PinAccent->setSampleFrequency();
+
+        PinRunStop->attach_asserted(this, &BaseMachineUIController::swRunStopPressed);
+        PinRunStop->setAssertValue(0);
+        PinRunStop->setSampleFrequency();
+
+        //--------------------------------------------------------------------
+        // 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());
+    }
+
+    void destract() {
+        //--------------------------------------------------------------------
+        // Destract Devices
+        //
+        delete gLCD;
+
+        delete AinPulseWidth;
+        delete AinCutOff;
+        delete AinResonance;
+        delete AinLevel;
+        delete AinDuration;
+        delete AinDecay;
+        delete AinSustain;
+        delete AinAccentLevel;
+
+        delete RotEncStep;
+        delete RotEncPitch;
+        delete RotEncBpm;
+
+        delete PinWaveShape;
+        delete PinUIMode;
+        delete PinOctaveUp;
+        delete PinOctaveDown;
+        delete PinNoteOnOff;
+        delete PinTie;
+        delete PinAccent;
+        delete PinRunStop;
+    }
+    
+    void getOscillatorParam(OscillatorParam* pParam) {
+        memcpy(pParam, &oscillatorParam, sizeof(oscillatorParam));
+    }
+    void getFilterParam(FilterParam* pParam) {
+        memcpy(pParam, &filterParam, sizeof(filterParam));
+    }   
+    void getEnvelopeParam(EnvelopeParam* pParam) {
+        memcpy(pParam, &envelopeParam, sizeof(envelopeParam));
+    }
+    uint8_t getBpm() { return bpm; }
+    uint8_t getAccentLevel() { return accentLevel; }
+    
+    bool getIsRunning() { return isRunning; }
+    
+    void setPlayingStep(int step)
+    {
+        playingStep = step;
+        isDirty = true;
+    }
+    
+    void update() {
+        pollingRotEncs();
+        pollingPots();
+
+        switch (UImode) {
+            case 0:
+                if (isDirty) {
+                    sequencerDisplay->update(SequencerDisplay::stop, editingStep, playingStep);
+                }
+                break;
+            case 1:
+                if (isDirty) {
+                    dumpToLCD00();
+                }
+                break;
+            case 2:
+                dumpToLCD01();
+                break;
+        }
+        isDirty = false;
+    }
+
+private:
+    ST7565* gLCD;
+
+    AverageAnalogIn* AinPulseWidth;
+    AverageAnalogIn* AinCutOff;
+    AverageAnalogIn* AinResonance;
+    AverageAnalogIn* AinLevel;
+    AverageAnalogIn* AinDuration;
+    AverageAnalogIn* AinDecay;
+    AverageAnalogIn* AinSustain;
+    AverageAnalogIn* AinAccentLevel;
+
+    RotaryEncoder* RotEncStep;
+    RotaryEncoder* RotEncPitch;
+    RotaryEncoder* RotEncBpm;
+
+    PinDetect* PinWaveShape;
+    PinDetect* PinUIMode;
+    PinDetect* PinOctaveUp;
+    PinDetect* PinOctaveDown;
+    PinDetect* PinNoteOnOff;
+    PinDetect* PinTie;
+    PinDetect* PinAccent;
+    PinDetect* PinRunStop;
+
+    ST7565_SequencerDisplay* sequencerDisplay;
+    
+    Sequence sequences[SEQUENCE_N];
+    
+    OscillatorParam oscillatorParam;
+    FilterParam filterParam;
+    EnvelopeParam envelopeParam;
+    
+    uint8_t bpm;
+    uint8_t accentLevel;
+
+    int editingStep;
+    int playingStep;
+    bool isRunning;
+    bool isDirty;
+    int UImode;
+
+    bool isStepChanged;
+
+    int errCutoff;
+    int errDuration;
+    int errDecay;
+    int errSustain;
+    int errResonance;
+    int errLevel;
+    int errPulseWidth;
+    int errAccentLevel;
+
+    //------------------------------------------------------------------------
+    // PinDetect callback functions
+    //------------------------------------------------------------------------
+    void swWaveShapePressed() {
+#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);
+        isDirty = true;
+    }
+
+    void swUIModePressed() {
+#if (UART_TRACE)
+        printf("PinUIMode Pushed\r\n");
+#endif
+        UImode++;
+        if (UImode > UImodeMax) {
+            UImode = 0;
+        }
+        isDirty = true;
+    }
+
+    void swOctaveUpPressed() {
+#if (UART_TRACE)
+        printf("PinOctaveUp Pushed\r\n");
+#endif
+        if (sequencerDisplay->getOctave() < octaveMax) {
+            sequencerDisplay->setOctave(sequencerDisplay->getOctave() + 1);
+            isDirty = true;
+        }
+    }
+
+    void swOctaveDownPressed() {
+#if (UART_TRACE)
+        printf("PinOctaveDown Pushed\r\n");
+#endif
+        if (sequencerDisplay->getOctave () > octaveMin) {
+            sequencerDisplay->setOctave(sequencerDisplay->getOctave() - 1);
+            isDirty = true;
+        }
+    }
+
+    void swNoteOnOffPressed() {
+#if (UART_TRACE)
+        printf("PinNoteOnOff Pushed\r\n");
+#endif
+        sequences[editingStep].setNoteOn(!sequences[editingStep].isNoteOn());
+        isDirty = true;
+    }
+
+    void swTiePressed() {
+#if (UART_TRACE)
+        printf("PinTie Pushed\r\n");
+#endif
+        sequences[editingStep].setTie(!sequences[editingStep].isTie());
+        isDirty = true;
+    }
+
+    void swAccentPressed() {
+#if (UART_TRACE)
+        printf("PinAccent Pushed\r\n");
+#endif
+        sequences[editingStep].setAccent(!sequences[editingStep].isAccent());
+        isDirty = true;
+    }
+
+    void swRunStopPressed() {
+#if (UART_TRACE)
+        printf("PinRunStop Pushed\r\n");
+#endif
+        if (isRunning) {
+            isRunning = false;
+        } else {
+            isRunning = true;
+        }
+        isDirty = true;
+    }
+
+    //------------------------------------------------------------------------
+    // Functions
+    //------------------------------------------------------------------------
+    void pollingRotEncs() {
+        int _bpm = RotEncBpm->getVal();
+        if (_bpm != bpm) {
+            bpm = _bpm;
+            sequencerDisplay->setBpm(_bpm);
+            isDirty = true;
+        }
+
+        int _step = RotEncStep->getVal();
+        if (_step != editingStep) {
+            editingStep = _step;
+            // syncronize sequence value & Rotary Encoder's value
+            RotEncPitch->setVal(sequences[editingStep].getPitch());
+            isDirty = true;
+        }
+
+        int _pitch = RotEncPitch->getVal();
+        if (_pitch != sequences[editingStep].getPitch()) {
+            sequences[editingStep].setPitch(_pitch);
+            isDirty = true;
+        }
+    }
+
+    void pollingPots() {
+        uint8_t pulseWidth = AinPulseWidth->read_u16() >> (16 - POT_RESOLUTION);
+        if (pulseWidth != oscillatorParam.pulseWidth) {
+            oscillatorParam.pulseWidth = pulseWidth;
+            errPulseWidth++;
+            isDirty = true;
+        }
+
+        uint8_t cutoff = AinCutOff->read_u16() >> (16 - POT_RESOLUTION);
+        if (cutoff != filterParam.cutoff) {
+            filterParam.cutoff = cutoff;
+            errCutoff++;
+            isDirty = true;
+        }
+
+        uint8_t resonance = AinResonance->read_u16() >> (16 - POT_RESOLUTION);
+        if (resonance != filterParam.resonance) {
+            filterParam.resonance = resonance;
+            errResonance++;
+            isDirty = true;
+        }
+
+        uint8_t level = AinLevel->read_u16() >> (16 - POT_RESOLUTION);
+        if (level != envelopeParam.level) {
+            errLevel++;
+            envelopeParam.level = level;
+            isDirty = true;
+        }
+
+        uint8_t duration = AinDuration->read_u16() >> (16 - POT_RESOLUTION);
+        if (duration != envelopeParam.duration) {
+            errDuration++;
+            envelopeParam.duration = duration;
+            isDirty = true;
+        }
+
+        uint8_t decay = AinDecay->read_u16() >> (16 - POT_RESOLUTION);
+        if (decay != envelopeParam.decay) {
+            errDecay++;
+            envelopeParam.decay = decay;
+            isDirty = true;
+        }
+
+        uint8_t sustain = AinSustain->read_u16() >> (16 - POT_RESOLUTION);
+        if (sustain != envelopeParam.sustain) {
+            errSustain++;
+            envelopeParam.sustain = sustain;
+            isDirty = true;
+        }
+
+        uint8_t _accentLevel = AinAccentLevel->read_u16() >> (16 - POT_RESOLUTION);
+        if (_accentLevel != accentLevel) {
+            errAccentLevel++;
+            accentLevel = _accentLevel;
+            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",
+                editingStep, sequences[editingStep].isNoteOn(), sequences[editingStep].getPitch());
+        gLCD->drawstring(0, col++, buff);
+
+        sprintf(buff, "Oct:%-2d Tie:%d Acc:%d",
+                sequencerDisplay->getOctave(), sequences[editingStep].isTie(),sequences[editingStep].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() {
+        char buff[64];
+
+        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, errResonance);
+        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();
+    }
+};
+
+#endif //_UICONTROLLER_H_