GLCD Library
A C Library for Embedded Applications
 All Data Structures Files Functions Variables Enumerations Enumerator Macros Groups Pages
graphics.c
Go to the documentation of this file.
1 
10 /*
11  Copyright (c) 2012, Andy Gock
12 
13  Copyright (c) 2012, Adafruit Industries
14 
15  All rights reserved.
16 
17  Redistribution and use in source and binary forms, with or without
18  modification, are permitted provided that the following conditions are met:
19  * Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21  * Redistributions in binary form must reproduce the above copyright
22  notice, this list of conditions and the following disclaimer in the
23  documentation and/or other materials provided with the distribution.
24  * Neither the name of Andy Gock nor the
25  names of its contributors may be used to endorse or promote products
26  derived from this software without specific prior written permission.
27 
28  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
29  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31  DISCLAIMED. IN NO EVENT SHALL ANDY GOCK BE LIABLE FOR ANY
32  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include "glcd.h"
44 
45 /* Based on PCD8544 library by Limor Fried */
46 void glcd_set_pixel(uint8_t x, uint8_t y, uint8_t color) {
47  if (x > (GLCD_LCD_WIDTH-1) || y > (GLCD_LCD_HEIGHT-1)) {
48  /* don't do anything if x/y is outside bounds of display size */
49  return;
50  }
51 
52  if (color) {
53  /* Set black */
54  glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] |= ( 1 << (y%8));
55  } else {
56  /* Set white */
57  glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] &= ~ (1 << (y%8));
58  }
59 
60  glcd_update_bbox(x,y,x,y);
61 }
62 
63 /* Based on PCD8544 library by Limor Fried */
64 uint8_t glcd_get_pixel(uint8_t x, uint8_t y) {
65  if ((x >= GLCD_LCD_WIDTH) || (y >= GLCD_LCD_HEIGHT)) {
66  return 0;
67  }
68 
69  if ( glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] & ( 1 << (y%8)) ) {
70  return 1;
71  } else {
72  return 0;
73  }
74 }
75 
76 void glcd_invert_pixel(uint8_t x, uint8_t y) {
77  if ((x >= GLCD_LCD_WIDTH) || (y >= GLCD_LCD_HEIGHT)) {
78  return;
79  }
80  glcd_update_bbox(x,y,x,y);
81  glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] ^= ( 1 << (y%8));
82 }
83 
84 /* Bresenham's algorithm - based on PCD8544 library Limor Fried */
85 void glcd_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color) {
86  uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
87  uint8_t dx, dy;
88  int8_t err;
89  int8_t ystep;
90 
91  if (steep) {
92  swap(x0, y0);
93  swap(x1, y1);
94  }
95 
96  if (x0 > x1) {
97  swap(x0, x1);
98  swap(y0, y1);
99  }
100 
101  glcd_update_bbox( x0, y0, x1, y1 );
102 
103  dx = x1 - x0;
104  dy = abs(y1 - y0);
105 
106  err = dx / 2;
107 
108  if (y0 < y1) {
109  ystep = 1;
110  } else {
111  ystep = -1;
112  }
113 
114  for (; x0<=x1; x0++) {
115  if (steep) {
116  glcd_set_pixel(y0, x0, color);
117  } else {
118  glcd_set_pixel(x0, y0, color);
119  }
120  err -= dy;
121  if (err < 0) {
122  y0 += ystep;
123  err += dx;
124  }
125  }
126 }
127 
128 void glcd_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
129 {
130  int16_t i;
131  for (i=x; i<x+w; i++) {
132  int16_t j;
133  for (j=y; j<y+h; j++) {
134  glcd_set_pixel(i, j, color);
135  }
136  }
137  glcd_update_bbox(x, y, x+w-1, y+h-1);
138 }
139 
140 void glcd_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
141 {
142  int16_t i;
143  for (i=x; i<x+w; i++) {
144  glcd_set_pixel(i, y, color);
145  glcd_set_pixel(i, y+h-1, color);
146  }
147  for (i=y; i<y+h; i++) {
148  glcd_set_pixel(x, i, color);
149  glcd_set_pixel(x+w-1, i, color);
150  }
151  glcd_update_bbox(x, y, x+w-1, y+h-1);
152 }
153 
154 void glcd_draw_rect_thick(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tx, uint8_t ty, uint8_t color)
155 {
156  int16_t i, t;
157 
158  if (tx == 0) {
159  tx = 1;
160  }
161 
162  if (ty == 0) {
163  ty = 1;
164  }
165 
166  for (i=x; i<x+w; i++) {
167  /* Top and bottom sides */
168  for (t=0; t<(ty); t++) {
169  glcd_set_pixel(i, y+t, color);
170  glcd_set_pixel(i, y+h-1-t, color);
171  }
172  }
173  for (i=y; i<y+h; i++) {
174  /* Left and right sides */
175  for (t=0; t<(tx); t++) {
176  glcd_set_pixel(x+t, i, color);
177  glcd_set_pixel(x+w-1-t, i, color);
178  }
179  }
180  glcd_update_bbox(x, y, x+w-1, y+h-1);
181 }
182 
183 void glcd_draw_rect_shadow(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
184 {
185  glcd_draw_rect(x, y, w, h, color);
186  glcd_draw_line(x+1, y+h, x+w, y+h, color);
187  glcd_draw_line(x+w, y+1, x+w, y+h, color);
188 }
189 
190 void glcd_draw_circle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
191 {
192 
193  int8_t f = 1 - r;
194  int8_t ddF_x = 1;
195  int8_t ddF_y = -2 * r;
196  int8_t x = 0;
197  int8_t y = r;
198 
199  glcd_update_bbox(x0-r, y0-r, x0+r, y0+r);
200 
201  glcd_set_pixel(x0, y0+r, color);
202  glcd_set_pixel(x0, y0-r, color);
203  glcd_set_pixel(x0+r, y0, color);
204  glcd_set_pixel(x0-r, y0, color);
205 
206  while (x<y) {
207  if (f >= 0) {
208  y--;
209  ddF_y += 2;
210  f += ddF_y;
211  }
212  x++;
213  ddF_x += 2;
214  f += ddF_x;
215 
216  glcd_set_pixel(x0 + x, y0 + y, color);
217  glcd_set_pixel(x0 - x, y0 + y, color);
218  glcd_set_pixel(x0 + x, y0 - y, color);
219  glcd_set_pixel(x0 - x, y0 - y, color);
220 
221  glcd_set_pixel(x0 + y, y0 + x, color);
222  glcd_set_pixel(x0 - y, y0 + x, color);
223  glcd_set_pixel(x0 + y, y0 - x, color);
224  glcd_set_pixel(x0 - y, y0 - x, color);
225 
226  }
227 }
228 
229 void glcd_fill_circle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
230 {
231 
232  int8_t f = 1 - r;
233  int8_t ddF_x = 1;
234  int8_t ddF_y = -2 * r;
235  int8_t x = 0;
236  int8_t y = r;
237 
238  int16_t i;
239 
240  glcd_update_bbox(x0-r, y0-r, x0+r, y0+r);
241 
242  for (i=y0-r; i<=y0+r; i++) {
243  glcd_set_pixel(x0, i, color);
244  }
245 
246  while (x < y) {
247  if (f >= 0) {
248  y--;
249  ddF_y += 2;
250  f += ddF_y;
251  }
252  x++;
253  ddF_x += 2;
254  f += ddF_x;
255 
256  for (i=y0-y; i<=y0+y; i++) {
257  glcd_set_pixel(x0+x, i, color);
258  glcd_set_pixel(x0-x, i, color);
259  }
260  for (i=y0-x; i<=y0+x; i++) {
261  glcd_set_pixel(x0+y, i, color);
262  glcd_set_pixel(x0-y, i, color);
263  }
264  }
265 }
266 
267 void glcd_invert_area(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
268 {
269  uint8_t xx, yy;
270  for (xx = x; xx < (x+w); xx++) {
271  /* Loop through each partial column */
272  for (yy = y; yy < (y+h); yy++) {
273  /* Go down and invert every pixel */
274  glcd_invert_pixel(xx,yy);
275  }
276  }
277 }
278 
279 void glcd_draw_bitmap(const unsigned char *data)
280 {
281 
282 #if 0
283  /* Testing purposes only: Writing to the LCD right away (not for AVR) */
284  /* Normally, we do not do this, we just write to the screen buffer */
285  uint8_t *original_buffer;
286 
287  /* Save the location of original screen buffer */
288  original_buffer = glcd_buffer_selected;
289 
290  /* Use bitmap location as screen buffer (this won't work when using AVR8 PGM_P) */
291  glcd_select_screen((uint8_t *)data, glcd_bbox_selected);
292 
293  /* Make sure we write the entre display */
295  glcd_write();
296 
297  /* Restore the screen buffer back to original */
298  glcd_select_screen(original_buffer, glcd_bbox_selected);
299 #endif
300 
301  /* Copy bitmap data to the screen buffer */
302 #if defined(GLCD_DEVICE_AVR8)
303  memcpy_P(glcd_buffer_selected, data, (GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8));
304 #else
305  memcpy(glcd_buffer_selected, data, (GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8));
306 #endif
307 
309 }
#define GLCD_LCD_WIDTH
User specified GLCD width in pixels Set to 0 for automatic assignment based on controller.
Definition: glcd.h:140
void glcd_draw_rect_shadow(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
Draw rectangle but do not fill.
Definition: graphics.c:183
void glcd_invert_pixel(uint8_t x, uint8_t y)
Invert state of pixel of specified location.
Definition: graphics.c:76
glcd_BoundingBox_t * glcd_bbox_selected
Pointer to bounding box currently in use.
Definition: glcd.c:65
void glcd_write(void)
Update the display within the specified bounding box.
void glcd_draw_rect_thick(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tx, uint8_t ty, uint8_t color)
Draw rectangle but do not fill.
Definition: graphics.c:154
void glcd_select_screen(uint8_t *buffer, glcd_BoundingBox_t *bbox)
Select screen buffer and bounding box structure.
Definition: glcd.c:133
void glcd_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color)
Draw line.
Definition: graphics.c:85
void glcd_bbox_refresh()
Marks the entire display for re-writing.
Definition: glcd.c:114
#define swap(a, b)
Definition: glcd.h:90
#define GLCD_LCD_HEIGHT
User specified GLCD height in pixels Set to 0 for automatic assignment based on controller.
Definition: glcd.h:141
uint8_t * glcd_buffer_selected
Pointer to screen buffer currently in use.
Definition: glcd.c:60
uint8_t glcd_get_pixel(uint8_t x, uint8_t y)
Get state of pixel from specified location.
Definition: graphics.c:64
void glcd_invert_area(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Invert pixels in a retangular area.
Definition: graphics.c:267
void glcd_set_pixel(uint8_t x, uint8_t y, uint8_t color)
Set pixel to specified colour.
Definition: graphics.c:46
void glcd_draw_circle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
Draw circle but do not fill.
Definition: graphics.c:190
uint8_t glcd_buffer[GLCD_LCD_WIDTH *GLCD_LCD_HEIGHT/8]
Screen buffer.
Definition: glcd.c:49
void glcd_fill_circle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
Draw circle and fill.
Definition: graphics.c:229
GLCD Library main header file.
void glcd_draw_bitmap(const unsigned char *data)
Draw bitmap to screen buffer.
Definition: graphics.c:279
void glcd_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
Draw rectangle but do not fill.
Definition: graphics.c:140
void glcd_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
Draw rectangle and fill with colour.
Definition: graphics.c:128
void glcd_update_bbox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax)
Update bounding box.
Definition: glcd.c:69