1 // Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
34 #include "owInterface.h"
39 static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
40 static unsigned char owi_dscrc_table[] = {
41 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
42 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
43 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
44 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
45 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
46 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
47 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
48 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
49 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
50 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
51 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
52 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
53 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
54 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
55 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
56 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
59 uint8_t owInterface::docrc8(uint8_t value) {
60 // See Application Note 27
63 crc8 = owi_dscrc_table[crc8 ^ value];
67 uint16_t owInterface::docrc16(uint16_t cdata) {
68 cdata = (cdata ^ (crc16 & 0xff)) & 0xff;
71 if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4])
84 uint8_t owInterface::calcCRC8(std::vector<uint8_t> data) {
88 return crc8; //0 bei erfolg oder crc wenn crc nicht babei
91 uint16_t owInterface::calcCRC16(std::vector<uint8_t> data) {
99 int owInterface::testCRC16(std::vector<uint8_t> data) {
100 return calcCRC16(data)==0xB001;
103 void owInterface::resetFlasher() { // go back from Bootloader
104 std::vector<uint8_t> data;
105 data.push_back(0x89);
108 snum.num=0xfa55aa55aa55aaa3;
110 if (log->last()==OWLOG_ERROR) {Free(); return;}
111 Communicate(&data, 1, 0);
114 if (log->last()==OWLOG_ERROR) return;
118 void owInterface::resetID() {
119 std::vector<uint8_t> data;
120 data.push_back(0x8B);
123 snum.num=0xfa55aa55aa55aaa3;
125 if (log->last()==OWLOG_ERROR) {Free(); return;}
126 Communicate(&data, 1, 0);
130 int owInterface::programmPage(int pagenr, std::vector<uint8_t> page, int pagesize) {
132 snum.num=0xfa55aa55aa55aaa3;
133 // printf("programm page %i",pagenr);
136 int diff = pagesize - page.size();
138 for (int i = 0; i < (diff); i++) page.push_back(0xFF);
140 std::vector<uint8_t> cl;
141 std::vector<uint8_t> clb; //backup
142 cl.push_back(0x0F); //code for Flashing
143 cl.push_back((pagenr*pagesize) & 0xFF); //adress in byte
144 cl.push_back((pagenr*pagesize) >> 8);
145 cl.insert(cl.end(),page.begin(),page.end()); //page
146 clb=cl; //make backup
149 if (log->last()==OWLOG_ERROR) {Free();return -3;}
150 Communicate(&cl, 3+pagesize, 0); //send (resive page)
152 if (log->last()==OWLOG_ERROR) return -3;
154 for(int k=0;k<maxrepeat;k++) { //repeat for readback error
156 cl.push_back(0xAA); //code for readback scratchpad
159 if (log->last()==OWLOG_ERROR) {Free();return -3;}
160 Communicate(&cl, 1, 2+pagesize); // read back scratchpad
162 if (log->last()==OWLOG_ERROR) return -3;
164 for (int i = 0; i < pagesize+2; i++) {
165 if (clb[i + 1] != cl[i + 1]) { //test
175 return -1; //error in scratchpad
178 cl.push_back(0x55);//Programm
181 if (log->last()==OWLOG_ERROR) {Free();return -3;}
182 Communicate(&cl, 1, 0);
184 if (log->last()==OWLOG_ERROR) return -3;
187 cl.push_back(0xB8);//recal programm memory to scratchpad
188 cl.push_back((pagenr*pagesize) & 0xFF);
189 cl.push_back((pagenr*pagesize) >> 8);
192 if (log->last()==OWLOG_ERROR) {Free();return -3;}
193 Communicate(&cl, 3, 0); //Copy programm memory to scratch
195 if (log->last()==OWLOG_ERROR) return -3;
198 for(int k=0;k<maxrepeat;k++) { //repead for reading scratch error
203 if (log->last()==OWLOG_ERROR) {Free();return -3;}
204 Communicate(&cl, 1, 2 + pagesize); //Reread scratch
206 if (log->last()==OWLOG_ERROR) return -3;
208 for (int i = 0; i < pagesize + 2; i++) {
209 if (cl[i + 1] != clb[i + 1]) {
227 int owInterface::flashHEXFile(std::string filename,snum_t dev,int resetid,int progress) {
228 log->set(OWLOG_INFO,"Open Hex-File: %s",filename.c_str());
229 hexFile *hf=new hexFile(filename);
230 if (hf->lastError==1) {log->set(OWLOG_ERROR,"CRC Error in HEX-File %s",filename.c_str());return -1;}
231 if (hf->lastError==2) {log->set(OWLOG_ERROR,"Error interpreting HEX-File %s",filename.c_str());return -2;}
232 if (hf->lastError==3) {log->set(OWLOG_ERROR,"File could not be opened: %s",filename.c_str());return -3;}
233 unsigned int blcount=hf->getBlockCount(64);
235 log->set(OWLOG_ERROR,"Code to big, max 7552 Byte allowed (118 Pages). Code has %i pages!",blcount);
238 log->set(OWLOG_INFO,"Try to start Bootloader on device %llX",dev.num);
243 std::vector<uint8_t> data;
245 data.push_back(0x88);
246 Communicate(&data, 1, 0);
248 Communicate(&data, 1, 0);
250 Communicate(&data, 1, 0);
252 log->set(OWLOG_INFO,"Search for Bootloader...");
253 log->setLogLevel(OWLOG_WARNING);
255 log->setLogLevel(OWLOG_INFO);
257 for (owDevice* dev :devices) {
258 if (dev->getNum().num==0xfa55aa55aa55aaa3) {
263 if (found==0) log->set(OWLOG_WARNING,"Bootloader not found");
265 } while ((found==0)&&(r>0));
267 log->set(OWLOG_ERROR,"Can not start Bootloader on this device %llX",dev.num);
270 log->set(OWLOG_INFO,"Start Programm %i Pages",blcount);
274 for ( i= 0; i < blcount; i++) {
275 std::vector<uint8_t> blk = hf->getBlock(i*64, 64);
276 int errc = maxrepeat*5;
279 if (programmPage(i, blk, 64) >= 0) {
280 if (progress) {printf("#");fflush(stdout);}
286 if (progress) {printf("\033[1;31m#\033[0m");fflush(stdout);} //printf("\033[1;33m%s\033[0m\n",s);
289 if (errc == 0) { er++; break; }
291 if (progress) printf("\n");
293 log->set(OWLOG_ERROR,"ERROR Writing Program Memory!!!");
295 log->set(OWLOG_ERROR,"If Fuse SELFPRGEN enabled?");
297 log->set(OWLOG_ERROR,"Maybe 1-Wire Connection is verry bad!");
300 log->set(OWLOG_INFO,"Set 1-Wire ID to ID in hexfile...",blcount);
308 log->set(OWLOG_INFO,"Back from bootloader to normal device...",blcount);
323 int owInterface::owSearch() {
325 int last_zero, rom_byte_number, search_result;
326 int id_bit, cmp_id_bit;
327 unsigned char rom_byte_mask, search_direction;
329 // initialize for search
337 // if the last call was not the last one
338 if (!LastDeviceFlag) {
344 LastDeviceFlag = FALSE;
345 LastFamilyDiscrepancy = 0;
349 if (log->last()==OWLOG_ERROR) return -3;
350 // issue the search command
352 if (log->last()==OWLOG_ERROR) return -3;
354 // loop to do the search
356 // read a bit and its complement
357 id_bit = sendrecivBit(1);
358 cmp_id_bit = sendrecivBit(1);
359 // check for no devices on 1-wire
360 if ((id_bit == 1) && (cmp_id_bit == 1))
363 // all devices coupled have 0 or 1
364 if (id_bit != cmp_id_bit)
365 search_direction = id_bit; // bit write value for search
367 // if this discrepancy if before the Last Discrepancy
368 // on a previous next then pick the same as last time
369 if (id_bit_number < LastDiscrepancy)
370 search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
372 // if equal to last pick 1, if not then pick 0
373 search_direction = (id_bit_number == LastDiscrepancy);
375 // if 0 was picked then record its position in LastZero
376 if (search_direction == 0) {
377 last_zero = id_bit_number;
378 // check for Last discrepancy in family
380 LastFamilyDiscrepancy = last_zero;
383 // set or clear the bit in the ROM byte rom_byte_number
384 // with mask rom_byte_mask
385 if (search_direction == 1)
386 ROM_NO[rom_byte_number] |= rom_byte_mask;
388 ROM_NO[rom_byte_number] &= ~rom_byte_mask;
389 // serial number search direction write bit
390 sendrecivBit(search_direction);
393 // increment the byte counter id_bit_number
394 // and shift the mask rom_byte_mask
398 // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
399 if (rom_byte_mask == 0) {
400 docrc8(ROM_NO[rom_byte_number]); // accumulate the CRC
406 while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
407 // if the search was successful then
408 if (!((id_bit_number < 65) || (crc8 != 0))) {
409 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
410 LastDiscrepancy = last_zero;
411 // check for last device
412 if (LastDiscrepancy == 0)
413 LastDeviceFlag = TRUE;
414 search_result = TRUE;
416 log->set(OWLOG_WARNING,"CRC Error on Search Rom");
420 // if no device found then reset counters so next 'search' will be like a first
421 if (!search_result || !ROM_NO[0]) {
423 LastDeviceFlag = FALSE;
424 LastFamilyDiscrepancy = 0;
425 search_result = FALSE;
428 return search_result;
432 void owInterface::Clean() {
433 for (owDevice* dev :devices) {
441 int owInterface::Find() {
443 std::vector<snum_t> found;
444 for (int k=0;k<maxrepeat;k++) {
449 if (log->last()>=OWLOG_WARNING) continue;
452 // print device found
453 for (i = 7; i >= 0; i--)
454 snum.byte[i]=ROM_NO[i];
455 //printf("%02X", ROM_NO[i]);
456 //printf(" %d\n",++cnt);
457 found.push_back(snum);
461 if (log->last()>=OWLOG_WARNING) {rslt=-1;break;}
466 if (log->last()>=OWLOG_WARNING) {
467 log->set(OWLOG_ERROR,"To much Errors while search rom");
468 //Alles so lassen wie es ist?
471 for(snum_t snum:found) {
473 //Device schon forhanden?
474 for(snum_t d : device_nums) {
475 if (snum.num==d.num) {snum_found=1;break;}
477 //nein, dann anlegen.
479 log->set(OWLOG_INFO,"new dev %llx\n",snum.num);
481 device_nums.push_back(snum);
484 switch (snum.byte[0]) {
485 case 0x28:d=new owDeviceDS18B20(this,snum);break;
486 case 0x26:d=new owDeviceDS2438(this,snum);break;
487 case 0x20:d=new owDeviceDS2450(this,snum);break;
488 case 0x1D:d=new owDeviceDS2423(this,snum);break;
489 default:d=new owDevice(this,snum);
491 devices.push_back(d);
492 if (d!=NULL) {d->readConfig();}
495 //Pruefe nach nicht mehr vorhandenen devices
497 for(snum_t d:device_nums) {
499 for(snum_t fd:found) {
500 if (fd.num==d.num) {snum_found=1;break;}
502 //Device nicht gefunden, vieleicht nur Fehler?
504 devices[dpos]->lastfound++;
505 log->set(OWLOG_INFO,"%llx not found %i times \n",device_nums[dpos].num,devices[dpos]->lastfound);
507 if (devices[dpos]->lastfound>2) {
509 log->set(OWLOG_INFO,"del device %llx (pos %i)\n",device_nums[dpos].num,dpos);
512 delete devices[dpos];
513 device_nums.erase(device_nums.begin()+dpos);
514 devices.erase(devices.begin()+dpos);
515 //printf("new length %i\n",devices.size());
520 devices[dpos]->lastfound=0;
528 int owInterface::MatchRom(snum_t snum) {
532 for(int i=0;i<8;i++) {
533 sendrecivByte(snum.byte[i]);
536 if (log->last()>OWLOG_WARNING) return 0;
539 int owInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
541 data->resize(scount);
542 for(uint8_t v:*data) {
543 (*data)[i]=sendrecivByte(v);i++;
546 for(i=0;i<rcount;i++) {
547 data->push_back(sendrecivByte(0xFF));