Advertisement
JohnWasser

PCD8544.cpp w/inverse text

Jun 2nd, 2011
343
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.48 KB | None | 0 0
  1. /*
  2.  * PCD8544 - Interface with Philips PCD8544 (or compatible) LCDs.
  3.  *
  4.  * Copyright (c) 2010 Carlos Rodrigues <cefrodrigues@gmail.com>
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  7.  * of this software and associated documentation files (the "Software"), to deal
  8.  * in the Software without restriction, including without limitation the rights
  9.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10.  * copies of the Software, and to permit persons to whom the Software is
  11.  * furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included in
  14.  * all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22.  * THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. #include "PCD8544.h"
  27.  
  28. #include <WProgram.h>
  29. #include <avr/pgmspace.h>
  30.  
  31.  
  32. #define PCD8544_CMD  LOW
  33. #define PCD8544_DATA HIGH
  34.  
  35.  
  36. /*
  37.  * If this was a ".h", it would get added to sketches when using
  38.  * the "Sketch -> Import Library..." menu on the Arduino IDE...
  39.  */
  40. #include "charset.cpp"
  41.  
  42.  
  43. PCD8544::PCD8544(unsigned char sclk, unsigned char sdin,
  44.                  unsigned char dc, unsigned char reset,
  45.                  unsigned char sce):
  46.     pin_sclk(sclk),
  47.     pin_sdin(sdin),
  48.     pin_dc(dc),
  49.     pin_reset(reset),
  50.     pin_sce(sce)
  51. {}
  52.  
  53.  
  54. void PCD8544::begin(unsigned char width, unsigned char height, unsigned char model)
  55. {
  56.     this->width = width;
  57.     this->height = height;
  58.  
  59.     this->column = 0;
  60.     this->line = 0;
  61.  
  62.     // Sanitize the custom glyphs...
  63.     memset(this->custom, 0, sizeof(this->custom));
  64.  
  65.     // All pins are outputs (these displays cannot be read)...
  66.     pinMode(this->pin_sclk, OUTPUT);
  67.     pinMode(this->pin_sdin, OUTPUT);
  68.     pinMode(this->pin_dc, OUTPUT);
  69.     pinMode(this->pin_reset, OUTPUT);
  70.     pinMode(this->pin_sce, OUTPUT);
  71.  
  72.     // Reset the controller state...
  73.     digitalWrite(this->pin_reset, HIGH);
  74.     digitalWrite(this->pin_sce, HIGH);
  75.     digitalWrite(this->pin_reset, LOW);
  76.     delay(100);  
  77.     digitalWrite(this->pin_reset, HIGH);
  78.  
  79.     // Set the LCD parameters...
  80.     this->send(PCD8544_CMD, 0x21);  // extended instruction set control (H=1)
  81.     this->send(PCD8544_CMD, 0x13);  // bias system (1:48)
  82.  
  83.     if (model == CHIP_ST7576) {
  84.         this->send(PCD8544_CMD, 0xe0);  // higher Vop, too faint at default
  85.         this->send(PCD8544_CMD, 0x05);  // partial display mode
  86.     } else {
  87.         this->send(PCD8544_CMD, 0xc2);  // default Vop (3.06 + 66 * 0.06 = 7V)
  88.     }
  89.  
  90.     this->send(PCD8544_CMD, 0x20);  // extended instruction set control (H=0)
  91.     this->send(PCD8544_CMD, 0x09);  // all display segments on
  92.  
  93.     // Clear RAM contents...
  94.     this->clear();
  95.  
  96.     // Activate LCD...
  97.     this->send(PCD8544_CMD, 0x08);  // display blank
  98.     this->send(PCD8544_CMD, 0x0c);  // normal mode (0x0d = inverse mode)
  99.     delay(100);
  100.  
  101.     // Place the cursor at the origin...
  102.     this->send(PCD8544_CMD, 0x80);
  103.     this->send(PCD8544_CMD, 0x40);
  104.    
  105.     // Clear the Inverse Text flag
  106.     this->inverseText = false;
  107. }
  108.  
  109.  
  110. void PCD8544::stop()
  111. {
  112.     this->clear();
  113.     this->setPower(false);
  114. }
  115.  
  116.  
  117. void PCD8544::clear()
  118. {
  119.     this->setCursor(0, 0);
  120.  
  121.     for (unsigned short i = 0; i < this->width * (this->height/8); i++) {
  122.         this->send(PCD8544_DATA, 0x00);
  123.     }
  124.  
  125.     this->setCursor(0, 0);
  126. }
  127.  
  128.  
  129. void PCD8544::clearLine()
  130. {
  131.     this->setCursor(0, this->line);
  132.  
  133.     for (unsigned char i = 0; i < this->width; i++) {
  134.         this->send(PCD8544_DATA, 0x00);
  135.     }
  136.  
  137.     this->setCursor(0, this->line);
  138. }
  139.  
  140.  
  141. void PCD8544::setPower(bool on)
  142. {
  143.     this->send(PCD8544_CMD, on ? 0x20 : 0x24);
  144. }
  145.  
  146.  
  147. inline void PCD8544::display()
  148. {
  149.     this->setPower(true);
  150. }
  151.  
  152.  
  153. inline void PCD8544::noDisplay()
  154. {
  155.     this->setPower(false);
  156. }
  157.  
  158.  
  159. void PCD8544::setInverse(bool inverse)
  160. {
  161.     this->send(PCD8544_CMD, inverse ? 0x0d : 0x0c);
  162. }
  163.  
  164. void PCD8544::setInverseText(bool inverse)
  165. {
  166.     this->inverseText = inverse;
  167. }
  168.  
  169.  
  170. void PCD8544::home()
  171. {
  172.     this->setCursor(0, this->line);
  173. }
  174.  
  175.  
  176. void PCD8544::setCursor(unsigned char column, unsigned char line)
  177. {
  178.     this->column = (column % this->width);
  179.     this->line = (line % (this->height/9 + 1));
  180.  
  181.     this->send(PCD8544_CMD, 0x80 | this->column);
  182.     this->send(PCD8544_CMD, 0x40 | this->line);
  183. }
  184.  
  185.  
  186. void PCD8544::createChar(unsigned char chr, const unsigned char *glyph)
  187. {
  188.     // ASCII 0-31 only...
  189.     if (chr >= ' ') {
  190.         return;
  191.     }
  192.    
  193.     this->custom[chr] = glyph;
  194. }
  195.  
  196.  
  197. void PCD8544::write(unsigned char chr)
  198. {
  199.     // ASCII 7-bit only...
  200.     if (chr >= 0x80) {
  201.         return;
  202.     }
  203.  
  204.     const unsigned char *glyph;
  205.     unsigned char pgm_buffer[5];
  206.  
  207.     if (chr >= ' ') {
  208.         // Regular ASCII characters are kept in flash to save RAM...
  209.         memcpy_P(pgm_buffer, &charset[chr - ' '], sizeof(pgm_buffer));
  210.         glyph = pgm_buffer;
  211.     } else {
  212.         // Custom glyphs, on the other hand, are stored in RAM...
  213.         if (this->custom[chr]) {
  214.             glyph = this->custom[chr];
  215.         } else {
  216.             // Default to a space character if unset...
  217.             memcpy_P(pgm_buffer, &charset[0], sizeof(pgm_buffer));
  218.             glyph = pgm_buffer;
  219.         }
  220.     }
  221.  
  222.     if (this->inverseText) {       
  223.         // Output one column at a time...
  224.         for (unsigned char i = 0; i < 5; i++) {
  225.             this->send(PCD8544_DATA, ~glyph[i]);
  226.         }
  227.  
  228.         // One column between characters...
  229.         this->send(PCD8544_DATA, 0xFF);
  230.     }
  231.     else {
  232.        
  233.         // Output one column at a time...
  234.         for (unsigned char i = 0; i < 5; i++) {
  235.             this->send(PCD8544_DATA, glyph[i]);
  236.         }
  237.        
  238.         // One column between characters...
  239.         this->send(PCD8544_DATA, 0x00);
  240.     }
  241.  
  242.  
  243.     // Update the cursor position...
  244.     this->column = (this->column + 6) % this->width;
  245.  
  246.     if (this->column == 0) {
  247.         this->line = (this->line + 1) % (this->height/9 + 1);
  248.     }
  249. }
  250.  
  251.  
  252. void PCD8544::drawBitmap(const unsigned char *data, unsigned char columns, unsigned char lines)
  253. {
  254.     unsigned char scolumn = this->column;
  255.     unsigned char sline = this->line;
  256.  
  257.     // The bitmap will be clipped at the right/bottom edge of the display...
  258.     unsigned char mx = (scolumn + columns > this->width) ? (this->width - scolumn) : columns;
  259.     unsigned char my = (sline + lines > this->height/8) ? (this->height/8 - sline) : lines;
  260.  
  261.     for (unsigned char y = 0; y < my; y++) {
  262.         this->setCursor(scolumn, sline + y);
  263.  
  264.         for (unsigned char x = 0; x < mx; x++) {
  265.             this->send(PCD8544_DATA, data[y * columns + x]);
  266.         }
  267.     }
  268.  
  269.     // Leave the cursor in a consistent position...
  270.     this->setCursor(scolumn + columns, sline);
  271. }
  272.  
  273.  
  274. void PCD8544::drawColumn(unsigned char lines, unsigned char value)
  275. {
  276.     unsigned char scolumn = this->column;
  277.     unsigned char sline = this->line;
  278.  
  279.     // Keep "value" within range...
  280.     if (value > lines*8) {
  281.         value = lines*8;
  282.     }
  283.  
  284.     // Find the line where "value" resides...
  285.     unsigned char mark = (lines*8 - 1 - value)/8;
  286.    
  287.     // Clear the lines above the mark...
  288.     for (unsigned char line = 0; line < mark; line++) {
  289.         this->setCursor(scolumn, sline + line);
  290.         this->send(PCD8544_DATA, 0x00);
  291.     }
  292.  
  293.     // Compute the byte to draw at the "mark" line...
  294.     unsigned char b = 0xff;
  295.     for (unsigned char i = 0; i < lines*8 - mark*8 - value; i++) {
  296.         b <<= 1;
  297.     }
  298.  
  299.     this->setCursor(scolumn, sline + mark);
  300.     this->send(PCD8544_DATA, b);
  301.  
  302.     // Fill the lines below the mark...
  303.     for (unsigned char line = mark + 1; line < lines; line++) {
  304.         this->setCursor(scolumn, sline + line);
  305.         this->send(PCD8544_DATA, 0xff);
  306.     }
  307.  
  308.     // Leave the cursor in a consistent position...
  309.     this->setCursor(scolumn + 1, sline);
  310. }
  311.  
  312.  
  313. void PCD8544::send(unsigned char type, unsigned char data)
  314. {
  315.     digitalWrite(this->pin_dc, type);
  316.  
  317.     digitalWrite(this->pin_sce, LOW);
  318.     shiftOut(this->pin_sdin, this->pin_sclk, MSBFIRST, data);
  319.     digitalWrite(this->pin_sce, HIGH);
  320. }
  321.  
  322.  
  323. /* vim: set expandtab ts=4 sw=4: */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement