EE445M RTOS
Taken at the University of Texas Spring 2015
framebuffer.c
Go to the documentation of this file.
1 /* -*- mode: c; c-basic-offset: 4; -*- */
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include "string.h"
6 #include "libstd/defines.h"
7 #include "framebuffer.h"
8 
9 #define NDEBUG
10 
12 
13  /* OPTIONAL OPTIMIZE: bit-strap this struct to reduce memory consumption */
14  unsigned char i;
15  unsigned char** fb = (unsigned char**) calloc(OLED_WIDTH, sizeof(unsigned char*));
16  for(i = 0; i < OLED_WIDTH; ++i) {
17  fb[i] = (unsigned char*) calloc(OLED_HEIGHT, sizeof(unsigned char));
18  }
19  return (framebuffer) fb;
20 }
21 
23 
24  unsigned char i;
25  for(i = 0; i < OLED_WIDTH; ++i) {
26  free(fb[i]);
27  }
28  free(fb);
29 }
30 
32 
33  if (sh->points[0] != null) {
34  _fb_draw_shape(fb, sh, sh->points[0]->shade);
35  }
36 }
37 
38 private
39 void _fb_draw_shape(framebuffer fb, shape* sh, shade_t shade) {
40 
41  unsigned short p;
42  for(p=0; p < sh->num_points; ++p) {
43  /* TODO: determine if the below line is necessary */
44  /* fb_set_pixel(fb, sh->points[p]->x, sh->points[p]->y, shade); */
45  if (p > 0) {
46  fb_draw_line_gradient(fb, sh->points[p-1], sh->points[p], shade);
47  }
48  }
49 
50  /* Enclose the figure */
51  if(p>1) {
52  fb_draw_line_gradient(fb, sh->points[0], sh->points[p-1], shade);
53  }
54 }
55 
56 void fb_draw_shapes(framebuffer fb, ushort numShapes, ...) {
57 
58  unsigned char i;
59  va_list args;
60 
61  va_start(args, numShapes);
62  for(i=0; i < numShapes; ++i) {
63  fb_draw_shape(fb, va_arg(args, shape*));
64  }
65  va_end(args); /* clean up the list */
66 }
67 
68 void fb_draw_shape_arr(framebuffer fb, ushort numShapes, shape** shape_arr) {
69 
70  unsigned char i;
71  for(i=0; i < numShapes; ++i) {
72  fb_draw_shape(fb, shape_arr[i]);
73  }
74 }
75 
76 void fb_erase_shape_arr(framebuffer fb, ushort numShapes, shape** shape_arr) {
77 
78  unsigned char i;
79  for(i=0; i < numShapes; ++i) {
80  fb_erase_shape(fb, shape_arr[i]);
81  }
82 }
83 
84 void fb_set_pixel(framebuffer fb, uchar x, uchar y, shade_t shade) {
85 
86  if (x < FB_WIDTH && y < FB_HEIGHT) {
87  fb[x][y] = shade;
88  } else {
89 #ifndef NDEBUG
90  printf("%sPixel off screen: ", __FUNCTION__);
91  fb_console_println_coordinate(x, y, shade);
92 #endif
93  }
94 }
95 
96 void fb_erase_char(framebuffer fb, point* top_left_corner, char c) {
97 
98  point* pen = shape_duplicate_point(top_left_corner);
99  pen->shade = FB_COLOR_ERASE;
100  _fb_draw_char(fb, pen, c);
101  SHDestroyPoint(pen);
102 }
103 
104 private
105 void _fb_draw_line(framebuffer fb, point* point1, point* point2, shade_t shade) {
106 
107  point* a;
108  point* b;
109  int dx, dy, sx, sy, e2, err;
110 
111  a = shape_duplicate_point(point1);
112  b = shape_duplicate_point(point2);
113 
114  dx = abs(b->x-a->x); sx = (a->x < b->x) ? 1 : -1;
115  dy = abs(b->y-a->y); sy = (a->y < b->y) ? 1 : -1;
116  err = (dx>dy ? dx : -dy)/2;
117  for(;;) {
118  fb_set_pixel(fb, a->x, a->y, shade);
119  if ((a->x == b->x) && (a->y == b->y)) {break;}
120  e2 = err;
121  if (e2 >-dx) {err -= dy; a->x += sx;}
122  if (e2 < dy) {err += dx; a->y += sy;}
123  }
124  SHDestroyPoint(a);
125  SHDestroyPoint(b);
126 }
127 
128 private
130 
131  fb_set_pixel(fb, center->x + x, center->y + y, center->shade);
132  fb_set_pixel(fb, center->x - x, center->y + y, center->shade);
133  fb_set_pixel(fb, center->x - x, center->y - y, center->shade);
134  fb_set_pixel(fb, center->x + x, center->y - y, center->shade);
135 }
136 
137 private
139 
140  int i;
141  for(i = -x; i <= x; ++i) {
142  fb_set_pixel(fb, center->x + i, center->y + y, center->shade);
143  fb_set_pixel(fb, center->x + i, center->y - y, center->shade);
144  }
145 }
146 
148  point* center,
149  ushort x_radius,
150  ushort y_radius,
151  shade_t shade) {
152 
153  ushort x, y;
154  int xx, yy, xx2, yy2, dx, dy, stop_x, stop_y, error;
155 
156  x = x_radius;
157  y = 0;
158 
159  xx = x_radius * x_radius; // width^2
160  yy = y_radius * y_radius; // height^2
161 
162  xx2 = xx*2;
163  yy2 = yy*2;
164 
165  dx = yy * (1 - 2*x_radius);
166  dy = xx;
167 
168  stop_x = yy*2*x_radius;
169  stop_y = 0;
170 
171  error = 0;
172 
173  while (stop_x > stop_y) {
174  _fb_plot_four_ellipse_points(fb, center, x, y);
175  ++y;
176  stop_y += xx2;
177  error += dy;
178  dy += xx2;
179  if (2*error + dx > 0) {
180  --x;
181  stop_x -= yy2;
182  error += dx;
183  dx += yy2;
184  }
185  }
186 
187  /* First set of points is done, now plot the second set */
188  x = 0;
189  y = y_radius;
190  dx = yy;
191  dy = xx * (1 - 2*y_radius);
192  error = 0;
193  stop_x = 0;
194  stop_y = xx2*y_radius;
195 
196  while (stop_x <= stop_y) {
197  _fb_plot_four_ellipse_points(fb, center, x, y);
198  x++;
199  stop_x += yy2;
200  error += dx;
201  dx += yy2;
202  if (2*error + dy > 0) {
203  --y;
204  stop_y -= xx2;
205  error += dy;
206  dy += xx2;
207  }
208  }
209 }
210 
212  point* center,
213  ushort x_radius,
214  ushort y_radius,
215  shade_t shade) {
216 
217  ushort x, y;
218  int xx, yy, xx2, yy2, dx, dy, last_y_filled, stop_x, stop_y, error, i;
219  xx = x_radius * x_radius; // width^2
220  yy = y_radius * y_radius; // height^2
221 
222  xx2 = xx*2;
223  yy2 = yy*2;
224 
225  error = 0;
226 
227  // fill the horizontal diameter
228  for (i = -x_radius; i <= x_radius; ++i) {
229  fb_set_pixel(fb, center->x + i, center->y, center->shade);
230  }
231 
232  /* First set of points is done, now plot the second set */
233  x = 0;
234  y = y_radius;
235  dx = yy;
236  dy = xx * (1 - 2*y_radius);
237  stop_x = 0;
238  stop_y = xx2*y_radius;
239 
240  // OPTIONAL OPTIMIZE: this loop
241  last_y_filled = y;
242  while (stop_x <= stop_y) {
243  if (y != last_y_filled) {
244  _fb_fill_four_ellipse_points(fb, center, x, y);
245  last_y_filled = y;
246  }
247  x++;
248  stop_x += yy2;
249  error += dx;
250  dx += yy2;
251  if (2*error + dy > 0) {
252  --y;
253  stop_y -= xx2;
254  error += dy;
255  dy += xx2;
256  }
257  }
258 }
259 
260 void fb_erase_string(framebuffer fb, point* top_left_corner, char* string) {
261 
262  point* pt = shape_duplicate_point(top_left_corner);
263  pt->shade = FB_COLOR_ERASE;
264  _fb_draw_string(fb, pt, string);
265  SHDestroyPoint(pt);
266 }
267 
268 private
269 void _fb_draw_string(framebuffer fb, point* top_left_corner, char* string) {
270 
271  point* pen = shape_duplicate_point(top_left_corner);
272  while(*string != null) {
273  _fb_draw_char(fb, pen, *(string++));
275  }
276  SHDestroyPoint(pen);
277 }
278 
279 /* TODO: Allow for newline/carriage returns, printf style perhaps */
280 /* TODO: abstract font usage (modal), allow for multiple fonts to be
281  * loaded/unloaded from memory (map). */
282 private
283 void _fb_draw_char(framebuffer fb, point* pen, char c) {
284 
285  uchar active, col, row, mask;
286  for(col=0; col < FONT_VALVANO_WIDTH; ++col) {
287  mask = 0x01;
288  if (pen->x+col >= FB_WIDTH) {
289  /* We have exceeded the number of pixels on the screen */
290 #ifndef NDEBUG
291  printf("%s pen has gone offscreen. Ignoring rest of character...\n", __FUNCTION__);
292 #endif
293  break;
294  }
295  for(row=0; row < FONT_VALVANO_HEIGHT; ++row) {
296  if (pen->y+row >= FB_HEIGHT) {break;}
297  active = mask & font_valvano[c][col];
298  fb_set_pixel(fb, pen->x + col, pen->y + row, active ? pen->shade : 0);
299  mask = mask << 1;
300  }
301  }
302 }
303 
305 
306 #ifdef __GNUC__
307  printf("(%d,%d):%d\n", p->x, p->y, p->shade);
308 #else
309 #ifndef NDEBUG
310  printf("%s This function was called in an inappropriate context.\n", __FUNCTION__);
311  printf("%s Please consult the documentation.\n", __FUNCTION__);
312 #endif
313 #endif
314 }
315 
317 
318 #ifdef __GNUC__
319  printf("(%d,%d):%d", p->x, p->y, p->shade);
320 #ifndef NDEBUG
321  printf("%s This function was called in an inappropriate context.\n", __FUNCTION__);
322  printf("%s Please consult the documentation.\n", __FUNCTION__);
323 #endif
324 #endif
325 }
326 
328 
329 #ifdef __GNUC__
330  printf("(%d,%d):%d\n", x, y, shade);
331 #ifndef NDEBUG
332  printf("%s This function was called in an inappropriate context.", __FUNCTION__);
333  printf("Please consult the documentation.\n");
334 #endif
335 #endif
336 }
337 
338 /* TODO: create a header prototype */
340 
341 #ifdef __GNUC__
342  printf("(%d,%d):%d", x, y, shade);
343 #ifndef NDEBUG
344  printf("%s This function was called in an inappropriate context.", __FUNCTION__);
345  printf("Please consult the documentation.\n");
346 #endif
347 #endif
348 }
void fb_erase_string(framebuffer fb, point *top_left_corner, char *string)
Erase string on fb starting at top_left_corner.
Definition: framebuffer.c:260
void fb_draw_ellipse(framebuffer fb, point *center, ushort x_radius, ushort y_radius, shade_t shade)
Draw an ellipse in fb at center with specified x- and y-radii of color shade.
Definition: framebuffer.c:147
unsigned short num_points
Definition: shape.h:28
unsigned short y
Definition: shape.h:16
#define OLED_HEIGHT
Definition: defines.h:106
#define FB_HEIGHT
Definition: defines.h:112
Representation of a shape.
Definition: shape.h:26
#define null
Definition: defines.h:29
private void _fb_draw_char(framebuffer fb, point *pen, char c)
For internal use only.
Definition: framebuffer.c:283
shade_t shade
Definition: shape.h:18
void fb_draw_shape_arr(framebuffer fb, ushort numShapes, shape **shape_arr)
Definition: framebuffer.c:68
#define FB_WIDTH
Definition: defines.h:113
private void _fb_draw_string(framebuffer fb, point *top_left_corner, char *string)
For internal use only.
Definition: framebuffer.c:269
private void _fb_draw_shape(framebuffer fb, shape *sh, shade_t shade)
For internal use only.
Definition: framebuffer.c:39
void fb_console_println_coordinate(uchar x, uchar y, shade_t shade)
Print a coordinate (ordered pair) to the console followed by a newline.
Definition: framebuffer.c:327
void fb_console_print_coordinate(uchar x, uchar y, shade_t shade)
Print a coordinate (ordered pair) to the console.
Definition: framebuffer.c:339
#define OLED_WIDTH
Definition: defines.h:107
void fb_draw_shape(framebuffer fb, shape *sh)
Using as a canvas, draw .
Definition: framebuffer.c:31
void fb_destroy(framebuffer fb)
Destroy a framebuffer object.
Definition: framebuffer.c:22
private void _fb_fill_four_ellipse_points(framebuffer fb, point *center, ushort x, ushort y)
Fill an ellipse on fb.
Definition: framebuffer.c:138
unsigned short ushort
Definition: defines.h:35
char ** framebuffer
Definition: framebuffer.h:12
point ** points
Definition: shape.h:29
point * shape_duplicate_point(point *p)
Definition: shape.h:77
static const unsigned char font_valvano[129][5]
Font definition: Professor Valvano style.
Definition: font.h:13
#define FONT_VALVANO_HEIGHT
Definition: defines.h:96
unsigned char uchar
Definition: defines.h:34
#define FONT_VALVANO_WIDTH
Definition: defines.h:97
#define FB_COLOR_ERASE
Definition: defines.h:81
framebuffer fb_init()
Create a framebuffer object and return the handle.
Definition: framebuffer.c:11
void fb_erase_char(framebuffer fb, point *top_left_corner, char c)
Erase char on fb starting at top_left_corner.
Definition: framebuffer.c:96
void fb_erase_shape(framebuffer fb, shape *sh)
Using as a canvas, draw .
Definition: framebuffer.h:211
void fb_erase_shape_arr(framebuffer fb, ushort numShapes, shape **shape_arr)
Definition: framebuffer.c:76
void fb_draw_shapes(framebuffer fb, ushort numShapes,...)
Definition: framebuffer.c:56
void fb_draw_line_gradient(framebuffer fb, point *point1, point *point2, shade_t shade)
Draw a line segment on from to .
Definition: framebuffer.h:347
Representation of an ordered pair with a shade.
Definition: shape.h:13
private void _fb_draw_line(framebuffer fb, point *point1, point *point2, shade_t shade)
The heavy-lifter (pixel-setter) in line-segment-drawing.
Definition: framebuffer.c:105
void fb_console_println_point(point *p)
Print a point (ordered pair) to the console followed by a newline.
Definition: framebuffer.c:304
void fb_draw_ellipse_fill(framebuffer fb, point *center, ushort x_radius, ushort y_radius, shade_t shade)
Draw on fb a shaded ellipse described by center, x- and y-radii.
Definition: framebuffer.c:211
#define shade_t
Definition: defines.h:41
void fb_console_print_point(point *p)
Print a point (ordered pair) to the console.
Definition: framebuffer.c:316
private void _fb_plot_four_ellipse_points(framebuffer fb, point *center, ushort x, ushort y)
Plot on fb the four symmetric points on an ellipse described by a center and x- and y-offsets...
Definition: framebuffer.c:129
#define FONT_VALVANO_KERNING
Definition: defines.h:98
unsigned short x
Definition: shape.h:15
void fb_set_pixel(framebuffer fb, uchar x, uchar y, shade_t shade)
In fb, set pixel (x,y) to .
Definition: framebuffer.c:84