Jump to content
Sign in to follow this  
johnc

LCD Plugin bug?

Recommended Posts

Can't get the cursor to position to locations 3,19 or 35 on the LCD for some reason.  Code works ok on a real LCD

 

Here's a test program to show the issue ...  move the DD RAM address back one location at from position 39 one location at a time and write an "X" in the location.  The character that is written to 3 is written to 5, to 19 is written to 21, to 35 is written to 37.  All other locations are just fine.

 

////////////////////////////////////////////////////////////////////////////

// LCD with HD44780 drive chip

////////////////////////////////////////////////////////////////////////////

// Author(s): David Hobday

// Date 4 September 2003

//

// Designed and test for 16F84A

//

// Interface :  

// RS = RA01

// WR = RA02

// E  = RA00

//

// DB7 = RB07

// DB6 = RB06

// DB5 = RB05

// DB4 = RB04

//                                                                              

// Using 4 Bit interface

//

 

/////////////////////////////////////////////////////////////////////////////

// Program to test LCD plugin - with 4 bit interface

// Designed and test for 16F84A

//

// **** Beware MPLABS assembler fails to report when program exceeds memory

// upto 4 words - this can then cause the program to fail!

// This program nearly totally fills the processor!

 

// 20MHz - frequency needs setting high for busy test,

// It write characters faster than they can be handled by the display and

// so get missed. If clock frequency set lower this may not happen

// Remeber also that the simualtor must also be told the clock rate so the plugins

// can convert clock ticks to actual time.

#pragma CLOCK_FREQ 20000000

 

// comment out when running on actual hardware - different delays used

//#define RUN_UNDER_SIM

 

#include <system.h>

 

void LCD_Setup(void);

void LCD_FunctionMode(void);

void LCD_DataMode(void);

void LCD_RawWriteNibble(char);

void LCD_Write(char);

void LCD_RawWrite(char);

char LCD_Read();

void lprintf( const char *lcdptr );   //write string

void LCD_Clear();

void LCD_WaitForNotBusy();

 

char writeDelayType;

 

////////////////////////////////////////////////////////////////////////////

// Control signal bit definitions

////////////////////////////////////////////////////////////////////////////

#define LCD_E    0  

#define LCD_RW   2  

#define LCD_RS   1

 

////////////////////////////////////////////////////////////////////////////

// LCD Commands ( Refer to LCD Data Sheet )

////////////////////////////////////////////////////////////////////////////

#define clear_lcd         0x01 // Clear Display

#define return_home       0x02 // Cursor to Home position

#define entry_mode        0x06 // Normal entry mode

#define entry_mode_rev    0x04 // Normal entry mode  -reverse direction

#define entry_mode_scroll 0x07 // - with shift

#define entry_mode_scroll_rev  0x05 // reverse direction

 

#define system_set_8_bit  0x38 //8 bit data mode 2 line ( 5x7 font )

#define system_set_4_bit  0x28 // 4 bit data mode 2 line ( 5x7 font )

#define system_set_reset  0x30 // Reset code

#define display_on        0x0C // Display ON - 2 line mode

#define display_off       0x08 // Display off

#define set_dd_line1      0x80 // Line 1 position 1

#define set_dd_line2      0xC0 // Line 2 position 1

#define set_dd_ram        0x80 // Line 1 position 1

#define write_data        0x00 // With RS = 1

#define cursor_on         0x0E // Switch Cursor ON

#define cursor_off        0x0C // Switch Cursor OFF

#define cursor_blink_on   0x0F // Cursor plus blink

#define cursor_shift_right 0x14 // Move cursor right

#define cursor_shift_left 0x10 // Move cursor left

#define display_shift_right 0x1C // Scroll display right

#define display_shift_left 0x18 // Scroll display left

 

#define WriteNoDelay 1

#define WriteDelayTime 0

#define WriteUseBusy 2

 

void TestDelay()

{

#ifdef RUN_UNDER_SIM

delay_ms( 2 );

#else

delay_ms( 2 );

#endif

}

 

void TestDelayShort()

{

#ifdef RUN_UNDER_SIM

delay_ms( 1 );

#else

delay_ms( 100 );

#endif

}

 

void main()

{

 

#ifdef RUN_UNDER_SIM

#else

delay_s( 1 ); // power up delay

#endif

 

trisa = 0x00; // port a output

 

while( 1 )

{

LCD_Setup();

 

char i = 0;

 

//////////////////////////////////////////////////

// Cursor Positioning

//////////////////////////////////////////////////

 

LCD_FunctionMode();

LCD_Clear();

LCD_FunctionMode();

LCD_Write( set_dd_ram + 0x06 ); // start text top line, col 7

LCD_DataMode();

lprintf( "TEST" ); // make sure everything is working ok

for( i = 39; i !=0; i-- )

{

LCD_FunctionMode();

LCD_Write( set_dd_ram | i ); // start the cusror at the end

LCD_DataMode(); // of the line and work our way

LCD_Write('X'); // back to 0

TestDelay();

 

}

 

}

}

 

void LCD_Clear()

{

LCD_FunctionMode();

LCD_Write( clear_lcd ); // clear display

LCD_Write( return_home );

delay_ms( 2 );

LCD_DataMode();

}

 

void LCD_Setup(void)

{

writeDelayType = WriteNoDelay; // no delays in data writes

 

delay_ms(16); // Power up delay

LCD_FunctionMode();

 

// Reset sequence as described in data sheets

LCD_RawWriteNibble( system_set_reset >> 4 );

delay_ms(5); // min delay here of 4.1 ms

LCD_RawWriteNibble( system_set_reset >> 4 );

delay_us(100); // min delay here of 100us

LCD_RawWriteNibble( system_set_reset >> 4 );

 

// busy flag is valid from this point onwards

LCD_WaitForNotBusy();

LCD_RawWriteNibble( system_set_4_bit >> 4 );

 

writeDelayType = WriteUseBusy; // use busy

LCD_Write( system_set_4_bit );

 

LCD_Write( display_off );

LCD_Write( entry_mode );

LCD_Write( display_on );

LCD_Write( set_dd_ram );

 

LCD_DataMode();

}

 

void LCD_FunctionMode(void)

{

  output_low_port_a( LCD_RS );

}

 

void LCD_DataMode(void)

{

  output_high_port_a( LCD_RS );

}

 

void LCD_Write(char d )

{

if ( writeDelayType == WriteUseBusy )

LCD_WaitForNotBusy();

 

LCD_RawWrite( d );

 

if ( writeDelayType == WriteDelayTime )

delay_us( 50 ); // enough time for normal command execution - clear and home need longer!!

}

 

void LCD_RawWrite( char d )

{

output_low_port_a( LCD_RW ); // set writing mode

// set port b lower bits to output

trisb &= 0x0F;

 

// output upper nibble

LCD_RawWriteNibble( d >> 4 );

 

// output lower nibble

LCD_RawWriteNibble( d );

}

 

 

void LCD_RawWriteNibble(char d )

{

output_low_port_a( LCD_RW ); // set writing mode

// port b upper nibble output

trisb &= 0x0F;

 

portb &= 0x0F;

portb |= d << 4;

 

// Clock data

  asm NOP // setup time

asm NOP // setup time

asm NOP // setup time

output_high_port_a( LCD_E );

output_low_port_a( LCD_E );  

asm NOP ;// holdup time

}

 

char LCD_Read()

{

char d;

 

// portb upper nibble input

trisb |= 0xF0;

output_high_port_a( LCD_RW ); // set reading mode

 

// data valid while EN high -

 

// first high nibble

output_high_port_a( LCD_E );

asm NOP // setup time

asm NOP // setup time

asm NOP // setup time

 

d = portb & 0xF0 ;

output_low_port_a( LCD_E );  

 

// then low nibble

output_high_port_a( LCD_E );

asm NOP // setup time

asm NOP // setup time

asm NOP // setup time

 

d |= portb >> 4;

output_low_port_a( LCD_E );  

 

return d;

}

 

void LCD_WaitForNotBusy()

{

char old_RS;

// save RS current state

old_RS = porta & ( 1 << LCD_RS );

 

output_low_port_a( LCD_RS );

while( LCD_Read() & 0x80 ); // wait while busy set

 

if ( old_RS ) // restore RS if necessary

output_high_port_a( LCD_RS );

}

 

void lprintf( const char *lcdptr )

{

char pi;

char c;

pi = 0;

                                         

   while( 1 )

   {

c = lcdptr[pi++];

if ( c + 1 == 1 ) // funny code here as c == 0 fails with compiler V5.1

break;

if ( c == '\n' )

{

LCD_FunctionMode();

LCD_Write( set_dd_ram + 0x40 );

LCD_DataMode();

}

else

LCD_Write( c );// Display on LCD

}

}

Share this post


Link to post
Share on other sites
Guest Dave

John,

 

Yep its a bug in LCD plugin - I think this is the first one :P . Quite a nice subtle one.

 

The plugin LCD thinks its getting a reset sequence (0x30 on upper nibble of the data bus three times is reset), so it starts eat the data. Then it finds its not a reset and continues.

 

19 in hex is 0x13, and in this case the display is used in 4 bit mode, so all data is on the upper nibble of the data bus.

 

Nicely spotted :)

 

Should be fixed soon.

 

Regards

Dave

Share this post


Link to post
Share on other sites
Guest john

Can you shoot over the new revision when you have fixed? :P   would make finishing / debugging my project much easier.

 

thanks !

 

johnc

Share this post


Link to post
Share on other sites
Guest johnc

I must be blind.  Where is it?  Down loaded the Extra Plugin's again and they seem to be the 4/3/04 version ...  Am I missing something?

 

johnc

Share this post


Link to post
Share on other sites
Guest Pavel
I must be blind.  Where is it?  Down loaded the Extra Plugin's again and they seem to be the 4/3/04 version ...  Am I missing something?

 

johnc

You need "LCD Plugin path" that is in the bottom of download table that is on the top of download page. Here is direct link:

http://www.picant.com/download/lcd.zip

 

Regards,

Pavel

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...