dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
osd_utils.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  *
31  * Additional note on redistribution: The copyright and license notices above
32  * must be maintained in each individual source file that is a derivative work
33  * of this source file; otherwise redistribution is prohibited.
34  */
35 
36 #include <openpilot.h>
37 #include "pios_video.h"
38 #include "fonts.h"
39 #include "osd_utils.h"
40 #include "physical_constants.h"
41 #include "math.h"
42 #include "misc_math.h"
43 
44 #include "gpsposition.h"
45 #include "homelocation.h"
46 
47 extern struct FontEntry* fonts[NUM_FONTS];
48 
49 #if defined(PIOS_VIDEO_SPLITBUFFER)
50 extern uint8_t *draw_buffer_level;
51 extern uint8_t *draw_buffer_mask;
52 extern uint8_t *disp_buffer_level;
53 extern uint8_t *disp_buffer_mask;
54 #else
55 extern uint8_t *draw_buffer;
56 extern uint8_t *disp_buffer;
57 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
58 
59 
61 {
62 #if defined(PIOS_VIDEO_SPLITBUFFER)
63  memset((uint8_t *)draw_buffer_mask, 0, BUFFER_HEIGHT * BUFFER_WIDTH);
64  memset((uint8_t *)draw_buffer_level, 0, BUFFER_HEIGHT * BUFFER_WIDTH);
65 #else
66  memset((uint8_t *)draw_buffer, 0, BUFFER_HEIGHT * BUFFER_WIDTH);
67 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
68 }
69 
70 void draw_image(uint16_t x, uint16_t y, const struct Image * image)
71 {
72 #if defined(PIOS_VIDEO_SPLITBUFFER)
73  CHECK_COORDS(x + image->width, y + image->height);
74  uint8_t byte_width = image->width / 8;
75  uint8_t pixel_offset = x % 8;
76  uint8_t mask1 = 0xFF;
77  uint8_t mask2 = 0x00;
78 
79  if (pixel_offset > 0) {
80  for (uint8_t i = 0; i<pixel_offset; i++) {
81  mask2 |= 0x01 << i;
82  }
83  mask1 = ~mask2;
84  }
85 
86  for (uint16_t yp = 0; yp < image->height; yp++) {
87  for (uint16_t xp = 0; xp < image->width / 8; xp++) {
88  draw_buffer_level[(y + yp) * BUFFER_WIDTH + xp + x / 8] |= (image->level[yp * byte_width + xp] & mask1) >> pixel_offset;
89  draw_buffer_mask[(y + yp) * BUFFER_WIDTH + xp + x / 8] |= (image->mask[yp * byte_width + xp] & mask1) >> pixel_offset;
90  if (pixel_offset > 0) {
91  draw_buffer_level[(y + yp) * BUFFER_WIDTH + xp + x / 8 + 1] |= (image->level[yp * byte_width + xp] & mask2) <<
92  (8 - pixel_offset);
93  draw_buffer_mask[(y + yp) * BUFFER_WIDTH + xp + x / 8 + 1] |= (image->mask[yp * byte_width + xp] & mask2) <<
94  (8 - pixel_offset);
95  }
96  }
97  }
98 #else
99  CHECK_COORDS(x + image->width, y + image->height);
100  uint8_t byte_width = image->width / 4;
101  uint8_t pixel_offset = 2 * (x % 4);
102  uint8_t mask1 = 0xFF;
103  uint8_t mask2 = 0x00;
104 
105  if (pixel_offset > 0) {
106  for (uint8_t i = 0; i<pixel_offset; i++) {
107  mask2 |= 0x01 << i;
108  }
109  mask1 = ~mask2;
110  }
111 
112  for (uint16_t yp = 0; yp < image->height; yp++) {
113  for (uint16_t xp = 0; xp < byte_width; xp++) {
114  draw_buffer[(y + yp) * BUFFER_WIDTH + xp + x / 4] |= (image->data[yp * byte_width + xp] & mask1) >> pixel_offset;
115  if (pixel_offset > 0) {
116  draw_buffer[(y + yp) * BUFFER_WIDTH + xp + x / 4 + 1] |= (image->data[yp * byte_width + xp] & mask2) <<
117  (8 - pixel_offset);
118  }
119  }
120  }
121 #endif /* PIOS_VIDEO_SPLITBUFFER */
122 }
123 
136 void plotFourQuadrants(int32_t centerX, int32_t centerY, int32_t deltaX, int32_t deltaY)
137 {
138  write_pixel_lm(centerX + deltaX, centerY + deltaY, 1, 1); // Ist Quadrant
139  write_pixel_lm(centerX - deltaX, centerY + deltaY, 1, 1); // IInd Quadrant
140  write_pixel_lm(centerX - deltaX, centerY - deltaY, 1, 1); // IIIrd Quadrant
141  write_pixel_lm(centerX + deltaX, centerY - deltaY, 1, 1); // IVth Quadrant
142 }
143 
152 void ellipse(int centerX, int centerY, int horizontalRadius, int verticalRadius)
153 {
154  int64_t doubleHorizontalRadius = horizontalRadius * horizontalRadius;
155  int64_t doubleVerticalRadius = verticalRadius * verticalRadius;
156 
157  int64_t error = doubleVerticalRadius - doubleHorizontalRadius * verticalRadius + (doubleVerticalRadius >> 2);
158 
159  int x = 0;
160  int y = verticalRadius;
161  int deltaX = 0;
162  int deltaY = (doubleHorizontalRadius << 1) * y;
163 
164  plotFourQuadrants(centerX, centerY, x, y);
165 
166  while (deltaY >= deltaX) {
167  x++;
168  deltaX += (doubleVerticalRadius << 1);
169 
170  error += deltaX + doubleVerticalRadius;
171 
172  if (error >= 0) {
173  y--;
174  deltaY -= (doubleHorizontalRadius << 1);
175 
176  error -= deltaY;
177  }
178  plotFourQuadrants(centerX, centerY, x, y);
179  }
180 
181  error = (int64_t)(doubleVerticalRadius * (x + 1 / 2.0f) * (x + 1 / 2.0f) + doubleHorizontalRadius * (y - 1) * (y - 1) - doubleHorizontalRadius * doubleVerticalRadius);
182 
183  while (y >= 0) {
184  error += doubleHorizontalRadius;
185  y--;
186  deltaY -= (doubleHorizontalRadius << 1);
187  error -= deltaY;
188 
189  if (error <= 0) {
190  x++;
191  deltaX += (doubleVerticalRadius << 1);
192  error += deltaX;
193  }
194 
195  plotFourQuadrants(centerX, centerY, x, y);
196  }
197 }
198 
199 void drawArrow(uint16_t x, uint16_t y, uint16_t angle, uint16_t size_quarter)
200 {
201  float sin_angle = sinf(angle * (float)(M_PI / 180));
202  float cos_angle = cosf(angle * (float)(M_PI / 180));
203  int16_t peak_x = (int16_t)(sin_angle * size_quarter * 2);
204  int16_t peak_y = (int16_t)(cos_angle * size_quarter * 2);
205  int16_t d_end_x = (int16_t)(cos_angle * size_quarter);
206  int16_t d_end_y = (int16_t)(sin_angle * size_quarter);
207 
208  write_line_lm(x + peak_x, y - peak_y, x - peak_x - d_end_x, y + peak_y - d_end_y, 1, 1);
209  write_line_lm(x + peak_x, y - peak_y, x - peak_x + d_end_x, y + peak_y + d_end_y, 1, 1);
210  write_line_lm(x, y, x - peak_x - d_end_x, y + peak_y - d_end_y, 1, 1);
211  write_line_lm(x, y, x - peak_x + d_end_x, y + peak_y + d_end_y, 1, 1);
212 }
213 
214 void drawBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
215 {
216  write_line_lm(x1, y1, x2, y1, 1, 1); // top
217  write_line_lm(x1, y1, x1, y2, 1, 1); // left
218  write_line_lm(x2, y1, x2, y2, 1, 1); // right
219  write_line_lm(x1, y2, x2, y2, 1, 1); // bottom
220 }
221 
222 #if defined(PIOS_VIDEO_SPLITBUFFER)
223 
231 void write_pixel(uint8_t *buff, int x, int y, int mode)
232 {
233  CHECK_COORDS(x, y);
234  // Determine the bit in the word to be set and the word
235  // index to set it in.
236  int wordnum = CALC_BUFF_ADDR(x, y);
237  uint8_t mask = CALC_BIT_MASK(x);
238  WRITE_WORD_MODE(buff, wordnum, mask, mode);
239 }
240 #else
241 void write_pixel(int x, int y, uint8_t value)
242 {
243  CHECK_COORDS(x, y);
244  // Determine the bit in the word to be set and the word
245  // index to set it in.
246  int wordnum = CALC_BUFF_ADDR(x, y);
247  uint8_t mask = CALC_BIT_MASK(x);
248  WRITE_WORD(draw_buffer, wordnum, mask, value);
249 }
250 #endif /* PIOS_VIDEO_SPLITBUFFER */
251 
261 void write_pixel_lm(int x, int y, int mmode, int lmode)
262 {
263  CHECK_COORDS(x, y);
264  // Determine the bit in the word to be set and the word
265  // index to set it in.
266  int addr = CALC_BUFF_ADDR(x, y);
267  uint8_t mask = CALC_BIT_MASK(x);
268 #if defined(PIOS_VIDEO_SPLITBUFFER)
269  WRITE_WORD_MODE(draw_buffer_mask, addr, mask, mmode);
270  WRITE_WORD_MODE(draw_buffer_level, addr, mask, lmode);
271 #else
272  uint8_t value = PACK_BITS(mmode, lmode);
273  WRITE_WORD(draw_buffer, addr, mask, value);
274 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
275 }
276 
286 #if defined(PIOS_VIDEO_SPLITBUFFER)
287 void write_hline(uint8_t *buff, int x0, int x1, int y, int mode)
288 {
289  CHECK_COORD_Y(y);
290  CLIP_COORD_X(x0);
291  CLIP_COORD_X(x1);
292  if (x0 > x1) {
293  SWAP(x0, x1);
294  }
295  if (x0 == x1) {
296  return;
297  }
298  /* This is an optimised algorithm for writing horizontal lines.
299  * We begin by finding the addresses of the x0 and x1 points. */
300  int addr0 = CALC_BUFF_ADDR(x0, y);
301  int addr1 = CALC_BUFF_ADDR(x1, y);
302  int addr0_bit = CALC_BIT_IN_WORD(x0);
303  int addr1_bit = CALC_BIT_IN_WORD(x1);
304  int mask, mask_l, mask_r, i;
305  /* If the addresses are equal, we only need to write one word
306  * which is an island. */
307  if (addr0 == addr1) {
308  mask = COMPUTE_HLINE_ISLAND_MASK(addr0_bit, addr1_bit);
309  WRITE_WORD_MODE(buff, addr0, mask, mode);
310  } else {
311  /* Otherwise we need to write the edges and then the middle. */
312  mask_l = COMPUTE_HLINE_EDGE_L_MASK(addr0_bit);
313  mask_r = COMPUTE_HLINE_EDGE_R_MASK(addr1_bit);
314  WRITE_WORD_MODE(buff, addr0, mask_l, mode);
315  WRITE_WORD_MODE(buff, addr1, mask_r, mode);
316  // Now write 0xffff words from start+1 to end-1.
317  for (i = addr0 + 1; i <= addr1 - 1; i++) {
318  uint8_t m = 0xff;
319  WRITE_WORD_MODE(buff, i, m, mode);
320  }
321  }
322 }
323 #else
324 void write_hline(int x0, int x1, int y, uint8_t value)
325 {
326  CHECK_COORD_Y(y);
327  CLIP_COORD_X(x0);
328  CLIP_COORD_X(x1);
329  if (x0 > x1) {
330  SWAP(x0, x1);
331  }
332  if (x0 == x1) {
333  return;
334  }
335  /* This is an optimised algorithm for writing horizontal lines.
336  * We begin by finding the addresses of the x0 and x1 points. */
337  int addr0 = CALC_BUFF_ADDR(x0, y);
338  int addr1 = CALC_BUFF_ADDR(x1, y);
339  int addr0_bit = CALC_BIT1_IN_WORD(x0);
340  int addr1_bit = CALC_BIT0_IN_WORD(x1);
341  int mask, mask_l, mask_r, i;
342  /* If the addresses are equal, we only need to write one word
343  * which is an island. */
344  if (addr0 == addr1) {
345  mask = COMPUTE_HLINE_ISLAND_MASK(addr0_bit, addr1_bit);
346  WRITE_WORD(draw_buffer, addr0, mask, value);
347  } else {
348  /* Otherwise we need to write the edges and then the middle. */
349  mask_l = COMPUTE_HLINE_EDGE_L_MASK(addr0_bit);
350  mask_r = COMPUTE_HLINE_EDGE_R_MASK(addr1_bit);
351  WRITE_WORD(draw_buffer, addr0, mask_l, value);
352  WRITE_WORD(draw_buffer, addr1, mask_r, value);
353  // Now write 0xffff words from start+1 to end-1.
354  for (i = addr0 + 1; i <= addr1 - 1; i++) {
355  uint8_t m = 0xff;
356  WRITE_WORD(draw_buffer, i, m, value);
357  }
358  }
359 }
360 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
361 
362 
372 void write_hline_lm(int x0, int x1, int y, int lmode, int mmode)
373 {
374 #if defined(PIOS_VIDEO_SPLITBUFFER)
375  // TODO: an optimisation would compute the masks and apply to
376  // both buffers simultaneously.
377  write_hline(draw_buffer_level, x0, x1, y, lmode);
378  write_hline(draw_buffer_mask, x0, x1, y, mmode);
379 #else
380  uint8_t value = PACK_BITS(mmode, lmode);
381  write_hline(x0, x1, y, value);
382 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
383 }
384 
397 void write_hline_outlined(int x0, int x1, int y, int endcap0, int endcap1, int mode, int mmode)
398 {
399  int stroke, fill;
400 
401  SETUP_STROKE_FILL(stroke, fill, mode);
402  if (x0 > x1) {
403  SWAP(x0, x1);
404  }
405  // Draw the main body of the line.
406  write_hline_lm(x0 + 1, x1 - 1, y - 1, stroke, mmode);
407  write_hline_lm(x0 + 1, x1 - 1, y + 1, stroke, mmode);
408  write_hline_lm(x0 + 1, x1 - 1, y, fill, mmode);
409  // Draw the endcaps, if any.
410  DRAW_ENDCAP_HLINE(endcap0, x0, y, stroke, fill, mmode);
411  DRAW_ENDCAP_HLINE(endcap1, x1, y, stroke, fill, mmode);
412 }
413 
423 #if defined(PIOS_VIDEO_SPLITBUFFER)
424 void write_vline(uint8_t *buff, int x, int y0, int y1, int mode)
425 {
426  CHECK_COORD_X(x);
427  CLIP_COORD_Y(y0);
428  CLIP_COORD_Y(y1);
429  if (y0 > y1) {
430  SWAP(y0, y1);
431  }
432  if (y0 == y1) {
433  return;
434  }
435  /* This is an optimised algorithm for writing vertical lines.
436  * We begin by finding the addresses of the x,y0 and x,y1 points. */
437  int addr0 = CALC_BUFF_ADDR(x, y0);
438  int addr1 = CALC_BUFF_ADDR(x, y1);
439  /* Then we calculate the pixel data to be written. */
440  uint8_t mask = CALC_BIT_MASK(x);
441  /* Run from addr0 to addr1 placing pixels. Increment by the number
442  * of words n each graphics line. */
443  for (int a = addr0; a <= addr1; a += BUFFER_WIDTH) {
444  WRITE_WORD_MODE(buff, a, mask, mode);
445  }
446 }
447 #else
448 void write_vline(int x, int y0, int y1, uint8_t value)
449 {
450  CHECK_COORD_X(x);
451  CLIP_COORD_Y(y0);
452  CLIP_COORD_Y(y1);
453  if (y0 > y1) {
454  SWAP(y0, y1);
455  }
456  if (y0 == y1) {
457  return;
458  }
459  /* This is an optimised algorithm for writing vertical lines.
460  * We begin by finding the addresses of the x,y0 and x,y1 points. */
461  int addr0 = CALC_BUFF_ADDR(x, y0);
462  int addr1 = CALC_BUFF_ADDR(x, y1);
463  /* Then we calculate the pixel data to be written. */
464  uint8_t mask = CALC_BIT_MASK(x);
465  /* Run from addr0 to addr1 placing pixels. Increment by the number
466  * of words n each graphics line. */
467  for (int a = addr0; a <= addr1; a += BUFFER_WIDTH) {
468  WRITE_WORD(draw_buffer, a, mask, value);
469  }
470 }
471 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
472 
473 
483 void write_vline_lm(int x, int y0, int y1, int lmode, int mmode)
484 {
485 #if defined(PIOS_VIDEO_SPLITBUFFER)
486  // TODO: an optimisation would compute the masks and apply to
487  // both buffers simultaneously.
488  write_vline(draw_buffer_level, x, y0, y1, lmode);
489  write_vline(draw_buffer_mask, x, y0, y1, mmode);
490 #else
491  uint8_t value = PACK_BITS(mmode, lmode);
492  write_vline(x, y0, y1, value);
493 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
494 }
495 
508 void write_vline_outlined(int x, int y0, int y1, int endcap0, int endcap1, int mode, int mmode)
509 {
510  int stroke, fill;
511 
512  if (y0 > y1) {
513  SWAP(y0, y1);
514  }
515  SETUP_STROKE_FILL(stroke, fill, mode);
516  // Draw the main body of the line.
517  write_vline_lm(x - 1, y0 + 1, y1 - 1, stroke, mmode);
518  write_vline_lm(x + 1, y0 + 1, y1 - 1, stroke, mmode);
519  write_vline_lm(x, y0 + 1, y1 - 1, fill, mmode);
520  // Draw the endcaps, if any.
521  DRAW_ENDCAP_VLINE(endcap0, x, y0, stroke, fill, mmode);
522  DRAW_ENDCAP_VLINE(endcap1, x, y1, stroke, fill, mmode);
523 }
524 
539 #if defined(PIOS_VIDEO_SPLITBUFFER)
540 void write_filled_rectangle(uint8_t *buff, int x, int y, int width, int height, int mode)
541 {
542  int yy, addr0_old, addr1_old;
543 
544  CHECK_COORDS(x, y);
545  CHECK_COORDS(x + width, y + height);
546  if (width <= 0 || height <= 0) {
547  return;
548  }
549  // Calculate as if the rectangle was only a horizontal line. We then
550  // step these addresses through each row until we iterate `height` times.
551  int addr0 = CALC_BUFF_ADDR(x, y);
552  int addr1 = CALC_BUFF_ADDR(x + width, y);
553  int addr0_bit = CALC_BIT_IN_WORD(x);
554  int addr1_bit = CALC_BIT_IN_WORD(x + width);
555  int mask, mask_l, mask_r, i;
556  // If the addresses are equal, we need to write one word vertically.
557  if (addr0 == addr1) {
558  mask = COMPUTE_HLINE_ISLAND_MASK(addr0_bit, addr1_bit);
559  while (height--) {
560  WRITE_WORD_MODE(buff, addr0, mask, mode);
561  addr0 += BUFFER_WIDTH;
562  }
563  } else {
564  // Otherwise we need to write the edges and then the middle repeatedly.
565  mask_l = COMPUTE_HLINE_EDGE_L_MASK(addr0_bit);
566  mask_r = COMPUTE_HLINE_EDGE_R_MASK(addr1_bit);
567  // Write edges first.
568  yy = 0;
569  addr0_old = addr0;
570  addr1_old = addr1;
571  while (yy < height) {
572  WRITE_WORD_MODE(buff, addr0, mask_l, mode);
573  WRITE_WORD_MODE(buff, addr1, mask_r, mode);
574  addr0 += BUFFER_WIDTH;
575  addr1 += BUFFER_WIDTH;
576  yy++;
577  }
578  // Now write 0xffff words from start+1 to end-1 for each row.
579  yy = 0;
580  addr0 = addr0_old;
581  addr1 = addr1_old;
582  while (yy < height) {
583  for (i = addr0 + 1; i <= addr1 - 1; i++) {
584  uint8_t m = 0xff;
585  WRITE_WORD_MODE(buff, i, m, mode);
586  }
587  addr0 += BUFFER_WIDTH;
588  addr1 += BUFFER_WIDTH;
589  yy++;
590  }
591  }
592 }
593 #else
594 void write_filled_rectangle(int x, int y, int width, int height, uint8_t value)
595 {
596  int yy, addr0_old, addr1_old;
597 
598  CHECK_COORDS(x, y);
599  CHECK_COORDS(x + width, y + height);
600  if (width <= 0 || height <= 0) {
601  return;
602  }
603  // Calculate as if the rectangle was only a horizontal line. We then
604  // step these addresses through each row until we iterate `height` times.
605  int addr0 = CALC_BUFF_ADDR(x, y);
606  int addr1 = CALC_BUFF_ADDR(x + width, y);
607  int addr0_bit = CALC_BIT_IN_WORD(x);
608  int addr1_bit = CALC_BIT_IN_WORD(x + width);
609  int mask, mask_l, mask_r, i;
610  // If the addresses are equal, we need to write one word vertically.
611  if (addr0 == addr1) {
612  mask = COMPUTE_HLINE_ISLAND_MASK(addr0_bit, addr1_bit);
613  while (height--) {
614  WRITE_WORD(draw_buffer, addr0, mask, value);
615  addr0 += BUFFER_WIDTH;
616  }
617  } else {
618  // Otherwise we need to write the edges and then the middle repeatedly.
619  mask_l = COMPUTE_HLINE_EDGE_L_MASK(addr0_bit);
620  mask_r = COMPUTE_HLINE_EDGE_R_MASK(addr1_bit);
621  // Write edges first.
622  yy = 0;
623  addr0_old = addr0;
624  addr1_old = addr1;
625  while (yy < height) {
626  WRITE_WORD(draw_buffer, addr0, mask_l, value);
627  WRITE_WORD(draw_buffer, addr1, mask_r, value);
628  addr0 += BUFFER_WIDTH;
629  addr1 += BUFFER_WIDTH;
630  yy++;
631  }
632  // Now write 0xffff words from start+1 to end-1 for each row.
633  yy = 0;
634  addr0 = addr0_old;
635  addr1 = addr1_old;
636  while (yy < height) {
637  for (i = addr0 + 1; i <= addr1 - 1; i++) {
638  uint8_t m = 0xff;
639  WRITE_WORD(draw_buffer, i, m, value);
640  }
641  addr0 += BUFFER_WIDTH;
642  addr1 += BUFFER_WIDTH;
643  yy++;
644  }
645  }
646 }
647 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
648 
659 void write_filled_rectangle_lm(int x, int y, int width, int height, int lmode, int mmode)
660 {
661 #if defined(PIOS_VIDEO_SPLITBUFFER)
662  write_filled_rectangle(draw_buffer_mask, x, y, width, height, mmode);
663  write_filled_rectangle(draw_buffer_level, x, y, width, height, lmode);
664 #else
665  uint8_t value = PACK_BITS(mmode, lmode);
666  write_filled_rectangle(x, y, width, height, value);
667 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
668 }
669 
681 void write_rectangle_outlined(int x, int y, int width, int height, int mode, int mmode)
682 {
683  write_hline_outlined(x, x + width, y, ENDCAP_ROUND, ENDCAP_ROUND, mode, mmode);
684  write_hline_outlined(x, x + width, y + height, ENDCAP_ROUND, ENDCAP_ROUND, mode, mmode);
685  write_vline_outlined(x, y, y + height, ENDCAP_ROUND, ENDCAP_ROUND, mode, mmode);
686  write_vline_outlined(x + width, y, y + height, ENDCAP_ROUND, ENDCAP_ROUND, mode, mmode);
687 }
688 
689 #if defined(PIOS_VIDEO_SPLITBUFFER)
690 
701 void write_circle(uint8_t *buff, int cx, int cy, int r, int dashp, int mode)
702 {
703  CHECK_COORDS(cx, cy);
704  int error = -r, x = r, y = 0;
705  while (x >= y) {
706  if (dashp == 0 || (y % dashp) < (dashp / 2)) {
707  CIRCLE_PLOT_8(buff, cx, cy, x, y, mode);
708  }
709  error += (y * 2) + 1;
710  y++;
711  if (error >= 0) {
712  --x;
713  error -= x * 2;
714  }
715  }
716 }
717 
729 void write_circle_outlined(int cx, int cy, int r, int dashp, int bmode, int mode, int mmode)
730 {
731  int stroke, fill;
732 
733  CHECK_COORDS(cx, cy);
734  SETUP_STROKE_FILL(stroke, fill, mode);
735  // This is a two step procedure. First, we draw the outline of the
736  // circle, then we draw the inner part.
737  int error = -r, x = r, y = 0;
738  while (x >= y) {
739  if (dashp == 0 || (y % dashp) < (dashp / 2)) {
740  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x + 1, y, mmode);
741  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x + 1, y, stroke);
742  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x, y + 1, mmode);
743  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x, y + 1, stroke);
744  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x - 1, y, mmode);
745  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x - 1, y, stroke);
746  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x, y - 1, mmode);
747  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x, y - 1, stroke);
748  if (bmode == 1) {
749  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x + 1, y + 1, mmode);
750  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x + 1, y + 1, stroke);
751  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x - 1, y - 1, mmode);
752  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x - 1, y - 1, stroke);
753  }
754  }
755  error += (y * 2) + 1;
756  y++;
757  if (error >= 0) {
758  --x;
759  error -= x * 2;
760  }
761  }
762  error = -r;
763  x = r;
764  y = 0;
765  while (x >= y) {
766  if (dashp == 0 || (y % dashp) < (dashp / 2)) {
767  CIRCLE_PLOT_8(draw_buffer_mask, cx, cy, x, y, mmode);
768  CIRCLE_PLOT_8(draw_buffer_level, cx, cy, x, y, fill);
769  }
770  error += (y * 2) + 1;
771  y++;
772  if (error >= 0) {
773  --x;
774  error -= x * 2;
775  }
776  }
777 }
778 
788 void write_circle_filled(uint8_t *buff, int cx, int cy, int r, int mode)
789 {
790  CHECK_COORDS(cx, cy);
791  int error = -r, x = r, y = 0, xch = 0;
792  // It turns out that filled circles can take advantage of the midpoint
793  // circle algorithm. We simply draw very fast horizontal lines across each
794  // pair of X,Y coordinates. In some cases, this can even be faster than
795  // drawing an outlined circle!
796  //
797  // Due to multiple writes to each set of pixels, we have a special exception
798  // for when using the toggling draw mode.
799  while (x >= y) {
800  if (y != 0) {
801  write_hline(buff, cx - x, cx + x, cy + y, mode);
802  write_hline(buff, cx - x, cx + x, cy - y, mode);
803  if (mode != 2 || (mode == 2 && xch && (cx - x) != (cx - y))) {
804  write_hline(buff, cx - y, cx + y, cy + x, mode);
805  write_hline(buff, cx - y, cx + y, cy - x, mode);
806  xch = 0;
807  }
808  }
809  error += (y * 2) + 1;
810  y++;
811  if (error >= 0) {
812  --x;
813  xch = 1;
814  error -= x * 2;
815  }
816  }
817  // Handle toggle mode.
818  if (mode == 2) {
819  write_hline(buff, cx - r, cx + r, cy, mode);
820  }
821 }
822 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
823 
834 #if defined(PIOS_VIDEO_SPLITBUFFER)
835 void write_line(uint8_t *buff, int x0, int y0, int x1, int y1, int mode)
836 {
837  // Based on http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
838  int steep = abs(y1 - y0) > abs(x1 - x0);
839 
840  if (steep) {
841  SWAP(x0, y0);
842  SWAP(x1, y1);
843  }
844  if (x0 > x1) {
845  SWAP(x0, x1);
846  SWAP(y0, y1);
847  }
848  int deltax = x1 - x0;
849  int deltay = abs(y1 - y0);
850  int error = deltax / 2;
851  int ystep;
852  int y = y0;
853  int x; // , lasty = y, stox = 0;
854  if (y0 < y1) {
855  ystep = 1;
856  } else {
857  ystep = -1;
858  }
859  for (x = x0; x < x1; x++) {
860  if (steep) {
861  write_pixel(buff, y, x, mode);
862  } else {
863  write_pixel(buff, x, y, mode);
864  }
865  error -= deltay;
866  if (error < 0) {
867  y += ystep;
868  error += deltax;
869  }
870  }
871 }
872 #else
873 void write_line(int x0, int y0, int x1, int y1, uint8_t value)
874 {
875  // Based on http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
876  int steep = abs(y1 - y0) > abs(x1 - x0);
877 
878  if (steep) {
879  SWAP(x0, y0);
880  SWAP(x1, y1);
881  }
882  if (x0 > x1) {
883  SWAP(x0, x1);
884  SWAP(y0, y1);
885  }
886  int deltax = x1 - x0;
887  int deltay = abs(y1 - y0);
888  int error = deltax / 2;
889  int ystep;
890  int y = y0;
891  int x; // , lasty = y, stox = 0;
892  if (y0 < y1) {
893  ystep = 1;
894  } else {
895  ystep = -1;
896  }
897  for (x = x0; x < x1; x++) {
898  if (steep) {
899  write_pixel(y, x, value);
900  } else {
901  write_pixel(x, y, value);
902  }
903  error -= deltay;
904  if (error < 0) {
905  y += ystep;
906  error += deltax;
907  }
908  }
909 }
910 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
911 
922 void write_line_lm(int x0, int y0, int x1, int y1, int mmode, int lmode)
923 {
924 #if defined(PIOS_VIDEO_SPLITBUFFER)
925  write_line(draw_buffer_mask, x0, y0, x1, y1, mmode);
926  write_line(draw_buffer_level, x0, y0, x1, y1, lmode);
927 #else
928  uint8_t value = PACK_BITS(mmode, lmode);
929  write_line(x0, y0, x1, y1, value);
930 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
931 }
932 
945 void write_line_outlined(int x0, int y0, int x1, int y1,
946  __attribute__((unused)) int endcap0, __attribute__((unused)) int endcap1,
947  int mode, int mmode)
948 {
949  // Based on http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
950  // This could be improved for speed.
951  int omode, imode;
952 
953  if (mode == 0) {
954  omode = 0;
955  imode = 1;
956  } else {
957  omode = 1;
958  imode = 0;
959  }
960  int steep = abs(y1 - y0) > abs(x1 - x0);
961  if (steep) {
962  SWAP(x0, y0);
963  SWAP(x1, y1);
964  }
965  if (x0 > x1) {
966  SWAP(x0, x1);
967  SWAP(y0, y1);
968  }
969  int deltax = x1 - x0;
970  int deltay = abs(y1 - y0);
971  int error = deltax / 2;
972  int ystep;
973  int y = y0;
974  int x;
975  if (y0 < y1) {
976  ystep = 1;
977  } else {
978  ystep = -1;
979  }
980  // Draw the outline.
981  for (x = x0; x < x1; x++) {
982  if (steep) {
983  write_pixel_lm(y - 1, x, mmode, omode);
984  write_pixel_lm(y + 1, x, mmode, omode);
985  write_pixel_lm(y, x - 1, mmode, omode);
986  write_pixel_lm(y, x + 1, mmode, omode);
987  } else {
988  write_pixel_lm(x - 1, y, mmode, omode);
989  write_pixel_lm(x + 1, y, mmode, omode);
990  write_pixel_lm(x, y - 1, mmode, omode);
991  write_pixel_lm(x, y + 1, mmode, omode);
992  }
993  error -= deltay;
994  if (error < 0) {
995  y += ystep;
996  error += deltax;
997  }
998  }
999  // Now draw the innards.
1000  error = deltax / 2;
1001  y = y0;
1002  for (x = x0; x < x1; x++) {
1003  if (steep) {
1004  write_pixel_lm(y, x, mmode, imode);
1005  } else {
1006  write_pixel_lm(x, y, mmode, imode);
1007  }
1008  error -= deltay;
1009  if (error < 0) {
1010  y += ystep;
1011  error += deltax;
1012  }
1013  }
1014 }
1015 
1029 void write_line_outlined_dashed(int x0, int y0, int x1, int y1,
1030  __attribute__((unused)) int endcap0, __attribute__((unused)) int endcap1,
1031  int mode, int mmode, int dots)
1032 {
1033  // Based on http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
1034  // This could be improved for speed.
1035  int omode, imode;
1036 
1037  if (mode == 0) {
1038  omode = 0;
1039  imode = 1;
1040  } else {
1041  omode = 1;
1042  imode = 0;
1043  }
1044  int steep = abs(y1 - y0) > abs(x1 - x0);
1045  if (steep) {
1046  SWAP(x0, y0);
1047  SWAP(x1, y1);
1048  }
1049  if (x0 > x1) {
1050  SWAP(x0, x1);
1051  SWAP(y0, y1);
1052  }
1053  int deltax = x1 - x0;
1054  int deltay = abs(y1 - y0);
1055  int error = deltax / 2;
1056  int ystep;
1057  int y = y0;
1058  int x;
1059  if (y0 < y1) {
1060  ystep = 1;
1061  } else {
1062  ystep = -1;
1063  }
1064  // Draw the outline.
1065  int dot_cnt = 0;
1066  int draw = 1;
1067  for (x = x0; x < x1; x++) {
1068  if (dots && !(dot_cnt++ % dots)) {
1069  draw++;
1070  }
1071  if (draw % 2) {
1072  if (steep) {
1073  write_pixel_lm(y - 1, x, mmode, omode);
1074  write_pixel_lm(y + 1, x, mmode, omode);
1075  write_pixel_lm(y, x - 1, mmode, omode);
1076  write_pixel_lm(y, x + 1, mmode, omode);
1077  } else {
1078  write_pixel_lm(x - 1, y, mmode, omode);
1079  write_pixel_lm(x + 1, y, mmode, omode);
1080  write_pixel_lm(x, y - 1, mmode, omode);
1081  write_pixel_lm(x, y + 1, mmode, omode);
1082  }
1083  }
1084  error -= deltay;
1085  if (error < 0) {
1086  y += ystep;
1087  error += deltax;
1088  }
1089  }
1090  // Now draw the innards.
1091  error = deltax / 2;
1092  y = y0;
1093  dot_cnt = 0;
1094  draw = 1;
1095  for (x = x0; x < x1; x++) {
1096  if (dots && !(dot_cnt++ % dots)) {
1097  draw++;
1098  }
1099  if (draw % 2) {
1100  if (steep) {
1101  write_pixel_lm(y, x, mmode, imode);
1102  } else {
1103  write_pixel_lm(x, y, mmode, imode);
1104  }
1105  }
1106  error -= deltay;
1107  if (error < 0) {
1108  y += ystep;
1109  error += deltax;
1110  }
1111  }
1112 }
1113 
1129 void write_word_misaligned_NAND(uint8_t *buff, uint16_t word, unsigned int addr, unsigned int xoff)
1130 {
1131  uint16_t firstmask = word >> xoff;
1132  uint16_t lastmask = word << (16 - xoff);
1133 
1134  WRITE_WORD_NAND(buff, addr + 1, firstmask & 0x00ff);
1135  WRITE_WORD_NAND(buff, addr, (firstmask & 0xff00) >> 8);
1136  if (xoff > 0) {
1137  WRITE_WORD_NAND(buff, addr + 2, (lastmask & 0xff00) >> 8);
1138  }
1139 }
1140 
1156 void write_word_misaligned_OR(uint8_t *buff, uint16_t word, unsigned int addr, unsigned int xoff)
1157 {
1158  uint16_t firstmask = word >> xoff;
1159  uint16_t lastmask = word << (16 - xoff);
1160 
1161  WRITE_WORD_OR(buff, addr + 1, firstmask & 0x00ff);
1162  WRITE_WORD_OR(buff, addr, (firstmask & 0xff00) >> 8);
1163  if (xoff > 0) {
1164  WRITE_WORD_OR(buff, addr + 2, (lastmask & 0xff00) >> 8);
1165  }
1166 }
1167 
1183 void write_word_misaligned_MASKED(uint8_t *buff, uint16_t word, uint16_t mask, unsigned int addr, unsigned int xoff)
1184 {
1185  uint16_t firstword = (word >> xoff);
1186  uint16_t lastword = word << (16 - xoff);
1187  uint16_t firstmask = (mask >> xoff);
1188  uint16_t lastmask = mask << (16 - xoff);
1189 
1190  WRITE_WORD(buff, addr + 1, firstmask & 0x00ff, firstword & 0x00ff);
1191  WRITE_WORD(buff, addr, (firstmask & 0xff00) >> 8, (firstword & 0xff00) >> 8);
1192  if (xoff > 0) {
1193  WRITE_WORD(buff, addr + 2, (lastmask & 0xff00) >> 8, (lastword & 0xff00) >> 8);
1194  }
1195 }
1196 
1197 
1206 void write_char(uint8_t ch, int x, int y, const struct FontEntry *font_info)
1207 {
1208  int yy, row;
1209 #if defined(PIOS_VIDEO_SPLITBUFFER)
1210  uint16_t levels;
1211 #else
1212  uint16_t data16;
1213 #endif
1214 
1215  uint16_t mask;
1216  ch = font_info->lookup[ch];
1217  if (ch == 255)
1218  return;
1219 
1220  // check if char is partly out of boundary
1221  uint8_t partly_out = (x < GRAPHICS_LEFT) || (x + font_info->width > GRAPHICS_RIGHT) || (y < GRAPHICS_TOP) || (y + font_info->height > GRAPHICS_BOTTOM);
1222  // check if char is totally out of boundary, if so return
1223  if (partly_out && ((x + font_info->width < GRAPHICS_LEFT) || (x > GRAPHICS_RIGHT) || (y + font_info->height < GRAPHICS_TOP) || (y > GRAPHICS_BOTTOM))) {
1224  return;
1225  }
1226 
1227  // Compute starting address of character
1228  int addr = CALC_BUFF_ADDR(x, y);
1229  int wbit = CALC_BIT_IN_WORD(x);
1230  row = ch * font_info->height;
1231 
1232  if (font_info->width > 8) {
1233  uint32_t data;
1234  for (yy = y; yy < y + font_info->height; yy++) {
1235  if (!partly_out || ((x >= GRAPHICS_LEFT) && (x + font_info->width <= GRAPHICS_RIGHT) && (yy >= GRAPHICS_TOP) && (yy <= GRAPHICS_BOTTOM))) {
1236  data = ((uint32_t*)font_info->data)[row];
1237 #if defined(PIOS_VIDEO_SPLITBUFFER)
1238  mask = data & 0xFFFF;
1239  levels = (data >> 16) & 0xFFFF;
1240  // mask
1241  write_word_misaligned_OR(draw_buffer_mask, mask, addr, wbit);
1242  // level
1243  write_word_misaligned_OR(draw_buffer_level, mask, addr, wbit);
1244  mask = (mask & levels);
1245  write_word_misaligned_NAND(draw_buffer_level, mask, addr, wbit);
1246 #else
1247  data16 = (data & 0xFFFF0000) >> 16;
1248  mask = data16 | (data16 << 1);
1249  write_word_misaligned_MASKED(draw_buffer, data16, mask, addr, wbit);
1250  data16 = (data & 0x0000FFFF);
1251  mask = data16 | (data16 << 1);
1252  write_word_misaligned_MASKED(draw_buffer, data16, mask, addr + 2, wbit);
1253 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
1254  }
1255  addr += BUFFER_WIDTH;
1256  row++;
1257  }
1258  }
1259  else {
1260  uint16_t data;
1261  for (yy = y; yy < y + font_info->height; yy++) {
1262  if (!partly_out || ((x >= GRAPHICS_LEFT) && (x + font_info->width <= GRAPHICS_RIGHT) && (yy >= GRAPHICS_TOP) && (yy <= GRAPHICS_BOTTOM))) {
1263  data = font_info->data[row];
1264 #if defined(PIOS_VIDEO_SPLITBUFFER)
1265  levels = data & 0xFF00;
1266  mask = (data & 0x00FF) << 8;
1267  // mask
1268  write_word_misaligned_OR(draw_buffer_mask, mask, addr, wbit);
1269  // level
1270  write_word_misaligned_OR(draw_buffer_level, mask, addr, wbit);
1271  mask = (mask & levels);
1272  write_word_misaligned_NAND(draw_buffer_level, mask, addr, wbit);
1273 #else
1274  mask = data | (data << 1);
1275  write_word_misaligned_MASKED(draw_buffer, data, mask, addr, wbit);
1276 #endif /* defined(PIOS_VIDEO_SPLITBUFFER) */
1277  }
1278  addr += BUFFER_WIDTH;
1279  row++;
1280  }
1281  }
1282 }
1283 
1284 
1290 const struct FontEntry * get_font_info(int font)
1291 {
1292  if (font >= NUM_FONTS)
1293  return NULL;
1294  return fonts[font];
1295 }
1296 
1308 void calc_text_dimensions(char *str, const struct FontEntry *font, int xs, int ys, struct FontDimensions *dim)
1309 {
1310  int max_length = 0, line_length = 0, lines = 1;
1311 
1312  while (*str != 0) {
1313  line_length++;
1314  if (*str == '\n' || *str == '\r') {
1315  if (line_length > max_length) {
1316  max_length = line_length;
1317  }
1318  line_length = 0;
1319  lines++;
1320  }
1321  str++;
1322  }
1323  if (line_length > max_length) {
1324  max_length = line_length;
1325  }
1326  dim->width = max_length * (font->width + xs);
1327  dim->height = lines * (font->height + ys);
1328 }
1329 
1344 void write_string(char *str, int x, int y, int xs, int ys, int va, int ha, int flags, int font)
1345 {
1346  int xx = 0, yy = 0, xx_original = 0;
1347  const struct FontEntry *font_info;
1348  struct FontDimensions dim;
1349 
1350  font_info = get_font_info(font);
1351 
1352  calc_text_dimensions(str, font_info, xs, ys, &dim);
1353  switch (va) {
1354  case TEXT_VA_TOP:
1355  yy = y;
1356  break;
1357  case TEXT_VA_MIDDLE:
1358  yy = y - (dim.height / 2) + 1;
1359  break;
1360  case TEXT_VA_BOTTOM:
1361  yy = y - dim.height;
1362  break;
1363  }
1364 
1365  switch (ha) {
1366  case TEXT_HA_LEFT:
1367  xx = x;
1368  break;
1369  case TEXT_HA_CENTER:
1370  xx = x - (dim.width / 2);
1371  break;
1372  case TEXT_HA_RIGHT:
1373  xx = x - dim.width;
1374  break;
1375  }
1376  // Then write each character.
1377  xx_original = xx;
1378  while (*str != 0) {
1379  if (*str == '\n' || *str == '\r') {
1380  yy += ys + font_info->height;
1381  xx = xx_original;
1382  } else {
1383  if (xx >= 0 && xx < GRAPHICS_WIDTH_REAL) {
1384  write_char(*str, xx, yy, font_info);
1385  }
1386  xx += font_info->width + xs;
1387  }
1388  str++;
1389  }
1390 }
1391 
1396 void draw_polygon(int16_t x, int16_t y, float angle, const point_t * points, uint8_t n_points, int mode, int mmode)
1397 {
1398  float sin_angle, cos_angle;
1399  int16_t x1, y1, x2, y2;
1400 
1401  sin_angle = sinf(angle * (float)(M_PI / 180));
1402  cos_angle = cosf(angle * (float)(M_PI / 180));
1403 
1404  x1 = roundf(cos_angle * points[0].x - sin_angle * points[0].y);
1405  y1 = roundf(sin_angle * points[0].x + cos_angle * points[0].y);
1406  x2 = 0; // so compiler doesn't give a warning
1407  y2 = 0;
1408 
1409  for (int i=0; i<n_points-1; i++)
1410  {
1411  x2 = roundf(cos_angle * points[i + 1].x - sin_angle * points[i + 1].y);
1412  y2 = roundf(sin_angle * points[i + 1].x + cos_angle * points[i + 1].y);
1413 
1414  write_line_outlined(x + x1, y + y1, x + x2, y + y2, 2, 2, mode, mmode);
1415  x1 = x2;
1416  y1 = y2;
1417  }
1418 
1419  x1 = roundf(cos_angle * points[0].x - sin_angle * points[0].y);
1420  y1 = roundf(sin_angle * points[0].x + cos_angle * points[0].y);
1421  write_line_outlined(x + x1, y + y1, x + x2, y + y2, 2, 2, mode, mmode);
1422 
1423  for (int i=0; i<n_points-1; i++)
1424  {
1425  x2 = roundf(cos_angle * points[i + 1].x - sin_angle * points[i + 1].y);
1426  y2 = roundf(sin_angle * points[i + 1].x + cos_angle * points[i + 1].y);
1427 
1428  write_line_lm(x + x1, y + y1, x + x2, y + y2, 1, 1);
1429  x1 = x2;
1430  y1 = y2;
1431  }
1432 
1433  x1 = roundf(cos_angle * points[0].x - sin_angle * points[0].y);
1434  y1 = roundf(sin_angle * points[0].x + cos_angle * points[0].y);
1435 
1436  write_line_lm( x + x1, y + y1, x + x2, y + y2, 1, 1);
1437 }
1438 
1447 void lla_to_ned(int32_t lattitude, int32_t longitude, float altitude, float *NED)
1448 {
1449  // TODO: Abstract out this code and also precompute the part based
1450  // on home location.
1451 
1452  HomeLocationData homeLocation;
1453  HomeLocationGet(&homeLocation);
1454 
1455  GPSPositionData gpsPosition;
1456  GPSPositionGet(&gpsPosition);
1457 
1458  float lat = lattitude / 10.0e6f * DEG2RAD;
1459 
1460  float T[3];
1461  T[0] = altitude + 6.378137E6f;
1462  T[1] = cosf(lat) * (altitude + 6.378137E6f);
1463  T[2] = -1.0f;
1464 
1465  float dL[3] = {(lattitude - homeLocation.Latitude) / 10.0e6f * DEG2RAD,
1466  (longitude - homeLocation.Longitude) / 10.0e6f * DEG2RAD,
1467  (altitude + gpsPosition.GeoidSeparation - homeLocation.Altitude)};
1468 
1469  NED[0] = T[0] * dL[0];
1470  NED[1] = T[1] * dL[1];
1471  NED[2] = T[2] * dL[2];
1472 }
1473 
OSD Utility Functions.
Definition: fonts.h:43
#define GRAPHICS_LEFT
Definition: pios_video.h:128
#define GRAPHICS_WIDTH_REAL
Definition: pios_video.h:140
void write_string(char *str, int x, int y, int xs, int ys, int va, int ha, int flags, int font)
Definition: osd_utils.c:1344
void write_circle_outlined(int cx, int cy, int r, int dashp, int bmode, int mode, int mmode)
void draw_polygon(int16_t x, int16_t y, float angle, const point_t *points, uint8_t n_points, int mode, int mmode)
Definition: osd_utils.c:1396
void write_vline_lm(int x, int y0, int y1, int lmode, int mmode)
Definition: osd_utils.c:483
#define DRAW_ENDCAP_VLINE(e, x, y, s, f, l)
Definition: osd_utils.h:109
void write_vline_outlined(int x, int y0, int y1, int endcap0, int endcap1, int mode, int mmode)
Definition: osd_utils.c:508
const uint8_t * lookup
Definition: fonts.h:46
#define COMPUTE_HLINE_ISLAND_MASK(b0, b1)
Definition: osd_utils.h:89
#define CALC_BIT0_IN_WORD(x)
Definition: osd_utils.h:63
#define TEXT_HA_LEFT
Definition: osd_utils.h:133
#define CLIP_COORD_Y(y)
Definition: osd_utils.h:150
#define CHECK_COORD_Y(y)
Definition: osd_utils.h:145
#define TEXT_VA_BOTTOM
Definition: osd_utils.h:132
void write_char(uint8_t ch, int x, int y, const struct FontEntry *font_info)
Definition: osd_utils.c:1206
#define ENDCAP_ROUND
Definition: osd_utils.h:100
void draw_image(uint16_t x, uint16_t y, const struct Image *image)
Definition: osd_utils.c:70
#define CLIP_COORD_X(x)
Definition: osd_utils.h:149
Definition: images.h:1074
OSD gen module, handles OSD draw. Parts from CL-OSD and SUPEROSD projects.
uint8_t * data
Definition: images.h:1077
#define CIRCLE_PLOT_8(buff, cx, cy, x, y, mode)
Definition: osd_utils.h:116
uint8_t width
Definition: fonts.h:44
void write_line(int x0, int y0, int x1, int y1, uint8_t value)
Definition: osd_utils.c:873
void write_rectangle_outlined(int x, int y, int width, int height, int mode, int mmode)
Definition: osd_utils.c:681
void write_line_outlined_dashed(int x0, int y0, int x1, int y1, __attribute__((unused)) int endcap0, __attribute__((unused)) int endcap1, int mode, int mmode, int dots)
Definition: osd_utils.c:1029
void write_word_misaligned_OR(uint8_t *buff, uint16_t word, unsigned int addr, unsigned int xoff)
Definition: osd_utils.c:1156
#define COMPUTE_HLINE_EDGE_R_MASK(b)
Definition: osd_utils.h:68
uint32_t lat
Definition: msp_messages.h:97
#define CALC_BUFF_ADDR(x, y)
Definition: osd_utils.h:72
void write_line_outlined(int x0, int y0, int x1, int y1, __attribute__((unused)) int endcap0, __attribute__((unused)) int endcap1, int mode, int mmode)
Definition: osd_utils.c:945
#define GRAPHICS_TOP
Definition: pios_video.h:129
uint16_t flags
Definition: uavtalk_priv.h:52
#define TEXT_HA_RIGHT
Definition: osd_utils.h:135
void write_filled_rectangle(int x, int y, int width, int height, uint8_t value)
Definition: osd_utils.c:594
#define SWAP(a, b)
Definition: osd_utils.h:153
#define BUFFER_HEIGHT
Definition: pios_video.h:148
static float T[3]
Scales used in NED transform (local tangent plane approx).
Definition: attitude.c:210
uint16_t altitude
Definition: msp_messages.h:100
uint8_t data[XFER_BYTES_PER_PACKET]
Definition: bl_messages.h:129
void calc_text_dimensions(char *str, const struct FontEntry *font, int xs, int ys, struct FontDimensions *dim)
Definition: osd_utils.c:1308
int32_t longitude
#define TEXT_HA_CENTER
Definition: osd_utils.h:134
uint8_t * draw_buffer_level
#define WRITE_WORD_NAND(buff, addr, mask)
Definition: osd_utils.h:82
void write_line_lm(int x0, int y0, int x1, int y1, int mmode, int lmode)
Definition: osd_utils.c:922
#define CALC_BIT_MASK(x)
Definition: osd_utils.h:61
#define NUM_FONTS
Definition: fonts.h:50
#define WRITE_WORD_MODE(buff, addr, mask, mode)
Definition: osd_utils.h:76
#define WRITE_WORD_OR(buff, addr, mask)
Definition: osd_utils.h:83
void write_word_misaligned_MASKED(uint8_t *buff, uint16_t word, uint16_t mask, unsigned int addr, unsigned int xoff)
Definition: osd_utils.c:1183
const uint16_t * data
Definition: fonts.h:47
uint8_t * disp_buffer
#define GRAPHICS_RIGHT
Definition: pios_video.h:130
void plotFourQuadrants(int32_t centerX, int32_t centerY, int32_t deltaX, int32_t deltaY)
Definition: osd_utils.c:136
uint8_t i
Definition: msp_messages.h:97
static HomeLocationData homeLocation
Definition: attitude.c:147
enum channel_mode mode
Definition: pios_servo.c:58
#define PACK_BITS(mask, level)
Definition: osd_utils.h:62
uint8_t height
Definition: fonts.h:45
#define TEXT_VA_TOP
Definition: osd_utils.h:130
uint8_t * draw_buffer_mask
void write_hline_outlined(int x0, int x1, int y, int endcap0, int endcap1, int mode, int mmode)
Definition: osd_utils.c:397
uint8_t * draw_buffer
uint16_t value
Definition: storm32bgc.c:155
uint16_t height
Definition: images.h:1076
void write_word_misaligned_NAND(uint8_t *buff, uint16_t word, unsigned int addr, unsigned int xoff)
Definition: osd_utils.c:1129
void clearGraphics()
Definition: osd_utils.c:60
void write_vline(int x, int y0, int y1, uint8_t value)
Definition: osd_utils.c:448
tuple f
Definition: px_mkfw.py:81
#define WRITE_WORD(buff, addr, mask, value)
Definition: osd_utils.h:85
#define CALC_BIT1_IN_WORD(x)
Definition: osd_utils.h:64
void drawBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
Definition: osd_utils.c:214
const struct FontEntry * get_font_info(int font)
Definition: osd_utils.c:1290
Includes PiOS and core architecture components.
uint8_t unused[4]
Definition: bl_messages.h:70
#define DRAW_ENDCAP_HLINE(e, x, y, s, f, l)
Definition: osd_utils.h:103
void ellipse(int centerX, int centerY, int horizontalRadius, int verticalRadius)
Definition: osd_utils.c:152
#define BUFFER_WIDTH
Definition: pios_video.h:147
void drawArrow(uint16_t x, uint16_t y, uint16_t angle, uint16_t size_quarter)
Definition: osd_utils.c:199
void write_hline_lm(int x0, int x1, int y, int lmode, int mmode)
Definition: osd_utils.c:372
#define TEXT_VA_MIDDLE
Definition: osd_utils.h:131
#define COMPUTE_HLINE_EDGE_L_MASK(b)
Definition: osd_utils.h:67
#define SETUP_STROKE_FILL(stroke, fill, mode)
Definition: osd_utils.h:93
void write_filled_rectangle_lm(int x, int y, int width, int height, int lmode, int mmode)
Definition: osd_utils.c:659
void error(int)
Definition: main.c:130
void lla_to_ned(int32_t lat, int32_t lon, float alt, float *NED)
Definition: osd_utils.c:1447
uint16_t width
Definition: images.h:1075
void write_pixel(int x, int y, uint8_t value)
Definition: osd_utils.c:241
struct FontEntry * fonts[NUM_FONTS]
Definition: fonts.c:1660
void write_hline(int x0, int x1, int y, uint8_t value)
Definition: osd_utils.c:324
#define CHECK_COORD_X(x)
Definition: osd_utils.h:144
void write_pixel_lm(int x, int y, int mmode, int lmode)
Definition: osd_utils.c:261
#define CHECK_COORDS(x, y)
Definition: osd_utils.h:143
#define GRAPHICS_BOTTOM
Definition: pios_video.h:131
#define CALC_BIT_IN_WORD(x)
Definition: osd_utils.h:59
typedef __attribute__
Definition: serial_4way.h:43