uStepper S-lite
i2cMaster.cpp
Go to the documentation of this file.
1 /********************************************************************************************
2 * File: i2cMaster.cpp *
3 * Version: 1.1.0 *
4 * Date: June 14, 2020 *
5 * Author: Thomas Hørring Olsen *
6 * *
7 *********************************************************************************************
8 * i2cMaster class *
9 * *
10 * This file contains the implementation of the class methods, used to communicate over *
11 * the I2C bus. *
12 * *
13 *********************************************************************************************
14 * (C) 2020 *
15 * *
16 * uStepper ApS *
17 * www.ustepper.com *
18 * administration@ustepper.com *
19 * *
20 * The code contained in this file is released under the following open source license: *
21 * *
22 * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International *
23 * *
24 * The code in this file is provided without warranty of any kind - use at own risk! *
25 * neither uStepper ApS nor the author, can be held responsible for any damage *
26 * caused by the use of the code contained in this file ! *
27 * *
28 ********************************************************************************************/
36 #include "i2cMaster.h"
37 #include "Arduino.h"
38 #include <util/delay.h>
39 bool i2cMaster::cmd(uint8_t cmd)
40 {
41  uint16_t i = 0;
42  // send command
43  _SFR_MEM8(this->twcr) = cmd;
44  // wait for command to complete
45  while (!(_SFR_MEM8(this->twcr) & (1 << TWINT1)))
46  {
47  i++;
48  if(i == 3000)
49  {
50  return false;
51  }
52  _delay_us(1);
53  }
54 
55  // save status bits
56  status = _SFR_MEM8(this->twsr) & 0xF8;
57 
58  return true;
59 }
60 
61 bool i2cMaster::read(uint8_t slaveAddr, uint8_t regAddr, uint8_t numOfBytes, uint8_t *data)
62 {
63  uint8_t i;
64 
65  if(this->start(slaveAddr, WRITE) == false)
66  {
67  this->stop();
68  return false;
69  }
70 
71  if(this->writeByte(regAddr) == false)
72  {
73  this->stop();
74  return false;
75  }
76 
77  if(this->restart(slaveAddr, READ) == false)
78  {
79  this->stop();
80  return false;
81  }
82 
83  for(i = 0; i < (numOfBytes - 1); i++)
84  {
85  if(this->readByte(ACK, &data[i]) == false)
86  {
87  this->stop();
88  return false;
89  }
90  }
91 
92  if(this->readByte(NACK, &data[numOfBytes-1]) == false)
93  {
94  this->stop();
95  return false;
96  }
97 
98  this->stop();
99 
100  return 1;
101 }
102 
103 bool i2cMaster::write(uint8_t slaveAddr, uint8_t regAddr, uint8_t numOfBytes, uint8_t *data)
104 {
105  uint8_t i = 0;
106  if(this->start(slaveAddr, WRITE) == false)
107  {
108  this->stop();
109  return false;
110  }
111  if(this->writeByte(regAddr) == false)
112  {
113  this->stop();
114  return false;
115  }
116  for(i = 0; i < numOfBytes; i++)
117  {
118  if(this->writeByte(*(data + i)) == false)
119  {
120  this->stop();
121  return false;
122  }
123  }
124  this->stop();
125  return 1;
126 }
127 
128 bool i2cMaster::readByte(bool ack, uint8_t *data)
129 {
130  if(ack)
131  {
132  if(this->cmd((1 << TWINT1) | (1 << TWEN1) | (1 << TWEA1)) == false)
133  {
134  return false;
135  }
136 
137  }
138 
139  else
140  {
141  if(this->cmd((1 << TWINT1) | (1 << TWEN1)) == false)
142  {
143  return false;
144  }
145  }
146 
147  *data = _SFR_MEM8(this->twdr);
148 
149  return true;
150 }
151 
152 bool i2cMaster::start(uint8_t addr, bool RW)
153 {
154  // send START condition
155  this->cmd((1<<TWINT1) | (1<<TWSTA1) | (1<<TWEN1) | (1 << TWEA1));
156 
157  if (this->getStatus() != START && this->getStatus() != REPSTART)
158  {
159  return false;
160  }
161 
162  // send device address and direction
163  _SFR_MEM8(this->twdr) = (addr << 1) | RW;
164  this->cmd((1 << TWINT1) | (1 << TWEN1) | (1 << TWEA1));
165 
166  if (RW == READ)
167  {
168 
169  return this->getStatus() == RXADDRACK;
170  }
171 
172  else
173  {
174  return this->getStatus() == TXADDRACK;
175  }
176 }
177 
178 bool i2cMaster::restart(uint8_t addr, bool RW)
179 {
180  return this->start(addr, RW);
181 }
182 
183 bool i2cMaster::writeByte(uint8_t data)
184 {
185  _SFR_MEM8(this->twdr) = data;
186 
187  this->cmd((1 << TWINT1) | (1 << TWEN1) | (1 << TWEA1));
188 
189  return this->getStatus() == TXDATAACK;
190 }
191 
192 bool i2cMaster::stop(void)
193 {
194  uint16_t i = 0;
195  // issue stop condition
196  _SFR_MEM8(this->twcr) = (1 << TWINT1) | (1 << TWEN1) | (1 << TWSTO1);
197 
198 
199  // wait until stop condition is executed and bus released
200  while (_SFR_MEM8(this->twcr) & (1 << TWSTO1))
201  {
202  i++;
203  if(i == 1000)
204  {
205  return false;
206  }
207  _delay_us(1);
208  }
209 
210  status = I2CFREE;
211 
212  return 1;
213 }
214 
215 
216 uint8_t i2cMaster::getStatus(void)
217 {
218  return status;
219 }
220 
222 {
223  // set bit rate register to 12 to obtain 400kHz scl frequency (in combination with no prescaling!)
224  _SFR_MEM8(this->twbr) = 1;
225  // no prescaler
226  _SFR_MEM8(this->twsr) &= 0xFC;
227 }
228 
229 void i2cMaster::begin(bool channel)
230 {
231  if(channel)
232  {
233  this->twsr = 0xD9;
234  this->twbr = 0xD8;
235  this->twdr = 0xDB;
236  this->twcr = 0xDC;
237  }
238  else
239  {
240  this->twsr = 0xB9;
241  this->twbr = 0xB8;
242  this->twdr = 0xBB;
243  this->twcr = 0xBC;
244  }
245  // set bit rate register to 12 to obtain 400kHz scl frequency (in combination with no prescaling!)
246  _SFR_MEM8(this->twbr) = 1;
247 
248 }
249 
250 void* i2cMaster::operator new(size_t size)
251 {
252  void *object = malloc(size);
253  return object;
254 }
255 
256 i2cMaster::i2cMaster(bool channel)
257 {
258  if(channel)
259  {
260  this->twsr = 0xD9;
261  this->twbr = 0xD8;
262  this->twdr = 0xDB;
263  this->twcr = 0xDC;
264  }
265  else
266  {
267  this->twsr = 0xB9;
268  this->twbr = 0xB8;
269  this->twdr = 0xBB;
270  this->twcr = 0xBC;
271  }
272 }
273 
275 {
276 
277 }
I2CFREE
#define I2CFREE
Definition: i2cMaster.h:43
i2cMaster::cmd
bool cmd(uint8_t cmd)
Sends commands over the I2C bus.
Definition: i2cMaster.cpp:39
READ
#define READ
Definition: i2cMaster.h:46
ACK
#define ACK
Definition: i2cMaster.h:67
i2cMaster::i2cMaster
i2cMaster(void)
Constructor.
Definition: i2cMaster.cpp:274
RXADDRACK
#define RXADDRACK
Definition: i2cMaster.h:64
i2cMaster::read
bool read(uint8_t slaveAddr, uint8_t regAddr, uint8_t numOfBytes, uint8_t *data)
sets up I2C connection to device, reads a number of data bytes and closes the connection
Definition: i2cMaster.cpp:61
START
#define START
Definition: i2cMaster.h:52
i2cMaster::begin
void begin(void)
Setup TWI (I2C) interface.
Definition: i2cMaster.cpp:221
TXADDRACK
#define TXADDRACK
Definition: i2cMaster.h:58
i2cMaster::getStatus
uint8_t getStatus(void)
Get current I2C status.
Definition: i2cMaster.cpp:216
i2cMaster::stop
bool stop(void)
Closes the I2C connection.
Definition: i2cMaster.cpp:192
i2cMaster::write
bool write(uint8_t slaveAddr, uint8_t regAddr, uint8_t numOfBytes, uint8_t *data)
sets up I2C connection to device, writes a number of data bytes and closes the connection
Definition: i2cMaster.cpp:103
TXDATAACK
#define TXDATAACK
Definition: i2cMaster.h:61
i2cMaster::restart
bool restart(uint8_t addr, bool RW)
Restarts connection between arduino and I2C device.
Definition: i2cMaster.cpp:178
i2cMaster.h
This file contains the implementation of the class methods, used to communicate over the I2C bus.
WRITE
#define WRITE
Definition: i2cMaster.h:49
REPSTART
#define REPSTART
Definition: i2cMaster.h:55
i2cMaster::writeByte
bool writeByte(uint8_t data)
Writes a byte to a device on the I2C bus.
Definition: i2cMaster.cpp:183
i2cMaster::status
uint8_t status
Definition: i2cMaster.h:97
i2cMaster::readByte
bool readByte(bool ack, uint8_t *data)
Reads a byte from the I2C bus.
Definition: i2cMaster.cpp:128
NACK
#define NACK
Definition: i2cMaster.h:70
i2cMaster::start
bool start(uint8_t addr, bool RW)
sets up connection between arduino and I2C device.
Definition: i2cMaster.cpp:152