GFX_SSD1327.c 13 KB

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