Permalink
Browse files

Cleaned up library, added brightness, fixed little bugs. See README.txt.

  • Loading branch information...
1 parent 6dcf0ae commit 1ec52d3981da9133b6a22921dd27064fc21ce9e0 @jpbot jpbot committed Aug 18, 2011
Showing with 225 additions and 139 deletions.
  1. +25 −1 README.txt
  2. +84 −99 SPI_VFD.cpp
  3. +40 −39 SPI_VFD.h
  4. +74 −0 examples/Dimmer/Dimmer.pde
  5. +2 −0 keywords.txt
View
26 README.txt
@@ -1,3 +1,27 @@
Arduino Library for 20T202DA2JA SPI VFD (vacuum fluorescent display)
-To install, click DOWNLOAD SOURCE in the top right corner, and see our tutorial at http://www.ladyada.net/library/arduino/libraries.html on Arduino Library installation
+To install, click DOWNLOAD SOURCE in the top right corner, and see our tutorial at http://www.ladyada.net/library/arduino/libraries.html on Arduino Library installation
+
+Modified Aug 17 2011 by J.P. McGlinn github user jpbot
+with help from Stephen Paine github user smpaine
+ -Thanks to smpaine for pointing out some parameter testing I didn't perform in my first go.
+ -Thanks to smpaine for implementing brightness in the begin method (My first thought was
+ constructor/init method)
+ -added brightness control (25%, 50%, 75%, 100%)
+ -initial brightness can be set at the constructor or begin method.
+ -begin method is called by the constructor for a 2x20 display making a call from setup() optional.
+ -added example Dimmer to show off brightness control
+ -removed references to LCD and LiquidCrystal so this library can be used with the
+ LiquidCrystal library
+ -lots of little fixes:
+ --chispselect is really strobe, and is required, so all the checking for is removed
+ --removed 5x10 mode because the datasheet doesn't suggest it's an option
+ --assume always 8bit, removed 4bit checking
+ --strobe and clock are HIGH at idle and were not set initially HIGH so first command
+ was ignored
+ --cleaned up some duplicate code in the begin method
+
+Unfortunately removing the 5x10 dotmode breaks backwards compatibility with the begin method.
+This wasn't used by many, but is something to be aware of. It also might make switching from
+a LCD less trivial. But this only affects the begin method. Bounds checking is done on the
+brightness parameter which replaced the dotmode parameter.
View
183 SPI_VFD.cpp
@@ -9,9 +9,8 @@
//
// 1. Display clear
// 2. Function set:
-// DL = 1; 8-bit interface data
-// N = 0; 1-line display
-// F = 0; 5x8 dot character font
+// N = 1; 2-line display
+// BR1=BR0=0; (100% brightness)
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
@@ -24,75 +23,80 @@
// can't assume that its in that state when a sketch starts (and the
// SPI_VFD constructor is called).
-SPI_VFD::SPI_VFD(uint8_t data, uint8_t clock, uint8_t chipselect)
-{
- init(data, clock, chipselect);
-}
-
-SPI_VFD::SPI_VFD(uint8_t data, uint8_t clock)
-{
- init(data, clock, 0);
-}
-
-void SPI_VFD::init(uint8_t data, uint8_t clock, uint8_t chipselect)
+SPI_VFD::SPI_VFD(uint8_t data, uint8_t clock, uint8_t strobe, uint8_t brightness)
{
_clock = clock;
_data = data;
- _chipselect = chipselect;
+ _strobe = strobe;
pinMode(_clock, OUTPUT);
pinMode(_data, OUTPUT);
-
- if (_chipselect) {
- pinMode(_chipselect, OUTPUT);
- }
-
- _displayfunction = LCD_8BITMODE; // its actually SPI but its 8 bit SPI
- begin(20, 2);
-}
+ pinMode(_strobe, OUTPUT);
-void SPI_VFD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
- if (lines > 1) {
- _displayfunction |= LCD_2LINE;
- }
- _numlines = lines;
- _currline = 0;
+ // normal state of these pins should be high. We must bring them high or the first
+ // command will not be captured by the display module.
+ digitalWrite(_strobe, HIGH);
+ digitalWrite(_clock, HIGH);
- // for some 1 line displays you can select a 10 pixel high font
- if ((dotsize != 0) && (lines == 1)) {
- _displayfunction |= LCD_5x10DOTS;
- }
+ begin(20, 2, brightness); //default to 2x20 display (SAMSUNG 20T202DA2JA)
+}
- clear();
- home();
+void SPI_VFD::begin(uint8_t cols, uint8_t lines, uint8_t brightness) {
+ // set number of lines
+ if (lines > 1)
+ _displayfunction = VFD_2LINE;
+ else
+ _displayfunction = VFD_1LINE;
- // set up the display size
- command(LCD_FUNCTIONSET | _displayfunction);
+ if (brightness>VFD_BRIGHTNESS25) //catch bad values
+ brightness = VFD_BRIGHTNESS100;
- // Initialize to default text direction (for romance languages)
- _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+ // set the brightness and push the linecount with VFD_SETFUNCTION
+ setBrightness(brightness);
+
+ _numlines = lines;
+ _currline = 0;
+
+ // Initialize to default text direction (for romance languages#include "SPI_VFD.h"
+ _displaymode = VFD_ENTRYLEFT | VFD_ENTRYSHIFTDECREMENT;
// set the entry mode
- command(LCD_ENTRYMODESET | _displaymode);
+ command(VFD_ENTRYMODESET | _displaymode);
- command(LCD_SETDDRAMADDR); // go to address 0
+ command(VFD_SETDDRAMADDR); // go to address 0
// turn the display on with no cursor or blinking default
- _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+ _displaycontrol = VFD_DISPLAYON;
display();
- command(LCD_SETDDRAMADDR); // go to address 0
+ clear();
+ home();
}
-
+
/********** high level commands, for the user! */
+void SPI_VFD::setBrightness(uint8_t brightness){
+ // set the brightness (only if a valid value is passed
+ if (brightness <= VFD_BRIGHTNESS25) {
+ _displayfunction &= ~VFD_BRIGHTNESS25;
+ _displayfunction |= brightness;
+
+ command(VFD_FUNCTIONSET | _displayfunction);
+ }
+}
+
+uint8_t SPI_VFD::getBrightness(){
+ // get the brightness
+ return _displayfunction & VFD_BRIGHTNESS25;
+}
+
void SPI_VFD::clear()
{
- command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
+ command(VFD_CLEARDISPLAY); // clear display, set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void SPI_VFD::home()
{
- command(LCD_RETURNHOME); // set cursor position to zero
+ command(VFD_RETURNHOME); // set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
@@ -103,108 +107,104 @@ void SPI_VFD::setCursor(uint8_t col, uint8_t row)
row = _numlines-1; // we count rows starting w/0
}
- command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
+ command(VFD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void SPI_VFD::noDisplay() {
- _displaycontrol &= ~LCD_DISPLAYON;
- command(LCD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol &= ~VFD_DISPLAYON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
void SPI_VFD::display() {
- _displaycontrol |= LCD_DISPLAYON;
- command(LCD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol |= VFD_DISPLAYON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void SPI_VFD::noCursor() {
- _displaycontrol &= ~LCD_CURSORON;
- command(LCD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol &= ~VFD_CURSORON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
void SPI_VFD::cursor() {
- _displaycontrol |= LCD_CURSORON;
- command(LCD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol |= VFD_CURSORON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void SPI_VFD::noBlink() {
- _displaycontrol &= ~LCD_BLINKON;
- command(LCD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol &= ~VFD_BLINKON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
void SPI_VFD::blink() {
- _displaycontrol |= LCD_BLINKON;
- command(LCD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol |= VFD_BLINKON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void SPI_VFD::scrollDisplayLeft(void) {
- command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
+ command(VFD_CURSORSHIFT | VFD_DISPLAYMOVE | VFD_MOVELEFT);
}
void SPI_VFD::scrollDisplayRight(void) {
- command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
+ command(VFD_CURSORSHIFT | VFD_DISPLAYMOVE | VFD_MOVERIGHT);
}
// This is for text that flows Left to Right
void SPI_VFD::leftToRight(void) {
- _displaymode |= LCD_ENTRYLEFT;
- command(LCD_ENTRYMODESET | _displaymode);
+ _displaymode |= VFD_ENTRYLEFT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void SPI_VFD::rightToLeft(void) {
- _displaymode &= ~LCD_ENTRYLEFT;
- command(LCD_ENTRYMODESET | _displaymode);
+ _displaymode &= ~VFD_ENTRYLEFT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void SPI_VFD::autoscroll(void) {
- _displaymode |= LCD_ENTRYSHIFTINCREMENT;
- command(LCD_ENTRYMODESET | _displaymode);
+ _displaymode |= VFD_ENTRYSHIFTINCREMENT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void SPI_VFD::noAutoscroll(void) {
- _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
- command(LCD_ENTRYMODESET | _displaymode);
+ _displaymode &= ~VFD_ENTRYSHIFTINCREMENT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void SPI_VFD::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
- command(LCD_SETCGRAMADDR | (location << 3));
+ command(VFD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
}
}
-/*********** mid level commands, for sending data/cmds */
+/*********** mid level commands, for sending data/cmds, init */
void SPI_VFD::command(uint8_t value) {
- if (_chipselect)
- digitalWrite(_chipselect, LOW);
- send(LCD_SPICOMMAND);
+ digitalWrite(_strobe, LOW);
+ send(VFD_SPICOMMAND);
send(value);
- if (_chipselect)
- digitalWrite(_chipselect, HIGH);
+ digitalWrite(_strobe, HIGH);
/*
- Serial.print(LCD_SPICOMMAND, HEX);
+ Serial.print(VFD_SPICOMMAND, HEX);
Serial.print('\t');
Serial.println(value, HEX);
*/
}
void SPI_VFD::write(uint8_t value) {
- if (_chipselect)
- digitalWrite(_chipselect, LOW);
- send(LCD_SPIDATA);
+ digitalWrite(_strobe, LOW);
+ send(VFD_SPIDATA);
send(value);
- if (_chipselect)
- digitalWrite(_chipselect, HIGH);
+ digitalWrite(_strobe, HIGH);
/*
- Serial.print(LCD_SPIDATA, HEX);
+ Serial.print(VFD_SPIDATA, HEX);
Serial.print('\t');
Serial.println(value, HEX);
*/
@@ -213,35 +213,20 @@ void SPI_VFD::write(uint8_t value) {
/************ low level data pushing commands **********/
// write spi data
-void SPI_VFD::send(uint8_t c) {
- //shiftOut(_data, _clock, MSBFIRST, value);
-
- //volatile uint8_t *sclkportreg = portOutputRegister(sclkport);
- //volatile uint8_t *sidportreg = portOutputRegister(sidport);
-
+inline void SPI_VFD::send(uint8_t c) {
int8_t i;
- //*sclkportreg |= sclkpin;
digitalWrite(_clock, HIGH);
for (i=7; i>=0; i--) {
- //*sclkportreg &= ~sclkpin;
- //SCLK_PORT &= ~_BV(SCLK);
digitalWrite(_clock, LOW);
if (c & _BV(i)) {
- //*sidportreg |= sidpin;
- //SID_PORT |= _BV(SID);
digitalWrite(_data, HIGH);
} else {
- //*sidportreg &= ~sidpin;
- //SID_PORT &= ~_BV(SID);
digitalWrite(_data, LOW);
}
- //*sclkportreg |= sclkpin;
- //SCLK_PORT |= _BV(SCLK);
digitalWrite(_clock, HIGH);
}
-
}
View
79 SPI_VFD.h
@@ -1,61 +1,62 @@
-#ifndef LiquidCrystal_h
-#define LiquidCrystal_h
+#ifndef SPI_VFD_h
+#define SPI_VFD_h
#include <inttypes.h>
#include "Print.h"
// commands
-#define LCD_CLEARDISPLAY 0x01
-#define LCD_RETURNHOME 0x02
-#define LCD_ENTRYMODESET 0x04
-#define LCD_DISPLAYCONTROL 0x08
-#define LCD_CURSORSHIFT 0x10
-#define LCD_FUNCTIONSET 0x20
-#define LCD_SETCGRAMADDR 0x40
-#define LCD_SETDDRAMADDR 0x80
+#define VFD_CLEARDISPLAY 0x01
+#define VFD_RETURNHOME 0x02
+#define VFD_ENTRYMODESET 0x04
+#define VFD_DISPLAYCONTROL 0x08
+#define VFD_CURSORSHIFT 0x10
+#define VFD_FUNCTIONSET 0x30
+#define VFD_SETCGRAMADDR 0x40
+#define VFD_SETDDRAMADDR 0x80
// flags for display entry mode
-#define LCD_ENTRYRIGHT 0x00
-#define LCD_ENTRYLEFT 0x02
-#define LCD_ENTRYSHIFTINCREMENT 0x01
-#define LCD_ENTRYSHIFTDECREMENT 0x00
+#define VFD_ENTRYRIGHT 0x00
+#define VFD_ENTRYLEFT 0x02
+#define VFD_ENTRYSHIFTINCREMENT 0x01
+#define VFD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
-#define LCD_DISPLAYON 0x04
-#define LCD_DISPLAYOFF 0x00
-#define LCD_CURSORON 0x02
-#define LCD_CURSOROFF 0x00
-#define LCD_BLINKON 0x01
-#define LCD_BLINKOFF 0x00
+#define VFD_DISPLAYON 0x04
+#define VFD_DISPLAYOFF 0x00
+#define VFD_CURSORON 0x02
+#define VFD_CURSOROFF 0x00
+#define VFD_BLINKON 0x01
+#define VFD_BLINKOFF 0x00
// flags for display/cursor shift
-#define LCD_DISPLAYMOVE 0x08
-#define LCD_CURSORMOVE 0x00
-#define LCD_MOVERIGHT 0x04
-#define LCD_MOVELEFT 0x00
+#define VFD_DISPLAYMOVE 0x08
+#define VFD_CURSORMOVE 0x00
+#define VFD_MOVERIGHT 0x04
+#define VFD_MOVELEFT 0x00
// flags for function set
-#define LCD_8BITMODE 0x10
-#define LCD_4BITMODE 0x00
-#define LCD_2LINE 0x08
-#define LCD_1LINE 0x00
-#define LCD_5x10DOTS 0x04
-#define LCD_5x8DOTS 0x00
+#define VFD_2LINE 0x08
+#define VFD_1LINE 0x00
+#define VFD_BRIGHTNESS25 0x03
+#define VFD_BRIGHTNESS50 0x02
+#define VFD_BRIGHTNESS75 0x01
+#define VFD_BRIGHTNESS100 0x00
-#define LCD_SPICOMMAND 0xF8
-#define LCD_SPIDATA 0xFA
+#define VFD_SPICOMMAND 0xF8
+#define VFD_SPIDATA 0xFA
class SPI_VFD : public Print {
public:
- SPI_VFD(uint8_t data, uint8_t clock, uint8_t chipselect);
- SPI_VFD(uint8_t data, uint8_t clock);
+ SPI_VFD(uint8_t data, uint8_t clock, uint8_t strobe, uint8_t brightness = VFD_BRIGHTNESS100);
- void init(uint8_t data, uint8_t clock, uint8_t chipselect);
- void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+ void init(uint8_t data, uint8_t clock, uint8_t strobe, uint8_t brightness);
+ void begin(uint8_t cols, uint8_t rows, uint8_t brightness = VFD_BRIGHTNESS100);
void clear();
void home();
+ void setBrightness(uint8_t brightness);
+ uint8_t getBrightness();
void noDisplay();
void display();
void noBlink();
@@ -74,17 +75,17 @@ class SPI_VFD : public Print {
virtual void write(uint8_t);
void command(uint8_t);
private:
- void send(uint8_t data);
+ inline void send(uint8_t data);
- uint8_t _clock, _data, _chipselect; // SPI interface
+ uint8_t _clock, _data, _strobe; // SPI interface
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _initialized;
- uint8_t _numlines,_currline;
+ uint8_t _numlines, _currline;
};
#endif
View
74 examples/Dimmer/Dimmer.pde
@@ -0,0 +1,74 @@
+/*
+ SPI_VFD Library - Dimmer
+
+ Demonstrates the use a 20x2 VFD display. The SPI_VFD
+ library works with all VFD displays that are compatible with the
+ NEC PD16314 driver and has the SPI pins brought out
+
+ This sketch prints "Hello World!" to the VFD
+ and adjusts the brightness of the VFD
+
+ The circuit:
+ * VFD Data (pin 3) to digital pin 2
+ * VFD Clock (pin 5) to digital pin 3
+ * VFD Strobe (pin 4) to digital pin 4
+ * VFD VCC (pin 2) to 5V
+ * VFD Ground (pin 1) to Ground
+
+ Library originally added 18 Apr 2008
+ by David A. Mellis
+ library modified 5 Jul 2009
+ by Limor Fried (http://www.ladyada.net)
+ example added 9 Jul 2009
+ by Tom Igoe
+ modified 22 Nov 2010
+ by Tom Igoe
+ Dimmer example added 17 Aug 2011
+ by J.P. McGlinn
+
+ This example code is in the public domain.
+ */
+
+// include the library code:
+#include <SPI_VFD.h>
+
+// initialize the library with the numbers of the interface pins
+SPI_VFD vfd(2, 3, 4, VFD_BRIGHTNESS25);
+
+// alternate form of constuctor sets brightness to 100% (default)
+// SPI_VFD vfd(2, 3, 4);
+
+// global to store brightness for the sketch
+uint8_t brightness = 0;
+
+void setup() {
+ // set up the VFD's number of columns and rows:
+ // unnecessary to call begin, this method is called by the constructor with 2x20.
+ // vfd.begin(20, 2);
+ //
+ // Alternate form of begin to set brightness
+ // vfd.begin(20, 2, VFD_BRIGHTNESS50);
+
+ // Print a message to the VFD.
+ vfd.print("hello, world!");
+ vfd.setCursor(0, 1);
+ vfd.print("Brightness: 0x");
+ vfd.print(vfd.getBrightness(), HEX);
+}
+
+void loop() {
+ // set the cursor to column 0, line 1
+ // (note: line 1 is the second row, since counting begins with 0):
+ vfd.setCursor(14, 0);
+ // print the number of seconds since reset:
+ vfd.print(millis()/1000);
+
+ delay(1000);
+
+ //set the brightness to a value between 0 and 3
+ vfd.setBrightness(brightness=brightness++%4);
+
+ //show the value for fun
+ vfd.setCursor(14, 1);
+ vfd.print(vfd.getBrightness(), HEX);
+}
View
2 keywords.txt
@@ -16,6 +16,8 @@ begin KEYWORD2
clear KEYWORD2
home KEYWORD2
print KEYWORD2
+setBrightness KEYWORD2
+getBrightness KEYWORD2
setCursor KEYWORD2
cursor KEYWORD2
noCursor KEYWORD2

0 comments on commit 1ec52d3

Please sign in to comment.