Simple single-color 8x8x8 LED Cube with AVRs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. * main.c
  3. *
  4. * Copyright 2011 Thomas Buck <xythobuz@me.com>
  5. * Copyright 2011 Max Nuding <max.nuding@gmail.com>
  6. * Copyright 2011 Felix Bäder <baeder.felix@gmail.com>
  7. *
  8. * This file is part of LED-Cube.
  9. *
  10. * LED-Cube is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * LED-Cube is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with LED-Cube. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #ifndef F_CPU
  24. #define F_CPU 16000000L
  25. #endif
  26. #define OK 0x42
  27. #define ERROR 0x23
  28. #include <avr/io.h>
  29. #include <util/delay.h>
  30. #include <avr/interrupt.h>
  31. #include <avr/pgmspace.h>
  32. #include <stdint.h>
  33. #include <stdlib.h>
  34. #include "serial.h"
  35. #include "cube.h"
  36. #include "time.h"
  37. #include "audio.h"
  38. #include "mem.h"
  39. #include "memLayer.h"
  40. #include "twi.h"
  41. #include "strings.h"
  42. #define NOERROR 0
  43. // Audio does not answer
  44. #define AUDIOERROR 1
  45. // Memory does not answer
  46. #define MEMORYERROR 2
  47. // Memory not writeable
  48. #define MEMORYWRITEERROR 4
  49. // x = errorcode, e = error definition, not NOERROR
  50. #define ISERROR(x, e) ((x) & (e))
  51. void serialHandler(char c);
  52. void sendAudioData(void);
  53. void recieveAnimations(void);
  54. void transmitAnimations(void);
  55. uint8_t audioModeSelected(void);
  56. void setPixelBuffer(uint8_t x, uint8_t y, uint8_t z, uint8_t *buf);
  57. void setRow(uint8_t x, uint8_t z, uint8_t height, uint8_t *buf);
  58. void visualizeAudioData(uint8_t *audioData, uint8_t *imageData);
  59. #ifdef DEBUG
  60. void printErrors(uint8_t e);
  61. uint8_t selfTest(void);
  62. #include "snake.c"
  63. #endif
  64. uint8_t refreshAnimationCount = 1;
  65. uint8_t lastButtonState = 0;
  66. char buffer[11];
  67. uint8_t defaultImage[64] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  68. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  69. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  70. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  71. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  72. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  73. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  74. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  75. int main(void) {
  76. uint8_t *audioData = NULL;
  77. uint8_t *imageData = NULL;
  78. uint8_t i, length = 0, lastMode;
  79. uint16_t count;
  80. uint64_t lastChecked;
  81. initCube();
  82. serialInit(25, 8, NONE, 1);
  83. i2c_init();
  84. initSystemTimer();
  85. sei(); // Enable Interrupts
  86. DDRD = 0xFC; // Mosfets as Output
  87. DDRB = 0xFE;
  88. DDRC = 0xFF; // Latch Enable
  89. DDRA = 0xFF; // Latch Data
  90. setImage(defaultImage); // Display something
  91. #ifdef DEBUG
  92. // Kill animation counter in debug mode
  93. // => Don't preserve animations while power down
  94. setAnimationCount(0);
  95. i = selfTest();
  96. if (i) {
  97. serialWriteString(getString(1));
  98. serialWriteString(itoa(i, buffer, 2));
  99. serialWrite('\n');
  100. printErrors(i);
  101. }
  102. #endif
  103. #ifdef DEBUG
  104. serialWriteString(getString(2));
  105. serialWriteString(getString(0));
  106. serialWriteString("Took ");
  107. serialWriteString(itoa(getSystemTime(), buffer, 10));
  108. serialWriteString(" ms!\n");
  109. #endif
  110. lastMode = audioModeSelected();
  111. lastChecked = getSystemTime();
  112. i = 0;
  113. count = getAnimationCount();
  114. while (1) {
  115. if(lastMode) {
  116. // Get Audio Data and visualize it
  117. if (isFinished()) {
  118. audioData = getAudioData();
  119. if (audioData != NULL) {
  120. imageData = (uint8_t *)malloc(64);
  121. visualizeAudioData(audioData, imageData);
  122. setImage(imageData);
  123. free(imageData);
  124. free(audioData);
  125. }
  126. }
  127. } else {
  128. if (refreshAnimationCount) {
  129. // Get animation count stored in FRAM via TWI, if needed
  130. count = getAnimationCount();
  131. refreshAnimationCount = 0;
  132. i = 0;
  133. }
  134. if (count > 0) {
  135. if (isFinished() > length) {
  136. // Load next image
  137. if (i < (count - 1)) {
  138. i++;
  139. } else {
  140. i = 0;
  141. }
  142. imageData = getFrame(i);
  143. length = imageData[64];
  144. setImage(imageData);
  145. free(imageData);
  146. }
  147. }
  148. }
  149. if (serialHasChar()) {
  150. serialHandler((char)(serialGet()));
  151. }
  152. if ((getSystemTime() - lastChecked) > 150) {
  153. lastMode = audioModeSelected();
  154. lastChecked = getSystemTime();
  155. }
  156. }
  157. close();
  158. return 0;
  159. }
  160. #ifdef DEBUG
  161. uint8_t selfTest(void) {
  162. uint8_t result = NOERROR;
  163. uint8_t *data = getAudioData();
  164. if (data == NULL) {
  165. result |= AUDIOERROR;
  166. } else {
  167. free(data);
  168. }
  169. data = memGetBytes(0, 1);
  170. if (data == NULL) {
  171. result |= MEMORYERROR;
  172. } else {
  173. free(data);
  174. }
  175. setGeneralPurposeByte(0, 0x42);
  176. if (getGeneralPurposeByte(0) != 0x42) {
  177. result |= MEMORYWRITEERROR;
  178. }
  179. return result;
  180. }
  181. void printErrors(uint8_t e) {
  182. if (ISERROR(e, AUDIOERROR)) {
  183. serialWriteString(getString(3));
  184. }
  185. if (ISERROR(e, MEMORYERROR)) {
  186. serialWriteString(getString(4));
  187. }
  188. if (ISERROR(e, MEMORYWRITEERROR)) {
  189. serialWriteString(getString(5));
  190. }
  191. }
  192. #endif
  193. void serialHandler(char c) {
  194. // Used letters:
  195. // a, c, d, g, s, t, v, x
  196. uint8_t i, y, z;
  197. #ifdef DEBUG
  198. serialWrite(c);
  199. serialWriteString(": ");
  200. #endif
  201. switch(c) {
  202. case OK:
  203. serialWrite(OK);
  204. break;
  205. case 'h': case 'H': case '?':
  206. serialWriteString(getString(6));
  207. #ifdef DEBUG
  208. serialWriteString(getString(7));
  209. serialWriteString(getString(8));
  210. serialWriteString(getString(9));
  211. serialWriteString(getString(10));
  212. serialWriteString(getString(11));
  213. serialWriteString(getString(12));
  214. serialWriteString(getString(13));
  215. #endif
  216. break;
  217. case 'd': case 'D':
  218. clearMem();
  219. serialWrite(OK);
  220. break;
  221. case 'g': case 'G':
  222. transmitAnimations();
  223. break;
  224. case 's': case 'S':
  225. recieveAnimations();
  226. break;
  227. case 'v': case 'V':
  228. serialWriteString(getString(0));
  229. break;
  230. #ifdef DEBUG
  231. case 't': case 'T':
  232. serialWriteString(getString(14));
  233. serialWriteString(ltoa(getSystemTime(), buffer, 10));
  234. serialWriteString("ms");
  235. if (getSystemTime() > 1000) {
  236. serialWriteString(" (");
  237. serialWriteString(itoa(getSystemTime() / 1000, buffer, 10));
  238. itoa(getSystemTime() % 1000, buffer, 10);
  239. if (buffer[0] != '\0')
  240. serialWrite('.');
  241. if (buffer[2] == '\0')
  242. serialWrite('0');
  243. if (buffer[1] == '\0')
  244. serialWrite('0');
  245. if (buffer[0] != '\0')
  246. serialWriteString(buffer);
  247. serialWriteString("s)\n");
  248. } else {
  249. serialWrite('\n');
  250. }
  251. break;
  252. case 'a': case 'A':
  253. sendAudioData();
  254. break;
  255. case 'c': case 'C':
  256. serialWriteString(itoa(getAnimationCount(), buffer, 10));
  257. serialWriteString(getString(15));
  258. break;
  259. case 'x': case 'X':
  260. // Get byte, store as animation count
  261. serialWriteString(getString(16));
  262. while (!serialHasChar());
  263. c = serialGet();
  264. setAnimationCount(c);
  265. serialWriteString(itoa(c, buffer, 10));
  266. serialWriteString(getString(17));
  267. break;
  268. case 'y': case 'Y':
  269. setAnimationCount(0x2201);
  270. serialWriteString(getString(18));
  271. break;
  272. case 'e': case 'E':
  273. c = selfTest();
  274. serialWriteString(getString(19));
  275. serialWriteString(itoa(c, buffer, 2));
  276. serialWrite('\n');
  277. printErrors(c);
  278. break;
  279. case 'n': case 'N':
  280. snake();
  281. break;
  282. case '0':
  283. fillBuffer(0);
  284. setAnimationCount(0);
  285. refreshAnimationCount = 1;
  286. serialWriteString(getString(20));
  287. break;
  288. case '1':
  289. fillBuffer(0xFF);
  290. setAnimationCount(0);
  291. refreshAnimationCount = 1;
  292. serialWriteString(getString(20));
  293. break;
  294. case '2':
  295. fillBuffer(0);
  296. for (i = 0; i < 64; i++) {
  297. defaultImage[i] = 0;
  298. }
  299. while(1) {
  300. for (i = 0; i < 8; i++) {
  301. for (y = 0; y < 8; y++) {
  302. defaultImage[y + (i * 8)] = 0;
  303. for (z = 0; z < 8; z++) {
  304. defaultImage[y + (i * 8)] |= (1 << z);
  305. setImage(defaultImage);
  306. while (isFinished() == 0);
  307. }
  308. defaultImage[y + (i * 8)] = 0;
  309. }
  310. }
  311. if (serialHasChar()) {
  312. break;
  313. }
  314. }
  315. break;
  316. #endif
  317. default:
  318. serialWrite(ERROR);
  319. break;
  320. }
  321. // c was used as temp var and does not contain the char anymore...!
  322. }
  323. #ifdef DEBUG
  324. void sendAudioData(void) {
  325. uint8_t i;
  326. uint8_t *audioData = getAudioData();
  327. if (audioData == NULL) {
  328. serialWriteString(getString(21));
  329. } else {
  330. serialWriteString(getString(22));
  331. for (i = 0; i < 7; i++) {
  332. serialWrite(i + '0');
  333. serialWriteString(": ");
  334. itoa(audioData[i], buffer, 10);
  335. serialWriteString(buffer);
  336. serialWrite('\n');
  337. }
  338. free(audioData);
  339. }
  340. }
  341. #endif
  342. void recieveAnimations() {
  343. uint8_t animCount, a, frameCount, f, i;
  344. uint16_t completeCount = 0, character;
  345. uint8_t frame[65];
  346. serialWrite(OK); // We are ready...
  347. character = serialGet();
  348. while (character & 0xFF00) { // Wait for answer
  349. character = serialGet();
  350. }
  351. animCount = (uint8_t)(character & 0x00FF); // Got animation count
  352. serialWrite(OK);
  353. for (a = 0; a < animCount; a++) {
  354. character = serialGet();
  355. while (character & 0xFF00) { // Wait for answer
  356. character = serialGet();
  357. }
  358. frameCount = (uint8_t)(character & 0x00FF); // Got frame count
  359. serialWrite(OK);
  360. for (f = 0; f < frameCount; f++) {
  361. character = serialGet();
  362. while (character & 0xFF00) { // Wait for answer
  363. character = serialGet();
  364. }
  365. frame[64] = (uint8_t)(character & 0x00FF); // Got duration
  366. serialWrite(OK);
  367. for (i = 0; i < 64; i++) {
  368. character = serialGet();
  369. while (character & 0xFF00) { // Wait for answer
  370. character = serialGet();
  371. }
  372. frame[i] = (uint8_t)(character & 0x00FF); // Got data byte
  373. }
  374. serialWrite(OK);
  375. setFrame(completeCount++, frame);
  376. }
  377. }
  378. character = serialGet();
  379. while (character & 0xFF00) { // Wait for answer
  380. character = serialGet();
  381. }
  382. character = serialGet();
  383. while (character & 0xFF00) { // Wait for answer
  384. character = serialGet();
  385. }
  386. character = serialGet();
  387. while (character & 0xFF00) { // Wait for answer
  388. character = serialGet();
  389. }
  390. character = serialGet();
  391. while (character & 0xFF00) { // Wait for answer
  392. character = serialGet();
  393. }
  394. serialWrite(OK);
  395. setAnimationCount(completeCount);
  396. refreshAnimationCount = 1;
  397. }
  398. void transmitAnimations() {
  399. // We store no animation information in here
  400. // So we have to place all frames in one or more
  401. // animations... We need 8 animations max...
  402. uint8_t animationsToGo;
  403. uint16_t framesToGo = getAnimationCount();
  404. uint16_t character;
  405. uint8_t a;
  406. uint8_t f, fMax, i;
  407. uint8_t *frame;
  408. if ((framesToGo % 255) == 0) {
  409. animationsToGo = framesToGo / 255;
  410. } else {
  411. animationsToGo = (framesToGo / 255) + 1;
  412. }
  413. serialWrite(OK);
  414. serialWrite(animationsToGo);
  415. while ((character = serialGet()) & 0xFF00); // Wait for answer
  416. if ((character & 0x00FF) != OK) { // Error code recieved
  417. return;
  418. }
  419. for (a = 0; a < animationsToGo; a++) {
  420. if (framesToGo > 255) {
  421. fMax = 255;
  422. } else {
  423. fMax = framesToGo;
  424. }
  425. serialWrite(fMax); // Number of Frames in current animation
  426. while ((character = serialGet()) & 0xFF00); // Wait for answer
  427. if ((character & 0x00FF) != OK) { // Error code recieved
  428. return;
  429. }
  430. for (f = 0; f < fMax; f++) {
  431. frame = getFrame(f + (255 * a));
  432. serialWrite(frame[64]); // frame duration
  433. while ((character = serialGet()) & 0xFF00); // Wait for answer
  434. if ((character & 0x00FF) != OK) { // Error code recieved
  435. free(frame);
  436. return;
  437. }
  438. for (i = 0; i < 64; i++) {
  439. serialWrite(frame[i]);
  440. }
  441. while ((character = serialGet()) & 0xFF00); // Wait for answer
  442. if ((character & 0x00FF) != OK) { // Error code recieved
  443. free(frame);
  444. return;
  445. }
  446. free(frame);
  447. }
  448. framesToGo -= fMax;
  449. }
  450. serialWrite(OK);
  451. serialWrite(OK);
  452. serialWrite(OK);
  453. serialWrite(OK);
  454. while ((character = serialGet()) & 0xFF00); // Wait for answer
  455. // Error code ignored...
  456. }
  457. uint8_t audioModeSelected(void) {
  458. // Pushbutton: PB0, Low active
  459. if (!(PINB & (1 << PB0))) {
  460. // Button pushed
  461. if (lastButtonState == 0) {
  462. lastButtonState = 1;
  463. } else {
  464. lastButtonState = 0;
  465. }
  466. #ifdef DEBUG
  467. serialWriteString("New State (");
  468. serialWriteString(itoa(lastButtonState, buffer, 10));
  469. serialWriteString(")\n");
  470. #endif
  471. }
  472. return lastButtonState;
  473. }
  474. void setRow(uint8_t x, uint8_t z, uint8_t height, uint8_t *buf) {
  475. uint8_t i = 0;
  476. for (; i < height; i++) {
  477. setPixelBuffer(x, i, z, buf);
  478. }
  479. }
  480. void setPixelBuffer(uint8_t x, uint8_t y, uint8_t z, uint8_t *buf) {
  481. buf[(8 * z) + y] |= (1 << x);
  482. }
  483. void visualizeAudioData(uint8_t *audioData, uint8_t *imageData) {
  484. uint8_t i;
  485. for (i = 0; i < 64; i++) {
  486. imageData[i] = 0;
  487. }
  488. // 8 LEDs, Max Val 255:
  489. // 256 / 8 = 32 => Divide by 31 (FACTOR) to get num of leds to light
  490. // 255 / FACTOR = 8,...
  491. // 127 / FACTOR = 4,...
  492. #define FACTOR 31
  493. // Could not figure out a way to represent this easily in a loop
  494. // without using a shitload of 'if's...
  495. setRow(0, 0, (audioData[0] / FACTOR), imageData);
  496. setRow(0, 1, (audioData[0] / FACTOR), imageData);
  497. setRow(1, 0, (audioData[0] / FACTOR), imageData);
  498. setRow(0, 2, (audioData[1] / FACTOR), imageData);
  499. setRow(0, 3, (audioData[1] / FACTOR), imageData);
  500. setRow(1, 1, (audioData[1] / FACTOR), imageData);
  501. setRow(1, 2, (audioData[1] / FACTOR), imageData);
  502. setRow(2, 0, (audioData[1] / FACTOR), imageData);
  503. setRow(2, 1, (audioData[1] / FACTOR), imageData);
  504. setRow(0, 4, (audioData[2] / FACTOR), imageData);
  505. setRow(0, 5, (audioData[2] / FACTOR), imageData);
  506. setRow(1, 3, (audioData[2] / FACTOR), imageData);
  507. setRow(1, 4, (audioData[2] / FACTOR), imageData);
  508. setRow(2, 2, (audioData[2] / FACTOR), imageData);
  509. setRow(2, 3, (audioData[2] / FACTOR), imageData);
  510. setRow(3, 0, (audioData[2] / FACTOR), imageData);
  511. setRow(3, 1, (audioData[2] / FACTOR), imageData);
  512. setRow(3, 2, (audioData[2] / FACTOR), imageData);
  513. setRow(4, 0, (audioData[2] / FACTOR), imageData);
  514. setRow(4, 1, (audioData[2] / FACTOR), imageData);
  515. setRow(0, 6, (audioData[3] / FACTOR), imageData);
  516. setRow(0, 7, (audioData[3] / FACTOR), imageData);
  517. setRow(1, 5, (audioData[3] / FACTOR), imageData);
  518. setRow(1, 6, (audioData[3] / FACTOR), imageData);
  519. setRow(2, 4, (audioData[3] / FACTOR), imageData);
  520. setRow(2, 5, (audioData[3] / FACTOR), imageData);
  521. setRow(3, 3, (audioData[3] / FACTOR), imageData);
  522. setRow(3, 4, (audioData[3] / FACTOR), imageData);
  523. setRow(4, 2, (audioData[3] / FACTOR), imageData);
  524. setRow(4, 3, (audioData[3] / FACTOR), imageData);
  525. setRow(5, 0, (audioData[3] / FACTOR), imageData);
  526. setRow(5, 1, (audioData[3] / FACTOR), imageData);
  527. setRow(5, 2, (audioData[3] / FACTOR), imageData);
  528. setRow(6, 0, (audioData[3] / FACTOR), imageData);
  529. setRow(6, 1, (audioData[3] / FACTOR), imageData);
  530. setRow(1, 7, (audioData[4] / FACTOR), imageData);
  531. setRow(2, 6, (audioData[4] / FACTOR), imageData);
  532. setRow(2, 7, (audioData[4] / FACTOR), imageData);
  533. setRow(3, 5, (audioData[4] / FACTOR), imageData);
  534. setRow(3, 6, (audioData[4] / FACTOR), imageData);
  535. setRow(4, 4, (audioData[4] / FACTOR), imageData);
  536. setRow(4, 5, (audioData[4] / FACTOR), imageData);
  537. setRow(5, 3, (audioData[4] / FACTOR), imageData);
  538. setRow(5, 4, (audioData[4] / FACTOR), imageData);
  539. setRow(6, 2, (audioData[4] / FACTOR), imageData);
  540. setRow(6, 3, (audioData[4] / FACTOR), imageData);
  541. setRow(7, 0, (audioData[4] / FACTOR), imageData);
  542. setRow(7, 1, (audioData[4] / FACTOR), imageData);
  543. setRow(3, 7, (audioData[5] / FACTOR), imageData);
  544. setRow(4, 6, (audioData[5] / FACTOR), imageData);
  545. setRow(4, 7, (audioData[5] / FACTOR), imageData);
  546. setRow(5, 5, (audioData[5] / FACTOR), imageData);
  547. setRow(5, 6, (audioData[5] / FACTOR), imageData);
  548. setRow(6, 4, (audioData[5] / FACTOR), imageData);
  549. setRow(6, 5, (audioData[5] / FACTOR), imageData);
  550. setRow(7, 2, (audioData[5] / FACTOR), imageData);
  551. setRow(7, 3, (audioData[5] / FACTOR), imageData);
  552. setRow(7, 4, (audioData[5] / FACTOR), imageData);
  553. setRow(5, 7, (audioData[6] / FACTOR), imageData);
  554. setRow(6, 6, (audioData[6] / FACTOR), imageData);
  555. setRow(6, 7, (audioData[6] / FACTOR), imageData);
  556. setRow(7, 5, (audioData[6] / FACTOR), imageData);
  557. setRow(7, 6, (audioData[6] / FACTOR), imageData);
  558. setRow(7, 7, (audioData[6] / FACTOR), imageData);
  559. }