大理水控初始版本
diff --git a/lcd/graphics.c b/lcd/graphics.c
new file mode 100644
index 0000000..dec75c0
--- /dev/null
+++ b/lcd/graphics.c
@@ -0,0 +1,309 @@
+/**
+ \file graphics.c
+ \brief Functions relating to graphics. e.g drawing lines, rectangles, circles etc.
+ \author Andy Gock
+
+ Some functions based on Limor Fried's PCD8544 Arduino library.
+
+ */
+
+/*
+ Copyright (c) 2012, Andy Gock
+
+ Copyright (c) 2012, Adafruit Industries
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Andy Gock nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL ANDY GOCK BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "glcd.h"
+
+/* Based on PCD8544 library by Limor Fried */
+void glcd_set_pixel(uint8_t x, uint8_t y, uint8_t color) {
+ if (x > (GLCD_LCD_WIDTH-1) || y > (GLCD_LCD_HEIGHT-1)) {
+ /* don't do anything if x/y is outside bounds of display size */
+ return;
+ }
+
+ if (color) {
+ /* Set black */
+ glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] |= ( 1 << (y%8));
+ } else {
+ /* Set white */
+ glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] &= ~ (1 << (y%8));
+ }
+
+ glcd_update_bbox(x,y,x,y);
+}
+
+/* Based on PCD8544 library by Limor Fried */
+uint8_t glcd_get_pixel(uint8_t x, uint8_t y) {
+ if ((x >= GLCD_LCD_WIDTH) || (y >= GLCD_LCD_HEIGHT)) {
+ return 0;
+ }
+
+ if ( glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] & ( 1 << (y%8)) ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void glcd_invert_pixel(uint8_t x, uint8_t y) {
+ if ((x >= GLCD_LCD_WIDTH) || (y >= GLCD_LCD_HEIGHT)) {
+ return;
+ }
+ glcd_update_bbox(x,y,x,y);
+ glcd_buffer[x+ (y/8)*GLCD_LCD_WIDTH] ^= ( 1 << (y%8));
+}
+
+/* Bresenham's algorithm - based on PCD8544 library Limor Fried */
+void glcd_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color) {
+ uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
+ uint8_t dx, dy;
+ int8_t err;
+ int8_t ystep;
+
+ if (steep) {
+ swap(x0, y0);
+ swap(x1, y1);
+ }
+
+ if (x0 > x1) {
+ swap(x0, x1);
+ swap(y0, y1);
+ }
+
+ glcd_update_bbox( x0, y0, x1, y1 );
+
+ dx = x1 - x0;
+ dy = abs(y1 - y0);
+
+ err = dx / 2;
+
+ if (y0 < y1) {
+ ystep = 1;
+ } else {
+ ystep = -1;
+ }
+
+ for (; x0<=x1; x0++) {
+ if (steep) {
+ glcd_set_pixel(y0, x0, color);
+ } else {
+ glcd_set_pixel(x0, y0, color);
+ }
+ err -= dy;
+ if (err < 0) {
+ y0 += ystep;
+ err += dx;
+ }
+ }
+}
+
+void glcd_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
+{
+ int16_t i;
+ for (i=x; i<x+w; i++) {
+ int16_t j;
+ for (j=y; j<y+h; j++) {
+ glcd_set_pixel(i, j, color);
+ }
+ }
+ glcd_update_bbox(x, y, x+w-1, y+h-1);
+}
+
+void glcd_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
+{
+ int16_t i;
+ for (i=x; i<x+w; i++) {
+ glcd_set_pixel(i, y, color);
+ glcd_set_pixel(i, y+h-1, color);
+ }
+ for (i=y; i<y+h; i++) {
+ glcd_set_pixel(x, i, color);
+ glcd_set_pixel(x+w-1, i, color);
+ }
+ glcd_update_bbox(x, y, x+w-1, y+h-1);
+}
+
+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)
+{
+ int16_t i, t;
+
+ if (tx == 0) {
+ tx = 1;
+ }
+
+ if (ty == 0) {
+ ty = 1;
+ }
+
+ for (i=x; i<x+w; i++) {
+ /* Top and bottom sides */
+ for (t=0; t<(ty); t++) {
+ glcd_set_pixel(i, y+t, color);
+ glcd_set_pixel(i, y+h-1-t, color);
+ }
+ }
+ for (i=y; i<y+h; i++) {
+ /* Left and right sides */
+ for (t=0; t<(tx); t++) {
+ glcd_set_pixel(x+t, i, color);
+ glcd_set_pixel(x+w-1-t, i, color);
+ }
+ }
+ glcd_update_bbox(x, y, x+w-1, y+h-1);
+}
+
+void glcd_draw_rect_shadow(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
+{
+ glcd_draw_rect(x, y, w, h, color);
+ glcd_draw_line(x+1, y+h, x+w, y+h, color);
+ glcd_draw_line(x+w, y+1, x+w, y+h, color);
+}
+
+void glcd_draw_circle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
+{
+
+ int8_t f = 1 - r;
+ int8_t ddF_x = 1;
+ int8_t ddF_y = -2 * r;
+ int8_t x = 0;
+ int8_t y = r;
+
+ glcd_update_bbox(x0-r, y0-r, x0+r, y0+r);
+
+ glcd_set_pixel(x0, y0+r, color);
+ glcd_set_pixel(x0, y0-r, color);
+ glcd_set_pixel(x0+r, y0, color);
+ glcd_set_pixel(x0-r, y0, color);
+
+ while (x<y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ glcd_set_pixel(x0 + x, y0 + y, color);
+ glcd_set_pixel(x0 - x, y0 + y, color);
+ glcd_set_pixel(x0 + x, y0 - y, color);
+ glcd_set_pixel(x0 - x, y0 - y, color);
+
+ glcd_set_pixel(x0 + y, y0 + x, color);
+ glcd_set_pixel(x0 - y, y0 + x, color);
+ glcd_set_pixel(x0 + y, y0 - x, color);
+ glcd_set_pixel(x0 - y, y0 - x, color);
+
+ }
+}
+
+void glcd_fill_circle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
+{
+
+ int8_t f = 1 - r;
+ int8_t ddF_x = 1;
+ int8_t ddF_y = -2 * r;
+ int8_t x = 0;
+ int8_t y = r;
+
+ int16_t i;
+
+ glcd_update_bbox(x0-r, y0-r, x0+r, y0+r);
+
+ for (i=y0-r; i<=y0+r; i++) {
+ glcd_set_pixel(x0, i, color);
+ }
+
+ while (x < y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ for (i=y0-y; i<=y0+y; i++) {
+ glcd_set_pixel(x0+x, i, color);
+ glcd_set_pixel(x0-x, i, color);
+ }
+ for (i=y0-x; i<=y0+x; i++) {
+ glcd_set_pixel(x0+y, i, color);
+ glcd_set_pixel(x0-y, i, color);
+ }
+ }
+}
+
+void glcd_invert_area(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
+{
+ uint8_t xx, yy;
+ for (xx = x; xx < (x+w); xx++) {
+ /* Loop through each partial column */
+ for (yy = y; yy < (y+h); yy++) {
+ /* Go down and invert every pixel */
+ glcd_invert_pixel(xx,yy);
+ }
+ }
+}
+
+void glcd_draw_bitmap(const unsigned char *data)
+{
+
+#if 0
+ /* Testing purposes only: Writing to the LCD right away (not for AVR) */
+ /* Normally, we do not do this, we just write to the screen buffer */
+ uint8_t *original_buffer;
+
+ /* Save the location of original screen buffer */
+ original_buffer = glcd_buffer_selected;
+
+ /* Use bitmap location as screen buffer (this won't work when using AVR8 PGM_P) */
+ glcd_select_screen((uint8_t *)data, glcd_bbox_selected);
+
+ /* Make sure we write the entre display */
+ glcd_bbox_refresh();
+ glcd_write();
+
+ /* Restore the screen buffer back to original */
+ glcd_select_screen(original_buffer, glcd_bbox_selected);
+#endif
+
+ /* Copy bitmap data to the screen buffer */
+#if defined(GLCD_DEVICE_AVR8)
+ memcpy_P(glcd_buffer_selected, data, (GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8));
+#else
+ memcpy(glcd_buffer_selected, data, (GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8));
+#endif
+
+ glcd_bbox_refresh();
+}