LEDWall.ino 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. #include <ESP32Lib.h>
  2. #define MINDURATION 10000
  3. #define MAXDURATION 15000
  4. #define LEDPin 2
  5. #define LED_X_PIXELS 25
  6. #define LED_Y_PIXELS 20
  7. #define LEADER_PIXELS 0 // unused pixels at the beginning
  8. SerialLED gfx;
  9. #define STATUS 23 // We've started!
  10. #define seedPin 21 // an unused pin to see the RNG
  11. unsigned char frame[LED_X_PIXELS][LED_Y_PIXELS][3];
  12. unsigned char difference[LED_X_PIXELS][LED_Y_PIXELS];
  13. /* Animation Functions */
  14. /*
  15. void cycle(int delaytime); // cycle all pixels through red, green, then blue
  16. void chasePixel(int delaytime, unsigned char r = 255, unsigned char g = 255, unsigned char b = 255); // pixel left to right, up and down the display
  17. void fillAndClear(int delaytime, unsigned char r = 255, unsigned char g = 255, unsigned char b = 255); // Fill and then empty
  18. void mrsparky(unsigned long duration, int delaytime = 0); // chaos, unless there's a
  19. void squares(int count, int delaytime, bool dir); // squares - dir == true means from the inside out
  20. */
  21. /* Helper functions */
  22. void printFrame(); // display whatever's in the frame
  23. void oneColor(unsigned char r, unsigned char g, unsigned char b); //set all to one color
  24. void setup() {
  25. Serial.begin(115200);
  26. ota_setup(); // Initialize WiFi and OTA
  27. //gfx.setGamma(2.8f, 2.8f, 2.8f); // R, G, B gamma correction?
  28. gfx.init(LEDPin, LED_X_PIXELS * LED_Y_PIXELS + LEADER_PIXELS, -1, -1);
  29. Serial.println("Testing pixelMap:");
  30. for (int y = LED_Y_PIXELS - 1; y >= 0; y--) {
  31. Serial.print("Row "); Serial.print(y); Serial.print(": ");
  32. for (int x = 0; x < LED_X_PIXELS; x++) {
  33. Serial.print(pixelMap(x, y)); Serial.print(" ");
  34. }
  35. Serial.println("");
  36. }
  37. oneColor(0, 0, 0);
  38. printFrame();
  39. randomSeed(analogRead(seedPin));
  40. pinMode(STATUS, OUTPUT);
  41. digitalWrite(STATUS, HIGH);
  42. }
  43. void loop() {
  44. vTaskDelay(10); // feed the other tasks
  45. switch (random(0, 100)) {
  46. case 0:
  47. Serial.println("Cycle...");
  48. cycle(random(1,10));
  49. break;
  50. case 1:
  51. Serial.println("Chase Pixel...");
  52. chasePixel(random(1,5), darkrandColor(), darkrandColor(), darkrandColor());
  53. break;
  54. case 2:
  55. Serial.println("Fill and Clear...");
  56. fillAndClear(random(1,5), darkrandColor(), darkrandColor(), darkrandColor());
  57. break;
  58. case 3:
  59. Serial.println("Mr. Sparky...");
  60. mrsparky(random(MINDURATION,MAXDURATION), 0);
  61. break;
  62. case 4:
  63. Serial.println("Mr. Sparky with delay (aka discoteque)...");
  64. mrsparky(random(MINDURATION,MAXDURATION), 100);
  65. break;
  66. case 5:
  67. Serial.println("Mr. Sparky with even longer delay (aka 50s?)...");
  68. mrsparky(random(MINDURATION,MAXDURATION), 750);
  69. break;
  70. case 6:
  71. Serial.println("Squares, inside out...");
  72. squares(random(MINDURATION,MAXDURATION), random(0, 100), random(2, 6), true);
  73. break;
  74. case 7:
  75. Serial.println("Squares, outside in...");
  76. squares(random(MINDURATION,MAXDURATION), random(0, 100), random(2, 6), false);
  77. break;
  78. case 8:
  79. Serial.println("Wormin...");
  80. worm(random(MINDURATION,MAXDURATION), random(10,70));
  81. break;
  82. case 9:
  83. Serial.println("Crazy Worms!");
  84. crazyworm(random(MINDURATION,MAXDURATION), random(10,70));
  85. break;
  86. case 10:
  87. Serial.println("Fading Worm...");
  88. fadeworm(random(MINDURATION,MAXDURATION), random(10,70), (unsigned char) random(1,10));
  89. break;
  90. case 11:
  91. Serial.println("Starfall...");
  92. starfall(random(MINDURATION,MAXDURATION), random(10,50), (unsigned char) random(1,10), random(5, 20));
  93. break;
  94. case 12:
  95. Serial.println("Rainbowfall...");
  96. rainbowfall(random(MINDURATION,MAXDURATION), random(10,50), (unsigned char) random(1,10), random(5, 20));
  97. break;
  98. case 13:
  99. Serial.println("Random cycle...");
  100. randomcycle(random(MINDURATION,MAXDURATION), random(0, 7), random(500, 2000));
  101. break;
  102. case 14:
  103. Serial.println("Gradient cycle...");
  104. gradientcycle(random(MINDURATION,MAXDURATION), random(0, 7), random(500, 2000));
  105. break;
  106. case 15:
  107. Serial.println("Evo Shandor...");
  108. show_evo(500);
  109. break;
  110. default:
  111. Serial.println("Oops... no selection... that's NUMBERWANG!");
  112. }
  113. }
  114. unsigned char randColor() {
  115. // weighted to prefer the lower 128
  116. if (random(0, 1)) {
  117. return (unsigned char) random(0, 255);
  118. } else {
  119. return (unsigned char) random(0, 128);
  120. }
  121. }
  122. unsigned char darkrandColor() {
  123. // Weighted even more for lower numbers
  124. switch (random(1, 3)) {
  125. //case 0: return (unsigned char) random(0, 31);
  126. case 1: return (unsigned char) random(0, 63);
  127. case 2: return (unsigned char) random(0, 127);
  128. case 3: return (unsigned char) random(0, 255);
  129. }
  130. // shouldn't get here
  131. return (unsigned char) random(0, 255);
  132. }
  133. void mrsparky(unsigned long duration, int delaytime) {
  134. unsigned long starttime = millis();
  135. while (millis() - starttime < duration) {
  136. randFrame();
  137. printFrame();
  138. if (delaytime > 0) {
  139. delay(delaytime);
  140. }
  141. }
  142. }
  143. void fillAndClear(int delaytime, unsigned char r, unsigned char g, unsigned char b) {
  144. oneColor(0, 0, 0);
  145. printFrame();
  146. // fill with color
  147. for (int y = 0; y < LED_Y_PIXELS; y++) {
  148. for (int x = 0; x < LED_X_PIXELS; x++) {
  149. frame[x][y][0] = r;
  150. frame[x][y][1] = g;
  151. frame[x][y][2] = b;
  152. printFrame();
  153. delay(delaytime);
  154. }
  155. }
  156. // back to black
  157. for (int y = LED_Y_PIXELS - 1; y >= 0; y--) {
  158. for (int x = LED_X_PIXELS - 1; x >= 0; x--) {
  159. frame[x][y][0] = 0;
  160. frame[x][y][1] = 0;
  161. frame[x][y][2] = 0;
  162. printFrame();
  163. delay(delaytime);
  164. }
  165. }
  166. }
  167. void chasePixel(int delaytime, unsigned char r, unsigned char g, unsigned char b) {
  168. oneColor(0, 0, 0);
  169. printFrame();
  170. for (int y = 0; y < LED_Y_PIXELS; y++) {
  171. if (y % 2 == 0) {
  172. // even rows go left to right:
  173. for (int x = 0; x < LED_X_PIXELS; x++) {
  174. frame[x][y][0] = r;
  175. frame[x][y][1] = g;
  176. frame[x][y][2] = b;
  177. printFrame();
  178. delay(delaytime);
  179. oneColor(0, 0, 0);
  180. }
  181. } else {
  182. // odd rows go right to left
  183. for (int x = LED_X_PIXELS - 1; x >= 0; x--) {
  184. frame[x][y][0] = r;
  185. frame[x][y][1] = g;
  186. frame[x][y][2] = b;
  187. printFrame();
  188. delay(delaytime);
  189. oneColor(0, 0, 0);
  190. }
  191. }
  192. }
  193. for (int y = LED_Y_PIXELS - 1; y >= 0; y--) {
  194. if (y % 2 == 0) {
  195. // even rows go right to left:
  196. for (int x = LED_X_PIXELS - 1; x >= 0; x--) {
  197. frame[x][y][0] = r;
  198. frame[x][y][1] = g;
  199. frame[x][y][2] = b;
  200. printFrame();
  201. delay(delaytime);
  202. oneColor(0, 0, 0);
  203. }
  204. } else {
  205. // odd rows go left to right
  206. for (int x = 0; x < LED_X_PIXELS; x++) {
  207. frame[x][y][0] = r;
  208. frame[x][y][1] = g;
  209. frame[x][y][2] = b;
  210. printFrame();
  211. delay(delaytime);
  212. oneColor(0, 0, 0);
  213. }
  214. }
  215. }
  216. }
  217. void cycle(int delaytime) {
  218. // cycle all pixels through red, green, then blue
  219. for (unsigned char r = 0; r <= 254; r++) {
  220. oneColor(r, 0, 0);
  221. printFrame();
  222. delay(delaytime);
  223. }
  224. for (unsigned char r = 255; r > 0; r--) {
  225. oneColor(r, 0, 0);
  226. printFrame();
  227. delay(delaytime);
  228. }
  229. for (unsigned char g = 0; g <= 254; g++) {
  230. oneColor(0, g, 0);
  231. printFrame();
  232. delay(delaytime);
  233. }
  234. for (unsigned char g = 255; g > 0; g--) {
  235. oneColor(0, g, 0);
  236. printFrame();
  237. delay(delaytime);
  238. }
  239. for (unsigned char b = 0; b <= 254; b++) {
  240. oneColor(0, 0, b);
  241. printFrame();
  242. delay(delaytime);
  243. }
  244. for (unsigned char b = 255; b > 0; b--) {
  245. oneColor(0, 0, b);
  246. printFrame();
  247. delay(delaytime);
  248. }
  249. oneColor(0, 0, 0);
  250. printFrame();
  251. }
  252. void printFrame() {
  253. for (int l = 0; l < LEADER_PIXELS; l++) {
  254. // Turn any lead pixels off
  255. gfx.setLED(l, 0, 0, 0);
  256. }
  257. for (int x = 0; x < LED_X_PIXELS; x++) {
  258. for (int y = 0; y < LED_Y_PIXELS; y++) {
  259. //Serial.print("Setting pixel "); Serial.print(pixelMap(x, y));
  260. //Serial.print(" to R:"); Serial.print((int) frame[x][y][0]);
  261. //Serial.print(" G:"); Serial.print((int) frame[x][y][1]);
  262. //Serial.print(" B:"); Serial.println((int) frame[x][y][2]);
  263. gfx.setLED(pixelMap(x, y), frame[x][y][0], frame[x][y][1], frame[x][y][2]);
  264. }
  265. }
  266. }
  267. int pixelMap(int x, int y) {
  268. // Translates x and y into a pixel number
  269. // (0, 0) is bottom left, (LED_X_PIXELS-1, LED_Y_PIXELS-1) is top right)
  270. if (x < 0 || x >= LED_X_PIXELS || y < 0 || y >= LED_Y_PIXELS) {
  271. Serial.print("ERROR: Cannot map ("); Serial.print(x); Serial.print(","); Serial.print(y); Serial.println(") into wall map");
  272. return -1;
  273. }
  274. x = LED_X_PIXELS - x - 1; // x starts at bottom right, so invert. If x is at bottom left, comment this out.
  275. int pixel = y * LED_X_PIXELS;
  276. if (y % 2 == 0) {
  277. // even rows are added
  278. pixel += x;
  279. } else {
  280. // odd rows are subtracted from the next one
  281. pixel += LED_X_PIXELS - x - 1;
  282. }
  283. //assert(pixel < LED_X_PIXELS * LED_Y_PIXELS);
  284. return pixel + LEADER_PIXELS;
  285. }
  286. void oneColor(unsigned char r, unsigned char g, unsigned char b) {
  287. // Sets the frame to an initial design
  288. for (int x = 0; x < LED_X_PIXELS; x++) {
  289. for (int y = 0; y < LED_Y_PIXELS; y++) {
  290. frame[x][y][0] = r; // Red
  291. frame[x][y][1] = g; // Green
  292. frame[x][y][2] = b; // Blue
  293. }
  294. }
  295. }
  296. void randFrame() {
  297. // Generates a random frame
  298. for (int x = 0; x < LED_X_PIXELS; x++) {
  299. for (int y = 0; y < LED_Y_PIXELS; y++) {
  300. frame[x][y][0] = randColor(); // Red
  301. frame[x][y][1] = randColor(); // Green
  302. frame[x][y][2] = randColor(); // Blue
  303. }
  304. }
  305. }
  306. /* Does nto work at all:
  307. void Flames(int delaytime) {
  308. for(int y = 0; y < LED_Y_PIXELS; y++) {
  309. for(int x = 0; x < LED_X_PIXELS; x++) {
  310. int c = pixelMap(x,y);
  311. frame[x][y][0] = c;
  312. frame[x][y][1] = (c * c) / (255);
  313. frame[x][y][2] = (c * c) / (255 * 8);
  314. }
  315. }
  316. printFrame();
  317. delay(delaytime);
  318. for(int c = 0; c < 255; c++) {
  319. for(int y = 0; y < LED_Y_PIXELS; y++) {
  320. for(int x = 0; x < LED_X_PIXELS; x++) {
  321. if(frame[x][y][0] > 127) {
  322. // Big number, probably intensify
  323. if(random(0, 4) > 0) {
  324. // intensify!
  325. int diff = 255 - frame[x][y][0];
  326. frame[x][y][0] += random(0, diff);
  327. } else {
  328. // detensify!
  329. frame[x][y][0] -= random(0, 127);
  330. }
  331. } else {
  332. // small number, probably weaken
  333. // Big number, probably intensify
  334. if(random(0, 4) > 0) {
  335. // detensify!
  336. frame[x][y][0] -= random(0, frame[x][y][0]);
  337. } else {
  338. // intensify!
  339. frame[x][y][0] += random(0, 127);
  340. }
  341. }
  342. frame[x][y][1] = (frame[x][y][0] * frame[x][y][0]) / 255;
  343. frame[x][y][2] = (frame[x][y][0] * frame[x][y][0]) / (255 * 8);
  344. }
  345. }
  346. printFrame();
  347. delay(delaytime);
  348. }
  349. }
  350. */
  351. int maxSquares(void) {
  352. // returns the maximum number of squares that can be drawn.
  353. // Note that squares can be drawn "outside" of one dimension.
  354. int maxdim = min(LED_X_PIXELS, LED_Y_PIXELS);
  355. // on an odd number, inside square is 1x1
  356. return floor(maxdim / 2);
  357. }
  358. void drawSquare(int squareno, unsigned char r, unsigned char g, unsigned char b) {
  359. // draws the nth square, counting from 0 from the middle out
  360. if (squareno > maxSquares()) {
  361. return;
  362. }
  363. int center_x = floor((LED_X_PIXELS - 1) / 2);
  364. int center_width = LED_X_PIXELS % 2 == 0 ? 2 : 1; // odd numbers have a 1x1 center
  365. int center_y = floor((LED_Y_PIXELS - 1) / 2);
  366. int center_height = LED_Y_PIXELS % 2 == 0 ? 2 : 1;
  367. int x_left = center_x - squareno;
  368. int x_right = center_x + center_width + squareno - 1;
  369. int y_bottom = center_y - squareno;
  370. int y_top = center_y + center_height + squareno - 1;
  371. Serial.print("Dimensions: X_left: "); Serial.print(x_left);
  372. Serial.print("; X_Right: "); Serial.print(x_right);
  373. Serial.print("; Y_Bottom: "); Serial.print(y_bottom);
  374. Serial.print("; Y_top: "); Serial.print(y_top);
  375. Serial.print("; Center_x: "); Serial.print(center_x);
  376. Serial.print("; Center_y: "); Serial.print(center_y);
  377. Serial.print("; Center_Width: "); Serial.print(center_width);
  378. Serial.print("; Center_Height: "); Serial.println(center_height);
  379. // top and bottom lines
  380. for (int x = x_left; x <= x_right; x++) {
  381. if (x < 0 || x > LED_X_PIXELS - 1 || y_bottom < 0 || y_top > LED_Y_PIXELS - 1) {
  382. Serial.print(" Skipping: ("); Serial.print(x);
  383. continue;
  384. }
  385. frame[x][y_bottom][0] = r;
  386. frame[x][y_bottom][1] = g;
  387. frame[x][y_bottom][2] = b;
  388. frame[x][y_top][0] = r;
  389. frame[x][y_top][1] = g;
  390. frame[x][y_top][2] = b;
  391. }
  392. // left and right lines
  393. for (int y = y_bottom; y <= y_top; y++) {
  394. if (x_left < 0 || x_right > LED_X_PIXELS - 1 || y < 0 || y > LED_Y_PIXELS - 1) {
  395. continue;
  396. }
  397. frame[x_left][y][0] = r;
  398. frame[x_left][y][1] = g;
  399. frame[x_left][y][2] = b;
  400. frame[x_right][y][0] = r;
  401. frame[x_right][y][1] = g;
  402. frame[x_right][y][2] = b;
  403. }
  404. }
  405. void squares(unsigned long duration, int delaytime, int numsquares, bool dir) {
  406. unsigned long starttime = millis();
  407. numsquares += 2; // 2 black squares
  408. oneColor(0, 0, 0);
  409. // draws squares moving out
  410. unsigned char colors[255][3];
  411. colors[0][0] = 0; //black makes the motion clearer
  412. colors[0][1] = 0;
  413. colors[0][2] = 0;
  414. colors[1][0] = 0; //black makes the motion clearer
  415. colors[1][1] = 0;
  416. colors[1][2] = 0;
  417. for (int i = 2; i < numsquares; i++) {
  418. // assign random colors
  419. colors[i][0] = randColor();
  420. colors[i][1] = randColor();
  421. colors[i][2] = randColor();
  422. }
  423. if (dir) {
  424. // inside out
  425. for (int i = 0; millis() - starttime < duration; i--) {
  426. // draw each of the squares
  427. for (int squareno = 0; squareno < maxSquares(); squareno++) {
  428. Serial.println("--------------");
  429. Serial.print("Drawing Square: "); Serial.println(squareno);
  430. drawSquare(squareno, colors[(i + squareno) % numsquares][0], colors[(i + squareno) % numsquares][1], colors[(i + squareno) % numsquares][2]);
  431. }
  432. printFrame();
  433. delay(delaytime);
  434. }
  435. } else {
  436. for (int i = 0; millis() - starttime < duration; i++) {
  437. // draw each of the squares
  438. for (int squareno = 0; squareno < maxSquares(); squareno++) {
  439. Serial.println("--------------");
  440. Serial.print("Drawing Square: "); Serial.println(squareno);
  441. drawSquare(squareno, colors[(i + squareno) % numsquares][0], colors[(i + squareno) % numsquares][1], colors[(i + squareno) % numsquares][2]);
  442. }
  443. printFrame();
  444. delay(delaytime);
  445. }
  446. }
  447. }
  448. void worm(unsigned long duration, int delaytime) {
  449. unsigned long starttime = millis();
  450. int x = random(3, LED_X_PIXELS - 3);
  451. int y = random(3, LED_Y_PIXELS - 3);
  452. unsigned char color[3];
  453. color[0] = randColor();
  454. color[1] = randColor();
  455. color[2] = randColor();
  456. unsigned char trailcolor[3];
  457. trailcolor[0] = randColor();
  458. trailcolor[1] = randColor();
  459. trailcolor[2] = randColor();
  460. unsigned char bgcolor[3];
  461. bgcolor[0] = darkrandColor();
  462. bgcolor[1] = darkrandColor();
  463. bgcolor[2] = darkrandColor();
  464. oneColor(bgcolor[0], bgcolor[1], bgcolor[2]);
  465. printFrame();
  466. bool moved = false;
  467. int lastmove = -1;
  468. for (int step = 0; millis() - starttime < duration; step++) {
  469. frame[x][y][0] = color[0];
  470. frame[x][y][1] = color[1];
  471. frame[x][y][2] = color[2];
  472. printFrame();
  473. // it's going to bet the trail color next
  474. frame[x][y][0] = trailcolor[0];
  475. frame[x][y][1] = trailcolor[1];
  476. frame[x][y][2] = trailcolor[2];
  477. delay(delaytime);
  478. // move randomly
  479. moved = false;
  480. int move;
  481. while (moved == false) {
  482. move = random(0, 12);
  483. if (move > 3) {
  484. if (lastmove == 0) {
  485. // the odd case of this being our first move
  486. move = random(0, 3);
  487. }
  488. move = lastmove; //repeat the last move
  489. }
  490. switch (move) {
  491. case 0: // move up
  492. if (lastmove != 1 && y < LED_Y_PIXELS - 1) {
  493. lastmove = 0;
  494. y++;
  495. moved = true;
  496. }
  497. break;
  498. case 1: // move down
  499. if (lastmove != 0 && y > 0) {
  500. lastmove = 1;
  501. y--;
  502. moved = true;
  503. }
  504. break;
  505. case 2: // move right
  506. if (lastmove != 3 && x < LED_X_PIXELS - 1) {
  507. lastmove = 2;
  508. x++;
  509. moved = true;
  510. }
  511. break;
  512. case 3: // move left
  513. if (lastmove != 2 && x > 0) {
  514. lastmove = 3;
  515. x--;
  516. moved = true;
  517. }
  518. break;
  519. }
  520. }
  521. }
  522. }
  523. void crazyfadebyint(int factor) {
  524. for (int x = 0; x < LED_X_PIXELS; x++) {
  525. for (int y = 0; y < LED_Y_PIXELS; y++) {
  526. if (frame[x][y][0] > factor) {
  527. frame[x][y][0] -= factor;
  528. } else {
  529. frame[x][y][0] = 0;
  530. }
  531. if (frame[x][y][1] > factor) {
  532. frame[x][y][1] -= factor;
  533. } else {
  534. frame[x][y][1] = 0;
  535. }
  536. if (frame[x][y][2] > factor) {
  537. frame[x][y][2] -= factor;
  538. } else {
  539. frame[x][y][2] = 0;
  540. }
  541. }
  542. }
  543. }
  544. void crazyworm(unsigned long duration, int delaytime) {
  545. unsigned long starttime = millis();
  546. int x = random(3, LED_X_PIXELS - 3);
  547. int y = random(3, LED_Y_PIXELS - 3);
  548. unsigned char color[3];
  549. color[0] = randColor();
  550. color[1] = randColor();
  551. color[2] = randColor();
  552. oneColor(0, 0, 0);
  553. printFrame();
  554. bool moved = false;
  555. int lastmove = -1;
  556. for (int step = 0; millis() - starttime < duration; step++) {
  557. crazyfadebyint(-10);
  558. frame[x][y][0] = color[0];
  559. frame[x][y][1] = color[1];
  560. frame[x][y][2] = color[2];
  561. printFrame();
  562. delay(delaytime);
  563. // move randomly
  564. moved = false;
  565. int move;
  566. while (moved == false) {
  567. move = random(0, 12);
  568. if (move > 3) {
  569. if (lastmove == 0) {
  570. // the odd case of this being our first move
  571. move = random(0, 3);
  572. }
  573. move = lastmove; //repeat the last move
  574. }
  575. switch (move) {
  576. case 0: // move up
  577. if (lastmove != 1 && y < LED_Y_PIXELS - 1) {
  578. lastmove = 0;
  579. y++;
  580. moved = true;
  581. }
  582. break;
  583. case 1: // move down
  584. if (lastmove != 0 && y > 0) {
  585. lastmove = 1;
  586. y--;
  587. moved = true;
  588. }
  589. break;
  590. case 2: // move right
  591. if (lastmove != 3 && x < LED_X_PIXELS - 1) {
  592. lastmove = 2;
  593. x++;
  594. moved = true;
  595. }
  596. break;
  597. case 3: // move left
  598. if (lastmove != 2 && x > 0) {
  599. lastmove = 3;
  600. x--;
  601. moved = true;
  602. }
  603. break;
  604. }
  605. }
  606. }
  607. }
  608. void fadebyint(unsigned char factor) {
  609. for (int x = 0; x < LED_X_PIXELS; x++) {
  610. for (int y = 0; y < LED_Y_PIXELS; y++) {
  611. //Serial.print('Current R: ');
  612. //Serial.print(frame[x][y][0]);
  613. //Serial.print('Current G: ');
  614. //Serial.print(frame[x][y][1]);
  615. //Serial.print('Current B: ');
  616. //Serial.println(frame[x][y][2]);
  617. if (frame[x][y][0] > factor) {
  618. frame[x][y][0] -= factor;
  619. } else {
  620. frame[x][y][0] = 0;
  621. }
  622. if (frame[x][y][1] > factor) {
  623. frame[x][y][1] -= factor;
  624. } else {
  625. frame[x][y][1] = 0;
  626. }
  627. if (frame[x][y][2] > factor) {
  628. frame[x][y][2] -= factor;
  629. } else {
  630. frame[x][y][2] = 0;
  631. }
  632. //Serial.print('Faded R: ');
  633. //Serial.print(frame[x][y][0]);
  634. //Serial.print('Faded G: ');
  635. //Serial.print(frame[x][y][1]);
  636. //Serial.print('Faded B: ');
  637. //Serial.println(frame[x][y][2]);
  638. }
  639. }
  640. }
  641. void fadeworm(unsigned long duration, int delaytime, unsigned char fadefactor) {
  642. unsigned long starttime = millis();
  643. int x = random(3, LED_X_PIXELS - 3);
  644. int y = random(3, LED_Y_PIXELS - 3);
  645. unsigned char color[3];
  646. color[0] = randColor();
  647. color[1] = randColor();
  648. color[2] = randColor();
  649. oneColor(0, 0, 0);
  650. printFrame();
  651. bool moved = false;
  652. int lastmove = -1;
  653. for (int step = 0; millis() - starttime < duration; step++) {
  654. fadebyint(fadefactor);
  655. frame[x][y][0] = color[0];
  656. frame[x][y][1] = color[1];
  657. frame[x][y][2] = color[2];
  658. printFrame();
  659. delay(delaytime);
  660. // move randomly
  661. moved = false;
  662. int move;
  663. while (moved == false) {
  664. move = random(0, 12);
  665. if (move > 3) {
  666. if (lastmove == 0) {
  667. // the odd case of this being our first move
  668. move = random(0, 3);
  669. }
  670. move = lastmove; //repeat the last move
  671. }
  672. switch (move) {
  673. case 0: // move up
  674. if (lastmove != 1 && y < LED_Y_PIXELS - 1) {
  675. lastmove = 0;
  676. y++;
  677. moved = true;
  678. }
  679. break;
  680. case 1: // move down
  681. if (lastmove != 0 && y > 0) {
  682. lastmove = 1;
  683. y--;
  684. moved = true;
  685. }
  686. break;
  687. case 2: // move right
  688. if (lastmove != 3 && x < LED_X_PIXELS - 1) {
  689. lastmove = 2;
  690. x++;
  691. moved = true;
  692. }
  693. break;
  694. case 3: // move left
  695. if (lastmove != 2 && x > 0) {
  696. lastmove = 3;
  697. x--;
  698. moved = true;
  699. }
  700. break;
  701. }
  702. }
  703. }
  704. }
  705. int starfall(unsigned long duration, int delaytime, unsigned char fadefactor, int chance) {
  706. unsigned long starttime = millis();
  707. int pos[LED_X_PIXELS];
  708. unsigned char color[3];
  709. color[0] = randColor();
  710. color[1] = randColor();
  711. color[2] = randColor();
  712. oneColor(0, 0, 0);
  713. // initialize starting positions
  714. for (int p = 0; p < LED_X_PIXELS; p++) {
  715. if (random(0, 100) <= chance) {
  716. pos[p] = random(0, LED_Y_PIXELS);
  717. frame[p][pos[p]][0] = color[0];
  718. frame[p][pos[p]][1] = color[1];
  719. frame[p][pos[p]][2] = color[2];
  720. } else {
  721. pos[p] = -1;
  722. }
  723. }
  724. printFrame();
  725. for (int step = 0; millis() - starttime < duration; step++) {
  726. fadebyint(fadefactor);
  727. for (int p = 0; p < LED_X_PIXELS; p++) {
  728. if (pos[p] == 0) {
  729. //Serial.print("Position "); Serial.print(p); Serial.println(" hit bottom");
  730. pos[p] = -1; // it hit the bottom
  731. }
  732. if (pos[p] > 0) {
  733. //Serial.print("Position "); Serial.print(p); Serial.print(" dropping from "); Serial.println(pos[p]);
  734. pos[p]--; // drop down one
  735. frame[p][pos[p]][0] = color[0];
  736. frame[p][pos[p]][1] = color[1];
  737. frame[p][pos[p]][2] = color[2];
  738. }
  739. if (pos[p] == -1 && random(0, 100) <= chance) {
  740. // spawn a new one
  741. //Serial.print("Position "); Serial.print(p); Serial.println(" spawning.");
  742. pos[p] = LED_Y_PIXELS - 1;
  743. frame[p][pos[p]][0] = color[0];
  744. frame[p][pos[p]][1] = color[1];
  745. frame[p][pos[p]][2] = color[2];
  746. }
  747. }
  748. printFrame();
  749. delay(delaytime);
  750. }
  751. }
  752. int rainbowfall(unsigned long duration, int delaytime, unsigned char fadefactor, int chance) {
  753. unsigned long starttime = millis();
  754. int pos[LED_X_PIXELS];
  755. unsigned char colors[LED_X_PIXELS][3];
  756. oneColor(0, 0, 0);
  757. // initialize starting positions
  758. for (int p = 0; p < LED_X_PIXELS; p++) {
  759. if (random(0, 100) <= chance) {
  760. pos[p] = random(0, LED_Y_PIXELS);
  761. frame[p][pos[p]][0] = colors[p][0] = randColor();
  762. frame[p][pos[p]][1] = colors[p][1] = randColor();
  763. frame[p][pos[p]][2] = colors[p][2] = randColor();
  764. } else {
  765. pos[p] = -1;
  766. }
  767. }
  768. printFrame();
  769. for (int step = 0; millis() - starttime < duration; step++) {
  770. fadebyint(fadefactor);
  771. for (int p = 0; p < LED_X_PIXELS; p++) {
  772. if (pos[p] == 0) {
  773. //Serial.print("Position "); Serial.print(p); Serial.println(" hit bottom");
  774. pos[p] = -1; // it hit the bottom
  775. }
  776. if (pos[p] > 0) {
  777. //Serial.print("Position "); Serial.print(p); Serial.print(" dropping from "); Serial.println(pos[p]);
  778. pos[p]--; // drop down one
  779. frame[p][pos[p]][0] = colors[p][0];
  780. frame[p][pos[p]][1] = colors[p][1];
  781. frame[p][pos[p]][2] = colors[p][2];
  782. }
  783. if (pos[p] == -1 && random(0, 100) <= chance) {
  784. // spawn a new one
  785. //Serial.print("Position "); Serial.print(p); Serial.println(" spawning.");
  786. pos[p] = LED_Y_PIXELS - 1;
  787. frame[p][pos[p]][0] = colors[p][0] = randColor();
  788. frame[p][pos[p]][1] = colors[p][1] = randColor();
  789. frame[p][pos[p]][2] = colors[p][2] = randColor();
  790. }
  791. }
  792. printFrame();
  793. delay(delaytime);
  794. }
  795. }
  796. void randomcycle(unsigned long duration, int delaytime, int stepspercycle) {
  797. unsigned long starttime = millis();
  798. // start with random colors
  799. unsigned char colors[LED_X_PIXELS][LED_Y_PIXELS][3];
  800. for (int x = 0; x < LED_X_PIXELS; x++) {
  801. for (int y = 0; y < LED_Y_PIXELS; y++) {
  802. colors[x][y][0] = randColor();
  803. colors[x][y][1] = randColor();
  804. colors[x][y][2] = randColor();
  805. }
  806. }
  807. for (int step = 0; millis() - starttime < duration; step++) {
  808. float factor = 0.5 + 0.5 * sin( (2.0 * 3.14 * step / stepspercycle));
  809. //Serial.print("Factor = "); Serial.println(factor);
  810. for (int x = 0; x < LED_X_PIXELS; x++) {
  811. for (int y = 0; y < LED_Y_PIXELS; y++) {
  812. frame[x][y][0] = (unsigned char) floor(factor * colors[x][y][0]);
  813. frame[x][y][1] = (unsigned char) floor(factor * colors[x][y][1]);
  814. frame[x][y][2] = (unsigned char) floor(factor * colors[x][y][2]);
  815. }
  816. }
  817. printFrame();
  818. delay(delaytime);
  819. }
  820. }
  821. float distance(int x1, int x2, int y1, int y2) {
  822. return (float) sqrt( pow((x2 - x1), 2) + pow((y2 - y1), 2) );
  823. }
  824. void one_gradientcycle(int delaytime, int stepspercycle) {
  825. int c_x = random(0, LED_X_PIXELS);
  826. int c_y = random(0, LED_Y_PIXELS);
  827. unsigned char basecolor[3];
  828. basecolor[0] = randColor();
  829. basecolor[1] = randColor();
  830. basecolor[2] = randColor();
  831. float maxdistance = distance(c_x, 0, c_y, 0);
  832. unsigned char colors[LED_X_PIXELS][LED_Y_PIXELS][3];
  833. for (int x = 0; x < LED_X_PIXELS; x++) {
  834. for (int y = 0; y < LED_Y_PIXELS; y++) {
  835. float gradfactor = 0.5 + 0.5 * sin( 2.0 * 3.14 * distance(x, c_x, y, c_y) / maxdistance - 3.14/2);
  836. colors[x][y][0] = (unsigned char) floor(gradfactor * basecolor[0]);
  837. colors[x][y][1] = (unsigned char) floor(gradfactor * basecolor[1]);
  838. colors[x][y][2] = (unsigned char) floor(gradfactor * basecolor[2]);
  839. //Serial.print("Base color: "); Serial.print(colors[x][y][0]);
  840. //Serial.print("; Distance: "); Serial.print(distance(x,y));
  841. //Serial.print("; Factor: "); Serial.print(gradfactor);
  842. //Serial.print("; Setting color: "); Serial.println(colors[x][y][0]);
  843. }
  844. }
  845. for (int step = 0; step < stepspercycle; step++) {
  846. float factor = 0.5 + 0.5 * sin( -3.14/2 + (2.0 * 3.14 * step / stepspercycle));
  847. //Serial.print("Factor = "); Serial.println(factor);
  848. for (int x = 0; x < LED_X_PIXELS; x++) {
  849. for (int y = 0; y < LED_Y_PIXELS; y++) {
  850. frame[x][y][0] = (unsigned char) floor(factor * colors[x][y][0]);
  851. frame[x][y][1] = (unsigned char) floor(factor * colors[x][y][1]);
  852. frame[x][y][2] = (unsigned char) floor(factor * colors[x][y][2]);
  853. }
  854. }
  855. printFrame();
  856. delay(delaytime);
  857. }
  858. }
  859. void gradientcycle(unsigned long duration, int delaytime, int stepspercycle) {
  860. unsigned long starttime = millis();
  861. for(int step = 0; (millis() - starttime < duration) && (step % stepspercycle == 0); step++) {
  862. one_gradientcycle(delaytime, stepspercycle);
  863. }
  864. }
  865. /*
  866. * still not sure how to do this since we're not a square.
  867. void pilotsquare(int delaytime, int steps) {
  868. int center_x = floor((LED_X_PIXELS - 1) / 2);
  869. int center_width = LED_X_PIXELS % 2 == 0 ? 2 : 1; // odd numbers have a 1x1 center
  870. int center_y = floor((LED_Y_PIXELS - 1) / 2);
  871. int center_height = LED_Y_PIXELS % 2 == 0 ? 2 : 1;
  872. }
  873. */