1 // Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
\r
2 // All rights reserved.
\r
4 // Redistribution and use in source and binary forms, with or without
\r
5 // modification, are permitted provided that the following conditions are
\r
8 // * Redistributions of source code must retain the above copyright
\r
9 // notice, this list of conditions and the following disclaimer.
\r
10 // * Redistributions in binary form must reproduce the above copyright
\r
11 // notice, this list of conditions and the following disclaimer in the
\r
12 // documentation and/or other materials provided with the
\r
14 // * All advertising materials mentioning features or use of this
\r
15 // software must display the following acknowledgement: This product
\r
16 // includes software developed by tm3d.de and its contributors.
\r
17 // * Neither the name of tm3d.de nor the names of its contributors may
\r
18 // be used to endorse or promote products derived from this software
\r
19 // without specific prior written permission.
\r
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
\r
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
\r
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
\r
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
\r
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
34 #include "owInterface.h"
\r
39 #include "hexfile.h"
\r
43 void usleep(__int64 usec)
\r
48 ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time
\r
50 timer = CreateWaitableTimer(NULL, TRUE, NULL);
\r
51 SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
\r
52 WaitForSingleObject(timer, INFINITE);
\r
58 static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
\r
59 static unsigned char owi_dscrc_table[] = {
\r
60 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
\r
61 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
\r
62 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
\r
63 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
\r
64 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
\r
65 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
\r
66 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
\r
67 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
\r
68 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
\r
69 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
\r
70 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
\r
71 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
\r
72 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
\r
73 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
\r
74 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
\r
75 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
\r
78 uint8_t owInterface::docrc8(uint8_t value) {
\r
79 // See Application Note 27
\r
82 crc8 = owi_dscrc_table[crc8 ^ value];
\r
86 uint16_t owInterface::docrc16(uint16_t cdata) {
\r
87 cdata = (cdata ^ (crc16 & 0xff)) & 0xff;
\r
90 if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4])
\r
103 uint8_t owInterface::calcCRC8(std::vector<uint8_t> data) {
\r
105 for(uint8_t v: data)
\r
107 return crc8; //0 bei erfolg oder crc wenn crc nicht babei
\r
110 uint16_t owInterface::calcCRC16(std::vector<uint8_t> data) {
\r
112 for(uint8_t v:data) {
\r
118 int owInterface::testCRC16(std::vector<uint8_t> data) {
\r
119 return calcCRC16(data)==0xB001;
\r
122 void owInterface::resetFlasher() { // go back from Bootloader
\r
123 std::vector<uint8_t> data;
\r
124 data.push_back(0x89);
\r
127 snum.num=0xfa55aa55aa55aaa3;
\r
129 if (log->last()==OWLOG_ERROR) {Free(); return;}
\r
130 Communicate(&data, 1, 0);
\r
133 if (log->last()==OWLOG_ERROR) return;
\r
137 void owInterface::resetID() {
\r
138 std::vector<uint8_t> data;
\r
139 data.push_back(0x8B);
\r
142 snum.num=0xfa55aa55aa55aaa3;
\r
144 if (log->last()==OWLOG_ERROR) {Free(); return;}
\r
145 Communicate(&data, 1, 0);
\r
149 int owInterface::programmPage(int pagenr, std::vector<uint8_t> page, int pagesize) {
\r
151 snum.num=0xfa55aa55aa55aaa3;
\r
152 // printf("programm page %i",pagenr);
\r
155 int diff = pagesize - page.size();
\r
157 for (int i = 0; i < (diff); i++) page.push_back(0xFF);
\r
159 std::vector<uint8_t> cl;
\r
160 std::vector<uint8_t> clb; //backup
\r
161 cl.push_back(0x0F); //code for Flashing
\r
162 cl.push_back((pagenr*pagesize) & 0xFF); //adress in byte
\r
163 cl.push_back((pagenr*pagesize) >> 8);
\r
164 cl.insert(cl.end(),page.begin(),page.end()); //page
\r
165 clb=cl; //make backup
\r
168 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
169 Communicate(&cl, 3+pagesize, 0); //send (resive page)
\r
171 if (log->last()==OWLOG_ERROR) return -3;
\r
173 for(int k=0;k<maxrepeat;k++) { //repeat for readback error
\r
175 cl.push_back(0xAA); //code for readback scratchpad
\r
178 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
179 Communicate(&cl, 1, 2+pagesize); // read back scratchpad
\r
181 if (log->last()==OWLOG_ERROR) return -3;
\r
183 for (int i = 0; i < pagesize+2; i++) {
\r
184 if (clb[i + 1] != cl[i + 1]) { //test
\r
194 return -1; //error in scratchpad
\r
197 cl.push_back(0x55);//Programm
\r
200 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
201 Communicate(&cl, 1, 0);
\r
203 if (log->last()==OWLOG_ERROR) return -3;
\r
206 cl.push_back(0xB8);//recal programm memory to scratchpad
\r
207 cl.push_back((pagenr*pagesize) & 0xFF);
\r
208 cl.push_back((pagenr*pagesize) >> 8);
\r
211 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
212 Communicate(&cl, 3, 0); //Copy programm memory to scratch
\r
214 if (log->last()==OWLOG_ERROR) return -3;
\r
217 for(int k=0;k<maxrepeat;k++) { //repead for reading scratch error
\r
219 cl.push_back(0xAA);
\r
222 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
223 Communicate(&cl, 1, 2 + pagesize); //Reread scratch
\r
225 if (log->last()==OWLOG_ERROR) return -3;
\r
227 for (int i = 0; i < pagesize + 2; i++) {
\r
228 if (cl[i + 1] != clb[i + 1]) {
\r
246 int owInterface::flashHEXFile(std::string filename,snum_t dev,int resetid,int progress) {
\r
247 log->set(OWLOG_INFO,"Open Hex-File: %s",filename.c_str());
\r
248 hexFile *hf=new hexFile(filename);
\r
249 if (hf->lastError==1) {log->set(OWLOG_ERROR,"CRC Error in HEX-File %s",filename.c_str());return -1;}
\r
250 if (hf->lastError==2) {log->set(OWLOG_ERROR,"Error interpreting HEX-File %s",filename.c_str());return -2;}
\r
251 if (hf->lastError==3) {log->set(OWLOG_ERROR,"File could not be opened: %s",filename.c_str());return -3;}
\r
252 unsigned int blcount=hf->getBlockCount(64);
\r
254 log->set(OWLOG_ERROR,"Code to big, max 7552 Byte allowed (118 Pages). Code has %i pages!",blcount);
\r
257 log->set(OWLOG_INFO,"Try to start Bootloader on device %llX",dev.num);
\r
262 std::vector<uint8_t> data;
\r
264 data.push_back(0x88);
\r
265 Communicate(&data, 1, 0);
\r
267 Communicate(&data, 1, 0);
\r
269 Communicate(&data, 1, 0);
\r
276 log->set(OWLOG_INFO,"Search for Bootloader...");
\r
277 log->setLogLevel(OWLOG_WARNING);
\r
279 log->setLogLevel(OWLOG_INFO);
\r
281 for (owDevice* dev :devices) {
\r
282 if (dev->getNum().num==0xfa55aa55aa55aaa3) {
\r
287 if (found==0) log->set(OWLOG_WARNING,"Bootloader not found");
\r
289 } while ((found==0)&&(r>0));
\r
291 log->set(OWLOG_ERROR,"Can not start Bootloader on this device %llX",dev.num);
\r
294 log->set(OWLOG_INFO,"Start Programm %i Pages",blcount);
\r
298 for ( i= 0; i < blcount; i++) {
\r
299 std::vector<uint8_t> blk = hf->getBlock(i*64, 64);
\r
300 int errc = maxrepeat*5;
\r
301 while (errc != 0) {
\r
303 if (programmPage(i, blk, 64) >= 0) {
\r
304 if (progress) {printf("#");fflush(stdout);}
\r
310 if (progress) {printf("\033[1;31m#\033[0m");fflush(stdout);} //printf("\033[1;33m%s\033[0m\n",s);
\r
313 if (errc == 0) { er++; break; }
\r
315 if (progress) printf("\n");
\r
317 log->set(OWLOG_ERROR,"ERROR Writing Program Memory!!!");
\r
319 log->set(OWLOG_ERROR,"If Fuse SELFPRGEN enabled?");
\r
321 log->set(OWLOG_ERROR,"Maybe 1-Wire Connection is verry bad!");
\r
324 log->set(OWLOG_INFO,"Set 1-Wire ID to ID in hexfile...",blcount);
\r
342 log->set(OWLOG_INFO,"Back from bootloader to normal device...",blcount);
\r
367 int owInterface::owSearch() {
\r
369 int last_zero, rom_byte_number, search_result;
\r
370 int id_bit, cmp_id_bit;
\r
371 unsigned char rom_byte_mask, search_direction;
\r
373 // initialize for search
\r
376 rom_byte_number = 0;
\r
381 // if the last call was not the last one
\r
382 if (!LastDeviceFlag) {
\r
386 // reset the search
\r
387 LastDiscrepancy = 0;
\r
388 LastDeviceFlag = FALSE;
\r
389 LastFamilyDiscrepancy = 0;
\r
393 if (log->last()==OWLOG_ERROR) return -3;
\r
394 // issue the search command
\r
395 sendrecivByte(0xF0);
\r
396 if (log->last()==OWLOG_ERROR) return -3;
\r
398 // loop to do the search
\r
400 // read a bit and its complement
\r
401 id_bit = sendrecivBit(1);
\r
402 cmp_id_bit = sendrecivBit(1);
\r
403 // check for no devices on 1-wire
\r
404 if ((id_bit == 1) && (cmp_id_bit == 1))
\r
407 // all devices coupled have 0 or 1
\r
408 if (id_bit != cmp_id_bit)
\r
409 search_direction = id_bit; // bit write value for search
\r
411 // if this discrepancy if before the Last Discrepancy
\r
412 // on a previous next then pick the same as last time
\r
413 if (id_bit_number < LastDiscrepancy)
\r
414 search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
\r
416 // if equal to last pick 1, if not then pick 0
\r
417 search_direction = (id_bit_number == LastDiscrepancy);
\r
419 // if 0 was picked then record its position in LastZero
\r
420 if (search_direction == 0) {
\r
421 last_zero = id_bit_number;
\r
422 // check for Last discrepancy in family
\r
424 LastFamilyDiscrepancy = last_zero;
\r
427 // set or clear the bit in the ROM byte rom_byte_number
\r
428 // with mask rom_byte_mask
\r
429 if (search_direction == 1)
\r
430 ROM_NO[rom_byte_number] |= rom_byte_mask;
\r
432 ROM_NO[rom_byte_number] &= ~rom_byte_mask;
\r
433 // serial number search direction write bit
\r
434 sendrecivBit(search_direction);
\r
437 // increment the byte counter id_bit_number
\r
438 // and shift the mask rom_byte_mask
\r
440 rom_byte_mask <<= 1;
\r
442 // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
\r
443 if (rom_byte_mask == 0) {
\r
444 docrc8(ROM_NO[rom_byte_number]); // accumulate the CRC
\r
450 while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
\r
451 // if the search was successful then
\r
452 if (!((id_bit_number < 65) || (crc8 != 0))) {
\r
453 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
\r
454 LastDiscrepancy = last_zero;
\r
455 // check for last device
\r
456 if (LastDiscrepancy == 0)
\r
457 LastDeviceFlag = TRUE;
\r
458 search_result = TRUE;
\r
460 log->set(OWLOG_WARNING,"CRC Error on Search Rom");
\r
464 // if no device found then reset counters so next 'search' will be like a first
\r
465 if (!search_result || !ROM_NO[0]) {
\r
466 LastDiscrepancy = 0;
\r
467 LastDeviceFlag = FALSE;
\r
468 LastFamilyDiscrepancy = 0;
\r
469 search_result = FALSE;
\r
472 return search_result;
\r
476 void owInterface::Clean() {
\r
477 for (owDevice* dev :devices) {
\r
481 device_nums.clear();
\r
485 int owInterface::Find() {
\r
487 std::vector<snum_t> found;
\r
488 for (int k=0;k<maxrepeat;k++) {
\r
493 if (log->last()>=OWLOG_WARNING) continue;
\r
496 // print device found
\r
497 for (i = 7; i >= 0; i--)
\r
498 snum.byte[i]=ROM_NO[i];
\r
499 //printf("%02X", ROM_NO[i]);
\r
500 //printf(" %d\n",++cnt);
\r
501 found.push_back(snum);
\r
505 if (log->last()>=OWLOG_WARNING) {rslt=-1;break;}
\r
507 if (rslt==0) break;
\r
510 if (log->last()>=OWLOG_WARNING) {
\r
511 log->set(OWLOG_ERROR,"To much Errors while search rom");
\r
512 //Alles so lassen wie es ist?
\r
515 for(snum_t snum:found) {
\r
517 //Device schon forhanden?
\r
518 for(snum_t d : device_nums) {
\r
519 if (snum.num==d.num) {snum_found=1;break;}
\r
521 //nein, dann anlegen.
\r
523 log->set(OWLOG_INFO,"new dev %llx\n",snum.num);
\r
525 device_nums.push_back(snum);
\r
528 switch (snum.byte[0]) {
\r
529 case 0x28:d=new owDeviceDS18B20(this,snum);break;
\r
530 case 0x26:d=new owDeviceDS2438(this,snum);break;
\r
531 case 0x20:d=new owDeviceDS2450(this,snum);break;
\r
532 case 0x1D:d=new owDeviceDS2423(this,snum);break;
\r
533 default:d=new owDevice(this,snum);
\r
535 devices.push_back(d);
\r
536 if (d!=NULL) {d->readConfig();}
\r
539 //Pruefe nach nicht mehr vorhandenen devices
\r
541 for(snum_t d:device_nums) {
\r
543 for(snum_t fd:found) {
\r
544 if (fd.num==d.num) {snum_found=1;break;}
\r
546 //Device nicht gefunden, vieleicht nur Fehler?
\r
548 devices[dpos]->lastfound++;
\r
549 log->set(OWLOG_INFO,"%llx not found %i times \n",device_nums[dpos].num,devices[dpos]->lastfound);
\r
551 if (devices[dpos]->lastfound>2) {
\r
553 log->set(OWLOG_INFO,"del device %llx (pos %i)\n",device_nums[dpos].num,dpos);
\r
556 delete devices[dpos];
\r
557 device_nums.erase(device_nums.begin()+dpos);
\r
558 devices.erase(devices.begin()+dpos);
\r
559 //printf("new length %i\n",devices.size());
\r
564 devices[dpos]->lastfound=0;
\r
572 int owInterface::MatchRom(snum_t snum) {
\r
574 /* sendrecivByte(0x55);
\r
576 for(int i=0;i<8;i++) {
\r
577 sendrecivByte(snum.byte[i]);
\r
580 if (log->last()>OWLOG_WARNING) return 0;*/
\r
581 std::vector<uint8_t> cl;
\r
582 cl.push_back(0x55); //code for Flashing
\r
583 for (int i = 0; i<8; i++) {
\r
584 cl.push_back(snum.byte[i]);
\r
586 Communicate(&cl, 9, 0);
\r
590 int owInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
\r
592 data->resize(scount);
\r
593 for(uint8_t v:*data) {
\r
594 (*data)[i]=sendrecivByte(v);i++;
\r
597 for(i=0;i<rcount;i++) {
\r
598 data->push_back(sendrecivByte(0xFF));
\r