Nucleo SPI Sequencer

Dependencies:   AverageAnalogIn N5110 Nucleo_rtos_UI_Test PinDetect RotaryEncoder Sequence mbed-rtos mbed FilterController

Fork of Nucleo_rtos_UI_Test by Ryo Od

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Nucleo SPI Sequencer
00003  *
00004  * 2016.06.12
00005  *
00006  */ 
00007  
00008 #define UART_TRACE  (0)
00009  
00010 #include "mbed.h"
00011 #include "rtos.h"
00012 #include "PinDetect.h"
00013 #include "RotaryEncoder.h"
00014 #include "N5110.h"
00015 #include "AverageAnalogIn.h"
00016 #include "SpiSequenceSender.h"
00017 #include "SpiFilterController.h"
00018 
00019 #define UART_TRACE  (0)
00020 #define SPI_RATE    (8000000)
00021 
00022 #define SEQUENCE_N  (16)
00023 #define PITCH_MAX   (12)
00024 
00025 DigitalOut CheckPin(PC_8);
00026 
00027 //------------------------------------------------------------------------
00028 // SPI Sequencer
00029 //------------------------------------------------------------------------
00030 SPI spiMaster(SPI_MOSI, SPI_MISO, SPI_SCK);
00031 Sequence sequence[SEQUENCE_N];
00032 SpiSequenceSender sequenceSender(&spiMaster, D9, sequence, SEQUENCE_N, 5);
00033 
00034 SpiFilterController filterController(&spiMaster, D10);
00035 
00036 //------------------------------------------------------------------------
00037 // User Interface
00038 //------------------------------------------------------------------------
00039 // SPI2 Morpho
00040 //        VCC,   SCE,  RST,  D/C,   MOSI,  SCLK,  LED
00041 N5110 Lcd(PA_12, PB_1, PB_2, PB_12, PB_15, PB_13, PA_11);
00042 
00043 RotaryEncoder RotEnc1(D2, D3, 0, SEQUENCE_N - 1, 0);
00044 RotaryEncoder RotEnc2(D4, D5, 0, PITCH_MAX, 0);
00045 
00046 AverageAnalogIn Pots[] = {
00047     AverageAnalogIn(A0),
00048     AverageAnalogIn(A1),
00049     AverageAnalogIn(A2),
00050     AverageAnalogIn(A3),
00051     AverageAnalogIn(A4),
00052 };
00053 
00054 PinDetect Pins[] = {
00055     PinDetect(PA_13, PullUp),
00056     PinDetect(PA_14, PullUp),
00057     PinDetect(PA_15, PullUp),
00058     PinDetect(PB_7,  PullUp),
00059     PinDetect(PC_13, PullUp),
00060     PinDetect(PB_10, PullUp),
00061     PinDetect(PA_8,  PullUp),
00062 };
00063 
00064 #if 0
00065 // ToDo: Filterにモジュレーション信号を送る方法を考える。
00066 struct Filter {
00067     int cutOff;
00068     int resonance;
00069     int envMod;
00070 } Filter;
00071 #endif
00072 
00073 int currentStep = 0;
00074 bool isRunning = true;
00075 bool isDirty = true;
00076 
00077 //------------------------------------------------------------------------
00078 // Fuctions
00079 //------------------------------------------------------------------------
00080 void updateLCD()
00081 {
00082     char buff[20];
00083     
00084     //Lcd.clear();
00085     sprintf(buff, "step#: %d  ", currentStep);
00086     Lcd.printString(buff, 0, 0);
00087     sprintf(buff, "pitch: %d  ", sequence[currentStep].getPitch());
00088     Lcd.printString(buff, 0, 1);
00089     sprintf(buff, "octave: %d  " ,sequence[currentStep].getOctave());
00090     Lcd.printString(buff, 0, 2);
00091     sprintf(buff, "%1d %1d %1d %1d %3d", 
00092         sequence[currentStep].noteOn, sequence[currentStep].tie, sequence[currentStep].accent,
00093         isRunning, sequenceSender.getWaveShape());
00094     Lcd.printString(buff, 0, 3);
00095     sprintf(buff, "%3d %3d %3d", 
00096         sequenceSender.getPulseWidth(), filterController.getEnvMod(), sequenceSender.getBpm());
00097     Lcd.printString(buff, 0, 4);
00098     sprintf(buff, "%3d %3d", filterController.getCutoff(), filterController.getResonance());
00099     Lcd.printString(buff, 0, 5);
00100     Lcd.refresh();
00101 }
00102 
00103 void initSequence()
00104 {
00105     for (int i = 0; i < SEQUENCE_N; i++) {
00106         Sequence& seq = sequenceSender.getSequences()[i];
00107         seq.setPitch(i);
00108         seq.setOctave(0);
00109         seq.tie = true;
00110     }
00111 }
00112 
00113 //------------------------------------------------------------------------
00114 // CallBack routines
00115 //------------------------------------------------------------------------
00116 void swOctaveUpPressed()
00117 {
00118     sequence[currentStep].setOctave(sequence[currentStep].getOctave() + 1);
00119     isDirty = true;
00120     #if (UART_TRACE)
00121     printf("swOctaveUpPressed\r\n");
00122     #endif
00123 }
00124 
00125 void swOctaveDownPressed()
00126 {
00127     sequence[currentStep].setOctave(sequence[currentStep].getOctave() - 1);
00128     isDirty = true;
00129     #if (UART_TRACE)
00130     printf("swOctaveDownPressed\r\n");
00131     #endif
00132 }
00133 
00134 void swNoteOnOffPressed()
00135 {
00136     sequence[currentStep].noteOn = !sequence[currentStep].noteOn;
00137     isDirty = true;
00138     #if (UART_TRACE)
00139     printf("swNoteOnOffPressed\r\n");
00140     #endif
00141 }
00142 
00143 void swTiePressed()
00144 {
00145     sequence[currentStep].tie = !sequence[currentStep].tie;
00146     isDirty = true;
00147     #if (UART_TRACE)
00148     printf("swTiePressed\r\n");
00149     #endif
00150 }
00151 
00152 void swAccentPressed()
00153 {
00154     sequence[currentStep].accent = !sequence[currentStep].accent;
00155     isDirty = true;
00156     #if (UART_TRACE)
00157     printf("swAccentPressed\r\n");
00158     #endif
00159 }
00160 
00161 void swRunStopPressed()
00162 {
00163     isRunning = !isRunning;
00164     if (isRunning) {
00165         sequenceSender.run(currentStep);
00166     } else {
00167         sequenceSender.stop();
00168     }
00169     isDirty = true;
00170     #if (UART_TRACE)
00171     printf("swRunStopPressed\r\n");
00172     #endif
00173 }
00174 
00175 void swWaveShapePressed()
00176 {
00177     uint8_t shape = sequenceSender.getWaveShape();
00178     shape++;
00179     if (shape == sequenceSender.WAVESHAPE_N) {
00180         shape = 0;
00181     }
00182     sequenceSender.setWaveShape(shape);
00183     isDirty = true;
00184     #if (UART_TRACE)
00185     printf("swWaveShapePressed\r\n");
00186     #endif
00187 }
00188 
00189 //------------------------------------------------------------------------
00190 // Thread
00191 //------------------------------------------------------------------------
00192 void pollingRotEncs(void const *argument)
00193 {
00194     while (true) {
00195         int _step = RotEnc1.getVal();
00196         if (_step != currentStep) {
00197             currentStep = _step;
00198             // syncronize sequence value & Rotary Encoder's value
00199             RotEnc2.setVal(sequence[currentStep].getPitch());
00200             isDirty = true;
00201         }
00202         int _pitch = RotEnc2.getVal();
00203         if (_pitch != sequence[currentStep].getPitch()) {
00204             sequence[currentStep].setPitch(_pitch);
00205             isDirty = true;
00206         }
00207         Thread::wait(10);
00208     }
00209 }
00210 
00211 void pollingPots(void const *argument)
00212 {
00213     unsigned short tmp;
00214     
00215     while (true) {
00216         // pulse width
00217         tmp = Pots[0].read_u16() >> 9;    // 7bit width
00218         if (tmp != (sequenceSender.getPulseWidth() >> 1)) {
00219             sequenceSender.setPulseWidth(tmp << 1);
00220             isDirty = true;
00221         }
00222         // filter envelope moduration 
00223         tmp = Pots[1].read_u16() >> 8;
00224         if (tmp != filterController.getEnvMod()) {
00225             filterController.setEnvMod(tmp);
00226             isDirty = true;
00227         }
00228         // bpm
00229         tmp = Pots[2].read_u16() >> 9;    // 7bit precission
00230         tmp <<= 1;
00231         if (tmp != sequenceSender.getBpm()) {
00232             sequenceSender.setBpm(tmp);
00233             isDirty = true;
00234         }
00235         // cutoff
00236         tmp = Pots[3].read_u16() >> 8;
00237         if (tmp != filterController.getCutoff()) {
00238             filterController.setCutoff(tmp);
00239             isDirty = true;
00240         }
00241         // resonance
00242         tmp = Pots[4].read_u16() >> 8;
00243         if (tmp != filterController.getResonance()) {
00244             filterController.setResonance(tmp);
00245             isDirty = true;
00246         }
00247         Thread::wait(20);
00248     }
00249 }
00250 
00251 //------------------------------------------------------------------------
00252 // Main routine
00253 //------------------------------------------------------------------------
00254 int main()
00255 {
00256     #if (UART_TRACE)
00257     printf("\n\n\r*** RTOS UI Test ***\r\n");
00258     #endif
00259     
00260     spiMaster.format(0, 8);
00261     spiMaster.frequency(SPI_RATE);
00262 
00263     // Init devices
00264     RotEnc1.setInterval(500);
00265     RotEnc2.setInterval(500);
00266     
00267     Pins[0].attach_asserted(&swOctaveUpPressed);
00268     Pins[1].attach_asserted(&swOctaveDownPressed);
00269     Pins[2].attach_asserted(&swNoteOnOffPressed);
00270     Pins[3].attach_asserted(&swTiePressed);
00271     Pins[4].attach_asserted(&swAccentPressed);
00272     Pins[5].attach_asserted(&swRunStopPressed);
00273     Pins[6].attach_asserted(&swWaveShapePressed);
00274     for (int i = 0; i < 7; i++) {
00275         Pins[i].setAssertValue(0);
00276         Pins[i].setSampleFrequency();
00277     }
00278     
00279     Lcd.init();
00280     Lcd.normalMode();      // normal colour mode
00281     Lcd.setBrightness(0.5); // put LED backlight on 50%
00282     
00283     // Thread start
00284     Thread thRotEnc(pollingRotEncs, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);
00285     Thread thPots(pollingPots, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);
00286 
00287     initSequence();
00288     sequenceSender.run(0);
00289     
00290     // Main loop
00291     while (true) {
00292         if (!isRunning && isDirty) {
00293             CheckPin = !CheckPin;
00294             filterController.outDCF();
00295             updateLCD();
00296             isDirty = false;
00297         }
00298     }
00299 }