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.

cubeWorker.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * cubeWorker.java
  3. *
  4. * Copyright 2012 Thomas Buck <xythobuz@me.com>
  5. *
  6. * This file is part of LED-Cube.
  7. *
  8. * LED-Cube is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * LED-Cube is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with LED-Cube. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. /*
  22. * This class handles one animation file. This file can contain
  23. * many animations, but has to be only 1Mbit in size (128*1024 Byte).
  24. */
  25. import java.util.ArrayList;
  26. import java.util.List;
  27. import java.util.StringTokenizer;
  28. import java.util.Collections;
  29. /**
  30. * This class holds all Data of the Application. Additionally it performs the
  31. * transmission of animation data to/from the cube and saves/loads animations
  32. * in/from a file.
  33. *
  34. * @author Thomas Buck
  35. * @version 1.0
  36. */
  37. public class cubeWorker {
  38. private final int framesRemaining = 2016; // (128 * 1024) / 65 = 2016,...
  39. private boolean changedState = false;
  40. private Frame parentFrame;
  41. private Animation[] animations = new Animation[1];
  42. /**
  43. * Creates a worker with one animation, containing an empty frame.
  44. */
  45. public cubeWorker(Frame parent) {
  46. animations[0] = new Animation();
  47. parentFrame = parent;
  48. }
  49. public cubeWorker(Animation[] anims, Frame parent) {
  50. animations = anims;
  51. parentFrame = parent;
  52. }
  53. /**
  54. * Returns number of frames in this cubeWorker.
  55. *
  56. * @return number of frames.
  57. */
  58. public int completeNumOfFrames() {
  59. int c = 0;
  60. for (int i = 0; i < size(); i++) {
  61. c += getAnimation(i).size();
  62. }
  63. return c;
  64. }
  65. // --------------------
  66. // Misc. Methods
  67. // --------------------
  68. /**
  69. * Get the number of animations in this worker.
  70. *
  71. * @return number of animations
  72. */
  73. public int size() {
  74. return animations.length;
  75. }
  76. /**
  77. * Get the number of frames you can add until the Cubes memory is full.
  78. *
  79. * @return number of frames remaining
  80. */
  81. public int memoryRemaining() {
  82. return framesRemaining - completeNumOfFrames();
  83. }
  84. /**
  85. * Add an animation. It has an initial empty frame
  86. *
  87. * @return Index of new animation, or -1 if not enough space remaining.
  88. */
  89. public int addAnimation() {
  90. changedState = true;
  91. if (memoryRemaining() <= 0) {
  92. return -1;
  93. } else {
  94. extendArray();
  95. animations[animations.length - 1] = new Animation();
  96. return animations.length - 1;
  97. }
  98. }
  99. /**
  100. * Remove an animation.
  101. *
  102. * @param i the animation you want to delete
  103. */
  104. public void removeAnimation(int i) {
  105. changedState = true;
  106. shiftOver(i);
  107. shrinkArray();
  108. }
  109. /**
  110. * Move an animation up.
  111. * @param i the animation you want to move
  112. */
  113. public void moveAnimationUp(int i) {
  114. if (i > 0) {
  115. Animation tmp = animations[i];
  116. animations[i] = animations[i - 1];
  117. animations[i - 1] = tmp;
  118. }
  119. }
  120. /**
  121. * Move an animation down.
  122. * @param i the animation you want to move
  123. */
  124. public void moveAnimationDown(int i) {
  125. if (i < (animations.length - 1)) {
  126. Animation tmp = animations[i];
  127. animations[i] = animations[i + 1];
  128. animations[i + 1] = tmp;
  129. }
  130. }
  131. public Animation getAnimation(int i) {
  132. if (i < animations.length) {
  133. return animations[i];
  134. } else {
  135. return null;
  136. }
  137. }
  138. public void setAnimation(Animation a, int i) {
  139. changedState = true;
  140. if (i < animations.length) {
  141. animations[i] = a;
  142. }
  143. }
  144. /**
  145. * Loads an animation file into this worker.
  146. *
  147. * @param path Path of file to load
  148. * @return 0 on success, -1 on error.
  149. */
  150. public int loadState(String path) {
  151. changedState = false;
  152. try {
  153. animations = AnimationUtility.readFile(path);
  154. } catch (Exception e) {
  155. System.out.println("Did not load!");
  156. e.printStackTrace(System.out);
  157. return -1;
  158. }
  159. int size = 0;
  160. for (int i = 0; i < animations.length; i++) {
  161. size += animations[i].size();
  162. }
  163. if (size > framesRemaining) {
  164. return -1;
  165. }
  166. return 0;
  167. }
  168. /**
  169. * Save the state of this object into a file.
  170. *
  171. * @param path Path to save file in
  172. * @return 0 on success, -1 on error
  173. */
  174. public int saveState(String path) {
  175. changedState = false;
  176. AnimationUtility.writeFile(path, animations);
  177. if (AnimationUtility.getLastError() != null) {
  178. System.out.println(AnimationUtility.getLastError());
  179. return -1;
  180. }
  181. return 0;
  182. }
  183. /**
  184. * Check if something changed after loading/saving.
  185. *
  186. * @return TRUE if something changed, FALSE otherwise
  187. */
  188. public boolean changedStateSinceSave() {
  189. return changedState;
  190. }
  191. /**
  192. * Get the array of animations in this worker.
  193. * @return animation array
  194. */
  195. public Animation[] getAnimationArray() {
  196. return animations;
  197. }
  198. /**
  199. * Send all animations to the cube.
  200. *
  201. * @param port Name of serial port to use
  202. * @return 0 on success, -1 on error
  203. */
  204. public int cubeSendState(String port) {
  205. int a, f;
  206. short[] d;
  207. if (HelperUtility.openPort(port) == false) {
  208. error("Could not open Port!");
  209. return -1;
  210. }
  211. // Send command
  212. d = new short[1];
  213. d[0] = 's';
  214. if (HelperUtility.writeData(d, 1) == false) {
  215. error("Could not write to port!");
  216. HelperUtility.closePort();
  217. return -1;
  218. }
  219. // Recieve ack
  220. d = HelperUtility.readData(1);
  221. if (d.length == 0) {
  222. error("Could not read from port!");
  223. HelperUtility.closePort();
  224. return -1;
  225. }
  226. if (d[0] != 0x42) {
  227. error("Cube not OK!");
  228. HelperUtility.closePort();
  229. return -1;
  230. }
  231. System.out.println("Command sent!");
  232. // Send animation count
  233. d = new short[1];
  234. if (animations.length >= 255) {
  235. error("Too many animations");
  236. return -1;
  237. }
  238. d[0] = (short)animations.length;
  239. if (HelperUtility.writeData(d, 1) == false) {
  240. error("Could not write to port!");
  241. HelperUtility.closePort();
  242. return -1;
  243. }
  244. // Recieve ack
  245. d = HelperUtility.readData(1);
  246. if (d.length == 0) {
  247. error("Could not read from port!");
  248. HelperUtility.closePort();
  249. return -1;
  250. }
  251. if (d[0] != 0x42) {
  252. error("Cube not OK!");
  253. HelperUtility.closePort();
  254. return -1;
  255. }
  256. System.out.println("Animation count sent (" + animations.length + ")!");
  257. for (a = 0; a < animations.length; a++) {
  258. // Send frame count
  259. d = new short[1];
  260. if (animations[a].size() >= 255) {
  261. error("Too many frames!");
  262. HelperUtility.closePort();
  263. return -1;
  264. }
  265. d[0] = (short)animations[a].size();
  266. if (HelperUtility.writeData(d, 1) == false) {
  267. error("Could not write to port!");
  268. HelperUtility.closePort();
  269. return -1;
  270. }
  271. // Recieve ack
  272. d = HelperUtility.readData(1);
  273. if (d.length == 0) {
  274. error("Could not read from port!");
  275. HelperUtility.closePort();
  276. return -1;
  277. }
  278. if (d[0] != 0x42) {
  279. error("Cube not OK!");
  280. HelperUtility.closePort();
  281. return -1;
  282. }
  283. System.out.println("Frame count sent (" + animations[a].size() + ")!");
  284. for (f = 0; f < animations[a].size(); f++) {
  285. // Send duration
  286. d = new short[1];
  287. d[0] = animations[a].getFrame(f).getTime();
  288. if (HelperUtility.writeData(d, 1) == false) {
  289. error("Could not write to port!");
  290. HelperUtility.closePort();
  291. return -1;
  292. }
  293. // Recieve ack
  294. d = HelperUtility.readData(1);
  295. if (d.length == 0) {
  296. error("Could not read from port!");
  297. HelperUtility.closePort();
  298. return -1;
  299. }
  300. if (d[0] != 0x42) {
  301. error("Cube not OK!");
  302. HelperUtility.closePort();
  303. return -1;
  304. }
  305. System.out.println("Duration sent (" + animations[a].getFrame(f).getTime() + ")!");
  306. // Send data
  307. d = animations[a].getFrame(f).getData();
  308. if (HelperUtility.writeData(d, 64) == false) {
  309. error("Could not write to port!");
  310. HelperUtility.closePort();
  311. return -1;
  312. }
  313. // Recieve ack
  314. d = HelperUtility.readData(1);
  315. if (d.length == 0) {
  316. error("Could not read from port!");
  317. HelperUtility.closePort();
  318. return -1;
  319. }
  320. if (d[0] != 0x42) {
  321. error("Cube not OK!");
  322. HelperUtility.closePort();
  323. return -1;
  324. }
  325. System.out.println("Data sent");
  326. }
  327. }
  328. // Send finish sequence
  329. d = new short[4];
  330. d[0] = 0x42;
  331. d[1] = 0x42;
  332. d[2] = 0x42;
  333. d[3] = 0x42;
  334. if (HelperUtility.writeData(d, 4) == false) {
  335. error("Could not write to port!");
  336. HelperUtility.closePort();
  337. return -1;
  338. }
  339. // Recieve ack
  340. d = HelperUtility.readData(1);
  341. if (d.length == 0) {
  342. error("Could not read from port!");
  343. HelperUtility.closePort();
  344. return -1;
  345. }
  346. if (d[0] != 0x42) {
  347. error("Cube not OK!");
  348. HelperUtility.closePort();
  349. return -1;
  350. }
  351. System.out.println("Uploaded animations!");
  352. return 0;
  353. }
  354. /**
  355. * Get all animations from the cube, place it in this object
  356. *
  357. * @param port Name of serial port to use
  358. * @return 0 on success, -1 on error
  359. */
  360. // We generate error messages in here
  361. public int cubeGetState(String port) {
  362. return -1;
  363. }
  364. /**
  365. * Try to speak with the cube.
  366. *
  367. * @return TRUE if cube responds
  368. * @param port Name of serial port
  369. */
  370. public boolean cubeProbeConnected(String port) {
  371. if (HelperUtility.openPort(port) == false) {
  372. error("Could not open Port!");
  373. return false;
  374. }
  375. short[] d = new short[1];
  376. d[0] = 0x42;
  377. if (HelperUtility.writeData(d, 1) == false) {
  378. error("Could not write to port!");
  379. HelperUtility.closePort();
  380. return false;
  381. }
  382. d = HelperUtility.readData(1);
  383. if (d.length == 0) {
  384. error("Could not read from port!");
  385. HelperUtility.closePort();
  386. return false;
  387. }
  388. HelperUtility.closePort();
  389. if (d[0] != 0x42) {
  390. error("Answer was not OK");
  391. return false;
  392. } else {
  393. System.out.println("Got probe response!");
  394. return true;
  395. }
  396. }
  397. private void error(String s) {
  398. System.out.println(s);
  399. parentFrame.errorMessage("Serial Error", s);
  400. }
  401. private void extendArray() {
  402. Animation newArray[] = new Animation[animations.length + 1];
  403. for (int i = 0; i < animations.length; i++) {
  404. newArray[i] = animations[i];
  405. }
  406. animations = newArray;
  407. }
  408. private void shrinkArray() {
  409. Animation newArray[] = new Animation[animations.length - 1];
  410. for (int i = 0; i < newArray.length; i++) {
  411. newArray[i] = animations[i];
  412. }
  413. animations = newArray;
  414. }
  415. private void shiftOver(int toForget) {
  416. for (int i = (toForget + 1); i < animations.length; i++) {
  417. animations[i - 1] = animations[i];
  418. }
  419. }
  420. }