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.

cubeWorker.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * cubeWorker.java
  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. /*
  24. * This class handles one animation file. This file can contain
  25. * many animations, but has to be only 1Mbit in size (128*1024 Byte).
  26. */
  27. import java.util.ArrayList;
  28. import java.util.List;
  29. import java.util.StringTokenizer;
  30. import java.util.Collections;
  31. /**
  32. * This class holds all Data of the Application. Additionally it performs the
  33. * transmission of animation data to/from the cube and saves/loads animations
  34. * in/from a file.
  35. *
  36. * @author Thomas Buck
  37. * @author Felix Bäder
  38. * @author Max Nuding
  39. * @version 1.0
  40. */
  41. public class cubeWorker {
  42. // --------------------
  43. // Definitions
  44. // --------------------
  45. final int UP = 0;
  46. final int DOWN = 1;
  47. // --------------------
  48. // Fields
  49. // --------------------
  50. private List<Animation> animations = new ArrayList<Animation>();
  51. private final int framesRemaining = 2016; // (128 * 1024) / 65 = 2016,...
  52. private boolean changedState = false;
  53. private Frame parentFrame;
  54. // --------------------
  55. /**
  56. * Creates a worker with one animation, containing an empty frame.
  57. */
  58. public cubeWorker(Frame parent) {
  59. animations.add(new Animation());
  60. animations.get(0).setName("Animation 1");
  61. animations.get(0).add(0);
  62. animations.get(0).get(0).setName("Frame 1");
  63. parentFrame = parent;
  64. }
  65. /**
  66. * Creates a worker from the given animation list
  67. *
  68. * @param anims List of animations
  69. */
  70. public cubeWorker(List<Animation> anims, Frame parent) {
  71. animations = anims;
  72. parentFrame = parent;
  73. }
  74. /**
  75. * Returns number of frames in this cubeWorker.
  76. *
  77. * @return number of frames.
  78. */
  79. public int completeNumOfFrames() {
  80. int count = 0;
  81. for (int i = 0; i < numOfAnimations(); i++) {
  82. count += numOfFrames(i);
  83. }
  84. return count;
  85. }
  86. // --------------------
  87. // Misc. Methods
  88. // --------------------
  89. // Returns a number that is below the size of the animations list and not used as order
  90. // If a order is higher or equal to the size of the list, it tries to assign a hole found to this
  91. // Returns -1 if there is no hole
  92. private int holeInAnimationList() {
  93. int s = animations.size();
  94. byte[] result = new byte[s];
  95. int hole = -1;
  96. int fix = -1;
  97. for (int i = 0; i < s; i++) {
  98. result[i] = 0;
  99. }
  100. for (int i = 0; i < s; i++) {
  101. int order = animations.get(i).getOrder();
  102. if (order >= s) {
  103. // Houston, we have a problem...
  104. fix = i;
  105. }
  106. result[order] = 1;
  107. }
  108. for (int i = 0; i < s; i++) {
  109. if (result[i] == 0) {
  110. hole = i;
  111. break;
  112. }
  113. }
  114. if ((hole != -1) && (fix != 1)) {
  115. animations.get(fix).setOrder(hole);
  116. return holeInAnimationList();
  117. }
  118. return hole;
  119. }
  120. // return true if damaged and to be sorted
  121. private boolean checkAnimationList() {
  122. for (int i = 0; i < animations.size(); i++) {
  123. if (animations.get(i).getOrder() != i) {
  124. int h = holeInAnimationList();
  125. if (h != -1) {
  126. animations.get(i).setOrder(h);
  127. }
  128. return true;
  129. }
  130. }
  131. return false;
  132. }
  133. /**
  134. * Get the number of animations in this worker.
  135. * Also fixes the order of the animation list, if needed.
  136. *
  137. * @return number of animations
  138. */
  139. public int numOfAnimations() {
  140. while(checkAnimationList()) {
  141. Collections.sort(animations);
  142. }
  143. return animations.size();
  144. }
  145. /**
  146. * Get the number of frames in an animation.
  147. *
  148. * @param selectedAnimation the animation you want to check
  149. * @return number of frames in this animation
  150. */
  151. public int numOfFrames(int selectedAnimation) {
  152. return animations.get(selectedAnimation).size();
  153. }
  154. /**
  155. * Get the number of frames you can add until the Cubes memory is full.
  156. *
  157. * @return number of frames remaining
  158. */
  159. public int framesRemaining() {
  160. return framesRemaining - completeNumOfFrames();
  161. }
  162. // --------------------
  163. // Animation Specific
  164. // --------------------
  165. /**
  166. * Add an animation. It has an initial empty frame
  167. *
  168. * @return Index of new animation, or -1 if not enough space remaining.
  169. */
  170. public int addAnimation() {
  171. changedState = true;
  172. if (framesRemaining() <= 0) {
  173. return -1;
  174. } else {
  175. int s = animations.size();
  176. animations.add(s, new Animation());
  177. animations.get(s).setName("Animation " + animations.size());
  178. animations.get(s).add(0, new AFrame());
  179. animations.get(s).get(0).setName("Frame 1");
  180. return s;
  181. }
  182. }
  183. /**
  184. * Remove an animation.
  185. *
  186. * @param selectedAnimation the animation you want to delete
  187. */
  188. public void removeAnimation(int selectedAnimation) {
  189. changedState = true;
  190. animations.remove(selectedAnimation);
  191. }
  192. /**
  193. * Get the name of an animation
  194. *
  195. * @return The name
  196. * @param selectedAnimation The animation you want to get the name from
  197. */
  198. public String getAnimationName(int selectedAnimation) {
  199. return animations.get(selectedAnimation).getName();
  200. }
  201. /**
  202. * Set the name of an animation  @param s New name
  203. *
  204. * @param selectedAnimation Index of the animation you want to change
  205. */
  206. public void setAnimationName(String s, int selectedAnimation) {
  207. changedState = true;
  208. animations.get(selectedAnimation).setName(s);
  209. }
  210. /**
  211. * Move an animation UP or DOWN.
  212. *
  213. * @param dir Direction. Use UP and DOWN defined in cubeWorker
  214. * @param selectedAnimation Animation you want to move
  215. */
  216. public void moveAnimation(int dir, int selectedAnimation) {
  217. changedState = true;
  218. if (dir == UP) {
  219. // animation moved up
  220. if (selectedAnimation > 0) {
  221. Animation tmp = animations.get(selectedAnimation);
  222. animations.set(selectedAnimation,
  223. animations.get(selectedAnimation - 1));
  224. animations.set(selectedAnimation - 1, tmp);
  225. }
  226. } else if (dir == DOWN) {
  227. // animation moved down
  228. if (selectedAnimation < (animations.size() - 1)) {
  229. Animation tmp = animations.get(selectedAnimation);
  230. animations.set(selectedAnimation,
  231. animations.get(selectedAnimation + 1));
  232. animations.set(selectedAnimation + 1, tmp);
  233. }
  234. }
  235. }
  236. // --------------------
  237. // Frame Specific
  238. // --------------------
  239. /**
  240. * Get the name of a frame.
  241. *
  242. * @param anim Animation the frame is in
  243. * @param frame Index of the frame
  244. */
  245. public String getFrameName(int anim, int frame) {
  246. return animations.get(anim).get(frame).getName();
  247. }
  248. /**
  249. * Set the name of a frame.
  250. *
  251. * @param s New name
  252. * @param anim Animation Index
  253. * @param frame Frame Index
  254. */
  255. public void setFrameName(String s, int anim, int frame) {
  256. changedState = true;
  257. animations.get(anim).get(frame).setName(s);
  258. }
  259. /**
  260. * Add a Frame to an animation.
  261. *
  262. * @return Index of new Frame or -1 if not enough space
  263. * @param anim Animation Index
  264. */
  265. public int addFrame(int anim) {
  266. changedState = true;
  267. if (framesRemaining() <= 0) {
  268. return -1;
  269. }
  270. int s = animations.get(anim).size();
  271. animations.get(anim).add(s);
  272. animations.get(anim).get(s)
  273. .setName("Frame " + animations.get(anim).size());
  274. return s;
  275. }
  276. /**
  277. * Remove a frame.
  278. *
  279. * @param anim Animation Index
  280. * @param frame Frame you want to remove
  281. */
  282. public void removeFrame(int anim, int frame) {
  283. changedState = true;
  284. animations.get(anim).remove(frame);
  285. }
  286. /**
  287. * Get the data of a frame.
  288. *
  289. * @param anim Animation Index  @param frame Frame Index
  290. * @return 64 byte array with data (8 bits per byte => 512 bits)
  291. */
  292. public short[] getFrame(int anim, int frame) {
  293. return animations.get(anim).get(frame).getData();
  294. }
  295. /**
  296. * Set the data of a frame
  297. *
  298. * @param data 64 byte array with data
  299. * @param anim Animation Index
  300. * @param frame Frame Index
  301. * @see cubeWorker#getFrame(int, int) getFrame()
  302. */
  303. public void setFrame(short[] data, int anim, int frame) {
  304. changedState = true;
  305. animations.get(anim).get(frame).setData(data);
  306. }
  307. /**
  308. * Get frame duration.
  309. *
  310. * @param anim Animation Index
  311. * @param frame Frame Index
  312. * @return Duration. 0 means 1/24th of a second.
  313. */
  314. public short getFrameTime(int anim, int frame) {
  315. return animations.get(anim).get(frame).getTime();
  316. }
  317. /**
  318. * Set the frames duration.
  319. *
  320. * @param time New duration
  321. * @param anim Animation Index
  322. * @param frame Frame Index
  323. * @see cubeWorker#getFrameTime(int, int) getFrameTime()
  324. */
  325. public void setFrameTime(short time, int anim, int frame) {
  326. changedState = true;
  327. animations.get(anim).get(frame).setTime(time);
  328. }
  329. /**
  330. * Move a frame.
  331. *
  332. * @param dir Direction to move. Use UP and DOWN from cubeWorker
  333. * @param anim Animation Index
  334. * @param frame Frame Index
  335. * @see cubeWorker#moveAnimation(int, int) moveAnimation()
  336. */
  337. public void moveFrame(int dir, int anim, int frame) {
  338. changedState = true;
  339. if (dir == UP) {
  340. // frame moved up
  341. if (frame > 0) {
  342. AFrame tmp = animations.get(anim).frames.get(frame);
  343. animations.get(anim).frames.set(frame,
  344. animations.get(anim).frames.get(frame - 1));
  345. animations.get(anim).frames.set(frame - 1, tmp);
  346. }
  347. } else if (dir == DOWN) {
  348. // frame moved down
  349. if (frame < (animations.get(anim).size() - 1)) {
  350. AFrame tmp = animations.get(anim).frames.get(frame);
  351. animations.get(anim).frames.set(frame,
  352. animations.get(anim).frames.get(frame + 1));
  353. animations.get(anim).frames.set(frame + 1, tmp);
  354. }
  355. }
  356. }
  357. // --------------------
  358. // File Specific
  359. // --------------------
  360. /**
  361. * Loads an animation file into this worker.
  362. *
  363. * @param path Path of file to load
  364. * @return 0 on success, -1 on error.
  365. */
  366. public int loadState(String path) {
  367. changedState = false;
  368. try {
  369. animations = AnimationUtility.readFile(path);
  370. } catch (Exception e) {
  371. System.out.println("Did not load!");
  372. e.printStackTrace(System.out);
  373. return -1;
  374. }
  375. int size = 0;
  376. for (int i = 0; i < animations.size(); i++) {
  377. size += animations.get(i).size();
  378. }
  379. if (size > framesRemaining) {
  380. return -1;
  381. }
  382. return 0;
  383. }
  384. /**
  385. * Save the state of this object into a file.
  386. *
  387. * @param path Path to save file in
  388. * @return 0 on success, -1 on error
  389. */
  390. public int saveState(String path) {
  391. changedState = false;
  392. AnimationUtility.writeFile(path, animations);
  393. if (AnimationUtility.getLastError() != null) {
  394. System.out.println(AnimationUtility.getLastError());
  395. return -1;
  396. }
  397. return 0;
  398. }
  399. /**
  400. * Check if something changed after loading/saving.
  401. *
  402. * @return TRUE if something changed, FALSE otherwise
  403. */
  404. public boolean changedStateSinceSave() {
  405. return changedState;
  406. }
  407. // --------------------
  408. // Serial Port Specific
  409. // --------------------
  410. /**
  411. * Send all animations to the cube.
  412. *
  413. * @param port Name of serial port to use
  414. * @return 0 on success, -1 on error
  415. */
  416. public int uploadState(String port) {
  417. try {
  418. SerialHelper sh = new SerialHelper(port, parentFrame);
  419. int ret = sh.sendAnimationsToCube(this);
  420. sh.closeSerialPort();
  421. return ret;
  422. } catch (Exception e) {
  423. return -1;
  424. }
  425. }
  426. /**
  427. * Get all animations from the cube, place it in this object
  428. *
  429. * @param port Name of serial port to use
  430. * @return 0 on success, -1 on error
  431. */
  432. public int downloadState(String port) {
  433. try {
  434. SerialHelper sh = new SerialHelper(port, parentFrame);
  435. cubeWorker ret = sh.getAnimationsFromCube();
  436. sh.closeSerialPort();
  437. if (ret == null) {
  438. return -1;
  439. } else {
  440. changedState = true;
  441. animations = ret.getAnimationList();
  442. return 0;
  443. }
  444. } catch (Exception e) {
  445. return -1;
  446. }
  447. }
  448. /**
  449. * Get the list used internally to store all the animations.
  450. * @return The list.
  451. */
  452. public List<Animation> getAnimationList() {
  453. return animations;
  454. }
  455. /**
  456. * Try to speak with the cube.
  457. *
  458. * @return TRUE if cube responds
  459. * @param port Name of serial port
  460. */
  461. public boolean probeCubeConnected(String port) {
  462. try {
  463. SerialHelper sh = new SerialHelper(port, parentFrame);
  464. boolean response = sh.probeForCube();
  465. sh.closeSerialPort();
  466. return response;
  467. } catch (Exception e) {
  468. return false;
  469. }
  470. }
  471. /**
  472. * Get the names of all available serial ports.
  473. *
  474. * @return Array of port names. First entry is "Select serial port..." if no
  475. * others
  476. */
  477. public String[] getSerialPorts() {
  478. String[] ports = { "Select serial port..." };
  479. String portLines = HelperUtility.getPorts();
  480. if (portLines == null) {
  481. return ports;
  482. }
  483. StringTokenizer sT = new StringTokenizer(portLines, "\n");
  484. int size = sT.countTokens();
  485. ports = new String[size];
  486. for (int i = 0; i < size; i++) {
  487. ports[i] = sT.nextToken();
  488. }
  489. return ports;
  490. }
  491. // --------------------
  492. }