PropWare  3.0.0.229
C++ objects and CMake build system for Parallax Propeller
simplei2c.c
Go to the documentation of this file.
1 
7 #include "simplei2c.h"
8 
9 static inline HUBTEXT void all_low(i2c *dev)
10 {
11  OUTA &= (dev->scl_mask_inv | dev->sda_mask_inv);
12  DIRA |= (dev->scl_mask | dev->sda_mask);
13 }
14 
15 static inline HUBTEXT void all_high(i2c *dev)
16 {
17  int dirmask = 0;
18  OUTA &= dev->sda_mask_inv;
19  OUTA |= dev->scl_mask;
20 
21  if(dev->drivescl) {
22  dirmask = (dev->scl_mask | dev->sda_mask);
23  }
24  else {
25  dirmask = (dev->scl_mask_inv & dev->sda_mask);
26  }
27  DIRA |= dirmask;
28 }
29 
30 static inline HUBTEXT void scl_low(i2c *bus)
31 {
32  OUTA &= bus->scl_mask_inv;
33  DIRA |= bus->scl_mask;
34 }
35 
36 static inline HUBTEXT void sda_low(i2c *bus)
37 {
38  OUTA &= bus->sda_mask_inv;
39  DIRA |= bus->sda_mask;
40 }
41 
42 static inline HUBTEXT void scl_high(i2c *bus)
43 {
44  if(bus->drivescl) {
45  OUTA |= bus->scl_mask;
46  DIRA |= bus->scl_mask;
47  }
48  else {
49  OUTA &= bus->scl_mask_inv;
50  DIRA &= bus->scl_mask_inv;
51  }
52 }
53 
54 static inline HUBTEXT void sda_high(i2c *bus)
55 {
56  DIRA &= bus->sda_mask_inv;
57 }
58 
59 
60 HUBTEXT i2c *i2c_open(i2c *bus, int sclPin, int sdaPin, int sclDrive)
61 {
62  bus->scl_mask = (1 << sclPin);
63  bus->sda_mask = (1 << sdaPin);
64  bus->scl_mask_inv = ~(1 << sclPin);
65  bus->sda_mask_inv = ~(1 << sdaPin);
66  bus->drivescl = sclDrive;
67  i2c_stop(bus);
68  return bus;
69 }
70 
71 HUBTEXT void i2c_start(i2c *bus)
72 {
73  all_high(bus);
74  sda_low(bus);
75  scl_low(bus);
76 }
77 
78 HUBTEXT void i2c_stop(i2c *bus)
79 {
80  all_low(bus);
81  scl_high(bus);
82 #ifndef __PROPELLER_CMM__
83  /* second scl_high call gives delay for sda_high to make timing */
84  scl_high(bus);
85 #endif
86  sda_high(bus);
87 }
88 
89 #ifdef SPLIT_WRITE_DRIVE
90 
91 static HUBTEXT int i2c_writeByteDrive(i2c *bus, int byte)
92 {
93  int result;
94  int count = 8;
95 
96  /* send the byte, high bit first */
97  do {
98  if (byte & 0x80)
99  DIRA &= bus->sda_mask_inv;
100  else
101  DIRA |= bus->sda_mask;
102  OUTA |= bus->scl_mask;
103  DIRA |= bus->scl_mask;
104  byte <<= 1;
105  scl_low(bus);
106  } while(--count > 0);
107  DIRA &= bus->sda_mask_inv;
108  /* get ack */
109  scl_high(bus);
110  result = (INA & bus->sda_mask);
111  scl_low(bus);
112  return result != 0;
113 }
114 
115 static HUBTEXT int i2c_writeBytePullup(i2c *bus, int byte)
116 {
117  int result;
118  int count = 8;
119 
120  /* send the byte, high bit first */
121  do {
122  if (byte & 0x80)
123  DIRA &= bus->sda_mask_inv;
124  else
125  DIRA |= bus->sda_mask;
126  byte <<= 1;
127  DIRA &= bus->scl_mask_inv;
128  /* use call instead of DIRA |= for timing */
129  scl_low(bus);
130  } while(--count > 0);
131  DIRA &= bus->sda_mask_inv;
132  /* receive the acknowledgement from the slave */
133  DIRA &= bus->scl_mask_inv;
134  result = (INA & bus->sda_mask);
135  DIRA |= bus->scl_mask;
136  return result != 0;
137 }
138 
139 HUBTEXT int i2c_writeByte(i2c *dev, int byte)
140 {
141  int result;
142  if(dev->drivescl)
143  return i2c_writeByteDrive(dev, byte);
144  else
145  return i2c_writeBytePullup(dev, byte);
146  return result;
147 }
148 
149 #else
150 
151 HUBTEXT int i2c_writeByte(i2c *bus, int byte)
152 {
153  int result;
154  int count = 8;
155 
156  /* send the byte, high bit first */
157  do {
158  if (byte & 0x80)
159  DIRA &= bus->sda_mask_inv;
160  else
161  DIRA |= bus->sda_mask;
162  scl_high(bus);
163  byte <<= 1;
164  scl_low(bus);
165  } while(--count > 0);
166  DIRA &= bus->sda_mask_inv;
167  /* get ack */
168  scl_high(bus);
169  result = (INA & bus->sda_mask);
170  scl_low(bus);
171  return result != 0;
172 }
173 #endif
174 
175 HUBTEXT int i2c_readByte(i2c *bus, int ackState)
176 {
177  int byte = 0;
178  int count = 8;
179 
180  DIRA &= bus->sda_mask_inv;
181 
182  for (count = 8; --count >= 0; ) {
183  byte <<= 1;
184  scl_high(bus);
185  byte |= (INA & bus->sda_mask) ? 1 : 0;
186  while(!(INA & bus->scl_mask)); /* clock stretching */
187  /* scl_low(bus); // slow */
188  OUTA &= bus->scl_mask_inv;
189  DIRA |= bus->scl_mask;
190  }
191 
192  /* acknowledge */
193  if (ackState)
194  DIRA &= bus->sda_mask_inv;
195  else
196  DIRA |= bus->sda_mask;
197  scl_high(bus);
198  scl_low(bus);
199 
200  return byte;
201 }
202 
203 HUBTEXT int i2c_writeData(i2c *bus, const unsigned char *data, int count)
204 {
205  int n = 0;
206  int rc = 0;
207  while(count-- > 0) {
208  rc |= i2c_writeByte(bus, (int) data[n]);
209  if(rc)
210  return n;
211  n++;
212  }
213  return n;
214 }
215 
216 HUBTEXT int i2c_readData(i2c *bus, unsigned char *data, int count)
217 {
218  int n = 0;
219  while(--count > 0) {
220  data[n] = (unsigned char) i2c_readByte(bus, 0);
221  n++;
222  }
223  data[n] = (unsigned char) i2c_readByte(bus, 1);
224  return n;
225 }
226 
227 HUBTEXT int i2c_poll(i2c *bus, int devaddr)
228 {
229  int ack = 0;
230  i2c_start(bus);
231  ack = i2c_writeByte(bus, devaddr);
232  return ack;
233 }
234 
235 /*
236 +--------------------------------------------------------------------
237 | TERMS OF USE: MIT License
238 +--------------------------------------------------------------------
239 Permission is hereby granted, free of charge, to any person obtaining
240 a copy of this software and associated documentation files
241 (the "Software"), to deal in the Software without restriction,
242 including without limitation the rights to use, copy, modify, merge,
243 publish, distribute, sublicense, and/or sell copies of the Software,
244 and to permit persons to whom the Software is furnished to do so,
245 subject to the following conditions:
246 
247 The above copyright notice and this permission notice shall be
248 included in all copies or substantial portions of the Software.
249 
250 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
251 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
252 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
253 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
254 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
255 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
256 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
257 +--------------------------------------------------------------------
258 */
259 
i2c_start
HUBTEXT void i2c_start(i2c *bus)
Signal i2c start condition on bus.
Definition: simplei2c.c:71
OUTA
#define OUTA
Use to set output pin states when corresponding DIRA bits are 1.
Definition: propeller1.h:157
i2c_readByte
HUBTEXT int i2c_readByte(i2c *bus, int ackState)
Receive i2c byte and reply with ack state. Does not set start or stop. Drives SCL line if i2c device ...
Definition: simplei2c.c:175
i2c_readData
HUBTEXT int i2c_readData(i2c *bus, unsigned char *data, int count)
Receive a block of i2c data. Does not send start or stop conditions.
Definition: simplei2c.c:216
INA
#define INA
Use to read the pins when corresponding DIRA bits are 0.
Definition: propeller1.h:153
i2c_writeByte
HUBTEXT int i2c_writeByte(i2c *bus, int byte)
Send i2c byte and return acknowledgement from device. Does not set start or stop. Drives SCL line i...
Definition: simplei2c.c:151
i2c_stop
HUBTEXT void i2c_stop(i2c *bus)
Send Signal i2c stop condition on bus.
Definition: simplei2c.c:78
i2c_writeData
HUBTEXT int i2c_writeData(i2c *bus, const unsigned char *data, int count)
Send a block of i2c data. Does not set start or stop.
Definition: simplei2c.c:203
i2c_poll
HUBTEXT int i2c_poll(i2c *bus, int devaddr)
Send i2c start and addr byte. Looks for ACK (0) or NACK (1). This is useful for checking if a device ...
Definition: simplei2c.c:227
count
long count(int pin, long duration)
Count number of low to high transitions an external input applies to an I/O pin over a certain period...
Definition: count.c:19
i2c_st
Definition: simplei2c.h:25
i2c_open
HUBTEXT i2c * i2c_open(i2c *bus, int sclPin, int sdaPin, int sclDrive)
Open an i2c device.
Definition: simplei2c.c:60
simplei2c.h
Provides simple i2c start, stop, read, and write functions. See simpletools library for additional I2...
char
DIRA
#define DIRA
Use to set pins to input (0) or output (1).
Definition: propeller1.h:161
HUBTEXT
#define HUBTEXT
HUBTEXT tells compiler to put code into HUB RAM section.
Definition: propeller.h:43