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:02:19 2016 +0000
Revision:
6:4e089888b809
Parent:
5:e4b68faa6801
Child:
7:8f38e85705ba
struct Oscillator???

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 5:e4b68faa6801 61 struct sSequence {
ryood 2:8cc6dff1d7fd 62 bool noteOn;
ryood 2:8cc6dff1d7fd 63 int octave;
ryood 2:8cc6dff1d7fd 64 int pitch;
ryood 2:8cc6dff1d7fd 65 bool tie;
ryood 2:8cc6dff1d7fd 66 bool accent;
ryood 5:e4b68faa6801 67 } sSequence[SEQUENCE_N];
ryood 2:8cc6dff1d7fd 68
ryood 4:d9a72e07749f 69 struct Filter {
ryood 4:d9a72e07749f 70 int cutOff;
ryood 4:d9a72e07749f 71 int resonance;
ryood 4:d9a72e07749f 72 int envMod;
ryood 4:d9a72e07749f 73 } Filter;
ryood 4:d9a72e07749f 74
ryood 3:8c8020dfd82f 75 int currentNote = 0;
ryood 4:d9a72e07749f 76 int tempo = 120;
ryood 3:8c8020dfd82f 77 bool isRunning = true;
ryood 3:8c8020dfd82f 78 bool isDirty = true;
ryood 2:8cc6dff1d7fd 79
ryood 5:e4b68faa6801 80 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 81 // Fuctions
ryood 5:e4b68faa6801 82 //------------------------------------------------------------------------
ryood 2:8cc6dff1d7fd 83 void updateLCD()
ryood 0:468e49a35876 84 {
ryood 0:468e49a35876 85 char buff[20];
ryood 0:468e49a35876 86
ryood 4:d9a72e07749f 87 //Lcd.clear();
ryood 4:d9a72e07749f 88 sprintf(buff, "Note#: %d ", currentNote);
ryood 4:d9a72e07749f 89 Lcd.printString(buff, 0, 0);
ryood 5:e4b68faa6801 90 sprintf(buff, "pitch: %d ", sSequence[currentNote].pitch);
ryood 0:468e49a35876 91 Lcd.printString(buff, 0, 1);
ryood 5:e4b68faa6801 92 sprintf(buff, "octave: %d " ,sSequence[currentNote].octave);
ryood 2:8cc6dff1d7fd 93 Lcd.printString(buff, 0, 2);
ryood 4:d9a72e07749f 94 sprintf(buff, "%1d %1d %1d %1d %3d",
ryood 5:e4b68faa6801 95 sSequence[currentNote].noteOn, sSequence[currentNote].tie, sSequence[currentNote].accent,
ryood 6:4e089888b809 96 isRunning, sequenceSender.getWaveShape());
ryood 2:8cc6dff1d7fd 97 Lcd.printString(buff, 0, 3);
ryood 6:4e089888b809 98 sprintf(buff, "%3d %3d %3d",
ryood 6:4e089888b809 99 sequenceSender.getPulseWidth(), Filter.envMod, tempo);
ryood 2:8cc6dff1d7fd 100 Lcd.printString(buff, 0, 4);
ryood 4:d9a72e07749f 101 sprintf(buff, "%3d %3d", Filter.cutOff, Filter.resonance);
ryood 4:d9a72e07749f 102 Lcd.printString(buff, 0, 5);
ryood 0:468e49a35876 103 Lcd.refresh();
ryood 0:468e49a35876 104 }
ryood 0:468e49a35876 105
ryood 5:e4b68faa6801 106 //------------------------------------------------------------------------
ryood 2:8cc6dff1d7fd 107 // CallBack routines
ryood 5:e4b68faa6801 108 //------------------------------------------------------------------------
ryood 2:8cc6dff1d7fd 109 void swOctaveUpPressed()
ryood 2:8cc6dff1d7fd 110 {
ryood 5:e4b68faa6801 111 sSequence[currentNote].octave++;
ryood 2:8cc6dff1d7fd 112 isDirty = true;
ryood 2:8cc6dff1d7fd 113 printf("swOctaveUpPressed\r\n");
ryood 2:8cc6dff1d7fd 114 }
ryood 2:8cc6dff1d7fd 115
ryood 2:8cc6dff1d7fd 116 void swOctaveDownPressed()
ryood 2:8cc6dff1d7fd 117 {
ryood 5:e4b68faa6801 118 sSequence[currentNote].octave--;
ryood 2:8cc6dff1d7fd 119 isDirty = true;
ryood 2:8cc6dff1d7fd 120 printf("swOctaveDownPressed\r\n");
ryood 2:8cc6dff1d7fd 121 }
ryood 2:8cc6dff1d7fd 122
ryood 2:8cc6dff1d7fd 123 void swNoteOnOffPressed()
ryood 2:8cc6dff1d7fd 124 {
ryood 5:e4b68faa6801 125 sSequence[currentNote].noteOn = !sSequence[currentNote].noteOn;
ryood 2:8cc6dff1d7fd 126 isDirty = true;
ryood 2:8cc6dff1d7fd 127 printf("swNoteOnOffPressed\r\n");
ryood 2:8cc6dff1d7fd 128 }
ryood 2:8cc6dff1d7fd 129
ryood 2:8cc6dff1d7fd 130 void swTiePressed()
ryood 2:8cc6dff1d7fd 131 {
ryood 5:e4b68faa6801 132 sSequence[currentNote].tie = !sSequence[currentNote].tie;
ryood 2:8cc6dff1d7fd 133 isDirty = true;
ryood 2:8cc6dff1d7fd 134 printf("swTiePressed\r\n");
ryood 2:8cc6dff1d7fd 135 }
ryood 2:8cc6dff1d7fd 136
ryood 2:8cc6dff1d7fd 137 void swAccentPressed()
ryood 2:8cc6dff1d7fd 138 {
ryood 5:e4b68faa6801 139 sSequence[currentNote].accent = !sSequence[currentNote].accent;
ryood 2:8cc6dff1d7fd 140 isDirty = true;
ryood 2:8cc6dff1d7fd 141 printf("swAccentPressed\r\n");
ryood 2:8cc6dff1d7fd 142 }
ryood 2:8cc6dff1d7fd 143
ryood 3:8c8020dfd82f 144 void swRunStopPressed()
ryood 3:8c8020dfd82f 145 {
ryood 3:8c8020dfd82f 146 isRunning = !isRunning;
ryood 3:8c8020dfd82f 147 isDirty = true;
ryood 3:8c8020dfd82f 148 printf("swRunStopPressed\r\n");
ryood 3:8c8020dfd82f 149 }
ryood 3:8c8020dfd82f 150
ryood 6:4e089888b809 151 void swWaveShapePressed()
ryood 3:8c8020dfd82f 152 {
ryood 6:4e089888b809 153 //Oscillator.waveShape++;
ryood 6:4e089888b809 154 uint8_t shape = sequenceSender.getWaveShape();
ryood 6:4e089888b809 155 shape++;
ryood 6:4e089888b809 156 if (shape == sequenceSender.WAVESHAPE_N) {
ryood 6:4e089888b809 157 shape = 0;
ryood 6:4e089888b809 158 }
ryood 6:4e089888b809 159 sequenceSender.setWaveShape(shape);
ryood 3:8c8020dfd82f 160 isDirty = true;
ryood 6:4e089888b809 161 printf("swWaveShapePressed\r\n");
ryood 3:8c8020dfd82f 162 }
ryood 3:8c8020dfd82f 163
ryood 5:e4b68faa6801 164 //------------------------------------------------------------------------
ryood 4:d9a72e07749f 165 // Thread
ryood 5:e4b68faa6801 166 //------------------------------------------------------------------------
ryood 4:d9a72e07749f 167 void pollingRotEncs(void const *argument)
ryood 3:8c8020dfd82f 168 {
ryood 4:d9a72e07749f 169 while (true) {
ryood 4:d9a72e07749f 170 int _note = RotEnc1.getVal();
ryood 4:d9a72e07749f 171 if (_note != currentNote) {
ryood 4:d9a72e07749f 172 currentNote = _note;
ryood 4:d9a72e07749f 173 isDirty = true;
ryood 4:d9a72e07749f 174 }
ryood 4:d9a72e07749f 175 int _pitch = RotEnc2.getVal();
ryood 5:e4b68faa6801 176 if (_pitch != sSequence[currentNote].pitch) {
ryood 5:e4b68faa6801 177 sSequence[currentNote].pitch = _pitch;
ryood 4:d9a72e07749f 178 isDirty = true;
ryood 4:d9a72e07749f 179 }
ryood 4:d9a72e07749f 180 Thread::wait(10);
ryood 3:8c8020dfd82f 181 }
ryood 3:8c8020dfd82f 182 }
ryood 3:8c8020dfd82f 183
ryood 4:d9a72e07749f 184 void pollingPots(void const *argument)
ryood 3:8c8020dfd82f 185 {
ryood 4:d9a72e07749f 186 unsigned short tmp;
ryood 4:d9a72e07749f 187
ryood 4:d9a72e07749f 188 while (true) {
ryood 4:d9a72e07749f 189 // pulse width
ryood 4:d9a72e07749f 190 tmp = Pots[0].read_u16() >> 9; // 7bit witdth
ryood 6:4e089888b809 191 if (tmp != (sequenceSender.getPulseWidth() >> 1)) {
ryood 6:4e089888b809 192 sequenceSender.setPulseWidth(tmp << 1);
ryood 4:d9a72e07749f 193 isDirty = true;
ryood 4:d9a72e07749f 194 }
ryood 4:d9a72e07749f 195 // filter envelope moduration
ryood 4:d9a72e07749f 196 tmp = Pots[1].read_u16() >> 9; // 7bit witdth
ryood 4:d9a72e07749f 197 if (tmp != Filter.envMod) {
ryood 4:d9a72e07749f 198 Filter.envMod = tmp;
ryood 4:d9a72e07749f 199 isDirty = true;
ryood 4:d9a72e07749f 200 }
ryood 4:d9a72e07749f 201 // tempo
ryood 4:d9a72e07749f 202 tmp = Pots[2].read_u16() >> 9; // 7bit witdth
ryood 4:d9a72e07749f 203 if (tmp != tempo) {
ryood 4:d9a72e07749f 204 tempo = tmp;
ryood 4:d9a72e07749f 205 isDirty = true;
ryood 4:d9a72e07749f 206 }
ryood 4:d9a72e07749f 207 // cutoff
ryood 4:d9a72e07749f 208 tmp = Pots[3].read_u16() >> 10; // 6bit witdth
ryood 4:d9a72e07749f 209 if (tmp != Filter.cutOff) {
ryood 4:d9a72e07749f 210 Filter.cutOff = tmp;
ryood 4:d9a72e07749f 211 isDirty = true;
ryood 4:d9a72e07749f 212 }
ryood 4:d9a72e07749f 213 // resonance
ryood 4:d9a72e07749f 214 tmp = Pots[4].read_u16() >> 10; // 6bit witdth
ryood 4:d9a72e07749f 215 if (tmp != Filter.resonance) {
ryood 4:d9a72e07749f 216 Filter.resonance = tmp;
ryood 4:d9a72e07749f 217 isDirty = true;
ryood 4:d9a72e07749f 218 }
ryood 4:d9a72e07749f 219 Thread::wait(20);
ryood 4:d9a72e07749f 220 }
ryood 3:8c8020dfd82f 221 }
ryood 3:8c8020dfd82f 222
ryood 5:e4b68faa6801 223 //------------------------------------------------------------------------
ryood 5:e4b68faa6801 224 // Main routine
ryood 5:e4b68faa6801 225 //------------------------------------------------------------------------
ryood 0:468e49a35876 226 int main()
ryood 0:468e49a35876 227 {
ryood 0:468e49a35876 228 printf("\n\n\r*** RTOS UI Test ***\r\n");
ryood 5:e4b68faa6801 229
ryood 5:e4b68faa6801 230 spiMaster.format(0, 8);
ryood 5:e4b68faa6801 231 spiMaster.frequency(SPI_RATE);
ryood 0:468e49a35876 232
ryood 0:468e49a35876 233 // Init devices
ryood 2:8cc6dff1d7fd 234 RotEnc1.setInterval(500);
ryood 2:8cc6dff1d7fd 235 RotEnc2.setInterval(500);
ryood 2:8cc6dff1d7fd 236
ryood 2:8cc6dff1d7fd 237 Pins[0].attach_asserted(&swOctaveUpPressed);
ryood 2:8cc6dff1d7fd 238 Pins[1].attach_asserted(&swOctaveDownPressed);
ryood 2:8cc6dff1d7fd 239 Pins[2].attach_asserted(&swNoteOnOffPressed);
ryood 2:8cc6dff1d7fd 240 Pins[3].attach_asserted(&swTiePressed);
ryood 2:8cc6dff1d7fd 241 Pins[4].attach_asserted(&swAccentPressed);
ryood 3:8c8020dfd82f 242 Pins[5].attach_asserted(&swRunStopPressed);
ryood 6:4e089888b809 243 Pins[6].attach_asserted(&swWaveShapePressed);
ryood 3:8c8020dfd82f 244 for (int i = 0; i < 7; i++) {
ryood 2:8cc6dff1d7fd 245 Pins[i].setAssertValue(0);
ryood 2:8cc6dff1d7fd 246 Pins[i].setSampleFrequency();
ryood 2:8cc6dff1d7fd 247 }
ryood 0:468e49a35876 248
ryood 0:468e49a35876 249 Lcd.init();
ryood 0:468e49a35876 250 Lcd.normalMode(); // normal colour mode
ryood 0:468e49a35876 251 Lcd.setBrightness(0.5); // put LED backlight on 50%
ryood 0:468e49a35876 252
ryood 2:8cc6dff1d7fd 253 // Thread start
ryood 4:d9a72e07749f 254 Thread thRotEnc(pollingRotEncs, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);
ryood 4:d9a72e07749f 255 Thread thPots(pollingPots, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);
ryood 5:e4b68faa6801 256
ryood 5:e4b68faa6801 257 for (int i = 0; i < SEQUENCE_N; i++) {
ryood 5:e4b68faa6801 258 Sequence& seq = sequenceSender.getSequences()[i];
ryood 6:4e089888b809 259 seq.setPitch(i);
ryood 5:e4b68faa6801 260 seq.setOctave(0);
ryood 5:e4b68faa6801 261 seq.tie = false;
ryood 5:e4b68faa6801 262 }
ryood 5:e4b68faa6801 263 sequenceSender.run(0);
ryood 0:468e49a35876 264
ryood 0:468e49a35876 265 // Main loop
ryood 0:468e49a35876 266 while (true) {
ryood 4:d9a72e07749f 267 CheckPin = !CheckPin;
ryood 0:468e49a35876 268 if (isDirty) {
ryood 2:8cc6dff1d7fd 269 updateLCD();
ryood 0:468e49a35876 270 isDirty = false;
ryood 0:468e49a35876 271 }
ryood 0:468e49a35876 272 }
ryood 0:468e49a35876 273 }