Nucleo SPI Sequencer
Dependencies: AverageAnalogIn N5110 Nucleo_rtos_UI_Test PinDetect RotaryEncoder Sequence mbed-rtos mbed FilterController
Fork of Nucleo_rtos_UI_Test by
main.cpp@9:06ba77ce8b3c, 2016-06-12 (annotated)
- Committer:
- ryood
- Date:
- Sun Jun 12 09:59:02 2016 +0000
- Revision:
- 9:06ba77ce8b3c
- Parent:
- 8:2c481dab525a
- Child:
- 10:28082577ed5f
BPM?Run/Stop???
Who changed what in which revision?
User | Revision | Line number | New 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 | 5:e4b68faa6801 | 31 | SpiSequenceSender sequenceSender(&spiMaster, D10, 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 | 0:468e49a35876 | 288 | if (isDirty) { |
ryood | 2:8cc6dff1d7fd | 289 | updateLCD(); |
ryood | 0:468e49a35876 | 290 | isDirty = false; |
ryood | 0:468e49a35876 | 291 | } |
ryood | 0:468e49a35876 | 292 | } |
ryood | 0:468e49a35876 | 293 | } |