Nucleo Sequencer of my Base Machine
Dependencies: Amp AverageAnalogIn Envelope FilterController Sequence BaseMachineComon mbed-rtos mbed
Fork of SpiSequenceSender_Test by
main.cpp@39:ed2704cdc7aa, 2016-10-10 (annotated)
- Committer:
- ryood
- Date:
- Mon Oct 10 05:36:04 2016 +0000
- Revision:
- 39:ed2704cdc7aa
- Parent:
- 38:820cb3a7102b
- Child:
- 40:fd75fb94898b
Remove: UI controll functions
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ryood | 15:9813d8eaf57e | 1 | /* |
ryood | 15:9813d8eaf57e | 2 | * main.cpp |
ryood | 15:9813d8eaf57e | 3 | * SpiSequencerSender_test |
ryood | 15:9813d8eaf57e | 4 | * |
ryood | 39:ed2704cdc7aa | 5 | * 2016.10.10 UIを分離 |
ryood | 15:9813d8eaf57e | 6 | * 2016.08.20 mbed Rev 121 / mbed-rtos Rev 117で動作確認 |
ryood | 15:9813d8eaf57e | 7 | * |
ryood | 15:9813d8eaf57e | 8 | */ |
ryood | 15:9813d8eaf57e | 9 | |
ryood | 0:21e39bc75e31 | 10 | #include "mbed.h" |
ryood | 5:4abac408b827 | 11 | #include "rtos.h" |
ryood | 39:ed2704cdc7aa | 12 | |
ryood | 0:21e39bc75e31 | 13 | |
ryood | 6:fc10eac60b91 | 14 | #define UART_TRACE (0) |
ryood | 6:fc10eac60b91 | 15 | #include "SpiSequenceSender.h" |
ryood | 9:3e4e08578e1c | 16 | #include "EnvelopeGenerator.h" |
ryood | 9:3e4e08578e1c | 17 | #include "SpiAmpController.h" |
ryood | 12:c248781608af | 18 | #include "SpiFilterController.h" |
ryood | 0:21e39bc75e31 | 19 | |
ryood | 16:b0419e3c9079 | 20 | #define TITLE_STR1 ("BaseMachine Sequencer") |
ryood | 39:ed2704cdc7aa | 21 | #define TITLE_STR2 ("20161010") |
ryood | 16:b0419e3c9079 | 22 | |
ryood | 6:fc10eac60b91 | 23 | #define SEQUENCE_N (16) |
ryood | 39:ed2704cdc7aa | 24 | #define SPI1_RATE (10000000) |
ryood | 39:ed2704cdc7aa | 25 | #define SPI2_RATE (3000000) // Actual frequency about 2.6MHz |
ryood | 39:ed2704cdc7aa | 26 | |
ryood | 39:ed2704cdc7aa | 27 | enum SequencerCmd { |
ryood | 39:ed2704cdc7aa | 28 | CMD_RCV_PLAYING_STEP = 0x01, |
ryood | 39:ed2704cdc7aa | 29 | CMD_RUN = 0x11, |
ryood | 39:ed2704cdc7aa | 30 | CMD_BPM = 0x12, |
ryood | 39:ed2704cdc7aa | 31 | CMD_ACCENT_LEVEL = 0x13, |
ryood | 39:ed2704cdc7aa | 32 | CMD_WAVE_SHAPE = 0x21, |
ryood | 39:ed2704cdc7aa | 33 | CMD_PULSE_WIDTH = 0x22, |
ryood | 39:ed2704cdc7aa | 34 | CMD_CUTOFF = 0x31, |
ryood | 39:ed2704cdc7aa | 35 | CMD_RESONANCE = 0x32, |
ryood | 39:ed2704cdc7aa | 36 | CMD_LEVEL = 0x41, |
ryood | 39:ed2704cdc7aa | 37 | CMD_DURATION = 0x42, |
ryood | 39:ed2704cdc7aa | 38 | CMD_DECAY = 0x43, |
ryood | 39:ed2704cdc7aa | 39 | CMD_SUSTAIN = 0x44, |
ryood | 39:ed2704cdc7aa | 40 | CMD_NOTE = 0x51, |
ryood | 39:ed2704cdc7aa | 41 | CMD_PITCH = 0x52, |
ryood | 39:ed2704cdc7aa | 42 | }; |
ryood | 0:21e39bc75e31 | 43 | |
ryood | 14:c173e03ee3ad | 44 | const int samplingPeriod = 1; // ms |
ryood | 10:fb04f9959fd9 | 45 | const int bpm = 120; |
ryood | 10:fb04f9959fd9 | 46 | const int envelopeLength = (60 * 1000 / (bpm * 4)) / samplingPeriod; |
ryood | 20:00d3b6ace8c7 | 47 | const int waveShape = SpiSequenceSender::WAVESHAPE_SQUARE; |
ryood | 20:00d3b6ace8c7 | 48 | const int baseNoteNumber = 36; |
ryood | 14:c173e03ee3ad | 49 | |
ryood | 14:c173e03ee3ad | 50 | // Initial Sequence |
ryood | 26:fbf48a178aeb | 51 | const int noteOn[SEQUENCE_N] = { 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 }; |
ryood | 26:fbf48a178aeb | 52 | const int pitch[SEQUENCE_N] = {36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36 }; |
ryood | 26:fbf48a178aeb | 53 | const int tie[SEQUENCE_N] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
ryood | 26:fbf48a178aeb | 54 | const int accent[SEQUENCE_N] = { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }; |
ryood | 10:fb04f9959fd9 | 55 | |
ryood | 16:b0419e3c9079 | 56 | // Devices |
ryood | 16:b0419e3c9079 | 57 | // |
ryood | 39:ed2704cdc7aa | 58 | //SPI1 (PinName mosi, PinName miso, PinName sclk, PinName ssel=NC) |
ryood | 39:ed2704cdc7aa | 59 | SPI SpiMaster(PA_7, PA_6, PA_5); |
ryood | 10:fb04f9959fd9 | 60 | |
ryood | 39:ed2704cdc7aa | 61 | //SPI2 (PinName mosi, PinName miso, PinName sclk, PinName ssel) |
ryood | 39:ed2704cdc7aa | 62 | SPISlave SpiSlave(PB_15, PB_14, PB_13, PB_12); |
ryood | 39:ed2704cdc7aa | 63 | DigitalOut StepChangePin(PB_1); |
ryood | 20:00d3b6ace8c7 | 64 | |
ryood | 39:ed2704cdc7aa | 65 | BusOut Leds(PA_0, PA_1, PA_4, PB_0, PC_1, PC_0, PA_10, PB_3); |
ryood | 34:602ee5e771e3 | 66 | |
ryood | 16:b0419e3c9079 | 67 | // Grobal Variables |
ryood | 16:b0419e3c9079 | 68 | // |
ryood | 16:b0419e3c9079 | 69 | Sequence sequences[SEQUENCE_N]; |
ryood | 39:ed2704cdc7aa | 70 | SpiSequenceSender sequenceSender(&SpiMaster, D9, sequences, SEQUENCE_N, samplingPeriod, bpm); |
ryood | 6:fc10eac60b91 | 71 | |
ryood | 10:fb04f9959fd9 | 72 | Envelope envelope(4095, envelopeLength, envelopeLength*3/4, envelopeLength/2, 2047); |
ryood | 9:3e4e08578e1c | 73 | EnvelopeGenerator envelopeGenerator; |
ryood | 39:ed2704cdc7aa | 74 | SpiAmpController ampController(&SpiMaster, D8, D7); |
ryood | 17:557658db3e81 | 75 | |
ryood | 39:ed2704cdc7aa | 76 | SpiFilterController filterController(&SpiMaster, D10); |
ryood | 16:b0419e3c9079 | 77 | |
ryood | 39:ed2704cdc7aa | 78 | int playingStep = 0; |
ryood | 39:ed2704cdc7aa | 79 | int editingStep = 0; |
ryood | 39:ed2704cdc7aa | 80 | bool isRunning = false; |
ryood | 16:b0419e3c9079 | 81 | |
ryood | 16:b0419e3c9079 | 82 | //------------------------------------------------------------------------ |
ryood | 16:b0419e3c9079 | 83 | // Callback functions |
ryood | 16:b0419e3c9079 | 84 | //------------------------------------------------------------------------ |
ryood | 35:0165b610796d | 85 | void updateTicks(int ticks) |
ryood | 8:de409197ff95 | 86 | { |
ryood | 8:de409197ff95 | 87 | if (ticks == 0) { |
ryood | 9:3e4e08578e1c | 88 | envelopeGenerator.init(envelope); |
ryood | 36:50ad7e0a9a95 | 89 | playingStep = sequenceSender.getStep(); |
ryood | 39:ed2704cdc7aa | 90 | // Masterにinterruptをかける。 |
ryood | 39:ed2704cdc7aa | 91 | StepChangePin.write(1); |
ryood | 39:ed2704cdc7aa | 92 | StepChangePin.write(0); |
ryood | 8:de409197ff95 | 93 | } |
ryood | 14:c173e03ee3ad | 94 | |
ryood | 27:c382689e652b | 95 | if (sequences[sequenceSender.getStep()].isNoteOn()) { |
ryood | 14:c173e03ee3ad | 96 | uint16_t level = envelopeGenerator.getModLevel(); |
ryood | 27:c382689e652b | 97 | if (!sequences[sequenceSender.getStep()].isAccent()) { |
ryood | 35:0165b610796d | 98 | level = level * 1 / 2; |
ryood | 27:c382689e652b | 99 | } |
ryood | 14:c173e03ee3ad | 100 | ampController.outDca(level); |
ryood | 14:c173e03ee3ad | 101 | } else { |
ryood | 14:c173e03ee3ad | 102 | ampController.outDca(0); |
ryood | 14:c173e03ee3ad | 103 | } |
ryood | 9:3e4e08578e1c | 104 | envelopeGenerator.update(); |
ryood | 12:c248781608af | 105 | |
ryood | 15:9813d8eaf57e | 106 | filterController.outDcf(); |
ryood | 8:de409197ff95 | 107 | } |
ryood | 8:de409197ff95 | 108 | |
ryood | 16:b0419e3c9079 | 109 | //------------------------------------------------------------------------ |
ryood | 16:b0419e3c9079 | 110 | // Functions |
ryood | 16:b0419e3c9079 | 111 | //------------------------------------------------------------------------ |
ryood | 20:00d3b6ace8c7 | 112 | |
ryood | 39:ed2704cdc7aa | 113 | void spiSlaveRecieve() |
ryood | 18:309f794eba74 | 114 | { |
ryood | 39:ed2704cdc7aa | 115 | if (SpiSlave.receive()) { |
ryood | 39:ed2704cdc7aa | 116 | SpiSlave.reply(playingStep); |
ryood | 39:ed2704cdc7aa | 117 | uint16_t recievedVal = SpiSlave.read(); |
ryood | 39:ed2704cdc7aa | 118 | uint8_t cmd = recievedVal >> 8; |
ryood | 39:ed2704cdc7aa | 119 | uint8_t data = recievedVal & 0xff; |
ryood | 39:ed2704cdc7aa | 120 | switch(cmd) { |
ryood | 39:ed2704cdc7aa | 121 | case CMD_RCV_PLAYING_STEP: |
ryood | 39:ed2704cdc7aa | 122 | // Do nothing |
ryood | 39:ed2704cdc7aa | 123 | break; |
ryood | 39:ed2704cdc7aa | 124 | case CMD_RUN: |
ryood | 39:ed2704cdc7aa | 125 | if (data == 0) { |
ryood | 39:ed2704cdc7aa | 126 | ampController.outDca(0); |
ryood | 39:ed2704cdc7aa | 127 | sequenceSender.stop(); |
ryood | 39:ed2704cdc7aa | 128 | isRunning = false; |
ryood | 39:ed2704cdc7aa | 129 | } |
ryood | 39:ed2704cdc7aa | 130 | else { |
ryood | 39:ed2704cdc7aa | 131 | sequenceSender.run(playingStep); |
ryood | 39:ed2704cdc7aa | 132 | isRunning = true; |
ryood | 39:ed2704cdc7aa | 133 | } |
ryood | 39:ed2704cdc7aa | 134 | break; |
ryood | 39:ed2704cdc7aa | 135 | case CMD_BPM: |
ryood | 39:ed2704cdc7aa | 136 | sequenceSender.setBpm(data); |
ryood | 39:ed2704cdc7aa | 137 | break; |
ryood | 39:ed2704cdc7aa | 138 | case CMD_ACCENT_LEVEL: |
ryood | 39:ed2704cdc7aa | 139 | // ToDo: Impl. accentLevel |
ryood | 39:ed2704cdc7aa | 140 | break; |
ryood | 39:ed2704cdc7aa | 141 | case CMD_WAVE_SHAPE: |
ryood | 39:ed2704cdc7aa | 142 | // ToDo: SequenceSender::WaveShapeとdataの値を合わせる。 |
ryood | 39:ed2704cdc7aa | 143 | Leds.write(data); |
ryood | 39:ed2704cdc7aa | 144 | if (data == 0) { |
ryood | 39:ed2704cdc7aa | 145 | sequenceSender.setWaveShape(SpiSequenceSender::WAVESHAPE_SQUARE); |
ryood | 39:ed2704cdc7aa | 146 | } |
ryood | 39:ed2704cdc7aa | 147 | else if (data == 1) { |
ryood | 39:ed2704cdc7aa | 148 | sequenceSender.setWaveShape(SpiSequenceSender::WAVESHAPE_SAW); |
ryood | 39:ed2704cdc7aa | 149 | } |
ryood | 39:ed2704cdc7aa | 150 | break; |
ryood | 39:ed2704cdc7aa | 151 | case CMD_PULSE_WIDTH: |
ryood | 39:ed2704cdc7aa | 152 | sequenceSender.setPulseWidth(data << 1); |
ryood | 39:ed2704cdc7aa | 153 | break; |
ryood | 39:ed2704cdc7aa | 154 | case CMD_CUTOFF: |
ryood | 39:ed2704cdc7aa | 155 | filterController.setCutoff(data << 1); |
ryood | 39:ed2704cdc7aa | 156 | break; |
ryood | 39:ed2704cdc7aa | 157 | case CMD_RESONANCE: |
ryood | 39:ed2704cdc7aa | 158 | filterController.setResonance(data << 1); |
ryood | 39:ed2704cdc7aa | 159 | break; |
ryood | 39:ed2704cdc7aa | 160 | case CMD_LEVEL: |
ryood | 39:ed2704cdc7aa | 161 | envelope.setLevel(data << 5); |
ryood | 39:ed2704cdc7aa | 162 | break; |
ryood | 39:ed2704cdc7aa | 163 | case CMD_DURATION: |
ryood | 39:ed2704cdc7aa | 164 | envelope.setDuration((float)data / 128.0f * envelopeLength); |
ryood | 39:ed2704cdc7aa | 165 | break; |
ryood | 39:ed2704cdc7aa | 166 | case CMD_DECAY: |
ryood | 39:ed2704cdc7aa | 167 | envelope.setDecay((float)data / 128.0f * envelopeLength); |
ryood | 39:ed2704cdc7aa | 168 | break; |
ryood | 39:ed2704cdc7aa | 169 | case CMD_SUSTAIN: |
ryood | 39:ed2704cdc7aa | 170 | envelope.setSustain(data << 5); |
ryood | 39:ed2704cdc7aa | 171 | break; |
ryood | 39:ed2704cdc7aa | 172 | case CMD_NOTE: |
ryood | 39:ed2704cdc7aa | 173 | editingStep = data >> 4; |
ryood | 39:ed2704cdc7aa | 174 | sequences[editingStep].setNoteOn(data & 0x01); |
ryood | 39:ed2704cdc7aa | 175 | sequences[editingStep].setTie((data & 0x02) >> 1); |
ryood | 39:ed2704cdc7aa | 176 | sequences[editingStep].setAccent((data & 0x04) >> 2); |
ryood | 39:ed2704cdc7aa | 177 | break; |
ryood | 39:ed2704cdc7aa | 178 | case CMD_PITCH: |
ryood | 39:ed2704cdc7aa | 179 | sequences[editingStep].setPitch(data); |
ryood | 39:ed2704cdc7aa | 180 | break; |
ryood | 39:ed2704cdc7aa | 181 | default: |
ryood | 39:ed2704cdc7aa | 182 | Leds.write(cmd); |
ryood | 39:ed2704cdc7aa | 183 | error("invalid SPI cmd"); |
ryood | 18:309f794eba74 | 184 | } |
ryood | 18:309f794eba74 | 185 | } |
ryood | 28:d8614d2b82f9 | 186 | } |
ryood | 28:d8614d2b82f9 | 187 | |
ryood | 16:b0419e3c9079 | 188 | //------------------------------------------------------------------------ |
ryood | 16:b0419e3c9079 | 189 | // Main routine |
ryood | 16:b0419e3c9079 | 190 | //------------------------------------------------------------------------ |
ryood | 0:21e39bc75e31 | 191 | int main() |
ryood | 0:21e39bc75e31 | 192 | { |
ryood | 18:309f794eba74 | 193 | #if (UART_TRACE) |
ryood | 18:309f794eba74 | 194 | printf("*** BaseMachine Sequencer ***\r\n"); |
ryood | 18:309f794eba74 | 195 | #endif |
ryood | 18:309f794eba74 | 196 | |
ryood | 39:ed2704cdc7aa | 197 | // Check LED |
ryood | 39:ed2704cdc7aa | 198 | for (int i = 0; i < 8; i++) { |
ryood | 39:ed2704cdc7aa | 199 | Leds[i].write(1); |
ryood | 39:ed2704cdc7aa | 200 | Thread::wait(500); |
ryood | 39:ed2704cdc7aa | 201 | } |
ryood | 39:ed2704cdc7aa | 202 | Leds.write(0x00); |
ryood | 39:ed2704cdc7aa | 203 | |
ryood | 24:040cdcb2ff14 | 204 | //-------------------------------------------------------------------- |
ryood | 16:b0419e3c9079 | 205 | // Setup Devices |
ryood | 16:b0419e3c9079 | 206 | // |
ryood | 39:ed2704cdc7aa | 207 | SpiMaster.format(8, 0); |
ryood | 39:ed2704cdc7aa | 208 | SpiMaster.frequency(SPI1_RATE); |
ryood | 39:ed2704cdc7aa | 209 | |
ryood | 39:ed2704cdc7aa | 210 | SpiSlave.format(16, 0); |
ryood | 39:ed2704cdc7aa | 211 | SpiSlave.frequency(SPI2_RATE); |
ryood | 0:21e39bc75e31 | 212 | |
ryood | 24:040cdcb2ff14 | 213 | // Mute output |
ryood | 24:040cdcb2ff14 | 214 | ampController.outDca(0); |
ryood | 24:040cdcb2ff14 | 215 | |
ryood | 24:040cdcb2ff14 | 216 | //-------------------------------------------------------------------- |
ryood | 22:82f1e7877f9f | 217 | // Initialize objects |
ryood | 0:21e39bc75e31 | 218 | // |
ryood | 15:9813d8eaf57e | 219 | Sequence::setBaseNoteNumber(baseNoteNumber); |
ryood | 14:c173e03ee3ad | 220 | |
ryood | 0:21e39bc75e31 | 221 | for (int i = 0; i < SEQUENCE_N; i++) { |
ryood | 0:21e39bc75e31 | 222 | Sequence& seq = sequenceSender.getSequences()[i]; |
ryood | 14:c173e03ee3ad | 223 | seq.setPitch(pitch[i]); |
ryood | 15:9813d8eaf57e | 224 | seq.setNoteOn(noteOn[i]); |
ryood | 15:9813d8eaf57e | 225 | seq.setTie(tie[i]); |
ryood | 26:fbf48a178aeb | 226 | seq.setAccent(accent[i]); |
ryood | 0:21e39bc75e31 | 227 | } |
ryood | 6:fc10eac60b91 | 228 | |
ryood | 9:3e4e08578e1c | 229 | envelopeGenerator.init(envelope); |
ryood | 12:c248781608af | 230 | |
ryood | 35:0165b610796d | 231 | sequenceSender.attachUpdate(&updateTicks); |
ryood | 14:c173e03ee3ad | 232 | sequenceSender.setWaveShape(waveShape); |
ryood | 5:4abac408b827 | 233 | |
ryood | 24:040cdcb2ff14 | 234 | //-------------------------------------------------------------------- |
ryood | 24:040cdcb2ff14 | 235 | // Main loop |
ryood | 24:040cdcb2ff14 | 236 | // |
ryood | 5:4abac408b827 | 237 | for (;;) { |
ryood | 39:ed2704cdc7aa | 238 | spiSlaveRecieve(); |
ryood | 5:4abac408b827 | 239 | } |
ryood | 39:ed2704cdc7aa | 240 | |
ryood | 0:21e39bc75e31 | 241 | } |