drawing_test.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // This file is Copyright (c) 2023 Victor Suarez Rovere <suarezvictor@gmail.com>
  2. // SPDX-License-Identifier: AGPL-3.0-only
  3. #define RAND_SEED 0xABCDEF
  4. static uint32_t lfsr = RAND_SEED; //won't work until suitable seed is set
  5. void srand32(uint32_t seed)
  6. {
  7. lfsr = seed;
  8. }
  9. uint32_t rand32(void)
  10. {
  11. const uint32_t POLY_MASK = 0xB4BCD35C;
  12. int feedback = lfsr & 1;
  13. lfsr >>= 1;
  14. if (feedback)
  15. lfsr ^= POLY_MASK;
  16. return lfsr;
  17. }
  18. void flush_caches()
  19. {
  20. #if defined(FRAMEBUFFER_CACHE_HANDLING) && !defined(CSR_ACCEL_RECTANGLE_FILL32_BASE) && defined(CSR_ACCEL_ELLIPSE_FILL32_BASE)
  21. flush_l2_cache(); //corrects screen pixels
  22. flush_cpu_dcache();
  23. #endif
  24. }
  25. // drawing tests -----------------------------------------------------------------------------------
  26. void draw_char(char ch, int x, int y, int width, int height, uint32_t rgba)
  27. {
  28. if(ch == ':')
  29. {
  30. int x0 = x+4*width;
  31. int y0 = y+2*height;
  32. accel_ellipse_fill32(VIDEO_FRAMEBUFFER_BASE, x0, y0, x0+2*width, y0+4*height, rgba, FRAME_PITCH);
  33. y0 += 6*width;
  34. flush_caches();
  35. accel_ellipse_fill32(VIDEO_FRAMEBUFFER_BASE, x0, y0, x0+2*width, y0+4*height, rgba, FRAME_PITCH);
  36. return;
  37. }
  38. if(ch == '.')
  39. {
  40. int x0 = x+4*width;
  41. int y0 = y+12*height;
  42. flush_caches();
  43. accel_ellipse_fill32(VIDEO_FRAMEBUFFER_BASE, x0, y0, x0+2*width, y0+2*height, rgba, FRAME_PITCH);
  44. return;
  45. }
  46. if(ch < '0' || ch > '9')
  47. return;
  48. /*
  49. 012345
  50. WWWW 0
  51. WW WW 2
  52. WW WW 4
  53. WWWW 6
  54. WW WW 8
  55. WW WW 10
  56. WWWW 12
  57. */
  58. struct segment
  59. {
  60. const char *mask;
  61. int x, y, w, h;
  62. } const segments[7]={
  63. {"1011011111", 1, 0, 4, 2}, //A (top)
  64. {"1111100111", 4, 1, 2, 6}, //B (top right)
  65. {"1101111111", 4, 7, 2, 6}, //C (bottom right)
  66. {"1011011011", 1, 12, 4, 2}, //D (bottom)
  67. {"1010001010", 0, 7, 2, 6}, //E (bottom left)
  68. {"1000111011", 0, 1, 2, 6}, //F (top left)
  69. {"0011111011", 1, 6, 4, 2}, //G (middle)
  70. };
  71. const struct segment *s = segments;
  72. for(int i=0; i < 7; ++i, ++s)
  73. {
  74. if(s->mask[ch-'0'] != '0')
  75. {
  76. int x0 = x+width*s->x;
  77. int y0 = y+height*s->y;
  78. int x1 = x0+width*s->w;
  79. int y1 = y0+height*s->h;
  80. if(x0 >= 0 && x1 < FRAME_WIDTH && y0 >= 0 && y1 < FRAME_HEIGHT)
  81. {
  82. //FIXME: recheck condition...
  83. flush_caches();
  84. accel_rectangle_fill32(VIDEO_FRAMEBUFFER_BASE, x0, y0, x1, y1, rgba, FRAME_PITCH);
  85. }
  86. }
  87. }
  88. struct corner
  89. {
  90. const char *mask;
  91. int x, y, w, h;
  92. } const corners[6]={
  93. {"1000111011", 0, 0, 2, 2}, //top-left
  94. {"1011000111", 4, 0, 2, 2}, //top-right
  95. {"0010011000", 4, 6, 2, 2}, //center-right
  96. {"1001011011", 4, 12, 2, 2}, //bottom-right
  97. {"1010001010", 0, 12, 2, 2}, //bottom-left
  98. {"0010110001", 0, 6, 2, 2}, //center-left
  99. };
  100. const struct corner *c = corners;
  101. for(int i=0; i < 6; ++i, ++c)
  102. {
  103. if(c->mask[ch-'0'] != '0')
  104. {
  105. int x0 = x+width*c->x;
  106. int y0 = y+height*c->y;
  107. int x1 = x0+width*c->w;
  108. int y1 = y0+height*c->h;
  109. if(x0 >= 0 && x1 < FRAME_WIDTH && y0 >= 0 && y1 < FRAME_HEIGHT)
  110. {
  111. accel_ellipse_fill32(VIDEO_FRAMEBUFFER_BASE, x0, y0, x1, y1, rgba, FRAME_PITCH);
  112. }
  113. }
  114. }
  115. //accel_rectangle(x-2, y-2, x+width*6+2, y+height*15-5, rgba); //optionally draw some lines around digits
  116. }
  117. int draw_clock(uint32_t bkcolor)
  118. {
  119. static uint64_t ttarget;
  120. static int init = 0;
  121. if(!init)
  122. {
  123. ttarget = highres_ticks();
  124. init=1;
  125. accel_rectangle_fill32(VIDEO_FRAMEBUFFER_BASE, 0, 0, FRAME_WIDTH-1, FRAME_HEIGHT-1, bkcolor, FRAME_PITCH);
  126. srand32(RAND_SEED);
  127. }
  128. #define DIGITS 7 //7, 9 or 10
  129. int64_t dt = highres_ticks() - ttarget;
  130. const uint64_t period = highres_ticks_freq()/(DIGITS == 10 ? 100 : DIGITS == 9 ? 10 : 1);
  131. static char timedigits[11]=
  132. { //01234567890
  133. //XX:XX:XX.00
  134. __TIME__ ".00"
  135. };
  136. static int x0 = 10, y0 = 350;
  137. static int dx = 1, dy = 1;
  138. const int sz = 7;
  139. if(dt >= 0)
  140. {
  141. ttarget += period;
  142. int incr = 1;
  143. // 0123456789012345
  144. // XXYY:XXYY:XXYY.ZZZZ
  145. static const int pos[11]={0,2,3, 5,7,8, 10,12,13, 15,17};
  146. uint32_t color = rand32() | 0xFF004000;
  147. for(int i = DIGITS; i >= 0; --i) //9 for 1/10th seconds, 10 for 1/100th seconds
  148. {
  149. int isnum = timedigits[i] >= '0' && timedigits[i] <= '9';
  150. if(incr && isnum)
  151. {
  152. char ovf = (i==6 || i==3) ? '5':'9'; //overflow value (decimal or sexagesimal)
  153. if(timedigits[i] == ovf)
  154. timedigits[i]='0';
  155. else
  156. {
  157. ++timedigits[i];
  158. incr = 0; //stop carry
  159. }
  160. }
  161. int x = x0+pos[i]*4*sz;
  162. int y = y0;
  163. if(isnum) //FIXME: to avoid problems with superposition of characters, all previous digits should be drawn prior to current ones
  164. draw_char('8', x-dx, y-dy, sz, sz, bkcolor); //clear previous digit
  165. else
  166. draw_char(timedigits[i], x-dx, y-dy, sz, sz, bkcolor); //clear previous symbol
  167. //if(timedigits[i]==':')
  168. // color = timedigits[9]<'5' ? 0xFFC0C0C0 : bkcolor;
  169. draw_char(timedigits[i], x, y, sz, sz, color);
  170. }
  171. const int xlimit = FRAME_WIDTH-(pos[DIGITS]*4+7)*sz;
  172. const int ylimit = FRAME_HEIGHT-sz*(14+1);
  173. #if DIGITS == 7
  174. int x0_new = ((uint32_t)ttarget*37*41) % xlimit; //random like
  175. int y0_new = ((uint32_t)ttarget*43*67) % ylimit; //random like
  176. dx = x0_new-x0;
  177. dy = y0_new-y0;
  178. #else
  179. //bouncing
  180. if(x0 >= xlimit)
  181. dx = -1;
  182. if(x0 <= 0)
  183. dx = 1;
  184. if(y0 >= ylimit)
  185. dy = -1;
  186. if(y0 <= 1*sz)
  187. dy = 1;
  188. #endif
  189. x0 += dx;
  190. y0 += dy;
  191. flush_caches();
  192. return 1;
  193. }
  194. return 0;
  195. }