Arduino-OWI
One-Wire Interface (OWI) library for Arduino
OWI.h
Go to the documentation of this file.
1 
19 #ifndef SLAVE_OWI_H
20 #define SLAVE_OWI_H
21 
22 #include "GPIO.h"
23 
31 namespace Slave {
32 template<BOARD::pin_t PIN>
33 class OWI {
34 public:
36  static const size_t ROM_MAX = 8;
37 
39  static const size_t ROMBITS = ROM_MAX * 8;
40 
47  OWI(const uint8_t* rom) :
48  m_timestamp(0),
49  m_label(255),
50  m_alarm(false)
51  {
52  uint8_t crc = 0;
53  for (size_t i = 0; i < ROM_MAX - 1; i++) {
54  uint8_t data = pgm_read_byte(rom++);
55  m_rom[i] = data;
56  crc = crc_update(crc, data);
57  }
58  m_rom[ROM_MAX - 1] = crc;
59  m_pin.open_drain();
60  }
61 
68  OWI(uint8_t family) :
69  m_timestamp(0),
70  m_label(255),
71  m_alarm(false)
72  {
73  uint8_t crc = crc_update(0, family);
74  uint8_t* p = 0;
75  m_rom[0] = family;
76  for (size_t i = 1; i < ROM_MAX - 1; i++) {
77  uint8_t data = *p++;
78  m_rom[i] = data;
79  crc = crc_update(crc, data);
80  }
81  m_rom[ROM_MAX - 1] = crc;
82  m_pin.open_drain();
83  }
84 
90  uint8_t crc()
91  {
92  return (m_crc);
93  }
94 
99  void crc(uint8_t value)
100  {
101  m_crc = value;
102  }
103 
108  bool alarm()
109  {
110  return (m_alarm);
111  }
112 
117  void alarm(bool value)
118  {
119  m_alarm = value;
120  }
121 
127  bool reset()
128  {
129  // Check reset start
130  if (m_timestamp == 0) {
131  if (!m_pin) m_timestamp = micros();
132  return (false);
133  }
134 
135  // Check reset pulse stop
136  if (!m_pin) return (false);
137 
138  // Check reset pulse width
139  if (micros() - m_timestamp < 410) {
140  m_timestamp = 0;
141  return (false);
142  }
143 
144  // Generate presence signal
145  m_pin.output();
146  delayMicroseconds(100);
147  m_pin.input();
148 
149  // Wait for possible presence signals from other devices
150  while (!m_pin);
151  m_timestamp = 0;
152 
153  return (true);
154  }
155 
162  uint8_t read(uint8_t bits = 8)
163  {
164  uint8_t adjust = 8 - bits;
165  uint8_t res = 0;
166  uint8_t mix = 0;
167  do {
168  noInterrupts();
169  // Wait for bit start
170  while (m_pin);
171  // Delay to sample bit value
172  delayMicroseconds(20);
173  res >>= 1;
174  if (m_pin) {
175  res |= 0x80;
176  mix = (m_crc ^ 1);
177  }
178  else {
179  mix = (m_crc ^ 0);
180  }
181  interrupts();
182  // Calculate cyclic redundancy check sum
183  m_crc >>= 1;
184  if (mix & 1) m_crc ^= 0x8C;
185  // Wait for bit end (max 50 us)
186  uint8_t count = 255;
187  while (!m_pin && --count);
188  if (count == 0) return (0);
189  } while (--bits);
190  res >>= adjust;
191  return (res);
192  }
193 
202  bool read(void* buf, size_t count)
203  {
204  // Write bytes and calculate crc
205  uint8_t* bp = (uint8_t*) buf;
206  m_crc = 0;
207  do {
208  uint8_t value = read();
209  *bp++ = value;
210  } while (--count);
211 
212  // Return crc validation
213  return (m_crc == 0);
214  }
215 
223  void write(uint8_t value, uint8_t bits = 8)
224  {
225  uint8_t mix = 0;
226  do {
227  noInterrupts();
228  // Wait for bit start
229  while (m_pin);
230  // Streck low if bit is zero
231  if ((value & 0x01) == 0) {
232  m_pin.output();
233  delayMicroseconds(20);
234  m_pin.input();
235  mix = (m_crc ^ 0);
236  }
237  else {
238  mix = (m_crc ^ 1);
239  }
240  interrupts();
241  value >>= 1;
242  // Calculate cyclic redundancy check sum
243  m_crc >>= 1;
244  if (mix & 1) m_crc ^= 0x8C;
245  // Wait for bit end (max 50 us)
246  uint8_t count = 255;
247  while (!m_pin && --count);
248  if (count == 0) return;
249  } while (--bits);
250  }
251 
258  void write(const void* buf, size_t count)
259  {
260  // Write bytes and calculate cyclic redundancy check-sum
261  const uint8_t* bp = (const uint8_t*) buf;
262  m_crc = 0;
263  do {
264  uint8_t value = *bp++;
265  write(value);
266  } while (--count);
267 
268  // Write calculated crc
269  write(m_crc);
270  }
271 
277  bool triplet(bool bit)
278  {
279  write(bit, 1);
280  write(!bit, 1);
281  return (read(1));
282  }
283 
287  enum {
288  SEARCH_ROM = 0xF0,
289  READ_ROM = 0x33,
290  MATCH_ROM = 0x55,
291  SKIP_ROM = 0xCC,
292  ALARM_SEARCH = 0xEC,
293  LABEL_ROM = 0x15,
294  READ_LABEL = 0x16,
295  MATCH_LABEL = 0x51
296  } __attribute__((packed));
297 
304  bool rom_command()
305  {
306  // Wait for reset
307  if (!reset()) return (false);
308 
309  // Standard ROM commands
310  switch (read()) {
311  case READ_ROM:
312  // Write ROM to master
313  write(m_rom, ROM_MAX - 1);
314  return (false);
315  case MATCH_ROM:
316  // Match ROM from master
317  for (size_t i = 0; i < ROM_MAX; i++)
318  if (m_rom[i] != read())
319  return (false);
320  case SKIP_ROM:
321  // Skip ROM, extended command will follow
322  return (true);
323  case ALARM_SEARCH:
324  // Ignore search request if alarm is not set
325  if (!m_alarm)
326  return (false);
327  case SEARCH_ROM:
328  // Write ROM bit and check branching
329  for (size_t i = 0; i < ROM_MAX; i++) {
330  uint8_t value = m_rom[i];
331  uint8_t mask = 0x01;
332  do {
333  uint8_t bit = (mask & value) != 0;
334  bool dir = triplet(bit);
335  if (dir != bit) return (false);
336  mask <<= 1;
337  } while (mask);
338  }
339  return (true);
340  case MATCH_LABEL:
341  // Device label setting
342  if (m_label == read())
343  return (true);
344  default:
345  // Ignore all other commands
346  return (false);
347  };
348  }
349 
355  uint8_t read_command()
356  {
357  uint8_t cmd = read();
358  switch (cmd) {
359  case LABEL_ROM:
360  // Set device label
361  m_label = read();
362  return (0);
363  case READ_LABEL:
364  // Get device label
365  write(m_label);
366  return (0);
367  default:
368  return (cmd);
369  };
370  }
371 
377  static inline uint8_t crc_update(uint8_t crc, uint8_t data)
378  __attribute__((always_inline))
379  {
380  crc = crc ^ data;
381  uint8_t bits = 8;
382  do {
383  if (crc & 0x01)
384  crc = (crc >> 1) ^ 0x8C;
385  else
386  crc >>= 1;
387  } while (--bits);
388  return (crc);
389  }
390 
391 protected:
393  GPIO<PIN> m_pin;
394 
396  uint32_t m_timestamp;
397 
399  uint8_t m_rom[ROM_MAX];
400 
402  uint8_t m_label;
403 
405  bool m_alarm;
406 
408  uint8_t m_crc;
409 };
410 };
411 #endif
void crc(uint8_t value)
Definition: OWI.h:99
static uint8_t crc_update(uint8_t crc, uint8_t data)
Definition: OWI.h:377
bool m_alarm
Definition: OWI.h:405
uint32_t m_timestamp
Definition: OWI.h:396
Initiate device alarm search.
Definition: OWI.h:292
bool read(void *buf, size_t count)
Definition: OWI.h:202
uint8_t read(uint8_t bits=8)
Definition: OWI.h:162
Definition: OWI.h:33
static const size_t ROM_MAX
Definition: OWI.h:36
bool reset()
Definition: OWI.h:127
uint8_t m_crc
Definition: OWI.h:408
Set short address (8-bit).
Definition: OWI.h:293
uint8_t crc()
Definition: OWI.h:90
Select device with 8-bit short address.
Definition: OWI.h:295
GPIO< PIN > m_pin
Definition: OWI.h:393
void alarm(bool value)
Definition: OWI.h:117
uint8_t m_rom[ROM_MAX]
Definition: OWI.h:399
static const size_t ROMBITS
Definition: OWI.h:39
uint8_t m_label
Definition: OWI.h:402
bool rom_command()
Definition: OWI.h:304
OWI(uint8_t family)
Definition: OWI.h:68
Broadcast or single device.
Definition: OWI.h:291
Read device family code and serial number.
Definition: OWI.h:289
bool alarm()
Definition: OWI.h:108
void write(const void *buf, size_t count)
Definition: OWI.h:258
Initiate device search.
Definition: OWI.h:288
bool triplet(bool bit)
Definition: OWI.h:277
Select device with 64-bit rom code.
Definition: OWI.h:290
uint8_t read_command()
Definition: OWI.h:355
Get 8-bit short address.
Definition: OWI.h:294
void write(uint8_t value, uint8_t bits=8)
Definition: OWI.h:223
OWI(const uint8_t *rom)
Definition: OWI.h:47
Definition: OWI.h:31