Created
September 22, 2015 00:12
-
-
Save TareObjects/39b26e7ecfd8a32893b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| $Id:$ | |
| ST7565 LCD library! | |
| Copyright (C) 2010 Limor Fried, Adafruit Industries | |
| This library is free software; you can redistribute it and/or | |
| modify it under the terms of the GNU Lesser General Public | |
| License as published by the Free Software Foundation; either | |
| version 2.1 of the License, or (at your option) any later version. | |
| This library is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public | |
| License along with this library; if not, write to the Free Software | |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| // some of this code was written by <cstone@pobox.com> originally; it is in the public domain. | |
| // this source is modified for AQM1284 by kkurahashi | |
| */ | |
| #include <stdlib.h> | |
| #include "ST7565.h" | |
| #define ST7565_STARTBYTES 1 | |
| #define _BV(bit) (1 << (bit)) | |
| unsigned char is_reversed = 0; | |
| // a handy reference to where the pages are on the screen | |
| const unsigned char pagemap[] = { 5, 4, 3, 2, 1, 0, 7, 6}; | |
| // a 5x7 font table | |
| const extern unsigned char font[]; | |
| // the memory buffer for the LCD | |
| unsigned char st7565_buffer[1024] = { | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x3, 0x7, 0xF, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x7F, 0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x1F, 0x3F, 0x70, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x6, 0x0, 0x0, 0x0, 0x3, 0x3, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xF, 0x7, 0x7, | |
| 0x7, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x3F, | |
| 0x70, 0x60, 0x60, 0x60, 0x60, 0x30, 0x7F, 0x3F, 0x0, 0x0, 0x1F, 0x3F, 0x70, 0x60, 0x60, 0x60, | |
| 0x60, 0x39, 0xFF, 0xFF, 0x0, 0x6, 0x1F, 0x39, 0x60, 0x60, 0x60, 0x60, 0x30, 0x3F, 0x7F, 0x0, | |
| 0x0, 0x60, 0xFF, 0xFF, 0x60, 0x60, 0x0, 0x7F, 0x7F, 0x70, 0x60, 0x60, 0x40, 0x0, 0x7F, 0x7F, | |
| 0x0, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x60, 0xFF, 0xFF, | |
| 0x60, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x80, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xE7, 0xE7, 0xE3, | |
| 0xF3, 0xF9, 0xFF, 0xFF, 0xFF, 0xF7, 0x7, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, | |
| 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x0, 0x0, 0x0, 0xC0, | |
| 0xE0, 0x60, 0x20, 0x20, 0x60, 0xE0, 0xE0, 0xE0, 0x0, 0x0, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x60, | |
| 0x60, 0xE0, 0xE0, 0xE0, 0x0, 0x0, 0x80, 0xC0, 0x60, 0x60, 0x20, 0x60, 0x60, 0xE0, 0xE0, 0x0, | |
| 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xE0, | |
| 0x60, 0x60, 0x60, 0x60, 0xE0, 0x80, 0x0, 0x0, 0x0, 0xE0, 0xE0, 0x0, 0x0, 0x0, 0xE0, 0xE0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x3, 0x7, 0x1F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF1, 0xE3, | |
| 0xE3, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFC, 0x7F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, | |
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xE0, 0x80, 0x0, 0x0, 0x0, 0xC, | |
| 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7F, 0x7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, | |
| 0xF8, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, | |
| 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xE0, 0xC0, 0xC0, 0xC0, 0xFF, 0x7F, 0x0, 0x0, 0x1E, 0x7F, | |
| 0xE1, 0xC0, 0xC0, 0xC0, 0xC0, 0x61, 0xFF, 0xFF, 0x0, 0x0, 0xFE, 0xFF, 0x1, 0x0, 0x0, 0x0, | |
| 0xFF, 0xFF, 0x0, 0x0, 0x21, 0xF9, 0xF8, 0xDC, 0xCC, 0xCF, 0x7, 0x0, 0xC0, 0xFF, 0xFF, 0xC0, | |
| 0x80, 0x0, 0xFF, 0xFF, 0xC0, 0xC0, 0x80, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x1F, 0x7F, 0xF9, | |
| 0xC8, 0xC8, 0xC8, 0xC8, 0x79, 0x39, 0x0, 0x0, 0x71, 0xF9, 0xD8, 0xCC, 0xCE, 0x47, 0x3, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xC0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, | |
| 0xC0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, | |
| 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, | |
| 0xC0, 0x80, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, | |
| 0x0, 0x0, 0xC0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0, 0x80, 0xC0, | |
| 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x0, 0x0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |
| 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,}; | |
| // reduces how much is refreshed, which speeds it up! | |
| // originally derived from Steve Evans/JCW's mod but cleaned up and | |
| // optimized | |
| // #define enablePartialUpdate | |
| #ifdef enablePartialUpdate | |
| static unsigned char xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax; | |
| #endif | |
| static void updateBoundingBox(unsigned char xmin, unsigned char ymin, unsigned char xmax, unsigned char ymax) { | |
| #ifdef enablePartialUpdate | |
| if (xmin < xUpdateMin) xUpdateMin = xmin; | |
| if (xmax > xUpdateMax) xUpdateMax = xmax; | |
| if (ymin < yUpdateMin) yUpdateMin = ymin; | |
| if (ymax > yUpdateMax) yUpdateMax = ymax; | |
| #endif | |
| } | |
| void ST7565::drawbitmap(unsigned char x, unsigned char y, | |
| const unsigned char *bitmap, unsigned char w, unsigned char h, | |
| unsigned char color) { | |
| for (unsigned char j=0; j<h; j++) { | |
| for (unsigned char i=0; i<w; i++ ) { | |
| if (pgm_read_byte(bitmap + i + (j/8)*w) & _BV(j%8)) { | |
| my_setpixel(x+i, y+j, color); | |
| } | |
| } | |
| } | |
| updateBoundingBox(x, y, x+w, y+h); | |
| } | |
| void ST7565::drawstring(unsigned char x, unsigned char line, char *c) { | |
| while (c[0] != 0) { | |
| drawchar(x, line, c[0]); | |
| c++; | |
| x += 6; // 6 pixels wide | |
| if (x + 6 >= LCDWIDTH) { | |
| x = 0; // ran out of this line | |
| line++; | |
| } | |
| if (line >= (LCDHEIGHT/8)) | |
| return; // ran out of space :( | |
| } | |
| } | |
| void ST7565::drawstring_P(unsigned char x, unsigned char line, const char *str) { | |
| while (1) { | |
| char c = pgm_read_byte(str++); | |
| if (! c) | |
| return; | |
| drawchar(x, line, c); | |
| x += 6; // 6 pixels wide | |
| if (x + 6 >= LCDWIDTH) { | |
| x = 0; // ran out of this line | |
| line++; | |
| } | |
| if (line >= (LCDHEIGHT/8)) | |
| return; // ran out of space :( | |
| } | |
| } | |
| void ST7565::drawchar(unsigned char x, unsigned char line, char c) { | |
| for (unsigned char i =0; i<5; i++ ) { | |
| st7565_buffer[x + (line*128) ] = pgm_read_byte(font+(c*5)+i); | |
| x++; | |
| } | |
| updateBoundingBox(x, line*8, x+5, line*8 + 8); | |
| } | |
| // bresenham's algorithm - thx wikpedia | |
| void ST7565::drawline(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, | |
| unsigned char color) { | |
| unsigned char steep = abs(y1 - y0) > abs(x1 - x0); | |
| if (steep) { | |
| swap(x0, y0); | |
| swap(x1, y1); | |
| } | |
| if (x0 > x1) { | |
| swap(x0, x1); | |
| swap(y0, y1); | |
| } | |
| // much faster to put the test here, since we've already sorted the points | |
| updateBoundingBox(x0, y0, x1, y1); | |
| unsigned char dx, dy; | |
| dx = x1 - x0; | |
| dy = abs(y1 - y0); | |
| int8_t err = dx / 2; | |
| int8_t ystep; | |
| if (y0 < y1) { | |
| ystep = 1; | |
| } else { | |
| ystep = -1;} | |
| for (; x0<=x1; x0++) { | |
| if (steep) { | |
| my_setpixel(y0, x0, color); | |
| } else { | |
| my_setpixel(x0, y0, color); | |
| } | |
| err -= dy; | |
| if (err < 0) { | |
| y0 += ystep; | |
| err += dx; | |
| } | |
| } | |
| } | |
| // filled rectangle | |
| void ST7565::fillrect(unsigned char x, unsigned char y, unsigned char w, unsigned char h, | |
| unsigned char color) { | |
| // stupidest version - just pixels - but fast with internal buffer! | |
| for (unsigned char i=x; i<x+w; i++) { | |
| for (unsigned char j=y; j<y+h; j++) { | |
| my_setpixel(i, j, color); | |
| } | |
| } | |
| updateBoundingBox(x, y, x+w, y+h); | |
| } | |
| // draw a rectangle | |
| void ST7565::drawrect(unsigned char x, unsigned char y, unsigned char w, unsigned char h, | |
| unsigned char color) { | |
| // stupidest version - just pixels - but fast with internal buffer! | |
| for (unsigned char i=x; i<x+w; i++) { | |
| my_setpixel(i, y, color); | |
| my_setpixel(i, y+h-1, color); | |
| } | |
| for (unsigned char i=y; i<y+h; i++) { | |
| my_setpixel(x, i, color); | |
| my_setpixel(x+w-1, i, color); | |
| } | |
| updateBoundingBox(x, y, x+w, y+h); | |
| } | |
| // draw a circle outline | |
| void ST7565::drawcircle(unsigned char x0, unsigned char y0, unsigned char r, | |
| unsigned char color) { | |
| updateBoundingBox(x0-r, y0-r, x0+r, y0+r); | |
| int8_t f = 1 - r; | |
| int8_t ddF_x = 1; | |
| int8_t ddF_y = -2 * r; | |
| int8_t x = 0; | |
| int8_t y = r; | |
| my_setpixel(x0, y0+r, color); | |
| my_setpixel(x0, y0-r, color); | |
| my_setpixel(x0+r, y0, color); | |
| my_setpixel(x0-r, y0, color); | |
| while (x<y) { | |
| if (f >= 0) { | |
| y--; | |
| ddF_y += 2; | |
| f += ddF_y; | |
| } | |
| x++; | |
| ddF_x += 2; | |
| f += ddF_x; | |
| my_setpixel(x0 + x, y0 + y, color); | |
| my_setpixel(x0 - x, y0 + y, color); | |
| my_setpixel(x0 + x, y0 - y, color); | |
| my_setpixel(x0 - x, y0 - y, color); | |
| my_setpixel(x0 + y, y0 + x, color); | |
| my_setpixel(x0 - y, y0 + x, color); | |
| my_setpixel(x0 + y, y0 - x, color); | |
| my_setpixel(x0 - y, y0 - x, color); | |
| } | |
| } | |
| void ST7565::fillcircle(unsigned char x0, unsigned char y0, unsigned char r, | |
| unsigned char color) { | |
| updateBoundingBox(x0-r, y0-r, x0+r, y0+r); | |
| int8_t f = 1 - r; | |
| int8_t ddF_x = 1; | |
| int8_t ddF_y = -2 * r; | |
| int8_t x = 0; | |
| int8_t y = r; | |
| for (unsigned char i=y0-r; i<=y0+r; i++) { | |
| my_setpixel(x0, i, color); | |
| } | |
| while (x<y) { | |
| if (f >= 0) { | |
| y--; | |
| ddF_y += 2; | |
| f += ddF_y; | |
| } | |
| x++; | |
| ddF_x += 2; | |
| f += ddF_x; | |
| for (unsigned char i=y0-y; i<=y0+y; i++) { | |
| my_setpixel(x0+x, i, color); | |
| my_setpixel(x0-x, i, color); | |
| } | |
| for (unsigned char i=y0-x; i<=y0+x; i++) { | |
| my_setpixel(x0+y, i, color); | |
| my_setpixel(x0-y, i, color); | |
| } | |
| } | |
| } | |
| void ST7565::my_setpixel(unsigned char x, unsigned char y, unsigned char color) { | |
| if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) | |
| return; | |
| // x is which column | |
| if (color) | |
| st7565_buffer[x+ (y/8)*128] |= _BV(7-(y%8)); | |
| else | |
| st7565_buffer[x+ (y/8)*128] &= ~_BV(7-(y%8)); | |
| } | |
| // the most basic function, set a single pixel | |
| void ST7565::setpixel(unsigned char x, unsigned char y, unsigned char color) { | |
| if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) | |
| return; | |
| // x is which column | |
| if (color) | |
| st7565_buffer[x+ (y/8)*128] |= _BV(7-(y%8)); | |
| else | |
| st7565_buffer[x+ (y/8)*128] &= ~_BV(7-(y%8)); | |
| updateBoundingBox(x,y,x,y); | |
| } | |
| // the most basic function, get a single pixel | |
| unsigned char ST7565::getpixel(unsigned char x, unsigned char y) { | |
| if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) | |
| return 0; | |
| return (st7565_buffer[x+ (y/8)*128] >> (7-(y%8))) & 0x1; | |
| } | |
| void ST7565::begin(unsigned char contrast) { | |
| st7565_init(); | |
| st7565_command(CMD_DISPLAY_ON); | |
| st7565_command(CMD_SET_ALLPTS_NORMAL); | |
| st7565_set_brightness(contrast); | |
| } | |
| void ST7565::st7565_init(void) { | |
| // set pin directions | |
| pinMode(sid, OUTPUT); | |
| pinMode(sclk, OUTPUT); | |
| pinMode(a0, OUTPUT); | |
| pinMode(rst, OUTPUT); | |
| pinMode(cs, OUTPUT); | |
| // toggle RST low to reset; CS low so it'll listen to us | |
| if (cs > 0) | |
| digitalWrite(cs, LOW); | |
| digitalWrite(rst, LOW); | |
| delay(500); | |
| digitalWrite(rst, HIGH); | |
| // LCD bias select | |
| st7565_command(CMD_SET_BIAS_7); | |
| // ADC select | |
| st7565_command(CMD_SET_ADC_NORMAL); | |
| // SHL select | |
| st7565_command(CMD_SET_COM_NORMAL); | |
| // Initial display line | |
| st7565_command(CMD_SET_DISP_START_LINE); | |
| // turn on voltage converter (VC=1, VR=0, VF=0) | |
| st7565_command(CMD_SET_POWER_CONTROL | 0x4); | |
| // wait for 50% rising | |
| delay(50); | |
| // turn on voltage regulator (VC=1, VR=1, VF=0) | |
| st7565_command(CMD_SET_POWER_CONTROL | 0x6); | |
| // wait >=50ms | |
| delay(50); | |
| // turn on voltage follower (VC=1, VR=1, VF=1) | |
| st7565_command(CMD_SET_POWER_CONTROL | 0x7); | |
| // wait | |
| delay(10); | |
| // set lcd operating voltage (regulator resistor, ref voltage resistor) | |
| st7565_command(CMD_SET_RESISTOR_RATIO | 0x6); | |
| // initial display line | |
| // set page address | |
| // set column address | |
| // write display data | |
| // set up a bounding box for screen updates | |
| updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); | |
| } | |
| inline void ST7565::spiwrite(unsigned char c) { | |
| shiftOut(sid, sclk, MSBFIRST, c); | |
| /* | |
| int8_t i; | |
| for (i=7; i>=0; i--) { | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(i)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| } | |
| */ | |
| /* | |
| // loop unwrapped! too fast doesnt work :( | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(7)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(6)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(5)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(4)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(3)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(2)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(1)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| SCLK_PORT &= ~_BV(SCLK); | |
| if (c & _BV(0)) | |
| SID_PORT |= _BV(SID); | |
| else | |
| SID_PORT &= ~_BV(SID); | |
| SCLK_PORT |= _BV(SCLK); | |
| */ | |
| } | |
| void ST7565::st7565_command(unsigned char c) { | |
| digitalWrite(a0, LOW); | |
| spiwrite(c); | |
| } | |
| void ST7565::st7565_data(unsigned char c) { | |
| digitalWrite(a0, HIGH); | |
| spiwrite(c); | |
| } | |
| void ST7565::st7565_set_brightness(unsigned char val) { | |
| st7565_command(0x23); // Vo voltage resistor ratio set | |
| st7565_command(CMD_SET_VOLUME_FIRST); | |
| st7565_command(CMD_SET_VOLUME_SECOND | (val & 0x3f)); | |
| } | |
| void ST7565::display(void) { | |
| unsigned char col, maxcol, p; | |
| /* | |
| Serial.print("Refresh ("); Serial.print(xUpdateMin, DEC); | |
| Serial.print(", "); Serial.print(xUpdateMax, DEC); | |
| Serial.print(","); Serial.print(yUpdateMin, DEC); | |
| Serial.print(", "); Serial.print(yUpdateMax, DEC); Serial.println(")"); | |
| */ | |
| for(p = 0; p < 8; p++) { | |
| /* | |
| putstring("new page! "); | |
| uart_putw_dec(p); | |
| putstring_nl(""); | |
| */ | |
| #ifdef enablePartialUpdate | |
| // check if this page is part of update | |
| if ( yUpdateMin >= ((p+1)*8) ) { | |
| continue; // nope, skip it! | |
| } | |
| if (yUpdateMax < p*8) { | |
| break; | |
| } | |
| #endif | |
| st7565_command(CMD_SET_PAGE | pagemap[p]); | |
| #ifdef enablePartialUpdate | |
| col = xUpdateMin; | |
| maxcol = xUpdateMax; | |
| #else | |
| // start at the beginning of the row | |
| col = 0; | |
| maxcol = LCDWIDTH-1; | |
| #endif | |
| st7565_command(CMD_SET_COLUMN_LOWER | ((col+ST7565_STARTBYTES) & 0xf)); | |
| st7565_command(CMD_SET_COLUMN_UPPER | (((col+ST7565_STARTBYTES) >> 4) & 0x0F)); | |
| st7565_command(CMD_RMW); | |
| for(; col <= maxcol; col++) { | |
| //uart_putw_dec(col); | |
| //uart_putchar(' '); | |
| st7565_data(st7565_buffer[(128*p)+col]); | |
| } | |
| } | |
| #ifdef enablePartialUpdate | |
| xUpdateMin = LCDWIDTH - 1; | |
| xUpdateMax = 0; | |
| yUpdateMin = LCDHEIGHT-1; | |
| yUpdateMax = 0; | |
| #endif | |
| } | |
| // clear everything | |
| void ST7565::clear(void) { | |
| memset(st7565_buffer, 0, 1024); | |
| updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); | |
| } | |
| // this doesnt touch the buffer, just clears the display RAM - might be handy | |
| void ST7565::clear_display(void) { | |
| unsigned char p, c; | |
| for(p = 0; p < 8; p++) { | |
| /* | |
| putstring("new page! "); | |
| uart_putw_dec(p); | |
| putstring_nl(""); | |
| */ | |
| st7565_command(CMD_SET_PAGE | p); | |
| for(c = 0; c < 129; c++) { | |
| //uart_putw_dec(c); | |
| //uart_putchar(' '); | |
| st7565_command(CMD_SET_COLUMN_LOWER | (c & 0xf)); | |
| st7565_command(CMD_SET_COLUMN_UPPER | ((c >> 4) & 0xf)); | |
| st7565_data(0x0); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment