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: mbed
Fork of STM32FMSynth by
main.cpp@6:9f8c8c3c111d, 2017-12-01 (annotated)
- Committer:
- davolfman
- Date:
- Fri Dec 01 22:48:48 2017 +0000
- Revision:
- 6:9f8c8c3c111d
- Parent:
- 5:ac5c4bd3ef4b
- Child:
- 7:b0cd74923bc6
Range correction on fastSin
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| davolfman | 0:b2f7400596ce | 1 | #include "mbed.h" | 
| davolfman | 3:83ac767f3a63 | 2 | #include "sintable.h" | 
| davolfman | 0:b2f7400596ce | 3 | |
| davolfman | 0:b2f7400596ce | 4 | AnalogOut DAC0(PA_4);//Not labeled in the docs for the f401, but seems to be for all | 
| davolfman | 0:b2f7400596ce | 5 | AnalogOut DAC1(PA_5); | 
| davolfman | 0:b2f7400596ce | 6 | |
| davolfman | 0:b2f7400596ce | 7 | AnalogIn ADC0(PA_0); | 
| davolfman | 0:b2f7400596ce | 8 | AnalogIn ADC1(PA_1); | 
| davolfman | 6:9f8c8c3c111d | 9 | //AnalogIn ADC2(PA_2);//these are the uart pins!! | 
| davolfman | 6:9f8c8c3c111d | 10 | //AnalogIn ADC3(PA_3);//these are the uart pins!! | 
| davolfman | 0:b2f7400596ce | 11 | //AnalogIn ADC4(PA_4);//we're using these for output | 
| davolfman | 0:b2f7400596ce | 12 | //AnalogIn ADC5(PA_5);//we're using these for output | 
| davolfman | 0:b2f7400596ce | 13 | AnalogIn ADC6(PA_6); | 
| davolfman | 0:b2f7400596ce | 14 | AnalogIn ADC7(PA_7); | 
| davolfman | 0:b2f7400596ce | 15 | //AnalogIn ADC8(PB_0);//lets leave the 2 we aren't using in a single port | 
| davolfman | 0:b2f7400596ce | 16 | //AnalogIn ADC9(PB_1);//that way we know there's not ADCs on one of them | 
| davolfman | 0:b2f7400596ce | 17 | AnalogIn ADC10(PC_0); | 
| davolfman | 0:b2f7400596ce | 18 | AnalogIn ADC11(PC_1); | 
| davolfman | 0:b2f7400596ce | 19 | AnalogIn ADC12(PC_2); | 
| davolfman | 0:b2f7400596ce | 20 | AnalogIn ADC13(PC_3); | 
| davolfman | 0:b2f7400596ce | 21 | AnalogIn ADC14(PC_4); | 
| davolfman | 0:b2f7400596ce | 22 | AnalogIn ADC15(PC_5); | 
| davolfman | 0:b2f7400596ce | 23 | |
| davolfman | 2:5454dee210ed | 24 | BusIn keyBank(PC_10, PC_11, PC_12, PC_13, PC_14, PC_15); | 
| davolfman | 2:5454dee210ed | 25 | BusOut keySelect(PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8); | 
| davolfman | 2:5454dee210ed | 26 | BusIn numerator(PA_8, PA_9, PA_10, PA_11); | 
| davolfman | 2:5454dee210ed | 27 | BusIn denominator(PA_12, PA_13, PA_14, PA_15); | 
| davolfman | 2:5454dee210ed | 28 | |
| davolfman | 0:b2f7400596ce | 29 | //Renaming ports | 
| davolfman | 0:b2f7400596ce | 30 | #define inVol ADC0 | 
| davolfman | 0:b2f7400596ce | 31 | #define inModAmt ADC1 | 
| davolfman | 0:b2f7400596ce | 32 | #define inCarA ADC6 | 
| davolfman | 0:b2f7400596ce | 33 | #define inCarD ADC7 | 
| davolfman | 0:b2f7400596ce | 34 | #define inCarS ADC10 | 
| davolfman | 0:b2f7400596ce | 35 | #define inCarR ADC11 | 
| davolfman | 0:b2f7400596ce | 36 | #define inModA ADC12 | 
| davolfman | 0:b2f7400596ce | 37 | #define inModD ADC13 | 
| davolfman | 0:b2f7400596ce | 38 | #define inModS ADC14 | 
| davolfman | 0:b2f7400596ce | 39 | #define inModR ADC15 | 
| davolfman | 0:b2f7400596ce | 40 | #define outMono DAC0 | 
| davolfman | 0:b2f7400596ce | 41 | |
| davolfman | 2:5454dee210ed | 42 | #define numKeys 49 | 
| davolfman | 1:f3350a372732 | 43 | #define PI M_PI | 
| davolfman | 0:b2f7400596ce | 44 | |
| davolfman | 4:1d2a699c95c7 | 45 | //constants | 
| davolfman | 4:1d2a699c95c7 | 46 | const int carrierIncrements[] = {107, 113, 120, 127, 135, 143, 151, 160, 170, | 
| davolfman | 4:1d2a699c95c7 | 47 | 180, 190, 202, 214, 227, 240, 254, 270, 286, 303, 321, 340, 360, 381, 404, | 
| davolfman | 4:1d2a699c95c7 | 48 | 428, 454, 481, 509, 540, 572, 606, 642, 680, 720, 763, 809, 857, 908, 962, | 
| davolfman | 4:1d2a699c95c7 | 49 | 1019, 1080, 1144, 1212, 1284, 1360, 1441, 1527, 1618, 1714}; | 
| davolfman | 1:f3350a372732 | 50 | const int attackLimit = (0x1 << 16) - 1; | 
| davolfman | 1:f3350a372732 | 51 | const int fixed2Pi = (int) ((2.0 * PI) * (0x1 << 16)); | 
| davolfman | 1:f3350a372732 | 52 | |
| davolfman | 0:b2f7400596ce | 53 | //non-constants | 
| davolfman | 1:f3350a372732 | 54 | //Most of these will be recalculated or reset on every input cycle of the main | 
| davolfman | 1:f3350a372732 | 55 | // loop, as appropriate | 
| davolfman | 0:b2f7400596ce | 56 | int FMmult; | 
| davolfman | 0:b2f7400596ce | 57 | int Volume; | 
| davolfman | 1:f3350a372732 | 58 | int modVol; | 
| davolfman | 1:f3350a372732 | 59 | int modAmpI; | 
| davolfman | 1:f3350a372732 | 60 | int carAmpS; | 
| davolfman | 2:5454dee210ed | 61 | //bool keysPressed[numKeys]; | 
| davolfman | 2:5454dee210ed | 62 | int64_t keyboard; | 
| davolfman | 0:b2f7400596ce | 63 | int carrierPhases[numKeys]; | 
| davolfman | 0:b2f7400596ce | 64 | int modulatorPhases[numKeys]; | 
| davolfman | 0:b2f7400596ce | 65 | short envelopeStatesC[numKeys]; | 
| davolfman | 0:b2f7400596ce | 66 | short envelopeStatesM[numKeys]; | 
| davolfman | 0:b2f7400596ce | 67 | int envelopeAmpsC[numKeys]; | 
| davolfman | 1:f3350a372732 | 68 | int envelopeAmpsM[numKeys]; | 
| davolfman | 1:f3350a372732 | 69 | |
| davolfman | 1:f3350a372732 | 70 | int modA; | 
| davolfman | 1:f3350a372732 | 71 | int modD; | 
| davolfman | 1:f3350a372732 | 72 | int modS; | 
| davolfman | 1:f3350a372732 | 73 | int modR; | 
| davolfman | 1:f3350a372732 | 74 | int carA; | 
| davolfman | 1:f3350a372732 | 75 | int carD; | 
| davolfman | 1:f3350a372732 | 76 | int carS; | 
| davolfman | 1:f3350a372732 | 77 | int carR; | 
| davolfman | 1:f3350a372732 | 78 | |
| davolfman | 1:f3350a372732 | 79 | int fastSin(const int phase){ | 
| davolfman | 5:ac5c4bd3ef4b | 80 | int index = (phase & 0x3ffc) >> 2; | 
| davolfman | 5:ac5c4bd3ef4b | 81 | int subindex = phase & 0x3; | 
| davolfman | 5:ac5c4bd3ef4b | 82 | int quadrant = (phase & 0xc000) >> 14; | 
| davolfman | 3:83ac767f3a63 | 83 | int sum = 0; | 
| davolfman | 5:ac5c4bd3ef4b | 84 | switch (quadrant) { | 
| davolfman | 5:ac5c4bd3ef4b | 85 | case 0: | 
| davolfman | 5:ac5c4bd3ef4b | 86 | sum += (4 - subindex) * sintable[index]; | 
| davolfman | 5:ac5c4bd3ef4b | 87 | sum += subindex * sintable[index+1]; | 
| davolfman | 5:ac5c4bd3ef4b | 88 | break; | 
| davolfman | 5:ac5c4bd3ef4b | 89 | case 1: | 
| davolfman | 6:9f8c8c3c111d | 90 | sum += (4 - subindex) * sintable[1+4095-index]; | 
| davolfman | 6:9f8c8c3c111d | 91 | sum += subindex * sintable[4095-index]; | 
| davolfman | 5:ac5c4bd3ef4b | 92 | break; | 
| davolfman | 5:ac5c4bd3ef4b | 93 | case 2: | 
| davolfman | 5:ac5c4bd3ef4b | 94 | sum -= (4 - subindex) * sintable[index]; | 
| davolfman | 5:ac5c4bd3ef4b | 95 | sum -= subindex * sintable[index+1]; | 
| davolfman | 5:ac5c4bd3ef4b | 96 | break; | 
| davolfman | 5:ac5c4bd3ef4b | 97 | case 3: | 
| davolfman | 6:9f8c8c3c111d | 98 | sum -= (4 - subindex) * sintable[1+4095-index]; | 
| davolfman | 6:9f8c8c3c111d | 99 | sum -= subindex * sintable[4095-index]; | 
| davolfman | 5:ac5c4bd3ef4b | 100 | break; | 
| davolfman | 5:ac5c4bd3ef4b | 101 | } | 
| davolfman | 3:83ac767f3a63 | 102 | sum = sum >> 2; | 
| davolfman | 3:83ac767f3a63 | 103 | |
| davolfman | 3:83ac767f3a63 | 104 | return sum; | 
| davolfman | 1:f3350a372732 | 105 | } | 
| davolfman | 0:b2f7400596ce | 106 | |
| davolfman | 1:f3350a372732 | 107 | void synthesize(){ | 
| davolfman | 1:f3350a372732 | 108 | carAmpS = 0; | 
| davolfman | 1:f3350a372732 | 109 | for(int i = 0; i < numKeys; ++i){ | 
| davolfman | 2:5454dee210ed | 110 | if(keyboard & (0x1 << i)){ | 
| davolfman | 1:f3350a372732 | 111 | if(envelopeStatesC[i] < 2) | 
| davolfman | 1:f3350a372732 | 112 | envelopeStatesC[i] = 4; | 
| davolfman | 1:f3350a372732 | 113 | if(envelopeStatesM[i] < 2) | 
| davolfman | 1:f3350a372732 | 114 | envelopeStatesM[i] = 4; | 
| davolfman | 1:f3350a372732 | 115 | |
| davolfman | 1:f3350a372732 | 116 | if(envelopeStatesC[i] == 4){ | 
| davolfman | 1:f3350a372732 | 117 | envelopeAmpsC[i] += carA; | 
| davolfman | 1:f3350a372732 | 118 | if(envelopeAmpsC[i] >= attackLimit){ | 
| davolfman | 1:f3350a372732 | 119 | envelopeAmpsC[i] = attackLimit; | 
| davolfman | 1:f3350a372732 | 120 | envelopeStatesC[i] = 3; | 
| davolfman | 1:f3350a372732 | 121 | } | 
| davolfman | 1:f3350a372732 | 122 | } | 
| davolfman | 1:f3350a372732 | 123 | |
| davolfman | 1:f3350a372732 | 124 | if(envelopeStatesM[i] == 4){ | 
| davolfman | 1:f3350a372732 | 125 | envelopeAmpsM[i] += modA; | 
| davolfman | 1:f3350a372732 | 126 | if(envelopeAmpsM[i] >= attackLimit){ | 
| davolfman | 1:f3350a372732 | 127 | envelopeAmpsM[i] = attackLimit; | 
| davolfman | 1:f3350a372732 | 128 | envelopeStatesM[i] = 3; | 
| davolfman | 1:f3350a372732 | 129 | } | 
| davolfman | 1:f3350a372732 | 130 | } | 
| davolfman | 1:f3350a372732 | 131 | |
| davolfman | 1:f3350a372732 | 132 | if(envelopeStatesC[i] == 3){ | 
| davolfman | 1:f3350a372732 | 133 | envelopeAmpsC[i] += carD; | 
| davolfman | 1:f3350a372732 | 134 | if(envelopeAmpsC[i] <= carS){ | 
| davolfman | 1:f3350a372732 | 135 | envelopeAmpsC[i] = carS; | 
| davolfman | 1:f3350a372732 | 136 | envelopeStatesC[i] = 2; | 
| davolfman | 1:f3350a372732 | 137 | } | 
| davolfman | 1:f3350a372732 | 138 | } | 
| davolfman | 1:f3350a372732 | 139 | |
| davolfman | 1:f3350a372732 | 140 | if(envelopeStatesM[i] == 3){ | 
| davolfman | 1:f3350a372732 | 141 | envelopeAmpsM[i] += modD; | 
| davolfman | 1:f3350a372732 | 142 | if(envelopeAmpsM[i] <= modS){ | 
| davolfman | 1:f3350a372732 | 143 | envelopeAmpsM[i] = modS; | 
| davolfman | 1:f3350a372732 | 144 | envelopeStatesM[i] = 2; | 
| davolfman | 1:f3350a372732 | 145 | } | 
| davolfman | 1:f3350a372732 | 146 | } | 
| davolfman | 1:f3350a372732 | 147 | }else{ | 
| davolfman | 1:f3350a372732 | 148 | if(envelopeStatesC[i] > 1) | 
| davolfman | 1:f3350a372732 | 149 | envelopeStatesC[i] = 1; | 
| davolfman | 1:f3350a372732 | 150 | if(envelopeStatesM[i] > 1) | 
| davolfman | 1:f3350a372732 | 151 | envelopeStatesM[i] = 1; | 
| davolfman | 1:f3350a372732 | 152 | |
| davolfman | 1:f3350a372732 | 153 | if(envelopeStatesC[i] == 1){ | 
| davolfman | 1:f3350a372732 | 154 | if(envelopeAmpsC[i] <= 0){ | 
| davolfman | 1:f3350a372732 | 155 | envelopeStatesC[i] = 0; | 
| davolfman | 1:f3350a372732 | 156 | envelopeAmpsC[i] = 0; | 
| davolfman | 1:f3350a372732 | 157 | }else{ | 
| davolfman | 1:f3350a372732 | 158 | envelopeAmpsC[i] -= carR; | 
| davolfman | 1:f3350a372732 | 159 | } | 
| davolfman | 1:f3350a372732 | 160 | } | 
| davolfman | 1:f3350a372732 | 161 | if(envelopeStatesM[i] == 1){ | 
| davolfman | 1:f3350a372732 | 162 | if(envelopeAmpsM[i] <= 0){ | 
| davolfman | 1:f3350a372732 | 163 | envelopeStatesM[i] = 0; | 
| davolfman | 1:f3350a372732 | 164 | envelopeAmpsM[i] = 0; | 
| davolfman | 1:f3350a372732 | 165 | }else{ | 
| davolfman | 1:f3350a372732 | 166 | envelopeAmpsM[i] -= modR; | 
| davolfman | 1:f3350a372732 | 167 | } | 
| davolfman | 1:f3350a372732 | 168 | } | 
| davolfman | 1:f3350a372732 | 169 | } | 
| davolfman | 1:f3350a372732 | 170 | |
| davolfman | 1:f3350a372732 | 171 | if(envelopeAmpsC[i] > 0){ | 
| davolfman | 1:f3350a372732 | 172 | modulatorPhases[i] += (Fmult * carrierIncrements[i]) >> 16; | 
| davolfman | 1:f3350a372732 | 173 | modAmpI = fastSin((((modulatorPhases[i] * envelopeAmpsM[i]) >> 16) | 
| davolfman | 1:f3350a372732 | 174 | * modVol) >> 16); | 
| davolfman | 1:f3350a372732 | 175 | carrierPhases[i] += ((carrierIncrements[i] + modAmpI) * fixed2pi) >> 16; | 
| davolfman | 1:f3350a372732 | 176 | carAmps += (fastSin(carrierPhases[i]) * envelopeAmpsC[i]) >> 16; | 
| davolfman | 1:f3350a372732 | 177 | } | 
| davolfman | 1:f3350a372732 | 178 | } | 
| davolfman | 1:f3350a372732 | 179 | outMono.write_u16(((carAmps / numKeys) * Volume) >> 16); | 
| davolfman | 1:f3350a372732 | 180 | } | 
| davolfman | 0:b2f7400596ce | 181 | |
| davolfman | 0:b2f7400596ce | 182 | |
| davolfman | 0:b2f7400596ce | 183 | int main() { | 
| davolfman | 2:5454dee210ed | 184 | int ratNumer; | 
| davolfman | 2:5454dee210ed | 185 | int ratDenom; | 
| davolfman | 2:5454dee210ed | 186 | |
| davolfman | 2:5454dee210ed | 187 | while(true){ | 
| davolfman | 2:5454dee210ed | 188 | ratNumer = 0xf & ~ numerator; | 
| davolfman | 2:5454dee210ed | 189 | ratDenom = 0xf & ~ denom; | 
| davolfman | 2:5454dee210ed | 190 | FMult = (ratNumer << 16) / ratDenom; | 
| davolfman | 2:5454dee210ed | 191 | |
| davolfman | 2:5454dee210ed | 192 | Volume = (int)inVol.read_u16(); | 
| davolfman | 2:5454dee210ed | 193 | modVol = (int)inModAmt.read_u16(); | 
| davolfman | 2:5454dee210ed | 194 | |
| davolfman | 2:5454dee210ed | 195 | carA = 0xffff / ((int)inCarA.read_u16()); | 
| davolfman | 2:5454dee210ed | 196 | carD = 0xffff / ((int)inCarD.read_u16()); | 
| davolfman | 2:5454dee210ed | 197 | carS = (int)inCarS.read_u16(); | 
| davolfman | 2:5454dee210ed | 198 | carR = 0xffff / ((int)inCarR.read_u16()); | 
| davolfman | 2:5454dee210ed | 199 | |
| davolfman | 2:5454dee210ed | 200 | modA = 0xffff / ((int)inModA.read_u16()); | 
| davolfman | 2:5454dee210ed | 201 | modD = 0xffff / ((int)inModD.read_u16()); | 
| davolfman | 2:5454dee210ed | 202 | modS = (int)inModS.read_u16(); | 
| davolfman | 2:5454dee210ed | 203 | modR = 0xffff / ((int)inModR.read_u16()); | 
| davolfman | 2:5454dee210ed | 204 | |
| davolfman | 2:5454dee210ed | 205 | |
| davolfman | 2:5454dee210ed | 206 | } | 
| davolfman | 0:b2f7400596ce | 207 | } | 
