Access to Serial.h print functions from I2C module

22 May 2010

Hi.

I have noticed that in the samples for writing to a serial display, putc, and printf are used.

I am using an I2C display and would like to be able to use these functions.  In looking at the I2C LCD examples they all make use of the LCD as a parallel display (ie, _rw, _rs, _e, (4 bit lines)).

My LCD is pure I2C where the interface on the display handles the connection to the LCD and I need only to send it hex codes for commands and characters.  
Using putc and printf would greatly simplify my interface.

Is there a way to add these to my I2C?

Thanks

Tim

22 May 2010

Hi Tim,

If you import these files in to your program:

this might be a good way to get the bits you need to easily do this. In there are two classes, TextDisplay which is a base class giving most of the general functions you'd expect for a text display, including locate, putc, printf, cls etc. Then there is TextLCD which derives from this to implement if for a specific display/driver; in this case a 4-bit 2x16 LCD.
If you look in TextLCD.h, the important bits are:
class TextLCD : public TextDisplay {       
public:                                    
    TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, PinName d2, PinName d3);
    virtual void character(int column, int row, int c);
    virtual int rows(); 
    virtual int columns();
}
This shows that TextLCD is derived from TextDisplay (where it gets all the useful functions from), and the functions it needs to implement; TextLCD constructor to setup the display, character to place a character at a location, and rows/columns to set the size.
For your own display, you basically want to do your own version of TextLCD.h/.cpp. For example:
class MyI2CTextLCD : public TextDisplay {       
public:                                    
    MyI2CTextLCD(...I2C and any other pins...);
    virtual void character(int column, int row, int c);
    virtual int rows(); 
    virtual int columns();
}
If you then go and implement these (using the code you've written so far) you'll get all the locate, printf, putc functions for free. Of course you can add more methods that you want your class to support.
Have a look and see if that is helpful/makes sense.
Simon
22 May 2010 . Edited: 22 May 2010

Hi Simon:

Thank you for your response and for trying to provide a way to accomplish what I am trying to do.  I think I will wait until I learn how to build a library as we have been discussing in another thread.  What you have posted here is beyond my understanding at this time.  It looks to me as though I would have to add TextLCD.h which does not resemble the LCD I am using.

As an example, here is the structure of each of the functions that I have defined.  I could likely reduce the number of functions I have defined by finding a different way of representing the "LCD_option" variable as that variable is the only thing that changes in each module to accomplish other tasks such as turning the cursor on and off.

//
//**************************************************************************************
//* Clear Screen
//**************************************************************************************
void LCD_clear_screen(int LCD_command, int LCD_option)
{
   LCD_command = 0xFE;             // command designator
   LCD_option  = 0x58;             // Clear Screen
   char cmd[2];
   cmd[0] = LCD_command;           // 0xFE
   cmd[1] = LCD_option;            // 0x58
   LCD.write(LCD_address, cmd, 2); // Send command element
}
//

The functions that position the cursor are all based on:

//
//**************************************************************************************
//* Set Cursor Position
//**************************************************************************************
void LCD_cursor_position(int LCD_command, int LCD_option, int LCD_col, int LCD_row)
{
   LCD_command = 0xFE;             // command designator
   LCD_option  = 0x47;             // Set Cursor Position
   char cmd[4];
   cmd[0] = LCD_command;           // 0xFE
   cmd[1] = LCD_option;            // 0x47
   cmd[2] = LCD_col;               // Valid = 1 - 16
   cmd[3] = LCD_row;               // Valid = 1 - 2
   LCD.write(LCD_address, cmd, 4); // Send command elements
}
//

which really is the same function with the inclusion of passing the col and row information to the existing command function.

In order to pass a line of text to the LCD, I once again use the same structure, with the exception that I have specified char letters[17] instead of cmd[1-4].  I have discovered that I can pass ascii characters instead of hex characters as indicated below.

//
//************************************************************************
// LCD Write First Row Init Function                   
//************************************************************************
void LCD_First_Row(int LCD_address)
{
     char letters[17];
     letters[0]  = 'D';   //D
     letters[1]  = 'i';   //i
     letters[2]  = 0x73;  //s
     letters[3]  = 0x70;  //p
     letters[4]  = 0x6C;  //l
     letters[5]  = 0x61;  //a
     letters[6]  = 0x79;  //y
     letters[7]  = 0x2E;  //.
     letters[8]  = 0x2E;  //.
     letters[9]  = 0x2E;  //.
     letters[10] = 0x2E;  //.
     letters[11] = 0x20;  //
     letters[12] = 0x52;  //R
     letters[13] = 0x65;  //e
     letters[14] = 0x61;  //a
     letters[15] = 0x64;  //d
     letters[16] = 0x79;  //y  
     LCD.write(LCD_address, letters, 17); // Send data elements
}

I would like to be able type the text that I wish to send as just "Display Ready" (with the appropriate number of blank spaces to match the number of characters per line and then send it to the LCD as such.

Right now, I can say what is written below and I have complete control of the LCD.

main()
{   
    while(1)
    {   
       LCD_clear_Screen;
       wait(1);
       LCD_First_Row;
       LCD_Second_Row;
    }
}

I had to edit this reply because I couldn't add a new line after the code box containing main().  I don't know why it works like that but it does.

If I am displaying a variable, I used

LCD.write(LCD_address, tagValue, 10);

where tagValue is a char array.

I'm sure that there is a more efficient way of doing all of this, but this is what I developed to easily communicate with I2C devices.  I don't see a way of changing this to match what you have outlined given my current approach.

I am open to suggestions for improvement but for now I will leave things as is until I can understand what is involved in building a library.

I do appreciate your attempt to help and I wish I understood it.  I just thought it would be convenient to write to the LCD in the same fashion as I use pc.printf to write to the serial terminal.

Thanks

Tim

01 Nov 2010

I have a serial display from sparkfun (Serial 2*16)

http://www.sparkfun.com/commerce/product_info.php?products_id=709

Is this the same you got?

//Niclas