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

Committer:
ryood
Date:
Sun Jun 12 08:49:34 2016 +0000
Revision:
8:2c481dab525a
Parent:
7:8f38e85705ba
Child:
9:06ba77ce8b3c
pitch?RotaryEncoder???????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ryood 4:d9a72e07749f 1 /*
ryood 5:e4b68faa6801 2 * Nucleo SPI Sequencer
ryood 4:d9a72e07749f 3 *
ryood 5:e4b68faa6801 4 * 2016.06.12
ryood 4:d9a72e07749f 5 *
ryood 4:d9a72e07749f 6 */
ryood 4:d9a72e07749f 7
ryood 0:468e49a35876 8 #include "mbed.h"
ryood 0:468e49a35876 9 #include "rtos.h"
ryood 2:8cc6dff1d7fd 10 #include "PinDetect.h"
ryood 2:8cc6dff1d7fd 11 #include "RotaryEncoder.h"
ryood 0:468e49a35876 12 #include "N5110.h"
ryood 4:d9a72e07749f 13 #include "AverageAnalogIn.h"
ryood 5:e4b68faa6801 14 #include "SpiSequenceSender.h"
ryood 2:8cc6dff1d7fd 15
ryood 5:e4b68faa6801 16 #define SPI_RATE (8000000)
ryood 5:e4b68faa6801 17
ryood 5:e4b68faa6801 18 #define SEQUENCE_N (16)
ryood 5:e4b68faa6801 19 #define OCTAVE_MIN (-1)
ryood 5:e4b68faa6801 20 #define OCTAVE_MAX (1)
ryood 5:e4b68faa6801 21 #define PITCH_MAX (12)
ryood 5:e4b68faa6801 22
ryood 5:e4b68faa6801 23 DigitalOut CheckPin(PC_8);
ryood 0:468e49a35876 24
ryood 5:e4b68faa6801 25 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 26 // SPI Sequencer
ryood 5:e4b68faa6801 27 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 28 SPI spiMaster(SPI_MOSI, SPI_MISO, SPI_SCK);
ryood 5:e4b68faa6801 29 Sequence sequence[SEQUENCE_N];
ryood 5:e4b68faa6801 30 SpiSequenceSender sequenceSender(&spiMaster, D10, sequence, SEQUENCE_N, 5);
ryood 5:e4b68faa6801 31
ryood 5:e4b68faa6801 32 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 33 // User Interface
ryood 5:e4b68faa6801 34 //------------------------------------------------------------------------
ryood 0:468e49a35876 35 // SPI2 Morpho
ryood 0:468e49a35876 36 // VCC, SCE, RST, D/C, MOSI, SCLK, LED
ryood 0:468e49a35876 37 N5110 Lcd(PA_12, PB_1, PB_2, PB_12, PB_15, PB_13, PA_11);
ryood 2:8cc6dff1d7fd 38
ryood 2:8cc6dff1d7fd 39 RotaryEncoder RotEnc1(D2, D3, 0, SEQUENCE_N - 1, 0);
ryood 2:8cc6dff1d7fd 40 RotaryEncoder RotEnc2(D4, D5, 0, PITCH_MAX, 0);
ryood 2:8cc6dff1d7fd 41
ryood 4:d9a72e07749f 42 AverageAnalogIn Pots[] = {
ryood 4:d9a72e07749f 43 AverageAnalogIn(A0),
ryood 4:d9a72e07749f 44 AverageAnalogIn(A1),
ryood 4:d9a72e07749f 45 AverageAnalogIn(A2),
ryood 4:d9a72e07749f 46 AverageAnalogIn(A3),
ryood 4:d9a72e07749f 47 AverageAnalogIn(A4),
ryood 3:8c8020dfd82f 48 };
ryood 3:8c8020dfd82f 49
ryood 2:8cc6dff1d7fd 50 PinDetect Pins[] = {
ryood 3:8c8020dfd82f 51 PinDetect(PA_13, PullUp),
ryood 3:8c8020dfd82f 52 PinDetect(PA_14, PullUp),
ryood 3:8c8020dfd82f 53 PinDetect(PA_15, PullUp),
ryood 3:8c8020dfd82f 54 PinDetect(PB_7, PullUp),
ryood 3:8c8020dfd82f 55 PinDetect(PC_13, PullUp),
ryood 3:8c8020dfd82f 56 PinDetect(PB_10, PullUp),
ryood 3:8c8020dfd82f 57 PinDetect(PA_8, PullUp),
ryood 2:8cc6dff1d7fd 58 };
ryood 2:8cc6dff1d7fd 59
ryood 2:8cc6dff1d7fd 60 // Grobal Variables
ryood 2:8cc6dff1d7fd 61
ryood 4:d9a72e07749f 62 struct Filter {
ryood 4:d9a72e07749f 63 int cutOff;
ryood 4:d9a72e07749f 64 int resonance;
ryood 4:d9a72e07749f 65 int envMod;
ryood 4:d9a72e07749f 66 } Filter;
ryood 4:d9a72e07749f 67
ryood 7:8f38e85705ba 68 int currentStep = 0;
ryood 4:d9a72e07749f 69 int tempo = 120;
ryood 3:8c8020dfd82f 70 bool isRunning = true;
ryood 3:8c8020dfd82f 71 bool isDirty = true;
ryood 2:8cc6dff1d7fd 72
ryood 5:e4b68faa6801 73 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 74 // Fuctions
ryood 5:e4b68faa6801 75 //------------------------------------------------------------------------
ryood 2:8cc6dff1d7fd 76 void updateLCD()
ryood 0:468e49a35876 77 {
ryood 0:468e49a35876 78 char buff[20];
ryood 0:468e49a35876 79
ryood 4:d9a72e07749f 80 //Lcd.clear();
ryood 7:8f38e85705ba 81 sprintf(buff, "Note#: %d ", currentStep);
ryood 4:d9a72e07749f 82 Lcd.printString(buff, 0, 0);
ryood 7:8f38e85705ba 83 sprintf(buff, "pitch: %d ", sequence[currentStep].getPitch());
ryood 0:468e49a35876 84 Lcd.printString(buff, 0, 1);
ryood 7:8f38e85705ba 85 sprintf(buff, "octave: %d " ,sequence[currentStep].getOctave());
ryood 2:8cc6dff1d7fd 86 Lcd.printString(buff, 0, 2);
ryood 4:d9a72e07749f 87 sprintf(buff, "%1d %1d %1d %1d %3d",
ryood 7:8f38e85705ba 88 sequence[currentStep].noteOn, sequence[currentStep].tie, sequence[currentStep].accent,
ryood 6:4e089888b809 89 isRunning, sequenceSender.getWaveShape());
ryood 2:8cc6dff1d7fd 90 Lcd.printString(buff, 0, 3);
ryood 6:4e089888b809 91 sprintf(buff, "%3d %3d %3d",
ryood 6:4e089888b809 92 sequenceSender.getPulseWidth(), Filter.envMod, tempo);
ryood 2:8cc6dff1d7fd 93 Lcd.printString(buff, 0, 4);
ryood 4:d9a72e07749f 94 sprintf(buff, "%3d %3d", Filter.cutOff, Filter.resonance);
ryood 4:d9a72e07749f 95 Lcd.printString(buff, 0, 5);
ryood 0:468e49a35876 96 Lcd.refresh();
ryood 0:468e49a35876 97 }
ryood 0:468e49a35876 98
ryood 5:e4b68faa6801 99 //------------------------------------------------------------------------
ryood 2:8cc6dff1d7fd 100 // CallBack routines
ryood 5:e4b68faa6801 101 //------------------------------------------------------------------------
ryood 2:8cc6dff1d7fd 102 void swOctaveUpPressed()
ryood 2:8cc6dff1d7fd 103 {
ryood 7:8f38e85705ba 104 sequence[currentStep].setOctave(sequence[currentStep].getOctave() + 1);
ryood 2:8cc6dff1d7fd 105 isDirty = true;
ryood 2:8cc6dff1d7fd 106 printf("swOctaveUpPressed\r\n");
ryood 2:8cc6dff1d7fd 107 }
ryood 2:8cc6dff1d7fd 108
ryood 2:8cc6dff1d7fd 109 void swOctaveDownPressed()
ryood 2:8cc6dff1d7fd 110 {
ryood 7:8f38e85705ba 111 sequence[currentStep].setOctave(sequence[currentStep].getOctave() - 1);
ryood 2:8cc6dff1d7fd 112 isDirty = true;
ryood 2:8cc6dff1d7fd 113 printf("swOctaveDownPressed\r\n");
ryood 2:8cc6dff1d7fd 114 }
ryood 2:8cc6dff1d7fd 115
ryood 2:8cc6dff1d7fd 116 void swNoteOnOffPressed()
ryood 2:8cc6dff1d7fd 117 {
ryood 7:8f38e85705ba 118 sequence[currentStep].noteOn = !sequence[currentStep].noteOn;
ryood 2:8cc6dff1d7fd 119 isDirty = true;
ryood 2:8cc6dff1d7fd 120 printf("swNoteOnOffPressed\r\n");
ryood 2:8cc6dff1d7fd 121 }
ryood 2:8cc6dff1d7fd 122
ryood 2:8cc6dff1d7fd 123 void swTiePressed()
ryood 2:8cc6dff1d7fd 124 {
ryood 7:8f38e85705ba 125 sequence[currentStep].tie = !sequence[currentStep].tie;
ryood 2:8cc6dff1d7fd 126 isDirty = true;
ryood 2:8cc6dff1d7fd 127 printf("swTiePressed\r\n");
ryood 2:8cc6dff1d7fd 128 }
ryood 2:8cc6dff1d7fd 129
ryood 2:8cc6dff1d7fd 130 void swAccentPressed()
ryood 2:8cc6dff1d7fd 131 {
ryood 7:8f38e85705ba 132 sequence[currentStep].accent = !sequence[currentStep].accent;
ryood 2:8cc6dff1d7fd 133 isDirty = true;
ryood 2:8cc6dff1d7fd 134 printf("swAccentPressed\r\n");
ryood 2:8cc6dff1d7fd 135 }
ryood 2:8cc6dff1d7fd 136
ryood 3:8c8020dfd82f 137 void swRunStopPressed()
ryood 3:8c8020dfd82f 138 {
ryood 3:8c8020dfd82f 139 isRunning = !isRunning;
ryood 3:8c8020dfd82f 140 isDirty = true;
ryood 3:8c8020dfd82f 141 printf("swRunStopPressed\r\n");
ryood 3:8c8020dfd82f 142 }
ryood 3:8c8020dfd82f 143
ryood 6:4e089888b809 144 void swWaveShapePressed()
ryood 3:8c8020dfd82f 145 {
ryood 6:4e089888b809 146 //Oscillator.waveShape++;
ryood 6:4e089888b809 147 uint8_t shape = sequenceSender.getWaveShape();
ryood 6:4e089888b809 148 shape++;
ryood 6:4e089888b809 149 if (shape == sequenceSender.WAVESHAPE_N) {
ryood 6:4e089888b809 150 shape = 0;
ryood 6:4e089888b809 151 }
ryood 6:4e089888b809 152 sequenceSender.setWaveShape(shape);
ryood 3:8c8020dfd82f 153 isDirty = true;
ryood 6:4e089888b809 154 printf("swWaveShapePressed\r\n");
ryood 3:8c8020dfd82f 155 }
ryood 3:8c8020dfd82f 156
ryood 5:e4b68faa6801 157 //------------------------------------------------------------------------
ryood 4:d9a72e07749f 158 // Thread
ryood 5:e4b68faa6801 159 //------------------------------------------------------------------------
ryood 4:d9a72e07749f 160 void pollingRotEncs(void const *argument)
ryood 3:8c8020dfd82f 161 {
ryood 4:d9a72e07749f 162 while (true) {
ryood 7:8f38e85705ba 163 int _step = RotEnc1.getVal();
ryood 7:8f38e85705ba 164 if (_step != currentStep) {
ryood 7:8f38e85705ba 165 currentStep = _step;
ryood 8:2c481dab525a 166 // syncronize sequence value & Rotary Encoder's value
ryood 8:2c481dab525a 167 RotEnc2.setVal(sequence[currentStep].getPitch());
ryood 4:d9a72e07749f 168 isDirty = true;
ryood 4:d9a72e07749f 169 }
ryood 4:d9a72e07749f 170 int _pitch = RotEnc2.getVal();
ryood 7:8f38e85705ba 171 if (_pitch != sequence[currentStep].getPitch()) {
ryood 7:8f38e85705ba 172 sequence[currentStep].setPitch(_pitch);
ryood 4:d9a72e07749f 173 isDirty = true;
ryood 4:d9a72e07749f 174 }
ryood 4:d9a72e07749f 175 Thread::wait(10);
ryood 3:8c8020dfd82f 176 }
ryood 3:8c8020dfd82f 177 }
ryood 3:8c8020dfd82f 178
ryood 4:d9a72e07749f 179 void pollingPots(void const *argument)
ryood 3:8c8020dfd82f 180 {
ryood 4:d9a72e07749f 181 unsigned short tmp;
ryood 4:d9a72e07749f 182
ryood 4:d9a72e07749f 183 while (true) {
ryood 4:d9a72e07749f 184 // pulse width
ryood 4:d9a72e07749f 185 tmp = Pots[0].read_u16() >> 9; // 7bit witdth
ryood 6:4e089888b809 186 if (tmp != (sequenceSender.getPulseWidth() >> 1)) {
ryood 6:4e089888b809 187 sequenceSender.setPulseWidth(tmp << 1);
ryood 4:d9a72e07749f 188 isDirty = true;
ryood 4:d9a72e07749f 189 }
ryood 4:d9a72e07749f 190 // filter envelope moduration
ryood 4:d9a72e07749f 191 tmp = Pots[1].read_u16() >> 9; // 7bit witdth
ryood 4:d9a72e07749f 192 if (tmp != Filter.envMod) {
ryood 4:d9a72e07749f 193 Filter.envMod = tmp;
ryood 4:d9a72e07749f 194 isDirty = true;
ryood 4:d9a72e07749f 195 }
ryood 4:d9a72e07749f 196 // tempo
ryood 4:d9a72e07749f 197 tmp = Pots[2].read_u16() >> 9; // 7bit witdth
ryood 4:d9a72e07749f 198 if (tmp != tempo) {
ryood 4:d9a72e07749f 199 tempo = tmp;
ryood 4:d9a72e07749f 200 isDirty = true;
ryood 4:d9a72e07749f 201 }
ryood 4:d9a72e07749f 202 // cutoff
ryood 4:d9a72e07749f 203 tmp = Pots[3].read_u16() >> 10; // 6bit witdth
ryood 4:d9a72e07749f 204 if (tmp != Filter.cutOff) {
ryood 4:d9a72e07749f 205 Filter.cutOff = tmp;
ryood 4:d9a72e07749f 206 isDirty = true;
ryood 4:d9a72e07749f 207 }
ryood 4:d9a72e07749f 208 // resonance
ryood 4:d9a72e07749f 209 tmp = Pots[4].read_u16() >> 10; // 6bit witdth
ryood 4:d9a72e07749f 210 if (tmp != Filter.resonance) {
ryood 4:d9a72e07749f 211 Filter.resonance = tmp;
ryood 4:d9a72e07749f 212 isDirty = true;
ryood 4:d9a72e07749f 213 }
ryood 4:d9a72e07749f 214 Thread::wait(20);
ryood 4:d9a72e07749f 215 }
ryood 3:8c8020dfd82f 216 }
ryood 3:8c8020dfd82f 217
ryood 5:e4b68faa6801 218 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 219 // Main routine
ryood 5:e4b68faa6801 220 //------------------------------------------------------------------------
ryood 0:468e49a35876 221 int main()
ryood 0:468e49a35876 222 {
ryood 0:468e49a35876 223 printf("\n\n\r*** RTOS UI Test ***\r\n");
ryood 5:e4b68faa6801 224
ryood 5:e4b68faa6801 225 spiMaster.format(0, 8);
ryood 5:e4b68faa6801 226 spiMaster.frequency(SPI_RATE);
ryood 0:468e49a35876 227
ryood 0:468e49a35876 228 // Init devices
ryood 2:8cc6dff1d7fd 229 RotEnc1.setInterval(500);
ryood 2:8cc6dff1d7fd 230 RotEnc2.setInterval(500);
ryood 2:8cc6dff1d7fd 231
ryood 2:8cc6dff1d7fd 232 Pins[0].attach_asserted(&swOctaveUpPressed);
ryood 2:8cc6dff1d7fd 233 Pins[1].attach_asserted(&swOctaveDownPressed);
ryood 2:8cc6dff1d7fd 234 Pins[2].attach_asserted(&swNoteOnOffPressed);
ryood 2:8cc6dff1d7fd 235 Pins[3].attach_asserted(&swTiePressed);
ryood 2:8cc6dff1d7fd 236 Pins[4].attach_asserted(&swAccentPressed);
ryood 3:8c8020dfd82f 237 Pins[5].attach_asserted(&swRunStopPressed);
ryood 6:4e089888b809 238 Pins[6].attach_asserted(&swWaveShapePressed);
ryood 3:8c8020dfd82f 239 for (int i = 0; i < 7; i++) {
ryood 2:8cc6dff1d7fd 240 Pins[i].setAssertValue(0);
ryood 2:8cc6dff1d7fd 241 Pins[i].setSampleFrequency();
ryood 2:8cc6dff1d7fd 242 }
ryood 0:468e49a35876 243
ryood 0:468e49a35876 244 Lcd.init();
ryood 0:468e49a35876 245 Lcd.normalMode(); // normal colour mode
ryood 0:468e49a35876 246 Lcd.setBrightness(0.5); // put LED backlight on 50%
ryood 0:468e49a35876 247
ryood 2:8cc6dff1d7fd 248 // Thread start
ryood 4:d9a72e07749f 249 Thread thRotEnc(pollingRotEncs, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);
ryood 4:d9a72e07749f 250 Thread thPots(pollingPots, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);
ryood 5:e4b68faa6801 251
ryood 8:2c481dab525a 252 /*
ryood 5:e4b68faa6801 253 for (int i = 0; i < SEQUENCE_N; i++) {
ryood 5:e4b68faa6801 254 Sequence& seq = sequenceSender.getSequences()[i];
ryood 8:2c481dab525a 255 seq.setPitch(0);
ryood 5:e4b68faa6801 256 seq.setOctave(0);
ryood 5:e4b68faa6801 257 seq.tie = false;
ryood 5:e4b68faa6801 258 }
ryood 8:2c481dab525a 259 */
ryood 5:e4b68faa6801 260 sequenceSender.run(0);
ryood 0:468e49a35876 261
ryood 0:468e49a35876 262 // Main loop
ryood 0:468e49a35876 263 while (true) {
ryood 4:d9a72e07749f 264 CheckPin = !CheckPin;
ryood 0:468e49a35876 265 if (isDirty) {
ryood 2:8cc6dff1d7fd 266 updateLCD();
ryood 0:468e49a35876 267 isDirty = false;
ryood 0:468e49a35876 268 }
ryood 0:468e49a35876 269 }
ryood 0:468e49a35876 270 }