-
Notifications
You must be signed in to change notification settings - Fork 20
/
OneWire.h
187 lines (161 loc) · 5.57 KB
/
OneWire.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* Copyright (c) 2021,2022 Piotr Stolarz
* OneWireNg: Arduino 1-wire service library
*
* Distributed under the 2-clause BSD License (the License)
* see accompanying file LICENSE for details.
*
* This software is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the License for more information.
*/
#ifndef __OWNG_ONEWIRE__
#define __OWNG_ONEWIRE__
#include <string.h> /* memcpy */
#include "OneWireNg_CurrentPlatform.h"
/**
* OneWire library compatibility interface class.
*
* This class implements classic Arduino OneWire library interface using
* OneWireNg service API. The main purpose of this class is to provide fast
* and effortless mechanism for developers experiencing issues with OneWire
* and eager to give OneWireNg a try. Finally, it's strongly recommended to
* switch into OneWireNg interface rather than stay with the OneWire due to
* OneWireNg's more mature and feature-rich API (search filtering, OD mode,
* touch support).
*
* For OneWire API specification refer to its source repository:
* https://github.com/PaulStoffregen/OneWire
*
* @note Although the OneWire API have been strictly preserved there are some
* implementation differences between them. The most fundamental one is
* probably the @c power argument in write family of functions. OneWireNg
* allows providing power to the 1-wire bus only in specific conditions and
* the bus is always "de-powered" before next activity on it. On the other
* hand OneWire requires de-powering each time the power has been provided
* to the bus and 1-wire activities doesn't turn them off. OneWireNg doesn't
* emulate this buggy behavior.
*/
class OneWire
{
public:
/**
* @note The default (no-args) constructor requires @ref begin() method to
* be called subsequently with MCU's GPIO pin number controlling the
* 1-wire data bus as an argument. Any attempt to call OneWire API w/o
* this @c begin() call will cause NULL pointer dereference inside
* @c OneWire logic.
*/
OneWire(): _ow(NULL) {}
OneWire(uint8_t pin): _ow(NULL) {
begin(pin);
}
~OneWire()
{
if (_ow)
_ow->OneWireNg::~OneWireNg();
_ow = NULL;
}
void begin(uint8_t pin)
{
if (_ow)
_ow->OneWireNg::~OneWireNg();
_ow = new (_ow_buf) OneWireNg_CurrentPlatform(
pin,
false /* turn off internal pull-up */
);
}
uint8_t reset(void) {
return (uint8_t)(_ow->reset() == OneWireNg::EC_SUCCESS);
}
void select(const uint8_t rom[8]) {
_ow->writeByte(OneWireNg::CMD_MATCH_ROM);
_ow->writeBytes(&rom[0], 8);
}
void skip(void) {
_ow->writeByte(OneWireNg::CMD_SKIP_ROM);
}
void write(uint8_t v, uint8_t power = 0) {
_ow->writeByte(v, power != 0);
}
void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0) {
_ow->writeBytes(buf, count, power != 0);
}
uint8_t read(void) {
return _ow->readByte();
}
void read_bytes(uint8_t *buf, uint16_t count) {
_ow->readBytes(buf, count);
}
void write_bit(uint8_t v) {
_ow->writeBit(v);
}
uint8_t read_bit(void) {
return (uint8_t)_ow->readBit();
}
void depower(void) {
_ow->powerBus(false);
}
#if CONFIG_SEARCH_ENABLED
void reset_search() {
_ow->searchReset();
# if (CONFIG_MAX_SEARCH_FILTERS > 0)
_ow->searchFilterDelAll();
# endif
}
#endif
#if (CONFIG_MAX_SEARCH_FILTERS > 0)
/**
* @note This routine differs from the original OneWire's counterpart.
* The original @c target_search() returns only the first address
* found (after the search reset) with a given family code. Any
* subsequent calls of this routine return addresses subsequent (in
* the 1-wire binary tree) to the first returned address. In other
* words, there is no way to filter all slaves with a given family
* code in a single search-scan. Usefulness of such routine is
* problematic, therefore this routine is able to maintain filtered
* family code across the whole search-scan (up to the next search
* reset) returning all slaves with a given family code in one scanning
* loop.
*/
void target_search(uint8_t family_code) {
reset_search();
_ow->searchFilterAdd(family_code);
}
#endif
#if CONFIG_SEARCH_ENABLED
bool search(uint8_t *newAddr, bool search_mode = true)
{
OneWireNg::Id id;
if (_ow->search(id, !search_mode) == OneWireNg::EC_MORE) {
memcpy(newAddr, &id[0], sizeof(id));
return true;
} else {
/* OneWire automatically resets search
state after each completed scan */
reset_search();
return false;
}
}
#endif
static uint8_t crc8(const uint8_t *addr, uint8_t len) {
return OneWireNg::crc8(addr, len);
}
#if CONFIG_CRC16_ENABLED
static bool check_crc16(const uint8_t *input, uint16_t len,
const uint8_t *inverted_crc, uint16_t crc = 0)
{
return !(uint16_t)(crc16(input, len, crc) ^
~OneWireNg::getLSB_u16(inverted_crc));
}
static uint16_t crc16(
const uint8_t *input, uint16_t len, uint16_t crc = 0)
{
return OneWireNg::crc16(input, len, crc);
}
#endif
private:
ALLOC_ALIGNED uint8_t _ow_buf[sizeof(OneWireNg_CurrentPlatform)];
OneWireNg *_ow;
};
#endif /* __OWNG_ONEWIRE__ */