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
41 uint8_t owCC_44_Temp=0;
\r
44 void usleep(__int64 usec)
\r
49 ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time
\r
51 timer = CreateWaitableTimer(NULL, TRUE, NULL);
\r
52 SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
\r
53 WaitForSingleObject(timer, INFINITE);
\r
59 static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
\r
60 static unsigned char owi_dscrc_table[] = {
\r
61 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
\r
62 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
\r
63 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
\r
64 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
\r
65 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
\r
66 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
\r
67 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
\r
68 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
\r
69 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
\r
70 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
\r
71 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
\r
72 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
\r
73 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
\r
74 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
\r
75 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
\r
76 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
\r
79 uint8_t owInterface::docrc8(uint8_t value) {
\r
80 // See Application Note 27
\r
83 crc8 = owi_dscrc_table[crc8 ^ value];
\r
87 uint16_t owInterface::docrc16(uint16_t cdata) {
\r
88 cdata = (cdata ^ (crc16 & 0xff)) & 0xff;
\r
91 if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4])
\r
104 uint8_t owInterface::calcCRC8(std::vector<uint8_t> data) {
\r
106 for(uint8_t v: data)
\r
108 return crc8; //0 bei erfolg oder crc wenn crc nicht babei
\r
111 uint16_t owInterface::calcCRC16(std::vector<uint8_t> data) {
\r
113 for(uint8_t v:data) {
\r
119 int owInterface::testCRC16(std::vector<uint8_t> data) {
\r
120 return calcCRC16(data)==0xB001;
\r
123 int owInterface::testCRC16(std::vector<uint8_t> data,uint16_t load) {
\r
125 for(uint8_t v:data) {
\r
128 return crc16==0xB001;
\r
133 void owInterface::resetFlasher(uint64_t id) { // go back from Bootloader
\r
134 std::vector<uint8_t> data;
\r
135 data.push_back(0x89);
\r
140 if (log->last()==OWLOG_ERROR) {Free(); return;}
\r
141 Communicate(&data, 1, 0);
\r
144 if (log->last()==OWLOG_ERROR) return;
\r
148 void owInterface::resetID(uint64_t id) {
\r
149 std::vector<uint8_t> data;
\r
150 data.push_back(0x8B);
\r
155 if (log->last()==OWLOG_ERROR) {Free(); return;}
\r
156 Communicate(&data, 1, 0);
\r
160 int owInterface::programmPage(uint64_t id,int pagenr, std::vector<uint8_t> page, int pagesize) {
\r
163 // printf("programm page %i",pagenr);
\r
166 int diff = pagesize - page.size();
\r
168 for (int i = 0; i < (diff); i++) page.push_back(0xFF);
\r
170 std::vector<uint8_t> cl;
\r
171 std::vector<uint8_t> clb; //backup
\r
172 cl.push_back(0x0F); //code for Flashing
\r
173 cl.push_back((pagenr*pagesize) & 0xFF); //adress in byte
\r
174 cl.push_back((pagenr*pagesize) >> 8);
\r
175 cl.insert(cl.end(),page.begin(),page.end()); //page
\r
176 clb=cl; //make backup
\r
179 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
180 Communicate(&cl, 3+pagesize, 0); //send (resive page)
\r
182 if (log->last()==OWLOG_ERROR) return -3;
\r
184 for(int k=0;k<maxrepeat;k++) { //repeat for readback error
\r
186 cl.push_back(0xAA); //code for readback scratchpad
\r
189 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
190 Communicate(&cl, 1, 2+pagesize); // read back scratchpad
\r
192 if (log->last()==OWLOG_ERROR) return -3;
\r
194 for (int i = 0; i < pagesize+2; i++) {
\r
195 if (clb[i + 1] != cl[i + 1]) { //test
\r
205 return -1; //error in scratchpad
\r
208 cl.push_back(0x55);//Programm
\r
211 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
212 Communicate(&cl, 1, 0);
\r
214 if (log->last()==OWLOG_ERROR) return -3;
\r
217 cl.push_back(0xB8);//recal programm memory to scratchpad
\r
218 cl.push_back((pagenr*pagesize) & 0xFF);
\r
219 cl.push_back((pagenr*pagesize) >> 8);
\r
222 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
223 Communicate(&cl, 3, 0); //Copy programm memory to scratch
\r
225 if (log->last()==OWLOG_ERROR) return -3;
\r
228 for(int k=0;k<maxrepeat;k++) { //repead for reading scratch error
\r
230 cl.push_back(0xAA);
\r
233 if (log->last()==OWLOG_ERROR) {Free();return -3;}
\r
234 Communicate(&cl, 1, 2 + pagesize); //Reread scratch
\r
236 if (log->last()==OWLOG_ERROR) return -3;
\r
238 for (int i = 0; i < pagesize + 2; i++) {
\r
239 if (cl[i + 1] != clb[i + 1]) {
\r
257 int owInterface::flashHEXFile(std::string filename,snum_t dev,int resetid,int progress) {
\r
258 log->set(OWLOG_INFO,"Open Hex-File: %s",filename.c_str());
\r
259 hexFile *hf=new hexFile(filename);
\r
260 if (hf->lastError==1) {log->set(OWLOG_ERROR,"CRC Error in HEX-File %s",filename.c_str());return -1;}
\r
261 if (hf->lastError==2) {log->set(OWLOG_ERROR,"Error interpreting HEX-File %s",filename.c_str());return -2;}
\r
262 if (hf->lastError==3) {log->set(OWLOG_ERROR,"File could not be opened: %s",filename.c_str());return -3;}
\r
264 log->set(OWLOG_INFO,"Try to start Bootloader on device %llX",dev.num);
\r
269 std::vector<uint8_t> data;
\r
271 data.push_back(0x88);
\r
272 Communicate(&data, 1, 0);
\r
274 Communicate(&data, 1, 0);
\r
276 Communicate(&data, 1, 0);
\r
283 log->set(OWLOG_INFO,"Search for Bootloader...");
\r
284 log->setLogLevel(OWLOG_WARNING);
\r
286 log->setLogLevel(OWLOG_INFO);
\r
288 for (owDevice* dev :devices) {
\r
289 if (dev->getNum().num==0xfa55aa55aa55aaa3) {
\r
293 if (dev->getNum().num==0x8A57AA57AA57AAA3) {
\r
298 if (found==0) log->set(OWLOG_WARNING,"Bootloader not found");
\r
300 } while ((found==0)&&(r>0));
\r
302 log->set(OWLOG_ERROR,"Can not start Bootloader on this device %llX",dev.num);
\r
306 unsigned int blcount=0;
\r
312 log->set(OWLOG_INFO,"Bootloader on ATtiny84A found. Pagesize = 64 bytes");
\r
314 blcount=hf->getBlockCount(64);
\r
315 id=0xfa55aa55aa55aaa3;
\r
317 log->set(OWLOG_ERROR,"Code to big, max 7552 Byte allowed (118 Pages). Code has %i pages!",blcount);
\r
322 log->set(OWLOG_INFO,"Bootloader on ATmega328PB found. Pagesize = 128 bytes");
\r
324 blcount=hf->getBlockCount(128);
\r
325 id=0x8A57AA57AA57AAA3;
\r
327 log->set(OWLOG_ERROR,"Code to big, max 31744 Byte allowed (248 Pages). Code has %i pages!",blcount);
\r
332 log->set(OWLOG_INFO,"Start Programm %i Pages",blcount);
\r
336 for ( i= 0; i < blcount; i++) {
\r
337 std::vector<uint8_t> blk = hf->getBlock(i*blsize, blsize);
\r
338 int errc = maxrepeat*5;
\r
339 while (errc != 0) {
\r
341 if (programmPage(id,i, blk,blsize) >= 0) {
\r
342 if (progress) {printf("#");fflush(stdout);}
\r
348 if (progress) {printf("\033[1;31m#\033[0m");fflush(stdout);} //printf("\033[1;33m%s\033[0m\n",s);
\r
351 if (errc == 0) { er++; break; }
\r
353 if (progress) printf("\n");
\r
355 log->set(OWLOG_ERROR,"ERROR Writing Program Memory!!!");
\r
357 log->set(OWLOG_ERROR,"If Fuse SELFPRGEN enabled?");
\r
359 log->set(OWLOG_ERROR,"Maybe 1-Wire Connection is verry bad!");
\r
362 log->set(OWLOG_INFO,"Set 1-Wire ID to ID in hexfile...",blcount);
\r
380 log->set(OWLOG_INFO,"Back from bootloader to normal device...",blcount);
\r
405 int owInterface::owSearch() {
\r
407 int last_zero, rom_byte_number, search_result;
\r
408 int id_bit, cmp_id_bit;
\r
409 unsigned char rom_byte_mask, search_direction;
\r
411 // initialize for search
\r
414 rom_byte_number = 0;
\r
419 // if the last call was not the last one
\r
420 if (!LastDeviceFlag) {
\r
424 // reset the search
\r
425 LastDiscrepancy = 0;
\r
426 LastDeviceFlag = FALSE;
\r
427 LastFamilyDiscrepancy = 0;
\r
431 if (log->last()==OWLOG_ERROR) return -3;
\r
432 // issue the search command
\r
433 sendrecivByte(0xF0);
\r
434 if (log->last()==OWLOG_ERROR) return -3;
\r
436 // loop to do the search
\r
438 // read a bit and its complement
\r
439 id_bit = sendrecivBit(1);
\r
440 cmp_id_bit = sendrecivBit(1);
\r
441 // check for no devices on 1-wire
\r
442 if ((id_bit == 1) && (cmp_id_bit == 1))
\r
445 // all devices coupled have 0 or 1
\r
446 if (id_bit != cmp_id_bit)
\r
447 search_direction = id_bit; // bit write value for search
\r
449 // if this discrepancy if before the Last Discrepancy
\r
450 // on a previous next then pick the same as last time
\r
451 if (id_bit_number < LastDiscrepancy)
\r
452 search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
\r
454 // if equal to last pick 1, if not then pick 0
\r
455 search_direction = (id_bit_number == LastDiscrepancy);
\r
457 // if 0 was picked then record its position in LastZero
\r
458 if (search_direction == 0) {
\r
459 last_zero = id_bit_number;
\r
460 // check for Last discrepancy in family
\r
462 LastFamilyDiscrepancy = last_zero;
\r
465 // set or clear the bit in the ROM byte rom_byte_number
\r
466 // with mask rom_byte_mask
\r
467 if (search_direction == 1)
\r
468 ROM_NO[rom_byte_number] |= rom_byte_mask;
\r
470 ROM_NO[rom_byte_number] &= ~rom_byte_mask;
\r
471 // serial number search direction write bit
\r
472 sendrecivBit(search_direction);
\r
475 // increment the byte counter id_bit_number
\r
476 // and shift the mask rom_byte_mask
\r
478 rom_byte_mask <<= 1;
\r
480 // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
\r
481 if (rom_byte_mask == 0) {
\r
482 docrc8(ROM_NO[rom_byte_number]); // accumulate the CRC
\r
488 while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
\r
489 // if the search was successful then
\r
490 if (!((id_bit_number < 65) || (crc8 != 0))) {
\r
491 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
\r
492 LastDiscrepancy = last_zero;
\r
493 // check for last device
\r
494 if (LastDiscrepancy == 0)
\r
495 LastDeviceFlag = TRUE;
\r
496 search_result = TRUE;
\r
498 log->set(OWLOG_WARNING,"CRC Error on Search Rom");
\r
502 // if no device found then reset counters so next 'search' will be like a first
\r
503 if (!search_result || !ROM_NO[0]) {
\r
504 LastDiscrepancy = 0;
\r
505 LastDeviceFlag = FALSE;
\r
506 LastFamilyDiscrepancy = 0;
\r
507 search_result = FALSE;
\r
510 return search_result;
\r
514 void owInterface::Clean() {
\r
515 for (owDevice* dev :devices) {
\r
519 device_nums.clear();
\r
523 int owInterface::Find() {
\r
525 std::vector<snum_t> found;
\r
526 for (int k=0;k<maxrepeat;k++) {
\r
531 if (log->last()>=OWLOG_WARNING) continue;
\r
534 // print device found
\r
535 for (i = 7; i >= 0; i--)
\r
536 snum.byte[i]=ROM_NO[i];
\r
537 //printf("%02X", ROM_NO[i]);
\r
538 //printf(" %d\n",++cnt);
\r
539 found.push_back(snum);
\r
543 if (log->last()>=OWLOG_WARNING) {rslt=-1;break;}
\r
545 if (rslt==0) break;
\r
548 if (log->last()>=OWLOG_WARNING) {
\r
549 log->set(OWLOG_ERROR,"To much Errors while search rom");
\r
550 //Alles so lassen wie es ist?
\r
553 for(snum_t snum:found) {
\r
555 //Device schon forhanden?
\r
556 for(snum_t d : device_nums) {
\r
557 if (snum.num==d.num) {snum_found=1;break;}
\r
559 //nein, dann anlegen.
\r
561 log->set(OWLOG_INFO,"new dev %llx\n",snum.num);
\r
563 device_nums.push_back(snum);
\r
566 switch (snum.byte[0]) {
\r
567 case 0x28:d=new owDeviceDS18B20(this,snum);break;
\r
568 case 0x26:d=new owDeviceDS2438(this,snum);break;
\r
569 case 0x20:d=new owDeviceDS2450(this,snum);break;
\r
570 case 0x1D:d=new owDeviceDS2423(this,snum);break;
\r
571 case 0x29:d=new owDeviceDS2408(this,snum);break;
\r
572 default:d=new owDevice(this,snum);
\r
574 devices.push_back(d);
\r
575 if (d!=NULL) {d->readConfig();}
\r
578 //Pruefe nach nicht mehr vorhandenen devices
\r
580 for(snum_t d:device_nums) {
\r
582 for(snum_t fd:found) {
\r
583 if (fd.num==d.num) {snum_found=1;break;}
\r
585 //Device nicht gefunden, vieleicht nur Fehler?
\r
587 devices[dpos]->lastfound++;
\r
588 log->set(OWLOG_INFO,"%llx not found %i times \n",device_nums[dpos].num,devices[dpos]->lastfound);
\r
590 if (devices[dpos]->lastfound>2) {
\r
592 log->set(OWLOG_INFO,"del device %llx (pos %i)\n",device_nums[dpos].num,dpos);
\r
595 delete devices[dpos];
\r
596 device_nums.erase(device_nums.begin()+dpos);
\r
597 devices.erase(devices.begin()+dpos);
\r
598 //printf("new length %i\n",devices.size());
\r
603 devices[dpos]->lastfound=0;
\r
611 int owInterface::MatchRom(snum_t snum) {
\r
613 /* sendrecivByte(0x55);
\r
615 for(int i=0;i<8;i++) {
\r
616 sendrecivByte(snum.byte[i]);
\r
619 if (log->last()>OWLOG_WARNING) return 0;*/
\r
620 std::vector<uint8_t> cl;
\r
621 cl.push_back(0x55); //code for Flashing
\r
622 for (int i = 0; i<8; i++) {
\r
623 cl.push_back(snum.byte[i]);
\r
625 Communicate(&cl, 9, 0);
\r
629 int owInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
\r
631 data->resize(scount);
\r
632 for(uint8_t v:*data) {
\r
633 (*data)[i]=sendrecivByte(v);i++;
\r
636 for(i=0;i<rcount;i++) {
\r
637 data->push_back(sendrecivByte(0xFF));
\r