1 /* Arduino SSD1306Ascii Library
2 * Copyright (C) 2015 by William Greiman
4 * This file is part of the Arduino SSD1306Ascii Library
6 * This Library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with the Arduino SSD1306Ascii Library. If not, see
18 * <http://www.gnu.org/licenses/>.
22 * @brief Small fast I2C class for AVR.
28 /** Bit to or with address for read start and read restart */
29 uint8_t const I2C_READ
= 1;
31 /** Bit to or with address for write start and write restart */
32 uint8_t const I2C_WRITE
= 0;
33 //------------------------------------------------------------------------------
34 // Status codes in TWSR - names are from Atmel TWSR.h with TWSR_ added
36 /** start condition transmitted */
37 uint8_t const TWSR_START
= 0x08;
39 /** repeated start condition transmitted */
40 uint8_t const TWSR_REP_START
= 0x10;
42 /** slave address plus write bit transmitted, ACK received */
43 uint8_t const TWSR_MTX_ADR_ACK
= 0x18;
45 /** data transmitted, ACK received */
46 uint8_t const TWSR_MTX_DATA_ACK
= 0x28;
48 /** slave address plus read bit transmitted, ACK received */
49 uint8_t const TWSR_MRX_ADR_ACK
= 0x40;
50 //------------------------------------------------------------------------------
53 * \brief Hardware I2C master class for AVR.
55 * Uses ATmega TWI hardware port
60 * @brief Initialize prescalar and SLC clock rate.
61 * @param[in] fastMode Fast 400 kHz mode if true else standard 100 kHz mode.
63 void begin(bool fastMode
= true) {
67 setClock(fastMode
&& F_CPU
> 15000000 ? 400000 : 100000);
70 * @brief Read a byte and send Ack if more reads follow else
71 Nak to terminate read.
73 * @param[in] last Set true to terminate the read else false.
74 * @return The byte read from the I2C bus.
76 uint8_t read(bool last
) {
77 execCmd((1 << TWINT
) | (1 << TWEN
) | (last
? 0 : (1 << TWEA
)));
81 * @brief Issue a repeated start condition.
83 * same as start with no stop. Included to document intention.
85 * @param[in] addressRW I2C address with read/write bit.
86 * @return The value true, 1, for success or false, 0, for failure.
88 bool repeatedStart(uint8_t addressRW
) {
89 return start(addressRW
);
92 * @brief Set the I2C bit rate.
94 * @param[in] frequency Desired frequency in Hz.
95 * Valid range for a 16 MHz board is about 40 kHz to 444,000 kHz.
97 void setClock(uint32_t frequency
) {
98 TWBR
= ((F_CPU
/ frequency
) - 16) / 2;
101 * @brief Issue a start condition.
103 * @param[in] addressRW I2C address with read/write bit.
105 * @return The value true for success or false for failure.
107 bool start(uint8_t addressRW
) {
108 // send START condition
109 execCmd((1 << TWINT
) | (1 << TWSTA
) | (1 << TWEN
));
110 if (status() != TWSR_START
&& status() != TWSR_REP_START
) {
113 // send device address and direction
115 execCmd((1 << TWINT
) | (1 << TWEN
));
116 if (addressRW
& I2C_READ
) {
117 return status() == TWSR_MRX_ADR_ACK
;
119 return status() == TWSR_MTX_ADR_ACK
;
122 /** @return status from last TWI command - useful for library debug */
123 uint8_t status(void) {return status_
;}
124 /** Issue a stop condition. */
126 TWCR
= (1 << TWINT
) | (1 << TWEN
) | (1 << TWSTO
);
128 // wait until stop condition is executed and bus released
129 while (TWCR
& (1 << TWSTO
)) {}
132 * @brief Write a byte.
134 * @param[in] data The byte to send.
136 * @return The value true, 1, if the slave returned an Ack or false for Nak.
138 bool write(uint8_t data
) {
140 execCmd((1 << TWINT
) | (1 << TWEN
));
141 return status() == TWSR_MTX_DATA_ACK
;
147 void execCmd(uint8_t cmdReg
) {
150 // wait for command to complete
151 while (!(TWCR
& (1 << TWINT
))) {}
153 status_
= TWSR
& 0xF8;