SingingCat 0
application
onewire.c
Go to the documentation of this file.
1#include "main-header.h"
2#include "onewire.h"
3#include "ds18b20crc.h"
4#include "powersave.h"
5
6// there are some timing operations in this file that
7// break with optimisations
8
9#pragma GCC optimize ("O0")
10
11#define ONEWIRE_TIMER 5
12
24#define ONEWIRE_INTERVAL 600
25static volatile uint32_t usctr;
26
30static int freq_divider = 0;
31static int reset(struct onewire_hwdef *hw);
32static void write_bit_0(struct onewire_hwdef *hw);
33static void write_bit_1(struct onewire_hwdef *hw);
34static byte read_bit(struct onewire_hwdef *hw);
35static void write_byte(struct onewire_hwdef *hw, byte b);
36static byte read_byte(struct onewire_hwdef *hw);
37//static byte read_pin();
38
39static byte buf[12];
40static inline void read_buf(struct onewire_hwdef *hw, int cnt);
41static byte toggler;
42static long last_run;
43
47static int is_valid(byte *recvBuf) {
48 int crc_calc = onewire_crc(recvBuf, 8);
49 int crc_read = recvBuf[8];
50
51 return (crc_calc == crc_read) ? 1 : 0;
52}
53
54static void print_recvbuf(byte *recvBuf) {
55 char hexbuf[40];
56
57 bufToHex((char *)&hexbuf, recvBuf, 10);
58 printf("Recv: %s", hexbuf);
59 int crc_calc = onewire_crc(recvBuf, 8);
60 int crc_read = recvBuf[8];
61
62 printf("(CRC calc: 0x%x, read: 0x%x) %s\r\n", crc_calc, crc_read,
63 (crc_calc == crc_read) ? "OK" : "FAIL");
64}
65
66
67// this is hardcoded to pin PC7 - (speed!) - once it works try mculib again
68// GPIOx_IDR
69volatile uint32_t *r_adr = (volatile uint32_t *)0x40020810;
70static inline byte read_pin(int mask) __attribute__ ((always_inline));
71
72static inline byte read_pin(int mask) {
73 // did try: this does not work. 2/1/2018 cnw
74 //return mculib_pin_get(get_pin());
75 return ((*r_adr) & mask) ? 1 : 0;
76}
81static inline void pull_low() __attribute__ ((always_inline));
82// GPIOx_ODR
83volatile uint32_t *wr_adr = (volatile uint32_t *)0x40020814;
84static inline void pull_low(int offset, int us) {
85 int delayus = (us == 0) ? 0 : (us / freq_divider);
86
87 (*wr_adr) &= ~(1 << offset);
88 //mculib_pin_set(pin,0);
89 usctr = 0;
90 while (delayus > usctr) {
91 }
92 (*wr_adr) |= 1 << offset;
93
94 //mculib_pin_set(pin,1); // open-drain - switch transistor off
95 return;
96}
97
98static void delay_us(int us) {
99 int delayus = us / freq_divider;
100
101 usctr = 0;
102 while (usctr < delayus) {
103 ;;
104 }
105 return;
106}
107
108static void ow_timer_irq() {
109 usctr++;
110}
114static int timer_enable() {
115 int r;
116 // will call STM32 timer2_irq 500 times a second
117 int freqreq = 100000; // one IRQ every 10us
118
119 freq_divider = 10;
120 r = mculib_timer_enable_simple(MAIN_MCULIBHANDLE, ONEWIRE_TIMER, freqreq, &ow_timer_irq);
121 if (r) {
122 mculib_print_mappings(&printf);
123 printf("onewire MCULIB Error (failed to enable timer %i): %i\r\n", ONEWIRE_TIMER, r);
124 } else {
125 printf("Timer %i enabled with frequency %i (divider to us: %i)\r\n", ONEWIRE_TIMER, freqreq, freq_divider);
126 }
127 return r;
128}
132static int read_temperature(struct onewire_hwdef *hw, byte *error) {
133 int res = 20005;
134 int r;
135 int repeat;
136
137 *error = 0;
138 //printf("Running onewire\r\n");
139 if ((r = mculib_pin_out_opendrain(MAIN_MCULIBHANDLE, hw->pin, HAL_PIN_FASTEST))) {
140 printf("Failed to configure pin %i for opendrain output: %i\r\n", hw->pin, r);
141 *error = 2;
142 return 20001;
143 }
144
145 timer_enable();
146 /*
147 * int started =mculib_get_seconds_since_boot();
148 * while ((mculib_get_seconds_since_boot() - started) < 5) {
149 * goto finish;
150 * }
151 */
152
153 if (!reset(hw)) {
154 printf("No onewire device detected. abort\r\n");
155 *error = 3;
156 res = 20003;
157 goto finish;
158 }
159 printf("Onewire device detected.\r\n");
160 for (repeat = 0; repeat < 5; repeat++) {
161 write_byte(hw, 0x33); // readrom
162 read_buf(hw, 9);
163 delay_us(500);
164
165 reset(hw);
166 write_byte(hw, 0xCC); // SKIP ROM
167 delay_us(50); // wait for whatever?
168
169 write_byte(hw, 0x44); // convert temperature
170 delay_us(5000); // wait for conversion
171
172 reset(hw);
173 write_byte(hw, 0xCC); // SKIP ROM
174 delay_us(50); // wait for whatever?
175 write_byte(hw, 0xBE); // read scratchpad (the temperature)
176 read_buf(hw, 9);
177
178 if (is_valid((byte *)buf)) {
179 break;
180 }
181 }
182 if (!is_valid((byte *)buf)) {
183 *error = 4;
184 res = 20004;
185 goto finish;
186 }
187 uint16_t tempRaw = ((uint16_t)buf[1]) << 8 | buf[0];
188 int neg = 0;
189
190 if (tempRaw & (1 << 15)) {
191 neg = 1;
192 tempRaw = 0xFFFF - tempRaw;
193 }
194 int32_t temp_c100 = (6 * ((int32_t)tempRaw)) + (tempRaw / 4);
195
196 if (neg) {
197 temp_c100 = 0 - temp_c100;
198 }
199 printf("Temp: %i, %i\r\n", (int)tempRaw, (int)temp_c100);
200 res = temp_c100;
201finish:
202 mculib_timer_disable(MAIN_MCULIBHANDLE, ONEWIRE_TIMER);
203 mculib_pin_release(MAIN_MCULIBHANDLE, hw->pin);
204 mculib_pin_out(MAIN_MCULIBHANDLE, hw->pin, HAL_PIN_SLOWEST);
205 mculib_pin_release(MAIN_MCULIBHANDLE, hw->pin);
206 return res;
207}
211static int reset(struct onewire_hwdef *hw) {
212 int r;
213
214 pull_low(hw->offset, 500); // min 480us
215 usctr = 0;
216 int low = 0;
217 int high = 0;
218
219 while (usctr < (480)) {
220 r = read_pin(1 << hw->offset);
221 if (r == 0) {
222 low++;
223 } else if (r == 1) {
224 high++;
225 } else {
226 printf("Error reading pin: %i\r\n", r);
227 return 0;
228 }
229 }
230 //printf("Presence detection: low=%i, high=%i, ctr=%i, lctr=%i\r\n",low,high,ctr,total);
231
232 // if we have no high signal we have neither DS18B20 and no pull-up
233 // if we have no low signal we have pull-up and no DS18B20
234 if ((low == 0) || (high == 0)) {
235 return 0;
236 }
237 return 1;
238}
239static byte read_byte(struct onewire_hwdef *hw) {
240 int i;
241 byte res = 0;
242
243 for (i = 0; i < 8; i++) {
244 byte b = read_bit(hw);
245 b = b << i;
246 res |= b;
247 }
248 return res;
249}
250static void write_byte(struct onewire_hwdef *hw, byte b) {
251 int i;
252
253 for (i = 0; i < 8; i++) {
254 // sending LSB first...
255 if ((b >> i) & 1) {
256 write_bit_1(hw);
257 } else {
258 write_bit_0(hw);
259 }
260 }
261}
262
263static void write_bit_1(struct onewire_hwdef *hw) {
264 pull_low(hw->offset, 0);
265 //pull_low(get_pin(),5);
266 delay_us(61); // 50 *should* be enough
267}
268static void write_bit_0(struct onewire_hwdef *hw) {
269 pull_low(hw->offset, 61);
270 delay_us(11);
271}
276static byte read_bit(struct onewire_hwdef *hw) {
277 int sampletime = 15 / freq_divider;
278 int samples = 0;
279 int val = 0;
280
281 pull_low(hw->offset, 5); // this should be low for 1us - 5us and sample at 10us. we can't be that exact on stm32lxx
282 usctr = 0;
283 val = read_pin(1 << hw->offset);
284 while (usctr < sampletime) {
285 samples++;
286 val = val + read_pin(1 << hw->offset);
287 }
288 delay_us(65); //min 60 us wait slot thing
289 //printf("Read bit: %i of %i samples \r\n",val,samples);
290 return (val > 0) ? 1 : 0;
291 //return (val == samples) ? 1 : 0;
292}
293static inline void read_buf(struct onewire_hwdef *hw, int cnt) {
294 int i;
295
296 for (i = 0; i < sizeof(buf); i++) {
297 buf[i] = 0xDA;
298 }
299 for (i = 0; i < cnt; i++) {
300 byte b = read_byte(hw);
301 buf[i] = b;
302 }
303 print_recvbuf((byte *)buf);
304}
305
306
307int query_onewire(struct onewire_hwdef *hw, byte *error) {
308 int i;
309 int temp = 30000;
310
311 power_set_speed(10);
312 for (i = 0; i < 5; i++) {
313 temp = read_temperature(hw, error);
314 printf("Temperature (pin %i): %i\r\n", hw->pin, temp);
315 if ((temp > 8500) || (*error != 0)) {
316 printf("Onewire above threshold - failed! \r\n");
317 } else {
318 break;
319 }
320 }
321 if (temp > 7500) {
322 return 0;
323 }
324 return temp;
325}
326
327/*********************************************************************************
328 * callbacks from sensors framework
329 *******************************************************************************/
330// called each time the sensors framework wants a reading
331int onewire_run(byte idx, byte *error) {
332 *error = 0;
333 struct onewire_hwdef hw;
334
335 if ((idx == 212) && (CONFIG_FLAGS_TEMP212)) {
336 hw.offset = 12;
337 hw.pin = 212; // PIN onewire is connected to
338 return query_onewire(&hw, error);
339 }
340
341 if ((idx == 207) && (CONFIG_FLAGS_TEMP207)) {
342 hw.offset = 7;
343 hw.pin = 207; // PIN onewire is connected to
344 return query_onewire(&hw, error);
345 }
346
347 if ((idx == 211) && (CONFIG_FLAGS_TEMP211)) {
348 hw.offset = 11;
349 hw.pin = 211; // PIN onewire is connected to
350 return query_onewire(&hw, error);
351 }
352 return 0;
353}
354// callback from sensors framework
355int onewire_reading_size(byte idx) {
356 return 2;
357}
358
359int onewire_init(byte idx) {
360 last_run = 0;
361 toggler = 0;
362 return 0;
363}