COSA
An Object-Oriented Platform for Arduino Programming
OWI.cpp
Go to the documentation of this file.
1 
26 #include "OWI.hh"
27 
28 bool
30 {
31  uint8_t retry = 4;
32  uint8_t res = 0;
33  do {
35  set();
36  clear();
37  DELAY(480);
38  set();
39  synchronized {
41  DELAY(70);
42  res = is_clear();
43  }
44  DELAY(410);
45  } while (retry-- && !res);
46  return (res != 0);
47 }
48 
49 uint8_t
50 OWI::read(uint8_t bits)
51 {
52  uint8_t res = 0;
53  uint8_t mix = 0;
54  uint8_t adjust = CHARBITS - bits;
55  while (bits--) {
56  synchronized {
58  set();
59  clear();
60  DELAY(6);
62  DELAY(9);
63  res >>= 1;
64  if (is_set()) {
65  res |= 0x80;
66  mix = (m_crc ^ 1);
67  }
68  else {
69  mix = (m_crc ^ 0);
70  }
71  }
72  m_crc >>= 1;
73  if (mix & 1) m_crc ^= 0x8C;
74  DELAY(55);
75  }
76  res >>= adjust;
77  return (res);
78 }
79 
80 bool
81 OWI::read(void* buf, uint8_t size)
82 {
83  uint8_t* bp = (uint8_t*) buf;
84  m_crc = 0;
85  while (size--) *bp++ = read();
86  return (m_crc == 0);
87 }
88 
89 void
90 OWI::write(uint8_t value, uint8_t bits, bool power)
91 {
92  uint8_t mix = 0;
94  set();
95  while (bits--) {
96  synchronized {
97  clear();
98  if (value & 1) {
99  DELAY(6);
100  set();
101  DELAY(64);
102  mix = (m_crc ^ 1);
103  }
104  else {
105  DELAY(60);
106  set();
107  DELAY(10);
108  mix = (m_crc ^ 0);
109  }
110  }
111  value >>= 1;
112  m_crc >>= 1;
113  if (mix & 1) m_crc ^= 0x8C;
114  }
115  if (!power) power_off();
116 }
117 
118 void
119 OWI::write(uint8_t value, void* buf, uint8_t size)
120 {
121  write(value);
122  uint8_t* bp = (uint8_t*) buf;
123  while (size--) write(*bp++);
124 }
125 
127 OWI::lookup(uint8_t* rom)
128 {
129  for (Driver* dev = m_device; dev != NULL; dev = dev->m_next) {
130  if (!memcmp(dev->m_rom, rom, ROM_MAX))
131  return (dev);
132  }
133  return (NULL);
134 }
135 
136 bool
138 {
139  OWI::Search iter(this);
140  OWI::Driver* dev = iter.next();
141  if (UNLIKELY(dev == NULL)) return (false);
142  do {
143  dev->on_alarm();
144  dev = iter.next();
145  } while (dev != NULL);
146  return (true);
147 }
148 
150 {
151  OWI::Driver dev(&owi);
152  int8_t last = OWI::Driver::FIRST;
153  do {
154  last = dev.search_rom(last);
155  if (UNLIKELY(last == OWI::Driver::ERROR)) return (outs);
156  outs << dev << endl;
157  } while (last != OWI::Driver::LAST);
158  return (outs);
159 }
160 
161 OWI::Driver::Driver(OWI* pin, const uint8_t* rom, const char* name) :
162  NAME((str_P) name),
163  ROM(rom),
164  m_next(NULL),
165  m_pin(pin)
166 {
167  eeprom_read_block(m_rom, rom, sizeof(m_rom));
168  m_pin->m_devices += 1;
169  m_next = m_pin->m_device;
170  m_pin->m_device = this;
171 }
172 
173 bool
175 {
176  if (UNLIKELY(ROM == NULL)) return (false);
177  eeprom_write_block(ROM, m_rom, sizeof(m_rom));
178  return (true);
179 }
180 
181 int8_t
183 {
184  uint8_t pos = 0;
185  int8_t next = LAST;
186  for (uint8_t i = 0; i < 8; i++) {
187  uint8_t data = 0;
188  for (uint8_t j = 0; j < 8; j++) {
189  data >>= 1;
190  switch (m_pin->read(2)) {
191  case 0b00: // Discrepency between device roms
192  if (pos == last) {
193  m_pin->write(1, 1);
194  data |= 0x80;
195  last = FIRST;
196  }
197  else if (pos > last) {
198  m_pin->write(0, 1);
199  next = pos;
200  }
201  else if (m_rom[i] & (1 << j)) {
202  m_pin->write(1, 1);
203  data |= 0x80;
204  }
205  else {
206  m_pin->write(0, 1);
207  next = pos;
208  }
209  break;
210  case 0b01: // Only one's at this position
211  m_pin->write(1, 1);
212  data |= 0x80;
213  break;
214  case 0b10: // Only zero's at this position
215  m_pin->write(0, 1);
216  break;
217  case 0b11: // No device detected
218  return (ERROR);
219  }
220  pos += 1;
221  }
222  m_rom[i] = data;
223  }
224  return (next);
225 }
226 
227 int8_t
229 {
230  if (!m_pin->reset()) return (ERROR);
232  return (search(last));
233 }
234 
235 bool
237 {
238  if (!m_pin->reset()) return (false);
240  return (m_pin->read(m_rom, ROM_MAX));
241 }
242 
243 bool
245 {
246  if (m_rom[0] == 0) return (false);
247  if (!m_pin->reset()) return (false);
248  if (m_pin->m_devices > 1)
250  else
252  return (true);
253 }
254 
255 bool
257 {
258  if (!m_pin->reset()) return (false);
260  return (true);
261 }
262 
263 int8_t
265 {
266  if (!m_pin->reset()) return (ERROR);
268  return (search(last));
269 }
270 
271 bool
272 OWI::Driver::connect(uint8_t family, uint8_t index)
273 {
274  int8_t last = FIRST;
275  do {
276  last = search_rom(last);
277  if (last == ERROR) return (false);
278  if (m_rom[0] == family) {
279  if (index == 0) {
280  m_pin->m_devices += 1;
281  m_next = m_pin->m_device;
282  m_pin->m_device = this;
283  return (true);
284  }
285  index -= 1;
286  }
287  } while (last != LAST);
288  memset(m_rom, 0, ROM_MAX);
289  return (false);
290 }
291 
293 {
294  uint8_t i;
295  if (dev.NAME != NULL) outs << dev.NAME << ':';
296  outs << PSTR("OWI::rom(family = ") << hex << dev.m_rom[0]
297  << PSTR(", id = 0x");
298  for (i = OWI::ROM_MAX - 2; i > 0; i--) {
299  uint8_t v = dev.m_rom[i];
300  outs << tohex(v >> 4) << tohex(v);
301  }
302  outs << PSTR(", crc = ") << hex << dev.m_rom[OWI::ROM_MAX - 1] << ')';
303  return (outs);
304 }
305 
308 {
309  do {
310  if (m_last == LAST) return (NULL);
311  m_last = alarm_search(m_last);
312  if (m_last == ERROR) return (NULL);
313  } while ((m_family != 0) && (m_rom[0] != m_family));
314  return (m_pin->lookup(m_rom));
315 }
316 
Definition: OWI.hh:36
int8_t alarm_search(int8_t last=FIRST)
Definition: OWI.cpp:264
uint8_t pin() const
Definition: Pin.hh:103
friend IOStream & operator<<(IOStream &outs, OWI &owi)
Definition: OWI.cpp:149
#define NULL
Definition: Types.h:101
Mode mode() const
Definition: IOPin.hh:71
void power_off()
Definition: OWI.hh:274
Driver * next()
Definition: OWI.cpp:307
#define PSTR(s)
Definition: Types.h:202
bool reset()
Definition: OWI.cpp:29
void write(uint8_t value, uint8_t bits=CHARBITS, bool power=false)
Definition: OWI.cpp:90
#define DELAY(us)
Definition: Types.h:280
int8_t search(int8_t last=FIRST)
Definition: OWI.cpp:182
bool update_rom()
Definition: OWI.cpp:174
#define CHARBITS
Definition: Types.h:57
const class prog_str * str_P
Definition: Types.h:187
bool read_rom()
Definition: OWI.cpp:236
bool is_set() const
Definition: Pin.hh:112
bool alarm_dispatch()
Definition: OWI.cpp:137
uint8_t m_rom[ROM_MAX]
Definition: OWI.hh:162
virtual void on_alarm()
Definition: OWI.hh:159
bool read() const
Definition: Pin.hh:172
Driver * m_next
Definition: OWI.hh:164
bool match_rom()
Definition: OWI.cpp:244
IOStream & endl(IOStream &outs)
Definition: IOStream.hh:817
char tohex(uint8_t value)
Definition: Types.h:592
const uint8_t * ROM
Definition: OWI.hh:163
bool is_clear() const
Definition: Pin.hh:142
Driver * lookup(uint8_t *rom)
Definition: OWI.cpp:127
const uint8_t m_pin
Definition: Pin.hh:230
OWI * m_pin
Definition: OWI.hh:165
Driver(OWI *pin, const char *name=NULL)
Definition: OWI.hh:74
bool connect(uint8_t family, uint8_t index)
Definition: OWI.cpp:272
bool skip_rom()
Definition: OWI.cpp:256
uint8_t read(uint8_t bits=CHARBITS)
Definition: OWI.cpp:50
void clear() const
Definition: OutputPin.hh:124
OutputPin & operator<<(int value)
Definition: OutputPin.hh:364
#define UNLIKELY(x)
Definition: Types.h:153
IOStream & hex(IOStream &outs)
Definition: IOStream.hh:793
int8_t search_rom(int8_t last=FIRST)
Definition: OWI.cpp:228
static const uint8_t ROM_MAX
Definition: OWI.hh:50
str_P NAME
Definition: OWI.hh:67