PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

308 lines
6.5KB

  1. #include <SPI.h>
  2. #include <RA8875.h>
  3. //uncomment for wireframe
  4. #define _WIREFRAME
  5. #define RA8875_CS 10
  6. #define RA8875_RESET 9//any pin or 255 to disable it!
  7. RA8875 tft = RA8875(RA8875_CS, RA8875_RESET);
  8. struct pt3d
  9. {
  10. int16_t x, y, z;
  11. };
  12. struct surface
  13. {
  14. uint8_t p[4];
  15. int16_t z;
  16. };
  17. struct pt2d
  18. {
  19. int16_t x, y;
  20. unsigned is_visible;
  21. };
  22. // define a value that corresponds to "1"
  23. #define U 300
  24. // eye to screen distance (fixed)
  25. #define ZS U
  26. // cube edge length is 2*U
  27. struct pt3d cube[8] =
  28. {
  29. { -U, -U, U},
  30. { U, -U, U},
  31. { U, -U, -U},
  32. { -U, -U, -U},
  33. { -U, U, U},
  34. { U, U, U},
  35. { U, U, -U},
  36. { -U, U, -U},
  37. };
  38. // define the surfaces
  39. struct surface cube_surface[6] =
  40. {
  41. { {0, 1, 2, 3}, 0 }, // bottom
  42. { {4, 5, 6, 7}, 0 }, // top
  43. { {0, 1, 5, 4}, 0 }, // back
  44. { {3, 7, 6, 2}, 0 }, // front
  45. { {1, 2, 6, 5}, 0 }, // right
  46. { {0, 3, 7, 4}, 0 }, // left
  47. };
  48. // define some structures for the copy of the box, calculation will be done there
  49. struct pt3d cube2[8];
  50. struct pt2d cube_pt[8];
  51. // will contain a rectangle border of the box projection into 2d plane
  52. int16_t x_min, x_max;
  53. int16_t y_min, y_max;
  54. const int16_t sin_tbl[65] = {
  55. 0, 1606, 3196, 4756, 6270, 7723, 9102, 10394, 11585, 12665, 13623, 14449, 15137, 15679, 16069, 16305, 16384, 16305, 16069, 15679,
  56. 15137, 14449, 13623, 12665, 11585, 10394, 9102, 7723, 6270, 4756, 3196, 1606, 0, -1605, -3195, -4755, -6269, -7722, -9101, -10393,
  57. -11584, -12664, -13622, -14448, -15136, -15678, -16068, -16304, -16383, -16304, -16068, -15678, -15136, -14448, -13622, -12664, -11584, -10393, -9101, -7722,
  58. -6269, -4755, -3195, -1605, 0
  59. };
  60. const int16_t cos_tbl[65] = {
  61. 16384, 16305, 16069, 15679, 15137, 14449, 13623, 12665, 11585, 10394, 9102, 7723, 6270, 4756, 3196, 1606, 0, -1605, -3195, -4755,
  62. -6269, -7722, -9101, -10393, -11584, -12664, -13622, -14448, -15136, -15678, -16068, -16304, -16383, -16304, -16068, -15678, -15136, -14448, -13622, -12664,
  63. -11584, -10393, -9101, -7722, -6269, -4755, -3195, -1605, 0, 1606, 3196, 4756, 6270, 7723, 9102, 10394, 11585, 12665, 13623, 14449,
  64. 15137, 15679, 16069, 16305, 16384
  65. };
  66. void copy_cube(void)
  67. {
  68. uint8_t i;
  69. for (i = 0; i < 8; i++)
  70. {
  71. cube2[i] = cube[i];
  72. }
  73. }
  74. void rotate_cube_y(uint16_t w)
  75. {
  76. uint8_t i;
  77. int16_t x, z;
  78. /*
  79. x' = x * cos(w) + z * sin(w)
  80. z' = - x * sin(w) + z * cos(w)
  81. */
  82. for (i = 0; i < 8; i++)
  83. {
  84. x = ((int32_t)cube2[i].x * (int32_t)cos_tbl[w] + (int32_t)cube2[i].z * (int32_t)sin_tbl[w]) >> 14;
  85. z = (-(int32_t)cube2[i].x * (int32_t)sin_tbl[w] + (int32_t)cube2[i].z * (int32_t)cos_tbl[w]) >> 14;
  86. //printf("%d: %d %d --> %d %d\n", i, cube2[i].x, cube2[i].z, x, z);
  87. cube2[i].x = x;
  88. cube2[i].z = z;
  89. }
  90. }
  91. void rotate_cube_x(uint16_t w)
  92. {
  93. uint8_t i;
  94. int16_t y, z;
  95. for (i = 0; i < 8; i++)
  96. {
  97. y = ((int32_t)cube2[i].y * (int32_t)cos_tbl[w] + (int32_t)cube2[i].z * (int32_t)sin_tbl[w]) >> 14;
  98. z = (-(int32_t)cube2[i].y * (int32_t)sin_tbl[w] + (int32_t)cube2[i].z * (int32_t)cos_tbl[w]) >> 14;
  99. cube2[i].y = y;
  100. cube2[i].z = z;
  101. }
  102. }
  103. void trans_cube(uint16_t z)
  104. {
  105. uint8_t i;
  106. for (i = 0; i < 8; i++)
  107. {
  108. cube2[i].z += z;
  109. }
  110. }
  111. void reset_min_max(void)
  112. {
  113. x_min = 0x07fff;
  114. y_min = 0x07fff;
  115. x_max = -0x07fff;
  116. y_max = -0x07fff;
  117. }
  118. // calculate xs and ys from a 3d value
  119. void convert_3d_to_2d(struct pt3d *p3, struct pt2d *p2)
  120. {
  121. int32_t t;
  122. p2->is_visible = 1;
  123. if (p3->z >= ZS)
  124. {
  125. t = ZS;
  126. t *= p3->x;
  127. t <<= 1;
  128. t /= p3->z;
  129. if (t >= -(tft.width() / 2) && t <= (tft.width() / 2) - 1)
  130. {
  131. t += (tft.width() / 2);
  132. p2->x = t;
  133. if (x_min > t) x_min = t;
  134. if (x_max < t) x_max = t;
  135. t = ZS;
  136. t *= p3->y;
  137. t <<= 1;
  138. t /= p3->z;
  139. if (t >= -(tft.height() / 2) && t <= (tft.height() / 2) - 1)
  140. {
  141. t += (tft.height() / 2);
  142. p2->y = t;
  143. if (y_min > t) y_min = t;
  144. if (y_max < t) y_max = t;
  145. }
  146. else
  147. {
  148. p2->is_visible = 0;
  149. }
  150. }
  151. else
  152. {
  153. p2->is_visible = 0;
  154. }
  155. }
  156. else
  157. {
  158. p2->is_visible = 0;
  159. }
  160. }
  161. void convert_cube(void)
  162. {
  163. uint8_t i;
  164. reset_min_max();
  165. for (i = 0; i < 8; i++)
  166. {
  167. convert_3d_to_2d(cube2 + i, cube_pt + i);
  168. }
  169. }
  170. void calculate_z(void)
  171. {
  172. uint8_t i, j;
  173. uint16_t z;
  174. for (i = 0; i < 6; i++)
  175. {
  176. z = 0;
  177. for (j = 0; j < 4; j++)
  178. {
  179. z += cube2[cube_surface[i].p[j]].z;
  180. }
  181. z /= 4;
  182. cube_surface[i].z = z;
  183. //printf("%d: z=%d\n", i, z);
  184. }
  185. }
  186. void draw_cube(void)
  187. {
  188. uint8_t i, ii;
  189. uint8_t skip_cnt = 3; /* it is known, that the first 3 surfaces are invisible */
  190. int16_t z, z_upper;
  191. uint16_t color;
  192. z_upper = 32767;
  193. for (;;)
  194. {
  195. ii = 6;
  196. z = -32767;
  197. for (i = 0; i < 6; i++)
  198. {
  199. if (cube_surface[i].z <= z_upper)
  200. {
  201. if (z < cube_surface[i].z)
  202. {
  203. z = cube_surface[i].z;
  204. ii = i;
  205. }
  206. }
  207. }
  208. if (ii >= 6) break;
  209. z_upper = cube_surface[ii].z;
  210. cube_surface[ii].z++;
  211. if (skip_cnt > 0)
  212. {
  213. skip_cnt--;
  214. }
  215. else
  216. {
  217. color = tft.Color565((uint8_t)(((ii + 1) & 1) * 255), (uint8_t)((((ii + 1) >> 1) & 1) * 255), (uint8_t)((((ii + 1) >> 2) & 1) * 255));
  218. #if defined(_WIREFRAME)
  219. tft.drawQuad(
  220. cube_pt[cube_surface[ii].p[0]].x, cube_pt[cube_surface[ii].p[0]].y,
  221. cube_pt[cube_surface[ii].p[1]].x, cube_pt[cube_surface[ii].p[1]].y,
  222. cube_pt[cube_surface[ii].p[2]].x, cube_pt[cube_surface[ii].p[2]].y,
  223. cube_pt[cube_surface[ii].p[3]].x, cube_pt[cube_surface[ii].p[3]].y, color);
  224. #else
  225. tft.fillQuad(
  226. cube_pt[cube_surface[ii].p[0]].x, cube_pt[cube_surface[ii].p[0]].y,
  227. cube_pt[cube_surface[ii].p[1]].x, cube_pt[cube_surface[ii].p[1]].y,
  228. cube_pt[cube_surface[ii].p[2]].x, cube_pt[cube_surface[ii].p[2]].y,
  229. cube_pt[cube_surface[ii].p[3]].x, cube_pt[cube_surface[ii].p[3]].y, color);
  230. #endif
  231. }
  232. }
  233. }
  234. void calc_and_draw(int16_t w, int16_t v)
  235. {
  236. copy_cube();
  237. rotate_cube_y(w);
  238. rotate_cube_x(v);
  239. trans_cube(U * 8);
  240. convert_cube();
  241. calculate_z();
  242. draw_cube();
  243. }
  244. void setup(void)
  245. {
  246. // Serial.begin(38400);
  247. // long unsigned debug_start = millis ();
  248. // while (!Serial && ((millis () - debug_start) <= 5000)) ;
  249. // Serial.println("RA8875 start");
  250. tft.begin(RA8875_800x480);
  251. }
  252. int16_t w = 0;
  253. int16_t v = 0;
  254. void loop(void)
  255. {
  256. calc_and_draw(w, v >> 3);
  257. v += 3;
  258. v &= 511;
  259. w++;
  260. w &= 63;
  261. delay(30);
  262. #if defined(_WIREFRAME)
  263. tft.fillRect(x_min, y_min, x_max - x_min + 3, y_max - y_min + 3, 0x0000);
  264. #else
  265. tft.fillRect(x_min, 0, x_max - x_min + 3, tft.height(), 0x0000);
  266. #endif
  267. }