![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
This is an mbed platform port for the musical floppy system created by sammy1am https://github.com/SammyIAm/Moppy
main.cpp@0:e313e46f2b3d, 2015-10-10 (annotated)
- Committer:
- aallport
- Date:
- Sat Oct 10 23:09:34 2015 +0000
- Revision:
- 0:e313e46f2b3d
Works on led's; need to test on floppydrives
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
aallport | 0:e313e46f2b3d | 1 | #include "mbed.h" |
aallport | 0:e313e46f2b3d | 2 | #include <Ticker.h> |
aallport | 0:e313e46f2b3d | 3 | #include "MODSERIAL.h" |
aallport | 0:e313e46f2b3d | 4 | |
aallport | 0:e313e46f2b3d | 5 | bool firstRun = true; |
aallport | 0:e313e46f2b3d | 6 | const int FIRST_PIN = 2; |
aallport | 0:e313e46f2b3d | 7 | const int PIN_MAX=17; |
aallport | 0:e313e46f2b3d | 8 | //in the array |
aallport | 0:e313e46f2b3d | 9 | MODSERIAL pc(USBTX, USBRX); |
aallport | 0:e313e46f2b3d | 10 | #define RESOLUTION 0.0040 |
aallport | 0:e313e46f2b3d | 11 | DigitalOut MyLED(LED1); |
aallport | 0:e313e46f2b3d | 12 | Ticker tick_flip; |
aallport | 0:e313e46f2b3d | 13 | |
aallport | 0:e313e46f2b3d | 14 | |
aallport | 0:e313e46f2b3d | 15 | /*NOTE: Many of the arrays below contain unused indexes. This is |
aallport | 0:e313e46f2b3d | 16 | to prevent the Arduino from having to convert a pin input to an alternate |
aallport | 0:e313e46f2b3d | 17 | array index and save as many cycles as possible. In other words information |
aallport | 0:e313e46f2b3d | 18 | for pin 2 will be stored in index 2, and information for pin 4 will be |
aallport | 0:e313e46f2b3d | 19 | stored in index 4.*/ |
aallport | 0:e313e46f2b3d | 20 | |
aallport | 0:e313e46f2b3d | 21 | |
aallport | 0:e313e46f2b3d | 22 | /*An array of maximum track positions for each step-control pin. Even pins |
aallport | 0:e313e46f2b3d | 23 | are used for control, so only even numbers need a value here. 3.5" Floppies have |
aallport | 0:e313e46f2b3d | 24 | 80 tracks, 5.25" have 50. These should be doubled, because each tick is now |
aallport | 0:e313e46f2b3d | 25 | half a position (use 158 and 98). |
aallport | 0:e313e46f2b3d | 26 | */ |
aallport | 0:e313e46f2b3d | 27 | char MAX_POSITION[] = { |
aallport | 0:e313e46f2b3d | 28 | 0,0,158,0,158,0,158,0,158,0,158,0,158,0,158,0,158,0}; |
aallport | 0:e313e46f2b3d | 29 | |
aallport | 0:e313e46f2b3d | 30 | //Array to track the current position of each floppy head. (Only even indexes (i.e. 2,4,6...) are used) |
aallport | 0:e313e46f2b3d | 31 | char currentPosition[] = { |
aallport | 0:e313e46f2b3d | 32 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
aallport | 0:e313e46f2b3d | 33 | |
aallport | 0:e313e46f2b3d | 34 | /*Array to keep track of state of each pin. Even indexes track the control-pins for toggle purposes. Odd indexes |
aallport | 0:e313e46f2b3d | 35 | track direction-pins. LOW = forward, HIGH=reverse |
aallport | 0:e313e46f2b3d | 36 | */ |
aallport | 0:e313e46f2b3d | 37 | //go to line 52 |
aallport | 0:e313e46f2b3d | 38 | |
aallport | 0:e313e46f2b3d | 39 | //Current period assigned to each pin. 0 = off. Each period is of the length specified by the RESOLUTION |
aallport | 0:e313e46f2b3d | 40 | //variable above. i.e. A period of 10 is (RESOLUTION x 10) microseconds long. |
aallport | 0:e313e46f2b3d | 41 | unsigned int currentPeriod[] = { |
aallport | 0:e313e46f2b3d | 42 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
aallport | 0:e313e46f2b3d | 43 | }; |
aallport | 0:e313e46f2b3d | 44 | |
aallport | 0:e313e46f2b3d | 45 | //Current tick |
aallport | 0:e313e46f2b3d | 46 | unsigned int currentTick[] = { |
aallport | 0:e313e46f2b3d | 47 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
aallport | 0:e313e46f2b3d | 48 | }; |
aallport | 0:e313e46f2b3d | 49 | |
aallport | 0:e313e46f2b3d | 50 | |
aallport | 0:e313e46f2b3d | 51 | |
aallport | 0:e313e46f2b3d | 52 | DigitalOut currentState[]= { |
aallport | 0:e313e46f2b3d | 53 | LED3, |
aallport | 0:e313e46f2b3d | 54 | LED4, |
aallport | 0:e313e46f2b3d | 55 | p5,//S1 |
aallport | 0:e313e46f2b3d | 56 | p6,//D1 |
aallport | 0:e313e46f2b3d | 57 | p7,//S2 |
aallport | 0:e313e46f2b3d | 58 | p8,//D2 |
aallport | 0:e313e46f2b3d | 59 | p9,//S3 |
aallport | 0:e313e46f2b3d | 60 | p10,//D3 |
aallport | 0:e313e46f2b3d | 61 | p11,//S4 |
aallport | 0:e313e46f2b3d | 62 | p12,//D4 |
aallport | 0:e313e46f2b3d | 63 | p13,//S5 |
aallport | 0:e313e46f2b3d | 64 | p14,//D5 |
aallport | 0:e313e46f2b3d | 65 | p15,//S6 |
aallport | 0:e313e46f2b3d | 66 | p16,//D6 |
aallport | 0:e313e46f2b3d | 67 | p17,//S7 |
aallport | 0:e313e46f2b3d | 68 | p18,//D7 |
aallport | 0:e313e46f2b3d | 69 | p19,//S8 |
aallport | 0:e313e46f2b3d | 70 | p20,//S8 |
aallport | 0:e313e46f2b3d | 71 | }; |
aallport | 0:e313e46f2b3d | 72 | |
aallport | 0:e313e46f2b3d | 73 | void togglePin(unsigned char pin, unsigned char direction_pin) |
aallport | 0:e313e46f2b3d | 74 | { |
aallport | 0:e313e46f2b3d | 75 | |
aallport | 0:e313e46f2b3d | 76 | //Switch directions if end has been reached |
aallport | 0:e313e46f2b3d | 77 | if (currentPosition[pin] >= MAX_POSITION[pin]) { |
aallport | 0:e313e46f2b3d | 78 | currentState[direction_pin] = 1; |
aallport | 0:e313e46f2b3d | 79 | wait_us(2); |
aallport | 0:e313e46f2b3d | 80 | } else if (currentPosition[pin] <= 0) { |
aallport | 0:e313e46f2b3d | 81 | currentState[direction_pin] = 0; |
aallport | 0:e313e46f2b3d | 82 | wait_us(2); |
aallport | 0:e313e46f2b3d | 83 | } |
aallport | 0:e313e46f2b3d | 84 | |
aallport | 0:e313e46f2b3d | 85 | //Update currentPosition |
aallport | 0:e313e46f2b3d | 86 | if (currentState[direction_pin] == 1) { |
aallport | 0:e313e46f2b3d | 87 | currentPosition[pin]--; |
aallport | 0:e313e46f2b3d | 88 | } else { |
aallport | 0:e313e46f2b3d | 89 | currentPosition[pin]++; |
aallport | 0:e313e46f2b3d | 90 | } |
aallport | 0:e313e46f2b3d | 91 | |
aallport | 0:e313e46f2b3d | 92 | //Pulse the control pin |
aallport | 0:e313e46f2b3d | 93 | currentState[pin] = !currentState[pin]; |
aallport | 0:e313e46f2b3d | 94 | wait_us(2); |
aallport | 0:e313e46f2b3d | 95 | } |
aallport | 0:e313e46f2b3d | 96 | |
aallport | 0:e313e46f2b3d | 97 | void tick() |
aallport | 0:e313e46f2b3d | 98 | { |
aallport | 0:e313e46f2b3d | 99 | /* |
aallport | 0:e313e46f2b3d | 100 | If there is a period set for control pin 2, count the number of |
aallport | 0:e313e46f2b3d | 101 | ticks that pass, and toggle the pin if the current period is reached. |
aallport | 0:e313e46f2b3d | 102 | */ |
aallport | 0:e313e46f2b3d | 103 | if (currentPeriod[2]>0) { |
aallport | 0:e313e46f2b3d | 104 | currentTick[2]++; |
aallport | 0:e313e46f2b3d | 105 | if (currentTick[2] >= currentPeriod[2]) { |
aallport | 0:e313e46f2b3d | 106 | togglePin(2,3); |
aallport | 0:e313e46f2b3d | 107 | currentTick[2]=0; |
aallport | 0:e313e46f2b3d | 108 | } |
aallport | 0:e313e46f2b3d | 109 | } |
aallport | 0:e313e46f2b3d | 110 | if (currentPeriod[4]>0) { |
aallport | 0:e313e46f2b3d | 111 | currentTick[4]++; |
aallport | 0:e313e46f2b3d | 112 | if (currentTick[4] >= currentPeriod[4]) { |
aallport | 0:e313e46f2b3d | 113 | togglePin(4,5); |
aallport | 0:e313e46f2b3d | 114 | currentTick[4]=0; |
aallport | 0:e313e46f2b3d | 115 | } |
aallport | 0:e313e46f2b3d | 116 | } |
aallport | 0:e313e46f2b3d | 117 | if (currentPeriod[6]>0) { |
aallport | 0:e313e46f2b3d | 118 | currentTick[6]++; |
aallport | 0:e313e46f2b3d | 119 | if (currentTick[6] >= currentPeriod[6]) { |
aallport | 0:e313e46f2b3d | 120 | togglePin(6,7); |
aallport | 0:e313e46f2b3d | 121 | currentTick[6]=0; |
aallport | 0:e313e46f2b3d | 122 | } |
aallport | 0:e313e46f2b3d | 123 | } |
aallport | 0:e313e46f2b3d | 124 | if (currentPeriod[8]>0) { |
aallport | 0:e313e46f2b3d | 125 | currentTick[8]++; |
aallport | 0:e313e46f2b3d | 126 | if (currentTick[8] >= currentPeriod[8]) { |
aallport | 0:e313e46f2b3d | 127 | togglePin(8,9); |
aallport | 0:e313e46f2b3d | 128 | currentTick[8]=0; |
aallport | 0:e313e46f2b3d | 129 | } |
aallport | 0:e313e46f2b3d | 130 | } |
aallport | 0:e313e46f2b3d | 131 | if (currentPeriod[10]>0) { |
aallport | 0:e313e46f2b3d | 132 | currentTick[10]++; |
aallport | 0:e313e46f2b3d | 133 | if (currentTick[10] >= currentPeriod[10]) { |
aallport | 0:e313e46f2b3d | 134 | togglePin(10,11); |
aallport | 0:e313e46f2b3d | 135 | currentTick[10]=0; |
aallport | 0:e313e46f2b3d | 136 | } |
aallport | 0:e313e46f2b3d | 137 | } |
aallport | 0:e313e46f2b3d | 138 | if (currentPeriod[12]>0) { |
aallport | 0:e313e46f2b3d | 139 | currentTick[12]++; |
aallport | 0:e313e46f2b3d | 140 | if (currentTick[12] >= currentPeriod[12]) { |
aallport | 0:e313e46f2b3d | 141 | togglePin(12,13); |
aallport | 0:e313e46f2b3d | 142 | currentTick[12]=0; |
aallport | 0:e313e46f2b3d | 143 | } |
aallport | 0:e313e46f2b3d | 144 | } |
aallport | 0:e313e46f2b3d | 145 | if (currentPeriod[14]>0) { |
aallport | 0:e313e46f2b3d | 146 | currentTick[14]++; |
aallport | 0:e313e46f2b3d | 147 | if (currentTick[14] >= currentPeriod[14]) { |
aallport | 0:e313e46f2b3d | 148 | togglePin(14,15); |
aallport | 0:e313e46f2b3d | 149 | currentTick[14]=0; |
aallport | 0:e313e46f2b3d | 150 | } |
aallport | 0:e313e46f2b3d | 151 | } |
aallport | 0:e313e46f2b3d | 152 | if (currentPeriod[16]>0) { |
aallport | 0:e313e46f2b3d | 153 | currentTick[16]++; |
aallport | 0:e313e46f2b3d | 154 | if (currentTick[16] >= currentPeriod[16]) { |
aallport | 0:e313e46f2b3d | 155 | togglePin(16,17); |
aallport | 0:e313e46f2b3d | 156 | currentTick[16]=0; |
aallport | 0:e313e46f2b3d | 157 | } |
aallport | 0:e313e46f2b3d | 158 | } |
aallport | 0:e313e46f2b3d | 159 | |
aallport | 0:e313e46f2b3d | 160 | } |
aallport | 0:e313e46f2b3d | 161 | |
aallport | 0:e313e46f2b3d | 162 | |
aallport | 0:e313e46f2b3d | 163 | // |
aallport | 0:e313e46f2b3d | 164 | //// UTILITY FUNCTIONS |
aallport | 0:e313e46f2b3d | 165 | // |
aallport | 0:e313e46f2b3d | 166 | |
aallport | 0:e313e46f2b3d | 167 | //Not used now, but good for debugging... |
aallport | 0:e313e46f2b3d | 168 | void blinkLED() |
aallport | 0:e313e46f2b3d | 169 | { |
aallport | 0:e313e46f2b3d | 170 | MyLED = 1; // set the LED on |
aallport | 0:e313e46f2b3d | 171 | wait(0.25); // wait for a second |
aallport | 0:e313e46f2b3d | 172 | MyLED = 0; |
aallport | 0:e313e46f2b3d | 173 | } |
aallport | 0:e313e46f2b3d | 174 | |
aallport | 0:e313e46f2b3d | 175 | //For a given controller pin, runs the read-head all the way back to 0 |
aallport | 0:e313e46f2b3d | 176 | void reset(unsigned char pin) |
aallport | 0:e313e46f2b3d | 177 | { |
aallport | 0:e313e46f2b3d | 178 | currentState[pin+1] = 1; // Go in reverse |
aallport | 0:e313e46f2b3d | 179 | wait_us(2); |
aallport | 0:e313e46f2b3d | 180 | for (unsigned char s = 0; s < MAX_POSITION[pin]; s+= 2) { //Half max because we're stepping directly (no toggle) |
aallport | 0:e313e46f2b3d | 181 | currentState[pin]=1; |
aallport | 0:e313e46f2b3d | 182 | wait_us(2); |
aallport | 0:e313e46f2b3d | 183 | currentState[pin]=0; |
aallport | 0:e313e46f2b3d | 184 | wait_us(2); |
aallport | 0:e313e46f2b3d | 185 | } |
aallport | 0:e313e46f2b3d | 186 | currentPosition[pin] = 0; // We're reset. |
aallport | 0:e313e46f2b3d | 187 | currentState[pin+1]=0; |
aallport | 0:e313e46f2b3d | 188 | wait_us(2); |
aallport | 0:e313e46f2b3d | 189 | currentPosition[pin+1] = 0; // Ready to go forward. |
aallport | 0:e313e46f2b3d | 190 | } |
aallport | 0:e313e46f2b3d | 191 | |
aallport | 0:e313e46f2b3d | 192 | //Resets all the Pins |
aallport | 0:e313e46f2b3d | 193 | void resetAll() |
aallport | 0:e313e46f2b3d | 194 | { |
aallport | 0:e313e46f2b3d | 195 | |
aallport | 0:e313e46f2b3d | 196 | // Old one-at-a-time reset |
aallport | 0:e313e46f2b3d | 197 | //for (byte p = FIRST_PIN;p< = PIN_MAX;p+ = 2){ |
aallport | 0:e313e46f2b3d | 198 | // reset(p); |
aallport | 0:e313e46f2b3d | 199 | //} |
aallport | 0:e313e46f2b3d | 200 | |
aallport | 0:e313e46f2b3d | 201 | //Stop all notes (don't want to be playing during/after reset) |
aallport | 0:e313e46f2b3d | 202 | for (int p=FIRST_PIN; p<=PIN_MAX; p+=2) { |
aallport | 0:e313e46f2b3d | 203 | currentPeriod[p]=0; // Stop playing notes |
aallport | 0:e313e46f2b3d | 204 | } |
aallport | 0:e313e46f2b3d | 205 | |
aallport | 0:e313e46f2b3d | 206 | // New all-at-once reset |
aallport | 0:e313e46f2b3d | 207 | for (int s=0; s<80 ; s++) { // For max drive's position |
aallport | 0:e313e46f2b3d | 208 | for (int p=FIRST_PIN; p<=PIN_MAX; p+=2) { |
aallport | 0:e313e46f2b3d | 209 | currentState[p+1]=1; // Go in reverse |
aallport | 0:e313e46f2b3d | 210 | wait_us(2); |
aallport | 0:e313e46f2b3d | 211 | currentState[p]=1; |
aallport | 0:e313e46f2b3d | 212 | wait_us(2); |
aallport | 0:e313e46f2b3d | 213 | currentState[p]=0; |
aallport | 0:e313e46f2b3d | 214 | wait_us(2); |
aallport | 0:e313e46f2b3d | 215 | } |
aallport | 0:e313e46f2b3d | 216 | } |
aallport | 0:e313e46f2b3d | 217 | |
aallport | 0:e313e46f2b3d | 218 | for (unsigned char p = FIRST_PIN; p <= PIN_MAX; p+= 2) { |
aallport | 0:e313e46f2b3d | 219 | currentPosition[p] = 0; // We're reset. |
aallport | 0:e313e46f2b3d | 220 | currentState[p+1] = 0; // Ready to go forward. |
aallport | 0:e313e46f2b3d | 221 | wait_us(2); |
aallport | 0:e313e46f2b3d | 222 | } |
aallport | 0:e313e46f2b3d | 223 | } |
aallport | 0:e313e46f2b3d | 224 | |
aallport | 0:e313e46f2b3d | 225 | int main() |
aallport | 0:e313e46f2b3d | 226 | { |
aallport | 0:e313e46f2b3d | 227 | tick_flip.attach(&tick,RESOLUTION); |
aallport | 0:e313e46f2b3d | 228 | //Setup Pins (Even-odd pairs for step control and direction |
aallport | 0:e313e46f2b3d | 229 | /* |
aallport | 0:e313e46f2b3d | 230 | pinMode(LED1, OUTPUT);// Pin 13 has an LED connected on most Arduino boards |
aallport | 0:e313e46f2b3d | 231 | pinMode(5, OUTPUT); // Step control 1 |
aallport | 0:e313e46f2b3d | 232 | pinMode(6, OUTPUT); // Direction 1 |
aallport | 0:e313e46f2b3d | 233 | pinMode(7, OUTPUT); // Step control 2 |
aallport | 0:e313e46f2b3d | 234 | pinMode(8, OUTPUT); // Direction 2 |
aallport | 0:e313e46f2b3d | 235 | pinMode(9, OUTPUT); // Step control 3 |
aallport | 0:e313e46f2b3d | 236 | pinMode(10, OUTPUT); // Direction 3 |
aallport | 0:e313e46f2b3d | 237 | pinMode(11, OUTPUT); // Step control 4 |
aallport | 0:e313e46f2b3d | 238 | pinMode(12, OUTPUT); // Direction 4 |
aallport | 0:e313e46f2b3d | 239 | pinMode(13, OUTPUT); // Step control 5 |
aallport | 0:e313e46f2b3d | 240 | pinMode(14, OUTPUT); // Direction 5 |
aallport | 0:e313e46f2b3d | 241 | pinMode(15, OUTPUT); // Step control 6 |
aallport | 0:e313e46f2b3d | 242 | pinMode(16, OUTPUT); // Direction 6 |
aallport | 0:e313e46f2b3d | 243 | pinMode(17, OUTPUT); // Step control 7 |
aallport | 0:e313e46f2b3d | 244 | pinMode(18, OUTPUT); // Direction 7 |
aallport | 0:e313e46f2b3d | 245 | pinMode(19, OUTPUT); // Step control 8 |
aallport | 0:e313e46f2b3d | 246 | pinMode(20, OUTPUT); // Direction 8 |
aallport | 0:e313e46f2b3d | 247 | */ |
aallport | 0:e313e46f2b3d | 248 | resetAll(); |
aallport | 0:e313e46f2b3d | 249 | while(1) { |
aallport | 0:e313e46f2b3d | 250 | |
aallport | 0:e313e46f2b3d | 251 | //The first loop, reset all the drives, and wait 2 seconds... |
aallport | 0:e313e46f2b3d | 252 | if (firstRun) { |
aallport | 0:e313e46f2b3d | 253 | firstRun = false; |
aallport | 0:e313e46f2b3d | 254 | resetAll(); |
aallport | 0:e313e46f2b3d | 255 | wait(2); |
aallport | 0:e313e46f2b3d | 256 | } |
aallport | 0:e313e46f2b3d | 257 | |
aallport | 0:e313e46f2b3d | 258 | //Only read if we have |
aallport | 0:e313e46f2b3d | 259 | if (pc.rxBufferGetCount() > 2) { |
aallport | 0:e313e46f2b3d | 260 | char part0 = pc.getc(); |
aallport | 0:e313e46f2b3d | 261 | char part1 = pc.getc(); |
aallport | 0:e313e46f2b3d | 262 | char part2 = pc.getc(); |
aallport | 0:e313e46f2b3d | 263 | //Watch for special 100-message to reset the drives |
aallport | 0:e313e46f2b3d | 264 | if (part0 == 100) { |
aallport | 0:e313e46f2b3d | 265 | resetAll(); |
aallport | 0:e313e46f2b3d | 266 | //Flush any remaining messages. |
aallport | 0:e313e46f2b3d | 267 | pc.rxBufferFlush(); |
aallport | 0:e313e46f2b3d | 268 | } else { |
aallport | 0:e313e46f2b3d | 269 | currentPeriod[part0] = (part1 << 8) | part2; |
aallport | 0:e313e46f2b3d | 270 | } |
aallport | 0:e313e46f2b3d | 271 | } |
aallport | 0:e313e46f2b3d | 272 | } |
aallport | 0:e313e46f2b3d | 273 | } |