大理水控初始版本
diff --git a/lcd/graphs.c b/lcd/graphs.c
new file mode 100644
index 0000000..fb1f034
--- /dev/null
+++ b/lcd/graphs.c
@@ -0,0 +1,120 @@
+/**
+   \file graphs.c
+   \brief Functions relating to graphs. e.g bar graphs etc.
+   \author Andy Gock
+ */ 
+
+/*
+	Copyright (c) 2012, Andy Gock
+
+	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 "glcd.h"
+
+static uint8_t glcd_map(uint8_t x1, uint8_t x2, uint8_t x);
+
+void glcd_bar_graph_horizontal(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t val)
+{
+	if (height < 3) {
+		return;
+	}
+	glcd_draw_rect(x, y, width, height, BLACK);
+	glcd_fill_rect(x+1, y+1, glcd_map(0,width-2,val), height-2 , BLACK);
+}
+
+void glcd_bar_graph_horizontal_no_border(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t val)
+{
+	if (height < 3) {
+		return;
+	}	
+	glcd_fill_rect(x, y, glcd_map(0,width,val), height , BLACK);
+}
+
+void glcd_bar_graph_vertical(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t val)
+{
+	glcd_draw_rect(x, y, width, height, BLACK);
+	glcd_fill_rect(x+1, y+1+glcd_map(0,height-2,255-val), width-2, height-2-glcd_map(0,height-2,255-val), BLACK);
+}
+
+void glcd_bar_graph_vertical_no_border(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t val)
+{
+	glcd_fill_rect(x, y+glcd_map(0,height-2,255-val), width, height-2-glcd_map(0,height-2,255-val), BLACK);
+}
+
+void glcd_scrolling_bar_graph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t val)
+{
+	uint8_t nx, ny;
+	uint8_t color;
+	
+	/* Draw border of graph */
+	glcd_draw_rect(x,y,width,height,BLACK);
+	
+	/* Scroll inner contents left by one pixel width */
+	for (ny = 1; ny <= (height-2); ny++) {
+		/* Redraw each horizontal line */
+		for (nx = 1; nx <= (width-2); nx += 1) {
+			color = glcd_get_pixel(x+nx+1,y+ny);
+			glcd_set_pixel(x+nx,y+ny,color);
+		}
+	}
+	
+	val = val * (height-3) / 255;
+	
+	/* Make sure we're not exceeding the size of box interior */
+	if (val > (height-3)) {
+		val = height - 3;
+	}
+	
+	/* Draw new bar - both black and white portions*/
+	glcd_draw_line(x+width-2,y+height-2,x+width-2,y+height-2-val,BLACK);
+	glcd_draw_line(x+width-2,y+height-3-val,x+width-2,y+1,WHITE);
+	
+	/* Write to display */
+	glcd_write();
+}
+
+void glcd_scrolling_bar_graph_timing(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t val, uint8_t line_width, uint16_t delay)
+{
+	uint8_t n;
+	if (line_width == 0) {
+		line_width = 1;
+	}
+	
+	/* Adjust graph line's width by just running glcd_scrolling_bar_graph() x number of times */
+	/* \todo This should be done differently! */
+	for (n=0; n<line_width; n++) {
+		glcd_scrolling_bar_graph(x,y,width,height,val);
+	}
+	
+	if (delay) {
+		delay_ms(delay);
+	}
+}
+
+static uint8_t glcd_map(uint8_t x1, uint8_t x2, uint8_t x)
+{
+	return x1+(x2-x1)*x/255;	
+}