Works now with Windows Visual Studio C++ too
[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::setConfigByte(uint8_t cb) {
284         std::vector<uint8_t> sp;
285         int k;
286         for(k=0;k<owi->maxrepeat;k++) {
287                 owi->log->clear();
288                 sp.clear();
289                 sp.push_back(0x4E);
290                 sp.push_back(0x00);
291                 sp.push_back(cb);
292                 Communicate(&sp,3,0);
293                 if (owi->log->last()>=OWLOG_ERROR) return -1;
294                 sp.clear();
295                 readScratchpad(&sp,0,0);
296                 if (owi->log->last()>=OWLOG_ERROR) return -2;
297                 if (cb==sp[0]) return 1;
298                 owi->log->set(OWLOG_WARNING,"ERROR set config byte of DS2438");
299         }
300         owi->log->set(OWLOG_WARNING,"Config of DS2438 byte not set");
301         return 0;
302 }
303
304 inline int16_t ow_fconvert(uint8_t b1, uint16_t b2) {
305   int tsht;
306   tsht=b1  |((int)b2<<8);
307   if (b2 & 0x080)
308         tsht |= 0xFFFFF0000;
309   return tsht;
310 }
311
312 int owDeviceDS2438::convertAll() {
313         for(int k=0;k<owi->maxrepeat;k++)  {
314                 std::vector<uint8_t> sp;
315                 sp.push_back(0x44);
316                 Communicate(&sp, 1, 0);
317                 if (owi->log->last()>=OWLOG_ERROR) continue;
318                 usleep(100000);
319                 if (setConfigByte(0x08)<=0) continue;
320                 for(int k=0;k<owi->maxrepeat;k++) {
321                         sp.clear();
322                         sp.push_back(0xB4);
323                         Communicate(&sp, 1, 0);
324                 }
325                 if (owi->log->last()>=OWLOG_ERROR) continue;
326                 usleep(100000);
327
328
329                 readScratchpad(&sp,0,1);
330                 int temp=ow_fconvert(sp[1],sp[2]);
331                 int VDD=ow_fconvert(sp[3],sp[4]);
332                 if (setConfigByte(0x00)<=0) continue;
333
334                 for(int k=0;k<owi->maxrepeat;k++) {
335                         sp.clear();
336                         sp.push_back(0xB4);
337                         Communicate(&sp, 1, 0);
338                 }
339                 if (owi->log->last()>=OWLOG_ERROR) continue;
340
341                 usleep(100000);
342
343
344
345                 readScratchpad(&sp,0,1);
346                 if (owi->log->last()>=OWLOG_ERROR) continue;
347                 int I=ow_fconvert(sp[5],sp[6]);
348                 int VAD=ow_fconvert(sp[3],sp[4]);
349                 raw[0]=temp;
350                 raw[1]=VDD;
351                 raw[2]=VAD;
352                 raw[3]=I;
353                 for(int i=0;i<4;i++) values[i]=config->calculateValue(i, raw);
354                 break;
355         }
356         if (owi->log->last()>=OWLOG_ERROR) return 0;
357         return 1;
358 }
359
360
361 void owDeviceDS2450::setDefaultConfig() {
362         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});
363         configstate=OWDCS_DEFAULT;
364 }
365
366 int owDeviceDS2450::convertAll() {
367         convert(0x0F,0);
368         if (owi->log->last()>=OWLOG_WARNING) {
369                 return 0;
370         }
371         std::vector<uint8_t> sp;
372         readMemory(0,&sp);
373         if (owi->log->last()>=OWLOG_WARNING) {
374                 return 0;
375         }
376
377         for(int i=0;i<4;i++) {
378                 raw[i]=(sp[2 * i] | sp[2 * i + 1] << 8);
379         }
380         for(int i=0;i<4;i++) {
381                 values[i]=config->calculateValue(i, raw);
382         }
383         return 1;
384
385 }
386
387 void owDeviceDS2450::readMemory(uint8_t addr,std::vector<uint8_t> *sp) {
388         std::vector<uint8_t> cl;
389         cl.push_back(0xAA);
390         cl.push_back(addr);
391         cl.push_back(0x00);
392         Communicate(&cl,3,10-addr);
393         if (owi->log->last()>=OWLOG_WARNING) {
394                 return;
395         }
396         if (!owi->testCRC16(cl)) {
397                 owi->log->set(OWLOG_ERROR,"CRC ERROR Reading Memory of DS2450");
398                 return;
399         }
400         sp->clear();
401         sp->insert(sp->begin(),cl.begin()+3,cl.end()-2);
402 }
403
404 void owDeviceDS2450::writeMemory(uint8_t addr,std::vector<uint8_t> *sp) {
405         std::vector<uint8_t> cl;
406         cl.push_back(0x55);
407         cl.push_back(addr);
408         cl.push_back(0x00);
409         owi->MatchRom(snum);
410         if (owi->log->last()>=OWLOG_WARNING) {
411                 return;
412         }
413         for(uint8_t b: (*sp)) {
414                 cl.push_back(b);
415                 owi->Communicate(&cl,cl.size(),2);
416                 if (owi->log->last()>=OWLOG_WARNING) {
417                         return;
418                 }
419                 if (!owi->testCRC16(cl)) {
420                         owi->log->set(OWLOG_ERROR,"CRC ERROR Writing Memory of DS2450");
421                         return;
422                 }
423                 cl.clear();
424                 owi->Communicate(&cl, 0, 1);
425                 if (owi->log->last()>=OWLOG_WARNING) {
426                         return;
427                 }
428                 if (cl[0] != b) {
429                         owi->log->set(OWLOG_ERROR,"ERROR Writing Memory of DS2450");
430                         return;
431                 }
432                 cl.clear();
433         }
434 }
435         
436 void owDeviceDS2450::convert(uint8_t mask, uint8_t preset) {
437         std::vector<uint8_t> cl;
438         cl.push_back(0x3C);
439         cl.push_back(mask);
440         cl.push_back(preset);
441         Communicate(&cl, 3, 2);
442         if (!owi->testCRC16(cl)) {
443                 owi->log->set(OWLOG_ERROR,"CRC ERROR Convert Command of DS2450");
444                 return;
445         }
446         usleep(10000);
447 }
448
449
450
451
452
453
454
455
456
457
458
459 void owDeviceDS2423::setDefaultConfig() {
460         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});
461         configstate=OWDCS_DEFAULT;
462 }
463
464 int owDeviceDS2423::convertAll() {
465         for(uint8_t i=12;i<16;i++) {
466                 raw[i-12]=readCounter(i);
467         }
468         for(int i=0;i<4;i++) {
469                 values[i]=config->calculateValue(i, raw);
470         }
471         return 1;
472 }
473 uint32_t owDeviceDS2423::readCounter(uint8_t page) {
474         std::vector<uint8_t> cl;
475         cl.push_back(0xA5);
476         uint16_t addr=(page<<5)+31;
477         cl.push_back(addr&0xFF);
478         cl.push_back(addr>>8);
479         Communicate(&cl,3,11);
480         //for (uint8_t v :cl) printf("%02X ",v);
481         //printf("\n");
482         if (!owi->testCRC16(cl)) {
483                 owi->log->set(OWLOG_ERROR,"CRC ERROR Reading Counter of DS2423");
484                 return 0;
485         }
486         uint32_t ret=0;
487          
488         for(size_t i=cl.size()-8;i>cl.size()-11;i--) {
489                 ret<<=8;
490                 ret|=cl[i];
491                 
492         }
493                 
494         return ret;
495 }
496
497
498
499
500
501
502