大理水控初始版本
diff --git a/lcd/glcd.c b/lcd/glcd.c
new file mode 100644
index 0000000..a0f1461
--- /dev/null
+++ b/lcd/glcd.c
@@ -0,0 +1,242 @@
+/**
+ \file glcd.c
+ \author Andy Gock
+ \brief Basic GLCD functions affecting bounding box manipulation,
+ clearing of screen and buffers, and basic scroll functions.
+ */
+
+/*
+ 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 <string.h>
+#include <stdio.h>
+#include "glcd.h"
+
+/** \addtogroup GlobalVars Global Variables
+ * @{
+ */
+
+/**
+ * Screen buffer
+ *
+ * Requires at least one bit for every pixel (e.g 504 bytes for 48x84 LCD)
+ */
+uint8_t glcd_buffer[GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8];
+
+/**
+ * Keeps track of bounding box of area on LCD which need to be
+ * updated next reresh cycle
+ */
+glcd_BoundingBox_t glcd_bbox;
+
+/**
+ * Pointer to screen buffer currently in use.
+ */
+uint8_t* glcd_buffer_selected;
+
+uint8_t glcd_disp_reverse_en = 0;
+
+/**
+ * Pointer to bounding box currently in use.
+ */
+glcd_BoundingBox_t* glcd_bbox_selected;
+
+/** @} */
+
+void glcd_set_reverse_sta(uint8_t sta)
+{
+ if(!sta)
+ glcd_disp_reverse_en = 0;
+ else
+ glcd_disp_reverse_en = 1;
+}
+
+uint8_t glcd_get_reverse_sta(void)
+{
+ return glcd_disp_reverse_en;
+}
+
+void glcd_update_bbox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax)
+{
+ /* Keep and check bounding box within limits of LCD screen dimensions */
+ if(xmin > (GLCD_LCD_WIDTH-1))
+ {
+ xmin = GLCD_LCD_WIDTH-1;
+ }
+ if(xmax > (GLCD_LCD_WIDTH-1))
+ {
+ xmax = GLCD_LCD_WIDTH-1;
+ }
+
+ if(ymin > (GLCD_LCD_HEIGHT-1))
+ {
+ ymin = GLCD_LCD_HEIGHT-1;
+ }
+ if(ymax > (GLCD_LCD_HEIGHT-1))
+ {
+ ymax = GLCD_LCD_HEIGHT-1;
+ }
+
+ /* Update the bounding box size */
+ if(xmin < glcd_bbox_selected->x_min)
+ {
+ glcd_bbox_selected->x_min = xmin;
+ }
+ if(xmax > glcd_bbox_selected->x_max)
+ {
+ glcd_bbox_selected->x_max = xmax;
+ }
+ if(ymin < glcd_bbox_selected->y_min)
+ {
+ glcd_bbox_selected->y_min = ymin;
+ }
+ if(ymax > glcd_bbox_selected->y_max)
+ {
+ glcd_bbox_selected->y_max = ymax;
+ }
+}
+
+void glcd_reset_bbox()
+{
+ /* Used after physically writing to the LCD */
+ glcd_bbox_selected->x_min = GLCD_LCD_WIDTH - 1;
+ glcd_bbox_selected->x_max = 0;
+ glcd_bbox_selected->y_min = GLCD_LCD_HEIGHT -1;
+ glcd_bbox_selected->y_max = 0;
+}
+
+void glcd_bbox_reset()
+{
+ glcd_reset_bbox();
+}
+
+void glcd_bbox_refresh()
+{
+ /* Marks bounding box as entire screen, so on next glcd_write(), it writes the entire buffer to the LCD */
+ glcd_bbox_selected->x_min = 0;
+ glcd_bbox_selected->x_max = GLCD_LCD_WIDTH - 1;
+ glcd_bbox_selected->y_min = 0;
+ glcd_bbox_selected->y_max = GLCD_LCD_HEIGHT -1;
+}
+
+void glcd_clear(void)
+{
+ memset(glcd_buffer_selected, 0x00, GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8);
+ glcd_update_bbox(0,0,GLCD_LCD_WIDTH - 1,GLCD_LCD_HEIGHT - 1);
+ glcd_write();
+}
+
+void glcd_clear_buffer(void)
+{
+ memset(glcd_buffer_selected, 0x00, GLCD_LCD_WIDTH * GLCD_LCD_HEIGHT / 8);
+ glcd_update_bbox(0,0,GLCD_LCD_WIDTH - 1,GLCD_LCD_HEIGHT - 1);
+}
+
+void glcd_select_screen(uint8_t* buffer, glcd_BoundingBox_t* bbox)
+{
+ glcd_buffer_selected = buffer;
+ glcd_bbox_selected = bbox;
+}
+
+void glcd_scroll(int8_t x, int8_t y)
+{
+ /** \todo Skeleton */
+
+ uint8_t row;
+
+ for(row=0; row<(GLCD_LCD_HEIGHT / 8); row++)
+ {
+ uint8_t x;
+ for(x=0; x<GLCD_LCD_WIDTH; x++)
+ {
+
+ }
+ }
+}
+
+void glcd_scroll_line(void)
+{
+ uint8_t y;
+ uint8_t number_of_rows = GLCD_LCD_HEIGHT / 8;
+ for(y=0; y<number_of_rows; y++)
+ {
+ if(y < (number_of_rows - 1))
+ {
+ /* All lines except the last */
+ memcpy(glcd_buffer_selected + y*GLCD_LCD_WIDTH,
+ glcd_buffer_selected + y*GLCD_LCD_WIDTH + GLCD_LCD_WIDTH, GLCD_LCD_WIDTH);
+ }
+ else
+ {
+ /* Last line, clear it */
+ memset(glcd_buffer_selected + (number_of_rows - 1)*GLCD_LCD_WIDTH, 0x00, GLCD_LCD_WIDTH);
+ }
+ }
+ glcd_update_bbox(0,0,GLCD_LCD_WIDTH - 1,GLCD_LCD_HEIGHT - 1);
+}
+
+void glcd_init(void)
+{
+ glcd_HW_init();
+
+ glcd_select_screen(glcd_buffer,&glcd_bbox);
+ glcd_clear();
+}
+void glcd_write()
+{
+
+ uint8_t bank;
+
+ for(bank = 0; bank < GLCD_NUMBER_OF_BANKS; bank++)
+ {
+ /* Each bank is a single row 8 bits tall */
+ uint8_t column;
+
+ if(glcd_bbox_selected->y_min >= (bank+1)*8)
+ {
+ continue; /* Skip the entire bank */
+ }
+
+ if(glcd_bbox_selected->y_max < bank*8)
+ {
+ break; /* No more banks need updating */
+ }
+
+ glcd_set_y_address(bank);
+ glcd_set_x_address(glcd_bbox_selected->x_min);
+
+ for(column = glcd_bbox_selected->x_min; column <= glcd_bbox_selected->x_max; column++)
+ {
+ glcd_data(glcd_buffer_selected[GLCD_NUMBER_OF_COLS * bank + column]);
+ }
+ }
+
+ glcd_reset_bbox();
+
+}
+