GFX_SSD1327.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. * GFX_SSD1327.h
  3. *
  4. * The MIT License.
  5. * Created on: 5.08.2020
  6. * Author: Mateusz Salamon
  7. * www.msalamon.pl
  8. * mateusz@msalamon.pl
  9. */
  10. #include "main.h"
  11. #include "GFX_SSD1327.h"
  12. #include "OLED_SSD1327.h"
  13. #if USING_LINES == 1
  14. #include <stdlib.h> // for abs() function
  15. #endif
  16. #if USING_IMAGE_ROTATE == 1
  17. #include <math.h>
  18. #endif
  19. #define _swap_int(a, b) { int t = a; a = b; b = t; }
  20. #if USING_STRINGS == 1
  21. const uint8_t* font;
  22. uint8_t size = 1;
  23. void GFX_SetFont(const uint8_t* font_t)
  24. {
  25. font = font_t;
  26. }
  27. void GFX_SetFontSize(uint8_t size_t)
  28. {
  29. if(size_t != 0)
  30. size = size_t;
  31. }
  32. uint8_t GFX_GetFontHeight(void)
  33. {
  34. return font[0];
  35. }
  36. uint8_t GFX_GetFontWidth(void)
  37. {
  38. return font[1];
  39. }
  40. uint8_t GFX_GetFontSize(void)
  41. {
  42. return size;
  43. }
  44. void GFX_DrawChar(int x, int y, char chr, uint8_t color, uint8_t background)
  45. {
  46. if(chr > 0x7E) return; // chr > '~'
  47. for(uint8_t i=0; i<font[1]; i++ )
  48. {
  49. uint8_t line = (uint8_t)font[(chr-0x20) * font[1] + i + 2];
  50. for(int8_t j=0; j<font[0]; j++, line >>= 1)
  51. {
  52. if(line & 1)
  53. {
  54. if(size == 1)
  55. GFX_DrawPixel(x+i, y+j, color);
  56. else
  57. GFX_DrawFillRectangle(x+i*size, y+j*size, size, size, color);
  58. }
  59. else if(background == 0)
  60. {
  61. if(size == 1)
  62. GFX_DrawPixel(x+i, y+j, background);
  63. else
  64. GFX_DrawFillRectangle(x+i*size, y+j*size, size, size, background);
  65. }
  66. }
  67. }
  68. }
  69. void GFX_DrawString(int x, int y, char* str, uint8_t color, uint8_t background)
  70. {
  71. int x_tmp = x;
  72. char znak;
  73. znak = *str;
  74. while(*str++)
  75. {
  76. GFX_DrawChar(x_tmp, y, znak, color, background);
  77. x_tmp += ((uint8_t)font[1] * size) + 1;
  78. if(background == 0)
  79. {
  80. for(uint8_t i=0; i<(font[0]*size); i++)
  81. {
  82. GFX_DrawPixel(x_tmp-1, y+i, PIXEL_BLACK);
  83. }
  84. }
  85. znak = *str;
  86. }
  87. }
  88. #endif
  89. #if USING_LINES == 1
  90. void GFX_WriteLine(int x_start, int y_start, int x_end, int y_end, uint8_t color)
  91. {
  92. int16_t steep = abs(y_end - y_start) > abs(x_end - x_start);
  93. if (steep) {
  94. _swap_int(x_start, y_start);
  95. _swap_int(x_end, y_end);
  96. }
  97. if (x_start > x_end) {
  98. _swap_int(x_start, x_end);
  99. _swap_int(y_start, y_end);
  100. }
  101. int16_t dx, dy;
  102. dx = x_end - x_start;
  103. dy = abs(y_end - y_start);
  104. int16_t err = dx / 2;
  105. int16_t ystep;
  106. if (y_start < y_end) {
  107. ystep = 1;
  108. } else {
  109. ystep = -1;
  110. }
  111. for (; x_start<=x_end; x_start++) {
  112. if (steep) {
  113. GFX_DrawPixel(y_start, x_start, color);
  114. } else {
  115. GFX_DrawPixel(x_start, y_start, color);
  116. }
  117. err -= dy;
  118. if (err < 0) {
  119. y_start += ystep;
  120. err += dx;
  121. }
  122. }
  123. }
  124. void GFX_DrawFastVLine(int x_start, int y_start, int h, uint8_t color)
  125. {
  126. GFX_WriteLine(x_start, y_start, x_start, y_start+h-1, color);
  127. }
  128. void GFX_DrawFastHLine(int x_start, int y_start, int w, uint8_t color)
  129. {
  130. GFX_WriteLine(x_start, y_start, x_start+w-1, y_start, color);
  131. }
  132. void GFX_DrawLine(int x_start, int y_start, int x_end, int y_end, uint8_t color)
  133. {
  134. if(x_start == x_end){
  135. if(y_start > y_end) _swap_int(y_start, y_end);
  136. GFX_DrawFastVLine(x_start, y_start, y_end - y_start + 1, color);
  137. } else if(y_start == y_end){
  138. if(x_start > x_end) _swap_int(x_start, x_end);
  139. GFX_DrawFastHLine(x_start, y_start, x_end - x_start + 1, color);
  140. } else {
  141. GFX_WriteLine(x_start, y_start, x_end, y_end, color);
  142. }
  143. }
  144. #endif
  145. #if USING_RECTANGLE == 1
  146. void GFX_DrawRectangle(int x, int y, uint16_t w, uint16_t h, uint8_t color)
  147. {
  148. GFX_DrawFastHLine(x, y, w, color);
  149. GFX_DrawFastHLine(x, y+h-1, w, color);
  150. GFX_DrawFastVLine(x, y, h, color);
  151. GFX_DrawFastVLine(x+w-1, y, h, color);
  152. }
  153. #endif
  154. #if USING_FILL_RECTANGLE == 1
  155. void GFX_DrawFillRectangle(int x, int y, uint16_t w, uint16_t h, uint8_t color)
  156. {
  157. for (int i=x; i<x+w; i++) {
  158. GFX_DrawFastVLine(i, y, h, color);
  159. }
  160. }
  161. #endif
  162. #if USING_CIRCLE == 1
  163. void GFX_DrawCircle(int x0, int y0, uint16_t r, uint8_t color)
  164. {
  165. int16_t f = 1 - r;
  166. int16_t ddF_x = 1;
  167. int16_t ddF_y = -2 * r;
  168. int16_t x = 0;
  169. int16_t y = r;
  170. GFX_DrawPixel(x0 , y0+r, color);
  171. GFX_DrawPixel(x0 , y0-r, color);
  172. GFX_DrawPixel(x0+r, y0 , color);
  173. GFX_DrawPixel(x0-r, y0 , color);
  174. while (x<y) {
  175. if (f >= 0) {
  176. y--;
  177. ddF_y += 2;
  178. f += ddF_y;
  179. }
  180. x++;
  181. ddF_x += 2;
  182. f += ddF_x;
  183. GFX_DrawPixel(x0 + x, y0 + y, color);
  184. GFX_DrawPixel(x0 - x, y0 + y, color);
  185. GFX_DrawPixel(x0 + x, y0 - y, color);
  186. GFX_DrawPixel(x0 - x, y0 - y, color);
  187. GFX_DrawPixel(x0 + y, y0 + x, color);
  188. GFX_DrawPixel(x0 - y, y0 + x, color);
  189. GFX_DrawPixel(x0 + y, y0 - x, color);
  190. GFX_DrawPixel(x0 - y, y0 - x, color);
  191. }
  192. }
  193. #endif
  194. #ifdef CIRCLE_HELPER
  195. void GFX_DrawCircleHelper( int x0, int y0, uint16_t r, uint8_t cornername, uint8_t color)
  196. {
  197. int16_t f = 1 - r;
  198. int16_t ddF_x = 1;
  199. int16_t ddF_y = -2 * r;
  200. int16_t x = 0;
  201. int16_t y = r;
  202. while (x<y) {
  203. if (f >= 0) {
  204. y--;
  205. ddF_y += 2;
  206. f += ddF_y;
  207. }
  208. x++;
  209. ddF_x += 2;
  210. f += ddF_x;
  211. if (cornername & 0x4) {
  212. GFX_DrawPixel(x0 + x, y0 + y, color);
  213. GFX_DrawPixel(x0 + y, y0 + x, color);
  214. }
  215. if (cornername & 0x2) {
  216. GFX_DrawPixel(x0 + x, y0 - y, color);
  217. GFX_DrawPixel(x0 + y, y0 - x, color);
  218. }
  219. if (cornername & 0x8) {
  220. GFX_DrawPixel(x0 - y, y0 + x, color);
  221. GFX_DrawPixel(x0 - x, y0 + y, color);
  222. }
  223. if (cornername & 0x1) {
  224. GFX_DrawPixel(x0 - y, y0 - x, color);
  225. GFX_DrawPixel(x0 - x, y0 - y, color);
  226. }
  227. }
  228. }
  229. #endif
  230. #ifdef FILL_CIRCLE_HELPER
  231. void GFX_DrawFillCircleHelper(int x0, int y0, uint16_t r, uint8_t cornername, int16_t delta, uint8_t color)
  232. {
  233. int16_t f = 1 - r;
  234. int16_t ddF_x = 1;
  235. int16_t ddF_y = -2 * r;
  236. int16_t x = 0;
  237. int16_t y = r;
  238. while (x<y) {
  239. if (f >= 0) {
  240. y--;
  241. ddF_y += 2;
  242. f += ddF_y;
  243. }
  244. x++;
  245. ddF_x += 2;
  246. f += ddF_x;
  247. if (cornername & 0x1) {
  248. GFX_DrawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
  249. GFX_DrawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
  250. }
  251. if (cornername & 0x2) {
  252. GFX_DrawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
  253. GFX_DrawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
  254. }
  255. }
  256. }
  257. #endif
  258. #if USING_FILL_CIRCLE == 1
  259. void GFX_DrawFillCircle(int x0, int y0, uint16_t r, uint8_t color)
  260. {
  261. GFX_DrawFastVLine(x0, y0-r, 2*r+1, color);
  262. GFX_DrawFillCircleHelper(x0, y0, r, 3, 0, color);
  263. }
  264. #endif
  265. #if USING_ROUND_RECTANGLE == 1
  266. void GFX_DrawRoundRectangle(int x, int y, uint16_t w, uint16_t h, uint16_t r, uint8_t color)
  267. {
  268. GFX_DrawFastHLine(x+r , y , w-2*r, color); // Top
  269. GFX_DrawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
  270. GFX_DrawFastVLine(x , y+r , h-2*r, color); // Left
  271. GFX_DrawFastVLine(x+w-1, y+r , h-2*r, color); // Right
  272. // draw four corners
  273. GFX_DrawCircleHelper(x+r , y+r , r, 1, color);
  274. GFX_DrawCircleHelper(x+w-r-1, y+r , r, 2, color);
  275. GFX_DrawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
  276. GFX_DrawCircleHelper(x+r , y+h-r-1, r, 8, color);
  277. }
  278. #endif
  279. #if USING_FILL_ROUND_RECTANGLE == 1
  280. void GFX_DrawFillRoundRectangle(int x, int y, uint16_t w, uint16_t h, uint16_t r, uint8_t color)
  281. {
  282. // smarter version
  283. GFX_DrawFillRectangle(x+r, y, w-2*r, h, color);
  284. // draw four corners
  285. GFX_DrawFillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
  286. GFX_DrawFillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
  287. }
  288. #endif
  289. #if USING_TRIANGLE == 1
  290. void GFX_DrawTriangle(int x0, int y0, int x1, int y1, int x2, int y2, uint8_t color)
  291. {
  292. GFX_DrawLine(x0, y0, x1, y1, color);
  293. GFX_DrawLine(x1, y1, x2, y2, color);
  294. GFX_DrawLine(x2, y2, x0, y0, color);
  295. }
  296. #endif
  297. #if USING_FILL_TRIANGLE == 1
  298. void GFX_DrawFillTriangle(int x0, int y0, int x1, int y1, int x2, int y2, uint8_t color)
  299. {
  300. int16_t a, b, y, last;
  301. // Sort coordinates by Y order (y2 >= y1 >= y0)
  302. if (y0 > y1) {
  303. _swap_int(y0, y1); _swap_int(x0, x1);
  304. }
  305. if (y1 > y2) {
  306. _swap_int(y2, y1); _swap_int(x2, x1);
  307. }
  308. if (y0 > y1) {
  309. _swap_int(y0, y1); _swap_int(x0, x1);
  310. }
  311. if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
  312. a = b = x0;
  313. if(x1 < a) a = x1;
  314. else if(x1 > b) b = x1;
  315. if(x2 < a) a = x2;
  316. else if(x2 > b) b = x2;
  317. GFX_DrawFastHLine(a, y0, b-a+1, color);
  318. return;
  319. }
  320. int16_t
  321. dx01 = x1 - x0,
  322. dy01 = y1 - y0,
  323. dx02 = x2 - x0,
  324. dy02 = y2 - y0,
  325. dx12 = x2 - x1,
  326. dy12 = y2 - y1;
  327. int32_t
  328. sa = 0,
  329. sb = 0;
  330. // For upper part of triangle, find scanline crossings for segments
  331. // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
  332. // is included here (and second loop will be skipped, avoiding a /0
  333. // error there), otherwise scanline y1 is skipped here and handled
  334. // in the second loop...which also avoids a /0 error here if y0=y1
  335. // (flat-topped triangle).
  336. if(y1 == y2) last = y1; // Include y1 scanline
  337. else last = y1-1; // Skip it
  338. for(y=y0; y<=last; y++) {
  339. a = x0 + sa / dy01;
  340. b = x0 + sb / dy02;
  341. sa += dx01;
  342. sb += dx02;
  343. /* longhand:
  344. a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
  345. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  346. */
  347. if(a > b) _swap_int(a,b);
  348. GFX_DrawFastHLine(a, y, b-a+1, color);
  349. }
  350. // For lower part of triangle, find scanline crossings for segments
  351. // 0-2 and 1-2. This loop is skipped if y1=y2.
  352. sa = dx12 * (y - y1);
  353. sb = dx02 * (y - y0);
  354. for(; y<=y2; y++) {
  355. a = x1 + sa / dy12;
  356. b = x0 + sb / dy02;
  357. sa += dx12;
  358. sb += dx02;
  359. /* longhand:
  360. a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
  361. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  362. */
  363. if(a > b) _swap_int(a,b);
  364. GFX_DrawFastHLine(a, y, b-a+1, color);
  365. }
  366. }
  367. #endif
  368. #if USING_IMAGE == 1
  369. #if AVR_USING == 1
  370. void GFX_Image_P(int x, int y, uint8_t *img, uint8_t w, uint8_t h, uint8_t color)
  371. {
  372. uint8_t i, j, byteWidth = (w+7)/8;
  373. for(j = 0; j < h; j++)
  374. {
  375. for(i = 0; i < w; i++)
  376. {
  377. if(pgm_read_byte(img + j *byteWidth + i /8) & (128 >> (i&7)) )
  378. GFX_DrawPixel(x+i, y+j, color);
  379. }
  380. }
  381. }
  382. #endif
  383. #if STM32_USING ==1
  384. void GFX_Image(int x, int y, const uint8_t *img, uint8_t w, uint8_t h)
  385. {
  386. uint8_t i, j;
  387. uint8_t SelectedCell;
  388. for(j = 0; j < h; j++)
  389. {
  390. for(i = 0; i < w; i++)
  391. {
  392. SelectedCell = img[i/2 + j*(w/2)];
  393. if(i % 2)
  394. {
  395. SelectedCell &= 0x0F;
  396. }
  397. else
  398. {
  399. SelectedCell >>= 4;
  400. }
  401. GFX_DrawPixel(x+i, y+j, SelectedCell);
  402. }
  403. }
  404. }
  405. #if USING_IMAGE_ROTATE == 1
  406. const double sinus_LUT[] =
  407. {// 0* to 90* = 91 valuse
  408. 0.0000,
  409. 0.0175,
  410. 0.0349,
  411. 0.0523,
  412. 0.0698,
  413. 0.0872,
  414. 0.1045,
  415. 0.1219,
  416. 0.1392,
  417. 0.1564,
  418. 0.1736,
  419. 0.1908,
  420. 0.2079,
  421. 0.2250,
  422. 0.2419,
  423. 0.2588,
  424. 0.2756,
  425. 0.2924,
  426. 0.3090,
  427. 0.3256,
  428. 0.3420,
  429. 0.3584,
  430. 0.3746,
  431. 0.3907,
  432. 0.4067,
  433. 0.4226,
  434. 0.4384,
  435. 0.4540,
  436. 0.4695,
  437. 0.4848,
  438. 0.5000,
  439. 0.5150,
  440. 0.5299,
  441. 0.5446,
  442. 0.5592,
  443. 0.5736,
  444. 0.5878,
  445. 0.6018,
  446. 0.6157,
  447. 0.6293,
  448. 0.6428,
  449. 0.6561,
  450. 0.6691,
  451. 0.6820,
  452. 0.6947,
  453. 0.7071,
  454. 0.7193,
  455. 0.7314,
  456. 0.7431,
  457. 0.7547,
  458. 0.7660,
  459. 0.7771,
  460. 0.7880,
  461. 0.7986,
  462. 0.8090,
  463. 0.8192,
  464. 0.8290,
  465. 0.8387,
  466. 0.8480,
  467. 0.8572,
  468. 0.8660,
  469. 0.8746,
  470. 0.8829,
  471. 0.8910,
  472. 0.8988,
  473. 0.9063,
  474. 0.9135,
  475. 0.9205,
  476. 0.9272,
  477. 0.9336,
  478. 0.9397,
  479. 0.9455,
  480. 0.9511,
  481. 0.9563,
  482. 0.9613,
  483. 0.9659,
  484. 0.9703,
  485. 0.9744,
  486. 0.9781,
  487. 0.9816,
  488. 0.9848,
  489. 0.9877,
  490. 0.9903,
  491. 0.9925,
  492. 0.9945,
  493. 0.9962,
  494. 0.9976,
  495. 0.9986,
  496. 0.9994,
  497. 0.9998,
  498. 1.0000,
  499. };
  500. double sinus(uint16_t angle)
  501. {
  502. angle %= 360;
  503. if((angle >= 0) && (angle < 90)) return sinus_LUT[angle];
  504. if((angle >= 90) && (angle < 180)) return sinus_LUT[180 - angle];
  505. if((angle >= 180) && (angle < 270)) return -(sinus_LUT[angle - 180]);
  506. if((angle >= 270) && (angle < 360)) return -(sinus_LUT[180 - (angle - 180)]);
  507. return 0; // will be never here
  508. }
  509. void GFX_ImageRotate(int x, int y, const uint8_t *img, uint8_t w, uint8_t h, uint8_t color, uint16_t angle)
  510. {
  511. angle %= 360;
  512. uint8_t wHalf = w/2;
  513. uint8_t hHalf = h/2;
  514. uint8_t i, j, byteWidth = (w+7)/8;
  515. double sinma = sinus(angle);
  516. double cosma = sinus(angle + 90);
  517. for(j = 0; j < h; j++)
  518. {
  519. for(i = 0; i < w; i++)
  520. {
  521. if(img[j *byteWidth + i /8] & (128 >> (i&7)) )
  522. {
  523. int xt = i - wHalf;
  524. int yt = j - hHalf;
  525. int xs = (xt*cosma - yt*sinma) + wHalf;
  526. int ys = (xt*sinma + yt*cosma) + hHalf;
  527. GFX_DrawPixel(xs+x, ys+y, color);
  528. }
  529. }
  530. }
  531. }
  532. #endif
  533. #endif
  534. #endif