/LEDMatrix.h

https://github.com/AaronLiddiment/LEDMatrix
C Header | 509 lines | 489 code | 18 blank | 2 comment | 139 complexity | 16e684273fa5e2d6c8c9253f49211415 MD5 | raw file
  1. #ifndef LEDMatrix_h
  2. #define LEDMatrix_h
  3. enum MatrixType_t { HORIZONTAL_MATRIX,
  4. VERTICAL_MATRIX,
  5. HORIZONTAL_ZIGZAG_MATRIX,
  6. VERTICAL_ZIGZAG_MATRIX };
  7. class cLEDMatrixBase
  8. {
  9. friend class cSprite;
  10. protected:
  11. int16_t m_Width, m_Height;
  12. MatrixType_t m_Type;
  13. struct CRGB *m_LED;
  14. struct CRGB m_OutOfBounds;
  15. public:
  16. cLEDMatrixBase();
  17. virtual uint16_t mXY(uint16_t x, uint16_t y)=0;
  18. void SetLEDArray(struct CRGB *pLED); // Only used with externally defined LED arrays
  19. struct CRGB *operator[](int n);
  20. struct CRGB &operator()(int16_t x, int16_t y);
  21. struct CRGB &operator()(int16_t i);
  22. int Size() { return(m_Width * m_Height); }
  23. int Width() { return(m_Width); }
  24. int Height() { return(m_Height); }
  25. void HorizontalMirror(bool FullHeight = true);
  26. void VerticalMirror();
  27. void QuadrantMirror();
  28. void QuadrantRotateMirror();
  29. void TriangleTopMirror(bool FullHeight = true);
  30. void TriangleBottomMirror(bool FullHeight = true);
  31. void QuadrantTopTriangleMirror();
  32. void QuadrantBottomTriangleMirror();
  33. void DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, CRGB Col);
  34. void DrawRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, CRGB Col);
  35. void DrawCircle(int16_t xc, int16_t yc, uint16_t r, CRGB Col);
  36. void DrawFilledRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, CRGB Col);
  37. void DrawFilledCircle(int16_t xc, int16_t yc, uint16_t r, CRGB Col);
  38. };
  39. template<int16_t tWidth, int16_t tHeight, MatrixType_t tMType, int16_t tXMult = 0, int16_t tYMult = 0> class cLEDMatrix : public cLEDMatrixBase
  40. {
  41. private:
  42. static const int16_t m_absWidth = (tWidth * ((tWidth < 0) * -1 + (tWidth > 0)));
  43. static const int16_t m_absHeight = (tHeight * ((tHeight < 0) * -1 + (tHeight > 0)));
  44. struct CRGB p_LED[(m_absWidth * m_absHeight * ((tXMult == 0) && (tXMult == 0))) + ((tXMult != 0) && (tXMult != 0))]; // Will always be at least 1
  45. public:
  46. cLEDMatrix()
  47. {
  48. m_Width = m_absWidth;
  49. m_Height = m_absHeight;
  50. m_Type = tMType;
  51. if ((tXMult == 0) && (tYMult == 0))
  52. m_LED = p_LED;
  53. else
  54. m_LED = NULL;
  55. }
  56. void SetLEDArray(struct CRGB *pLED)
  57. {
  58. m_LED = pLED;
  59. }
  60. virtual uint16_t mXY(uint16_t x, uint16_t y)
  61. {
  62. if (tWidth < 0)
  63. x = (m_absWidth - 1) - x;
  64. if (tHeight < 0)
  65. y = (m_absHeight - 1) - y;
  66. if (tMType == HORIZONTAL_MATRIX)
  67. {
  68. if ((tXMult == 0) && (tYMult == 0))
  69. return((y * m_absWidth) + x);
  70. else
  71. return((y * m_absWidth * tYMult) + (x * tXMult));
  72. }
  73. else if (tMType == VERTICAL_MATRIX)
  74. {
  75. if ((tXMult == 0) && (tYMult == 0))
  76. return((x * m_absHeight) + y);
  77. else
  78. return((x * m_absHeight * tXMult) + (y * tYMult));
  79. }
  80. else if (tMType == HORIZONTAL_ZIGZAG_MATRIX)
  81. {
  82. if (y % 2)
  83. {
  84. if ((tXMult == 0) && (tYMult == 0))
  85. return((((y + 1) * m_absWidth) - 1) - x);
  86. else
  87. return((((y + 1) * m_absWidth * tYMult) - tXMult) - (x * tXMult));
  88. }
  89. else
  90. {
  91. if ((tXMult == 0) && (tYMult == 0))
  92. return((y * m_absWidth) + x);
  93. else
  94. return((y * m_absWidth * tYMult) + (x * tXMult));
  95. }
  96. }
  97. else /* if (tMType == VERTICAL_ZIGZAG_MATRIX) */
  98. {
  99. if (x % 2)
  100. {
  101. if ((tXMult == 0) && (tYMult == 0))
  102. return((((x + 1) * m_absHeight) - 1) - y);
  103. else
  104. return((((x + 1) * m_absHeight * tXMult) - tYMult) - (y * tYMult));
  105. }
  106. else
  107. {
  108. if ((tXMult == 0) && (tYMult == 0))
  109. return((x * m_absHeight) + y);
  110. else
  111. return((x * m_absHeight * tXMult) + (y * tYMult));
  112. }
  113. }
  114. }
  115. void ShiftLeft(void)
  116. {
  117. if ((tXMult == 0) && (tYMult == 0))
  118. {
  119. switch (tMType)
  120. {
  121. case HORIZONTAL_MATRIX:
  122. if (tWidth > 0)
  123. HPWSL();
  124. else
  125. HNWSL();
  126. break;
  127. case VERTICAL_MATRIX:
  128. if (tWidth > 0)
  129. VPWSL();
  130. else
  131. VNWSL();
  132. break;
  133. case HORIZONTAL_ZIGZAG_MATRIX:
  134. if (tWidth > 0)
  135. HZPWSL();
  136. else
  137. HZNWSL();
  138. break;
  139. case VERTICAL_ZIGZAG_MATRIX:
  140. if (tWidth > 0)
  141. VZPWSL();
  142. else
  143. VZNWSL();
  144. break;
  145. }
  146. }
  147. }
  148. void ShiftRight(void)
  149. {
  150. if ((tXMult == 0) && (tYMult == 0))
  151. {
  152. switch (tMType)
  153. {
  154. case HORIZONTAL_MATRIX:
  155. if (tWidth > 0)
  156. HNWSL();
  157. else
  158. HPWSL();
  159. break;
  160. case VERTICAL_MATRIX:
  161. if (tWidth > 0)
  162. VNWSL();
  163. else
  164. VPWSL();
  165. break;
  166. case HORIZONTAL_ZIGZAG_MATRIX:
  167. if (tWidth > 0)
  168. HZNWSL();
  169. else
  170. HZPWSL();
  171. break;
  172. case VERTICAL_ZIGZAG_MATRIX:
  173. if (tWidth > 0)
  174. VZNWSL();
  175. else
  176. VZPWSL();
  177. break;
  178. }
  179. }
  180. }
  181. void ShiftDown(void)
  182. {
  183. if ((tXMult == 0) && (tYMult == 0))
  184. {
  185. switch (tMType)
  186. {
  187. case HORIZONTAL_MATRIX:
  188. if (tHeight > 0)
  189. HPHSD();
  190. else
  191. HNHSD();
  192. break;
  193. case VERTICAL_MATRIX:
  194. if (tHeight > 0)
  195. VPHSD();
  196. else
  197. VNHSD();
  198. break;
  199. case HORIZONTAL_ZIGZAG_MATRIX:
  200. if (tHeight > 0)
  201. HZPHSD();
  202. else
  203. HZNHSD();
  204. break;
  205. case VERTICAL_ZIGZAG_MATRIX:
  206. if (tHeight > 0)
  207. VZPHSD();
  208. else
  209. VZNHSD();
  210. break;
  211. }
  212. }
  213. }
  214. void ShiftUp(void)
  215. {
  216. if ((tXMult == 0) && (tYMult == 0))
  217. {
  218. switch (tMType)
  219. {
  220. case HORIZONTAL_MATRIX:
  221. if (tHeight > 0)
  222. HNHSD();
  223. else
  224. HPHSD();
  225. break;
  226. case VERTICAL_MATRIX:
  227. if (tHeight > 0)
  228. VNHSD();
  229. else
  230. VPHSD();
  231. break;
  232. case HORIZONTAL_ZIGZAG_MATRIX:
  233. if (tHeight > 0)
  234. HZNHSD();
  235. else
  236. HZPHSD();
  237. break;
  238. case VERTICAL_ZIGZAG_MATRIX:
  239. if (tHeight > 0)
  240. VZNHSD();
  241. else
  242. VZPHSD();
  243. break;
  244. }
  245. }
  246. }
  247. private:
  248. // Functions used by ShiftLeft & ShiftRight
  249. void HPWSL(void)
  250. {
  251. int16_t i = 0;
  252. for (int16_t y=m_absHeight; y>0; --y,++i)
  253. {
  254. for (int16_t x=m_absWidth-1; x>0; --x,++i)
  255. p_LED[i] = p_LED[i + 1];
  256. p_LED[i] = CRGB(0, 0, 0);
  257. }
  258. }
  259. void HNWSL(void)
  260. {
  261. int16_t i = m_absWidth - 1;
  262. for (int16_t y=m_absHeight; y>0; --y)
  263. {
  264. for (int16_t x=m_absWidth-1; x>0; --x,--i)
  265. p_LED[i] = p_LED[i - 1];
  266. p_LED[i] = CRGB(0, 0, 0);
  267. i += ((m_absWidth * 2) - 1);
  268. }
  269. }
  270. void VPWSL(void)
  271. {
  272. int16_t i = 0;
  273. int16_t j = m_absHeight;
  274. for (int16_t x=m_absWidth-1; x>0; --x)
  275. {
  276. for (int16_t y=m_absHeight; y>0; --y)
  277. p_LED[i++] = p_LED[j++];
  278. }
  279. for (int16_t y=m_absHeight; y>0; --y)
  280. p_LED[i++] = CRGB(0, 0, 0);
  281. }
  282. void VNWSL(void)
  283. {
  284. int16_t i = (m_absHeight * m_absWidth) - 1;
  285. int16_t j = i - m_absHeight;
  286. for (int16_t x=m_absWidth-1; x>0; --x)
  287. {
  288. for (int16_t y=m_absHeight; y>0; --y)
  289. p_LED[i--] = p_LED[j--];
  290. }
  291. for (int16_t y=m_absHeight; y>0; --y)
  292. p_LED[i--] = CRGB(0, 0, 0);
  293. }
  294. void HZPWSL(void)
  295. {
  296. int16_t i = 0;
  297. for (int16_t y=m_absHeight; y>0; y-=2)
  298. {
  299. for (int16_t x=m_absWidth-1; x>0; --x,++i)
  300. p_LED[i] = p_LED[i + 1];
  301. p_LED[i] = CRGB(0, 0, 0);
  302. i++;
  303. if (y > 1)
  304. {
  305. i += (m_absWidth - 1);
  306. for (int16_t x=m_absWidth-1; x>0; --x,--i)
  307. p_LED[i] = p_LED[i - 1];
  308. p_LED[i] = CRGB(0, 0, 0);
  309. i += m_absWidth;
  310. }
  311. }
  312. }
  313. void HZNWSL(void)
  314. {
  315. int16_t i = m_absWidth - 1;
  316. for (int16_t y=m_absHeight; y>0; y-=2)
  317. {
  318. for (int16_t x=m_absWidth-1; x>0; --x,--i)
  319. p_LED[i] = p_LED[i - 1];
  320. p_LED[i] = CRGB(0, 0, 0);
  321. if (y > 1)
  322. {
  323. i += m_absWidth;
  324. for (int16_t x=m_absWidth-1; x>0; --x,++i)
  325. p_LED[i] = p_LED[i + 1];
  326. p_LED[i] = CRGB(0, 0, 0);
  327. i += m_absWidth;
  328. }
  329. }
  330. }
  331. void VZPWSL(void)
  332. {
  333. int16_t i = 0;
  334. int16_t j = (m_absHeight * 2) - 1;
  335. for (int16_t x=m_absWidth-1; x>0; x-=2)
  336. {
  337. for (int16_t y=m_absHeight; y>0; --y)
  338. p_LED[i++] = p_LED[j--];
  339. if (x > 1)
  340. {
  341. j += (m_absHeight * 2);
  342. for (int16_t y=m_absHeight; y>0; --y)
  343. p_LED[i++] = p_LED[j--];
  344. j += (m_absHeight * 2);
  345. }
  346. }
  347. for (int16_t y=m_absHeight; y>0; y--)
  348. p_LED[i++] = CRGB(0, 0, 0);
  349. }
  350. void VZNWSL(void)
  351. {
  352. int16_t i = (m_absHeight * m_absWidth) - 1;
  353. int16_t j = m_absHeight * (m_absWidth - 2);
  354. for (int16_t x=m_absWidth-1; x>0; x-=2)
  355. {
  356. for (int16_t y=m_absHeight; y>0; --y)
  357. p_LED[i--] = p_LED[j++];
  358. if (x > 1)
  359. {
  360. j -= (m_absHeight * 2);
  361. for (int16_t y=m_absHeight; y>0; --y)
  362. p_LED[i--] = p_LED[j++];
  363. j -= (m_absHeight * 2);
  364. }
  365. }
  366. for (int16_t y=m_absHeight; y>0; y--)
  367. p_LED[i--] = CRGB(0, 0, 0);
  368. }
  369. // Functions used by ShiftDown & ShiftUp
  370. void HPHSD(void)
  371. {
  372. int16_t i = 0;
  373. int16_t j = m_absWidth;
  374. for (int16_t y=m_absHeight-1; y>0; --y)
  375. {
  376. for (int16_t x=m_absWidth; x>0; --x)
  377. p_LED[i++] = p_LED[j++];
  378. }
  379. for (int16_t x=m_absWidth; x>0; --x)
  380. p_LED[i++] = CRGB(0, 0, 0);
  381. }
  382. void HNHSD(void)
  383. {
  384. int16_t i = (m_absWidth * m_absHeight) - 1;
  385. int16_t j = i - m_absWidth;
  386. for (int16_t y=m_absHeight-1; y>0; --y)
  387. {
  388. for (int16_t x=m_absWidth; x>0; --x)
  389. p_LED[i--] = p_LED[j--];
  390. }
  391. for (int16_t x=m_absWidth; x>0; --x)
  392. p_LED[i--] = CRGB(0, 0, 0);
  393. }
  394. void VPHSD(void)
  395. {
  396. int16_t i = 0;
  397. for (int16_t x=m_absWidth; x>0; --x,++i)
  398. {
  399. for (int16_t y=m_absHeight-1; y>0; --y,++i)
  400. p_LED[i] = p_LED[i + 1];
  401. p_LED[i] = CRGB(0, 0, 0);
  402. }
  403. }
  404. void VNHSD(void)
  405. {
  406. int16_t i = m_absHeight - 1;
  407. for (int16_t x=m_absWidth; x>0; --x)
  408. {
  409. for (int16_t y=m_absHeight-1; y>0; --y,--i)
  410. p_LED[i] = p_LED[i - 1];
  411. p_LED[i] = CRGB(0, 0, 0);
  412. i += ((m_absHeight * 2) - 1);
  413. }
  414. }
  415. void HZPHSD(void)
  416. {
  417. int16_t i = 0;
  418. int16_t j = (m_absWidth * 2) - 1;
  419. for (int16_t y=m_absHeight-1; y>0; y-=2)
  420. {
  421. for (int16_t x=m_absWidth; x>0; --x)
  422. p_LED[i++] = p_LED[j--];
  423. if (y > 1)
  424. {
  425. j += (m_absWidth * 2);
  426. for (int16_t x=m_absWidth; x>0; --x)
  427. p_LED[i++] = p_LED[j--];
  428. j += (m_absWidth * 2);
  429. }
  430. }
  431. for (int16_t x=m_absWidth; x>0; x--)
  432. p_LED[i++] = CRGB(0, 0, 0);
  433. }
  434. void HZNHSD(void)
  435. {
  436. int16_t i = (m_absWidth * m_absHeight) - 1;
  437. int16_t j = m_absWidth * (m_absHeight - 2);
  438. for (int16_t y=m_absHeight-1; y>0; y-=2)
  439. {
  440. for (int16_t x=m_absWidth; x>0; --x)
  441. p_LED[i--] = p_LED[j++];
  442. if (y > 1)
  443. {
  444. j -= (m_absWidth * 2);
  445. for (int16_t x=m_absWidth; x>0; --x)
  446. p_LED[i--] = p_LED[j++];
  447. j -= (m_absWidth * 2);
  448. }
  449. }
  450. for (int16_t x=m_absWidth; x>0; x--)
  451. p_LED[i--] = CRGB(0, 0, 0);
  452. }
  453. void VZPHSD(void)
  454. {
  455. int16_t i = 0;
  456. for (int16_t x=m_absWidth; x>0; x-=2)
  457. {
  458. for (int16_t y=m_absHeight-1; y>0; --y,++i)
  459. p_LED[i] = p_LED[i + 1];
  460. p_LED[i] = CRGB(0, 0, 0);
  461. i++;
  462. if (x > 1)
  463. {
  464. i += (m_absHeight - 1);
  465. for (int16_t y=m_absHeight-1; y>0; --y,--i)
  466. p_LED[i] = p_LED[i - 1];
  467. p_LED[i] = CRGB(0, 0, 0);
  468. i += m_absHeight;
  469. }
  470. }
  471. }
  472. void VZNHSD(void)
  473. {
  474. int16_t i = m_absHeight - 1;
  475. for (int16_t x=m_absWidth; x>0; x-=2)
  476. {
  477. for (int16_t y=m_absHeight-1; y>0; --y,--i)
  478. p_LED[i] = p_LED[i - 1];
  479. p_LED[i] = CRGB(0, 0, 0);
  480. if (x > 1)
  481. {
  482. i += m_absHeight;
  483. for (int16_t y=m_absHeight-1; y>0; --y,++i)
  484. p_LED[i] = p_LED[i + 1];
  485. p_LED[i] = CRGB(0, 0, 0);
  486. i += m_absHeight;
  487. }
  488. }
  489. }
  490. };
  491. #endif