CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

2 x 16 Fordata lcd display at 80 Mc/s [Solved]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
smee



Joined: 16 Jan 2014
Posts: 24

View user's profile Send private message

2 x 16 Fordata lcd display at 80 Mc/s [Solved]
PostPosted: Sun Jun 02, 2019 5:38 am     Reply with quote

Could someone help me with this?

I have a dspic33fj128gp802 connected to a Fordata 3v lcd.
Farnell part number 2674133, it uses the splc780d chip.

I have been using Ttelmah's speeded up driver for the lcd.
But i cannot for the life of me, get the thing to function properly.

It misses characters.

The example '/fTest of print' will display
' Ts f rnt' for example.

I am using ICD3 with mplab 8.92 and compiler version 4.120.

Code:

// test of display.

#include "33FJ128GP802.h"   // include the processor header file
#ifdef __DEBUG
   #device icd=true
#endif

#FUSES NOWDT
#FUSES FRC_PLL
//#FUSES PUT128
#FUSES ICSP1
#FUSES NOJTAG
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOIESO   // NO INTERNAL/EXTERNAL SWITCHOVER
#build (stack=4096)

#OCS 80 Mhz

// LCD connections

#define LCD_DB4   PIN_B10
#define LCD_DB5   PIN_B9
#define LCD_DB6   PIN_B8
#define LCD_DB7   PIN_B6

#define LCD_RS    PIN_A2
#define LCD_RW    PIN_A3
#define LCD_E     PIN_A4

#ifndef __DEBUG
   #define BLight   PIN_B1
#endif



//-----------------------------------
// LCD Display
unsigned int8 Lcd_address;
#include "LCD216/Flex_new.c"   // include the lcd driver
//-----------------------------------


#zero_ram

void main()
{


delay_ms(500);
lcd_init();   // initialise the lcd display

printf(lcd_putc,"\fTest of print");

do { } while (1==1);

}




and the flex_new file is

Code:

// Flex_LCD420.c
//PCM_Programmer's flex_lcd driver for 4x20
//Modified for the chip being used in this thread, and PIC24/30

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.  Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD.  It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit.  Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.
#define USE_RW_PIN   1     
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW   1     
// these are the line addresses for the fordata 2 x 16 lcd.

#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x28

// Screen is 16 characters wide.
#define LCD_WIDTH 0x10


// These are the line addresses for most 4x20 LCDs.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54
*/

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/





//========================================

#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)

unsigned int8 lcd_line;

unsigned int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
 0xc,                     // Display on
 1,                       // Clear display
 6                        // Increment cursor
 };
                             
//#define INS_TIME 1000000000LL/(getenv("INSTRUCTION_CLOCK"))
//Gives time for one instruction in nSec

#define INS_TIME 50
//#define INS_TIME 10   // have doubled the actual
// 50 nano seconds instruction time

#define NS80 ((80/(INS_TIME))+1)
//gives instruction count for 80nSec (remember though integer so
//rounds down). Hence +1 instruction.
#define NS320 ((320/(INS_TIME))+1)
//gives instruction count for 320nSec.

#use standard_io(a)
#use standard_io(b)



//-------------------------------------
void lcd_send_nibble(unsigned int8 nibble)
{
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));   
 output_bit(LCD_DB7, !!(nibble & 8));   

 //delay_cycles(1); //Issue here not enough delay at fast CPU speeds
 delay_cycles(NS80); //min 80nSec
 output_high(LCD_E);
 delay_us(1);
 output_low(LCD_E);
// delay_us(1);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.     

#ifdef USE_RW_PIN
unsigned int8 lcd_read_nibble(void)
{
unsigned int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;
   
output_high(LCD_E);
delay_us(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
 
output_low(LCD_E);
delay_us(1);
   
return(retval);   
}   
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_RW_PIN
unsigned int8 lcd_read_byte(void)
{
unsigned int8 low;
unsigned int8 high;
output_high(LCD_RW);
//same delay issue here
delay_cycles(NS320); //320nSec minimum required
high=0;
high = lcd_read_nibble();
high=high<<4;
low=0;
low = lcd_read_nibble();
low=high | low;
return(low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(unsigned int8 address, unsigned int8 n)
{
unsigned int8 x,z;
output_low(LCD_RS);

#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
Lcd_Address=x;
#else
delay_us(60);
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);
     
#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif
delay_cycles(NS320);

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------
void lcd_init(void)
{// initialise the lcd ready for use.
unsigned int8 i;
output_low(LCD_E);
lcd_line = 1;
output_low(LCD_RS);
#ifdef USE_RW_PIN
   output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(45);   // Greater than 40ms after vdd =2.7v     

lcd_send_nibble(0x03);
delay_ms(5);
lcd_send_nibble(0x03);
delay_us(100);
lcd_send_nibble(0x03);
while(bit_test(lcd_read_byte(),7)) ;
lcd_send_nibble(0x02);
while(bit_test(lcd_read_byte(),7)) ;
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);
    #ifndef USE_RW_PIN
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(unsigned int8 x, unsigned int8 y)
{
unsigned int8 address;


switch(y)
  {
   case 1:
     address = LCD_LINE_1_ADDRESS;
     break;

   case 2:
     address = LCD_LINE_2_ADDRESS;
     break;

//   case 3:
//   address = LCD_LINE_3_ADDRESS;
//     break;

//   case 4:
//     address = LCD_LINE_4_ADDRESS;
//     break;

   default:
     address = LCD_LINE_1_ADDRESS;
     break;
     
  }

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------

//------------------------------
void lcd_putc(char c)
{
 switch(c)
   {
//   case 36:
//      lcd_send_byte(1,1); // translates to correct currency.
//   break;
    case '\f':
      lcd_send_byte(0,1);      // 0x01=clear the display
      lcd_line = 1;
      delay_ms(2);
      break;
   
    case '\n':
        lcd_gotoxy(1, ++lcd_line);
      lcd_send_byte(1,' ');
       break;
   
    case '\b':
       lcd_send_byte(0,0x10);
       break;
    case '\r':
        lcd_gotoxy(1, lcd_line);
      lcd_send_byte(1,' ');
       break;
    default:
       lcd_send_byte(1,c);
       break;
   }
  if (lcd_line>2)
     {
       lcd_line=1;
     }
if (lcd_line==1)
if (Lcd_Address>16)
   {
   lcd_gotoxy(1, lcd_line);
   lcd_send_byte(1,' ');
   }

if (lcd_line==2)
if (Lcd_Address>(0x28+16))
   {
   lcd_gotoxy(1, lcd_line);
   lcd_send_byte(1,' ');
   }

}
//------------------------------
#ifdef USE_RW_PIN
char lcd_getc(unsigned int8 x, unsigned int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value = lcd_read_byte();
output_low(LCD_RS);
return(value);
}
#endif


I have altered some bits of this from Ttelmah's original, but only in desperation.
I don't know what to do next.


Last edited by smee on Tue Jun 04, 2019 8:35 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9136
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jun 02, 2019 6:40 am     Reply with quote

I downloaded the spec sheet from Farnell for the LCD module. TR, TF ( rise time, fall time) is specified at typical 150 milliseconds. While there is no minimum listed, well, there has to be ! There isn't a 'device access speed' listed.
I suspect you're accessing it way too fast. I haven't time to look at the revised driver but generally speaking LCD modules are SLOW.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jun 02, 2019 9:04 am     Reply with quote

List the connections between the PIC and the lcd.
Ttelmah



Joined: 11 Mar 2010
Posts: 19266

View user's profile Send private message

PostPosted: Sun Jun 02, 2019 9:46 am     Reply with quote

In the posted code, there is no #use delay statement.
delays won't give the times they should without this. Result the code
won't work.

#OCZ, does not do the clock configuration that #USE DELAY does. Use
#USE DELAY, otherwise PLL setups etc., will not always be done correctly.
smee



Joined: 16 Jan 2014
Posts: 24

View user's profile Send private message

PostPosted: Tue Jun 04, 2019 6:59 am     Reply with quote

I have made the following alterations to the code.

main.c
Code:

// test of display.

#include "33FJ128GP802.h"   // include the processor header file
#ifdef __DEBUG
   #device icd=true
#endif

#FUSES NOWDT
#FUSES FRC_PLL
//#FUSES PUT128
#FUSES ICSP1
#FUSES NOJTAG
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOIESO   // NO INTERNAL/EXTERNAL SWITCHOVER
#build (stack=2048)

//#OCS 80 Mhz
#use delay(internal=80mhz)



// LCD connections

#define LCD_DB4   PIN_B10
#define LCD_DB5   PIN_B9
#define LCD_DB6   PIN_B8
#define LCD_DB7   PIN_B6

#define LCD_RS    PIN_A2
#define LCD_RW    PIN_A3
#define LCD_E     PIN_A4

#ifndef __DEBUG
   #define BLight   PIN_B1
#endif

//-----------------------------------
// LCD Display
unsigned int8 Lcd_address;
//#include "LCD216/Flex_new.c"   // include the lcd driver
#include "LCD216/Flex_orig.c"
//-----------------------------------

#zero_ram

void main()
{

output_low(LCD_E);
output_low(LCD_RW);
output_low(LCD_RS);

output_low(LCD_DB4);
output_low(LCD_DB5);
output_low(LCD_DB6);
output_low(LCD_DB7);

delay_ms(500);
lcd_init();   // initialise the lcd display

printf(lcd_putc,"\fTest of screen");

do {
output_toggle(PIN_B7);
delay_ms(1);
 } while (1==1);

}


The file flex_orig.c is that posted from
http://www.ccsinfo.com/forum/viewtopic.php?t=57617
The posting is by Ttelmah.

It still malfunctions.
I can fix it by putting a delay_ms(1) at the start of lcd_putc.

But i can not understand why it won't function correctly without it.
I now have the output_toggle at the end to prove that the timings are correct, which they are.
Ttelmah



Joined: 11 Mar 2010
Posts: 19266

View user's profile Send private message

PostPosted: Tue Jun 04, 2019 7:32 am     Reply with quote

I'd suspect the issue is your splc780d chip timings.

The calculations I did were to just ensure the 80nSec and 320nSec timings
needed by the standard Hitachi controller. You'd need to go through the
data sheet for this chip and see where it differs. You'll probably find the
actual data cycle time requires just a little more delay than is being given.
smee



Joined: 16 Jan 2014
Posts: 24

View user's profile Send private message

PostPosted: Tue Jun 04, 2019 8:33 am     Reply with quote

The splc780d has a faster response than those used, so it should of have worked out of the box.

I have been looking at the data sheets.
My current fix, is to test for the busy flag to be clear at the end of the lcd_send_byte function.

Exiting only once the busy flag is clear, seems to fix it.

Entry to exit of the lcd_send_byte function is averaging about 25us.

Thank you to everyone for the help. Very Happy
Ttelmah



Joined: 11 Mar 2010
Posts: 19266

View user's profile Send private message

PostPosted: Tue Jun 04, 2019 10:36 am     Reply with quote

It doesn't have faster timings. Slightly slower, but not enough to matter.
It has faster on the first, but slower on the second.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group