Simple single-color 8x8x8 LED Cube with AVRs
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

main.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. #include "visualizer.h"
  44. #include "animations.h"
  45. #include "transmit.h"
  46. // Length of an idle animation frame, 24 -> 1 second
  47. #define IDLELENGTH 48
  48. void init(void);
  49. uint8_t audioModeSelected(void);
  50. uint8_t selfTest(void);
  51. void serialHandler(char c);
  52. uint8_t defaultImageCube[64] = { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81,
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55. 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81,
  56. 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81,
  57. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  58. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  59. 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 };
  60. #define NOERROR 0
  61. // Audio does not answer
  62. #define AUDIOERROR 1
  63. // Memory does not answer
  64. #define MEMORYERROR 2
  65. // Memory not writeable
  66. #define MEMORYWRITEERROR 4
  67. // x = errorcode, e = error definition, not NOERROR
  68. #define ISERROR(x, e) ((x) & (e))
  69. uint8_t shouldRestart = 0;
  70. uint8_t refreshAnimationCount = 0;
  71. uint8_t lastButtonState = 0;
  72. uint8_t maxButtonState = 1; // No audio, get's checked later
  73. uint8_t disableAudioData = 0;
  74. uint8_t disableMemory = 0;
  75. uint8_t disableAnim = 0;
  76. char buffer[11];
  77. int main(void) {
  78. /*
  79. Quick Summary of the jobs main has to do:
  80. - Initialize Cube
  81. - Regularly check the buttonstate
  82. - Check for incoming serial transmission and run serialHandler
  83. - Check if animations are stored
  84. --> If yes, display them
  85. --> If no, display our idle animations
  86. */
  87. uint8_t i;
  88. uint8_t imageIndex = 0, imageCount = 0;
  89. uint8_t idleIndex = 0, idleCount = 0;
  90. uint8_t lastButtonCheck;
  91. // uint8_t fpsWasSent = 0;
  92. // uint32_t temp;
  93. uint8_t *imageData = NULL, *audioData = NULL;
  94. uint8_t duration = 0;
  95. // Initialization:
  96. MCUCSR = 0; // Reset Watchdog
  97. wdt_disable();
  98. init(); // Initialize all subsystems, set port directions, enable interrupts
  99. wdt_enable(WDTO_1S); // Watchdog reset after 1 second
  100. i = selfTest(); // Run selftest, print errors
  101. // Disable subsystems if they are unavailable
  102. if (ISERROR(i, AUDIOERROR))
  103. disableAudioData = 1;
  104. if (ISERROR(i, MEMORYERROR) || ISERROR(i, MEMORYWRITEERROR))
  105. disableMemory = 1;
  106. serialWriteString(getString(0)); // Print Version
  107. audioModeSelected(); // Initial button state check
  108. lastButtonCheck = getSystemTime(); // Time we checked
  109. if (disableMemory == 0)
  110. imageCount = getAnimationCount(); // Retrieve image count from memory
  111. idleCount = numOfAnimations();
  112. if (disableAudioData == 0)
  113. maxButtonState = numberOfVisualizations() + 1; // Number of toggle steps for button
  114. while(1) { // Our Mainloop
  115. if (!shouldRestart) { // A flag to trigger a watchdog reset
  116. wdt_reset();
  117. }
  118. if (refreshAnimationCount) {
  119. refreshAnimationCount = 0;
  120. if (disableMemory == 0)
  121. imageCount = getAnimationCount();
  122. }
  123. if (serialHasChar()) { // Run serialHandler
  124. serialHandler((char)(serialGet()));
  125. }
  126. if ((getSystemTime() - lastButtonCheck) >= 150) { // Check button state every 150ms
  127. audioModeSelected();
  128. lastButtonCheck = getSystemTime();
  129. }
  130. if (lastButtonState == 0) {
  131. // Display animations, stored or built-in
  132. if (disableAnim == 0) {
  133. if ((imageCount > 0) && (disableMemory == 0)) {
  134. // Memory frames
  135. if (isFinished() > duration) {
  136. // Last frame was displayed long enough
  137. imageIndex = (imageIndex < (imageCount - 1)) ? (imageIndex + 1) : 0;
  138. imageData = getFrame(i);
  139. if (imageData == NULL) {
  140. duration = 24;
  141. setImage(defaultImageCube);
  142. } else {
  143. duration = imageData[64];
  144. setImage(imageData);
  145. free(imageData);
  146. }
  147. }
  148. } else {
  149. // Built-In Frames
  150. if (isFinished() > duration) {
  151. idleIndex = (idleIndex < (idleCount - 1)) ? (idleIndex + 1) : 0;
  152. duration = executeAnimation(idleIndex);
  153. }
  154. }
  155. }
  156. } else {
  157. // An audiomode is selected
  158. if (disableAudioData == 0) {
  159. if (isFinished()) {
  160. audioData = getAudioData();
  161. if (audioData != NULL) {
  162. runVisualization(audioData, (lastButtonState - 1));
  163. } else {
  164. lastButtonState = 0;
  165. duration = 24;
  166. setImage(defaultImageCube); // Quasi Error Screen
  167. }
  168. }
  169. } else {
  170. lastButtonState = 0;
  171. }
  172. }
  173. // Print fps after one second
  174. /* if ((getSystemTime() >= 1000) && (fpsWasSent == 0)) {
  175. temp = getTriggerCount();
  176. serialWriteString(ltoa(temp, buffer, 10));
  177. serialWriteString(getString(27));
  178. serialWriteString(ltoa((temp / 8), buffer, 10));
  179. serialWriteString(getString(28));
  180. fpsWasSent = 1;
  181. } */
  182. }
  183. close(); // This is of course unneccessary. We never reach this point.
  184. return 0;
  185. }
  186. void init(void) {
  187. DDRA = 0xFF; // Latch Data Bus as Output
  188. DDRD = 0xFC; DDRB = 24; // Mosfets as Output
  189. DDRC = 0xFC; DDRB |= 6; // Latch Enable as Output
  190. DDRB &= ~(1 << PB0); // Pushbutton as Input
  191. initCube();
  192. serialInit(25, 8, NONE, 1);
  193. i2c_init();
  194. initSystemTimer();
  195. sei(); // Enable Interrupts
  196. setImage(defaultImageCube); // Display something
  197. }
  198. uint8_t audioModeSelected(void) {
  199. // Pushbutton: PB0, Low active
  200. if (!(PINB & (1 << PB0))) {
  201. // Button pushed
  202. if (lastButtonState < (maxButtonState - 1)) {
  203. lastButtonState++;
  204. } else {
  205. lastButtonState = 0;
  206. }
  207. }
  208. return lastButtonState;
  209. }
  210. uint8_t selfTest(void) {
  211. uint8_t result = NOERROR;
  212. uint8_t *data = getAudioData();
  213. if (data == NULL) {
  214. result |= AUDIOERROR;
  215. } else {
  216. }
  217. data = memGetBytes(0, 1);
  218. if (data == NULL) {
  219. result |= MEMORYERROR;
  220. } else {
  221. free(data);
  222. }
  223. setGeneralPurposeByte(0, 0x23);
  224. if (getGeneralPurposeByte(0) != 0x23) {
  225. result |= MEMORYWRITEERROR;
  226. }
  227. if (result) { // Error in Selftest
  228. serialWriteString(getString(1));
  229. serialWriteString(itoa(result, buffer, 2));
  230. serialWrite('\n');
  231. if (ISERROR(result, AUDIOERROR)) {
  232. serialWriteString(getString(3));
  233. }
  234. if (ISERROR(result, MEMORYERROR)) {
  235. serialWriteString(getString(4));
  236. }
  237. if (ISERROR(result, MEMORYWRITEERROR)) {
  238. serialWriteString(getString(5));
  239. }
  240. }
  241. return result;
  242. }
  243. void randomAnimation(void) {
  244. uint8_t *b = (uint8_t *)malloc(64);
  245. uint8_t x, y, z;
  246. if (b == NULL) {
  247. serialWriteString(getString(24));
  248. return;
  249. }
  250. for (x = 0; x < 64; x++) {
  251. b[x] = 0;
  252. }
  253. while(1) {
  254. wdt_reset();
  255. setImage(b);
  256. while(isFinished() == 0);
  257. x = rand() / 4096;
  258. y = rand() / 4096;
  259. z = rand() / 4096;
  260. b[x + (8 * y)] ^= (1 << z);
  261. if (serialHasChar()) {
  262. serialWriteString(getString(25));
  263. free(b);
  264. serialGet();
  265. return;
  266. }
  267. }
  268. free(b);
  269. }
  270. void serialHandler(char c) {
  271. // Used letters:
  272. // a, b, c, d, e, g, i, n, q, r, s, t, v, x, y, 0, 1, 2, 3, #
  273. uint8_t i, y, z;
  274. switch(c) {
  275. case OK:
  276. serialWrite(OK);
  277. break;
  278. case 'h': case 'H': case '?':
  279. serialWriteString(getString(6));
  280. serialWriteString(getString(7));
  281. serialWriteString(getString(8));
  282. serialWriteString(getString(9));
  283. serialWriteString(getString(10));
  284. serialWriteString(getString(11));
  285. serialWriteString(getString(12));
  286. serialWriteString(getString(13));
  287. serialWriteString(getString(26));
  288. break;
  289. case 'd': case 'D':
  290. // clearMem(); // Much too invasive
  291. setAnimationCount(0);
  292. serialWrite(OK);
  293. refreshAnimationCount = 1;
  294. break;
  295. case 'g': case 'G':
  296. transmitAnimations();
  297. break;
  298. case 's': case 'S':
  299. recieveAnimations();
  300. break;
  301. case 'v': case 'V':
  302. serialWriteString(getString(0));
  303. break;
  304. case 'm': case 'M':
  305. if (lastButtonState < (maxButtonState - 1)) {
  306. lastButtonState++;
  307. } else {
  308. lastButtonState = 0;
  309. }
  310. if (lastButtonState) {
  311. serialWriteString(getString(41));
  312. } else {
  313. serialWriteString(getString(40));
  314. }
  315. break;
  316. case 'q': case 'Q':
  317. shouldRestart = 1;
  318. serialWriteString(getString(30));
  319. break;
  320. case 'r': case 'R':
  321. randomAnimation();
  322. break;
  323. case 't': case 'T':
  324. printTime();
  325. break;
  326. case 'a': case 'A':
  327. sendAudioData();
  328. break;
  329. case 'c': case 'C':
  330. serialWriteString(itoa(getAnimationCount(), buffer, 10));
  331. serialWriteString(getString(15));
  332. break;
  333. case 'x': case 'X':
  334. // Get byte, store as animation count
  335. serialWriteString(getString(16));
  336. while (!serialHasChar());
  337. c = serialGet();
  338. setAnimationCount(c);
  339. serialWriteString(itoa(c, buffer, 10));
  340. serialWriteString(getString(17));
  341. break;
  342. case 'y': case 'Y':
  343. setAnimationCount(0x2201);
  344. serialWriteString(getString(18));
  345. break;
  346. case 'e': case 'E':
  347. selfTest();
  348. break;
  349. case 'n': case 'N':
  350. // snake();
  351. break;
  352. case '0':
  353. fillBuffer(0);
  354. disableAnim = 1;
  355. break;
  356. case '1':
  357. fillBuffer(0xFF);
  358. disableAnim = 1;
  359. break;
  360. case '3':
  361. setImage(defaultImageCube);
  362. disableAnim = 1;
  363. break;
  364. case '2':
  365. fillBuffer(0);
  366. while(1) {
  367. for (i = 0; i < 8; i++) {
  368. for (y = 0; y < 8; y++) {
  369. defaultImageCube[y + (i * 8)] = 0;
  370. for (z = 0; z < 8; z++) {
  371. defaultImageCube[y + (i * 8)] |= (1 << z);
  372. setImage(defaultImageCube);
  373. while (isFinished() == 0) {
  374. wdt_reset();
  375. if (serialHasChar()) {
  376. goto killMeForIt; // Yes I know...
  377. // But I need to break out of 2 while Loops...
  378. }
  379. }
  380. }
  381. // defaultImageCube[y + (i * 8)] = 0;
  382. }
  383. }
  384. }
  385. break;
  386. killMeForIt:
  387. serialGet(); // Killed because we got a serial char. Remove it from buffer.
  388. serialWriteString(getString(25));
  389. break;
  390. case 'I': case 'i':
  391. serialWriteString(ltoa(getTriggerCount(), buffer, 10));
  392. serialWrite('\n');
  393. break;
  394. default:
  395. serialWrite(ERROR);
  396. break;
  397. }
  398. // c was used as temp var and does not contain the char anymore...!
  399. }