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@6:4e089888b809, 2016-06-12 (annotated)
- 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?
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 | 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 | } |