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 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  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 <avr/wdt.h>
  35. #include "serial.h"
  36. #include "cube.h"
  37. #include "time.h"
  38. #include "audio.h"
  39. #include "mem.h"
  40. #include "memLayer.h"
  41. #include "twi.h"
  42. #include "strings.h"
  43. #define NOERROR 0
  44. // Audio does not answer
  45. #define AUDIOERROR 1
  46. // Memory does not answer
  47. #define MEMORYERROR 2
  48. // Memory not writeable
  49. #define MEMORYWRITEERROR 4
  50. // x = errorcode, e = error definition, not NOERROR
  51. #define ISERROR(x, e) ((x) & (e))
  52. // Length of an idle animation frame, 24 -> 1 second
  53. #define IDLELENGTH 24
  54. void serialHandler(char c);
  55. void sendAudioData(void);
  56. void recieveAnimations(void);
  57. void transmitAnimations(void);
  58. uint8_t audioModeSelected(void);
  59. void setPixelBuffer(uint8_t x, uint8_t y, uint8_t z, uint8_t *buf);
  60. void setRow(uint8_t x, uint8_t z, uint8_t height, uint8_t *buf);
  61. void visualizeAudioData(uint8_t *audioData, uint8_t *imageData);
  62. #ifdef DEBUG
  63. void printErrors(uint8_t e);
  64. uint8_t selfTest(void);
  65. void printTime(void);
  66. #include "snake.c"
  67. #endif
  68. uint8_t shouldRestart = 0;
  69. uint8_t refreshAnimationCount = 1;
  70. uint8_t lastButtonState = 0;
  71. uint8_t mcusr_mirror;
  72. char buffer[11];
  73. uint8_t defaultImageA[64] = { 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  74. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  75. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  76. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  77. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  78. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  79. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff,
  80. 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0xff };
  81. uint8_t defaultImageB[64] = { 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  82. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  83. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  84. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  85. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  86. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  87. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81,
  88. 0x7e, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81 };
  89. uint8_t defaultImageC[64] = { 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  90. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  91. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  92. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  93. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  94. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  95. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02,
  96. 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02 };
  97. #define IDLEANIMATIONCOUNT 3
  98. uint8_t *idleAnimation[IDLEANIMATIONCOUNT] = { defaultImageA, defaultImageB, defaultImageC };
  99. uint8_t DebugDone = 0; // Bit 0: 10s int. count, Bit 1: unused
  100. // Bit 2: state changed, disable idle
  101. int main(void) {
  102. uint8_t *audioData = NULL;
  103. uint8_t *imageData = NULL;
  104. uint8_t i, length = 0, lastMode;
  105. uint16_t count;
  106. uint64_t lastChecked;
  107. uint8_t idleCounter = 0;
  108. #ifdef DEBUG
  109. uint32_t temp;
  110. #endif
  111. mcusr_mirror = MCUCSR;
  112. MCUCSR = 0;
  113. wdt_disable();
  114. initCube();
  115. serialInit(25, 8, NONE, 1);
  116. i2c_init();
  117. initSystemTimer();
  118. sei(); // Enable Interrupts
  119. // wdt_enable(WDTO_500MS); // Enable watchdog reset after 500ms
  120. wdt_enable(WDTO_1S); // Watchdog reset after 1 second
  121. DDRA = 0xFF; // Latch Data Bus as Output
  122. DDRD = 0xFC; DDRB = 24; // Mosfets as Output
  123. DDRC = 0xFC; DDRB |= 6; // Latch Enable as Output
  124. DDRB &= ~(1 << PB0); // Pushbutton as Input
  125. setImage(defaultImageA); // Display something
  126. #ifdef DEBUG
  127. // Kill animation counter in debug mode
  128. // => Don't preserve animations while power down
  129. setAnimationCount(0);
  130. i = selfTest();
  131. if (i) {
  132. serialWriteString(getString(1));
  133. serialWriteString(itoa(i, buffer, 2));
  134. serialWrite('\n');
  135. printErrors(i);
  136. }
  137. serialWriteString(getString(2));
  138. serialWriteString(getString(0));
  139. serialWriteString("Took ");
  140. serialWriteString(itoa(getSystemTime(), buffer, 10));
  141. serialWriteString(" ms!\n");
  142. if (mcusr_mirror & WDRF) {
  143. serialWriteString(getString(31));
  144. } else if (mcusr_mirror & BORF) {
  145. serialWriteString(getString(32));
  146. } else if (mcusr_mirror & EXTRF) {
  147. serialWriteString(getString(34));
  148. } else if (mcusr_mirror & JTRF) {
  149. serialWriteString(getString(35));
  150. } else if (mcusr_mirror & PORF) {
  151. serialWriteString(getString(36));
  152. } else {
  153. serialWriteString(getString(33));
  154. }
  155. #endif
  156. lastMode = audioModeSelected();
  157. lastChecked = getSystemTime();
  158. i = 0;
  159. count = getAnimationCount();
  160. while (1) {
  161. // Reset if requested
  162. if (!shouldRestart) {
  163. wdt_reset();
  164. }
  165. if(lastMode) {
  166. // Get Audio Data and visualize it
  167. if (isFinished()) {
  168. audioData = getAudioData(); // Not malloc'ed => Don't free
  169. if (audioData != NULL) {
  170. imageData = (uint8_t *)malloc(64);
  171. if (imageData == NULL) {
  172. #ifdef DEBUG
  173. serialWriteString(getString(24));
  174. #endif
  175. while(1); // Ran out of heap => Watchdog Reset
  176. }
  177. visualizeAudioData(audioData, imageData);
  178. setImage(imageData);
  179. free(imageData);
  180. }
  181. }
  182. } else {
  183. if (refreshAnimationCount) {
  184. // Get animation count stored in FRAM via TWI, if needed
  185. count = getAnimationCount();
  186. refreshAnimationCount = 0;
  187. i = 0;
  188. }
  189. if (count > 0) {
  190. if (isFinished() > length) {
  191. // Load next image
  192. if (i < (count - 1)) {
  193. i++;
  194. } else {
  195. i = 0;
  196. }
  197. imageData = getFrame(i);
  198. length = imageData[64];
  199. setImage(imageData);
  200. free(imageData);
  201. }
  202. } else {
  203. if (!(DebugDone & 4)) { // Idle animation allowed
  204. if (isFinished() >= IDLELENGTH) {
  205. // Should happen every half second
  206. setImage(idleAnimation[idleCounter]);
  207. if (idleCounter < (IDLEANIMATIONCOUNT - 1)) {
  208. idleCounter++;
  209. } else {
  210. idleCounter = 0;
  211. }
  212. }
  213. }
  214. }
  215. }
  216. if (serialHasChar()) {
  217. serialHandler((char)(serialGet()));
  218. }
  219. #ifdef DEBUG
  220. // Print frames per second
  221. if ((getSystemTime() >= 1000) && ((DebugDone & 1) == 0)) {
  222. temp = getTriggerCount();
  223. serialWriteString(ltoa(temp, buffer, 10));
  224. serialWriteString(getString(27));
  225. serialWriteString(ltoa((temp / 8), buffer, 10));
  226. serialWriteString(getString(28));
  227. DebugDone |= 1;
  228. }
  229. // Show how stable we are running :)
  230. if (((getSystemTime() % 60000) == 0) && (getSystemTime() > 0)) {
  231. serialWriteString(getString(37));
  232. printTime();
  233. }
  234. #endif
  235. if ((getSystemTime() - lastChecked) > 150) {
  236. lastMode = audioModeSelected();
  237. lastChecked = getSystemTime();
  238. }
  239. }
  240. close();
  241. return 0;
  242. }
  243. #ifdef DEBUG
  244. uint8_t selfTest(void) {
  245. uint8_t result = NOERROR;
  246. uint8_t *data = getAudioData();
  247. if (data == NULL) {
  248. result |= AUDIOERROR;
  249. } else {
  250. free(data);
  251. }
  252. data = memGetBytes(0, 1);
  253. if (data == NULL) {
  254. result |= MEMORYERROR;
  255. } else {
  256. free(data);
  257. }
  258. setGeneralPurposeByte(0, 0x23);
  259. if (getGeneralPurposeByte(0) != 0x23) {
  260. result |= MEMORYWRITEERROR;
  261. }
  262. return result;
  263. }
  264. void printErrors(uint8_t e) {
  265. if (ISERROR(e, AUDIOERROR)) {
  266. serialWriteString(getString(3));
  267. }
  268. if (ISERROR(e, MEMORYERROR)) {
  269. serialWriteString(getString(4));
  270. }
  271. if (ISERROR(e, MEMORYWRITEERROR)) {
  272. serialWriteString(getString(5));
  273. }
  274. }
  275. void randomAnimation(void) {
  276. uint8_t *b = (uint8_t *)malloc(64);
  277. uint8_t x, y, z;
  278. if (b == NULL) {
  279. serialWriteString(getString(24));
  280. return;
  281. }
  282. for (x = 0; x < 64; x++) {
  283. b[x] = 0;
  284. }
  285. while(1) {
  286. setImage(b);
  287. while(isFinished() == 0);
  288. x = rand() / 4096;
  289. y = rand() / 4096;
  290. z = rand() / 4096;
  291. b[x + (8 * y)] ^= (1 << z);
  292. if (serialHasChar()) {
  293. serialWriteString(getString(25));
  294. free(b);
  295. serialHandler(serialGet());
  296. return;
  297. }
  298. }
  299. free(b);
  300. }
  301. #endif
  302. void serialHandler(char c) {
  303. // Used letters:
  304. // a, c, d, e, g, i, n, q, r, s, t, v, x, y, 0, 1, 2
  305. #ifdef DEBUG
  306. uint8_t i, y, z;
  307. serialWrite(c);
  308. serialWriteString(": ");
  309. #endif
  310. switch(c) {
  311. case OK:
  312. serialWrite(OK);
  313. break;
  314. case 'h': case 'H': case '?':
  315. serialWriteString(getString(6));
  316. #ifdef DEBUG
  317. serialWriteString(getString(7));
  318. serialWriteString(getString(8));
  319. serialWriteString(getString(9));
  320. serialWriteString(getString(10));
  321. serialWriteString(getString(11));
  322. serialWriteString(getString(12));
  323. serialWriteString(getString(13));
  324. serialWriteString(getString(26));
  325. #endif
  326. break;
  327. case 'd': case 'D':
  328. clearMem();
  329. #ifndef DEBUG
  330. serialWrite(OK);
  331. #endif
  332. #ifdef DEBUG
  333. serialWriteString(getString(29));
  334. #endif
  335. break;
  336. #ifndef DEBUG
  337. case 'g': case 'G':
  338. transmitAnimations();
  339. break;
  340. case 's': case 'S':
  341. recieveAnimations();
  342. break;
  343. #endif
  344. case 'v': case 'V':
  345. serialWriteString(getString(0));
  346. break;
  347. #ifdef DEBUG
  348. case 'm': case 'M':
  349. lastButtonState = !lastButtonState;
  350. serialWriteString(getString(40));
  351. break;
  352. case 'q': case 'Q':
  353. shouldRestart = 1;
  354. serialWriteString(getString(30));
  355. break;
  356. case 'r': case 'R':
  357. randomAnimation();
  358. break;
  359. case 't': case 'T':
  360. printTime();
  361. break;
  362. case 'a': case 'A':
  363. sendAudioData();
  364. break;
  365. case 'c': case 'C':
  366. serialWriteString(itoa(getAnimationCount(), buffer, 10));
  367. serialWriteString(getString(15));
  368. break;
  369. case 'x': case 'X':
  370. // Get byte, store as animation count
  371. serialWriteString(getString(16));
  372. while (!serialHasChar());
  373. c = serialGet();
  374. setAnimationCount(c);
  375. serialWriteString(itoa(c, buffer, 10));
  376. serialWriteString(getString(17));
  377. break;
  378. case 'y': case 'Y':
  379. setAnimationCount(0x2201);
  380. serialWriteString(getString(18));
  381. break;
  382. case 'e': case 'E':
  383. c = selfTest();
  384. serialWriteString(getString(19));
  385. serialWriteString(itoa(c, buffer, 2));
  386. serialWrite('\n');
  387. printErrors(c);
  388. break;
  389. case 'n': case 'N':
  390. snake();
  391. break;
  392. case '0':
  393. fillBuffer(0);
  394. DebugDone |= 4;
  395. break;
  396. case '1':
  397. fillBuffer(0xFF);
  398. DebugDone |= 4;
  399. break;
  400. case '2':
  401. DebugDone |= 4;
  402. fillBuffer(0);
  403. for (i = 0; i < 64; i++) {
  404. defaultImageA[i] = 0;
  405. }
  406. while(1) {
  407. for (i = 0; i < 8; i++) {
  408. for (y = 0; y < 8; y++) {
  409. defaultImageA[y + (i * 8)] = 0;
  410. for (z = 0; z < 8; z++) {
  411. defaultImageA[y + (i * 8)] |= (1 << z);
  412. setImage(defaultImageA);
  413. while (isFinished() == 0) {
  414. if (serialHasChar()) {
  415. goto killMeForIt; // Yes I know...
  416. // But I need to break out of 2 while Loops...
  417. }
  418. }
  419. }
  420. defaultImageA[y + (i * 8)] = 0;
  421. }
  422. }
  423. }
  424. break;
  425. killMeForIt:
  426. serialGet();
  427. serialWriteString(getString(25));
  428. break;
  429. case 'I': case 'i':
  430. serialWriteString(ltoa(getTriggerCount(), buffer, 10));
  431. serialWrite('\n');
  432. break;
  433. #endif
  434. default:
  435. serialWrite(ERROR);
  436. break;
  437. }
  438. // c was used as temp var and does not contain the char anymore...!
  439. }
  440. #ifdef DEBUG
  441. void printTime(void) {
  442. serialWriteString(getString(14));
  443. serialWriteString(ltoa(getSystemTime(), buffer, 10));
  444. serialWriteString("ms");
  445. if (getSystemTime() > 60000) {
  446. serialWriteString(" (");
  447. serialWriteString(itoa(getSystemTime() / 60000, buffer, 10));
  448. serialWriteString(" min)");
  449. }
  450. if (getSystemTime() > 1000) {
  451. serialWriteString(" (");
  452. serialWriteString(itoa(getSystemTime() / 1000, buffer, 10));
  453. itoa(getSystemTime() % 1000, buffer, 10);
  454. if (buffer[0] != '\0')
  455. serialWrite('.');
  456. if (buffer[2] == '\0')
  457. serialWrite('0');
  458. if (buffer[1] == '\0')
  459. serialWrite('0');
  460. if (buffer[0] != '\0')
  461. serialWriteString(buffer);
  462. serialWriteString("s)\n");
  463. } else {
  464. serialWrite('\n');
  465. }
  466. }
  467. void sendAudioData(void) {
  468. uint8_t i;
  469. uint8_t *audioData = getAudioData();
  470. if (audioData == NULL) {
  471. serialWriteString(getString(21));
  472. } else {
  473. serialWriteString(getString(22));
  474. for (i = 0; i < 7; i++) {
  475. serialWrite(i + '0');
  476. serialWriteString(": ");
  477. itoa(audioData[i], buffer, 10);
  478. serialWriteString(buffer);
  479. serialWrite('\n');
  480. }
  481. }
  482. }
  483. #endif
  484. void recieveAnimations() {
  485. uint8_t animCount, a, frameCount, f, i;
  486. uint16_t completeCount = 0, character;
  487. uint8_t frame[65];
  488. serialWrite(OK); // We are ready...
  489. character = serialGet();
  490. while (character & 0xFF00) { // Wait for answer
  491. character = serialGet();
  492. }
  493. animCount = (uint8_t)(character & 0x00FF); // Got animation count
  494. serialWrite(OK);
  495. for (a = 0; a < animCount; a++) {
  496. character = serialGet();
  497. while (character & 0xFF00) { // Wait for answer
  498. character = serialGet();
  499. }
  500. frameCount = (uint8_t)(character & 0x00FF); // Got frame count
  501. serialWrite(OK);
  502. for (f = 0; f < frameCount; f++) {
  503. character = serialGet();
  504. while (character & 0xFF00) { // Wait for answer
  505. character = serialGet();
  506. }
  507. frame[64] = (uint8_t)(character & 0x00FF); // Got duration
  508. serialWrite(OK);
  509. for (i = 0; i < 64; i++) {
  510. character = serialGet();
  511. while (character & 0xFF00) { // Wait for answer
  512. character = serialGet();
  513. }
  514. frame[i] = (uint8_t)(character & 0x00FF); // Got data byte
  515. }
  516. serialWrite(OK);
  517. setFrame(completeCount++, frame);
  518. }
  519. }
  520. character = serialGet();
  521. while (character & 0xFF00) { // Wait for answer
  522. character = serialGet();
  523. }
  524. character = serialGet();
  525. while (character & 0xFF00) { // Wait for answer
  526. character = serialGet();
  527. }
  528. character = serialGet();
  529. while (character & 0xFF00) { // Wait for answer
  530. character = serialGet();
  531. }
  532. character = serialGet();
  533. while (character & 0xFF00) { // Wait for answer
  534. character = serialGet();
  535. }
  536. serialWrite(OK);
  537. setAnimationCount(completeCount);
  538. refreshAnimationCount = 1;
  539. }
  540. void transmitAnimations() {
  541. // We store no animation information in here
  542. // So we have to place all frames in one or more
  543. // animations... We need 8 animations max...
  544. uint8_t animationsToGo;
  545. uint16_t framesToGo = getAnimationCount();
  546. uint16_t character;
  547. uint8_t a;
  548. uint8_t f, fMax, i;
  549. uint8_t *frame;
  550. if ((framesToGo % 255) == 0) {
  551. animationsToGo = framesToGo / 255;
  552. } else {
  553. animationsToGo = (framesToGo / 255) + 1;
  554. }
  555. serialWrite(OK);
  556. serialWrite(animationsToGo);
  557. while ((character = serialGet()) & 0xFF00); // Wait for answer
  558. if ((character & 0x00FF) != OK) { // Error code recieved
  559. return;
  560. }
  561. for (a = 0; a < animationsToGo; a++) {
  562. if (framesToGo > 255) {
  563. fMax = 255;
  564. } else {
  565. fMax = framesToGo;
  566. }
  567. serialWrite(fMax); // Number of Frames in current animation
  568. while ((character = serialGet()) & 0xFF00); // Wait for answer
  569. if ((character & 0x00FF) != OK) { // Error code recieved
  570. return;
  571. }
  572. for (f = 0; f < fMax; f++) {
  573. frame = getFrame(f + (255 * a));
  574. serialWrite(frame[64]); // frame duration
  575. while ((character = serialGet()) & 0xFF00); // Wait for answer
  576. if ((character & 0x00FF) != OK) { // Error code recieved
  577. free(frame);
  578. return;
  579. }
  580. for (i = 0; i < 64; i++) {
  581. serialWrite(frame[i]);
  582. }
  583. while ((character = serialGet()) & 0xFF00); // Wait for answer
  584. if ((character & 0x00FF) != OK) { // Error code recieved
  585. free(frame);
  586. return;
  587. }
  588. free(frame);
  589. }
  590. framesToGo -= fMax;
  591. }
  592. serialWrite(OK);
  593. serialWrite(OK);
  594. serialWrite(OK);
  595. serialWrite(OK);
  596. while ((character = serialGet()) & 0xFF00); // Wait for answer
  597. // Error code ignored...
  598. }
  599. uint8_t audioModeSelected(void) {
  600. // Pushbutton: PB0, Low active
  601. if (!(PINB & (1 << PB0))) {
  602. // Button pushed
  603. if (lastButtonState == 0) {
  604. lastButtonState = 1;
  605. } else {
  606. lastButtonState = 0;
  607. }
  608. #ifdef DEBUG
  609. if (lastButtonState) {
  610. serialWriteString(getString(38));
  611. } else {
  612. serialWriteString(getString(39));
  613. }
  614. #endif
  615. }
  616. return lastButtonState;
  617. }
  618. void setRow(uint8_t x, uint8_t z, uint8_t height, uint8_t *buf) {
  619. uint8_t i = 0;
  620. for (; i < height; i++) {
  621. setPixelBuffer(x, i, z, buf);
  622. }
  623. }
  624. void setPixelBuffer(uint8_t x, uint8_t y, uint8_t z, uint8_t *buf) {
  625. buf[(8 * z) + (7 - y)] |= (1 << x);
  626. }
  627. void visualizeAudioData(uint8_t *audioData, uint8_t *imageData) {
  628. uint8_t i;
  629. for (i = 0; i < 64; i++) {
  630. imageData[i] = 0;
  631. }
  632. // 8 LEDs, Max Val 255:
  633. // 256 / 8 = 32 => Divide by 31 (FACTOR) to get num of leds to light
  634. // 255 / FACTOR = 8,...
  635. // 127 / FACTOR = 4,...
  636. #define FACTOR 31
  637. // Could not figure out a way to represent this easily in a loop
  638. // without using a shitload of 'if's...
  639. setRow(0, 0, (audioData[0] / FACTOR), imageData);
  640. setRow(0, 1, (audioData[0] / FACTOR), imageData);
  641. setRow(1, 0, (audioData[0] / FACTOR), imageData);
  642. setRow(0, 2, (audioData[1] / FACTOR), imageData);
  643. setRow(0, 3, (audioData[1] / FACTOR), imageData);
  644. setRow(1, 1, (audioData[1] / FACTOR), imageData);
  645. setRow(1, 2, (audioData[1] / FACTOR), imageData);
  646. setRow(2, 0, (audioData[1] / FACTOR), imageData);
  647. setRow(2, 1, (audioData[1] / FACTOR), imageData);
  648. setRow(0, 4, (audioData[2] / FACTOR), imageData);
  649. setRow(0, 5, (audioData[2] / FACTOR), imageData);
  650. setRow(1, 3, (audioData[2] / FACTOR), imageData);
  651. setRow(1, 4, (audioData[2] / FACTOR), imageData);
  652. setRow(2, 2, (audioData[2] / FACTOR), imageData);
  653. setRow(2, 3, (audioData[2] / FACTOR), imageData);
  654. setRow(3, 0, (audioData[2] / FACTOR), imageData);
  655. setRow(3, 1, (audioData[2] / FACTOR), imageData);
  656. setRow(3, 2, (audioData[2] / FACTOR), imageData);
  657. setRow(4, 0, (audioData[2] / FACTOR), imageData);
  658. setRow(4, 1, (audioData[2] / FACTOR), imageData);
  659. setRow(0, 6, (audioData[3] / FACTOR), imageData);
  660. setRow(0, 7, (audioData[3] / FACTOR), imageData);
  661. setRow(1, 5, (audioData[3] / FACTOR), imageData);
  662. setRow(1, 6, (audioData[3] / FACTOR), imageData);
  663. setRow(2, 4, (audioData[3] / FACTOR), imageData);
  664. setRow(2, 5, (audioData[3] / FACTOR), imageData);
  665. setRow(3, 3, (audioData[3] / FACTOR), imageData);
  666. setRow(3, 4, (audioData[3] / FACTOR), imageData);
  667. setRow(4, 2, (audioData[3] / FACTOR), imageData);
  668. setRow(4, 3, (audioData[3] / FACTOR), imageData);
  669. setRow(5, 0, (audioData[3] / FACTOR), imageData);
  670. setRow(5, 1, (audioData[3] / FACTOR), imageData);
  671. setRow(5, 2, (audioData[3] / FACTOR), imageData);
  672. setRow(6, 0, (audioData[3] / FACTOR), imageData);
  673. setRow(6, 1, (audioData[3] / FACTOR), imageData);
  674. setRow(1, 7, (audioData[4] / FACTOR), imageData);
  675. setRow(2, 6, (audioData[4] / FACTOR), imageData);
  676. setRow(2, 7, (audioData[4] / FACTOR), imageData);
  677. setRow(3, 5, (audioData[4] / FACTOR), imageData);
  678. setRow(3, 6, (audioData[4] / FACTOR), imageData);
  679. setRow(4, 4, (audioData[4] / FACTOR), imageData);
  680. setRow(4, 5, (audioData[4] / FACTOR), imageData);
  681. setRow(5, 3, (audioData[4] / FACTOR), imageData);
  682. setRow(5, 4, (audioData[4] / FACTOR), imageData);
  683. setRow(6, 2, (audioData[4] / FACTOR), imageData);
  684. setRow(6, 3, (audioData[4] / FACTOR), imageData);
  685. setRow(7, 0, (audioData[4] / FACTOR), imageData);
  686. setRow(7, 1, (audioData[4] / FACTOR), imageData);
  687. setRow(3, 7, (audioData[5] / FACTOR), imageData);
  688. setRow(4, 6, (audioData[5] / FACTOR), imageData);
  689. setRow(4, 7, (audioData[5] / FACTOR), imageData);
  690. setRow(5, 5, (audioData[5] / FACTOR), imageData);
  691. setRow(5, 6, (audioData[5] / FACTOR), imageData);
  692. setRow(6, 4, (audioData[5] / FACTOR), imageData);
  693. setRow(6, 5, (audioData[5] / FACTOR), imageData);
  694. setRow(7, 2, (audioData[5] / FACTOR), imageData);
  695. setRow(7, 3, (audioData[5] / FACTOR), imageData);
  696. setRow(7, 4, (audioData[5] / FACTOR), imageData);
  697. setRow(5, 7, (audioData[6] / FACTOR), imageData);
  698. setRow(6, 6, (audioData[6] / FACTOR), imageData);
  699. setRow(6, 7, (audioData[6] / FACTOR), imageData);
  700. setRow(7, 5, (audioData[6] / FACTOR), imageData);
  701. setRow(7, 6, (audioData[6] / FACTOR), imageData);
  702. setRow(7, 7, (audioData[6] / FACTOR), imageData);
  703. }