Thanks @common_ground, I've pushed a fix to the library maintainer
https://github.com/marcoschwartz/LiquidCrystal_I2C/pull/5
hopefully he will merge it and fix the problem for everyone.
@huginen have you already solved the issue by yourself? If no, may you test the patch
https://github.com/marcoschwartz/LiquidCrystal_I2C/pull/5/files
and tell if it works for you?
Cristian,
While there was an issue in the i2c library that was triggered by this new Print class code,
there is a still a fundamental issue with new new Print class code.
The issue is that the Print class code is actually composed of two parts. The low level functions like read()/write() and the higher level output formatting functions like print().
And both layers support partial/incomplete i/o.
(outputting less than the maximum asked to output)
I believe that if print() is allowed to support partial/incomplete i/o, that we will be fighting related issues for years.
What seems to have happened is that in 1.6.6. write() was updated to properly support incomplete i/o and print() is now seeing issues because it doesn't support incomplete i/o.
(An error is essentially a single type of incomplete i/o)
Yes it was a coding error in a library in this case, but it brings up a larger issue related to partial/incomplete i/o and the print() functions.
Currently, I don't believe that the write() API is mandated to always swallow all the data provided unless there is an error.
So the issues becomes, how to deal with print() when write() does incomplete/partial i/o?
Looking forward, unless the write() API mandates blocking when low level buffers are full or updating the Print class print() functions to ensure blocking, when write() returns after incomplete i/o, I think we will see more issues in the future.
While it is ok for functions like write() to support and potentially even require supporting incomplete i/o, it is not appropriate for functions like print() to force this same requirement back up to its callers.
This is because callers of write() know the full contents of what is being output. The callers of print() do not know the full contents of what is being output since print() is performing output formatting.
In other words suppose I do something like:
foo.print(bar);
and the variable bar is an big integer number and is is 1234567
Now suppose that the low level i/o library buffer is full and rather than block (spin) waiting for enough room to take all the requested output, decides to take only what it can.
Suppose that was only 4 bytes.
So the low level i/o library write() will return 4 and then foo.print() will now return 4.
What the heck is a sketch or any other potentially caller of print() code, supposed to do with that?
It has no way of resuming the output nor does it even know how many total output characters there were.
The point is that if the API is going to support incomplete i/o, it MUST have a option to enable/disable this mechanism for functions like print() to not return until all output characters have been handed off.
(The only exception is a fatal error where the i/o would never complete)
I argued this point (enable/disable incomplete/async i/o) a year or so ago when we were looking at and arguing over the buffer available function calls.
There must be a way to allow users of the Print class, specifically the print() functions to have a mechanism to be assured that when the print() function returns that all the characters have been handed off.
This is an absolute requirement since only print() knows what characters are to be output when formatting is done. The caller has no idea.
It is unacceptable to require all users of the print() calls to have to support incomplete i/o.
And even if they do support incomplete i/o, there is no way to complete the i/o for output that was formatted by print() like number output.
Suppose somebody writes an i/o library that decides to do very limited output buffering and simply returns 0 when the output buffer is full vs blocking? This is allowed by the API but a sketch would never be able to print numbers using print() calls when the numbers were more digits than output buffer could hold, even if the sketch code add in all the complexities to support incomplete i/o for print() functions.
I'm strongly suggesting that print() use blocking i/o.
If non blocking print() i/o behavior is supported by print() (which I don't even think is possible since print() does output formatting), then there needs to be an API to enable incomplete i/o for an object (disabled by default) so that sketches can get the existing blocking behavior by default which preserves backward compatibility and keeps user sketches simple.
But I'd still recommend that print() be kept simple and always be blocking since there is no real technical way to support incomplete i/o with print() functions.
Return on errors, yes, but not incomplete i/o.
With regard to errors vs partial i/o. That brings up another API issue.
The write() API should be able to distinguish between errors and incomplete i/o.
for example, if the hardware is broken and it can't transmit, how can that be indicated?
Currently, if you return zero, then that could mean the low level buffers are full (incomplete i/o) or it could mean an actual error.
A negative value would be better to indicate an error.
--- bill