LCD shield and/or LCD serial backpack

No one has made a LCD shield yet which I find odd. Is there any interest for one?
I could even make it use my cool 3 pin LCD interface or even I2C, SPI and serial.

Also serial backpacks are relatively pricey and not as useful as they could be.
In theory I could make a backpack which cost $10 and also provided SPI and I2C interfaces.
For comparison, SparkFun's is $17 and only provides serial.

What do you guys think?

Although I am now past that point on my current project, I would have been very interested in an I2C LCD shield for $10.

I would think that I2C and serial support for LCDs at that price would be useful to many.

Well for the backpack I've calculated approx costs.

The PCB is a tiny 1.5 inches by 0.75 inches which at BatchPCB means $5 per board.
It would be $2.50 if I can shave off a fraction off a inch.
At Futurlec for buying 100 of them its just over a dollar a board.

Components wise I can get them singly for about $3.50.
Buying in bulk would slash that amount.

Specs:
ATmega8 running at 16mhz.
Contrast control via trimpot.
Ability to turn the LCD's backlight on/off (power saving or for getting attention).
I2C, Serial and SPI all avaliable.
ICSP header for programming.

Software:
The software will be GPLed naturally. :slight_smile:
I'll probably put the Arduino bootloader on it so it can be easily updated.
The serial protocol will probably be compatible with other serial backpacks.
The SPI and I2C protocols will be a efficient protocol which I'll work out.
Sample code will be provided for interfacing it with the Arduino using all three methods.

So is there enough interest for me to make a batch of about 25 boards?

Sounds cool.

If you do want to put the Arduino bootloader on it, you should probably do a lot of testing to make sure it doesn't cause any problems. If people are sending serial commands to the chip (intended to control the LCD) while the bootloader is active, it could get confused and never launch the code that controls the LCD. The latest ATmega168 bootloader has some code to try to prevent these sorts of problems, but it's not perfect, and it's not in the current ATmega8 bootloader. Also, you'll need to balance out the need for the bootloader to have a reasonable delay (so people can actually time an upload properly) vs. having the LCD being responsive quickly. One idea would be to have a jumper on a digital pin that the bootloader checks when it starts - immediately running the LCD application if it's LOW (or HIGH). We didn't do that on the Arduino because we didn't want to dedicate a pin to it or add an extra jumper to the board, but it might make sense for this application. There might even be commented code in the bootloader to handle it. :slight_smile:

So is there enough interest for me to make a batch of about 25 boards?

I am in for one.

Presumably you will be using the RW line rather than delays to determine when the LCD is ready to accept data.

Presumably you will be using the RW line rather than delays to determine when the LCD is ready to accept data.

Yep. Its got a dedicated chip so there is no need to cut corners with the pins. :slight_smile:

Also I just realised that I can make the backlight brightness variable.

Presumably you will be using the RW line rather than delays to determine when the LCD is ready to accept data.

Yep. Its got a dedicated chip so there is no need to cut corners with the pins. :slight_smile:

Also I just realised that I can make the backlight brightness variable.

Not sure if you have taken a look at Peter Anderson's K107 backpack. Should at least provide a good reference for designing your own backpack..

If you do want to put the Arduino bootloader on it, you should probably do a lot of testing to make sure it doesn't cause any problems.

Sorry I missed your post.

If they are using it with a Arduino then it wouldnt matter at all because they would have to wait anyway.
Ladyada has a hack which starts the program if anything other than 00 is sent to the bootloader so that would also work.
I might put a SMD jumper on to enable/disable it. Just solder over it to enable.

The K107 looks good but it has a awful number of limitations.
I can steal some ideas from its software though. :slight_smile:

Ok I've finished fiddling with it. Here is the design so far:

I ditched the ICSP connector to save space.
Since I'm breaking out SPI anyway, it'll be simple to make a adaptor.
The labels need to be moved around a bit as well.

It should be breadboard compatible and you'd be able to use a DIP-16 socket if you wanted.
You can also solder it directly to a LCD or even put a socket on it so its removable.

Any feedback?

Also what kind of transistor should I use?
It controls the backlight so it needs to handle about 200mA.

Looking good!

More a passing thought then a suggestion, but I was wondering if you would gain real estate and lower cost replacing the contrast pot with a transistor and capacitor driven from a spare onboard pwm pin. Providing the arduino with software commands to increase and decrease contrast may be more convenient then getting at the pot.

Looking good!

More a passing thought then a suggestion, but I was wondering if you would gain real estate and lower cost replacing the contrast pot with a transistor and capacitor driven from a spare onboard pwm pin. Providing the arduino with software commands to increase and decrease contrast may be more convenient then getting at the pot.

Other people may have had different experiences but I have always found that I only adjust the contrast once.

Its certainly possible.
Even if it is set only once its probably cheaper.
The value can be stored in EEPROM once the optimal contrast is found or it can be changed dynamically.

hej cheater, great idea! just 2 questions: do you target a special LCD or is your board supposed to be a general garphics card? i'm asking this, because i use these monochrome nokia displays (monochrome, 84px x 48px). i have the code working and really would like to work on a library if someone would be willing to assist. the problem with this display is, that it works on 3.3v and comes with a pretty annoying connector which like cries for a custom board.

sparkfun is selling the display including a board (no backlight) for $35. http://www.sparkfun.com/commerce/product_info.php?products_id=8428
the display only is available for about $5 / 4$. the color displays (OLED) i'v been looking need 3.3v (some 3.6v) as well. you could keep that in mind when configuring the atmegas brown out detection and stuff. plus maybe you find one of these mobile phones display connectors to be worth supportable. i guess there are a million different, still it might be something to investigate.

my second question is a general question on your first design. do you (or anyone) have experience on running an atmega on the internal oscillator at 8Mhz? just maybe you don't need the crystal and can save that space. if the communication uses a clock line i wouldn't see a problem with timing or speed. what do think?

i'm using ladyada's bootloader hack as well, and have no problems uploading sketches to the 8Mhz/3.3v at 19.200 bps using just RX/TX. "run program on power up" is a great feature (and something i would suggest for the official arduino bootloader! to upload a sketch you reset the board with the reset button).

i'm for the software controlled contrast and backlight by the way. they can be used for cool effects.

as for a backlight transistor: i think bc-337 and 2n2222 would be suited. at least these i've found to meet very often, and if i remember correctly support a max of 400mA (or was it 800?).

if we could find a reasonable priced way to get them here to berlin, i'd be interested in at least 2 of these :slight_smile:

//kuk

... i use these monochrome nokia displays (monochrome, 84px x 48px). i have the code working and really would like to work on a library if someone would be willing to assist.

I don't want to hijack this thread but I have a few of these and would be interested in helping with a library. It would be great if cheater could support these displays in his shield, but if not then it may be worth starting another thread to discuss this.

hej cheater, great idea! just 2 questions: do you target a special LCD or is your board supposed to be a general garphics card?

This is designed for a standard HD44780 character LCD, not a graphical one.
The idea however can be adapted to nearly anything.

i'm asking this, because i use these monochrome nokia displays (monochrome, 84px x 48px). i have the code working and really would like to work on a library if someone would be willing to assist. the problem with this display is, that it works on 3.3v and comes with a pretty annoying connector which like cries for a custom board.

I'd assist if I had one. :wink:

my second question is a general question on your first design. do you (or anyone) have experience on running an atmega on the internal oscillator at 8Mhz? just maybe you don't need the crystal and can save that space. if the communication uses a clock line i wouldn't see a problem with timing or speed. what do think?

I dont have experience with it but I have ordered a bunch of ATtiny chips to play with along with two ATmega32's.
So in a week or two I will have experience running them without a crystal. :slight_smile:

Space isnt a issue with my design.
The width is constant because I want it to fit in a DIP socket and the length is also constant because it needs to match a LCD's pin out.

The crystal is dirt cheap and is faster and more reliable. Why not have it? :slight_smile:
For smaller designs I probably wouldnt have one though.

as for a backlight transistor: i think bc-337 and 2n2222 would be suited. at least these i've found to meet very often, and if i remember correctly support a max of 400mA (or was it 800?).

I found a SMD one which says its max current is 800mA so that should be fine.

The backlight shouldnt cause much of a problem anyway.
I've got a neat setup where I control 4 20x4 LCDs from three pins with individual backlight control.
A 595 can power the backlights just fine even with massive capacitors which make a cool fading effect.

if we could find a reasonable priced way to get them here to berlin, i'd be interested in at least 2 of these :slight_smile:

Australia to Berlin should be fine. :slight_smile:

I'm getting a 128x64 graphical LCD (a larger one, not a tiny one. KS0108B controller) so I can definitely help with graphical routines for any LCD and a library for similar LCDs.
Just need to dust off my trigonometry. :slight_smile:

I could also make a backpack or shield for other LCDs which does all the hard work and provides Serial/I2C/SPI interfaces.
Making one for a PSP LCD (with touch screen even) would be bloody cool. :smiley:

i use these monochrome nokia displays (monochrome, 84px x 48px). i have the code working and really would like to work on a library if someone would be willing to assist.

Ooo, yes. :slight_smile: I have an LCD wired up here but haven't tested it because I got distracted by the whole network thing... :smiley:

Here are my Arduino and Nokia LCD notes probably not much use currently but thought I'd throw them on the pile.

--Phil.

Here's a basic code to display text, lines and dots. Original c code came from Massimo. I already posted it to the forum, but thing get easily lost here. i know it should be up on the playground. but me too got distracted from it by other projects. The circuit i use never got updated, like i planned, using a proper 3,3v regulator for the display. i'm doing other stuff lately with arduino running on 3.3v so i might get back to it.

here the lazy circuit NOKIADISPLAYvsARDUINO | display taken from a nokia 3310 whic… | Flickr using 4 diodes to reduce voltage to appr. 3.2v and voltage dividers for communication.
here's a basic version of the code [again here, and not on the playground, so maybe we could clean it up build a library from it together]:

//  arduino pinout for LCD.
int CONTROL_LED=12;
int LCD_POWER_PIN      =       11;
int LCD_DC_PIN         =        2; //  PB0  4  Data Command
int LCD_CE_PIN         =        3; //  PB2  5  /CS   active low chip select ??
int SPI_MOSI_PIN       =        4; //  PB3  3  Serial   line
int LCD_RST_PIN        =        5; //  PB4  8   /RES RESET
int SPI_CLK_PIN        =        6; //  PB5  2  CLOCK


#define LCD_X_RES                  84
#define LCD_Y_RES                  48



#define LCD_CACHE_SIZE             ((LCD_X_RES * LCD_Y_RES) / 8)

/*--------------------------------------------------------------------------------------------------
 Type definitions
 --------------------------------------------------------------------------------------------------*/



#define    LCD_CMD  0
#define    LCD_DATA  1

#define    PIXEL_OFF   0
#define    PIXEL_ON    1
#define    PIXEL_XOR   2

#define    FONT_1X  1
#define    FONT_2X  2


typedef unsigned int               word;

// Public function prototypes

void LcdInit       ( void );
void LcdClear      ( void );
void LcdUpdate     ( void );
void LcdGotoXY     ( byte x, byte y );
void LcdChr        ( int size, byte ch );
void LcdStr        ( int size, char *dataPtr );
void LcdPixel      ( byte x, byte y, int mode );
void LcdLine       ( byte x1, byte y1, byte x2, byte y2, int mode );
void LcdSendCmd ( byte data, int cd );


// This table defines the standard ASCII characters in a 5x7 dot format.


// Global Variables

byte  LcdCache [ LCD_CACHE_SIZE ];

int   LcdCacheIdx;
int   LoWaterMark;

int   HiWaterMark;
boolean  UpdateLcd;
 char sign;

// This table defines the standard ASCII characters in a 5x7 dot format.
static const byte FontLookup [][5] =
{
  { 
    0x7E, 0x11, 0x11, 0x11, 0x7E     }
  ,   // A
  { 
    0x7F, 0x49, 0x49, 0x49, 0x36     }
  ,   // B
  { 
    0x3E, 0x41, 0x41, 0x41, 0x22     }
  ,   // C
  { 
    0x7F, 0x41, 0x41, 0x22, 0x1C     }
  ,   // D
  { 
    0x7F, 0x49, 0x49, 0x49, 0x41     }
  ,   // E
  { 
    0x7F, 0x09, 0x09, 0x09, 0x01     }
  ,   // F
  { 
    0x3E, 0x41, 0x49, 0x49, 0x7A     }
  ,   // G
  { 
    0x7F, 0x08, 0x08, 0x08, 0x7F     }
  ,   // H
  { 
    0x00, 0x41, 0x7F, 0x41, 0x00     }
  ,   // I
  { 
    0x20, 0x40, 0x41, 0x3F, 0x01     }
  ,   // J
  { 
    0x7F, 0x08, 0x14, 0x22, 0x41     }
  ,   // K
  { 
    0x7F, 0x40, 0x40, 0x40, 0x40     }
  ,   // L
  { 
    0x7F, 0x02, 0x0C, 0x02, 0x7F     }
  ,   // M
  { 
    0x7F, 0x04, 0x08, 0x10, 0x7F     }
  ,   // N
  { 
    0x3E, 0x41, 0x41, 0x41, 0x3E     }
     // O

  ,   // Y
  { 
    0x61, 0x51, 0x49, 0x45, 0x43     }
    //Z
};
/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdSendCmd
 
 Description  :  Sends data to display controller.
 
 Argument(s)  :  data -> Data to be sent
 cd   -> Command or data (see/use enum)
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdSendCmd ( byte data, int cd )
{


  byte i = 8;

  byte mask;



  //

  if ( cd == LCD_DATA )
  {
    digitalWrite(LCD_DC_PIN,HIGH);
  }
  else
  {
    digitalWrite(LCD_DC_PIN,LOW) ;
  }




  while(0 < i) {

    mask = 0x01 << --i; // get bitmask and move to least significant bit
    // cause edge to fall
    digitalWrite(SPI_CLK_PIN,LOW); // tick
    delayMicroseconds(400);
    // set out byte
    if(data & mask){ // choose bit

      digitalWrite(SPI_MOSI_PIN,HIGH); // send 1

    }
    else{

      digitalWrite(SPI_MOSI_PIN,LOW); // send 0

    }

    // cause edge to rise

    digitalWrite(SPI_CLK_PIN,HIGH); // tock
    delayMicroseconds(400);





  }


}

//end of part 1

part 2 of the sketch

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdInit
 
 Description  :  Performs MCU SPI & LCD controller initialization.
 
 Argument(s)  :  None.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdInit ( void )
{

  int m;


  //  Toggle display reset pin.
  digitalWrite(LCD_RST_PIN,LOW);
  delay(40);
  digitalWrite(LCD_RST_PIN,HIGH);

  //  Enable SPI port: No interrupt, MSBit first, Master mode, CPOL->0, CPHA->0, Clk/4
  // SPCR = 0x50;



  LcdSendCmd( 0x21, LCD_CMD );  // LCD Extended Commands.
  LcdSendCmd( 0xB3, LCD_CMD );  // Set LCD Vop (Contrast). //B1
  LcdSendCmd( 0x04, LCD_CMD );  // Set Temp coefficent. //0x04

  LcdSendCmd( 0x13, LCD_CMD );  // LCD bias mode 1:48. //0x13
  LcdSendCmd( 0x20, LCD_CMD );  // LCD Standard Commands, Horizontal addressing mode.

  LcdSendCmd( 0x0C, LCD_CMD );  // LCD in normal mode. 0x0d for inverse
  // LcdSendCmd( 0x0D, LCD_CMD );

  //  Reset watermark pointers.
  LoWaterMark = LCD_CACHE_SIZE;
  HiWaterMark = 0;
  


  
    LcdClear();
  LcdUpdate();
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdContrast
 
 Description  :  Set display contrast.
 
 Argument(s)  :  contrast -> Contrast value from 0x00 to 0x7F.
 
 Return value :  None.
 
 Notes        :  No change visible at ambient temperature.
 
 --------------------------------------------------------------------------------------------------*/
void LcdContrast ( byte contrast )
{
  //  LCD Extended Commands.
  LcdSendCmd( 0x21, LCD_CMD );

  // Set LCD Vop (Contrast).
  LcdSendCmd( 0x80 | contrast, LCD_CMD );

  //  LCD Standard Commands, horizontal addressing mode.
  LcdSendCmd( 0x20, LCD_CMD );
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdClear
 
 Description  :  Clears the display. LcdUpdate must be called next.
 
 Argument(s)  :  None.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdClear ( void )
{
  int i;

  for ( i = 0; i < LCD_CACHE_SIZE; i++ )
  {
    LcdCache[i] = 0x00;
  }

  //  Reset watermark pointers.
  LoWaterMark = 0;
  HiWaterMark = LCD_CACHE_SIZE - 1;

  UpdateLcd = true;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdGotoXY
 
 Description  :  Sets cursor location to xy location corresponding to basic font size.
 
 Argument(s)  :  x, y -> Coordinate for new cursor position. Range: 1,1 .. 14,6
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdGotoXY ( byte x, byte y )
{
  LcdCacheIdx = (x - 1) * 6 + (y - 1) * 84;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdChr
 
 Description  :  Displays a character at current cursor location and increment cursor location.
 
 Argument(s)  :  size -> Font size. See enum.
 ch   -> Character to write.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdChr ( int size, byte ch )
{
  byte i, c;
  byte b1, b2;
  int  tmpIdx;

  if ( LcdCacheIdx < LoWaterMark )
  {
    //  Update low marker.
    LoWaterMark = LcdCacheIdx;
  }

  if ( (ch < 0x20) || (ch > 0x7b) )
  {
    //  Convert to a printable character.
    ch = 65;
  }

  if ( size == FONT_1X )
  {
    for ( i = 0; i < 5; i++ )
    {
      LcdCache[LcdCacheIdx++] = FontLookup[ch - 65][i] << 1;
    }
  }
  else if ( size == FONT_2X )
  {
    tmpIdx = LcdCacheIdx - 84;

    if ( tmpIdx < LoWaterMark )
    {
      LoWaterMark = tmpIdx;
    }

    if ( tmpIdx < 0 ) return;

    for ( i = 0; i < 5; i++ )
    {
      c = FontLookup[ch - 32][i] << 1;
      b1 =  (c & 0x01) * 3;
      b1 |= (c & 0x02) * 6;
      b1 |= (c & 0x04) * 12;
      b1 |= (c & 0x08) * 24;

      c >>= 4;
      b2 =  (c & 0x01) * 3;
      b2 |= (c & 0x02) * 6;
      b2 |= (c & 0x04) * 12;
      b2 |= (c & 0x08) * 24;

      LcdCache[tmpIdx++] = b1;
      LcdCache[tmpIdx++] = b1;
      LcdCache[tmpIdx + 82] = b2;
      LcdCache[tmpIdx + 83] = b2;
    }

    //  Update x cursor position.
    LcdCacheIdx += 11;
  }

  if ( LcdCacheIdx > HiWaterMark )
  {
    //  Update high marker.
    HiWaterMark = LcdCacheIdx;
  }

  //  Horizontal gap between characters.
  LcdCache[LcdCacheIdx++] = 0x00;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdStr
 
 Description  :  Displays a character at current cursor location and increment cursor location
 according to font size.
 
 Argument(s)  :  size    -> Font size. See enum.
 dataPtr -> Pointer to null terminated ASCII string to display.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdStr ( int size, char *dataPtr )
{
  while ( *dataPtr )
  {
    LcdChr( size, *dataPtr++ );
  }
}

part 3 (this is long. note that i kept running out of memory while getting this together fot the atmega8. that's why there are no small letters in the font bitmap)

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdPixel
 
 Description  :  Displays a pixel at given absolute (x, y) location.
 
 Argument(s)  :  x, y -> Absolute pixel coordinates
 mode -> Off, On or Xor. See enum.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdPixel ( byte x, byte y, int mode )
{
  word  index;
  byte  offset;
  byte  data;

  if ( x > LCD_X_RES ) return;
  if ( y > LCD_Y_RES ) return;

  index = ((y / 8) * 84) + x;
  offset  = y - ((y / 8) * 8);

  data = LcdCache[index];

  if ( mode == PIXEL_OFF )
  {
    data &= (~(0x01 << offset));
  }
  else if ( mode == PIXEL_ON )
  {
    data |= (0x01 << offset);
  }
  else if ( mode  == PIXEL_XOR )
  {
    data ^= (0x01 << offset);
  }

  LcdCache[index] = data;

  if ( index < LoWaterMark )
  {
    //  Update low marker.
    LoWaterMark = index;
  }

  if ( index > HiWaterMark )
  {
    //  Update high marker.
    HiWaterMark = index;
  }
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdLine
 
 Description  :  Draws a line between two points on the display.
 
 Argument(s)  :  x1, y1 -> Absolute pixel coordinates for line origin.
 x2, y2 -> Absolute pixel coordinates for line end.
 mode   -> Off, On or Xor. See enum.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdLine ( byte x1, byte y1, byte x2, byte y2, int mode )
{
  int dx, dy, stepx, stepy, fraction;

  dy = y2 - y1;
  dx = x2 - x1;

  if ( dy < 0 )
  {
    dy    = -dy;
    stepy = -1;
  }
  else
  {
    stepy = 1;
  }

  if ( dx < 0 )
  {
    dx    = -dx;
    stepx = -1;
  }
  else
  {
    stepx = 1;
  }

  dx <<= 1;
  dy <<= 1;

  LcdPixel( x1, y1, mode );

  if ( dx > dy )
  {
    fraction = dy - (dx >> 1);
    while ( x1 != x2 )
    {
      if ( fraction >= 0 )
      {
        y1 += stepy;
        fraction -= dx;
      }
      x1 += stepx;
      fraction += dy;
      LcdPixel( x1, y1, mode );
    }
  }
  else
  {
    fraction = dx - (dy >> 1);
    while ( y1 != y2 )
    {
      if ( fraction >= 0 )
      {
        x1 += stepx;
        fraction -= dy;
      }
      y1 += stepy;
      fraction += dx;
      LcdPixel( x1, y1, mode );
    }
  }

  UpdateLcd = true;
}

/*--------------------------------------------------------------------------------------------------
 
 Name         :  LcdUpdate
 
 Description  :  Copies the LCD cache into the device RAM.
 
 Argument(s)  :  None.
 
 Return value :  None.
 
 --------------------------------------------------------------------------------------------------*/
void LcdUpdate ( void )
{
  int i;
  
//always update everything for the moment
LoWaterMark = 0;
HiWaterMark = LCD_CACHE_SIZE - 1;


  if ( LoWaterMark < 0 ){
    LoWaterMark = 0;
  }
  else if ( LoWaterMark >= LCD_CACHE_SIZE ){
    LoWaterMark = LCD_CACHE_SIZE - 1;
  }

  if ( HiWaterMark < 0 ){
    HiWaterMark = 0;
  }
  else if ( HiWaterMark >= LCD_CACHE_SIZE ){
    HiWaterMark = LCD_CACHE_SIZE - 1;
  }

  //  Set base address according to LoWaterMark.
  LcdSendCmd( 0x80 | (LoWaterMark % LCD_X_RES), LCD_CMD );
  LcdSendCmd( 0x40 | (LoWaterMark / LCD_X_RES), LCD_CMD );

  //  Serialize the video buffer.
  for ( i = LoWaterMark; i <= HiWaterMark; i++ )
  {
    LcdSendCmd( LcdCache[i], LCD_DATA );
  }

  //  Reset watermark pointers.
  LoWaterMark = LCD_CACHE_SIZE - 1;
  HiWaterMark = 0;

  UpdateLcd = false;
}

and finally setup() and our loop()

void setup() {

  beginSerial(19200);
  //power control led
  pinMode(CONTROL_LED,OUTPUT); 


  pinMode(LCD_RST_PIN,OUTPUT); 
  pinMode(LCD_DC_PIN ,OUTPUT);
  pinMode(LCD_CE_PIN ,OUTPUT);
  pinMode(SPI_MOSI_PIN ,OUTPUT);
  pinMode(SPI_CLK_PIN,OUTPUT);

  //power the display
  //not used in this sketch. the display was powered permanently
 // pinMode(LCD_POWER_PIN,OUTPUT); 

  //start
  digitalWrite(CONTROL_LED, HIGH); 
  LcdInit();
  
}

void loop() {
 LcdLine ( 0, 0, 83, 47, 2 );
  LcdChr(1,(char)'A');
  LcdStr(1, "BCDEFG");
  LcdUpdate();
}

//kuk

The K107 looks good but it has a awful number of limitations.

Just to clarify some things sort of mis-stated above. Peter Anderson http://www.phanderson.com created the LCD1x7 and LCD1x8 series of PIC chips (currently 16F648A) that serve as the core of the serial to parallel conversion for a HD44780 character based LCD display. He sells the chip and packages a schematic with it.

The K107 is a pcb I designed to house Peter's chip. It s a flexible design which can accomodate 2x7, 1x10, 1x14, and 1x16 pin configurations (2x8 has been added to Rev 4 of the board which will go to production runs in the next month or so). Peter's firmware allows handling of 2x16, 2x20, 2x24, 2x40, 4x16 and 4x20 character geometries (software selectable). The signal input can be TTL TRUe or RS232 INVerted (jumper selectable) and can be had in 2400 baud, 9600 baud, or 19200 baud. The serial baudrate is fixed in firmware specifically to avoid the potential problems, some of which have been discussed above. The K107 board with an Anderson chip comes up running every time. The Anderson firmware provides for all the expected LCD controls, as well as customizable characters, customizable startup splash screen, 4 line high numerals for large displays, etc.

The Anderson chip uses the PIC internal UART and has a 64 character buffer so a very busy display may require some 1-40 ms delays. LCD displays are not fast devices these delays are going to happen no matter how fast you get data to the control board, whether it be serial, SPI or I2C

I wrote a complete library for the K107 based upon the TX part of Software Serial. I run my displays at 19200 on my Arduino and BBB boards all the time with no problems.

I would be interested to know exactly what you feel are the 'awful number of limitations'

The K107 Serial LCD Controller can be seen at http://www.wulfden.org/k107/ and my Freeduino offerings (incuding some bundles with K107 boards and displays) can be seen at http://www.wulfden.org/freeduino/freeduino.shtml.

By the way, while the original Anderson design called for a TIP41C (TO220) to PWM the display backlight. That was overkill. I found that a 2N4401 (TO92) in the negative line of the LED backlight was more than adequate for even the brightest 4x20 backlit displays. I have sold nearly 2000 K107 boards and not one user has complained of the 4401 burning up or getting hot.

cheers ... BBR