70fe96a829170978eef1c79e8208e903dda28523
[owTools.git] / src / owDevice.cpp
1 // Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //  * Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 //  * Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the
13 //    distribution.
14 //  * All advertising materials mentioning features or use of this
15 //    software must display the following acknowledgement: This product
16 //    includes software developed by tm3d.de and its contributors.
17 //  * Neither the name of tm3d.de nor the names of its contributors may
18 //    be used to endorse or promote products derived from this software
19 //    without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33
34 #include "owInterface.h"
35 #include <unistd.h>
36
37 owDevice::owDevice(owInterface *owi_,snum_t num) {
38                 snum=num;
39                 owi=owi_;
40                 config=new owDeviceConfig;
41                 configstate=OWDCS_NONE;
42                 raw.insert(raw.begin(),4,0);
43                 values.insert(values.begin(),4,0);
44                 lastfound=0;
45         }
46         
47 void owDevice::setDefaultConfig() {
48                 config->setInvalid();
49         }
50         
51 std::vector<std::string> owDevice::getFamilyInfo() {
52                 return owDeviceConfig::getFamilyInfo(snum.byte[0]);
53         }
54 int owDevice::readConfig() {
55         std::vector<uint8_t> cl;
56         int r=owi->maxrepeat+1;
57         setDefaultConfig();
58         int conf16=0;
59         do {
60                 owi->log->clear();
61                 cl.clear();
62                 cl.push_back(0x85);
63                 Communicate(&cl, 1, 26);
64                 //for (uint8_t v:cl) printf("%02X ",v); 
65                 if ((cl[1]==0xFF)||(cl[2]==0xFF)) {
66                         owi->log->set(OWLOG_INFO,"Get Config not work, maybe not a emulation from www.tm3d.de");
67                         return 0;
68                 }
69                 int oldInfo=1;
70                 //all Code pos +1 
71                 for(int i=19;i<27;i++) if (cl[i]!=0xFF) {oldInfo=0;break;} 
72                 if (oldInfo) {
73                         owi->log->set(OWLOG_INFO,"Old 16 Byte Config");
74                         if (cl[18]==0xFF) { 
75                                 if (!owi->calcCRC8(std::vector<uint8_t>(cl.begin()+1,cl.begin()+17))) {
76                                         owi->log->set(OWLOG_WARNING,"CRC8 ERROR Reading Config");
77                                 }
78                         } else {
79                                 if (!owi->testCRC16(cl)) {
80                                         owi->log->set(OWLOG_WARNING,"CRC16 ERROR Reading Config ");
81                                 }
82                         }
83                         if (owi->log->last()<OWLOG_WARNING) {
84                                 cl[9]=2; //Attiny84A
85                                 for(int i=0;i<7;i++) {cl[18+i]=cl[10+i];cl[10+i]=0;} //Move OWID2 Set Sensor to 0
86                                 conf16=1;
87
88                         }
89                 } else { //New CRC
90                         if (cl[26]==0xFF) { 
91                                 if (!owi->calcCRC8(std::vector<uint8_t>(cl.begin()+1,cl.begin()+25))) {
92                                         owi->log->set(OWLOG_WARNING,"CRC8 ERROR Reading Config");
93                                 }
94                         } else {
95                                 if (!owi->testCRC16(cl)) {
96                                         owi->log->set(OWLOG_WARNING,"CRC16 ERROR Reading Config ");
97                                 }
98                         }
99                 }               
100                 r--;
101         }
102         while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
103         if (r==0) {
104                 owi->log->set(OWLOG_ERROR,"To much Errors while read config");
105                 return -1;
106         }
107         config->setConfig(std::vector<uint8_t>(cl.begin()+1,cl.begin()+25));
108         if (config->valid) {
109                 if (conf16) configstate=OWDCS_16; else configstate=OWDCS_24;
110         } else configstate=OWDCS_NONE;
111         return 1;
112 }
113
114
115 int owDevice::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
116         owi->Wait_Free();
117         owi->MatchRom(snum);
118         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
119         owi->Communicate(data, scount, rcount);  
120         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
121         owi->Free();
122         return 1;
123 }
124
125 int owDevice::CommunicateShort(std::vector<uint8_t> *data, int scount, int rcount) {
126         owi->Wait_Free();
127         owi->Reset();
128         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
129         owi->Communicate(data, scount, rcount);
130         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
131         owi->Free();
132         return 1;
133 }
134
135
136 void owDevice::changeID(snum_t nid) {
137         int i;
138         if (nid.byte[0] != snum.byte[0]) {
139                 owi->log->set(OWLOG_ERROR,"Family ID should not be changed, no correct ID");
140                 return;
141         }
142         std::vector<uint8_t> id;
143         for(i=0;i<7;i++) id.push_back(nid.byte[i]);
144         id.push_back(owi->calcCRC8(id));
145         std::vector<uint8_t> cl;
146         int r=owi->maxrepeat+1;
147         do {
148                 owi->log->clear();
149                 cl.clear();
150                 cl.push_back(0x75);
151                 cl.insert(cl.begin()+1,id.begin(),id.end());
152                 Communicate(&cl, 9,0);
153                 if (owi->log->last()==OWLOG_ERROR) {r--;continue;}
154                 cl.clear();
155                 cl.push_back(0xA7);
156                 Communicate(&cl, 1, 8);
157                 if (owi->log->last()==OWLOG_ERROR) {r--;continue;}
158                 for (i = 0; i < 8; i++) {
159                         if (cl[i + 1] != id[i]) {
160                                 owi->log->set(OWLOG_WARNING,"changeID Comunication ERROR");
161                                 break;
162                         }
163                 }
164                 r--;
165         }
166         while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
167         if (r==0) {
168                 owi->log->set(OWLOG_ERROR,"Can not change ID");
169                 return;
170         }       
171         cl.clear();
172         cl.push_back(0x79);
173         cl.push_back(snum.byte[1]);
174         cl.push_back(snum.byte[5]);
175         cl.push_back(snum.byte[6]);
176         Communicate(&cl, 4, 0);
177         usleep(50000);  
178 }
179
180 void owDevice::runFlasher() {
181         std::vector<uint8_t> cl;
182         cl.push_back(0x88);
183         this->Communicate(&cl, 1, 0);
184         this->Communicate(&cl, 1, 0);
185         this->Communicate(&cl, 1, 0);
186 }
187
188
189
190
191
192
193
194
195
196 void owDeviceDS18B20::setDefaultConfig() {
197         config->setConfig({1,1, 0,0, 0,0, 0,0, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0});
198         configstate=OWDCS_DEFAULT;
199 };
200
201 int owDeviceDS18B20::readScratchpad(std::vector<uint8_t> *sp) {
202         std::vector<uint8_t> cl;
203         int r=owi->maxrepeat+1;
204         do {
205                 cl.clear();
206                 cl.push_back(0xBE);
207                 Communicate(&cl, 1, 9);
208                 if (owi->log->last()>=OWLOG_ERROR) return -1;
209                 sp->clear();
210                 sp->insert(sp->begin(),cl.begin()+1,cl.end());
211                 if (owi->calcCRC8(*sp)==0) return 1;
212                 owi->log->set(OWLOG_WARNING,"CRC ERROR reading DS18B20 Scrachpad");
213                 r--;
214         } while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
215                         
216         return 0;
217 }
218
219 int owDeviceDS18B20::convertAll() {
220         std::vector<uint8_t> sp;
221         sp.push_back(0x44);
222         Communicate(&sp, 1, 0);
223         usleep(750000);
224
225         if (readScratchpad(&sp)) {
226                 int16_t tsht;
227                 tsht = sp[0] | ((int)sp[1] << 8);
228                 if (sp[1] & 0x080)
229                         tsht |= 0xFFFFF0000;
230                 raw[0]=tsht;
231                 values[0]=config->calculateValue(0, raw);
232                         return 1;
233         }               
234         return 0;
235 }
236
237
238 void owDeviceDS2438::setDefaultConfig() {
239         config->setConfig({1,6, 6,8, 4,7, 6,17, 0,2,3,12,4,0,0,0,0,0,0,0,0,0,0,0});
240         configstate=OWDCS_DEFAULT;
241 }
242
243
244 int owDeviceDS2438::readScratchpad(std::vector<uint8_t> *sp, uint8_t page, int recall) {
245         std::vector<uint8_t> cl;
246         int r=owi->maxrepeat+1;
247         do {
248                 if (recall) {
249                         cl.clear();
250                         cl.push_back(0xB8); //recall
251                         cl.push_back(page);
252                         Communicate(&cl, 2, 0);
253                         if (owi->log->last()>=OWLOG_ERROR) return -1;
254                 }
255                 cl.clear();
256                 cl.push_back(0xBE);
257                 cl.push_back(page);
258                 Communicate(&cl, 2, 9);
259                 if (owi->log->last()>=OWLOG_ERROR) return -1;
260                 sp->clear();
261                 sp->insert(sp->begin(),cl.begin()+2,cl.end());
262                 if (owi->calcCRC8(*sp)==0) return 1;
263                 owi->log->set(OWLOG_WARNING,"CRC ERROR reading DS2438 Scrachpad");
264                 r--;
265         } while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
266                         
267         return 0;
268 }
269
270 int owDeviceDS2438::setConfigByte(uint8_t cb) {
271         std::vector<uint8_t> sp;
272         int k;
273         for(k=0;k<owi->maxrepeat;k++) {
274                 owi->log->clear();
275                 sp.clear();
276                 sp.push_back(0x4E);
277                 sp.push_back(0x00);
278                 sp.push_back(cb);
279                 Communicate(&sp,3,0);
280                 if (owi->log->last()>=OWLOG_ERROR) return -1;
281                 sp.clear();
282                 readScratchpad(&sp,0,0);
283                 if (owi->log->last()>=OWLOG_ERROR) return -2;
284                 if (cb==sp[0]) return 1;
285                 owi->log->set(OWLOG_WARNING,"ERROR set config byte of DS2438");
286         }
287         owi->log->set(OWLOG_WARNING,"Config of DS2438 byte not set");
288         return 0;
289 }
290
291 inline int16_t ow_fconvert(uint8_t b1, uint16_t b2) {
292   int tsht;
293   tsht=b1  |((int)b2<<8);
294   if (b2 & 0x080)
295         tsht |= 0xFFFFF0000;
296   return tsht;
297 }
298
299 int owDeviceDS2438::convertAll() {
300         for(int k=0;k<owi->maxrepeat;k++)  {
301                 std::vector<uint8_t> sp;
302                 sp.push_back(0x44);
303                 Communicate(&sp, 1, 0);
304                 if (owi->log->last()>=OWLOG_ERROR) continue;
305                 usleep(100000);
306                 if (setConfigByte(0x08)<=0) continue;
307                 for(int k=0;k<owi->maxrepeat;k++) {
308                         sp.clear();
309                         sp.push_back(0xB4);
310                         Communicate(&sp, 1, 0);
311                 }
312                 if (owi->log->last()>=OWLOG_ERROR) continue;
313                 usleep(100000);
314
315
316                 readScratchpad(&sp,0,1);
317                 int temp=ow_fconvert(sp[1],sp[2]);
318                 int VDD=ow_fconvert(sp[3],sp[4]);
319                 if (setConfigByte(0x00)<=0) continue;
320
321                 for(int k=0;k<owi->maxrepeat;k++) {
322                         sp.clear();
323                         sp.push_back(0xB4);
324                         Communicate(&sp, 1, 0);
325                 }
326                 if (owi->log->last()>=OWLOG_ERROR) continue;
327
328                 usleep(100000);
329
330
331
332                 readScratchpad(&sp,0,1);
333                 if (owi->log->last()>=OWLOG_ERROR) continue;
334                 int I=ow_fconvert(sp[5],sp[6]);
335                 int VAD=ow_fconvert(sp[3],sp[4]);
336                 raw[0]=temp;
337                 raw[1]=VDD;
338                 raw[2]=VAD;
339                 raw[3]=I;
340                 for(int i=0;i<4;i++) values[i]=config->calculateValue(i, raw);
341                 break;
342         }
343         if (owi->log->last()>=OWLOG_ERROR) return 0;
344         return 1;
345 }
346
347
348 void owDeviceDS2450::setDefaultConfig() {
349         config->setConfig({6,9, 6,9, 6,9, 6,9, 0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0});
350         configstate=OWDCS_DEFAULT;
351 }
352
353 int owDeviceDS2450::convertAll() {
354         convert(0x0F,0);
355         if (owi->log->last()>=OWLOG_WARNING) {
356                 return 0;
357         }
358         std::vector<uint8_t> sp;
359         readMemory(0,&sp);
360         if (owi->log->last()>=OWLOG_WARNING) {
361                 return 0;
362         }
363
364         for(int i=0;i<4;i++) {
365                 raw[i]=(sp[2 * i] | sp[2 * i + 1] << 8);
366         }
367         for(int i=0;i<4;i++) {
368                 values[i]=config->calculateValue(i, raw);
369         }
370         return 1;
371
372 }
373
374 void owDeviceDS2450::readMemory(uint8_t addr,std::vector<uint8_t> *sp) {
375         std::vector<uint8_t> cl;
376         cl.push_back(0xAA);
377         cl.push_back(addr);
378         cl.push_back(0x00);
379         Communicate(&cl,3,10-addr);
380         if (owi->log->last()>=OWLOG_WARNING) {
381                 return;
382         }
383         if (!owi->testCRC16(cl)) {
384                 owi->log->set(OWLOG_ERROR,"CRC ERROR Reading Memory of DS2450");
385                 return;
386         }
387         sp->clear();
388         sp->insert(sp->begin(),cl.begin()+3,cl.end()-2);
389 }
390
391 void owDeviceDS2450::writeMemory(uint8_t addr,std::vector<uint8_t> *sp) {
392         std::vector<uint8_t> cl;
393         cl.push_back(0x55);
394         cl.push_back(addr);
395         cl.push_back(0x00);
396         owi->MatchRom(snum);
397         if (owi->log->last()>=OWLOG_WARNING) {
398                 return;
399         }
400         for(uint8_t b: (*sp)) {
401                 cl.push_back(b);
402                 owi->Communicate(&cl,cl.size(),2);
403                 if (owi->log->last()>=OWLOG_WARNING) {
404                         return;
405                 }
406                 if (!owi->testCRC16(cl)) {
407                         owi->log->set(OWLOG_ERROR,"CRC ERROR Writing Memory of DS2450");
408                         return;
409                 }
410                 cl.clear();
411                 owi->Communicate(&cl, 0, 1);
412                 if (owi->log->last()>=OWLOG_WARNING) {
413                         return;
414                 }
415                 if (cl[0] != b) {
416                         owi->log->set(OWLOG_ERROR,"ERROR Writing Memory of DS2450");
417                         return;
418                 }
419                 cl.clear();
420         }
421 }
422         
423 void owDeviceDS2450::convert(uint8_t mask, uint8_t preset) {
424         std::vector<uint8_t> cl;
425         cl.push_back(0x3C);
426         cl.push_back(mask);
427         cl.push_back(preset);
428         Communicate(&cl, 3, 2);
429         if (!owi->testCRC16(cl)) {
430                 owi->log->set(OWLOG_ERROR,"CRC ERROR Convert Command of DS2450");
431                 return;
432         }
433         usleep(10000);
434 }
435
436
437
438
439
440
441
442
443
444
445
446 void owDeviceDS2423::setDefaultConfig() {
447         config->setConfig({9,13, 9,13, 9,13, 9,13, 0,19,19,19,19,0,0,0,0,0,0,0,0,0,0,0});
448         configstate=OWDCS_DEFAULT;
449 }
450
451 int owDeviceDS2423::convertAll() {
452         for(uint8_t i=12;i<16;i++) {
453                 raw[i-12]=readCounter(i);
454         }
455         for(int i=0;i<4;i++) {
456                 values[i]=config->calculateValue(i, raw);
457         }
458         return 1;
459 }
460 uint32_t owDeviceDS2423::readCounter(uint8_t page) {
461         std::vector<uint8_t> cl;
462         cl.push_back(0xA5);
463         uint16_t addr=(page<<5)+31;
464         cl.push_back(addr&0xFF);
465         cl.push_back(addr>>8);
466         Communicate(&cl,3,11);
467         //for (uint8_t v :cl) printf("%02X ",v);
468         //printf("\n");
469         if (!owi->testCRC16(cl)) {
470                 owi->log->set(OWLOG_ERROR,"CRC ERROR Reading Counter of DS2423");
471                 return 0;
472         }
473         uint32_t ret=0;
474          
475         for(size_t i=cl.size()-8;i>cl.size()-11;i--) {
476                 ret<<=8;
477                 ret|=cl[i];
478                 
479         }
480                 
481         return ret;
482 }
483
484
485
486
487
488
489