Skip to content

Commit 6e3b436

Browse files
authored
Merge pull request #26 from markisch:feature-faster
Speed up transfers
2 parents a61ebb2 + c6c6531 commit 6e3b436

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

src/LiquidCrystal_PCF8574.cpp

+35-10
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ void LiquidCrystal_PCF8574::createChar_P(uint8_t location, const byte *charmap)
267267
byte c = pgm_read_byte(p++);
268268
write(c);
269269
}
270-
} // createCharPgm()
270+
} // createChar_P()
271271
#endif
272272

273273

@@ -282,33 +282,58 @@ inline size_t LiquidCrystal_PCF8574::write(uint8_t ch)
282282
// write either command or data
283283
void LiquidCrystal_PCF8574::_send(uint8_t value, bool isData)
284284
{
285+
// An I2C transmission has a significant overhead of ~10+1 I2C clock
286+
// cycles. We consequently only perform it only once per _send().
287+
288+
Wire.beginTransmission(_i2cAddr);
285289
// write high 4 bits
286-
_sendNibble((value >> 4 & 0x0F), isData);
290+
_writeNibble((value >> 4 & 0x0F), isData);
287291
// write low 4 bits
288-
_sendNibble((value & 0x0F), isData);
292+
_writeNibble((value & 0x0F), isData);
293+
Wire.endTransmission();
289294
} // _send()
290295

291296

292297
// write a nibble / halfByte with handshake
293-
void LiquidCrystal_PCF8574::_sendNibble(uint8_t halfByte, bool isData)
298+
void LiquidCrystal_PCF8574::_writeNibble(uint8_t halfByte, bool isData)
294299
{
295300
// map the data to the given pin connections
296-
uint8_t data = 0;
301+
uint8_t data = isData ? _rs_mask : 0;
302+
// _rw_mask is not used here.
303+
if (_backlight > 0)
304+
data |= _backlight_mask;
297305

298306
// allow for arbitrary pin configuration
299307
if (halfByte & 0x01) data |= _data_mask[0];
300308
if (halfByte & 0x02) data |= _data_mask[1];
301309
if (halfByte & 0x04) data |= _data_mask[2];
302310
if (halfByte & 0x08) data |= _data_mask[3];
303311

304-
_write2Wire(data, isData, true);
305-
delayMicroseconds(1); // enable pulse must be >450ns
306-
_write2Wire(data, isData, false);
307-
delayMicroseconds(37); // commands need > 37us to settle
312+
// Note that the specified speed of the PCF8574 chip is 100KHz.
313+
// Transmitting a single byte takes 9 clock ticks at 100kHz -> 90us.
314+
// The 37us delay is only necessary after sending the second nibble.
315+
// But in that case we have to restart the transfer using additional
316+
// >10 clock cycles. Hence, no additional delays are necessary even
317+
// when the I2C bus is operated beyond the chip's spec in fast mode
318+
// at 400 kHz.
319+
320+
Wire.write(data | _enable_mask);
321+
// delayMicroseconds(1); // enable pulse must be >450ns
322+
Wire.write(data);
323+
// delayMicroseconds(37); // commands need > 37us to settle
324+
} // _writeNibble
325+
326+
327+
// write a nibble / halfByte with handshake
328+
void LiquidCrystal_PCF8574::_sendNibble(uint8_t halfByte, bool isData)
329+
{
330+
Wire.beginTransmission(_i2cAddr);
331+
_writeNibble(halfByte, isData);
332+
Wire.endTransmission();
308333
} // _sendNibble
309334

310335

311-
// private function to change the PCF8674 pins to the given value
336+
// private function to change the PCF8574 pins to the given value
312337
void LiquidCrystal_PCF8574::_write2Wire(uint8_t data, bool isData, bool enable)
313338
{
314339
if (isData)

src/LiquidCrystal_PCF8574.h

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class LiquidCrystal_PCF8574 : public Print
101101
// low level functions
102102
void _send(uint8_t value, bool isData = false);
103103
void _sendNibble(uint8_t halfByte, bool isData = false);
104+
void _writeNibble(uint8_t halfByte, bool isData);
104105
void _write2Wire(uint8_t data, bool isData, bool enable);
105106

106107
void init(uint8_t i2cAddr, uint8_t rs, uint8_t rw, uint8_t enable,

0 commit comments

Comments
 (0)