This is an mbed platform port for the musical floppy system created by sammy1am https://github.com/SammyIAm/Moppy

Dependencies:   MODSERIAL mbed

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?

UserRevisionLine numberNew 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 }