Permalink
Browse files

Updated SPI_VFD to check for display readiness before sending commands.

According to the data sheet, the display sets an internal variable, BF,
to 0 when it is ready for another command, and sets it to 1 when the
display is busy. So, now the code waits for the display to set BF to 0
prior to sending any commands to it.
  • Loading branch information...
1 parent c4e9696 commit 6f728a1f40093ce7658b3c8cda2c319e9f1fd8f5 @smpaine committed Aug 19, 2011
Showing with 213 additions and 161 deletions.
  1. +169 −120 SPI_VFD.cpp
  2. +44 −41 SPI_VFD.h
View
289 SPI_VFD.cpp
@@ -25,208 +25,257 @@
SPI_VFD::SPI_VFD(uint8_t data, uint8_t clock, uint8_t strobe, uint8_t brightness)
{
- _clock = clock;
- _data = data;
- _strobe = strobe;
-
- pinMode(_clock, OUTPUT);
- pinMode(_data, OUTPUT);
- pinMode(_strobe, OUTPUT);
-
- // 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);
-
- begin(20, 2, brightness); //default to 2x20 display (SAMSUNG 20T202DA2JA)
+ _clock = clock;
+ _data = data;
+ _strobe = strobe;
+
+ pinMode(_clock, OUTPUT);
+ pinMode(_data, OUTPUT);
+ pinMode(_strobe, OUTPUT);
+
+ // 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);
+
+ begin(20, 2, brightness); //default to 2x20 display (SAMSUNG 20T202DA2JA)
}
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;
-
- if (brightness>VFD_BRIGHTNESS25) //catch bad values
- brightness = VFD_BRIGHTNESS100;
-
- // 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(VFD_ENTRYMODESET | _displaymode);
-
- command(VFD_SETDDRAMADDR); // go to address 0
-
- // turn the display on with no cursor or blinking default
- _displaycontrol = VFD_DISPLAYON;
- display();
-
- clear();
- home();
-}
-
+ // set number of lines
+ if (lines > 1)
+ _displayfunction = VFD_2LINE;
+ else
+ _displayfunction = VFD_1LINE;
+
+ if (brightness>VFD_BRIGHTNESS25) //catch bad values
+ brightness = VFD_BRIGHTNESS100;
+
+ // 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(VFD_ENTRYMODESET | _displaymode);
+
+ command(VFD_SETDDRAMADDR); // go to address 0
+
+ // turn the display on with no cursor or blinking default
+ _displaycontrol = VFD_DISPLAYON;
+ display();
+
+ 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);
- }
+ // 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;
+ // get the brightness
+ return _displayfunction & VFD_BRIGHTNESS25;
}
void SPI_VFD::clear()
{
- command(VFD_CLEARDISPLAY); // clear display, set cursor position to zero
- delayMicroseconds(2000); // this command takes a long time!
+ command(VFD_CLEARDISPLAY); // clear display, set cursor position to zero
}
void SPI_VFD::home()
{
- command(VFD_RETURNHOME); // set cursor position to zero
- delayMicroseconds(2000); // this command takes a long time!
+ command(VFD_RETURNHOME); // set cursor position to zero
}
void SPI_VFD::setCursor(uint8_t col, uint8_t row)
{
- int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
- if ( row > _numlines ) {
- row = _numlines-1; // we count rows starting w/0
- }
-
- command(VFD_SETDDRAMADDR | (col + row_offsets[row]));
+ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+ if ( row > _numlines ) {
+ row = _numlines-1; // we count rows starting w/0
+ }
+
+ command(VFD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void SPI_VFD::noDisplay() {
- _displaycontrol &= ~VFD_DISPLAYON;
- command(VFD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol &= ~VFD_DISPLAYON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
void SPI_VFD::display() {
- _displaycontrol |= VFD_DISPLAYON;
- command(VFD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol |= VFD_DISPLAYON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void SPI_VFD::noCursor() {
- _displaycontrol &= ~VFD_CURSORON;
- command(VFD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol &= ~VFD_CURSORON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
void SPI_VFD::cursor() {
- _displaycontrol |= VFD_CURSORON;
- command(VFD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol |= VFD_CURSORON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void SPI_VFD::noBlink() {
- _displaycontrol &= ~VFD_BLINKON;
- command(VFD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol &= ~VFD_BLINKON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
void SPI_VFD::blink() {
- _displaycontrol |= VFD_BLINKON;
- command(VFD_DISPLAYCONTROL | _displaycontrol);
+ _displaycontrol |= VFD_BLINKON;
+ command(VFD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void SPI_VFD::scrollDisplayLeft(void) {
- command(VFD_CURSORSHIFT | VFD_DISPLAYMOVE | VFD_MOVELEFT);
+ command(VFD_CURSORSHIFT | VFD_DISPLAYMOVE | VFD_MOVELEFT);
}
void SPI_VFD::scrollDisplayRight(void) {
- command(VFD_CURSORSHIFT | VFD_DISPLAYMOVE | VFD_MOVERIGHT);
+ command(VFD_CURSORSHIFT | VFD_DISPLAYMOVE | VFD_MOVERIGHT);
}
// This is for text that flows Left to Right
void SPI_VFD::leftToRight(void) {
- _displaymode |= VFD_ENTRYLEFT;
- command(VFD_ENTRYMODESET | _displaymode);
+ _displaymode |= VFD_ENTRYLEFT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void SPI_VFD::rightToLeft(void) {
- _displaymode &= ~VFD_ENTRYLEFT;
- command(VFD_ENTRYMODESET | _displaymode);
+ _displaymode &= ~VFD_ENTRYLEFT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void SPI_VFD::autoscroll(void) {
- _displaymode |= VFD_ENTRYSHIFTINCREMENT;
- command(VFD_ENTRYMODESET | _displaymode);
+ _displaymode |= VFD_ENTRYSHIFTINCREMENT;
+ command(VFD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void SPI_VFD::noAutoscroll(void) {
- _displaymode &= ~VFD_ENTRYSHIFTINCREMENT;
- command(VFD_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(VFD_SETCGRAMADDR | (location << 3));
- for (int i=0; i<8; i++) {
- write(charmap[i]);
- }
+ location &= 0x7; // we only have 8 locations 0-7
+ command(VFD_SETCGRAMADDR | (location << 3));
+ for (int i=0; i<8; i++) {
+ write(charmap[i]);
+ }
}
/*********** mid level commands, for sending data/cmds, init */
void SPI_VFD::command(uint8_t value) {
- digitalWrite(_strobe, LOW);
- send(VFD_SPICOMMAND);
- send(value);
- digitalWrite(_strobe, HIGH);
-
- /*
- Serial.print(VFD_SPICOMMAND, HEX);
- Serial.print('\t');
- Serial.println(value, HEX);
- */
+ uint8_t ready;
+
+ // Wait for display to be ready
+ do {
+ //Serial.print("Checking BF... ");
+
+ // check if display is ready (checking for BF=0)
+ ready=read_addr();
+
+ // only care about BF, which is MSB
+ ready>>=7;
+ } while (ready);
+
+ digitalWrite(_strobe, LOW);
+ send(VFD_SPICOMMAND);
+ send(value);
+ digitalWrite(_strobe, HIGH);
+
+ /*
+ Serial.print(VFD_SPICOMMAND, HEX);
+ Serial.print('\t');
+ Serial.println(value, HEX);
+ */
}
void SPI_VFD::write(uint8_t value) {
- digitalWrite(_strobe, LOW);
- send(VFD_SPIDATA);
- send(value);
- digitalWrite(_strobe, HIGH);
+ digitalWrite(_strobe, LOW);
+ send(VFD_SPIWRITE);
+ send(value);
+ digitalWrite(_strobe, HIGH);
+
+ /*
+ Serial.print(VFD_SPIWRITE, HEX);
+ Serial.print('\t');
+ Serial.println(value, HEX);
+ */
+}
- /*
- Serial.print(VFD_SPIDATA, HEX);
- Serial.print('\t');
- Serial.println(value, HEX);
- */
+uint8_t SPI_VFD::read_addr() {
+ uint8_t value;
+
+ digitalWrite(_strobe, LOW);
+ send(VFD_SPIADDREAD);
+ delayMicroseconds(1);
+ value=recv();
+ digitalWrite(_strobe, HIGH);
+
+ /*
+ Serial.print(VFD_SPIADDREAD, HEX);
+ Serial.print('\t');
+ Serial.println(value, HEX);
+ */
+
+ return value;
}
/************ low level data pushing commands **********/
// write spi data
inline void SPI_VFD::send(uint8_t c) {
- int8_t i;
-
- digitalWrite(_clock, HIGH);
-
- for (i=7; i>=0; i--) {
- digitalWrite(_clock, LOW);
+ int8_t i;
+
+ digitalWrite(_clock, HIGH);
- if (c & _BV(i)) {
- digitalWrite(_data, HIGH);
- } else {
- digitalWrite(_data, LOW);
+ for (i=7; i>=0; i--) {
+ digitalWrite(_clock, LOW);
+
+ if (c & _BV(i)) {
+ digitalWrite(_data, HIGH);
+ } else {
+ digitalWrite(_data, LOW);
+ }
+
+ digitalWrite(_clock, HIGH);
}
+}
+
+// read spi data
+inline uint8_t SPI_VFD::recv() {
+ int8_t i,c;
digitalWrite(_clock, HIGH);
- }
+
+ for (i=7; i>=0; i--) {
+ // pull clock low
+ digitalWrite(_clock, LOW);
+ // read next value from display
+ c=digitalRead(_data);
+ // make room for next value
+ if (i) {
+ c<<=1;
+ }
+ // pull clock high to prepare for next read
+ digitalWrite(_clock, HIGH);
+ }
}
View
85 SPI_VFD.h
@@ -43,49 +43,52 @@
#define VFD_BRIGHTNESS100 0x00
#define VFD_SPICOMMAND 0xF8
-#define VFD_SPIDATA 0xFA
+#define VFD_SPIWRITE 0xFA
+#define VFD_SPIADDREAD 0xFC
class SPI_VFD : public Print {
public:
- SPI_VFD(uint8_t data, uint8_t clock, uint8_t strobe, uint8_t brightness = VFD_BRIGHTNESS100);
+ 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 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();
+ void blink();
+ void noCursor();
+ void cursor();
+ void scrollDisplayLeft();
+ void scrollDisplayRight();
+ void leftToRight();
+ void rightToLeft();
+ void autoscroll();
+ void noAutoscroll();
+
+ void createChar(uint8_t, uint8_t[]);
+ void setCursor(uint8_t, uint8_t);
+ virtual void write(uint8_t);
+ virtual uint8_t read_addr();
+ void command(uint8_t);
+ private:
+ inline void send(uint8_t data);
+ inline uint8_t recv();
+
+ uint8_t _clock, _data, _strobe; // SPI interface
+
+ uint8_t _displayfunction;
+ uint8_t _displaycontrol;
+ uint8_t _displaymode;
+
+ uint8_t _initialized;
+
+ uint8_t _numlines, _currline;
+ };
- 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();
- void blink();
- void noCursor();
- void cursor();
- void scrollDisplayLeft();
- void scrollDisplayRight();
- void leftToRight();
- void rightToLeft();
- void autoscroll();
- void noAutoscroll();
-
- void createChar(uint8_t, uint8_t[]);
- void setCursor(uint8_t, uint8_t);
- virtual void write(uint8_t);
- void command(uint8_t);
-private:
- inline void send(uint8_t data);
-
- uint8_t _clock, _data, _strobe; // SPI interface
-
- uint8_t _displayfunction;
- uint8_t _displaycontrol;
- uint8_t _displaymode;
-
- uint8_t _initialized;
-
- uint8_t _numlines, _currline;
-};
-
#endif

1 comment on commit 6f728a1

@smpaine
Owner

Looks like a big commit because of indentation change... (2 spaces vs tab)

Please sign in to comment.