libpynq  (release 5EID0-2023 version 0.3.0 of 2024-04-25 09:42 )
display.c
Go to the documentation of this file.
1 /*
2 MIT License
3 
4 Copyright (c) 2020
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 
24 Modified by Eindhoven University of Technology 2023.
25 */
27 #include <display.h>
28 #include <gpio.h>
29 #include <lcdconfig.h>
30 #include <log.h>
31 #include <math.h>
32 #include <platform.h>
33 #include <string.h>
34 #include <switchbox.h>
35 #include <unistd.h>
36 #include <util.h>
37 
38 #undef LOG_DOMAIN
39 #define LOG_DOMAIN "display"
40 
41 #define TAG "ST7789"
42 #define _DEBUG_ 0
43 
44 #define M_PI 3.14159265358979323846
45 
46 static arm_shared spi0_handle;
47 static volatile uint32_t *spi0 = NULL;
48 
49 // states that are set for usage of the DC pin in SPI
50 typedef enum { SPI_Data_Mode = 1, SPI_Command_Mode = 0 } spi_mode_t;
51 
52 #define GPIO_MODE_OUTPUT 1
53 
55  switch (mode) {
56  case SPI_Data_Mode:
57  return GPIO_LEVEL_HIGH;
58  case SPI_Command_Mode:
59  return GPIO_LEVEL_LOW;
60  default:
61  return GPIO_LEVEL_LOW;
62  }
63 }
64 
65 bool spi_master_write_command(display_t *display, uint8_t cmd) {
67  spi0[0x68 / 4] = cmd;
68  while (((spi0[0x64 / 4]) & 4) == 0) {
69  }
70  usleep(1);
71  return true;
72 }
73 
74 bool spi_master_write_data_byte(display_t *display, uint8_t data) {
76 
77  spi0[0x68 / 4] = data;
78  while (((spi0[0x64 / 4]) & 4) == 0) {
79  }
80  return true;
81 }
82 
83 bool spi_master_write_data_word(display_t *display, uint16_t data) {
84  static uint8_t Byte[2];
85  Byte[0] = (data >> 8) & 0xFF;
86  Byte[1] = data & 0xFF;
88  spi0[0x68 / 4] = Byte[0];
89  spi0[0x68 / 4] = Byte[1];
90 
91  while (((spi0[0x64 / 4]) & 4) == 0) {
92  }
93  return true;
94 }
95 
96 bool spi_master_write_addr(display_t *display, uint16_t addr1, uint16_t addr2) {
97  static uint8_t Byte[4];
98  Byte[0] = (addr1 >> 8) & 0xFF;
99  Byte[1] = addr1 & 0xFF;
100  Byte[2] = (addr2 >> 8) & 0xFF;
101  Byte[3] = addr2 & 0xFF;
103 
104  // check ordering
105  spi0[0x68 / 4] = Byte[0];
106  spi0[0x68 / 4] = Byte[1];
107  spi0[0x68 / 4] = Byte[2];
108  spi0[0x68 / 4] = Byte[3];
109 
110  while (((spi0[0x64 / 4]) & 4) == 0) {
111  }
112  return true;
113 }
114 
115 bool spi_master_write_color(display_t *display, uint16_t color, uint16_t size) {
117  for (int i = 0; i < size; i++) {
118  while (((spi0[0x64 / 4]) & 8) == 8) {
119  }
120  spi0[0x68 / 4] = (color >> 8) & 0xFF;
121  while (((spi0[0x64 / 4]) & 8) == 8) {
122  }
123  spi0[0x68 / 4] = (color) & 0xFF;
124  }
125  while (((spi0[0x64 / 4]) & 4) == 0) {
126  }
127  return -1;
128 }
129 
130 bool spi_master_write_colors(display_t *display, uint16_t *colors,
131  uint16_t size) {
133  for (int i = 0; i < size; i++) {
134  while (((spi0[0x64 / 4]) & 8) == 8) {
135  }
136  spi0[0x68 / 4] = (colors[i] >> 8) & 0xFF;
137  while (((spi0[0x64 / 4]) & 8) == 8) {
138  }
139  spi0[0x68 / 4] = (colors[i]) & 0xFF;
140  }
141  // wait till empty, then add a small extra buffer
142  // because last byte we don't exactly know when send.
143  while (((spi0[0x64 / 4]) & 4) == 0) {
144  }
145  return true;
146 }
147 
148 void spi_master_init(display_t *display) {
149  // linking given pins in the switchbox
150  switchbox_set_pin(LCD_MOSI, SWB_SPI1_MOSI);
151  switchbox_set_pin(LCD_SCLK, SWB_SPI1_CLK);
153  switchbox_set_pin(LCD_DC, SWB_GPIO);
154  switchbox_set_pin(LCD_RESET, SWB_GPIO);
155  switchbox_set_pin(LCD_BL, SWB_GPIO);
156 
157  // setting the appropriate direction of each protocol pin
162  gpio_set_level(LCD_RESET, GPIO_LEVEL_LOW);
164 
165  // creating a shared memory instance for communicating the hardware addresses
166  // of the linked pins
167  spi0 = arm_shared_init(&spi0_handle, axi_quad_spi_1, 4096);
168  if (_DEBUG_)
169  printf("spi reset: %08X\n", spi0[0x40 / 4]);
170  spi0[0x40 / 4] = 0x0000000a;
171  if (_DEBUG_)
172  printf("spi control: %08X\n", spi0[0x60 / 4]);
173  spi0[0x60 / 4] = (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
174  if (_DEBUG_)
175  printf("spi control: %08X\n", spi0[0x60 / 4]);
176  if (_DEBUG_)
177  printf("spi status: %08X\n", spi0[0x64 / 4]);
178 
179  // select slave 1
180  spi0[0x70 / 4] = 0;
181  if (_DEBUG_)
182  printf("spi control: %08X\n", spi0[0x60 / 4]);
183  if (_DEBUG_)
184  printf("testing DISPLAY\n");
185  if (_DEBUG_)
186  printf("LCD_CS=%d\n", LCD_CS);
187  if (LCD_CS >= 0) {
188  gpio_reset_pin(LCD_CS);
190  gpio_set_level(LCD_CS, 0);
191  }
192 
193  if (_DEBUG_)
194  printf("LCD_DC=%d", LCD_DC);
195  gpio_reset_pin(LCD_DC);
197  gpio_set_level(LCD_DC, 0);
198  if (_DEBUG_)
199  printf("LCD_RESET=%d", LCD_RESET);
200 
201  if (LCD_RESET >= 0) {
202  gpio_reset_pin(LCD_RESET);
204  gpio_set_level(LCD_RESET, 1);
205  sleep_msec(100);
206  gpio_set_level(LCD_RESET, 0);
207  sleep_msec(500);
208  gpio_set_level(LCD_RESET, 1);
209  sleep_msec(300);
210  }
211 
212  if (_DEBUG_)
213  printf("LCD_BL=%d", LCD_BL);
214  if (LCD_BL >= 0) {
215  gpio_reset_pin(LCD_BL);
217  gpio_set_level(LCD_BL, 0);
218  }
219 
220  if (_DEBUG_)
221  printf("LCD_MOSI=%d", LCD_MOSI);
222  if (_DEBUG_)
223  printf("LCD_SCLK=%d\n", LCD_SCLK);
224 
225  display->_dc = LCD_DC;
226  display->_bl = LCD_BL;
227 }
228 
229 void displayInit(display_t *display, int width, int height, int offsetx,
230  int offsety) {
231  spi_master_init(display);
232  display->_width = width;
233  display->_height = height;
234  display->_offsetx = offsetx;
235  display->_offsety = offsety;
236  display->_font_direction = TEXT_DIRECTION0;
237  display->_font_fill = false;
238  display->_font_underline = false;
239 
240  spi_master_write_command(display, 0x01); // software Reset
241  sleep_msec(150);
242 
243  spi_master_write_command(display, 0x11); // sleep Out
244  sleep_msec(255);
245 
246  spi_master_write_command(display, 0x3A); // Interface Pixel Format
247  spi_master_write_data_byte(display, 0x55);
248  sleep_msec(10);
249 
250  spi_master_write_command(display, 0x36); // Memory Data Access Control
251  spi_master_write_data_byte(display, 0x00);
252 
253  spi_master_write_command(display, 0x2A); // Column Address Set
254  spi_master_write_data_byte(display, 0x00);
255  spi_master_write_data_byte(display, 0x00);
256  spi_master_write_data_byte(display, 0x00);
257  spi_master_write_data_byte(display, 0xF0);
258 
259  spi_master_write_command(display, 0x2B); // Row Address Set
260  spi_master_write_data_byte(display, 0x00);
261  spi_master_write_data_byte(display, 0x00);
262  spi_master_write_data_byte(display, 0x00);
263  spi_master_write_data_byte(display, 0xF0);
264 
265  spi_master_write_command(display, 0x21); // Display Inversion On
266  sleep_msec(10);
267 
268  spi_master_write_command(display, 0x13); // Normal Display Mode On
269  sleep_msec(10);
270 
271  spi_master_write_command(display, 0x29); // Display ON
272  sleep_msec(255);
273 
274  if (display->_bl >= 0) {
275  gpio_set_level(display->_bl, 1);
276  }
277 }
278 
279 void display_set_flip(display_t *display, bool xflip, bool yflip) {
280  if (display == NULL) {
281  pynq_error("display_destroy: display has not been initialized\n");
282  }
283  if (display->_width != DISPLAY_WIDTH || display->_height != DISPLAY_HEIGHT) {
284  pynq_error("display_destroy: internal error (wrong display hardware)\n");
285  }
286  spi_master_write_command(display, 0x36); // Memory Data Access Control
287  uint8_t set = (yflip << 7) | (xflip << 6);
288  spi_master_write_data_byte(display, set);
289  if (yflip) {
290  display->_offsety = 320 - display->_height;
291  } else {
292  display->_offsety = 0;
293  }
294  if (xflip) {
295  display->_offsetx = 240 - display->_width;
296  } else {
297  display->_offsetx = 0;
298  }
299 }
300 
301 void display_init(display_t *display) {
302  if (display == NULL) {
303  pynq_error("display_init: display is NULL\n");
304  }
305  displayInit(display, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, 0);
306  display_set_flip(display, true, true);
307 }
308 
309 void display_destroy(display_t *display __attribute__((unused))) {
310  if (display == NULL || display->_width != DISPLAY_WIDTH) {
311  pynq_error("display_destroy: display has not been initialized\n");
312  }
313  // if channel is open
314  if (spi0 != NULL) {
315  (void)arm_shared_close(&spi0_handle);
316  spi0 = NULL;
317  }
318 }
319 
320 void displayDrawPixel(display_t *display, uint16_t x, uint16_t y,
321  uint16_t color) {
322  if (display == NULL || display->_width != DISPLAY_WIDTH) {
323  pynq_error("displayDrawPixel: display has not been initialized\n");
324  }
325  if (x >= display->_width || y >= display->_height) {
326  pynq_error("displayDrawPixel: x=%d y=%d outside screen boundaries\n", x, y);
327  }
328  uint16_t _x = x + display->_offsetx;
329  uint16_t _y = y + display->_offsety;
330 
331  spi_master_write_command(display, 0x2A); // set column(x) address
332  spi_master_write_addr(display, _x, _x);
333  spi_master_write_command(display, 0x2B); // set Page(y) address
334  spi_master_write_addr(display, _y, _y);
335  spi_master_write_command(display, 0x2C); // memory write
336  spi_master_write_data_word(display, color);
337 }
338 
339 void displayDrawMultiPixels(display_t *display, uint16_t x, uint16_t y,
340  uint16_t size, uint16_t *colors) {
341  if (display == NULL || display->_width != DISPLAY_WIDTH) {
342  pynq_error("displayDrawMultiPixels: display has not been initialized\n");
343  }
344  if (x > display->_width || x + size > display->_width ||
345  y >= display->_height) {
346  pynq_error(
347  "displayDrawMultiPixels: x=%d y=%d size=%d outside screen boundaries\n",
348  x, y, size);
349  }
350 
351  uint16_t _x1 = x + display->_offsetx;
352  uint16_t _x2 = _x1 + size;
353  uint16_t _y1 = y + display->_offsety;
354  uint16_t _y2 = _y1;
355 
356  spi_master_write_command(display, 0x2A); // set column(x) address
357  spi_master_write_addr(display, _x1, _x2);
358  spi_master_write_command(display, 0x2B); // set Page(y) address
359  spi_master_write_addr(display, _y1, _y2);
360  spi_master_write_command(display, 0x2C); // memory write
361  spi_master_write_colors(display, colors, size);
362 }
363 
364 void displayDrawFillRect(display_t *display, uint16_t x1, uint16_t y1,
365  uint16_t x2, uint16_t y2, uint16_t color) {
366  if (display == NULL || display->_width != DISPLAY_WIDTH) {
367  pynq_error("displayDrawPixel: display has not been initialized\n");
368  }
369  if (x1 >= display->_width || x2 >= display->_width ||
370  y1 >= display->_height || y2 >= display->_height) {
371  pynq_error("displayDrawFillRect: x1=%d y1=%d x2=%d y2=%d outside screen "
372  "boundaries\n",
373  x1, y1, x2, y2);
374  }
375  // swapping points so that it is always plotted from x1 y1 bottom left, x2 y2
376  // top right
377  uint16_t x1_temp = x1, x2_temp = x2;
378  uint16_t y1_temp = y1, y2_temp = y2;
379  if (x1 > x2) {
380  x1 = x2_temp;
381  x2 = x1_temp;
382  }
383 
384  if (y1 > y2) {
385  y1 = y2_temp;
386  y2 = y1_temp;
387  }
388 
389  // printf("offset(x)=%d offset(y)=%d",display->_offsetx,display->_offsety);
390  uint16_t _x1 = x1 + display->_offsetx;
391  uint16_t _x2 = x2 + display->_offsetx;
392  uint16_t _y1 = y1 + display->_offsety;
393  uint16_t _y2 = y2 + display->_offsety;
394 
395  spi_master_write_command(display, 0x2A); // set column(x) address
396  spi_master_write_addr(display, _x1, _x2);
397  spi_master_write_command(display, 0x2B); // set Page(y) address
398  spi_master_write_addr(display, _y1, _y2);
399  spi_master_write_command(display, 0x2C); // memory write
400  for (int i = _x1; i <= _x2; i++) {
401  uint16_t size = _y2 - _y1 + 1;
402  spi_master_write_color(display, color, size);
403  }
404 }
405 
406 void displayDisplayOff(display_t *display) {
407  if (display == NULL || display->_width != DISPLAY_WIDTH) {
408  pynq_error("displayDisplayOff: display has not been initialized\n");
409  }
410  spi_master_write_command(display, 0x28); // display off
411 }
412 
413 void displayDisplayOn(display_t *display) {
414  if (display == NULL || display->_width != DISPLAY_WIDTH) {
415  pynq_error("displayDisplayOn: display has not been initialized\n");
416  }
417  spi_master_write_command(display, 0x29); // display on
418 }
419 
420 void displayFillScreen(display_t *display, uint16_t color) {
421  if (display == NULL || display->_width != DISPLAY_WIDTH) {
422  pynq_error("displayFillScreen: display has not been initialized\n");
423  }
424  displayDrawFillRect(display, 0, 0, display->_width - 1, display->_height - 1,
425  color);
426 }
427 
428 void displayDrawLine(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2,
429  uint16_t y2, uint16_t color) {
430  if (display == NULL || display->_width != DISPLAY_WIDTH) {
431  pynq_error("displayDrawLine: display has not been initialized\n");
432  }
433  if (x1 >= display->_width || y1 >= display->_height) {
434  pynq_error("displayDrawLine: x1=%d y1=%d outside screen boundaries\n", x1,
435  y1);
436  } else if (x2 >= display->_width || y2 >= display->_height) {
437  pynq_error("displayDrawLine: x2=%d y2=%d outside screen boundaries\n", x2,
438  y2);
439  }
440  int i;
441  int dx, dy;
442  int sx, sy;
443  int E;
444 
445  /* distance between two points */
446  dx = (x2 > x1) ? x2 - x1 : x1 - x2;
447  dy = (y2 > y1) ? y2 - y1 : y1 - y2;
448 
449  /* direction of two point */
450  sx = (x2 > x1) ? 1 : -1;
451  sy = (y2 > y1) ? 1 : -1;
452 
453  /* inclination < 1 */
454  if (dx > dy) {
455  E = -dx;
456  for (i = 0; i <= dx; i++) {
457  displayDrawPixel(display, x1, y1, color);
458  x1 += sx;
459  E += 2 * dy;
460  if (E >= 0) {
461  y1 += sy;
462  E -= 2 * dx;
463  }
464  }
465 
466  /* inclination >= 1 */
467  } else {
468  E = -dy;
469  for (i = 0; i <= dy; i++) {
470  displayDrawPixel(display, x1, y1, color);
471  y1 += sy;
472  E += 2 * dx;
473  if (E >= 0) {
474  x1 += sx;
475  E -= 2 * dy;
476  }
477  }
478  }
479 }
480 
481 void displayDrawRect(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2,
482  uint16_t y2, uint16_t color) {
483  if (display == NULL || display->_width != DISPLAY_WIDTH) {
484  pynq_error("displayDrawRect: display has not been initialized\n");
485  }
486  if (x1 >= display->_width || y1 >= display->_height) {
487  pynq_error("displayDrawRect: x1=%d y1=%d outside screen boundaries\n", x1,
488  y1);
489  } else if (x2 >= display->_width || y2 >= display->_height) {
490  pynq_error("displayDrawRect: x2=%d y2=%d outside screen boundaries\n", x2,
491  y2);
492  }
493  displayDrawLine(display, x1, y1, x2, y1, color);
494  displayDrawLine(display, x2, y1, x2, y2, color);
495  displayDrawLine(display, x2, y2, x1, y2, color);
496  displayDrawLine(display, x1, y2, x1, y1, color);
497 }
498 
499 void displayDrawRectAngle(display_t *display, uint16_t xc, uint16_t yc,
500  uint16_t w, uint16_t h, uint16_t angle,
501  uint16_t color) {
502  double xd, yd, rd;
503  int x1, y1;
504  int x2, y2;
505  int x3, y3;
506  int x4, y4;
507  rd = -angle * M_PI / 180.0;
508  xd = 0.0 - w / 2;
509  yd = h / 2;
510  x1 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
511  y1 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
512 
513  yd = 0.0 - yd;
514  x2 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
515  y2 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
516 
517  xd = w / 2;
518  yd = h / 2;
519  x3 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
520  y3 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
521 
522  yd = 0.0 - yd;
523  x4 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
524  y4 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
525 
526  if (display == NULL || display->_width != DISPLAY_WIDTH) {
527  pynq_error("displayDrawRectAngle: display has not been initialized\n");
528  }
529  if (x1 >= display->_width || y1 >= display->_height) {
530  pynq_error("displayDrawRectAngle: x1=%d y1=%d outside screen boundaries\n",
531  x1, y1);
532  } else if (x2 >= display->_width || y2 >= display->_height) {
533  pynq_error("displayDrawRectAngle: x2=%d y2=%d outside screen boundaries\n",
534  x2, y2);
535  } else if (x3 >= display->_width || y3 >= display->_height) {
536  pynq_error("displayDrawRectAngle: x3=%d y3=%d outside screen boundaries\n",
537  x3, y3);
538  } else if (x4 >= display->_width || y4 >= display->_height) {
539  pynq_error("displayDrawRectAngle: x4=%d y4=%d outside screen boundaries\n",
540  x4, y4);
541  }
542 
543  displayDrawLine(display, x1, y1, x2, y2, color);
544  displayDrawLine(display, x1, y1, x3, y3, color);
545  displayDrawLine(display, x2, y2, x4, y4, color);
546  displayDrawLine(display, x3, y3, x4, y4, color);
547 }
548 
549 // x1: First X coordinate of triangle point
550 // y1: First Y coordinate of triangle point
551 // x2: Second X coordinate of triangle point
552 // y2: Second Y coordinate of triangle point
553 // x3: Third X coordinate of triangle point
554 // y3: Third Y coordinate of triangle point
555 // color:color
556 void displayDrawTriangle(display_t *display, uint16_t x1, uint16_t y1,
557  uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3,
558  uint16_t color) {
559  if (display == NULL || display->_width != DISPLAY_WIDTH) {
560  pynq_error("displayDrawTriangle: display has not been initialized\n");
561  }
562  if (x1 >= display->_width || y1 >= display->_height) {
563  pynq_error("displayDrawRectAngle: x1=%d y1=%d outside screen boundaries\n",
564  x1, y1);
565  } else if (x2 >= display->_width || y2 >= display->_height) {
566  pynq_error("displayDrawRectAngle: x2=%d y2=%d outside screen boundaries\n",
567  x2, y2);
568  } else if (x3 >= display->_width || y3 >= display->_height) {
569  pynq_error("displayDrawRectAngle: x3=%d y3=%d outside screen boundaries\n",
570  x3, y3);
571  }
572 
573  // draw the lines for the basic triangle
574  displayDrawLine(display, x1, y1, x2, y2, color);
575  displayDrawLine(display, x2, y2, x3, y3, color);
576  displayDrawLine(display, x3, y3, x1, y1, color);
577 }
578 
579 // when the origin is (0, 0), the point (x1, y1) after rotating the point (x, y)
580 // by the angle is obtained by the following calculation.
581 // x1 = x * cos(angle) - y * sin(angle)
582 // y1 = x * sin(angle) + y * cos(angle)
583 void displayDrawTriangleCenter(display_t *display, uint16_t xc, uint16_t yc,
584  uint16_t w, uint16_t h, uint16_t angle,
585  uint16_t color) {
586  double xd, yd, rd;
587  int x1, y1;
588  int x2, y2;
589  int x3, y3;
590  rd = -angle * M_PI / 180.0;
591  xd = 0.0;
592  yd = h / 2;
593  x1 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
594  y1 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
595 
596  xd = w / 2;
597  yd = 0.0 - yd;
598  x2 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
599  y2 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
600 
601  xd = 0.0 - w / 2;
602  x3 = (int)(xd * cos(rd) - yd * sin(rd) + xc);
603  y3 = (int)(xd * sin(rd) + yd * cos(rd) + yc);
604 
605  if (display == NULL || display->_width != DISPLAY_WIDTH) {
606  pynq_error("displayDrawTriangleCenter: display has not been initialized\n");
607  }
608  if (x1 >= display->_width || y1 >= display->_height) {
609  pynq_error("displayDrawRectAngle: x1=%d y1=%d outside screen boundaries\n",
610  x1, y1);
611  } else if (x2 >= display->_width || y2 >= display->_height) {
612  pynq_error("displayDrawRectAngle: x2=%d y2=%d outside screen boundaries\n",
613  x2, y2);
614  } else if (x3 >= display->_width || y3 >= display->_height) {
615  pynq_error("displayDrawRectAngle: x3=%d y3=%d outside screen boundaries\n",
616  x3, y3);
617  }
618 
619  displayDrawLine(display, x1, y1, x2, y2, color);
620  displayDrawLine(display, x1, y1, x3, y3, color);
621  displayDrawLine(display, x2, y2, x3, y3, color);
622 }
623 
624 void displayDrawCircle(display_t *display, uint16_t x_center, uint16_t y_center,
625  uint16_t r, uint16_t color) {
626  if (display == NULL || display->_width != DISPLAY_WIDTH) {
627  pynq_error("displayDrawCircle: display has not been initialized\n");
628  }
629  if (r == 0) {
630  pynq_error(
631  "displayDrawCircle: x_center=%d y_center=%d r=%d r cannot be 0\n",
632  x_center, y_center, r);
633  }
634 
635  int x_max = x_center + r, x_min = x_center - r, y_max = y_center + r,
636  y_min = y_center - r;
637 
638  if (x_max >= display->_width || x_min < 0 || y_max >= display->_height ||
639  y_min < 0) {
640  pynq_error("displayDrawCircle: x_center=%d y_center=%d r=%d outside screen "
641  "boundaries\n",
642  x_center, y_center, r);
643  }
644 
645  int x;
646  int y;
647  int err;
648  int old_err;
649 
650  x = 0;
651  y = -r;
652  err = 2 - 2 * r;
653  do {
654  displayDrawPixel(display, x_center - x, y_center + y, color);
655  displayDrawPixel(display, x_center - y, y_center - x, color);
656  displayDrawPixel(display, x_center + x, y_center - y, color);
657  displayDrawPixel(display, x_center + y, y_center + x, color);
658  if ((old_err = err) <= x)
659  err += ++x * 2 + 1;
660  if (old_err > y || err > x)
661  err += ++y * 2 + 1;
662  } while (y < 0);
663 }
664 
665 void displayDrawFillCircle(display_t *display, uint16_t x_center,
666  uint16_t y_center, uint16_t r, uint16_t color) {
667  if (display == NULL || display->_width != DISPLAY_WIDTH) {
668  pynq_error("displayDrawFillCircle: display has not been initialized\n");
669  }
670  if (r == 0) {
671  pynq_error(
672  "displayDrawFillCircle: x_center=%d y_center=%d r=%d r cannot be 0\n",
673  x_center, y_center, r);
674  }
675 
676  int x_max = x_center + r, x_min = x_center - r, y_max = y_center + r,
677  y_min = y_center - r;
678 
679  if (x_max >= display->_width || x_min < 0 || y_max >= display->_height ||
680  y_min < 0) {
681  pynq_error("displayDrawFillCircle: x_center=%d y_center=%d r=%d outside "
682  "screen boundaries\n",
683  x_center, y_center, r);
684  }
685 
686  int x;
687  int y;
688  int err;
689  int old_err;
690  int ChangeX;
691 
692  x = 0;
693  y = -r;
694  err = 2 - 2 * r;
695  ChangeX = 1;
696  do {
697  if (ChangeX) {
698  displayDrawLine(display, x_center - x, y_center - y, x_center - x,
699  y_center + y, color);
700  displayDrawLine(display, x_center + x, y_center - y, x_center + x,
701  y_center + y, color);
702  } // endif
703  ChangeX = (old_err = err) <= x;
704  if (ChangeX)
705  err += ++x * 2 + 1;
706  if (old_err > y || err > x)
707  err += ++y * 2 + 1;
708  } while (y <= 0);
709 }
710 
711 void displayDrawRoundRect(display_t *display, uint16_t x1, uint16_t y1,
712  uint16_t x2, uint16_t y2, uint16_t r,
713  uint16_t color) {
714  if (display == NULL || display->_width != DISPLAY_WIDTH) {
715  pynq_error("displayDrawRoundRect: display has not been initialized\n");
716  }
717  if (r == 0) {
718  pynq_error("displayDrawRoundRect: x_center=%d x1=%d y1=%d r cannot be 0\n",
719  x1, y1, r);
720  } else if (x1 >= display->_width || y1 >= display->_height) {
721  pynq_error("displayDrawRoundRect: x1=%d y1=%d outside screen boundaries\n",
722  x1, y1);
723  } else if (x2 >= display->_width || y2 >= display->_height) {
724  pynq_error("displayDrawRoundRect: x2=%d y2=%d outside screen boundaries\n",
725  x2, y2);
726  }
727  int x;
728  int y;
729  int err;
730  int old_err;
731  unsigned char temp;
732 
733  if (x1 > x2) {
734  temp = x1;
735  x1 = x2;
736  x2 = temp;
737  }
738 
739  if (y1 > y2) {
740  temp = y1;
741  y1 = y2;
742  y2 = temp;
743  }
744 
745  if (_DEBUG_)
746  printf("x1=%d x2=%d delta=%d r=%d", x1, x2, x2 - x1, r);
747  if (_DEBUG_)
748  printf("y1=%d y2=%d delta=%d r=%d", y1, y2, y2 - y1, r);
749  if (x2 - x1 < r)
750  return; // TODO add 20190517?
751  if (y2 - y1 < r)
752  return; // TODO add 20190517?
753 
754  x = 0;
755  y = -r;
756  err = 2 - 2 * r;
757 
758  do {
759  if (x) {
760  displayDrawPixel(display, x1 + r - x, y1 + r + y, color);
761  displayDrawPixel(display, x2 - r + x, y1 + r + y, color);
762  displayDrawPixel(display, x1 + r - x, y2 - r - y, color);
763  displayDrawPixel(display, x2 - r + x, y2 - r - y, color);
764  }
765  if ((old_err = err) <= x)
766  err += ++x * 2 + 1;
767  if (old_err > y || err > x)
768  err += ++y * 2 + 1;
769  } while (y < 0);
770 
771  if (_DEBUG_)
772  printf("x1+r=%d x2-r=%d", x1 + r, x2 - r);
773  displayDrawLine(display, x1 + r, y1, x2 - r, y1, color);
774  displayDrawLine(display, x1 + r, y2, x2 - r, y2, color);
775  if (_DEBUG_)
776  printf("y1+r=%d y2-r=%d", y1 + r, y2 - r);
777  displayDrawLine(display, x1, y1 + r, x1, y2 - r, color);
778  displayDrawLine(display, x2, y1 + r, x2, y2 - r, color);
779 }
780 
781 uint16_t rgb_conv(uint16_t r, uint16_t g, uint16_t b) {
782  return (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
783 }
784 
785 int displayDrawChar(display_t *display, FontxFile *fxs, uint16_t x, uint16_t y,
786  uint8_t ascii, uint16_t color) {
787  uint16_t xx, yy, bit, ofs;
788  unsigned char fonts[128]; // font pattern
789  unsigned char pw, ph;
790  int h, w;
791  uint16_t mask;
792  bool rc = GetFontx(fxs, ascii, fonts, &pw, &ph);
793 
794  if (display == NULL || display->_width != DISPLAY_WIDTH) {
795  pynq_error("displayDrawChar: display has not been initialized\n");
796  }
797  if (_DEBUG_) {
798  printf("_font_direction=%d\n", display->_font_direction);
799  printf("GetFontx rc=%d pw=%d ph=%d\n", rc, pw, ph);
800  }
801 
802  if (!rc) {
803  pynq_error("displayDrawChar: cannot get font from font file\n");
804  }
805 
806  switch (display->_font_direction) {
807  case TEXT_DIRECTION0:
808  if (x + pw >= display->_width || y + ph >= display->_height) {
809  pynq_error("displayDrawChar: x=%d y=%d for font height=%d width=%d and "
810  "direction=%d outside screen boundaries\n",
811  x, y, ph, pw, display->_font_direction);
812  }
813  break;
814  case TEXT_DIRECTION90:
815  if (x + ph >= display->_height || y + pw >= display->_width) {
816  pynq_error("displayDrawChar: x=%d y=%d for font height=%d width=%d and "
817  "direction=%d outside screen boundaries\n",
818  x, y, ph, pw, display->_font_direction);
819  }
820  break;
821  case TEXT_DIRECTION180:
822  if (x - pw <= 0 || y - ph <= 0) {
823  pynq_error("displayDrawChar: x=%d y=%d for font height=%d width=%d and "
824  "direction=%d outside screen boundaries\n",
825  x, y, ph, pw, display->_font_direction);
826  }
827  break;
828  case TEXT_DIRECTION270:
829  if (x - ph <= 0 || y - pw <= 0) {
830  pynq_error("displayDrawChar: x=%d y=%d for font height=%d width=%d and "
831  "direction=%d outside screen boundaries\n",
832  x, y, ph, pw, display->_font_direction);
833  }
834  break;
835  }
836 
837  int16_t xd1 = 0, yd1 = 0, xd2 = 0, yd2 = 0;
838  uint16_t xss = 0, yss = 0;
839  int16_t xsd = 0, ysd = 0, next = 0;
840  uint16_t x0 = 0, x1 = 0, y0 = 0, y1 = 0;
841  if (display->_font_direction == 0) {
842  xd1 = +1;
843  yd1 = +1; //-1;
844  xd2 = 0;
845  yd2 = 0;
846  xss = x;
847  yss = y - (ph - 1);
848  xsd = 1;
849  ysd = 0;
850  next = x + pw;
851 
852  x0 = x;
853  y0 = y - (ph - 1);
854  x1 = x + (pw - 1);
855  y1 = y;
856  } else if (display->_font_direction == 2) {
857  xd1 = -1;
858  yd1 = -1; //+1;
859  xd2 = 0;
860  yd2 = 0;
861  xss = x;
862  yss = y + ph + 1;
863  xsd = 1;
864  ysd = 0;
865  next = x - pw;
866 
867  x0 = x - (pw - 1);
868  y0 = y;
869  x1 = x;
870  y1 = y + (ph - 1);
871  } else if (display->_font_direction == 1) {
872  xd1 = 0;
873  yd1 = 0;
874  xd2 = -1;
875  yd2 = +1; //-1;
876  xss = x + ph;
877  yss = y;
878  xsd = 0;
879  ysd = 1;
880  next = y + pw; // y - pw;
881 
882  x0 = x;
883  y0 = y;
884  x1 = x + (ph - 1);
885  y1 = y + (pw - 1);
886  } else if (display->_font_direction == 3) {
887  xd1 = 0;
888  yd1 = 0;
889  xd2 = +1;
890  yd2 = -1; //+1;
891  xss = x - (ph - 1);
892  yss = y;
893  xsd = 0;
894  ysd = 1;
895  next = y - pw; // y + pw;
896 
897  x0 = x - (ph - 1);
898  y0 = y - (pw - 1);
899  x1 = x;
900  y1 = y;
901  }
902 
903  // TODO: fix the problem of underflow properly some time
904  if (display->_font_fill && x0 < DISPLAY_WIDTH && y0 < DISPLAY_HEIGHT &&
905  x1 < DISPLAY_WIDTH && y1 < DISPLAY_HEIGHT) {
906  displayDrawFillRect(display, x0, y0, x1, y1, display->_font_fill_color);
907  }
908 
909  int bits;
910  if (_DEBUG_)
911  printf("xss=%d yss=%d\n", xss, yss);
912  ofs = 0;
913  yy = yss;
914  xx = xss;
915  for (h = 0; h < ph; h++) {
916  if (xsd)
917  xx = xss;
918  if (ysd)
919  yy = yss;
920  bits = pw;
921  for (w = 0; w < ((pw + 4) / 8); w++) {
922  mask = 0x80;
923  for (bit = 0; bit < 8; bit++) {
924  bits--;
925  if (bits < 0)
926  continue;
927  // TODO: fix the problem of underflow properly some time
928  if (fonts[ofs] & mask && xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT) {
929  displayDrawPixel(display, xx, yy, color);
930  }
931  // TODO: fix the problem of underflow properly some time
932  if (h == (ph - 2) && display->_font_underline && xx < DISPLAY_WIDTH &&
933  yy < DISPLAY_HEIGHT)
934  displayDrawPixel(display, xx, yy, display->_font_underline_color);
935  // TODO: fix the problem of underflow properly some time
936  if (h == (ph - 1) && display->_font_underline && xx < DISPLAY_WIDTH &&
937  yy < DISPLAY_HEIGHT)
938  displayDrawPixel(display, xx, yy, display->_font_underline_color);
939  xx = xx + xd1;
940  yy = yy + yd2;
941  mask = mask >> 1;
942  }
943  ofs++;
944  }
945  yy = yy + yd1;
946  xx = xx + xd2;
947  }
948 
949  if (next < 0)
950  next = 0;
951  return next;
952 }
953 
954 int displayDrawString(display_t *display, FontxFile *fx, uint16_t x, uint16_t y,
955  uint8_t *ascii, uint16_t color) {
956  int length = strlen((char *)ascii);
957  if (display == NULL || display->_width != DISPLAY_WIDTH) {
958  pynq_error("displayDrawString: display has not been initialized\n");
959  }
960  if (_DEBUG_)
961  printf("displayDrawString length=%d\n", length);
962  for (int i = 0; i < length; i++) {
963  if (_DEBUG_)
964  printf("ascii[%d]=%x x=%d y=%d\n", i, ascii[i], x, y);
965  if (display->_font_direction == 0)
966  x = displayDrawChar(display, fx, x, y, ascii[i], color);
967  if (display->_font_direction == 1)
968  y = displayDrawChar(display, fx, x, y, ascii[i], color);
969  if (display->_font_direction == 2)
970  x = displayDrawChar(display, fx, x, y, ascii[i], color);
971  if (display->_font_direction == 3)
972  y = displayDrawChar(display, fx, x, y, ascii[i], color);
973  }
974  if (display->_font_direction == 0)
975  return x;
976  if (display->_font_direction == 2)
977  return x;
978  if (display->_font_direction == 1)
979  return y;
980  if (display->_font_direction == 3)
981  return y;
982  return 0;
983 }
984 
985 void displaySetFontDirection(display_t *display, uint16_t dir) {
986  if (display == NULL || display->_width != DISPLAY_WIDTH) {
987  pynq_error("displaySetFontDirection: display has not been initialized\n");
988  }
989  display->_font_direction = dir;
990 }
991 
992 void displaySetFontFill(display_t *display, uint16_t color) {
993  if (display == NULL || display->_width != DISPLAY_WIDTH) {
994  pynq_error("displaySetFontFill: display has not been initialized\n");
995  }
996  display->_font_fill = true;
997  display->_font_fill_color = color;
998 }
999 
1000 void displayUnsetFontFill(display_t *display) { display->_font_fill = false; }
1001 
1002 void displaySetFontUnderLine(display_t *display, uint16_t color) {
1003  if (display == NULL || display->_width != DISPLAY_WIDTH) {
1004  pynq_error("displaySetFontUnderLine: display has not been initialized\n");
1005  }
1006  display->_font_underline = true;
1007  display->_font_underline_color = color;
1008 }
1009 
1011  if (display == NULL || display->_width != DISPLAY_WIDTH) {
1012  pynq_error("displayUnsetFontUnderLine: display has not been initialized\n");
1013  }
1014  display->_font_underline = false;
1015 }
1016 
1018  if (display == NULL || display->_width != DISPLAY_WIDTH) {
1019  pynq_error("displayBacklightOff: display has not been initialized\n");
1020  }
1021  if (display->_bl >= 0) {
1022  gpio_set_level(display->_bl, 0);
1023  }
1024 }
1025 
1027  if (display == NULL || display->_width != DISPLAY_WIDTH) {
1028  pynq_error("displayBacklightOn: display has not been initialized\n");
1029  }
1030  if (display->_bl >= 0) {
1031  gpio_set_level(display->_bl, 1);
1032  }
1033 }
1034 
1036  if (display == NULL || display->_width != DISPLAY_WIDTH) {
1037  pynq_error("displayInversionOff: display has not been initialized\n");
1038  }
1039  spi_master_write_command(display, 0x21); // display Inversion Off
1040 }
1041 
1043  if (display == NULL || display->_width != DISPLAY_WIDTH) {
1044  pynq_error("displayInversionOn: display has not been initialized\n");
1045  }
1046  spi_master_write_command(display, 0x20); // display Inversion On
1047 }
displayInit
void displayInit(display_t *display, int width, int height, int offsetx, int offsety)
Definition: display.c:229
display_t
Internal type, do not use. Type of display that stores parameters for usage in different functions.
Definition: display.h:116
spi_master_write_color
bool spi_master_write_color(display_t *display, uint16_t color, uint16_t size)
Definition: display.c:115
GPIO_DIR_OUTPUT
@ GPIO_DIR_OUTPUT
Definition: gpio.h:92
displayDisplayOn
void displayDisplayOn(display_t *display)
Initialize DISPLAY screen.
Definition: display.c:413
SWB_GPIO
@ SWB_GPIO
Definition: switchbox.h:64
display_t::_height
uint16_t _height
Definition: display.h:118
_DEBUG_
#define _DEBUG_
Definition: display.c:42
GPIO_MODE_OUTPUT
#define GPIO_MODE_OUTPUT
Definition: display.c:52
displayBacklightOff
void displayBacklightOff(display_t *display)
Turn off the display backlight.
Definition: display.c:1017
displayInversionOn
void displayInversionOn(display_t *display)
Turn on inversion of the colors.
Definition: display.c:1042
pynq_error
#define pynq_error(...)
Definition: log.h:118
switchbox_set_pin
void switchbox_set_pin(const pin_t pin_number, const uint8_t pin_type)
Definition: switchbox.c:4
spi_master_write_data_word
bool spi_master_write_data_word(display_t *display, uint16_t data)
Definition: display.c:83
DISPLAY_WIDTH
#define DISPLAY_WIDTH
Definition: display.h:84
arm_shared_memory_system.h
gpio_set_level
void gpio_set_level(const io_t pin, const gpio_level_t level)
Set the level of the output IO pin. If the pin is configured as input, this function does nothing.
Definition: gpio.c:7
spi_master_init
void spi_master_init(display_t *display)
Definition: display.c:148
displaySetFontFill
void displaySetFontFill(display_t *display, uint16_t color)
Enables the _font_fill and sets the _font_fill_color in the display handle.
Definition: display.c:992
gpio_reset_pin
void gpio_reset_pin(const io_t pin)
Function is currently a no-op placeholder for arduino compatibility.
Definition: gpio.c:4
sleep_msec
void sleep_msec(int msec)
Wait for msec milliseconds.
Definition: util.c:2
spi_mode_t
spi_mode_t
Definition: display.c:50
display_t::_bl
int16_t _bl
Definition: display.h:127
arm_shared_t
Definition: arm_shared_memory_system.h:39
displayDrawCircle
void displayDrawCircle(display_t *display, uint16_t x_center, uint16_t y_center, uint16_t r, uint16_t color)
Draw a circle without infill on the display.
Definition: display.c:624
arm_shared_close
void arm_shared_close(arm_shared *handle)
Definition: arm_shared_memory_system.c:70
switchbox.h
SWB_SPI1_CLK
@ SWB_SPI1_CLK
Definition: switchbox.h:80
GPIO_LEVEL_LOW
@ GPIO_LEVEL_LOW
Definition: gpio.h:100
display_t::_font_underline
uint16_t _font_underline
Definition: display.h:124
DISPLAY_HEIGHT
#define DISPLAY_HEIGHT
Definition: display.h:83
SWB_SPI1_MOSI
@ SWB_SPI1_MOSI
Definition: switchbox.h:84
spi_master_write_data_byte
bool spi_master_write_data_byte(display_t *display, uint8_t data)
Definition: display.c:74
displaySetFontDirection
void displaySetFontDirection(display_t *display, uint16_t dir)
Changes the direction the characters will be printed.
Definition: display.c:985
displayDrawRectAngle
void displayDrawRectAngle(display_t *display, uint16_t xc, uint16_t yc, uint16_t w, uint16_t h, uint16_t angle, uint16_t color)
Draws a rectangle with rounded corners at a specified angle on the display.
Definition: display.c:499
display_t::_offsetx
uint16_t _offsetx
Definition: display.h:119
gpio_set_direction
void gpio_set_direction(const io_t pin, const gpio_direction_t direction)
Set the IO pin as in input or output.
Definition: gpio.c:5
displayUnsetFontFill
void displayUnsetFontFill(display_t *display)
Sets the _font_fill parameter to false in the display handle, turns off the font fill.
Definition: display.c:1000
spi_master_write_command
bool spi_master_write_command(display_t *display, uint8_t cmd)
Definition: display.c:65
display_destroy
void display_destroy(display_t *display __attribute__((unused)))
Definition: display.c:309
displayUnsetFontUnderLine
void displayUnsetFontUnderLine(display_t *display)
Turns off _font_underline in the display handle.
Definition: display.c:1010
spi_master_write_colors
bool spi_master_write_colors(display_t *display, uint16_t *colors, uint16_t size)
Definition: display.c:130
display_init
void display_init(display_t *display)
Initialize the display display.
Definition: display.c:301
display_t::_font_underline_color
uint16_t _font_underline_color
Definition: display.h:125
rgb_conv
uint16_t rgb_conv(uint16_t r, uint16_t g, uint16_t b)
RGB conversion for generating a color.
Definition: display.c:781
gpio_level_t
gpio_level_t
Definition: gpio.h:98
TEXT_DIRECTION180
@ TEXT_DIRECTION180
Definition: display.h:107
__attribute__
union __attribute__((packed))
Definition: stepper.c:51
displayInversionOff
void displayInversionOff(display_t *display)
Turn off inversion of the colors.
Definition: display.c:1035
displayBacklightOn
void displayBacklightOn(display_t *display)
Turn on the display backlight.
Definition: display.c:1026
TEXT_DIRECTION0
@ TEXT_DIRECTION0
Definition: display.h:105
SPI_Command_Mode
@ SPI_Command_Mode
Definition: display.c:50
displayDrawRect
void displayDrawRect(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Draw a filled rectangle.
Definition: display.c:481
displayDrawTriangleCenter
void displayDrawTriangleCenter(display_t *display, uint16_t xc, uint16_t yc, uint16_t w, uint16_t h, uint16_t angle, uint16_t color)
Draws a triangle at a specified angle on the display.
Definition: display.c:583
display_t::_font_fill_color
uint16_t _font_fill_color
Definition: display.h:123
GetFontx
bool GetFontx(FontxFile *fxs, uint8_t ascii, uint8_t *pGlyph, uint8_t *pw, uint8_t *ph)
Gets the glyph data for the specified ASCII character.
Definition: fontx.c:9
display_set_flip
void display_set_flip(display_t *display, bool xflip, bool yflip)
Flip the drawing off the screen.
Definition: display.c:279
log.h
display_t::_width
uint16_t _width
Definition: display.h:117
FontxFile
Struct representing a font file.
Definition: fontx.h:28
arm_shared_init
void * arm_shared_init(arm_shared *handle, const uint32_t address, const uint32_t length)
Definition: arm_shared_memory_system.c:32
display.h
spi_master_write_addr
bool spi_master_write_addr(display_t *display, uint16_t addr1, uint16_t addr2)
Definition: display.c:96
TEXT_DIRECTION90
@ TEXT_DIRECTION90
Definition: display.h:106
gpio.h
SPI_Data_Mode
@ SPI_Data_Mode
Definition: display.c:50
displayDrawLine
void displayDrawLine(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Draw a line from two coordinates.
Definition: display.c:428
colors
colors
Colors that can be used with the display.
Definition: display.h:89
TEXT_DIRECTION270
@ TEXT_DIRECTION270
Definition: display.h:108
spi_to_gpio
gpio_level_t spi_to_gpio(spi_mode_t mode)
Definition: display.c:54
displayDisplayOff
void displayDisplayOff(display_t *display)
Turn off the display.
Definition: display.c:406
displayFillScreen
void displayFillScreen(display_t *display, uint16_t color)
Fill entire display with a single color using the ldcDrawFillRect function.
Definition: display.c:420
display_t::_font_direction
uint16_t _font_direction
Definition: display.h:121
displaySetFontUnderLine
void displaySetFontUnderLine(display_t *display, uint16_t color)
Turns on _font_underline in the display handle and sets the _font_underline_color to the specified co...
Definition: display.c:1002
GPIO_LEVEL_HIGH
@ GPIO_LEVEL_HIGH
Definition: gpio.h:102
displayDrawTriangle
void displayDrawTriangle(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)
Draw a triangle without infill between the three given points in the given color.
Definition: display.c:556
SWB_SPI1_SS
@ SWB_SPI1_SS
Definition: switchbox.h:86
displayDrawRoundRect
void displayDrawRoundRect(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t r, uint16_t color)
Draw a rectangle with rounded angles.
Definition: display.c:711
displayDrawFillRect
void displayDrawFillRect(display_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
Draw a filled rectangle to the display.
Definition: display.c:364
util.h
display_t::_font_fill
uint16_t _font_fill
Definition: display.h:122
displayDrawMultiPixels
void displayDrawMultiPixels(display_t *display, uint16_t x, uint16_t y, uint16_t size, uint16_t *colors)
Definition: display.c:339
displayDrawPixel
void displayDrawPixel(display_t *display, uint16_t x, uint16_t y, uint16_t color)
Draw a single pixel to the display.
Definition: display.c:320
display_t::_dc
int16_t _dc
Definition: display.h:126
M_PI
#define M_PI
Definition: display.c:44
displayDrawFillCircle
void displayDrawFillCircle(display_t *display, uint16_t x_center, uint16_t y_center, uint16_t r, uint16_t color)
Draw a circle with infill on the display.
Definition: display.c:665
display_t::_offsety
uint16_t _offsety
Definition: display.h:120
displayDrawChar
int displayDrawChar(display_t *display, FontxFile *fxs, uint16_t x, uint16_t y, uint8_t ascii, uint16_t color)
Draws a character on the given coordinates of the display.
Definition: display.c:785
displayDrawString
int displayDrawString(display_t *display, FontxFile *fx, uint16_t x, uint16_t y, uint8_t *ascii, uint16_t color)
Function to draw a string on the display.
Definition: display.c:954