First draft
[hackover2013-badge-firmware.git] / drivers / lcd / bitmap / sharpmem / sharpmem.c
1 /**************************************************************************/
2 /*!
3 @file sharpmem.c
4 @author K. Townsend (microBuilder.eu)
5
6 @section DESCRIPTION
7
8 Driver for Sharp Memory Displays.
9
10 This driver uses a bit-banged 3-pin SPI interface. For the SPI
11 interface, the select line (CS) is active high, and the clock
12 line (SCK) is active high.
13
14 Note: The LCD expects the address and data
15 bits to arrive LSB, though the M3 shifts the bits out MSB so they
16 need to be switched in SW first.
17
18 @section EXAMPLE
19 @code
20
21 sharpmemInit();
22 sharpmemEnable(true);
23
24 // Render some text and a line into the image buffer
25 uint32_t i;
26 sharpmemDrawString(1, 10, "5x8 System", Font_System5x8);
27 sharpmemDrawString(1, 20, "7x8 System", Font_System7x8);
28 for (i = 0; i < 96; i++)
29 {
30 sharpmemDrawPixel(i, i);
31 }
32
33 while(1)
34 {
35 // Screen must be refreshed at least once per second
36 sharpmemRefresh();
37 systickDelay(1000);
38 }
39
40 @endcode
41
42 @section LICENSE
43
44 Software License Agreement (BSD License)
45
46 Copyright (c) 2010, microBuilder SARL
47 All rights reserved.
48
49 Redistribution and use in source and binary forms, with or without
50 modification, are permitted provided that the following conditions are met:
51 1. Redistributions of source code must retain the above copyright
52 notice, this list of conditions and the following disclaimer.
53 2. Redistributions in binary form must reproduce the above copyright
54 notice, this list of conditions and the following disclaimer in the
55 documentation and/or other materials provided with the distribution.
56 3. Neither the name of the copyright holders nor the
57 names of its contributors may be used to endorse or promote products
58 derived from this software without specific prior written permission.
59
60 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
61 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
62 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
63 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
64 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
65 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
66 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
67 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
68 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
69 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 */
71 /**************************************************************************/
72 #include <string.h>
73
74 #include "sharpmem.h"
75
76 #include "core/systick/systick.h"
77 #include "core/gpio/gpio.h"
78 #include "drivers/lcd/smallfonts.h"
79
80 #define TOGGLE_VCOM do { _sharpmem_vcom = _sharpmem_vcom ? 0x00 : SHARPMEM_BIT_VCOM; } while(0);
81
82 static uint8_t _sharpmembuffer[(SHARPMEM_LCDWIDTH * SHARPMEM_LCDHEIGHT) / 8];
83 static volatile uint8_t _sharpmem_vcom = SHARPMEM_BIT_VCOM;
84
85 /*************************************************/
86 /* Private Methods */
87 /*************************************************/
88
89 /**************************************************************************/
90 /*!
91 @brief Swaps the bit order from MSB to LSB, since the LCD expects LSB,
92 but the M3 shifts bits out MSB.
93 */
94 /**************************************************************************/
95 uint8_t sharpmemSwap(uint8_t data)
96 {
97 uint8_t out = 0;
98 if (data)
99 {
100 if(data & 0x01) out |= 0x80;
101 if(data & 0x02) out |= 0x40;
102 if(data & 0x04) out |= 0x20;
103 if(data & 0x08) out |= 0x10;
104 if(data & 0x10) out |= 0x08;
105 if(data & 0x20) out |= 0x04;
106 if(data & 0x40) out |= 0x02;
107 if(data & 0x80) out |= 0x01;
108 }
109
110 return out;
111 }
112
113 /*************************************************/
114 void sharpmemSendByte(uint8_t data)
115 {
116 uint8_t i = 0;
117
118 // Make sure clock pin starts low
119 CLR_SCLK;
120
121 // Write from MSB to LSB
122 // LCD expects LSB first
123 for (i=0; i<8; i++)
124 {
125 if (data & 0x80)
126 {
127 SET_MOSI;
128 }
129 else
130 {
131 CLR_MOSI;
132 }
133 // Clock is active high
134 SET_SCLK;
135 data <<= 1;
136 __asm volatile("nop");
137 CLR_SCLK;
138 }
139 }
140
141 /**************************************************************************/
142 /*!
143 @brief Draws a single graphic character using the supplied font
144 */
145 /**************************************************************************/
146 static void sharpmemDrawChar(uint16_t x, uint16_t y, const char c, struct FONT_DEF font)
147 {
148 uint8_t col, column[font.u8Width];
149
150 // Check if the requested character is available
151 if ((c >= font.u8FirstChar) && (c <= font.u8LastChar))
152 {
153 // Retrieve appropriate columns from font data
154 for (col = 0; col < font.u8Width; col++)
155 {
156 column[col] = font.au8FontTable[((c - 32) * font.u8Width) + col]; // Get first column of appropriate character
157 }
158 }
159 else
160 {
161 // Requested character is not available in this font ... send a space instead
162 for (col = 0; col < font.u8Width; col++)
163 {
164 column[col] = 0xFF; // Send solid space
165 }
166 }
167
168 // Render each column
169 uint16_t xoffset, yoffset;
170 for (xoffset = 0; xoffset < font.u8Width; xoffset++)
171 {
172 for (yoffset = 0; yoffset < (font.u8Height + 1); yoffset++)
173 {
174 uint8_t bit = 0x00;
175 bit = (column[xoffset] << (8 - (yoffset + 1))); // Shift current row bit left
176 bit = (bit >> 7); // Shift current row but right (results in 0x01 for black, and 0x00 for white)
177 if (bit)
178 {
179 sharpmemDrawPixel(x + xoffset, y + yoffset);
180 }
181 }
182 }
183 }
184
185 /*************************************************/
186 /* Public Methods */
187 /*************************************************/
188
189 /*************************************************/
190 void sharpmemInit(void)
191 {
192 // Set control pins to output
193 gpioSetDir(SHARPMEM_PORT, SHARPMEM_SCLK_PIN, 1);
194 gpioSetDir(SHARPMEM_PORT, SHARPMEM_MOSI_PIN, 1);
195 gpioSetDir(SHARPMEM_PORT, SHARPMEM_CS_PIN, 1);
196 gpioSetDir(SHARPMEM_PORT, SHARPMEM_DISP_PIN, 1);
197
198 // Set pins to default state
199 CLR_SCLK;
200 CLR_MOSI;
201 CLR_CS;
202 CLR_DISP;
203
204 // Set the vcom bit to a defined state
205 _sharpmem_vcom = SHARPMEM_BIT_VCOM;
206
207 // Clear the display and turn it off by default
208 sharpmemClearScreen();
209 sharpmemEnable(false);
210 }
211
212 /**************************************************************************/
213 /*!
214 @brief Turns the display on or off (memory is retained even when the
215 display is off)
216
217 @param[in] enabled
218 Whether the display should be on (TRUE/1) or off (FALSE/0)
219 */
220 /**************************************************************************/
221 void sharpmemEnable(bool enable)
222 {
223 if (enable)
224 {
225 SET_DISP;
226 }
227 else
228 {
229 CLR_DISP;
230 }
231 }
232
233 /**************************************************************************/
234 /*!
235 @brief Draws a single pixel in image buffer
236
237 @param[in] x
238 The x position (0 based)
239 @param[in] y
240 The y position (0 based)
241 */
242 /**************************************************************************/
243 void sharpmemDrawPixel(uint16_t x, uint16_t y)
244 {
245 if ((x >= SHARPMEM_LCDWIDTH) || (y >= SHARPMEM_LCDHEIGHT))
246 return;
247
248 _sharpmembuffer[(y*SHARPMEM_LCDWIDTH + x) /8] |= (1 << x % 8);
249 }
250
251 /**************************************************************************/
252 /*!
253 @brief Clears a single pixel in image buffer
254
255 @param[in] x
256 The x position (0 based)
257 @param[in] y
258 The y position (0 based)
259 */
260 /**************************************************************************/
261 void sharpmemClearPixel(uint16_t x, uint16_t y)
262 {
263 if ((x >= SHARPMEM_LCDWIDTH) || (y >= SHARPMEM_LCDHEIGHT))
264 return;
265
266 _sharpmembuffer[(y*SHARPMEM_LCDWIDTH + x) /8] &= ~(1 << x % 8);
267 }
268
269 /**************************************************************************/
270 /*!
271 @brief Gets the value (1 or 0) of the specified pixel from the buffer
272
273 @param[in] x
274 The x position (0 based)
275 @param[in] y
276 The y position (0 based)
277
278 @return 1 if the pixel is enabled, 0 if disabled
279 */
280 /**************************************************************************/
281 uint8_t sharpmemGetPixel(uint16_t x, uint16_t y)
282 {
283 if ((x >=SHARPMEM_LCDWIDTH) || (y >=SHARPMEM_LCDHEIGHT)) return 0;
284 return _sharpmembuffer[(y*SHARPMEM_LCDWIDTH + x) /8] & (1 << x % 8) ? 1 : 0;
285 }
286
287 /**************************************************************************/
288 /*!
289 @brief Clears the screen
290 */
291 /**************************************************************************/
292 void sharpmemClearScreen()
293 {
294 memset(_sharpmembuffer, 0x00, (SHARPMEM_LCDWIDTH * SHARPMEM_LCDHEIGHT) / 8);
295 // Send the clear screen command rather than doing a HW refresh (quicker)
296 SET_CS;
297 sharpmemSendByte(_sharpmem_vcom | SHARPMEM_BIT_CLEAR);
298 sharpmemSendByte(0x00);
299 TOGGLE_VCOM;
300 CLR_CS;
301 }
302
303 /**************************************************************************/
304 /*!
305 @brief Renders the contents of the pixel buffer on the LCD
306 */
307 /**************************************************************************/
308 void sharpmemRefresh(void)
309 {
310 uint16_t i, totalbytes, currentline, oldline;
311 totalbytes = (SHARPMEM_LCDWIDTH * SHARPMEM_LCDHEIGHT) / 8;
312
313 // Send the write command
314 SET_CS;
315 sharpmemSendByte(SHARPMEM_BIT_WRITECMD | _sharpmem_vcom);
316 TOGGLE_VCOM;
317
318 // Send the address for line 1
319 oldline = currentline = 1;
320 sharpmemSendByte(sharpmemSwap(currentline));
321
322 // Send image buffer
323 for (i=0; i<totalbytes; i++)
324 {
325 sharpmemSendByte(sharpmemSwap(_sharpmembuffer[i]));
326 currentline = ((i+1)/(SHARPMEM_LCDWIDTH/8)) + 1;
327 if(currentline != oldline)
328 {
329 // Send end of line and address bytes
330 sharpmemSendByte(0x00);
331 if (currentline < SHARPMEM_LCDHEIGHT)
332 {
333 sharpmemSendByte(sharpmemSwap(currentline));
334 }
335 oldline = currentline;
336 }
337 }
338
339 // Send another trailing 8 bits for the last line
340 sharpmemSendByte(0x00);
341 CLR_CS;
342 }
343
344 /**************************************************************************/
345 /*!
346 @brief Draws a string using the supplied font data.
347
348 @param[in] x
349 Starting x co-ordinate
350 @param[in] y
351 Starting y co-ordinate
352 @param[in] text
353 The string to render
354 @param[in] font
355 Pointer to the FONT_DEF to use when drawing the string
356
357 @section Example
358
359 @code
360
361 #include "drivers/lcd/bitmap/sharpmem/sharpmem.h"
362 #include "drivers/lcd/smallfonts.h"
363
364 // Configure the pins and initialise the LCD screen
365 sharpmemInit();
366
367 // Render some text on the screen
368 sharpmemDrawString(1, 10, "5x8 System", Font_System5x8);
369 sharpmemDrawString(1, 20, "7x8 System", Font_System7x8);
370
371 // Refresh the screen to see the results
372 sharpmemRefresh();
373
374 @endcode
375 */
376 /**************************************************************************/
377 void sharpmemDrawString(uint16_t x, uint16_t y, const char* text, struct FONT_DEF font)
378 {
379 uint8_t l;
380 for (l = 0; l < strlen(text); l++)
381 {
382 sharpmemDrawChar(x + (l * (font.u8Width + 1)), y, text[l], font);
383 }
384 }
This page took 0.060437 seconds and 5 git commands to generate.