Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: AverageAnalogIn N5110 Nucleo_rtos_UI_Test PinDetect RotaryEncoder Sequence mbed-rtos mbed FilterController
Fork of Nucleo_rtos_UI_Test by
main.cpp@7:8f38e85705ba, 2016-06-12 (annotated)
- Committer:
- ryood
- Date:
- Sun Jun 12 08:19:29 2016 +0000
- Revision:
- 7:8f38e85705ba
- Parent:
- 6:4e089888b809
- Child:
- 8:2c481dab525a
struct Sequence???
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 | 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 | 4:d9a72e07749f | 166 | isDirty = true; |
| ryood | 4:d9a72e07749f | 167 | } |
| ryood | 4:d9a72e07749f | 168 | int _pitch = RotEnc2.getVal(); |
| ryood | 7:8f38e85705ba | 169 | if (_pitch != sequence[currentStep].getPitch()) { |
| ryood | 7:8f38e85705ba | 170 | sequence[currentStep].setPitch(_pitch); |
| ryood | 4:d9a72e07749f | 171 | isDirty = true; |
| ryood | 4:d9a72e07749f | 172 | } |
| ryood | 4:d9a72e07749f | 173 | Thread::wait(10); |
| ryood | 3:8c8020dfd82f | 174 | } |
| ryood | 3:8c8020dfd82f | 175 | } |
| ryood | 3:8c8020dfd82f | 176 | |
| ryood | 4:d9a72e07749f | 177 | void pollingPots(void const *argument) |
| ryood | 3:8c8020dfd82f | 178 | { |
| ryood | 4:d9a72e07749f | 179 | unsigned short tmp; |
| ryood | 4:d9a72e07749f | 180 | |
| ryood | 4:d9a72e07749f | 181 | while (true) { |
| ryood | 4:d9a72e07749f | 182 | // pulse width |
| ryood | 4:d9a72e07749f | 183 | tmp = Pots[0].read_u16() >> 9; // 7bit witdth |
| ryood | 6:4e089888b809 | 184 | if (tmp != (sequenceSender.getPulseWidth() >> 1)) { |
| ryood | 6:4e089888b809 | 185 | sequenceSender.setPulseWidth(tmp << 1); |
| ryood | 4:d9a72e07749f | 186 | isDirty = true; |
| ryood | 4:d9a72e07749f | 187 | } |
| ryood | 4:d9a72e07749f | 188 | // filter envelope moduration |
| ryood | 4:d9a72e07749f | 189 | tmp = Pots[1].read_u16() >> 9; // 7bit witdth |
| ryood | 4:d9a72e07749f | 190 | if (tmp != Filter.envMod) { |
| ryood | 4:d9a72e07749f | 191 | Filter.envMod = tmp; |
| ryood | 4:d9a72e07749f | 192 | isDirty = true; |
| ryood | 4:d9a72e07749f | 193 | } |
| ryood | 4:d9a72e07749f | 194 | // tempo |
| ryood | 4:d9a72e07749f | 195 | tmp = Pots[2].read_u16() >> 9; // 7bit witdth |
| ryood | 4:d9a72e07749f | 196 | if (tmp != tempo) { |
| ryood | 4:d9a72e07749f | 197 | tempo = tmp; |
| ryood | 4:d9a72e07749f | 198 | isDirty = true; |
| ryood | 4:d9a72e07749f | 199 | } |
| ryood | 4:d9a72e07749f | 200 | // cutoff |
| ryood | 4:d9a72e07749f | 201 | tmp = Pots[3].read_u16() >> 10; // 6bit witdth |
| ryood | 4:d9a72e07749f | 202 | if (tmp != Filter.cutOff) { |
| ryood | 4:d9a72e07749f | 203 | Filter.cutOff = tmp; |
| ryood | 4:d9a72e07749f | 204 | isDirty = true; |
| ryood | 4:d9a72e07749f | 205 | } |
| ryood | 4:d9a72e07749f | 206 | // resonance |
| ryood | 4:d9a72e07749f | 207 | tmp = Pots[4].read_u16() >> 10; // 6bit witdth |
| ryood | 4:d9a72e07749f | 208 | if (tmp != Filter.resonance) { |
| ryood | 4:d9a72e07749f | 209 | Filter.resonance = tmp; |
| ryood | 4:d9a72e07749f | 210 | isDirty = true; |
| ryood | 4:d9a72e07749f | 211 | } |
| ryood | 4:d9a72e07749f | 212 | Thread::wait(20); |
| ryood | 4:d9a72e07749f | 213 | } |
| ryood | 3:8c8020dfd82f | 214 | } |
| ryood | 3:8c8020dfd82f | 215 | |
| ryood | 5:e4b68faa6801 | 216 | //------------------------------------------------------------------------ |
| ryood | 5:e4b68faa6801 | 217 | // Main routine |
| ryood | 5:e4b68faa6801 | 218 | //------------------------------------------------------------------------ |
| ryood | 0:468e49a35876 | 219 | int main() |
| ryood | 0:468e49a35876 | 220 | { |
| ryood | 0:468e49a35876 | 221 | printf("\n\n\r*** RTOS UI Test ***\r\n"); |
| ryood | 5:e4b68faa6801 | 222 | |
| ryood | 5:e4b68faa6801 | 223 | spiMaster.format(0, 8); |
| ryood | 5:e4b68faa6801 | 224 | spiMaster.frequency(SPI_RATE); |
| ryood | 0:468e49a35876 | 225 | |
| ryood | 0:468e49a35876 | 226 | // Init devices |
| ryood | 2:8cc6dff1d7fd | 227 | RotEnc1.setInterval(500); |
| ryood | 2:8cc6dff1d7fd | 228 | RotEnc2.setInterval(500); |
| ryood | 2:8cc6dff1d7fd | 229 | |
| ryood | 2:8cc6dff1d7fd | 230 | Pins[0].attach_asserted(&swOctaveUpPressed); |
| ryood | 2:8cc6dff1d7fd | 231 | Pins[1].attach_asserted(&swOctaveDownPressed); |
| ryood | 2:8cc6dff1d7fd | 232 | Pins[2].attach_asserted(&swNoteOnOffPressed); |
| ryood | 2:8cc6dff1d7fd | 233 | Pins[3].attach_asserted(&swTiePressed); |
| ryood | 2:8cc6dff1d7fd | 234 | Pins[4].attach_asserted(&swAccentPressed); |
| ryood | 3:8c8020dfd82f | 235 | Pins[5].attach_asserted(&swRunStopPressed); |
| ryood | 6:4e089888b809 | 236 | Pins[6].attach_asserted(&swWaveShapePressed); |
| ryood | 3:8c8020dfd82f | 237 | for (int i = 0; i < 7; i++) { |
| ryood | 2:8cc6dff1d7fd | 238 | Pins[i].setAssertValue(0); |
| ryood | 2:8cc6dff1d7fd | 239 | Pins[i].setSampleFrequency(); |
| ryood | 2:8cc6dff1d7fd | 240 | } |
| ryood | 0:468e49a35876 | 241 | |
| ryood | 0:468e49a35876 | 242 | Lcd.init(); |
| ryood | 0:468e49a35876 | 243 | Lcd.normalMode(); // normal colour mode |
| ryood | 0:468e49a35876 | 244 | Lcd.setBrightness(0.5); // put LED backlight on 50% |
| ryood | 0:468e49a35876 | 245 | |
| ryood | 2:8cc6dff1d7fd | 246 | // Thread start |
| ryood | 4:d9a72e07749f | 247 | Thread thRotEnc(pollingRotEncs, NULL, osPriorityNormal, DEFAULT_STACK_SIZE); |
| ryood | 4:d9a72e07749f | 248 | Thread thPots(pollingPots, NULL, osPriorityNormal, DEFAULT_STACK_SIZE); |
| ryood | 5:e4b68faa6801 | 249 | |
| ryood | 5:e4b68faa6801 | 250 | for (int i = 0; i < SEQUENCE_N; i++) { |
| ryood | 5:e4b68faa6801 | 251 | Sequence& seq = sequenceSender.getSequences()[i]; |
| ryood | 6:4e089888b809 | 252 | seq.setPitch(i); |
| ryood | 5:e4b68faa6801 | 253 | seq.setOctave(0); |
| ryood | 5:e4b68faa6801 | 254 | seq.tie = false; |
| ryood | 5:e4b68faa6801 | 255 | } |
| ryood | 5:e4b68faa6801 | 256 | sequenceSender.run(0); |
| ryood | 0:468e49a35876 | 257 | |
| ryood | 0:468e49a35876 | 258 | // Main loop |
| ryood | 0:468e49a35876 | 259 | while (true) { |
| ryood | 4:d9a72e07749f | 260 | CheckPin = !CheckPin; |
| ryood | 0:468e49a35876 | 261 | if (isDirty) { |
| ryood | 2:8cc6dff1d7fd | 262 | updateLCD(); |
| ryood | 0:468e49a35876 | 263 | isDirty = false; |
| ryood | 0:468e49a35876 | 264 | } |
| ryood | 0:468e49a35876 | 265 | } |
| ryood | 0:468e49a35876 | 266 | } |
