OpenWareLaboratory
ScreenBuffer.h
Go to the documentation of this file.
1 #ifndef __ScreenBuffer_h__
2 #define __ScreenBuffer_h__
3 
4 #include <stdint.h>
5 #include <string.h>
6 #include "device.h"
7 #include "message.h"
8 
9 
10 template<typename Colour, Colour BLACK, Colour WHITE>
11 class ScreenBuffer {
12 private:
13  const uint16_t width;
14  const uint16_t height;
15  Colour* pixels;
16  uint16_t cursor_x;
17  uint16_t cursor_y;
18  uint8_t textsize;
19  uint16_t textcolor;
20  uint16_t textbgcolor;
21  bool wrap;
22 
23  inline void swap(int& a, int& b) { int t = a; a = b; b = t; };
24 
25 public:
26 ScreenBuffer(uint16_t w, uint16_t h) :
27  width(w), height(h), pixels(NULL),
28  cursor_x(0), cursor_y(0), textsize(1),
29  textcolor(WHITE), textbgcolor(WHITE), wrap(true) {}
30  inline int getWidth(){
31  return width;
32  }
33  inline int getHeight(){
34  return height;
35  }
36  void setBuffer(uint8_t* buffer){
37  pixels = (Colour*)buffer;
38  }
40  return pixels;
41  }
42  Colour getPixel(unsigned int x, unsigned int y);
43  void setPixel(unsigned int x, unsigned int y, Colour c);
44  void invertPixel(unsigned int x, unsigned int y);
45  void fill(Colour c);
46  void fade(uint16_t steps);
47  void clear(){
48  cursor_x = cursor_y = 0;
49  fill(BLACK);
50  }
51  void clear(int x, int y, int width, int height){
52  fillRectangle(x, y, width, height, BLACK);
53  }
54 
55  // text
56  void print(const char* str) {
57  unsigned int len = strnlen(str, 256);
58  for(unsigned int i=0; i<len; ++i)
59  write(str[i]);
60  }
61 
62  void print(float num) {
63  print(msg_ftoa(num, 10));
64  }
65 
66  void print(int num) {
67  print(msg_itoa(num, 10));
68  }
69 
70  void print(int x, int y, const char* text){
71  setCursor(x, y);
72  print(text);
73  }
74 
75  void drawVerticalLine(int x, int y,
76  int length, Colour c){
77  // drawLine(x, y, x, y+length-1, c);
78  length += y;
79  while(y < length)
80  setPixel(x, y++, c);
81  }
82 
83  void drawHorizontalLine(int x, int y,
84  int length, Colour c){
85  // drawLine(x, y, x+length-1, y, c);
86  length += x;
87  while(x < length)
88  setPixel(x++, y, c);
89  }
90 
91  void fillRectangle(int x, int y, int w, int h,
92  Colour c) {
93  // for(int i=x; i<x+w; i++)
94  // drawVerticalLine(i, y, h, c);
95  for(int i=y; i<y+h; i++)
96  drawHorizontalLine(x, i, w, c);
97  }
98 
99  void drawRectangle(int x, int y, int w, int h,
100  Colour c) {
101  drawHorizontalLine(x+1, y, w-2, c);
102  drawHorizontalLine(x+1, y+h-1, w-2, c);
103  drawVerticalLine(x, y, h, c);
104  drawVerticalLine(x+w-1, y, h, c);
105  }
106 
107 
108  // Bresenham's algorithm - thx wikpedia
109  void drawLine(int x0, int y0,
110  int x1, int y1,
111  Colour c) {
112  int steep = abs(y1 - y0) > abs(x1 - x0);
113  if (steep) {
114  swap(x0, y0);
115  swap(x1, y1);
116  }
117  if (x0 > x1) {
118  swap(x0, x1);
119  swap(y0, y1);
120  }
121  int dx, dy;
122  dx = x1 - x0;
123  dy = abs(y1 - y0);
124  int err = dx / 2;
125  int ystep;
126  if (y0 < y1)
127  ystep = 1;
128  else
129  ystep = -1;
130  for (; x0<=x1; x0++) {
131  if (steep)
132  setPixel(y0, x0, c);
133  else
134  setPixel(x0, y0, c);
135  err -= dy;
136  if (err < 0) {
137  y0 += ystep;
138  err += dx;
139  }
140  }
141  }
142 
143  void setCursor(uint16_t x, uint16_t y) {
144  cursor_x = x;
145  cursor_y = y;
146  }
147 
148  void setTextSize(uint8_t s) {
149  textsize = (s > 0) ? s : 1;
150  }
151 
153  // For 'transparent' background, we'll set the bg
154  // to the same as fg instead of using a flag
155  textcolor = textbgcolor = c;
156  }
157 
159  textcolor = c;
160  textbgcolor = b;
161  }
162 
163  void setTextWrap(bool w) {
164  wrap = w;
165  }
166 
167  void invert(){
168  invert(0, 0, width, height);
169  }
170 
171  void invert(int x, int y, int w, int h){
172  for(int i=x; i<x+w; ++i)
173  for(int j=y; j<y+h; ++j)
174  invertPixel(i, j);
175  }
176 
177  void write(uint8_t c) {
178  if (c == '\n') {
179  cursor_y += textsize*8;
180  cursor_x = 0;
181  } else if (c == '\r') {
182  // skip em
183  } else {
184  drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
185  cursor_x += textsize*6;
186  if(wrap && (cursor_x > (width - textsize*6))){
187  cursor_y += textsize*8;
188  cursor_x = 0;
189  }
190  }
191  }
192 
193  void drawCircle(uint16_t x, uint16_t y, uint16_t r, Colour c){
194  /*
195  * Bresenhams midpoint circle algorithm AKA "Make turbo C great again!"
196  * We don't use floating point or any slow maths to find circle points.
197  * But since we draw it around center, circles with even radius become
198  * slightly asymmetric.
199  */
200  int16_t tx = r;
201  int16_t ty = 0;
202  int16_t err = 0;
203  while (tx >= ty) {
204  setPixel(x + tx, y + ty, c); // p1
205  setPixel(x + ty, y + tx, c); // p2
206  setPixel(x - ty, y + tx, c); // p3
207  setPixel(x - tx, y + ty, c); // p4
208  setPixel(x - tx, y - ty, c); // p5
209  setPixel(x - ty, y - tx, c); // p6
210  setPixel(x + ty, y - tx, c); // p7
211  setPixel(x + tx, y - ty, c); // p8
212  if (err <= 0){
213  ty += 1;
214  err += 2 * ty + 1;
215  }
216  if (err >= 0){
217  tx -= 1;
218  err -= 2 * tx + 1;
219  }
220  }
221  }
222 
223  void fillCircle(uint16_t x, uint16_t y, uint16_t r, Colour c){
224  /*
225  * This is based on code from drawCircle, but we connect circle's points
226  * with horizontal lines
227  */
228  int16_t tx = r;
229  int16_t ty = 0;
230  int16_t err = 0;
231  while (tx >= ty) {
232  drawHorizontalLine(x - tx, y + ty, tx * 2 + 1, c); // p4 -> p1
233  drawHorizontalLine(x - ty, y + tx, ty * 2 + 1, c); // p3 -> p2
234  drawHorizontalLine(x - tx, y - ty, tx * 2 + 1, c); // p5 -> p8
235  drawHorizontalLine(x - ty, y - tx, ty * 2 + 1, c); // p6 -> p7
236  if (err <= 0){
237  ty += 1;
238  err += 2 * ty + 1;
239  }
240  if (err >= 0){
241  tx -= 1;
242  err -= 2 * tx + 1;
243  }
244  }
245  }
246 
247  // Draw a character
248  void drawChar(uint16_t x, uint16_t y, unsigned char ch,
249  Colour c, Colour bg, uint8_t size) {
250  extern const unsigned char font[];
251 
252  // if((x >= width) || // Clip right
253  // (y >= height) || // Clip bottom
254  // ((x + 6 * size - 1) < 0) || // Clip left
255  // ((y + 8 * size - 1) < 0)) // Clip top
256  // return;
257  y -= 8 * size; // set origin to bottom left
258  for(int8_t i=0; i<6; i++ ) {
259  uint8_t line;
260  if (i == 5)
261  line = 0x0;
262  else
263  line = font[(ch*5)+i];
264  for (int8_t j = 0; j<8; j++) {
265  if (line & 0x1) {
266  if (size == 1) // default size
267  setPixel(x+i, y+j, c);
268  else { // big size
269  fillRectangle(x+(i*size), y+(j*size), size, size, c);
270  }
271  } else if (bg != c) {
272  if (size == 1) // default size
273  setPixel(x+i, y+j, bg);
274  else { // big size
275  fillRectangle(x+i*size, y+j*size, size, size, bg);
276  }
277  }
278  line >>= 1;
279  }
280  }
281  }
282 
283  // Draw a character rotated 90 degrees
284  void drawRotatedChar(uint16_t x, uint16_t y, unsigned char ch,
285  Colour c, Colour bg, uint8_t size) {
286  extern const unsigned char font[];
287  // if((x >= width) || // Clip right
288  // (y >= height) || // Clip bottom
289  // ((x + 8 * size - 1) < 0) || // Clip left
290  // ((y + 6 * size - 1) < 0)) // Clip top
291  // return;
292  // for (int8_t i=5; i>=0; i-- ) {
293  for (int8_t i=0; i<6; i++ ) {
294  uint8_t line;
295  if (i == 5)
296  line = 0x0;
297  else
298  line = font[(ch*5)+i];
299  // for (int8_t j = 0; j<8; j++) {
300  for (int8_t j = 7; j>=0; j--) {
301  if (line & 0x1) {
302  if (size == 1) // default size
303  setPixel(y+i, x+j, c);
304  else { // big size
305  // fillRectangle(x+(i*size), y+(j*size), size, size, c);
306  fillRectangle(y+(j*size), x+(i*size), size, size, c);
307  }
308  } else if (bg != c) {
309  if (size == 1) // default size
310  setPixel(y+i, x+j, bg);
311  else { // big size
312  // fillRectangle(x+i*size, y+j*size, size, size, bg);
313  fillRectangle(y+j*size, x+i*size, size, size, bg);
314  }
315  }
316  line >>= 1;
317  }
318  }
319  }
320 };
321 
322 #endif // __ScreenBuffer_h__
uint16_t Colour
#define BLACK
#define WHITE
#define abs(x)
Definition: basicmaths.h:44
void print(const char *str)
Definition: ScreenBuffer.h:56
int getHeight()
Definition: ScreenBuffer.h:33
void setPixel(unsigned int x, unsigned int y, Colour c)
Colour getPixel(unsigned int x, unsigned int y)
void invertPixel(unsigned int x, unsigned int y)
void setTextColour(Colour c)
Definition: ScreenBuffer.h:152
void fade(uint16_t steps)
void fillRectangle(int x, int y, int w, int h, Colour c)
Definition: ScreenBuffer.h:91
void clear()
Definition: ScreenBuffer.h:47
void invert(int x, int y, int w, int h)
Definition: ScreenBuffer.h:171
void drawLine(int x0, int y0, int x1, int y1, Colour c)
Definition: ScreenBuffer.h:109
void setTextSize(uint8_t s)
Definition: ScreenBuffer.h:148
void print(int x, int y, const char *text)
Definition: ScreenBuffer.h:70
void drawChar(uint16_t x, uint16_t y, unsigned char ch, Colour c, Colour bg, uint8_t size)
Definition: ScreenBuffer.h:248
void setTextWrap(bool w)
Definition: ScreenBuffer.h:163
void write(uint8_t c)
Definition: ScreenBuffer.h:177
void fillCircle(uint16_t x, uint16_t y, uint16_t r, Colour c)
Definition: ScreenBuffer.h:223
void setTextColour(Colour c, Colour b)
Definition: ScreenBuffer.h:158
void drawHorizontalLine(int x, int y, int length, Colour c)
Definition: ScreenBuffer.h:83
void print(int num)
Definition: ScreenBuffer.h:66
void setCursor(uint16_t x, uint16_t y)
Definition: ScreenBuffer.h:143
void drawRectangle(int x, int y, int w, int h, Colour c)
Definition: ScreenBuffer.h:99
void fill(Colour c)
ScreenBuffer(uint16_t w, uint16_t h)
Definition: ScreenBuffer.h:26
Colour * getBuffer()
Definition: ScreenBuffer.h:39
void print(float num)
Definition: ScreenBuffer.h:62
void drawVerticalLine(int x, int y, int length, Colour c)
Definition: ScreenBuffer.h:75
void setBuffer(uint8_t *buffer)
Definition: ScreenBuffer.h:36
void drawCircle(uint16_t x, uint16_t y, uint16_t r, Colour c)
Definition: ScreenBuffer.h:193
void clear(int x, int y, int width, int height)
Definition: ScreenBuffer.h:51
int getWidth()
Definition: ScreenBuffer.h:30
void drawRotatedChar(uint16_t x, uint16_t y, unsigned char ch, Colour c, Colour bg, uint8_t size)
Definition: ScreenBuffer.h:284
char * msg_itoa(int val, int base)
char * msg_ftoa(float val, int base)