/** * I changed blink.pde and the cellular automaton pde for my needs. * The cellular automaton has 14 cells which state is generated by the function generate_ca(). * I use only cells 3-8 for sending its output signals to the relating pins where the speakers are connected. * The sounds are created by switching the pins on an off many times per second, so that I get a square wave * with a certain frequency for each pin. */ int cells[14]; // An array of 0s and 1s int generation; int step; int rules[]={0,1,1,1,1,1,1,0}; // An array to store the ruleset, for example {0,1,1,0,1,1,0,1} int outputs[]={0,0,0,0,0}; int b; void setup() // run once, when the sketch starts { for (int i=0; i<14; i++) { pinMode(i, OUTPUT); // sets the digital pin as output } initialize_ca(); } void loop() // run over and over again { // calculating the next step of the ca generate_ca(); // generating sounds for (int t=1; t<100; t++) { for (int i=3; i<9; i++) { if (t%((2^i))==0) { if (cells[i]==1) { if (outputs[i]==0) { digitalWrite(i, HIGH); outputs[i] = 1; } else { digitalWrite(i, LOW); outputs[i] = 0; } } } } delayMicroseconds(80); } for (int i=3; i<9; i++) { digitalWrite(i, LOW); } // pause delay(120); } void initialize_ca() { for (int i = 0; i < sizeof(cells); i++) { cells[i] = 0; } cells[9]=1; cells[6]=1; cells[11]=1; cells[12]=1; generation = 0; } // The process of creating the new generation void generate_ca() { // First we create an empty array for the new values int nextgen[sizeof(cells)]; int left; int me; int right; // For every spot, determine new state by examing current state, and neighbor states // Ignore edges that only have one neighor for (int i = 0; i < sizeof(cells); i++) { if (i!=0) { left = cells[i-1]; // Left neighbor state } else { left = cells[sizeof(cells)-1]; } me = cells[i]; // Current state if (i!=sizeof(cells)-1) { right = cells[i+1]; // Right neighbor state } else { right = cells[0]; } nextgen[i] = rule(left,me,right); // Compute next generation state based on ruleset } for (int i = 0; i < sizeof(cells); i++) { cells[i] = nextgen[i]; } } // Implementing the Wolfram rules // Could be improved and made more concise, but here we can explicitly see what is going on for each case int rule (int a, int b, int c) { if (a == 1 && b == 1 && c == 1) return rules[0]; if (a == 1 && b == 1 && c == 0) return rules[1]; if (a == 1 && b == 0 && c == 1) return rules[2]; if (a == 1 && b == 0 && c == 0) return rules[3]; if (a == 0 && b == 1 && c == 1) return rules[4]; if (a == 0 && b == 1 && c == 0) return rules[5]; if (a == 0 && b == 0 && c == 1) return rules[6]; if (a == 0 && b == 0 && c == 0) return rules[7]; return 0; }