Skip to content
This repository was archived by the owner on Sep 7, 2022. It is now read-only.

Commit eb3784a

Browse files
committed
Fix OW implementation
1 parent 7443fb6 commit eb3784a

File tree

1 file changed

+303
-0
lines changed

1 file changed

+303
-0
lines changed

ow.c

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
#include <fcntl.h>
2+
#include <stdio.h>
3+
#include <driver/gpio.h>
4+
#include <unistd.h>
5+
#include "freertos/FreeRTOS.h"
6+
#include <freertos/task.h>
7+
#include <limits.h>
8+
#include "esp_log.h"
9+
#include "esp8266/gpio_struct.h"
10+
11+
12+
/* ESP12 PIN4 and PIN5 sometimes swapped :@ */
13+
#define OW_PIN_DATA 5
14+
#define OW_PIN_POWER 4
15+
#define OW_GET_IN() ( fast_pin_get(OW_PIN_DATA) )
16+
#define OW_OUT_LOW() ( fast_pin_set(OW_PIN_DATA, 0) )
17+
#define OW_OUT_HIGH() ( fast_pin_set(OW_PIN_DATA, 1) )
18+
#define OW_DIR_IN() ( fast_pin_dir(OW_PIN_DATA, 0) )
19+
#define OW_DIR_OUT() ( fast_pin_dir(OW_PIN_DATA, 1) )
20+
21+
22+
void onewire_gpio_setup() {
23+
gpio_config_t io_conf;
24+
io_conf.intr_type = GPIO_INTR_DISABLE;
25+
io_conf.mode = GPIO_MODE_OUTPUT;
26+
io_conf.pin_bit_mask = 1ULL << OW_PIN_DATA | 1ULL << OW_PIN_POWER;
27+
io_conf.pull_down_en = 0;
28+
io_conf.pull_up_en = 0;
29+
gpio_config(&io_conf);
30+
gpio_set_direction(OW_PIN_POWER, GPIO_MODE_OUTPUT);
31+
gpio_set_level(OW_PIN_POWER, 1);
32+
}
33+
34+
IRAM_ATTR inline void __attribute__ ((always_inline)) fast_pin_set(gpio_num_t gpio_num, uint32_t level) {
35+
if (level) {
36+
GPIO.out_w1ts |= (0x1 << gpio_num);
37+
} else {
38+
GPIO.out_w1tc |= (0x1 << gpio_num);
39+
}
40+
}
41+
42+
IRAM_ATTR inline int __attribute__ ((always_inline)) fast_pin_get(gpio_num_t gpio_num)
43+
{
44+
return (GPIO.in >> gpio_num) & 0x1;
45+
}
46+
47+
IRAM_ATTR inline void __attribute__ ((always_inline)) fast_pin_dir(gpio_num_t gpio_num, gpio_mode_t mode)
48+
{
49+
if (mode) {
50+
GPIO.enable_w1ts |= (0x1 << gpio_num);
51+
} else {
52+
GPIO.enable_w1tc |= (0x1 << gpio_num);
53+
}
54+
}
55+
56+
57+
58+
// 12.5ns with 80MHz clock
59+
IRAM_ATTR inline void __attribute__ ((always_inline)) WaitUS(uint32_t delta)
60+
{
61+
uint32_t cycleCount;
62+
uint32_t waitUntil;
63+
delta *= 80;
64+
delta -= 5;
65+
__asm__ __volatile__("rsr %0, ccount":"=a" (waitUntil));
66+
waitUntil += delta;
67+
do {
68+
__asm__ __volatile__("rsr %0, ccount":"=a" (cycleCount));
69+
} while (waitUntil > cycleCount);
70+
}
71+
72+
73+
// OK if just using a single permanently connected device
74+
IRAM_ATTR int onewire_reset() {
75+
int r;
76+
77+
OW_DIR_OUT();
78+
vPortETSIntrLock();
79+
OW_OUT_LOW();
80+
WaitUS(480);
81+
OW_DIR_IN();
82+
WaitUS(70);
83+
r = OW_GET_IN(); // Is OW device present it will pull low
84+
vPortETSIntrUnlock();
85+
86+
WaitUS(410); // TODO: Why?
87+
// if r - 1 - bad, means device didnt pulled low
88+
return (r);
89+
}
90+
91+
92+
#define OW_RECOVERY_TIME 10 // Depends on wire length
93+
94+
/*********************** onewire_write() ********************************/
95+
/*This function writes a byte to the sensor.*/
96+
/* */
97+
/*Parameters: byte - the byte to be written to the 1-wire */
98+
/*Returns: */
99+
/*********************************************************************/
100+
101+
102+
IRAM_ATTR void onewire_write(int data) {
103+
int count, temp;
104+
105+
vPortETSIntrLock();
106+
107+
for (count = 0; count < 8; ++count) {
108+
OW_DIR_OUT();
109+
temp = data >> count;
110+
temp &= 0x1;
111+
if (temp) {
112+
OW_OUT_LOW();
113+
WaitUS(10);
114+
OW_OUT_HIGH();
115+
WaitUS(55);
116+
} else {
117+
OW_OUT_LOW();
118+
WaitUS(65);
119+
OW_OUT_HIGH();
120+
WaitUS(5);
121+
}
122+
}
123+
vPortETSIntrUnlock();
124+
}
125+
126+
IRAM_ATTR int onewire_read() {
127+
int count, data = 0;
128+
vPortETSIntrLock();
129+
for (count = 0; count < 8; ++count) {
130+
OW_DIR_OUT();
131+
OW_OUT_LOW();
132+
WaitUS(3);
133+
OW_DIR_IN();
134+
WaitUS(10);
135+
if (OW_GET_IN())
136+
data |= (1 << count);
137+
WaitUS(50);
138+
}
139+
vPortETSIntrUnlock();
140+
return ( data );
141+
}
142+
143+
#define CRC8_POLYNOMIAL 0x8C
144+
uint8_t crc8_data(uint8_t *buffer, uint8_t length)
145+
{
146+
uint8_t crc8 = 0, valid = 0;
147+
uint8_t inByte, byteCount, bitCount, mix;
148+
149+
for (byteCount = 0; byteCount < length; byteCount++)
150+
{
151+
inByte = buffer[byteCount];
152+
if (inByte)
153+
{
154+
valid = 1;
155+
}
156+
for (bitCount = 0; bitCount < CHAR_BIT; bitCount++)
157+
{
158+
mix = (crc8 ^ inByte) & 0x01;
159+
crc8 >>= 1;
160+
if (mix)
161+
{
162+
crc8 ^= CRC8_POLYNOMIAL;
163+
}
164+
inByte >>= 1;
165+
}
166+
}
167+
if (!valid)
168+
{
169+
/* If all bytes are 0, return a different CRC so that the test will fail */
170+
return 0xFF;
171+
}
172+
return crc8;
173+
}
174+
175+
int ds1820_read(double *temp) {
176+
uint8_t i = 0, data[9], type = 0;
177+
int32_t raw;
178+
uint8_t crc8 = 0xFF;
179+
180+
/*
181+
// Can be used to verify calibration of WaitUS
182+
uint32_t d1, d2;
183+
vPortETSIntrLock();
184+
__asm__ __volatile__("rsr %0, ccount":"=a" (d1));
185+
WaitUS(10);
186+
__asm__ __volatile__("rsr %0, ccount":"=a" (d2));
187+
vPortETSIntrUnlock();
188+
printf("%d\r\n", d2-d1);
189+
190+
191+
192+
__asm__ __volatile__("rsr %0, ccount":"=a" (d1));
193+
WaitUS(100);
194+
__asm__ __volatile__("rsr %0, ccount":"=a" (d2));
195+
printf("%d\r\n", d2-d1);
196+
197+
198+
vPortETSIntrLock();
199+
__asm__ __volatile__("rsr %0, ccount":"=a" (d1));
200+
WaitUS(200);
201+
__asm__ __volatile__("rsr %0, ccount":"=a" (d2));
202+
vPortETSIntrUnlock();
203+
printf("%d\r\n", d2-d1);
204+
*/
205+
206+
if (onewire_reset())
207+
return -1; // Device not found
208+
209+
vTaskDelay(100 / portTICK_RATE_MS);
210+
// Read ROM (and important - type)
211+
onewire_write(0x33);
212+
for (i = 0; i < 8; i++)
213+
data[i] = onewire_read();
214+
215+
crc8 = crc8_data(data, 7);
216+
type = data[0];
217+
if (crc8 != data[7]) {
218+
for (i = 0; i < 8; i++)
219+
printf("rom[%d]%02x ", i, data[i]);
220+
printf("\r\n");
221+
222+
printf("ROM CRC error\r\n");
223+
return -5;
224+
}
225+
226+
227+
if (onewire_reset())
228+
return -3;
229+
230+
onewire_write(0xCC);
231+
onewire_write(0x44);
232+
233+
// Conversion delay
234+
vTaskDelay(1000 / portTICK_RATE_MS);
235+
236+
if (onewire_reset())
237+
return -4;
238+
239+
onewire_write(0xCC);
240+
onewire_write(0xBE);
241+
for (i = 0; i < 9; i++)
242+
data[i] = onewire_read();
243+
244+
crc8 = crc8_data(data, 8);
245+
246+
if (crc8 != data[8]) {
247+
for (i = 0; i < 9; i++)
248+
printf("data[%d]%02x ", i, data[i]);
249+
ESP_LOGE("ow", "CRC mismatch %02x %02x", data[8], crc8);
250+
return -2;
251+
}
252+
253+
254+
255+
if (type == 0x10) {
256+
//printf(" OLD TYPE\r\n");
257+
*temp = (double)(data[0] >> 1);
258+
double count_per_c = 0x10;
259+
double count_remain = data[6];
260+
*temp = *temp - 0.25 + ((count_per_c - count_remain) / count_per_c);
261+
} else {
262+
double minus = 1.0;
263+
if (data[1] & 0x80)
264+
minus = -1.0;
265+
266+
uint8_t cfg = (data[4] & 0x60);
267+
uint8_t mask = 0xFF;
268+
269+
/* Ignore some bits depends on precision */
270+
if (cfg == 0x00)
271+
mask = 0xF8;
272+
else if (cfg == 0x20)
273+
mask = 0xFC;
274+
else if (cfg == 0x40)
275+
mask = 0xFE;
276+
277+
raw = (data[1] << 8) | (data[0] & mask);
278+
279+
/* If minus... */
280+
if (minus == -1.0)
281+
raw = 0xFFFF - raw;
282+
*temp = (double)raw * 0.0625 * minus;
283+
284+
/* Increase resolution */
285+
if (cfg != 0x60) {
286+
printf("Fixing resolution\r\n");
287+
onewire_reset();
288+
onewire_write(0xCC);
289+
onewire_write(0x4E);
290+
onewire_write(0x0);//alarm
291+
onewire_write(0x0);//alarm
292+
onewire_write(0x7F);
293+
onewire_reset();
294+
vTaskDelay(30 / portTICK_RATE_MS);
295+
onewire_write(0xCC);
296+
onewire_write(0x48); // save to eeprom
297+
vTaskDelay(30 / portTICK_RATE_MS);
298+
}
299+
300+
}
301+
302+
return 0;
303+
}

0 commit comments

Comments
 (0)