bdb54a93e3570d59e7719bbc1a49ada4effe9807
[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 #ifdef LINUX
36 #include <unistd.h>
37 #endif
38 #ifdef WIN
39 void usleep(int waitTime) {\r
40         __int64 time1 = 0, time2 = 0, freq = 0;\r
41 \r
42         QueryPerformanceCounter((LARGE_INTEGER *)&time1);\r
43         QueryPerformanceFrequency((LARGE_INTEGER *)&freq);\r
44 \r
45         do {\r
46                 QueryPerformanceCounter((LARGE_INTEGER *)&time2);\r
47         } while ((time2 - time1) < waitTime);\r
48 }
49 #endif
50 owDevice::owDevice(owInterface *owi_,snum_t num) {
51                 snum=num;
52                 owi=owi_;
53                 config=new owDeviceConfig;
54                 configstate=OWDCS_NONE;
55                 raw.insert(raw.begin(),4,0);
56                 values.insert(values.begin(),4,0);
57                 lastfound=0;
58         }
59         
60 void owDevice::setDefaultConfig() {
61                 config->setInvalid();
62         }
63         
64 std::vector<std::string> owDevice::getFamilyInfo() {
65                 return owDeviceConfig::getFamilyInfo(snum.byte[0]);
66         }
67 int owDevice::readConfig() {
68         std::vector<uint8_t> cl;
69         int r=owi->maxrepeat+1;
70         setDefaultConfig();
71         int conf16=0;
72         do {
73                 owi->log->clear();
74                 cl.clear();
75                 cl.push_back(0x85);
76                 Communicate(&cl, 1, 26);
77                 //for (uint8_t v:cl) printf("%02X ",v); 
78                 if ((cl[1]==0xFF)||(cl[2]==0xFF)) {
79                         owi->log->set(OWLOG_INFO,"Get Config not work, maybe not a emulation from www.tm3d.de");
80                         return 0;
81                 }
82                 int oldInfo=1;
83                 //all Code pos +1 
84                 for(int i=19;i<27;i++) if (cl[i]!=0xFF) {oldInfo=0;break;} 
85                 if (oldInfo) {
86                         owi->log->set(OWLOG_INFO,"Old 16 Byte Config");
87                         if (cl[18]==0xFF) { 
88                                 if (!owi->calcCRC8(std::vector<uint8_t>(cl.begin()+1,cl.begin()+17))) {
89                                         owi->log->set(OWLOG_WARNING,"CRC8 ERROR Reading Config");
90                                 }
91                         } else {
92                                 if (!owi->testCRC16(cl)) {
93                                         owi->log->set(OWLOG_WARNING,"CRC16 ERROR Reading Config ");
94                                 }
95                         }
96                         if (owi->log->last()<OWLOG_WARNING) {
97                                 cl[9]=2; //Attiny84A
98                                 for(int i=0;i<7;i++) {cl[18+i]=cl[10+i];cl[10+i]=0;} //Move OWID2 Set Sensor to 0
99                                 conf16=1;
100
101                         }
102                 } else { //New CRC
103                         if (cl[26]==0xFF) { 
104                                 if (!owi->calcCRC8(std::vector<uint8_t>(cl.begin()+1,cl.begin()+25))) {
105                                         owi->log->set(OWLOG_WARNING,"CRC8 ERROR Reading Config");
106                                 }
107                         } else {
108                                 if (!owi->testCRC16(cl)) {
109                                         owi->log->set(OWLOG_WARNING,"CRC16 ERROR Reading Config ");
110                                 }
111                         }
112                 }               
113                 r--;
114         }
115         while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
116         if (r==0) {
117                 owi->log->set(OWLOG_ERROR,"To much Errors while read config");
118                 return -1;
119         }
120         config->setConfig(std::vector<uint8_t>(cl.begin()+1,cl.begin()+25));
121         if (config->valid) {
122                 if (conf16) configstate=OWDCS_16; else configstate=OWDCS_24;
123         } else configstate=OWDCS_NONE;
124         return 1;
125 }
126
127
128 int owDevice::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
129         owi->Wait_Free();
130         owi->MatchRom(snum);
131         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
132         owi->Communicate(data, scount, rcount);  
133         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
134         owi->Free();
135         return 1;
136 }
137
138 int owDevice::CommunicateShort(std::vector<uint8_t> *data, int scount, int rcount) {
139         owi->Wait_Free();
140         owi->Reset();
141         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
142         owi->Communicate(data, scount, rcount);
143         if (owi->log->last()==OWLOG_ERROR) {owi->Free();return 0;}
144         owi->Free();
145         return 1;
146 }
147
148
149 void owDevice::changeID(snum_t nid) {
150         int i;
151         if (nid.byte[0] != snum.byte[0]) {
152                 owi->log->set(OWLOG_ERROR,"Family ID should not be changed, no correct ID");
153                 return;
154         }
155         std::vector<uint8_t> id;
156         for(i=0;i<7;i++) id.push_back(nid.byte[i]);
157         id.push_back(owi->calcCRC8(id));
158         std::vector<uint8_t> cl;
159         int r=owi->maxrepeat+1;
160         do {
161                 owi->log->clear();
162                 cl.clear();
163                 cl.push_back(0x75);
164                 cl.insert(cl.begin()+1,id.begin(),id.end());
165                 Communicate(&cl, 9,0);
166                 if (owi->log->last()==OWLOG_ERROR) {r--;continue;}
167                 cl.clear();
168                 cl.push_back(0xA7);
169                 Communicate(&cl, 1, 8);
170                 if (owi->log->last()==OWLOG_ERROR) {r--;continue;}
171                 for (i = 0; i < 8; i++) {
172                         if (cl[i + 1] != id[i]) {
173                                 owi->log->set(OWLOG_WARNING,"changeID Comunication ERROR");
174                                 break;
175                         }
176                 }
177                 r--;
178         }
179         while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
180         if (r==0) {
181                 owi->log->set(OWLOG_ERROR,"Can not change ID");
182                 return;
183         }       
184         cl.clear();
185         cl.push_back(0x79);
186         cl.push_back(snum.byte[1]);
187         cl.push_back(snum.byte[5]);
188         cl.push_back(snum.byte[6]);
189         Communicate(&cl, 4, 0);
190         usleep(50000);  
191 }
192
193 void owDevice::runFlasher() {
194         std::vector<uint8_t> cl;
195         cl.push_back(0x88);
196         this->Communicate(&cl, 1, 0);
197         this->Communicate(&cl, 1, 0);
198         this->Communicate(&cl, 1, 0);
199 }
200
201
202
203
204
205
206
207
208
209 void owDeviceDS18B20::setDefaultConfig() {
210         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});
211         configstate=OWDCS_DEFAULT;
212 };
213
214 int owDeviceDS18B20::readScratchpad(std::vector<uint8_t> *sp) {
215         std::vector<uint8_t> cl;
216         int r=owi->maxrepeat+1;
217         do {
218                 cl.clear();
219                 cl.push_back(0xBE);
220                 Communicate(&cl, 1, 9);
221                 if (owi->log->last()>=OWLOG_ERROR) return -1;
222                 sp->clear();
223                 sp->insert(sp->begin(),cl.begin()+1,cl.end());
224                 if (owi->calcCRC8(*sp)==0) return 1;
225                 owi->log->set(OWLOG_WARNING,"CRC ERROR reading DS18B20 Scrachpad");
226                 r--;
227         } while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
228                         
229         return 0;
230 }
231
232 int owDeviceDS18B20::convertAll() {
233         std::vector<uint8_t> sp;
234         //sp.push_back(0x44);
235         //communicate(&sp, 1, 0); ///########################################################
236         usleep(750000);
237
238         if (readScratchpad(&sp)) {
239                 int16_t tsht;
240                 tsht = sp[0] | ((int)sp[1] << 8);
241                 if (sp[1] & 0x080)
242                         tsht |= 0xFFFFF0000;
243                 raw[0]=tsht;
244                 values[0]=config->calculateValue(0, raw);
245                         return 1;
246         }               
247         return 0;
248 }
249
250
251 void owDeviceDS2438::setDefaultConfig() {
252         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});
253         configstate=OWDCS_DEFAULT;
254 }
255
256
257 int owDeviceDS2438::readScratchpad(std::vector<uint8_t> *sp, uint8_t page, int recall) {
258         std::vector<uint8_t> cl;
259         int r=owi->maxrepeat+1;
260         do {
261                 if (recall) {
262                         cl.clear();
263                         cl.push_back(0xB8); //recall
264                         cl.push_back(page);
265                         Communicate(&cl, 2, 0);
266                         if (owi->log->last()>=OWLOG_ERROR) return -1;
267                 }
268                 cl.clear();
269                 cl.push_back(0xBE);
270                 cl.push_back(page);
271                 Communicate(&cl, 2, 9);
272                 if (owi->log->last()>=OWLOG_ERROR) return -1;
273                 sp->clear();
274                 sp->insert(sp->begin(),cl.begin()+2,cl.end());
275                 if (owi->calcCRC8(*sp)==0) return 1;
276                 owi->log->set(OWLOG_WARNING,"CRC ERROR reading DS2438 Scrachpad");
277                 r--;
278         } while ((owi->log->last()>=OWLOG_WARNING)&&(r>0));
279                         
280         return 0;
281 }
282
283 int owDeviceDS2438::readMemory(int page,int start, int count,std::vector<uint8_t> *data) {
284         if ((page>7)||(page<0)||(start>7)||(start<0)||(start+count>8)) return 0;
285         std::vector<uint8_t> cl;
286         cl.clear();
287         cl.push_back(0xB8); //recall
288         cl.push_back(page);
289         Communicate(&cl, 2, 0);
290         if (owi->log->last()>=OWLOG_ERROR) return -1;
291         cl.clear();
292         cl.push_back(0xBE);
293         cl.push_back(page);
294         Communicate(&cl, 2, 9);
295         if (owi->log->last()>=OWLOG_ERROR) return -1;
296         cl.erase(cl.begin());
297         cl.erase(cl.begin());
298         if (owi->calcCRC8(cl)!=0) {
299                 owi->log->set(OWLOG_WARNING,"CRC ERROR reading DS2438 Scrachpad");
300         }
301         data->clear();
302         data->insert(data->begin(),cl.begin()+start,cl.begin()+start+count);
303         return count;
304 }
305 int owDeviceDS2438::writeMemory(int page,int start, int count,std::vector<uint8_t> *data) {
306         if ((page>7)||(page<0)||(start>7)||(start<0)||(start+count>8)) return 0;
307         std::vector<uint8_t> sp;
308         if ((start>0)||(count<8)) {
309                 readMemory(page,0,8,&sp);
310         }
311         std::vector<uint8_t> cl;
312         cl.push_back(0x4E); 
313         cl.push_back(page);
314         int j=0;
315         for(int i=0;i<8;i++) {
316                 if ((i<start)||(i>=start+count)) cl.push_back(sp[i]); else {cl.push_back((*data)[j]);j++;}
317         }
318         Communicate(&cl, 10,0);
319         if (owi->log->last()>=OWLOG_ERROR) return -1;
320         std::vector<uint8_t> cl1;
321         cl1.push_back(0xBE);
322         cl1.push_back(page);
323         Communicate(&cl1, 2, 9);
324         if (owi->log->last()>=OWLOG_ERROR) return -1;
325         cl1.erase(cl1.begin());
326         cl1.erase(cl1.begin());
327         if (owi->calcCRC8(cl1)!=0) {
328                 owi->log->set(OWLOG_WARNING,"CRC ERROR rereading DS2438 Scrachpad");
329         }
330         for(int i=0;i<8;i++) {
331                 if (cl1[i]!=cl[i+2]) {
332                         owi->log->set(OWLOG_ERROR,"Reread not equal, nothing copied");
333                         return 0; 
334                 }
335         }
336         cl.clear();
337         cl.push_back(0x48);
338         cl.push_back(page);
339         Communicate(&cl, 2, 0);
340         if (owi->log->last()>=OWLOG_ERROR) return -1;
341         return 1;
342 }
343
344
345
346 int owDeviceDS2438::setConfigByte(uint8_t cb) {
347         std::vector<uint8_t> sp;
348         int k;
349         for(k=0;k<owi->maxrepeat;k++) {
350                 owi->log->clear();
351                 sp.clear();
352                 sp.push_back(0x4E);
353                 sp.push_back(0x00);
354                 sp.push_back(cb);
355                 Communicate(&sp,3,0);
356                 if (owi->log->last()>=OWLOG_ERROR) return -1;
357                 sp.clear();
358                 readScratchpad(&sp,0,0);
359                 if (owi->log->last()>=OWLOG_ERROR) return -2;
360                 if (cb==sp[0]) return 1;
361                 owi->log->set(OWLOG_WARNING,"ERROR set config byte of DS2438");
362         }
363         owi->log->set(OWLOG_WARNING,"Config of DS2438 byte not set");
364         return 0;
365 }
366
367 inline int16_t ow_fconvert(uint8_t b1, uint16_t b2) {
368   int tsht;
369   tsht=b1  |((int)b2<<8);
370   if (b2 & 0x080)
371         tsht |= 0xFFFFF0000;
372   return tsht;
373 }
374
375 int owDeviceDS2438::convertAll() {
376         for(int k=0;k<owi->maxrepeat;k++)  {
377                 std::vector<uint8_t> sp;
378                 //sp.push_back(0x44);
379                 //Communicate(&sp, 1, 0);///########################################################
380                 if (owi->log->last()>=OWLOG_ERROR) continue;
381                 usleep(100000);
382                 if (setConfigByte(0x08)<=0) continue;
383                 for(int k=0;k<owi->maxrepeat;k++) {
384                         sp.clear();
385                         sp.push_back(0xB4);
386                         Communicate(&sp, 1, 0);
387                 }
388                 if (owi->log->last()>=OWLOG_ERROR) continue;
389                 usleep(100000);
390
391
392                 readScratchpad(&sp,0,1);
393                 int temp=ow_fconvert(sp[1],sp[2]);
394                 int VDD=ow_fconvert(sp[3],sp[4]);
395                 if (setConfigByte(0x00)<=0) continue;
396
397                 for(int k=0;k<owi->maxrepeat;k++) {
398                         sp.clear();
399                         sp.push_back(0xB4);
400                         Communicate(&sp, 1, 0);
401                 }
402                 if (owi->log->last()>=OWLOG_ERROR) continue;
403
404                 usleep(100000);
405
406
407
408                 readScratchpad(&sp,0,1);
409                 if (owi->log->last()>=OWLOG_ERROR) continue;
410                 int I=ow_fconvert(sp[5],sp[6]);
411                 int VAD=ow_fconvert(sp[3],sp[4]);
412                 raw[0]=temp;
413                 raw[1]=VDD;
414                 raw[2]=VAD;
415                 raw[3]=I;
416                 for(int i=0;i<4;i++) values[i]=config->calculateValue(i, raw);
417                 break;
418         }
419         if (owi->log->last()>=OWLOG_ERROR) return 0;
420         return 1;
421 }
422
423
424 void owDeviceDS2450::setDefaultConfig() {
425         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});
426         configstate=OWDCS_DEFAULT;
427 }
428
429 int owDeviceDS2450::convertAll() {
430         convert(0x0F,0);
431         if (owi->log->last()>=OWLOG_WARNING) {
432                 return 0;
433         }
434         std::vector<uint8_t> sp;
435         readMemory(0,&sp);
436         if (owi->log->last()>=OWLOG_WARNING) {
437                 return 0;
438         }
439
440         for(int i=0;i<4;i++) {
441                 raw[i]=(sp[2 * i] | sp[2 * i + 1] << 8);
442         }
443         for(int i=0;i<4;i++) {
444                 values[i]=config->calculateValue(i, raw);
445         }
446         return 1;
447
448 }
449
450 void owDeviceDS2450::readMemory(uint8_t addr,std::vector<uint8_t> *sp) {
451         std::vector<uint8_t> cl;
452         cl.push_back(0xAA);
453         cl.push_back(addr);
454         cl.push_back(0x00);
455         Communicate(&cl,3,10-addr);
456         if (owi->log->last()>=OWLOG_WARNING) {
457                 return;
458         }
459         if (!owi->testCRC16(cl)) {
460                 for (uint8_t v :cl) printf("%02X ",v);
461                 printf("\n");
462                 owi->log->set(OWLOG_ERROR,"CRC ERROR Reading Memory of DS2450");
463                 return;
464         }
465         sp->clear();
466         sp->insert(sp->begin(),cl.begin()+3,cl.end()-2);
467 }
468
469 void owDeviceDS2450::writeMemory(uint8_t addr,std::vector<uint8_t> *sp) {
470         std::vector<uint8_t> cl;
471         cl.push_back(0x55);
472         cl.push_back(addr);
473         cl.push_back(0x00);
474         owi->MatchRom(snum);
475         if (owi->log->last()>=OWLOG_WARNING) {
476                 return;
477         }
478         for(uint8_t b: (*sp)) {
479                 cl.push_back(b);
480                 owi->Communicate(&cl,cl.size(),2);
481                 if (owi->log->last()>=OWLOG_WARNING) {
482                         return;
483                 }
484                 if (!owi->testCRC16(cl)) {
485                         owi->log->set(OWLOG_ERROR,"CRC ERROR Writing Memory of DS2450");
486                         return;
487                 }
488                 cl.clear();
489                 owi->Communicate(&cl, 0, 1);
490                 if (owi->log->last()>=OWLOG_WARNING) {
491                         return;
492                 }
493                 if (cl[0] != b) {
494                         owi->log->set(OWLOG_ERROR,"ERROR Writing Memory of DS2450");
495                         return;
496                 }
497                 cl.clear();
498         }
499 }
500         
501 void owDeviceDS2450::convert(uint8_t mask, uint8_t preset) {
502         std::vector<uint8_t> cl;
503         cl.push_back(0x3C);
504         cl.push_back(mask);
505         cl.push_back(preset);
506         Communicate(&cl, 3, 2);
507         if (!owi->testCRC16(cl)) {
508                 for (uint8_t v :cl) printf("%02X ",v);
509                 printf("\n");
510                 owi->log->set(OWLOG_ERROR,"CRC ERROR Convert Command of DS2450");
511                 return;
512         }
513         usleep(10000);
514 }
515
516
517
518
519
520
521
522
523
524
525
526 void owDeviceDS2423::setDefaultConfig() {
527         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});
528         configstate=OWDCS_DEFAULT;
529 }
530
531 int owDeviceDS2423::convertAll() {
532         for(uint8_t i=12;i<16;i++) {
533                 raw[i-12]=readCounter(i);
534         }
535         for(int i=0;i<4;i++) {
536                 values[i]=config->calculateValue(i, raw);
537         }
538         return 1;
539 }
540 uint32_t owDeviceDS2423::readCounter(uint8_t page) {
541         std::vector<uint8_t> cl;
542         cl.push_back(0xA5);
543         uint16_t addr=(page<<5)+31;
544         cl.push_back(addr&0xFF);
545         cl.push_back(addr>>8);
546         Communicate(&cl,3,11);
547         //for (uint8_t v :cl) printf("%02X ",v);
548         //printf("\n");
549         if (!owi->testCRC16(cl)) {
550                 owi->log->set(OWLOG_ERROR,"CRC ERROR Reading Counter of DS2423");
551                 return 0;
552         }
553         uint32_t ret=0;
554          
555         for(size_t i=cl.size()-8;i>cl.size()-11;i--) {
556                 ret<<=8;
557                 ret|=cl[i];
558                 
559         }
560                 
561         return ret;
562 }
563
564
565 int owDeviceDS2423::readMemory(int page,int start, int count,std::vector<uint8_t> *data){
566         std::vector<uint8_t> cl;
567         cl.push_back(0xF0);
568         uint16_t adr=page<<5;
569         cl.push_back(adr&0xFF);
570         cl.push_back((adr>>8)&0xFF);
571         Communicate(&cl, 3, 32);
572         //No CRC 
573         data->clear();
574         data->insert(data->begin(),cl.begin()+3+start,cl.begin()+start+3+count);
575         return count;   
576
577 }
578 int owDeviceDS2423::writeMemory(int page,int start, int count,std::vector<uint8_t> *data) {
579         std::vector<uint8_t> cl;
580         cl.push_back(0x0F);
581         uint16_t adr=(page<<5)+start;
582         cl.push_back(adr&0xFF);
583         cl.push_back(adr>>8);
584         for(int i=0;i<count;i++) {
585                 cl.push_back((*data)[i]);
586         }
587         Communicate(&cl, 3+count, 0);
588         for (uint8_t v :cl) printf("%02X ",v);printf("\n");
589         cl.clear();
590         cl.push_back(0xAA);
591         Communicate(&cl, 1, 36);
592         //for (uint8_t v :cl) printf("%02X ",v);;printf("\n");
593         cl[0]=0x5A;
594         Communicate(&cl, 4, 1);
595         usleep(100000);
596         if (cl[4]!=0xAA) {
597                 for (uint8_t v :cl) printf("%02X ",v);;printf("\n");
598                 owi->log->set(OWLOG_ERROR,"DS2423 Copy from Scratchpad to Memmory Error");
599                 //return 0;
600         }
601         return count;
602 }
603
604
605
606
607
608