EE445M RTOS
Taken at the University of Texas Spring 2015
graph_framebuffer.c
Go to the documentation of this file.
1 /* framebuffer.c
2  * Hershal Bhave and Eric Crosson
3  * 2014-02-08, extracted on 2015-01-18
4  * Function: represent a framebuffer of an oscope in memory.
5  * Lab 3
6  * Last Revision: LOOK IN GIT FGT
7  * LM3S1968
8  */
9 
10 #include "graph_framebuffer.h"
11 #include "shape.h"
12 #include <math.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 /* Below are the functions that handle graphing graph (graphlib.h) objects */
17 
18 /*
19  A wrapper for FBDrawGraph where the user does not have to fill in
20  implicit information about the graph size.
21  Inputs: fb framebuffer to use as canvas
22  g graph to draw on fb
23  Outputs: void
24 */
26  point* origin = shape_create_point((pixel_t) 0, (pixel_t) 0, (shade_t) 15);
27  FBDrawGraph(fb, g, origin, (pixel_t) OLED_WIDTH, (pixel_t) OLED_HEIGHT);
28  SHDestroyPoint(origin);
29 }
30 
31 /*
32  A wrapper for FBEraseGraph where the user does not have to fill in
33  implicit information about the graph size.
34  Inputs: fb framebuffer to use as canvas
35  g graph to draw on fb
36  Outputs: void
37 */
41  SHDestroyPoint(origin);
42 }
43 
44 /*
45  A wrapper for FBEraseGraphData where the user does not have to fill
46  in implicit information about the graph size.
47  Inputs: fb framebuffer to use as canvas
48  g graph to draw on fb
49  Outputs: void
50 */
54  SHDestroyPoint(origin);
55 }
56 
57 /*
58  This method handles the drawing of each part of a graph object. The
59  task of drawing each part has been delegated to a subroutine for
60  ease of debugging and testing. Before calling each subroutine, this
61  method sets the internal framebuffer variables inside of the
62  specified graph object.
63  Inputs: fb framebuffer to use as canvas
64  g graph to draw on fb
65  top_left_corner top left corner of graph
66  width width of graph
67  height height of graph
68  Outputs: void
69 
70  ** NOTICE **
71  This is where the rubber meets the road.
72 */
73 void FBDrawGraph(framebuffer fb, graph* g, point* top_left_corner,
74  pixel_t width, pixel_t height) {
75  /* Determine how many pixels to reserve for the scale numbers next
76  * to the axes */
77  pixel_t x_range_padding = max_pixel_width_of_long(g->y_min, g->y_max);
78  pixel_t y_range_padding = max_pixel_height_of_long(g->x_min, g->x_max);
79 
80  /* {x,y}_pixel_{start,end} information in /resources/2014-04-07 10.07.01.jpg */
81  g->x_pixel_start = top_left_corner->x + x_range_padding;
82  g->x_pixel_end = top_left_corner->x + width;
83  g->y_pixel_start = top_left_corner->y;
84  g->y_pixel_end = top_left_corner->y + height - 2 - y_range_padding;
85 
86  _FBDrawGraphBounds(fb, g, x_range_padding, y_range_padding, top_left_corner, width, height, top_left_corner->shade);
87  _FBDrawGraphData(fb, g, top_left_corner, top_left_corner->shade);
88  _FBDrawGraphTitle(fb, g);
90  _FBDrawGraphAxesScale(fb, g);
91 }
92 
93 /*
94  Using fb as a canvas, erase g which starts at top_left_corner, being
95  of dimensions width and height.
96  Inputs: fb framebuffer to use as canvas
97  g graph to draw on fb
98  top_left_corner top left corner of graph
99  width width of graph
100  height height of graph
101  Outputs: void
102 */
103 void FBEraseGraph(framebuffer fb, graph* g, point* top_left_corner,
104  pixel_t width, pixel_t height) {
105  /* Determine how many pixels to reserve for the scale numbers next
106  * to the axes */
107  pixel_t x_range_padding = max_pixel_width_of_long(g->y_min, g->y_max);
108  pixel_t y_range_padding = max_pixel_height_of_long(g->x_min, g->x_max);
109 
110  /* {x,y}_pixel_{start,end} information in /resources/2014-04-07 10.07.01.jpg */
111  g->x_pixel_start = top_left_corner->x + x_range_padding;
112  g->x_pixel_end = top_left_corner->x + width;
113  g->y_pixel_start = top_left_corner->y;
114  g->y_pixel_end = top_left_corner->y + height - 2 - y_range_padding;
115 
116  _FBDrawGraphBounds(fb, g, x_range_padding, y_range_padding, top_left_corner, width, height, FB_SHADE_ERASE);
117  _FBDrawGraphData(fb, g, top_left_corner, FB_SHADE_ERASE);
118  _FBDrawGraphTitle(fb, g);
119  _FBDrawGraphAxesTitles(fb, g);
120  _FBDrawGraphAxesScale(fb, g);
121 }
122 
123 /*
124  Using fb as a canvas, erase data points from g which starts at
125  top_left_corner, being of dimensions width and height.
126  Inputs: fb framebuffer to use as canvas
127  g graph to draw on fb
128  top_left_corner top left corner of graph
129  width width of graph
130  height height of graph
131  Outputs: void
132 */
133 void FBEraseGraphData(framebuffer fb, graph* g, point* top_left_corner,
134  pixel_t width, pixel_t height) {
135  /* Determine how many pixels to reserve for the scale numbers next
136  * to the axes */
137  pixel_t x_range_padding = max_pixel_width_of_long(g->y_min, g->y_max);
138  pixel_t y_range_padding = max_pixel_height_of_long(g->x_min, g->x_max);
139 
140  /* {x,y}_pixel_{start,end} information in /resources/2014-04-07 10.07.01.jpg */
141  g->x_pixel_start = top_left_corner->x + x_range_padding;
142  g->x_pixel_end = top_left_corner->x + width;
143  g->y_pixel_start = top_left_corner->y;
144  g->y_pixel_end = top_left_corner->y + height - 2 - y_range_padding;
145 
146  _FBDrawGraphData(fb, g, top_left_corner, FB_SHADE_ERASE);
147 }
148 
149 /*
150  Using fb as a canvas, draw g which starts at top_left_corner, being
151  of dimensions width and height. Use shade to draw the bounds.
152  Inputs: fb framebuffer to use as canvas
153  g graph to draw on fb
154  top_left_corner top left corner of graph
155  width width of graph
156  height height of graph
157  Outputs: void
158 */
160  graph* g,
161  pixel_t x_range_padding,
162  pixel_t y_range_padding,
163  point* top_left_corner,
164  pixel_t width,
165  pixel_t height,
166  shade_t shade) {
167  /* Draw X axis boundaries (aka vertical lines) */
168  FBDrawAnonLine(fb,
169  shape_create_point(top_left_corner->x + x_range_padding,
170  top_left_corner->y,
171  shade),
172  shape_create_point(top_left_corner->x + x_range_padding,
173  top_left_corner->y + (height - y_range_padding),
174  shade),
175  shade);
176  /* Draw Y axis boundaries (aka horizontal lines) */
177  FBDrawAnonLine(fb,
178  shape_create_point(top_left_corner->x + x_range_padding,
179  top_left_corner->y + height - y_range_padding,
180  shade),
181  shape_create_point(top_left_corner->x + x_range_padding + width,
182  top_left_corner->y + height - y_range_padding,
183  shade),
184  shade);
185 }
186 
187 /*
188  Using fb as a canvas, draw data points of g which starts at
189  top_left_corner, being of dimensions width and height. Use shade to
190  draw the bounds.
191  Inputs: fb framebuffer to use as canvas
192  g graph to draw on fb
193  top_left_corner top left corner of graph
194  width width of graph
195  height height of graph
196  Outputs: void
197 */
198 private void _FBDrawGraphData(framebuffer fb, graph* g, point* top_left_corner, shade_t shade) {
199 
200  long idx = 0;
201  /* Temporary variables reused in printfs */
202  pixel_t x1, x2, y1, y2;
203  /* Set this to true from lldb/gdb to see useful debugging information */
204  bool debug = true;
205 
206  for(idx=0;
207  (((g->all_data_points_valid == true) && (idx < g->x_index_max-1))) ||
208  (g->all_data_points_valid == false && (idx < (g->most_recent_data_point - 1)));
209  ++idx) {
210 
211  fprintf(stderr, "Printing index %ld\n", idx);
212 
213  if ((idx <= g->most_recent_data_point) &&
215  /* Draw nothing */
216  when (debug) {fprintf(stderr, "Not drawing this cycle [idx:%ld]\n", idx);}
217  } else {
218 
219  x1 = g->x_pixel_start + ((idx)*(g->x_pixel_end-g->x_pixel_start)/(g->x_max-g->x_min));
220  y1 = g->y_pixel_end - ((g->data[idx]+g->y_min)*(g->y_pixel_end-g->y_pixel_start)/(g->y_max-g->y_min));
221  x2 = g->x_pixel_start + ((idx+1)*(g->x_pixel_end-g->x_pixel_start)/(g->x_max-g->x_min));
222  y2 = g->y_pixel_end - ((g->data[idx+1]+g->y_min)*(g->y_pixel_end-g->y_pixel_start)/(g->y_max-g->y_min));
223 
224  FBDrawAnonLine(fb,
225  shape_create_point(x1, y1, shade),
226  shape_create_point(x2, y2, shade),
227  shade);
228 
229  when (debug) {fprintf(stderr, "Line from:\t(%u,\t%u) to (%u,\t%u)\n",x1,y1,x2,y2);}
230  }
231  }
232 }
233 
234 /* TODO: document this function */
235 private void _FBDrawGraphTitle(framebuffer fb, graph* g) {
236 
237 }
238 
239 /* TODO: document this function */
241 
242 }
243 
244 /* TODO: document this function */
246 
247 }
248 
249 /*
250  Return the greater of two unsigned chars.
251  Inputs: one uchar a to compare
252  two uchar b to compare
253  Outputs: unsigned char the max of one and two
254 */
255 unsigned char max_uc(unsigned char one, unsigned char two) {
256  if (one > two) {return one;} else return two;
257 }
258 
259 /*
260  Return the height of a string in pixels.
261  Inputs: str string to calculate the height of
262  Outputs: pixel_t pixel height of str
263 */
265  /* TODO: consider line wrapping */
266  return VALVANO_FONT_LINE_SPACING + VALVANO_FONT_HEIGHT;
267 }
268 
269 /*
270  Return the width of a string in pixels.
271  Inputs: str string to calculate the width of
272  Outputs: pixel_t pixel width of str
273 */
274 private pixel_t _FBPixelWidthOfString(char* str) {
275  return VALVANO_FONT_KERNING + ((VALVANO_FONT_KERNING + VALVANO_FONT_WIDTH) * strlen(str));
276 }
277 
278 /*
279  Return the width of a long in pixels.
280  Inputs: l long to calculate the width of
281  Outputs: pixel_t pixel width of l
282 */
283 private pixel_t _FBPixelWidthOfLong(long l) {
284  // 2 pixels because we want one to pad the front and one on the back
285  return VALVANO_FONT_KERNING + (log(l) * VALVANO_FONT_WIDTH);
286 }
287 
288 /*
289  Return the height of a long in pixels.
290  Inputs: l l to calculate the height of
291  Outputs: pixel_t pixel height of l
292 */
293 private pixel_t _FBPixelHeightOfLong(long l) {
294  // 2 pixels because we want one to pad the top and one on the bottom
295  return VALVANO_FONT_LINE_SPACING + VALVANO_FONT_HEIGHT;
296 }
private void _FBDrawGraphAxesScale(framebuffer fb, graph *g)
unsigned short y
Definition: shape.h:16
pixel_t x_pixel_start
Definition: graphlib.h:71
private pixel_t _FBPixelWidthOfString(char *str)
pixel_t y_pixel_end
Definition: graphlib.h:72
#define when(cond)
Definition: defines.h:60
long most_recent_data_point
Definition: graphlib.h:66
#define OLED_HEIGHT
Definition: defines.h:106
pixel_t y_pixel_start
Definition: graphlib.h:72
#define pixel_t
Definition: defines.h:46
shade_t shade
Definition: shape.h:18
#define OLED_WIDTH
Definition: defines.h:107
#define y_pixel_t
Definition: defines.h:48
char ** framebuffer
Definition: framebuffer.h:12
private void _FBDrawGraphBounds(framebuffer fb, graph *g, pixel_t x_range_padding, pixel_t y_range_padding, point *top_left_corner, pixel_t width, pixel_t height, shade_t shade)
long * data
Definition: graphlib.h:41
private pixel_t _FBPixelHeightOfLong(long l)
long x_max
Definition: graphlib.h:37
private pixel_t _FBPixelWidthOfLong(long l)
#define GL_BLANK_STEPS_PRECEEDING_STALE_DATA
Definition: graphlib.h:14
Definition: graphlib.h:29
unsigned char max_uc(unsigned char one, unsigned char two)
void FBEraseGraph(framebuffer fb, graph *g, point *top_left_corner, pixel_t width, pixel_t height)
#define FB_COLOR_ERASE
Definition: defines.h:81
private void _FBDrawGraphData(framebuffer fb, graph *g, point *top_left_corner, shade_t shade)
point * shape_create_point(ushort x, ushort y, shade_t shade)
Definition: shape.c:6
private void _FBDrawGraphTitle(framebuffer fb, graph *g)
private void _FBDrawGraphAxesTitles(framebuffer fb, graph *g)
Representation of an ordered pair with a shade.
Definition: shape.h:13
#define shade_t
Definition: defines.h:41
void FBEraseGraphData(framebuffer fb, graph *g, point *top_left_corner, pixel_t width, pixel_t height)
long x_min
Definition: graphlib.h:37
#define FB_SHADE_ERASE
Definition: defines.h:74
void FBDrawGraph(framebuffer fb, graph *g, point *top_left_corner, pixel_t width, pixel_t height)
long y_min
Definition: graphlib.h:38
long y_max
Definition: graphlib.h:38
void FBEraseFullscreenGraph(framebuffer fb, graph *g)
pixel_t x_pixel_end
Definition: graphlib.h:71
unsigned short x
Definition: shape.h:15
bool all_data_points_valid
Definition: graphlib.h:55
void FBEraseFullscreenGraphData(framebuffer fb, graph *g)
void FBDrawFullscreenGraph(framebuffer fb, graph *g)
pixel_t _FBPixelHeightOfString(char *str)
#define x_pixel_t
Definition: defines.h:47