Pages: 1 ... 3 4 [5] 6 7 ... 10   Go Down
Author Topic: New LiquidCrystal library - LCD library  (Read 19838 times)
0 Members and 1 Guest are viewing this topic.
Western New York, USA
Online Online
Faraday Member
**
Karma: 25
Posts: 4113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Maybe he will chime in.
Ding-Dong

I think John took care of all this in LiquidCrystal440. 

This will handle most displays and should be the default:
00
40
14
54

This is for the 16x4:
00
40
10
50

(all are in hex)


Don
Logged

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 38
Posts: 2173
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Don, thanks for ringing in, I will make good note to have that in the code for next release.
Logged

   

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 38
Posts: 2173
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Release 1.2.0 of the New LiquidCrystal library is available for download.

This version has very nice features added:
- substantial performance improvements for the Shiftregister class and the 4BIT mode has been polished.
- configuration and backlight control through the library.
- support for a wide range on shift register LCDs, currently completing a 1 wire SR mode.
- new methods to control the backlight
- new methods to move the cursor left and right.
- mayor library refactoring which makes it very easy to add support for other HW LCD controllers.

You can download version 1.2.0 from: https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads

Benchmarks

Execution time

                LiquidCrystal    4BIT        ShiftRegister    ShiftRegister SR_LCD3     I2C
benchmark1      11055 us         2966 us     3132 us          5355 us                   47809 us
benchmark2      125770 us        34660 us    34982 us         60446 us                  541634 us
benchmark3      13660 us         3616 us     3824 us          6564 us                   59071 us
benchmark4      13643 us         3597 us     3804 us          6544 us                   59051 us

Average LCD write operation time

                LiquidCrystal      4BIT        ShiftRegister     ShiftRegister SR_LCD3     I2C
write op.       325 us             87 us       91 us             156 us                    1406 us

Performance ratio vs LiquidCrystal library

                LiquidCrystal      4BIT        ShiftRegister     ShiftRegister SR_LCD3     I2C
Performance     1                  3.72        3.57              2.08                      0,23
Logged

   

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2338
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A few things that need updating and couple of suggestions for enhancements/improvements.


Needed updates:
------------------------
You can't get away with not masking interrupts during
fio_digitalWrite_xxx() routines.

You run the risk of corrupting registers by doing this.
If the user is using other bits/pins in the port for other things and touch the port bits
during their ISRs then the lcd library will corrupt their port bits.



Other Suggestions:
--------------------------

I wouldn't use LOW in shiftOut1() in this if statement:
Code:
// assume that pin is HIGH (smokin' pot all day... :) - requires initialization
if(LOW==!!(value & (1 << i)))
This assumes LOW is 0.
This is a case where 0/1 or zero/non-zero really is needed.

- Bit ordering in shiftout()
I'd eliminate the bit ordering support in the fio_shiftout() routine.
The output bits of the SR are defined based on a bit ordering
so there should not be a need to support shifting
either direction. I'd pick a direction and only support that one way.
(just like in the fio_shiftOut1() routine)

- reduced interrupt mask time in shiftOut1()
The critical times that need interrupt masking are during
fio_digitalWrite_xxx() calls (to prevent port bit corruptions) and during the timing for the 0 and 1 bit clocking
(to ensure proper 1 to 0 discharge timing).
There is no need to mask interrupts during the 0 to 1 recharge time or during
either delay during the latch cycle. Those delays can be any time as long as they
are at least as long as the requested delay.

The current routine will block interrupts for close to 1ms which IMO is too long.
(worst case is sending a 0 byte)
What you want to do is mask interrupts when you set the clock/data bit and
when you time the 1 to 0 discharge time but then unmask it after you turn the bit back to 1
during the recharge time.

Here is what I'm talking about for shiftOut1()
(untested, but this is pretty much the same code I'm using in my 1 wire lcd code)

Code:
void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value, boolean noLatch)
{
        /*
         * this function are based on Shif1 protocol developed by Roman Black (http://www.romanblack.com/shift1.htm)
         *
         * test sketches:
         *      http://pastebin.com/raw.php?i=2hnC9v2Z
         *      http://pastebin.com/raw.php?i=bGg4DhXQ
         *      http://pastebin.com/raw.php?i=tg1ZFiM5
         *    http://pastebin.com/raw.php?i=93ExPDD3 - cascading
         * tested with:
         *      TPIC6595N - seems to work fine (circuit: http://www.3guys1laser.com/
         *                   arduino-one-wire-shift-register-prototype)
         *      7HC595N
         */

        // Track interrupt state for later
        uint8_t oldSREG;
        oldSREG = SREG;

        // iterate but ignore last bit (is is set when latch is done)
        for(int8_t i = 7; i>0; --i)
        {

                // assume that pin is HIGH (smokin' pot all day... :) - requires initialization
                if(value & _BV(i))
                {
                        // HIGH = 1 Bit
                        cli();
                        fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
                        fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH); // clock in bit, no delay needed to clock high bit
                        SREG = oldSREG;
                        delayMicroseconds(15); //hold pin HIGH for at least 15us to recharge
                }
                else
                {
                        // LOW = 0 Bit
                        cli();
                        fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
                        delayMicroseconds(15);                                    // hold pin LOW for 15us to create low bit
                        fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH); // clock in bit
                        SREG = oldSREG;                                           // hold pin HIGH for at least 30us to recharge
                        delayMicroseconds(30);
                }
        }
        if(!noLatch)
        {
                // send last bit (=LOW) and Latch command
                cli();
                fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
                SREG = oldSREG;
                delayMicroseconds(199);                          // Hold pin low for at least 200us to lower latch signal
                cli();
                fio_digitalWrite_HIGH(shift1Register,shift1Bit); // latch all bits to output
                SREG = oldSREG;
                delayMicroseconds(299);                          // Hold high for at least 300us to recharge and leave it that way
        }
}

BTW, there are ways to speed up the 1 wire mode by a factor 5 to 10 which
will make it faster than the 2 wire mode when 2 wire mode uses the standard shiftout()
function.
But it requires a different hardware design and closer attention to the charge/discharge times.
Ideally the charge/discharge delays could be configurable in the constructor to allow different
hardware designs.

--- bill




Logged

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 38
Posts: 2173
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bill, thanks for your comments and support. I will pass on the comments which I am sure will be seen on 1.2.1.
Logged

   

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If I might make a suggestion with regard to the I2C...

I appreciate the use of a constructor to initialise the device specific EN, RW and RS values however I feel that it needs to be expanded to permit the specification of the back light values which are presently covered by the defines
Code:
#define LCD_NOBACKLIGHT 0x00
#define LCD_BACKLIGHT   0xFF
I can see that there is a setBacklightPin method but i'm not sure that it covers all the options.

From the code samples I have gathered and my own hardware I have uncovered these as all being valid mask values.
#define LCD_BACKLIGHT 0x00
#define LCD_BACKLIGHT 0x08
#define LCD_BACKLIGHT   0xFF

#define LCD_NOBACKLIGHT 0x80
#define LCD_NOBACKLIGHT 0x00

I suspect it would be easier to just permit developers to input their masks directly through a constructor.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2338
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think masks need to be input or that there needs to be other BACKLIGHT defines.
While the variable names are very confusing the mask seems to be calculated from the
pin number.
Have look at setBacklightPin() :
Code:
void LiquidCrystal_I2C::setBacklightPin ( uint8_t pin )
{
   _backlightPin = ( 1 << pin );
}

_backlightPin holds the actual data byte mask while _backlightMask
holds the mask or 0 if the backlight is off.
While it seems to work, it is very confusing to use the name _backlightPin to
hold the mask for the pin (fm, Hint.... Hint....)

That said, it might be nice to support being able to specify the backlight pin/bit in a constructor.

My concern is more the "mode" argument to setBacklight()
In the LCD API 1.0 recommendation: http://arduino.cc/playground/Code/LCDAPI
the prototype is different: setBacklight(val);
where val is a brightness value vs a LOW/HIGH mode value.
That allows the same function to work without dimming as well as
with PWM dimming for interfaces that have PWM  control over the backlight.

I would prefer setBacklight() to conform to the LCD API 1.0 rather than use a LOW/HIGH mode
that way dimming would work as well.

It is a very small change to support this.
That way I2C would get on/off control and the parallel interface would get dimming support.
[The digitalWrite() in the parallel code turns in to a analogWrite() ]

--- bill
« Last Edit: March 01, 2012, 11:22:32 pm by bperrybap » Logged

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


I can see that there is a setBacklightPin method but i'm not sure that it covers all the options.

smiley
I was being polite and wasn't actually doubtful.

Look at how it's used.

The library backlight off mask is 0x00. You cannot "&" a pin value to that to get a backlight off mask of  0x80 for the hardware that needs it.

Better to just let the masks be specified.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2338
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


I can see that there is a setBacklightPin method but i'm not sure that it covers all the options.

smiley
I was being polite and wasn't actually doubtful.

Look at how it's used.

The library backlight off mask is 0x00. You cannot "&" a pin value to that to get a backlight off mask of  0x80 for the hardware that needs it.

Better to just let the masks be specified.


The current code allows any pin/bit (mask) that is wanted/needed but does assume positive logic
to drive the backlight.

It wasn't clear to me what you were wanting/asking for.

Are you wanting support for inverted logic on the backlight?
i.e. logic 0 turns the backlight on and logic 1 turns the backlight off?

(have you seen a board out there that does it this way?)

I think to support both positive and negative logic there has to be more than a single
piece of information regardless of whether it is a bit number or a mask.
So it would need either a bit number and a flag or two bit masks.
Since all the other connections are specified in bit numbers, I'd lean towards a bit number and a positive/negative
logic flag for the backlight rather than two bitmasks.

Now if  there is a desire to support dimming through multiple output pins, then it does get a bit more complicated
in that now there must be a way to deal with how to map the intensity to the multiple pins.
Say for example I have an extra pin on my SR. I could two 2 pins to 2 transistors with two different resistors and
now I have the ability to do 3 intensities and off.

What were you thinking?

--- bill
Logged

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is nothing complicated in what I have posted. It's pretty simple and straight forward and requires no second guessing of my intent.

The person who modified the I2C version to work with the attiny85 put in his settings for his LCD and that included the troublesome backlight mask that I have mentioned.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2338
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is nothing complicated in what I have posted. It's pretty simple and straight forward and requires no second guessing of my intent.

But it isn't straight forward.
I can't figure out what you want since you are not being specific nor pointing directly to exact code to reference.
Leaving people to guess what you mean isn't a good way to communicate your desires.
So I'll ask again.
What is it that you are wanting?

Beyond wanting to modify the constructors for additional information,
Are you wanting to to support negative logic for the backlight control?

Quote
The person who modified the I2C version to work with the attiny85 put in his settings for his LCD and that included the troublesome backlight mask that I have mentioned.


The code that fm posted that I looked at only uses 0x00 and 0xff for BACKLIGHT defines to turn on/off the bitmask
that controls the backlight.

I can't find any references to the other BACKLIGHT defines you mentioned in fm's code
so I'm not seeing any troublesome masks.

Can you provide a link to code and exact modules and line numbers
of the problems you are talking about?

--- bill
Logged

Guildford, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 217
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is nothing complicated in what I have posted. It's pretty simple and straight forward and requires no second guessing of my intent.

I don't wish to disagree with you, but I'm not clear what you're after either. I do not think it's clear or straight forward.

Iain
Logged

Australia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To someone who understands the code segment and functionality that I spoke about it should be quite clear.

I am not here to explain the inner workings of I2C and LCD's to people who just want to argue.
 smiley-roll

Let me google that for you

Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2338
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To someone who understands the code segment and functionality that I spoke about it should be quite clear.

I am not here to explain the inner workings of I2C and LCD's to people who just want to argue.
 smiley-roll

Let me google that for you


Ah, i see we have a smart ass on our hands.

First, before this post, you never posted any code, any code segments, nor  any links to any code.
You only babbled about masks and some not completely clear statements that possibly
could be interpreted as the desire for negative logic to control the backlight circuitry.

2nd what you were talking about has absolutely NOTHING to do with I2C it has to do with setting output pins
to control the backlight circuitry and even that doesn't really have anything to do with LCDs.

3rd, when modifying multi layer API interfaces for these kinds of bit twiddling control,
the changes can have implications beyond just the i2c device layer. The same modifications
can apply to the other interfaces as well which means it should be handled in a generic/common way.
So your thinking about just ic2 expander output bits is way too narrow.

Well after looking at the attiny85 code you so graciously finally provided a link to above, which has nothing to do with fm's code,
I can see that the tiny85 code that you are looking at hard codes the backlight control to bit 7 as well as
uses negative logic for backlight control.

Without seeing actual code, there was no way to know for sure what you were babbling about in your previous posts.

fm's code already allows using any bit for backlight control but presumes positive logic.

So what you were really wanting all this time but were unable to verbalize in a way that
was pretty simple and straight forward and requires no second guessing of your intent
was that you were wanting support for negative logic for backlight control.

Gee, it would have been so much simpler if you would have just come right out and said
that is what you wanted/needed, especially since I even asked if that was what you wanted.

--- bill


Logged

Málaga, Spain
Offline Offline
Edison Member
*
Karma: 38
Posts: 2173
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Bill, thanks for the hints you've posted. I have noted them down for library improvements on coming versions.

@m12lrpv - I think that we are talking about different libraries. In this particular case (for the New LiquidCrystal), the library, in its I2C configuration does support three main class constructors: only address, address + EN, RS, RW, address + EN, RS, RW + Di (i=1..4).
As for negative logic control, with the current methods it is possible but on the code it will look strange: setBackligh (LOW) -> will change to 0, will switch on the light. setBacklight (HIGH) -> will change to 255, will set the backlight off.
Logged

   

Pages: 1 ... 3 4 [5] 6 7 ... 10   Go Up
Jump to: