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:
Tue Jun 21 08:41:11 2016 +0000
Revision:
10:28082577ed5f
Parent:
9:06ba77ce8b3c
Child:
11:3aab82f74a75
DCO?CS?D9????AverageAnalogIn?????????

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