1 /**
2 * \file
3 *
4 * \brief Local framebuffer
5 *
6 * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #include "gfx_mono_framebuffer.h"
48
49 /* Pointer to the framebuffer; updated by the gfx_mono_set_framebuffer function */
50 static uint8_t *fbpointer;
51
52 /**
53 * \brief Set the LCD framebuffer.
54 *
55 * \param[in] framebuffer A pointer to an allocated area of RAM that can hold the
56 * framebuffer.
57 *
58 * A small example:
59 * \code
60 uint8_t framebuffer[FRAMEBUFFER_SIZE];
61 gfx_mono_set_framebuffer(framebuffer);
62 \endcode
63 */
gfx_mono_set_framebuffer(uint8_t * framebuffer)64 void gfx_mono_set_framebuffer(uint8_t *framebuffer)
65 {
66 fbpointer = framebuffer;
67 }
68
69 /**
70 * \brief Put a page from RAM to the framebuffer
71 *
72 * \param[in] data Pointer to data to be written
73 * \param[in] page Page address
74 * \param[in] column Offset into page (x coordinate)
75 * \param[in] width Number of bytes to be written.
76 *
77 * The following example will write 32 bytes from data_buf to the page 0,
78 * column 10 (byte 10 to 42 in the framebuffer).
79 * \code
80 gfx_mono_framebuffer_put_page(data_buf, 0, 10, 32);
81 \endcode
82 */
gfx_mono_framebuffer_put_page(gfx_mono_color_t * data,gfx_coord_t page,gfx_coord_t column,gfx_coord_t width)83 void gfx_mono_framebuffer_put_page(gfx_mono_color_t *data, gfx_coord_t page,
84 gfx_coord_t column, gfx_coord_t width)
85 {
86 gfx_mono_color_t *data_pt = data;
87 gfx_coord_t *framebuffer_pt = fbpointer +
88 ((page * GFX_MONO_LCD_WIDTH) + column);
89
90 do {
91 *framebuffer_pt++ = *data_pt++;
92 } while (--width > 0);
93 }
94
95 /**
96 * \brief Read a page from the framebuffer
97 *
98 * \param[in] data Pointer where to store the read data
99 * \param[in] page Page address
100 * \param[in] column Offset into page (x coordinate)
101 * \param[in] width Number of bytes to be read
102 *
103 * The following example will read back the first 128 bytes (first page) from
104 * the framebuffer:
105 * \code
106 gfx_mono_framebuffer_get_page(read_buffer, 0, 0, 128);
107 \endcode
108 */
gfx_mono_framebuffer_get_page(gfx_mono_color_t * data,gfx_coord_t page,gfx_coord_t column,gfx_coord_t width)109 void gfx_mono_framebuffer_get_page(gfx_mono_color_t *data, gfx_coord_t page, \
110 gfx_coord_t column, gfx_coord_t width)
111 {
112 gfx_coord_t *framebuffer_pt = fbpointer +
113 ((page * GFX_MONO_LCD_WIDTH) + column);
114 do {
115 *data++ = *framebuffer_pt++;
116 } while (--width > 0);
117 }
118
119 /**
120 * \brief Draw pixel to framebuffer
121 *
122 * \param[in] x X coordinate of the pixel
123 * \param[in] y Y coordinate of the pixel
124 * \param[in] color Pixel operation
125 *
126 */
gfx_mono_framebuffer_draw_pixel(gfx_coord_t x,gfx_coord_t y,gfx_mono_color_t color)127 void gfx_mono_framebuffer_draw_pixel(gfx_coord_t x, gfx_coord_t y,
128 gfx_mono_color_t color)
129 {
130 uint8_t page;
131 uint8_t pixel_mask;
132 uint8_t pixel_value;
133
134 /* Discard pixels drawn outside the screen */
135 if ((x > GFX_MONO_LCD_WIDTH - 1) || (y > GFX_MONO_LCD_HEIGHT - 1)) {
136 return;
137 }
138
139 page = y / GFX_MONO_LCD_PIXELS_PER_BYTE;
140 pixel_mask = (1 << (y - (page * 8)));
141
142 /*
143 * Read the page containing the pixel in interest, then perform the
144 * requested action on this pixel before writing the page back to the
145 * display.
146 */
147 pixel_value = gfx_mono_framebuffer_get_byte(page, x);
148
149 switch (color) {
150 case GFX_PIXEL_SET:
151 pixel_value |= pixel_mask;
152 break;
153
154 case GFX_PIXEL_CLR:
155 pixel_value &= ~pixel_mask;
156 break;
157
158 case GFX_PIXEL_XOR:
159 pixel_value ^= pixel_mask;
160 break;
161
162 default:
163 break;
164 }
165
166 gfx_mono_framebuffer_put_byte(page, x, pixel_value);
167 }
168
169 /**
170 * \brief Get the pixel value at x,y in framebuffer
171 *
172 * \param[in] x X coordinate of pixel
173 * \param[in] y Y coordinate of pixel
174 * \return Non zero value if pixel is set.
175 *
176 */
gfx_mono_framebuffer_get_pixel(gfx_coord_t x,gfx_coord_t y)177 uint8_t gfx_mono_framebuffer_get_pixel(gfx_coord_t x, gfx_coord_t y)
178 {
179 uint8_t page;
180 uint8_t pixel_mask;
181
182 if ((x > GFX_MONO_LCD_WIDTH - 1) || (y > GFX_MONO_LCD_HEIGHT - 1)) {
183 return 0;
184 }
185
186 page = y / GFX_MONO_LCD_PIXELS_PER_BYTE;
187 pixel_mask = (1 << (y - (page * 8)));
188
189 return gfx_mono_framebuffer_get_byte(page, x) & pixel_mask;
190 }
191
192 /**
193 * \brief Put a byte to the framebuffer
194 *
195 * \param[in] page Page address
196 * \param[in] column Page offset (x coordinate)
197 * \param[in] data Data to be written
198 *
199 * This example will put the value 0xFF to the first byte in the framebuffer
200 * \code
201 gfx_mono_framebuffer_put_byte(0, 0, 0xFF);
202 \endcode
203 */
gfx_mono_framebuffer_put_byte(gfx_coord_t page,gfx_coord_t column,uint8_t data)204 void gfx_mono_framebuffer_put_byte(gfx_coord_t page, gfx_coord_t column,
205 uint8_t data)
206 {
207 *(fbpointer + (page * GFX_MONO_LCD_WIDTH) + column) = data;
208 }
209
210 /**
211 * \brief Get a byte from the framebuffer
212 *
213 * \param[in] page Page address
214 * \param[in] column Page offset (x coordinate)
215 * \return data from LCD controller or framebuffer.
216 *
217 * The following code will read the first byte of the framebuffer
218 * \code
219 data = gfx_mono_framebuffer_get_byte(0, 0);
220 \endcode
221 */
gfx_mono_framebuffer_get_byte(gfx_coord_t page,gfx_coord_t column)222 uint8_t gfx_mono_framebuffer_get_byte(gfx_coord_t page, gfx_coord_t column)
223 {
224 return *(fbpointer + (page * GFX_MONO_LCD_WIDTH) + column);
225 }
226
227 /**
228 * \brief Read/Modify/Write a byte in the framebuffer
229 *
230 * This function will read the byte from the framebuffer and
231 * do a mask operation on the byte according to the pixel operation selected
232 * by the color argument and the pixel mask provided.
233 *
234 * \param[in] page Page address
235 * \param[in] column Page offset (x coordinate)
236 * \param[in] pixel_mask Mask for pixel operation
237 * \param[in] color Pixel operation
238 *
239 * A small example that will XOR the first byte of the framebuffer with 0xAA
240 * \code
241 gfx_mono_framebuffer_mask_byte(0,0,0xAA,GFX_PIXEL_XOR);
242 \endcode
243 */
gfx_mono_framebuffer_mask_byte(gfx_coord_t page,gfx_coord_t column,gfx_mono_color_t pixel_mask,gfx_mono_color_t color)244 void gfx_mono_framebuffer_mask_byte(gfx_coord_t page, gfx_coord_t column,
245 gfx_mono_color_t pixel_mask, gfx_mono_color_t color)
246 {
247 gfx_mono_color_t temp;
248
249 temp = gfx_mono_get_byte(page, column);
250
251 switch (color) {
252 case GFX_PIXEL_SET:
253 temp |= pixel_mask;
254 break;
255
256 case GFX_PIXEL_CLR:
257 temp &= ~pixel_mask;
258 break;
259
260 case GFX_PIXEL_XOR:
261 temp ^= pixel_mask;
262 break;
263 }
264
265 gfx_mono_put_byte(page, column, temp);
266 }
267