libyggdrasil  v1.0.0
display.hpp
Go to the documentation of this file.
1  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * _____.___. .___ .__.__ *
3  * \__ | | ____ ____ __| _/___________ _____|__| | *
4  * / | |/ ___\ / ___\ / __ |\_ __ \__ \ / ___/ | | *
5  * \____ / /_/ > /_/ > /_/ | | | \// __ \_\___ \| | |__ *
6  * / ______\___ /\___ /\____ | |__| (____ /____ >__|____/ *
7  * \/ /_____//_____/ \/ \/ \/ *
8  * - Common - *
9  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10  * This software can be used by students and other personal of the *
11  * Bern University of Applied Sciences under the terms of the MIT *
12  * license. *
13  * For other persons this software is under the terms of the GNU *
14  * General Public License version 2. *
15  * *
16  * Copyright © 2021, Bern University of Applied Sciences. *
17  * All rights reserved. *
18  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
26 #pragma once
27 
28 #include <cpp/common/registers.hpp>
30 #include <cpp/common/math.hpp>
31 
32 #include <c/resources/fonts/fonts.h>
33 
34 namespace bsp::drv {
35 
36  using Palette = std::array<u32, 256>;
37 
44  template<auto Context, template<auto> typename DisplayImpl>
45  struct Display {
46  Display() = delete;
47  Display(const Display&) = delete;
48  Display(Display &&) = delete;
49 
50  using Impl = DisplayImpl<Context>;
51 
52  /*
53  * @brief Display initialization
54  *
55  * @param orientation Display orientation
56  * @return Success
57  */
58  static auto init(auto ... args) {
59  return Impl::init(args...);
60  }
61 
67  static auto deinit(auto ... args) {
68  return Impl::deinit(args...);
69  }
70 
71  /*
72  * @brief Display reset
73  */
74  static void reset() {
75  Impl::reset();
76  }
77 
78  /*
79  * @brief Get the display width
80  *
81  * @return display width
82  */
83  static auto getWidth() {
84  return Impl::getWidth();
85  }
86 
87  /*
88  * @brief Get the display height
89  *
90  * @return display height
91  */
92  static auto getHeight() {
93  return Impl::getHeight();
94  }
95 
96  /*
97  * @brief Get the default color palette
98  *
99  * @return Default color palette
100  */
102  return Impl::getDefaultPalette();
103  }
104 
105  /*
106  * @brief Get the framebuffer address
107  *
108  * @return framebuffer address
109  */
110  static void* getFramebufferAddress() {
111  return Impl::getFramebufferAddress();
112  }
113 
114  /*
115  * @brief Set the color palette
116  *
117  * @param palettet Color palette
118  */
119  static void setPalette(const Palette &palette) {
120  Impl::setPalette(palette);
121  }
122 
123  /*
124  * @brief Enable the display
125  */
126  static void turnOn() {
127  Impl::turnOn();
128  }
129 
130  /*
131  * @brief Disable the display
132  */
133  static void turnOff() {
134  Impl::turnOff();
135  }
136 
142  static void clear(auto colorIndex) {
143  Impl::clear(static_cast<u8>(colorIndex));
144  }
145 
155  static void drawRectangle(u16 x1, u16 y1, u16 x2, u16 y2, auto colorIndex) {
156  x1 = math::clamp<u16>(x1, 0, Display::getWidth() - 1);
157  y1 = math::clamp<u16>(y1, 0, Display::getHeight() - 1);
158  x2 = math::clamp<u16>(x2, 0, Display::getWidth() - 1);
159  y2 = math::clamp<u16>(y2, 0, Display::getHeight() - 1);
160 
161  for (u16 x = x1; x < x2; x++)
162  Display::drawPixel(x, y1, colorIndex);
163  for (u16 x = x1; x < x2; x++)
164  Display::drawPixel(x, y2, colorIndex);
165  for (u16 y = y1; y < y2; y++)
166  Display::drawPixel(x1, y, colorIndex);
167  for (u16 y = y1; y < y2; y++)
168  Display::drawPixel(x2, y, colorIndex);
169  }
170 
180  static void fillRectangle(u16 x1, u16 y1, u16 x2, u16 y2, auto colorIndex) {
181  x1 = math::clamp<u16>(x1, 0, Display::getWidth() - 1);
182  y1 = math::clamp<u16>(y1, 0, Display::getHeight() - 1);
183  x2 = math::clamp<u16>(x2, 0, Display::getWidth() - 1);
184  y2 = math::clamp<u16>(y2, 0, Display::getHeight() - 1);
185 
186  for (u16 x = x1; x < x2; x++)
187  for (u16 y = y1; y < y2; y++)
188  Display::drawPixel(x, y, colorIndex);
189  }
190 
191 
199  static void drawPixel(u16 x, u16 y, auto colorIndex) {
200  u8 colorValue = static_cast<u8>(colorIndex);
201  Impl::setPixel(x, y, colorValue);
202  }
203 
213  static void drawLine(u16 x1, u16 y1, u16 x2, u16 y2, auto colorIndex) {
214  x1 = math::clamp<u16>(x1, 0, Display::getWidth() - 1);
215  y1 = math::clamp<u16>(y1, 0, Display::getHeight() - 1);
216  x2 = math::clamp<u16>(x2, 0, Display::getWidth() - 1);
217  y2 = math::clamp<u16>(y2, 0, Display::getHeight() - 1);
218 
219  i16 deltaX = std::abs(x2 - x1);
220  i16 deltaY = -std::abs(y2 - y1);
221  i16 speedX = x1 < x2 ? 1 : -1;
222  i16 speedY = y1 < y2 ? 1 : -1;
223 
224  i16 error = deltaX + deltaY;
225 
226  /* Bresenham */
227  while (!(x1 == x2 && y1 == y2)) {
228  Display::drawPixel(x1, y1, colorIndex);
229 
230  if ((error * 2) > deltaY) {
231  error += deltaY;
232  x1 += speedX;
233  }
234  if ((error * 2) < deltaX) {
235  error += deltaX;
236  y1 += speedY;
237  }
238  }
239  }
240 
249  static void drawCircle(i16 centerX, i16 centerY, u16 radius, auto colorIndex) {
250  auto setPixels = [](i16 centerX, i16 centerY, i16 x, i16 y, u8 colorIndex) {
251  Display::drawPixel(centerX+x, centerY+y, colorIndex);
252  Display::drawPixel(centerX-x, centerY+y, colorIndex);
253  Display::drawPixel(centerX+x, centerY-y, colorIndex);
254  Display::drawPixel(centerX-x, centerY-y, colorIndex);
255  Display::drawPixel(centerX+y, centerY+x, colorIndex);
256  Display::drawPixel(centerX-y, centerY+x, colorIndex);
257  Display::drawPixel(centerX+y, centerY-x, colorIndex);
258  Display::drawPixel(centerX-y, centerY-x, colorIndex);
259  };
260 
261  i16 x = 0, y = radius;
262  i16 d = 3 - 2 * radius;
263  setPixels(centerX, centerY, x, y, colorIndex);
264 
265  /* Bresenham */
266  while (y >= x) {
267  x++;
268 
269  if (d > 0) {
270  y--;
271  d = d + 4 * (x - y) + 10;
272  } else {
273  d = d + 4 * x + 6;
274  }
275 
276  setPixels(centerX, centerY, x, y, colorIndex);
277  }
278  }
279 
288  static void fillCircle(i16 centerX, i16 centerY, u16 radius, auto colorIndex) {
289  i16 x = radius;
290  i16 y = 0;
291  i16 radiusError = 0;
292  i16 xChange = 1 - (radius << 1);
293  i16 yChange = 0;
294 
295  /* Bresenham */
296  while (x >= y) {
297  for (i16 i = centerX - x; i <= centerX + x; i++) {
298  i16 y1 = centerY + y;
299  i16 y2 = centerY - y;
300  i16 x1 = i;
301 
302  y1 = math::clamp<u16>(y1, 0, Display::getHeight() - 1);
303  y2 = math::clamp<u16>(y2, 0, Display::getHeight() - 1);
304  x1 = math::clamp<u16>(x1, 0, Display::getWidth() -1 );
305 
306  Display::drawPixel(x1, y1, colorIndex);
307  Display::drawPixel(x1, y2, colorIndex);
308 
309  }
310 
311  for (i16 i = centerX - y; i <= centerX + y; i++) {
312  i16 y1 = centerY + x;
313  i16 y2 = centerY - x;
314  i16 x1 = i;
315 
316  y1 = math::clamp<u16>(y1, 0, Display::getHeight() - 1);
317  y2 = math::clamp<u16>(y2, 0, Display::getHeight() - 1);
318  x1 = math::clamp<u16>(x1, 0, Display::getWidth() -1 );
319 
320  Display::drawPixel(x1, y1, colorIndex);
321  Display::drawPixel(x1, y2, colorIndex);
322  }
323 
324  y++;
325  radiusError += yChange;
326  yChange += 2;
327  if (((radiusError << 1) + xChange) > 0) {
328  x--;
329  radiusError += xChange;
330  xChange += 2;
331  }
332  }
333  }
334 
344  static void drawCharacter(u16 x, u16 y, char c, auto colorIndex, Font &font) {
345  x = math::clamp<u16>(x, 0, Display::getWidth() - 1);
346  y = math::clamp<u16>(y, 0, Display::getHeight() - 1);
347 
348  u16 width = font.Width;
349  u16 height = font.Height;
350 
351  const u8 *dataStart = &font.table[(c - ' ') * height * ((width + 7) / 8)];
352 
353  u8 offset = 8 * ((width + 7) / 8) - width;
354 
355  u32 line = 0;
356 
357  /* Bresenham */
358  for (u32 i = 0; i < height; i++) {
359  const u8 *data = (dataStart + (width + 7) / 8 * i);
360 
361  switch ((width + 7) / 8) {
362  case 1:
363  line = data[0];
364  break;
365  case 2:
366  line = data[0] << 8 | data[1];
367  break;
368  case 3:
369  default:
370  line = data[0] << 16 | data[1] << 8 | data[0];
371  break;
372  }
373 
374  for (u16 bit = 0; bit < width; bit++) {
375  if (line & (1 << (width - bit + offset - 1)))
376  Display::drawPixel(x + bit, y, colorIndex);
377  }
378 
379  y++;
380  }
381  }
382 
392  static void drawString(u16 x, u16 y, std::string_view string, auto colorIndex, Font& font) {
393  for (char c : string) {
394  Display::drawCharacter(x, y, c, colorIndex, font);
395  x += font.Width;
396  }
397  }
398  };
399 
400 }
bsp::drv::Display::clear
static void clear(auto colorIndex)
Clear the display to a color.
Definition: display.hpp:142
bsp::drv::Display::drawPixel
static void drawPixel(u16 x, u16 y, auto colorIndex)
Draw a single pixel.
Definition: display.hpp:199
bsp::drv::Display::getHeight
static auto getHeight()
Definition: display.hpp:92
bsp::drv::Display::Display
Display(const Display &)=delete
u16
uint16_t u16
Definition: types.h:37
bsp::drv::Display::fillRectangle
static void fillRectangle(u16 x1, u16 y1, u16 x2, u16 y2, auto colorIndex)
Draw a filled rectangle.
Definition: display.hpp:180
u8
uint8_t u8
Unsigned integer definitions.
Definition: types.h:36
bsp::drv::Display::init
static auto init(auto ... args)
Definition: display.hpp:58
i16
int16_t i16
Definition: types.h:47
bsp::drv::Display::fillCircle
static void fillCircle(i16 centerX, i16 centerY, u16 radius, auto colorIndex)
Draw a filled cricle.
Definition: display.hpp:288
bsp::drv::Display::reset
static void reset()
Definition: display.hpp:74
bsp::drv::Display::drawLine
static void drawLine(u16 x1, u16 y1, u16 x2, u16 y2, auto colorIndex)
Draw a line.
Definition: display.hpp:213
u32
uint32_t u32
Definition: types.h:38
bsp::drv::Display::Impl
DisplayImpl< Context > Impl
Definition: display.hpp:50
bsp::drv::Palette
std::array< u32, 256 > Palette
Definition: display.hpp:36
bsp::drv::Display::drawRectangle
static void drawRectangle(u16 x1, u16 y1, u16 x2, u16 y2, auto colorIndex)
Draw a rectangle.
Definition: display.hpp:155
bsp::drv::Display::drawCircle
static void drawCircle(i16 centerX, i16 centerY, u16 radius, auto colorIndex)
Draw a cricle.
Definition: display.hpp:249
bsp::drv::Display::Display
Display(Display &&)=delete
bsp::drv::Display::getDefaultPalette
static Palette getDefaultPalette()
Definition: display.hpp:101
bsp::drv::Display
Base class for Display abstraction.
Definition: display.hpp:45
bsp::drv::Display::turnOn
static void turnOn()
Definition: display.hpp:126
registers.hpp
Zero-cost abstraction for accessing registers and bits/bitfields within them.
bsp::drv::Display::Display
Display()=delete
bsp::drv::Display::getFramebufferAddress
static void * getFramebufferAddress()
Definition: display.hpp:110
bsp::drv::Display::drawString
static void drawString(u16 x, u16 y, std::string_view string, auto colorIndex, Font &font)
Draw a string.
Definition: display.hpp:392
attributes.hpp
Commonly used C++ and GNU attributes.
bsp::drv::Display::setPalette
static void setPalette(const Palette &palette)
Definition: display.hpp:119
bsp::drv::Display::deinit
static auto deinit(auto ... args)
Deinit function.
Definition: display.hpp:67
bsp::drv
Definition: display.hpp:37
bsp::drv::Display::drawCharacter
static void drawCharacter(u16 x, u16 y, char c, auto colorIndex, Font &font)
Draw a single character.
Definition: display.hpp:344
bsp::drv::Display::getWidth
static auto getWidth()
Definition: display.hpp:83
bsp::drv::Display::turnOff
static void turnOff()
Definition: display.hpp:133
math.hpp
Commonly used math functions.