From: Tobias <tm@tm3d.de>
Date: Fri, 31 Mar 2017 07:01:41 +0000 (+0200)
Subject: Works now with Windows Visual Studio C++ too
X-Git-Url: https://git.smho.de/?a=commitdiff_plain;h=1a6465a924428af072a8eb5e75ee547c394f4d8e;p=owTools.git

Works now with Windows Visual Studio C++ too
---

diff --git a/src/hexfile.cpp b/src/hexfile.cpp
index 32ce679..df45d46 100755
--- a/src/hexfile.cpp
+++ b/src/hexfile.cpp
@@ -53,13 +53,13 @@ hexFile::hexFile(std::string fname) {
         if (line[0]==':') {
 			//ss << std::hex << line.substr(1,2);
 			//ss >> bc;
-			uint8_t bc=std::stoul( line.substr(1,2), nullptr, 16);
+			uint8_t bc=(uint8_t)std::stoul( line.substr(1,2), nullptr, 16);
 			uint32_t fw=std::stoul(line.substr(3,4),nullptr, 16);
-			uint8_t ty=std::stoul(line.substr(7,2),nullptr,16);
+			uint8_t ty=(uint8_t)std::stoul(line.substr(7,2),nullptr,16);
 			uint32_t chsm = bc + (fw >> 8) + (fw & 0xFF) + ty;
 			for (int i = 0; i < bc; i++) {
 				int p = 9 + i * 2;
-				uint8_t b = std::stoul(line.substr(p, 2),nullptr, 16);
+				uint8_t b = (uint8_t)std::stoul(line.substr(p, 2),nullptr, 16);
 				chsm = chsm + b;
 				prog.push_back(b);
 			}
diff --git a/src/main.cpp b/src/main.cpp
index c36dd88..7c28e12 100755
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -30,26 +30,34 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "owTools.h"
 
+#ifdef LINUX
 #include <mysql.h>
 #include "mySensorDB.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
 #include <sys/mman.h>
-#include <fcntl.h>    /* For O_RDWR */
 #include <unistd.h>
 #include <pthread.h>
 #include <sched.h>
+#endif
+
+#ifdef WIN
+#include "Windows.h"
+#include "time.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>    /* For O_RDWR */
 #include <memory.h>
-#include "owTools.h"
 #include "hexfile.h"
 #include <iostream>
 #include <algorithm>
 #include <fstream>
 #include <sstream> 
 
-
+#ifdef LINUX
 
 #define RB "\e(0\x6a\e(B" // 188 Right Bottom corner
 #define RT "\e(0\x6b\e(B" // 187 Right Top corner
@@ -63,7 +71,21 @@
 #define TC "\e(0\x77\e(B" // 203 Top Cross
 #define VL "\e(0\x78\e(B" // 186 Vertical Line
 #define SP " " 		  // space string
-        
+#endif
+#ifdef WIN
+#define RB " "// 188 Right Bottom corner
+#define RT  " "// 187 Right Top corner
+#define LT  " "// 201 Left Top cornet
+#define LB  " "// 200 Left Bottom corner
+#define MC " " // 206 Midle Cross
+#define HL " "// 205 Horizontal Line
+#define LC  " "// 204 Left Cross
+#define RC  " "// 185 Right Cross
+#define BC  " "// 202 Bottom Cross
+#define TC  " "// 203 Top Cross
+#define VL  " "// 186 Vertical Line
+#define SP " " 		  // space string
+#endif
 
 void printhelp() {
 printf("owTools - Programm for reading und  controlling 1-Wire Devices from www.tm3d.de\n\n");
@@ -137,17 +159,17 @@ int getArgi(std::string flag) {
 	return atoi(getArg(flag).c_str());
 }
 
-
+#ifdef LINUX
 int database=0;
 mySensorDB *sdb=NULL;
-
-
+#endif
+/*
 snum_t getArgsnum(std::string flag) {
 	snum_t snum;
 	snum.num=0;
 	return snum;
 }
-
+*/
 int findCPU(std::string cpu) {
 	std::ifstream fileInput;
 	std::string line;
@@ -192,7 +214,7 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 					for (owDevice* dev :*devices) {
 						if (dev->configstate!=OWDCS_NONE) {
 							for (size_t i=0;i<4;i++) {
-								if (dev->config->getPropertyID(i)!=0)
+								if (dev->config->getPropertyID((uint8_t)i)!=0)
 									printf("\033[1;34m%02X.%02X%02X\033[0m\t",dev->getNum().byte[7],dev->getNum().byte[1],dev->getNum().byte[0]);
 							}
 						}
@@ -201,8 +223,8 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 					for (owDevice* dev :*devices) {
 						if (dev->configstate!=OWDCS_NONE) {
 							for (size_t i=0;i<4;i++) {
-								if (dev->config->getPropertyID(i)!=0)
-									printf("\033[0;36m%s\033[0m\t",dev->config->getQuantity(i).substr(0,7).c_str());
+								if (dev->config->getPropertyID((uint8_t)i)!=0)
+									printf("\033[0;36m%s\033[0m\t",dev->config->getQuantity((uint8_t)i).substr(0,7).c_str());
 							}
 						}
 					}
@@ -210,10 +232,10 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 					for (owDevice* dev :*devices) {
 						if (dev->configstate!=OWDCS_NONE) {
 							for (size_t i=0;i<4;i++) {
-								if (dev->config->getPropertyID(i)!=0) {
-									size_t l=utf8_length(dev->config->getUnit(i));
+								if (dev->config->getPropertyID((uint8_t)i)!=0) {
+									size_t l=utf8_length(dev->config->getUnit((uint8_t)i));
 									std::string ls="           ";
-									printf("\033[3;34m[%s]%s\033[0m\t",dev->config->getUnit(i).c_str(),ls.substr(0,5-l).c_str());
+									printf("\033[3;34m[%s]%s\033[0m\t",dev->config->getUnit((uint8_t)i).c_str(),ls.substr(0,5-l).c_str());
 								}
 							}
 						}
@@ -221,19 +243,26 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 					
 				}	
 				printf("\n");
-
+#ifdef LINUX
 				if (database) {
 					//owi->log->setLogLevel(0);
 					for (owDevice* dev : *devices) {
 						sdb->createDeviceTable(dev);
 					}
 				}
+#endif
 			}
 			
 		}
 		time_t t=time(NULL);
 		int st=(int)t;
+#ifdef LINUX
 		struct tm tm = *localtime(&t);
+#endif
+#ifdef WIN
+		struct tm tm;
+		localtime_s(&tm,&t);
+#endif
 		printf("%d-%02d-%02d %02d:%02d:%02d\t", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
 		for (owDevice* dev :*devices) {
 			for(int k=0;k<owi->maxrepeat;k++){
@@ -244,7 +273,7 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 			if (owi->log->last()<OWLOG_ERROR) {
 				if (dev->configstate!=OWDCS_NONE) {
 					for (size_t i=0;i<4;i++) {					
-						if (dev->config->getPropertyID(i)!=0) {
+						if (dev->config->getPropertyID((int8_t)i)!=0) {
 							if (dev->values[i]<=-10) 
 								printf("%0.2f \t",dev->values[i]);
 							else if (dev->values[i]<0) 
@@ -261,9 +290,11 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 						}
 					}
 				}
+#ifdef LINUX
 				if (database) {
 					sdb->insertValues(dev);
 				}
+#endif
 			} else {
 				owi->log->setLogLevel(OWLOG_INFO);
 				owi->log->set(OWLOG_ERROR,"Too many errors, mybee conection is dead.");
@@ -273,7 +304,14 @@ void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int s
 		
 		}
 		printf("\n");
-		while (((int)time(NULL))<(st+intervall)) sleep(1);
+		while (((int)time(NULL)) < (st + intervall)) {
+#ifdef LINUX
+			sleep(1);
+#endif
+#ifdef WIN
+			Sleep(1000);
+#endif		
+		}
 	}
 }
 
@@ -290,14 +328,14 @@ void device_menu(owDevice* d) {
 	printf("Values info: ");
 	int tm3d=d->readConfig();
 	for (size_t i=0;i<4;i++) {
-		printf("%s in %s",d->config->getQuantity(i).c_str(),d->config->getUnit(i).c_str());
+		printf("%s in %s",d->config->getQuantity((uint8_t)i).c_str(),d->config->getUnit((uint8_t)i).c_str());
 		if (i<4) printf("; "); 
 	}
 	if (tm3d) printf(" (tm3d.de)"); else printf(" (default)"); 
 	printf("\n");
 	d->convertAll();
 	for (size_t i=0;i<d->values.size();i++) {
-		printf("\033[1;33m%0.4f %s\033[0m  ",d->values[i],d->config->getUnit(i).c_str());
+		printf("\033[1;33m%0.4f %s\033[0m  ",d->values[i],d->config->getUnit((uint8_t)i).c_str());
 	}
 	printf("\n");
 	for(int i=0;i<70;i++) printf(HL);printf("\n");
@@ -405,19 +443,13 @@ int main(int argc, char *argv[]) {
 	std::transform(adapter.begin(), adapter.end(),adapter.begin(), ::toupper);
 
 	std::string s;
-	
+#ifdef LINUX	
 	if(adapter.find("COM")!=std::string::npos) {
 		owi=new owCOMInterface();
 		int port=atoi(adapter.substr(adapter.find("COM")+3).c_str());
 		printf("Open /dev/ttyS%i\n",port);
 		owi->InitAdapter(port);
 	} else 
-	if(adapter.find("ARDUINO")!=std::string::npos) {
-		owi=new owARDUINOInterface();
-		int port=atoi(adapter.substr(adapter.find("ARDUINO")+7).c_str());
-		printf("Open /dev/ttyS%i\n",port);
-		owi->InitAdapter(port);
-	} else 
 	if(adapter.find("USB")!=std::string::npos) {
 		owi=new owUSBInterface();
 		int port=atoi(adapter.substr(adapter.find("USB")+3).c_str());
@@ -443,12 +475,49 @@ int main(int argc, char *argv[]) {
 		} else {
 			printf("\033[1;31mGPIO works with Raspberry PI only \033[0m\n");
 		}
-	}  
-	if (owi==NULL) {
+	}  else
+#endif
+	if (adapter.find("ARDUINO") != std::string::npos) {
+		owi = new owARDUINOInterface();
+		int port = atoi(adapter.substr(adapter.find("ARDUINO") + 7).c_str());
+		printf("Open /dev/ttyS%i\n", port);
+		owi->InitAdapter(port);
+	}
+
+#ifdef WIN
+		else 
+	if (adapter.find("USB") != std::string::npos) {
+		printf("USB \n");
+		owi = new owTMEXWIN();
+		int port = atoi(adapter.substr(adapter.find("USB") + 3).c_str());
+		printf("Open the %i. USB Adapter\n", port);
+		int err;
+		char cs[20];
+		sprintf_s(cs, 20, "{%i,6}", port);
+		if ((err = owi->InitAdapter(cs))==0) {
+					printf("ERROR Init USB Adapter\n");
+					exit(0);
+				}
+			}
+	else
+		if (adapter.find("COM") != std::string::npos) {
+			printf("USB \n");
+			owi = new owTMEXWIN();
+			int port = atoi(adapter.substr(adapter.find("COM") + 3).c_str());
+			printf("Open Adapter on COM%i\n", port);
+			int err;
+			char cs[20];
+			sprintf_s(cs, 20, "{%i,5}", port);
+			if ((err = owi->InitAdapter(cs))==0) {
+				printf("ERROR Init Serial Adapter\n");
+				exit(0);
+			}
+		}
+#endif
+	if (owi == NULL) {
 		printf("No 1-Wiremaster found\n");
 		return 0;
 	}
-
 	setLogMode();
 	
 	
@@ -466,6 +535,7 @@ int main(int argc, char *argv[]) {
 		if ((s=getArg("p")) !="") {
 			pause=atoi(s.c_str());
 		} else pause=30;
+#ifdef LINUX
 		if  ((s=getArg("d")) !="") {
 			reload=1;
 			printf("Use Database\n");
@@ -482,7 +552,8 @@ int main(int argc, char *argv[]) {
 				exit(1);
 			}				
 			database=1;
-		}	
+		}
+#endif
 			
 		
 		continuous(&(owi->devices),pause,1,reload);	
@@ -529,7 +600,12 @@ int main(int argc, char *argv[]) {
 		if ((getArg("g"))=="1") {
 			printf("get ID from Server\n");
 			char s[255];
+#ifdef LINUX
 			sprintf(s,"wget -q http://www.tm3d.de/shop99/owid.php?fam=%02X -O id.txt",snum.byte[0]);
+#endif
+#ifdef WIN
+			sprintf_s(s, "wget -q http://www.tm3d.de/shop99/owid.php?fam=%02X -O id.txt", snum.byte[0]);
+#endif
 			int err;
 			if ((err=system(s))==0) {
 				printf("OK!\n");
@@ -546,7 +622,7 @@ int main(int argc, char *argv[]) {
 	    					if (c=='x') br=1;
 	    				} else {
 	    					if ((c==',')|(c=='}')) {
-	    						isnum.byte[i]=strtol(s, NULL, 16);
+	    						isnum.byte[i]=(uint8_t)strtol(s, NULL, 16);
 	    						//printf("%x\n",strtol(s, NULL, 16));
 	    						i++;
 	    						br=0;
@@ -619,7 +695,12 @@ int main(int argc, char *argv[]) {
 						colm.push_back("");
 					} else {
 						char hs[50];
+#ifdef LINUX
 						sprintf(hs,"%0.3f",dev->values[i]);
+#endif
+#ifdef WIN
+						sprintf_s(hs, "%0.3f", dev->values[i]);
+#endif
 						colm.push_back(hs);
 					}
 					if (max<utf8_length(colm[3])) max=utf8_length(colm[3]);
diff --git a/src/owARDUINOInterface.cpp b/src/owARDUINOInterface.cpp
index 33d2814..4ec1911 100644
--- a/src/owARDUINOInterface.cpp
+++ b/src/owARDUINOInterface.cpp
@@ -1,489 +1,560 @@
-// Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//  * Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-//  * Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the
-//    distribution.
-//  * All advertising materials mentioning features or use of this
-//    software must display the following acknowledgement: This product
-//    includes software developed by tm3d.de and its contributors.
-//  * Neither the name of tm3d.de nor the names of its contributors may
-//    be used to endorse or promote products derived from this software
-//    without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/select.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <termios.h>
-#include <errno.h>
-#include <sys/time.h>
-#include "owARDUINOInterface.h"
-
-#define MODE_DATA                      0xE1
-#define MODE_COMMAND                   0xE3
-
-// Baud rate bits
-#define PARMSET_9600                   0x00
-#define PARMSET_19200                  0x02
-#define PARMSET_57600                  0x04
-#define PARMSET_115200                 0x06
-
-
-
-#define COM_IDENTIFER 1
-#define COM_RESET 2
-#define COM_SEARCH_INIT 3
-#define COM_SEARCH_NEXT 4
-#define COM_BLOCK 5
-#define COM_SBYTE 6
-#define COM_RBYTE 7
-#define COM_SBIT 8
-#define COM_RBIT 9
-
-//---------------------------------------------------------------------------
-//  Description:
-//     flush the rx and tx buffers
-//
-// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
-//              OpenCOM to indicate the port number.
-//
-void owARDUINOInterface::FlushCOM() {
-   tcflush(fd, TCIOFLUSH);
-}
-
-
-int owARDUINOInterface::OpenCOM(uint8_t comnr) {
-	struct termios t;               // see man termios - declared as above
-	int rc;
-	//int fd;
-	char port_zstr[100];
-	if (com_init) return fd;
-
-	sprintf(port_zstr,"/dev/ttyUSB%i",comnr);
-
-   fd = open(port_zstr, O_RDWR|O_NONBLOCK| O_NOCTTY );
-   if (fd<0)
-   {
-	   log->set(OWLOG_ERROR,"ERROR open Com %s return %i",port_zstr,fd);
-      return fd;
-   }
-   rc = tcgetattr (fd, &t);
-   if (rc < 0)
-   {
-      int tmp;
-      tmp = errno;
-      close(fd);
-      errno = tmp;
-      log->set(OWLOG_ERROR,"OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s",port_zstr);
-      return rc; // changed (2.00), used to return rc;
-   }
-
-   cfsetospeed(&t, B9600);
-   cfsetispeed (&t, B9600);
-
-   // Get terminal parameters. (2.00) removed raw
-   tcgetattr(fd,&t);
-   // Save original settings.
-   origterm = t;
-
-  	t.c_cflag     &=  ~PARENB;            // Make 8n1
-	t.c_cflag     &=  ~CSTOPB;
-	t.c_cflag     &=  ~CSIZE;
-	t.c_cflag     |=  CS8;
-
-	t.c_cflag     &=  ~CRTSCTS;           // no flow control
-	t.c_cc[VMIN]   =  1;                  // read doesn't block
-	t.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
-	t.c_cflag     |=  CREAD | CLOCAL;     // turn on READ & ignore ctrl lines
-	t.c_cflag     &=  ~CRTSCTS;       // no flow control
-	t.c_iflag     &=  ~(IXON | IXOFF | IXANY);// turn off s/w flow ctrl
-/* Make raw */
-	cfmakeraw(&t);
- 	 tcflush(fd,TCIOFLUSH);
-
-   rc = tcsetattr(fd, TCSAFLUSH, &t);
- 
-   if (rc < 0)
-   {
-      int tmp;
-      tmp = errno;
-      close(fd);
-      errno = tmp;
-      log->set(OWLOG_ERROR,"OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s",port_zstr);
-      return rc; // changed (2.00), used to return rc;
-   }
-	com_init=1;
-   return fd; // changed (2.00), used to return fd;
-}
-
-
-//---------------------------------------------------------------------------
-// Closes the connection to the port.
-//
-// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
-//              OpenCOM to indicate the port number.
-//
-void owARDUINOInterface::CloseCOM()
-{
-   // restore tty settings
-   tcsetattr(fd, TCSAFLUSH, &origterm);
-   FlushCOM();
-   close(fd);
-   com_init=0;
-   
-}
-
-
-//--------------------------------------------------------------------------
-// Write an array of bytes to the COM port, verify that it was
-// sent out.  Assume that baud rate has been set.
-//
-// 'portnum'   - number 0 to MAX_PORTNUM-1.  This number provided will
-//               be used to indicate the port number desired when calling
-//               all other functions in this library.
-// Returns 1 for success and 0 for failure
-//
-int owARDUINOInterface::WriteCOM( int outlen, uint8_t *outbuf)
-{
-   long count = outlen;
-   int i=0;
-   for (int k=0;k<outlen;k++) {
-   		 i+= write(fd, outbuf+k, 1);
-//   		 sleep(1);
-   	}
-
-   tcdrain(fd);
-   return (i == count);
-}
-
-
-//--------------------------------------------------------------------------
-// Read an array of bytes to the COM port, verify that it was
-// sent out.  Assume that baud rate has been set.
-//
-// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
-//              OpenCOM to indicate the port number.
-// 'outlen'   - number of bytes to write to COM port
-// 'outbuf'   - pointer ot an array of bytes to write
-//
-// Returns:  TRUE(1)  - success
-//           FALSE(0) - failure
-//
-int owARDUINOInterface::ReadCOM( int inlen, uint8_t *inbuf)
-{
-   fd_set         filedescr;
-   struct timeval tval;
-   int            cnt;
-
-   // loop to wait until each byte is available and read it
-   for (cnt = 0; cnt < inlen; cnt++)
-   {
-      // set a descriptor to wait for a character available
-      FD_ZERO(&filedescr);
-      FD_SET(fd,&filedescr);
-      // set timeout to 10ms
-      tval.tv_sec = 10;
-      tval.tv_usec = 10000;
-
-      // if byte available read or return bytes read
-      if (select(fd+1,&filedescr,NULL,NULL,&tval) != 0)
-      {
-         if (read(fd,&inbuf[cnt],1) != 1) {
-			log->set(OWLOG_ERROR,"Read Error on Serial");
-
-            return cnt;
-         }
-      }
-      else {
-		log->set(OWLOG_ERROR,"Read Error on Serial (select)");
-        return cnt;
-	}
-   }
-
-   
-   // success, so return desired length
-   return inlen;
-}
-
-
-
-
-//--------------------------------------------------------------------------
-//  Description:
-//     Send a break on the com port for at least 2 ms
-//
-// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
-//              OpenCOM to indicate the port number.
-//
-void owARDUINOInterface::BreakCOM()
-{
-   int duration = 0;              // see man termios break may be
-   tcsendbreak(fd, duration);     // too long
-}
-
-
-//--------------------------------------------------------------------------
-// Set the baud rate on the com port.
-//
-// 'portnum'   - number 0 to MAX_PORTNUM-1.  This number was provided to
-//               OpenCOM to indicate the port number.
-// 'new_baud'  - new baud rate defined as
-// PARMSET_9600     0x00
-// PARMSET_19200    0x02
-// PARMSET_57600    0x04
-// PARMSET_115200   0x06
-//
-void owARDUINOInterface::SetBaudCOM( uint8_t new_baud)
-{
-   struct termios t;
-   int rc;
-   speed_t baud;
-
-   // read the attribute structure
-   rc = tcgetattr(fd, &t);
-   if (rc < 0)
-   {
-      close(fd); 
-      log->set(OWLOG_ERROR,"Error on Serial (set Boudrate)");
-
-      return;
-   }
-
-   // convert parameter to linux baud rate
-   switch(new_baud)
-   {
-      case PARMSET_9600:
-         baud = B9600;
-         break;
-      case PARMSET_19200:
-         baud = B19200;
-         break;
-      case PARMSET_57600:
-         baud = B57600;
-         break;
-      case PARMSET_115200:
-         baud = B115200;
-         break;
-      default:
-         baud = B9600;
-         break;
-   }
-
-   // set baud in structure
-   cfsetospeed(&t, baud);
-   cfsetispeed(&t, baud);
-
-   // change baud on port
-   rc = tcsetattr(fd, TCSAFLUSH, &t);
-   if (rc < 0) {
-	  log->set(OWLOG_ERROR,"Error on Serial (set Boudrate)");
-
-      close(fd);
-  }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-int owARDUINOInterface::InitAdapter(uint8_t nr) {
-	// attempt to open the communications port
-	if ((fd = OpenCOM(nr)) < 0)
-	{
-		log->set(OWLOG_ERROR,"OWERROR_OPENCOM_FAILED");
-		return -1;
-	}	
-	sleep(2);
-	uint8_t readbuffer[20],sendpacket[20];
-  	uint8_t sendlen=0;
-	sendpacket[sendlen++]=0x01;
-	sendpacket[sendlen++]=0x00;
-	sendpacket[sendlen++]=0x03;
- 	if (WriteCOM(sendlen,sendpacket)) {
-      if ((sendlen=ReadCOM(3,readbuffer)) == 3) {
-      
-	//	printf("%02X %02X %02X\n",readbuffer[0],readbuffer[1],readbuffer[2] );
-	
-		
-		
-      }  else {
-      	//printf("%i\n",sendlen);
-      	log->set(OWLOG_ERROR,"OWERROR_READCOM_FAILED");
-      }
-   }   else  log->set(OWLOG_ERROR,"OWERROR_WRITECOM_FAILED");	  	 
-  	 
-	com_init=1;
-	
-	
-	return 1;	
-}
-
-
-int owARDUINOInterface::owFirst() {
-	uint8_t readbuffer[20],sendpacket[20];
-	uint8_t sendlen=0;
-	sendpacket[sendlen++]=0x03;
-	sendpacket[sendlen++]=0x00;	
-	sendpacket[sendlen++]=0x08;
-	if (WriteCOM(sendlen,sendpacket)) {
-		if ((sendlen=ReadCOM(8,readbuffer)) == 8) {
-			if (readbuffer[0]!=0) {
-				for (int i=0;i<8;i++) ROM_NO[i]=readbuffer[i];
-				return 1;
-			}
-		}
-	}
-	return 0;
-
-}
-int owARDUINOInterface::owNext() {
-	uint8_t readbuffer[20],sendpacket[20];
-	uint8_t sendlen=0;
-	sendpacket[sendlen++]=0x04;
-	sendpacket[sendlen++]=0x00;	
-	sendpacket[sendlen++]=0x08;
-	if (WriteCOM(sendlen,sendpacket)) {
-		if ((sendlen=ReadCOM(8,readbuffer)) == 8) {
-			if (readbuffer[0]!=0) {
-				for (int i=0;i<8;i++) ROM_NO[i]=readbuffer[i];
-				return 1;
-			}
-		}
-	}
-	return 0;
-
-}
-
-
-void owARDUINOInterface::ReleaseAdapter() {
-	CloseCOM();
-}
-
-
-int owARDUINOInterface::Reset() {
-	uint8_t readbuffer[5],sendpacket[5];
-  	uint8_t sendlen=0;
- /* 	size_t l;
-
- 	if ((l=read(fd,readbuffer,5))>0) {
-		printf("in buf %i bytes %02X %02X %02X %02X %02X\n",l,readbuffer[0],readbuffer[1],readbuffer[2],readbuffer[3],readbuffer[4]);
-	 }*/
-	sendlen=0;
-	sendpacket[sendlen++]=0x02;
-	sendpacket[sendlen++]=0x00;
-	sendpacket[sendlen++]=0x01;
-	if (WriteCOM(sendlen,sendpacket)) {
-		if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
-		//	printf("Reset %i\n",readbuffer[0]);
-			if (readbuffer[0]) return 1;
-			
-		}
-	}
-
-	return 0;
-}
-
-
-uint8_t owARDUINOInterface::sendrecivByte(uint8_t byte) {
-	
-	uint8_t readbuffer[5],sendpacket[5];
-  	uint8_t sendlen=0;
-/*  	size_t l;
-  	if ((l=read(fd,readbuffer,5))>0) {
-		printf("in buf %i bytes %02X %02X %02X %02X %02X\n",l,readbuffer[0],readbuffer[1],readbuffer[2],readbuffer[3],readbuffer[4]);
-	 }*/
-	if (byte!=0xFF) {
-		sendlen=0;
-		sendpacket[sendlen++]=COM_SBYTE;
-		sendpacket[sendlen++]=0x01;
-		sendpacket[sendlen++]=0x01;
-		sendpacket[sendlen++]=byte;
-		if (WriteCOM(sendlen,sendpacket)) {
-			if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
-		//		printf("Send %02X %02X \n",byte,readbuffer[0]);
-
-				return byte;
-			}
-		}
-	} else {
-		sendlen=0;
-		sendpacket[sendlen++]=COM_RBYTE;
-		sendpacket[sendlen++]=0x00;
-		sendpacket[sendlen++]=0x01;
-		if (WriteCOM(sendlen,sendpacket)) {
-			if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
-			//	printf("Recive %02X\n",readbuffer[0]);
-				return readbuffer[0];
-			}
-		}
-		
-	}
-
-   return 0;				
-}
-uint8_t owARDUINOInterface::sendrecivBit(uint8_t bit) {
-	return 0;
-}
-
-int owARDUINOInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
-	int i=0;
-	data->resize(scount);
-	uint8_t readbuffer[128],sendpacket[128+3];
-  	uint8_t sendlen=0;
-	sendpacket[sendlen++]=COM_BLOCK;
-	sendpacket[sendlen++]=scount;
-	sendpacket[sendlen++]=rcount;
-	for(uint8_t v:*data) {
-		sendpacket[sendlen++]=v;
-		(*data)[i]=v;i++;
-	}
-	if (WriteCOM(sendlen,sendpacket)) {
-			if ((sendlen=ReadCOM(rcount,readbuffer)) == rcount) {
-				for(i=0;i<rcount;i++) {
-					//printf("%02X ",readbuffer[i]);
-					data->push_back(readbuffer[i]);
-				}
-				//printf("\n");
-			}
-		}
-		
-	
-	return 0;
-}
-	
+// Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the
+//    distribution.
+//  * All advertising materials mentioning features or use of this
+//    software must display the following acknowledgement: This product
+//    includes software developed by tm3d.de and its contributors.
+//  * Neither the name of tm3d.de nor the names of its contributors may
+//    be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifdef LINUX
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/time.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+#include "owARDUINOInterface.h"
+
+
+#define COM_IDENTIFER 1
+#define COM_RESET 2
+#define COM_SEARCH_INIT 3
+#define COM_SEARCH_NEXT 4
+#define COM_BLOCK 5
+#define COM_SBYTE 6
+#define COM_RBYTE 7
+#define COM_SBIT 8
+#define COM_RBIT 9
+
+//---------------------------------------------------------------------------
+//  Description:
+//     flush the rx and tx buffers
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+//
+void owARDUINOInterface::FlushCOM() {
+#ifdef LINUX
+   tcflush(fd, TCIOFLUSH);
+#endif 
+#ifdef WIN
+   PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT |
+	   PURGE_TXCLEAR | PURGE_RXCLEAR);
+#endif
+}
+
+#ifdef LINUX
+int 
+#endif
+#ifdef WIN
+HANDLE 
+#endif
+owARDUINOInterface::OpenCOM(uint8_t comnr)
+{
+	char port_zstr[100];
+#ifdef LINUX
+	struct termios t;               // see man termios - declared as above
+	int rc;
+	//int fd;
+	
+	if (com_init) return fd;
+
+	sprintf(port_zstr,"/dev/ttyUSB%i",comnr);
+
+   fd = open(port_zstr, O_RDWR|O_NONBLOCK| O_NOCTTY );
+   if (fd<0)
+   {
+	   log->set(OWLOG_ERROR,"ERROR open Com %s return %i",port_zstr,fd);
+      return fd;
+   }
+   rc = tcgetattr (fd, &t);
+   if (rc < 0)
+   {
+      int tmp;
+      tmp = errno;
+      close(fd);
+      errno = tmp;
+      log->set(OWLOG_ERROR,"OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s",port_zstr);
+      return rc; // changed (2.00), used to return rc;
+   }
+
+   cfsetospeed(&t, B9600);
+   cfsetispeed (&t, B9600);
+
+   // Get terminal parameters. (2.00) removed raw
+   tcgetattr(fd,&t);
+   // Save original settings.
+   origterm = t;
+
+  	t.c_cflag     &=  ~PARENB;            // Make 8n1
+	t.c_cflag     &=  ~CSTOPB;
+	t.c_cflag     &=  ~CSIZE;
+	t.c_cflag     |=  CS8;
+
+	t.c_cflag     &=  ~CRTSCTS;           // no flow control
+	t.c_cc[VMIN]   =  1;                  // read doesn't block
+	t.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
+	t.c_cflag     |=  CREAD | CLOCAL;     // turn on READ & ignore ctrl lines
+	t.c_cflag     &=  ~CRTSCTS;       // no flow control
+	t.c_iflag     &=  ~(IXON | IXOFF | IXANY);// turn off s/w flow ctrl
+/* Make raw */
+	cfmakeraw(&t);
+ 	 tcflush(fd,TCIOFLUSH);
+
+   rc = tcsetattr(fd, TCSAFLUSH, &t);
+ 
+   if (rc < 0)
+   {
+      int tmp;
+      tmp = errno;
+      close(fd);
+      errno = tmp;
+      log->set(OWLOG_ERROR,"OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s",port_zstr);
+      return rc; // changed (2.00), used to return rc;
+   }
+	com_init=1;
+   return fd; // changed (2.00), used to return fd;
+#endif
+#ifdef WIN
+   short fRetVal;
+   COMMTIMEOUTS CommTimeOuts;
+   DCB dcb;
+   int comnr1 = comnr;
+   sprintf_s(port_zstr,100, "COM%d", comnr1);
+   if (fd <= 0) {
+	   if ((fd =  CreateFileA(port_zstr, GENERIC_READ | GENERIC_WRITE,
+			   0,
+			   NULL,                 // no security attrs
+			   OPEN_EXISTING,
+			   FILE_FLAG_OVERLAPPED, // overlapped I/O
+			   NULL)) == (HANDLE)-1) {
+		   fd = 0;
+		   log->set(OWLOG_ERROR, "ERROR open Com %s return %i", port_zstr, fd);
+		   return (FALSE);
+	   } else  {
+		   // get any early notifications
+		   SetCommMask(fd, EV_RXCHAR | EV_TXEMPTY | EV_ERR | EV_BREAK);
+		   SetupComm(fd, 2048, 2048);
+		   // purge any information in the buffer
+		   PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT |   PURGE_TXCLEAR | PURGE_RXCLEAR);
+		   // set up for overlapped non-blocking I/O
+		   CommTimeOuts.ReadIntervalTimeout = 0;
+		   CommTimeOuts.ReadTotalTimeoutMultiplier = 20;
+		   CommTimeOuts.ReadTotalTimeoutConstant = 40;
+		   CommTimeOuts.WriteTotalTimeoutMultiplier = 20;
+		   CommTimeOuts.WriteTotalTimeoutConstant = 40;
+		   SetCommTimeouts(fd, &CommTimeOuts);
+		   // setup the com port
+		   GetCommState(fd, &dcb);
+		   dcb.BaudRate = CBR_9600;               // current baud rate
+		   dcb.fBinary = TRUE;                    // binary mode, no EOF check
+		   dcb.fParity = FALSE;                   // enable parity checking
+		   dcb.fOutxCtsFlow = FALSE;              // CTS output flow control
+		   dcb.fOutxDsrFlow = FALSE;              // DSR output flow control
+		   dcb.fDtrControl = FALSE;  // DTR flow control type
+		   dcb.fDsrSensitivity = FALSE;           // DSR sensitivity
+		   dcb.fTXContinueOnXoff = FALSE;          // XOFF continues Tx
+		   dcb.fOutX = FALSE;                     // XON/XOFF out flow control
+		   dcb.fInX = FALSE;                      // XON/XOFF in flow control
+		   dcb.fErrorChar = FALSE;                // enable error replacement
+		   dcb.fNull = FALSE;                     // enable null stripping
+		   dcb.fRtsControl = FALSE;  // RTS flow control
+		   dcb.fAbortOnError = FALSE;             // abort reads/writes on error
+		   dcb.XonLim = 0;                        // transmit XON threshold
+		   dcb.XoffLim = 0;                       // transmit XOFF threshold
+		   dcb.ByteSize = 8;                      // number of bits/byte, 4-8
+		   dcb.Parity = NOPARITY;                 // 0-4=no,odd,even,mark,space
+		   dcb.StopBits = ONESTOPBIT;             // 0,1,2 = 1, 1.5, 2
+		   dcb.XonChar = 0;                       // Tx and Rx XON character
+		   dcb.XoffChar = 0;                      // Tx and Rx XOFF character
+		   dcb.ErrorChar = 0;                     // error replacement character
+		   dcb.EofChar = 0;                       // end of input character
+		   dcb.EvtChar = 0;                       // received event character
+		   fRetVal = SetCommState(fd, &dcb);
+
+	   }
+	   // check if successfull
+	   if (!fRetVal)   {
+		   CloseHandle(fd);
+		   fd = 0;
+		   log->set(OWLOG_ERROR, "OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s", port_zstr);
+	   }
+	   return (fd);
+   }
+   return 0;
+#endif
+}
+
+
+//---------------------------------------------------------------------------
+// Closes the connection to the port.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+//
+void owARDUINOInterface::CloseCOM()
+{
+#ifdef LINUX
+   // restore tty settings
+   tcsetattr(fd, TCSAFLUSH, &origterm);
+   FlushCOM();
+   close(fd);
+#endif
+#ifdef WIN
+   // disable event notification and wait for thread
+   // to halt
+   SetCommMask(fd, 0);
+
+   PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT |	   PURGE_TXCLEAR | PURGE_RXCLEAR);
+   CloseHandle(fd);
+   fd = 0;
+#endif
+   com_init = 0;
+
+}
+
+
+//--------------------------------------------------------------------------
+// Write an array of bytes to the COM port, verify that it was
+// sent out.  Assume that baud rate has been set.
+//
+// 'portnum'   - number 0 to MAX_PORTNUM-1.  This number provided will
+//               be used to indicate the port number desired when calling
+//               all other functions in this library.
+// Returns 1 for success and 0 for failure
+//
+int owARDUINOInterface::WriteCOM( int outlen, uint8_t *outbuf) {
+#ifdef LINUX
+   long count = outlen;
+   int i=0;
+   for (int k=0;k<outlen;k++) {
+   		 i+= write(fd, outbuf+k, 1);
+//   		 sleep(1);
+   	}
+
+   tcdrain(fd);
+   return (i == count);
+#endif
+#ifdef WIN
+   BOOL fWriteStat;
+   DWORD dwBytesWritten = 0;
+   DWORD ler = 0, to;
+   OVERLAPPED osWrite = { 0 };
+   // calculate a timeout
+   to = 20 * outlen + 60;
+   // write the byte
+   osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+   ResetEvent(osWrite.hEvent);
+   fWriteStat = WriteFile(fd, (LPSTR)&outbuf[0],  outlen, &dwBytesWritten, &osWrite);
+   // check for an error
+  // Sleep(100);
+   if (!fWriteStat)
+	   ler = GetLastError();
+   // if not done writting then wait
+   if (!fWriteStat && ler == ERROR_IO_PENDING) {
+	  // log->set(OWLOG_ERROR, "SERIAL_ERROR_IO_PENDING");
+	   WaitForSingleObject(osWrite.hEvent, to);
+	   // verify all is written correctly
+
+	   fWriteStat = GetOverlappedResult(fd, &osWrite,  &dwBytesWritten, FALSE);
+   }
+   // check results of write
+   if (!fWriteStat || (dwBytesWritten != (DWORD)outlen))
+	   return 0;
+   else
+	   return 1;
+#endif
+}
+
+
+//--------------------------------------------------------------------------
+// Read an array of bytes to the COM port, verify that it was
+// sent out.  Assume that baud rate has been set.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+// 'outlen'   - number of bytes to write to COM port
+// 'outbuf'   - pointer ot an array of bytes to write
+//
+// Returns:  TRUE(1)  - success
+//           FALSE(0) - failure
+//
+int owARDUINOInterface::ReadCOM( int inlen, uint8_t *inbuf)
+{
+#ifdef LINUX
+   fd_set         filedescr;
+   struct timeval tval;
+   int            cnt;
+
+   // loop to wait until each byte is available and read it
+   for (cnt = 0; cnt < inlen; cnt++)
+   {
+      // set a descriptor to wait for a character available
+      FD_ZERO(&filedescr);
+      FD_SET(fd,&filedescr);
+      // set timeout to 10ms
+      tval.tv_sec = 10;
+      tval.tv_usec = 10000;
+
+      // if byte available read or return bytes read
+      if (select(fd+1,&filedescr,NULL,NULL,&tval) != 0)
+      {
+         if (read(fd,&inbuf[cnt],1) != 1) {
+			log->set(OWLOG_ERROR,"Read Error on Serial");
+
+            return cnt;
+         }
+      }
+      else {
+		log->set(OWLOG_ERROR,"Read Error on Serial (select)");
+        return cnt;
+	}
+   }
+
+   
+   // success, so return desired length
+   return inlen;
+#endif
+#ifdef WIN
+   DWORD dwLength = 0;
+   BOOL fReadStat;
+   DWORD ler = 0, to;
+   OVERLAPPED osReader = { 0 };
+   // calculate a timeout
+   to = 20 * inlen + 60;
+   // read
+   osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+   ResetEvent(osReader.hEvent);
+   fReadStat = ReadFile(fd, (LPSTR)&inbuf[0],  inlen, &dwLength, &osReader);
+   //Sleep(100);
+   // check for an error
+   if (!fReadStat) {
+	   ler = GetLastError();
+	//   log->set(OWLOG_ERROR, "Read Error on Serial");
+   }
+   // if not done writing then wait
+   int e = 0;
+   while (!fReadStat && ler == ERROR_IO_PENDING) {
+	   // wait until everything is read
+	  // log->set(OWLOG_ERROR, "Read Error on Serial");
+	  // printf("try Read %i\n", e); e++;
+	   WaitForSingleObject(osReader.hEvent, to);
+	   // verify all is read correctly
+	   fReadStat = GetOverlappedResult(fd, &osReader,   &dwLength, FALSE);
+	   //printf("%i %i\n", dwLength, inlen);
+	   if (dwLength == inlen) break;
+	   if (e == 3) break;
+	   printf("repeat\n");
+
+   }
+   // check results
+   if (fReadStat)
+	   return dwLength;
+   else
+	   return 0;
+#endif
+}
+
+
+/*
+
+//--------------------------------------------------------------------------
+//  Description:
+//     Send a break on the com port for at least 2 ms
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+//
+void owARDUINOInterface::BreakCOM()
+{
+   int duration = 0;              // see man termios break may be
+   tcsendbreak(fd, duration);     // too long
+}
+
+*/
+
+
+
+
+
+
+
+
+
+int owARDUINOInterface::InitAdapter(uint8_t nr) {
+	// attempt to open the communications port
+	if ((fd = OpenCOM(nr)) < 0)
+	{
+		log->set(OWLOG_ERROR,"OWERROR_OPENCOM_FAILED");
+		return -1;
+	}
+#ifdef WIN
+	Sleep(2000);
+#endif
+#ifdef LINUX
+	sleep(2);
+#endif
+	uint8_t readbuffer[20],sendpacket[20];
+  	uint8_t sendlen=0;
+	sendpacket[sendlen++]=0x01;
+	sendpacket[sendlen++]=0x00;
+	sendpacket[sendlen++]=0x03;
+ 	if (WriteCOM(sendlen,sendpacket)) {
+      if ((sendlen=ReadCOM(3,readbuffer)) == 3) {
+		//	printf("%02X %02X %02X\n",readbuffer[0],readbuffer[1],readbuffer[2] );
+      }  else {
+      	log->set(OWLOG_ERROR,"OWERROR_READCOM_FAILED");
+      }
+   }   else  log->set(OWLOG_ERROR,"OWERROR_WRITECOM_FAILED");	  	 
+	com_init=1;
+	return 1;	
+}
+
+
+int owARDUINOInterface::owFirst() {
+	uint8_t readbuffer[20],sendpacket[20];
+	uint8_t sendlen=0;
+	sendpacket[sendlen++]=0x03;
+	sendpacket[sendlen++]=0x00;	
+	sendpacket[sendlen++]=0x08;
+	if (WriteCOM(sendlen,sendpacket)) {
+		if ((sendlen=ReadCOM(8,readbuffer)) == 8) {
+			if (readbuffer[0]!=0) {
+				for (int i=0;i<8;i++) ROM_NO[i]=readbuffer[i];
+				return 1;
+			}
+		}
+	}
+	return 0;
+
+}
+int owARDUINOInterface::owNext() {
+	uint8_t readbuffer[20],sendpacket[20];
+	uint8_t sendlen=0;
+	sendpacket[sendlen++]=0x04;
+	sendpacket[sendlen++]=0x00;	
+	sendpacket[sendlen++]=0x08;
+	if (WriteCOM(sendlen,sendpacket)) {
+		if ((sendlen=ReadCOM(8,readbuffer)) == 8) {
+			if (readbuffer[0]!=0) {
+				for (int i=0;i<8;i++) ROM_NO[i]=readbuffer[i];
+				return 1;
+			}
+		}
+	}
+	return 0;
+
+}
+
+
+void owARDUINOInterface::ReleaseAdapter() {
+	CloseCOM();
+}
+
+
+int owARDUINOInterface::Reset() {
+	uint8_t readbuffer[5],sendpacket[5];
+  	uint8_t sendlen=0;
+	sendlen=0;
+	sendpacket[sendlen++]=0x02;
+	sendpacket[sendlen++]=0x00;
+	sendpacket[sendlen++]=0x01;
+	if (WriteCOM(sendlen,sendpacket)) {
+		if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
+			if (readbuffer[0]) return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+uint8_t owARDUINOInterface::sendrecivByte(uint8_t byte) {
+	
+	uint8_t readbuffer[5],sendpacket[5];
+  	uint8_t sendlen=0;
+	if (byte!=0xFF) {
+		sendlen=0;
+		sendpacket[sendlen++]=COM_SBYTE;
+		sendpacket[sendlen++]=0x01;
+		sendpacket[sendlen++]=0x01;
+		sendpacket[sendlen++]=byte;
+		if (WriteCOM(sendlen,sendpacket)) {
+			if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
+				return byte;
+			}
+		}
+	} else {
+		sendlen=0;
+		sendpacket[sendlen++]=COM_RBYTE;
+		sendpacket[sendlen++]=0x00;
+		sendpacket[sendlen++]=0x01;
+		if (WriteCOM(sendlen,sendpacket)) {
+			if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
+				return readbuffer[0];
+			}
+		}
+		
+	}
+
+   return 0;				
+}
+uint8_t owARDUINOInterface::sendrecivBit(uint8_t bit) {
+	return 0;
+}
+
+int owARDUINOInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
+	int i=0;
+	data->resize(scount);
+	uint8_t readbuffer[128],sendpacket[128+3];
+  	uint8_t sendlen=0;
+	sendpacket[sendlen++]=COM_BLOCK;
+	sendpacket[sendlen++]=scount;
+	sendpacket[sendlen++]=rcount;
+	for(uint8_t v:*data) {
+		sendpacket[sendlen++]=v;
+		(*data)[i]=v;i++;
+	}
+
+	if (WriteCOM(sendlen,sendpacket)) {
+		if ((sendlen=ReadCOM(rcount,readbuffer)) == rcount) {
+				for(i=0;i<rcount;i++) {
+					data->push_back(readbuffer[i]);
+				}
+			} else {
+				for (i = 0; i<rcount; i++) 
+					data->push_back(0xFF);
+			}
+		}
+	return 0;
+}
+	
diff --git a/src/owARDUINOInterface.h b/src/owARDUINOInterface.h
index 9dc72cb..14024c1 100644
--- a/src/owARDUINOInterface.h
+++ b/src/owARDUINOInterface.h
@@ -38,7 +38,12 @@
 
 class owARDUINOInterface:public owInterface{
 protected: 
+#ifdef LINUX
 	int fd;
+#endif
+#ifdef WIN
+	HANDLE fd;
+#endif
 	int com_init;
 public:
 	owARDUINOInterface():owInterface() {
@@ -61,16 +66,22 @@ protected:
 	uint8_t UMode;  // current DS2480B command or data mode state
 	uint8_t USpeed; // current DS2480B 1-Wire Net communication speed
 	uint8_t UVersion; // current DS2480B version 
+#ifdef LINUX
 	struct termios origterm;
-
-
+#endif
+#ifdef LINUX
 	int OpenCOM(uint8_t comnr);
+#endif
+#ifdef WIN
+	HANDLE OpenCOM(uint8_t comnr);
+#endif
+
 	void CloseCOM();
 	void FlushCOM();
 	int  WriteCOM(int outlen, uint8_t *outbuf);
 	int ReadCOM(int inlen, uint8_t *inbuf);
-	void BreakCOM();
-	void SetBaudCOM(uint8_t new_baud);
+//	void BreakCOM();
+
 	
 };
 
diff --git a/src/owDevice.cpp b/src/owDevice.cpp
index 70fe96a..070ec40 100755
--- a/src/owDevice.cpp
+++ b/src/owDevice.cpp
@@ -32,8 +32,21 @@
 
 
 #include "owInterface.h"
+#ifdef LINUX
 #include <unistd.h>
-
+#endif
+#ifdef WIN
+void usleep(int waitTime) {
+	__int64 time1 = 0, time2 = 0, freq = 0;
+
+	QueryPerformanceCounter((LARGE_INTEGER *)&time1);
+	QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
+
+	do {
+		QueryPerformanceCounter((LARGE_INTEGER *)&time2);
+	} while ((time2 - time1) < waitTime);
+}
+#endif
 owDevice::owDevice(owInterface *owi_,snum_t num) {
 		snum=num;
 		owi=owi_;
diff --git a/src/owInterface.cpp b/src/owInterface.cpp
index 66ea440..c08ea2d 100755
--- a/src/owInterface.cpp
+++ b/src/owInterface.cpp
@@ -1,553 +1,604 @@
-// Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//  * Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-//  * Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the
-//    distribution.
-//  * All advertising materials mentioning features or use of this
-//    software must display the following acknowledgement: This product
-//    includes software developed by tm3d.de and its contributors.
-//  * Neither the name of tm3d.de nor the names of its contributors may
-//    be used to endorse or promote products derived from this software
-//    without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "owInterface.h"
-#include <unistd.h>
-#include <math.h>
-#include "hexfile.h"
-
-static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
-static unsigned char owi_dscrc_table[] = {
-        0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
-      157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
-       35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
-      190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
-       70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
-      219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
-      101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
-      248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
-      140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
-       17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
-      175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
-       50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
-      202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
-       87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
-      233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
-      116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
-
-      
-uint8_t owInterface::docrc8(uint8_t value) {
-   // See Application Note 27
-   
-   // TEST BUILD
-   crc8 = owi_dscrc_table[crc8 ^ value];
-   return crc8;
-}
- 
-uint16_t owInterface::docrc16(uint16_t cdata) {
-   cdata = (cdata ^ (crc16 & 0xff)) & 0xff;
-   crc16 >>= 8;
-
-   if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4])
-     crc16 ^= 0xc001;
-
-   cdata <<= 6;
-   crc16   ^= cdata;
-   cdata <<= 1;
-   crc16   ^= cdata;
-
-   return crc16;
-		
-	
-}
-
-uint8_t owInterface::calcCRC8(std::vector<uint8_t> data) {
-	 crc8 = 0;
-	  for(uint8_t v: data) 
-			docrc8(v);
-	return crc8; //0 bei erfolg oder crc wenn crc nicht babei
-}
-
-uint16_t owInterface::calcCRC16(std::vector<uint8_t> data) {
-	crc16=0;
-	for(uint8_t v:data) {
-		docrc16(v);
-	}
-	return crc16;
-}
-
-int owInterface::testCRC16(std::vector<uint8_t> data)  {
-	return calcCRC16(data)==0xB001;
-}
-		
-void owInterface::resetFlasher() { // go back from Bootloader
-	std::vector<uint8_t> data;
-	data.push_back(0x89);
-	Wait_Free();
-	snum_t snum;
-	snum.num=0xfa55aa55aa55aaa3;
-	MatchRom(snum);
-	if (log->last()==OWLOG_ERROR) {Free(); return;}
-	Communicate(&data, 1, 0);
-	
-	Free();
-	if (log->last()==OWLOG_ERROR) return;
-	usleep(50);	
-}
-
-void owInterface::resetID() {
-	std::vector<uint8_t> data;
-	data.push_back(0x8B);
-	Wait_Free();
-	snum_t snum;
-	snum.num=0xfa55aa55aa55aaa3;
-	MatchRom(snum);
-	if (log->last()==OWLOG_ERROR) {Free(); return;}
-	Communicate(&data, 1, 0);
-	Free();
-}
-
-int owInterface::programmPage(int pagenr, std::vector<uint8_t> page, int pagesize) {
-	snum_t snum;
-	snum.num=0xfa55aa55aa55aaa3;
-//	printf("programm page %i",pagenr);
-	
-	
-	int diff = pagesize - page.size();
-	if (diff>0) {
-		for (int i = 0; i < (diff); i++) page.push_back(0xFF);
-	}
-	std::vector<uint8_t> cl;
-	std::vector<uint8_t> clb; //backup 
-	cl.push_back(0x0F);  //code for Flashing
-	cl.push_back((pagenr*pagesize) & 0xFF); //adress in byte
-	cl.push_back((pagenr*pagesize) >> 8);
-	cl.insert(cl.end(),page.begin(),page.end()); //page
-	clb=cl;		//make backup
-	Wait_Free();
-	MatchRom(snum); 
-	if (log->last()==OWLOG_ERROR) {Free();return -3;}
-	Communicate(&cl, 3+pagesize, 0); //send (resive page)
-	Free();
-	if (log->last()==OWLOG_ERROR) return -3;
-	int err=0;
-	for(int k=0;k<maxrepeat;k++) { //repeat for readback error 
-		cl.clear();
-		cl.push_back(0xAA); //code for readback scratchpad
-		Wait_Free();
-		MatchRom(snum);
-		if (log->last()==OWLOG_ERROR) {Free();return -3;}
-		Communicate(&cl, 1, 2+pagesize); // read back scratchpad
-		Free();
-		if (log->last()==OWLOG_ERROR) return -3;
-		err=0;
-		for (int i = 0; i < pagesize+2; i++) {
-			if (clb[i + 1] != cl[i + 1]) {  //test
-				usleep(50000);
-				err=1;
-				break;
-			}
-		}
-		if (err==0) break;
-	}
-	if (err==1) {
-		usleep(50000);
-		return -1;  //error in scratchpad
-	}
-	cl.clear();
-	cl.push_back(0x55);//Programm
-	Wait_Free();
-	MatchRom(snum);
-	if (log->last()==OWLOG_ERROR) {Free();return -3;}
-	Communicate(&cl, 1, 0);
-	Free();
-	if (log->last()==OWLOG_ERROR) return -3;
-	usleep(50000);
-	cl.clear();
-	cl.push_back(0xB8);//recal programm memory to scratchpad
-	cl.push_back((pagenr*pagesize) & 0xFF);
-	cl.push_back((pagenr*pagesize) >> 8);
-	Wait_Free();
-	MatchRom(snum);
-	if (log->last()==OWLOG_ERROR) {Free();return -3;}
-	Communicate(&cl, 3, 0); //Copy programm memory to scratch
-	Free();
-	if (log->last()==OWLOG_ERROR) return -3;
-	usleep(50000);
-	
-	for(int k=0;k<maxrepeat;k++) { //repead for reading scratch error
-		cl.clear();
-		cl.push_back(0xAA);
-		Wait_Free();
-		MatchRom(snum);
-		if (log->last()==OWLOG_ERROR) {Free();return -3;}
-		Communicate(&cl, 1, 2 + pagesize); //Reread scratch
-		Free();
-		if (log->last()==OWLOG_ERROR) return -3;
-		err=0;
-		for (int i = 0; i < pagesize + 2; i++) {
-			if (cl[i + 1] != clb[i + 1]) {
-				usleep(50000);
-				err=1;
-				break;
-			}
-		}
-		if (err==0) break;
-	}
-	if (err==1) {
-		usleep(50000);
-		return -2;
-	}
-
-
-	return 0;
-}
-
-
-int owInterface::flashHEXFile(std::string filename,snum_t dev,int resetid,int progress) {
-	log->set(OWLOG_INFO,"Open Hex-File: %s",filename.c_str());
-	hexFile *hf=new hexFile(filename);
-	if (hf->lastError==1) {log->set(OWLOG_ERROR,"CRC Error in HEX-File %s",filename.c_str());return -1;}
-	if (hf->lastError==2) {log->set(OWLOG_ERROR,"Error interpreting  HEX-File %s",filename.c_str());return -2;}
-	if (hf->lastError==3) {log->set(OWLOG_ERROR,"File could not be opened: %s",filename.c_str());return -3;}
-	unsigned int blcount=hf->getBlockCount(64);
-	if (blcount>118) {
-		log->set(OWLOG_ERROR,"Code to big, max 7552 Byte allowed (118 Pages). Code has %i pages!",blcount);
-		return -5;
-	}
-	log->set(OWLOG_INFO,"Try to start Bootloader on device %llX",dev.num);
-	int r=maxrepeat+1;
-	int found;
-	do {
-		log->clear();
-		std::vector<uint8_t> data;
-		MatchRom(dev);
-		data.push_back(0x88);
-		Communicate(&data, 1, 0);
-		MatchRom(dev);
-		Communicate(&data, 1, 0);
-		MatchRom(dev);
-		Communicate(&data, 1, 0);
-		sleep(3);
-		log->set(OWLOG_INFO,"Search for Bootloader...");
-		log->setLogLevel(OWLOG_WARNING);
-		Find();
-		log->setLogLevel(OWLOG_INFO);
-		found=0;
-		for (owDevice* dev :devices) {
-			if (dev->getNum().num==0xfa55aa55aa55aaa3) {
-				found=1;
-				break;
-			}	
-	 	}
-	 	if (found==0) log->set(OWLOG_WARNING,"Bootloader not found");
-	 	r--;
-	}	while ((found==0)&&(r>0));
-	if (r==0) {
-		log->set(OWLOG_ERROR,"Can not start Bootloader on this device %llX",dev.num);
-		return -4;
-	}
-	log->set(OWLOG_INFO,"Start Programm %i Pages",blcount);
-	int rp=0;
-	int er=0;
-	unsigned int i =0;
-	for ( i= 0; i < blcount; i++) {
-		std::vector<uint8_t> blk = hf->getBlock(i*64, 64);
-		int errc = maxrepeat*5;
-		while (errc != 0) {
-			log->clear();
-			if (programmPage(i, blk, 64) >= 0) {
-				if (progress) {printf("#");fflush(stdout);} 
-				break;
-			}
-			
-			errc -= 1;
-			rp++;
-			if (progress) {printf("\033[1;31m#\033[0m");fflush(stdout);} //printf("\033[1;33m%s\033[0m\n",s);
-					
-		}
-      if (errc == 0) { er++; break; }
-	}
-	if (progress) printf("\n");
-	if (er != 0) {
-		log->set(OWLOG_ERROR,"ERROR Writing Program Memory!!!");
-		if (i==0) {
-			log->set(OWLOG_ERROR,"If Fuse SELFPRGEN enabled?");
-		} else
-			log->set(OWLOG_ERROR,"Maybe 1-Wire Connection is verry bad!");
-	} else {
-		if (resetid) {
-			log->set(OWLOG_INFO,"Set 1-Wire ID to ID in hexfile...",blcount); 
-			resetID();
-			sleep(3);
-			resetID();	
-			sleep(3);
-		}
-	}	
-	
-	log->set(OWLOG_INFO,"Back from bootloader to normal device...",blcount); 
-	
-	
-	resetFlasher();
-	sleep(1);	
-	resetFlasher();
-	sleep(3);	
-
-	Find();
-	
-	return 1;
-		
-}
-
-
-int owInterface::owSearch() {
-	int id_bit_number;
-	int last_zero, rom_byte_number, search_result;
-	int id_bit, cmp_id_bit;
-	unsigned char rom_byte_mask, search_direction;
-
-	// initialize for search
-	id_bit_number = 1;
-	last_zero = 0;
-	rom_byte_number = 0;
-	rom_byte_mask = 1;
-	search_result = 0;
-	crc8 = 0;
-
-	// if the last call was not the last one
-	if (!LastDeviceFlag) {
-		// 1-Wire reset
-		Wait_Free();
-		if (!Reset()) {
-        // reset the search
-			LastDiscrepancy = 0;
-			LastDeviceFlag = FALSE;
-			LastFamilyDiscrepancy = 0;
-			Free();
-			return FALSE;
-		}
-		if (log->last()==OWLOG_ERROR) return -3;
-		// issue the search command 
-		sendrecivByte(0xF0);  
-		if (log->last()==OWLOG_ERROR) return -3;
-
-		// loop to do the search
-		do {
-			// read a bit and its complement
-			id_bit = sendrecivBit(1);
-			cmp_id_bit = sendrecivBit(1);
-			// check for no devices on 1-wire
-			if ((id_bit == 1) && (cmp_id_bit == 1))
-				break;
-			else {
-				// all devices coupled have 0 or 1
-				if (id_bit != cmp_id_bit)
-					search_direction = id_bit;  // bit write value for search
-				else  {
-					// if this discrepancy if before the Last Discrepancy
-					// on a previous next then pick the same as last time
-					if (id_bit_number < LastDiscrepancy)
-						search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
-					else
-						// if equal to last pick 1, if not then pick 0
-						search_direction = (id_bit_number == LastDiscrepancy);
-
-					// if 0 was picked then record its position in LastZero
-					if (search_direction == 0) {
-						last_zero = id_bit_number;
-						// check for Last discrepancy in family
-						if (last_zero < 9)
-							LastFamilyDiscrepancy = last_zero;
-					}
-				}
-				// set or clear the bit in the ROM byte rom_byte_number
-				// with mask rom_byte_mask
-				if (search_direction == 1)
-					ROM_NO[rom_byte_number] |= rom_byte_mask;
-				else
-					ROM_NO[rom_byte_number] &= ~rom_byte_mask;
-				// serial number search direction write bit
-				sendrecivBit(search_direction);
-				//usleep(50);
-
-				// increment the byte counter id_bit_number
-				// and shift the mask rom_byte_mask
-				id_bit_number++;
-				rom_byte_mask <<= 1;
-
-				// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
-				if (rom_byte_mask == 0) {
-					docrc8(ROM_NO[rom_byte_number]);  // accumulate the CRC
-					rom_byte_number++;
-					rom_byte_mask = 1;
-				}
-			}
-		}
-		while(rom_byte_number < 8);  // loop until through all ROM bytes 0-7
-		// if the search was successful then
-		if (!((id_bit_number < 65) || (crc8 != 0))) {
-			// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
-			LastDiscrepancy = last_zero;
-			// check for last device
-			if (LastDiscrepancy == 0)
-			LastDeviceFlag = TRUE;
-			search_result = TRUE;
-		} else {
-			log->set(OWLOG_WARNING,"CRC Error on Search Rom");
-		}
-	}
-
-		// if no device found then reset counters so next 'search' will be like a first
-	if (!search_result || !ROM_NO[0]) {
-		LastDiscrepancy = 0;
-		LastDeviceFlag = FALSE;
-		LastFamilyDiscrepancy = 0;
-		search_result = FALSE;
-	}
-	Free();
-	return search_result;
-	
-
-}
-void owInterface::Clean() {
-	for (owDevice* dev :devices) {
-		delete dev;
-	}
-	devices.clear();
-	device_nums.clear();
-	devices_changed=1;
-}
-
-int owInterface::Find() {
-	int rslt,i,cnt=0;
-	std::vector<snum_t> found;
-	for (int k=0;k<maxrepeat;k++) {
-		cnt=0;
-		log->clear();
-		found.clear();
-		rslt = owFirst();
-		if (log->last()>=OWLOG_WARNING) continue;
-		while (rslt){
-			snum_t snum;
-			// print device found
-			for (i = 7; i >= 0; i--)
-				snum.byte[i]=ROM_NO[i];
-				//printf("%02X", ROM_NO[i]);
-				//printf("  %d\n",++cnt);
-			found.push_back(snum);
-			cnt++;
-			log->clear();
-			rslt = owNext();
-			if (log->last()>=OWLOG_WARNING) {rslt=-1;break;}
-		}
-		if (rslt==0) break;
-	
-	}
-	if (log->last()>=OWLOG_WARNING) { 
-		log->set(OWLOG_ERROR,"To much Errors while search rom"); 
-		//Alles so lassen wie es ist?		
-		return 0;
-	}
-	for(snum_t snum:found) {
-		int snum_found=0;
-		//Device schon forhanden?
-		for(snum_t d : device_nums) {
-			if (snum.num==d.num) {snum_found=1;break;}
-		}
-		//nein, dann anlegen.
-		if (!snum_found) {
-			log->set(OWLOG_INFO,"new dev %llx\n",snum.num);
-			devices_changed=1;
-			device_nums.push_back(snum);
-			owDevice *d=NULL;
-			
-			switch (snum.byte[0]) {
-				case 0x28:d=new owDeviceDS18B20(this,snum);break;
-				case 0x26:d=new owDeviceDS2438(this,snum);break;
-				case 0x20:d=new owDeviceDS2450(this,snum);break;
-				case 0x1D:d=new owDeviceDS2423(this,snum);break;
-				default:d=new owDevice(this,snum);
-			}
-			devices.push_back(d);
-			if (d!=NULL)	{d->readConfig();}
-		}
-	}
-	//Pruefe nach nicht mehr vorhandenen devices
-	int dpos=0;
-	for(snum_t d:device_nums) {
-		int snum_found=0;
-		for(snum_t fd:found) {
-			if (fd.num==d.num) {snum_found=1;break;}
-		}
-		//Device nicht gefunden, vieleicht nur Fehler?
-		if (!snum_found) {
-			devices[dpos]->lastfound++;
-			log->set(OWLOG_INFO,"%llx not found %i times \n",device_nums[dpos].num,devices[dpos]->lastfound); 
-			
-			if (devices[dpos]->lastfound>2) {
-
-				log->set(OWLOG_INFO,"del device %llx (pos %i)\n",device_nums[dpos].num,dpos);
-			
-				devices_changed=1;
-				delete devices[dpos];
-				device_nums.erase(device_nums.begin()+dpos);
-				devices.erase(devices.begin()+dpos);	
-			//printf("new length %i\n",devices.size());
-				dpos--;
-			} 
-
-		} else {
-			devices[dpos]->lastfound=0;
-		}
-		dpos++;
-		
-	}	
-	return cnt;	
-}
-
-int owInterface::MatchRom(snum_t snum) {
-	Reset();
-	sendrecivByte(0x55);
-	usleep(20);
-	for(int i=0;i<8;i++) {
-		sendrecivByte(snum.byte[i]); 
-		usleep(20);
-	}
-	if (log->last()>OWLOG_WARNING) return 0;
-	return 1;
-}
-int owInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
-	int i=0;
-	data->resize(scount);
-	for(uint8_t v:*data) {
-		(*data)[i]=sendrecivByte(v);i++;
-		usleep(20);
-	}
-	for(i=0;i<rcount;i++) {
-		data->push_back(sendrecivByte(0xFF));
-		usleep(20);
-		
-	}
-	return 0;
-}
-
+// Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the
+//    distribution.
+//  * All advertising materials mentioning features or use of this
+//    software must display the following acknowledgement: This product
+//    includes software developed by tm3d.de and its contributors.
+//  * Neither the name of tm3d.de nor the names of its contributors may
+//    be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#include "owInterface.h"
+#ifdef LINUX
+#include <unistd.h>
+#endif
+#include <math.h>
+#include "hexfile.h"
+
+
+#ifdef WIN
+void usleep(__int64 usec)
+{
+	HANDLE timer;
+	LARGE_INTEGER ft;
+
+	ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time
+
+	timer = CreateWaitableTimer(NULL, TRUE, NULL);
+	SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
+	WaitForSingleObject(timer, INFINITE);
+	CloseHandle(timer);
+}
+#endif
+
+
+static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
+static unsigned char owi_dscrc_table[] = {
+        0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
+      157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
+       35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
+      190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
+       70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
+      219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
+      101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
+      248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
+      140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
+       17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
+      175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
+       50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
+      202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
+       87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
+      233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
+      116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
+
+      
+uint8_t owInterface::docrc8(uint8_t value) {
+   // See Application Note 27
+   
+   // TEST BUILD
+   crc8 = owi_dscrc_table[crc8 ^ value];
+   return crc8;
+}
+ 
+uint16_t owInterface::docrc16(uint16_t cdata) {
+   cdata = (cdata ^ (crc16 & 0xff)) & 0xff;
+   crc16 >>= 8;
+
+   if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4])
+     crc16 ^= 0xc001;
+
+   cdata <<= 6;
+   crc16   ^= cdata;
+   cdata <<= 1;
+   crc16   ^= cdata;
+
+   return crc16;
+		
+	
+}
+
+uint8_t owInterface::calcCRC8(std::vector<uint8_t> data) {
+	 crc8 = 0;
+	  for(uint8_t v: data) 
+			docrc8(v);
+	return crc8; //0 bei erfolg oder crc wenn crc nicht babei
+}
+
+uint16_t owInterface::calcCRC16(std::vector<uint8_t> data) {
+	crc16=0;
+	for(uint8_t v:data) {
+		docrc16(v);
+	}
+	return crc16;
+}
+
+int owInterface::testCRC16(std::vector<uint8_t> data)  {
+	return calcCRC16(data)==0xB001;
+}
+		
+void owInterface::resetFlasher() { // go back from Bootloader
+	std::vector<uint8_t> data;
+	data.push_back(0x89);
+	Wait_Free();
+	snum_t snum;
+	snum.num=0xfa55aa55aa55aaa3;
+	MatchRom(snum);
+	if (log->last()==OWLOG_ERROR) {Free(); return;}
+	Communicate(&data, 1, 0);
+	
+	Free();
+	if (log->last()==OWLOG_ERROR) return;
+	usleep(50);	
+}
+
+void owInterface::resetID() {
+	std::vector<uint8_t> data;
+	data.push_back(0x8B);
+	Wait_Free();
+	snum_t snum;
+	snum.num=0xfa55aa55aa55aaa3;
+	MatchRom(snum);
+	if (log->last()==OWLOG_ERROR) {Free(); return;}
+	Communicate(&data, 1, 0);
+	Free();
+}
+
+int owInterface::programmPage(int pagenr, std::vector<uint8_t> page, int pagesize) {
+	snum_t snum;
+	snum.num=0xfa55aa55aa55aaa3;
+//	printf("programm page %i",pagenr);
+	
+	
+	int diff = pagesize - page.size();
+	if (diff>0) {
+		for (int i = 0; i < (diff); i++) page.push_back(0xFF);
+	}
+	std::vector<uint8_t> cl;
+	std::vector<uint8_t> clb; //backup 
+	cl.push_back(0x0F);  //code for Flashing
+	cl.push_back((pagenr*pagesize) & 0xFF); //adress in byte
+	cl.push_back((pagenr*pagesize) >> 8);
+	cl.insert(cl.end(),page.begin(),page.end()); //page
+	clb=cl;		//make backup
+	Wait_Free();
+	MatchRom(snum); 
+	if (log->last()==OWLOG_ERROR) {Free();return -3;}
+	Communicate(&cl, 3+pagesize, 0); //send (resive page)
+	Free();
+	if (log->last()==OWLOG_ERROR) return -3;
+	int err=0;
+	for(int k=0;k<maxrepeat;k++) { //repeat for readback error 
+		cl.clear();
+		cl.push_back(0xAA); //code for readback scratchpad
+		Wait_Free();
+		MatchRom(snum);
+		if (log->last()==OWLOG_ERROR) {Free();return -3;}
+		Communicate(&cl, 1, 2+pagesize); // read back scratchpad
+		Free();
+		if (log->last()==OWLOG_ERROR) return -3;
+		err=0;
+		for (int i = 0; i < pagesize+2; i++) {
+			if (clb[i + 1] != cl[i + 1]) {  //test
+				usleep(50000);
+				err=1;
+				break;
+			}
+		}
+		if (err==0) break;
+	}
+	if (err==1) {
+		usleep(50000);
+		return -1;  //error in scratchpad
+	}
+	cl.clear();
+	cl.push_back(0x55);//Programm
+	Wait_Free();
+	MatchRom(snum);
+	if (log->last()==OWLOG_ERROR) {Free();return -3;}
+	Communicate(&cl, 1, 0);
+	Free();
+	if (log->last()==OWLOG_ERROR) return -3;
+	usleep(50000);
+	cl.clear();
+	cl.push_back(0xB8);//recal programm memory to scratchpad
+	cl.push_back((pagenr*pagesize) & 0xFF);
+	cl.push_back((pagenr*pagesize) >> 8);
+	Wait_Free();
+	MatchRom(snum);
+	if (log->last()==OWLOG_ERROR) {Free();return -3;}
+	Communicate(&cl, 3, 0); //Copy programm memory to scratch
+	Free();
+	if (log->last()==OWLOG_ERROR) return -3;
+	usleep(50000);
+	
+	for(int k=0;k<maxrepeat;k++) { //repead for reading scratch error
+		cl.clear();
+		cl.push_back(0xAA);
+		Wait_Free();
+		MatchRom(snum);
+		if (log->last()==OWLOG_ERROR) {Free();return -3;}
+		Communicate(&cl, 1, 2 + pagesize); //Reread scratch
+		Free();
+		if (log->last()==OWLOG_ERROR) return -3;
+		err=0;
+		for (int i = 0; i < pagesize + 2; i++) {
+			if (cl[i + 1] != clb[i + 1]) {
+				usleep(50000);
+				err=1;
+				break;
+			}
+		}
+		if (err==0) break;
+	}
+	if (err==1) {
+		usleep(50000);
+		return -2;
+	}
+
+
+	return 0;
+}
+
+
+int owInterface::flashHEXFile(std::string filename,snum_t dev,int resetid,int progress) {
+	log->set(OWLOG_INFO,"Open Hex-File: %s",filename.c_str());
+	hexFile *hf=new hexFile(filename);
+	if (hf->lastError==1) {log->set(OWLOG_ERROR,"CRC Error in HEX-File %s",filename.c_str());return -1;}
+	if (hf->lastError==2) {log->set(OWLOG_ERROR,"Error interpreting  HEX-File %s",filename.c_str());return -2;}
+	if (hf->lastError==3) {log->set(OWLOG_ERROR,"File could not be opened: %s",filename.c_str());return -3;}
+	unsigned int blcount=hf->getBlockCount(64);
+	if (blcount>118) {
+		log->set(OWLOG_ERROR,"Code to big, max 7552 Byte allowed (118 Pages). Code has %i pages!",blcount);
+		return -5;
+	}
+	log->set(OWLOG_INFO,"Try to start Bootloader on device %llX",dev.num);
+	int r=maxrepeat+1;
+	int found;
+	do {
+		log->clear();
+		std::vector<uint8_t> data;
+		MatchRom(dev);
+		data.push_back(0x88);
+		Communicate(&data, 1, 0);
+		MatchRom(dev);
+		Communicate(&data, 1, 0);
+		MatchRom(dev);
+		Communicate(&data, 1, 0);
+#ifdef LINUX
+		sleep(3);
+#endif
+#ifdef WIN
+		Sleep(3000);
+#endif
+		log->set(OWLOG_INFO,"Search for Bootloader...");
+		log->setLogLevel(OWLOG_WARNING);
+		Find();
+		log->setLogLevel(OWLOG_INFO);
+		found=0;
+		for (owDevice* dev :devices) {
+			if (dev->getNum().num==0xfa55aa55aa55aaa3) {
+				found=1;
+				break;
+			}	
+	 	}
+	 	if (found==0) log->set(OWLOG_WARNING,"Bootloader not found");
+	 	r--;
+	}	while ((found==0)&&(r>0));
+	if (r==0) {
+		log->set(OWLOG_ERROR,"Can not start Bootloader on this device %llX",dev.num);
+		return -4;
+	}
+	log->set(OWLOG_INFO,"Start Programm %i Pages",blcount);
+	int rp=0;
+	int er=0;
+	unsigned int i =0;
+	for ( i= 0; i < blcount; i++) {
+		std::vector<uint8_t> blk = hf->getBlock(i*64, 64);
+		int errc = maxrepeat*5;
+		while (errc != 0) {
+			log->clear();
+			if (programmPage(i, blk, 64) >= 0) {
+				if (progress) {printf("#");fflush(stdout);} 
+				break;
+			}
+			
+			errc -= 1;
+			rp++;
+			if (progress) {printf("\033[1;31m#\033[0m");fflush(stdout);} //printf("\033[1;33m%s\033[0m\n",s);
+					
+		}
+      if (errc == 0) { er++; break; }
+	}
+	if (progress) printf("\n");
+	if (er != 0) {
+		log->set(OWLOG_ERROR,"ERROR Writing Program Memory!!!");
+		if (i==0) {
+			log->set(OWLOG_ERROR,"If Fuse SELFPRGEN enabled?");
+		} else
+			log->set(OWLOG_ERROR,"Maybe 1-Wire Connection is verry bad!");
+	} else {
+		if (resetid) {
+			log->set(OWLOG_INFO,"Set 1-Wire ID to ID in hexfile...",blcount); 
+			resetID();
+#ifdef LINUX
+			sleep(3);
+#endif
+#ifdef WIN
+			Sleep(3000);
+#endif
+			resetID();	
+#ifdef LINUX
+			sleep(3);
+#endif
+#ifdef WIN
+			Sleep(3000);
+#endif
+		}
+	}	
+	
+	log->set(OWLOG_INFO,"Back from bootloader to normal device...",blcount); 
+	
+	
+	resetFlasher();
+#ifdef LINUX
+	sleep(1);	
+#endif
+#ifdef WIN
+	Sleep(1000);
+#endif
+	resetFlasher();
+#ifdef LINUX
+	sleep(3);
+#endif
+#ifdef WIN
+	Sleep(3000);
+#endif
+
+	Find();
+	
+	return 1;
+		
+}
+
+
+int owInterface::owSearch() {
+	int id_bit_number;
+	int last_zero, rom_byte_number, search_result;
+	int id_bit, cmp_id_bit;
+	unsigned char rom_byte_mask, search_direction;
+
+	// initialize for search
+	id_bit_number = 1;
+	last_zero = 0;
+	rom_byte_number = 0;
+	rom_byte_mask = 1;
+	search_result = 0;
+	crc8 = 0;
+
+	// if the last call was not the last one
+	if (!LastDeviceFlag) {
+		// 1-Wire reset
+		Wait_Free();
+		if (!Reset()) {
+        // reset the search
+			LastDiscrepancy = 0;
+			LastDeviceFlag = FALSE;
+			LastFamilyDiscrepancy = 0;
+			Free();
+			return FALSE;
+		}
+		if (log->last()==OWLOG_ERROR) return -3;
+		// issue the search command 
+		sendrecivByte(0xF0);  
+		if (log->last()==OWLOG_ERROR) return -3;
+
+		// loop to do the search
+		do {
+			// read a bit and its complement
+			id_bit = sendrecivBit(1);
+			cmp_id_bit = sendrecivBit(1);
+			// check for no devices on 1-wire
+			if ((id_bit == 1) && (cmp_id_bit == 1))
+				break;
+			else {
+				// all devices coupled have 0 or 1
+				if (id_bit != cmp_id_bit)
+					search_direction = id_bit;  // bit write value for search
+				else  {
+					// if this discrepancy if before the Last Discrepancy
+					// on a previous next then pick the same as last time
+					if (id_bit_number < LastDiscrepancy)
+						search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
+					else
+						// if equal to last pick 1, if not then pick 0
+						search_direction = (id_bit_number == LastDiscrepancy);
+
+					// if 0 was picked then record its position in LastZero
+					if (search_direction == 0) {
+						last_zero = id_bit_number;
+						// check for Last discrepancy in family
+						if (last_zero < 9)
+							LastFamilyDiscrepancy = last_zero;
+					}
+				}
+				// set or clear the bit in the ROM byte rom_byte_number
+				// with mask rom_byte_mask
+				if (search_direction == 1)
+					ROM_NO[rom_byte_number] |= rom_byte_mask;
+				else
+					ROM_NO[rom_byte_number] &= ~rom_byte_mask;
+				// serial number search direction write bit
+				sendrecivBit(search_direction);
+				//usleep(50);
+
+				// increment the byte counter id_bit_number
+				// and shift the mask rom_byte_mask
+				id_bit_number++;
+				rom_byte_mask <<= 1;
+
+				// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
+				if (rom_byte_mask == 0) {
+					docrc8(ROM_NO[rom_byte_number]);  // accumulate the CRC
+					rom_byte_number++;
+					rom_byte_mask = 1;
+				}
+			}
+		}
+		while(rom_byte_number < 8);  // loop until through all ROM bytes 0-7
+		// if the search was successful then
+		if (!((id_bit_number < 65) || (crc8 != 0))) {
+			// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
+			LastDiscrepancy = last_zero;
+			// check for last device
+			if (LastDiscrepancy == 0)
+			LastDeviceFlag = TRUE;
+			search_result = TRUE;
+		} else {
+			log->set(OWLOG_WARNING,"CRC Error on Search Rom");
+		}
+	}
+
+		// if no device found then reset counters so next 'search' will be like a first
+	if (!search_result || !ROM_NO[0]) {
+		LastDiscrepancy = 0;
+		LastDeviceFlag = FALSE;
+		LastFamilyDiscrepancy = 0;
+		search_result = FALSE;
+	}
+	Free();
+	return search_result;
+	
+
+}
+void owInterface::Clean() {
+	for (owDevice* dev :devices) {
+		delete dev;
+	}
+	devices.clear();
+	device_nums.clear();
+	devices_changed=1;
+}
+
+int owInterface::Find() {
+	int rslt,i,cnt=0;
+	std::vector<snum_t> found;
+	for (int k=0;k<maxrepeat;k++) {
+		cnt=0;
+		log->clear();
+		found.clear();
+		rslt = owFirst();
+		if (log->last()>=OWLOG_WARNING) continue;
+		while (rslt){
+			snum_t snum;
+			// print device found
+			for (i = 7; i >= 0; i--)
+				snum.byte[i]=ROM_NO[i];
+				//printf("%02X", ROM_NO[i]);
+				//printf("  %d\n",++cnt);
+			found.push_back(snum);
+			cnt++;
+			log->clear();
+			rslt = owNext();
+			if (log->last()>=OWLOG_WARNING) {rslt=-1;break;}
+		}
+		if (rslt==0) break;
+	
+	}
+	if (log->last()>=OWLOG_WARNING) { 
+		log->set(OWLOG_ERROR,"To much Errors while search rom"); 
+		//Alles so lassen wie es ist?		
+		return 0;
+	}
+	for(snum_t snum:found) {
+		int snum_found=0;
+		//Device schon forhanden?
+		for(snum_t d : device_nums) {
+			if (snum.num==d.num) {snum_found=1;break;}
+		}
+		//nein, dann anlegen.
+		if (!snum_found) {
+			log->set(OWLOG_INFO,"new dev %llx\n",snum.num);
+			devices_changed=1;
+			device_nums.push_back(snum);
+			owDevice *d=NULL;
+			
+			switch (snum.byte[0]) {
+				case 0x28:d=new owDeviceDS18B20(this,snum);break;
+				case 0x26:d=new owDeviceDS2438(this,snum);break;
+				case 0x20:d=new owDeviceDS2450(this,snum);break;
+				case 0x1D:d=new owDeviceDS2423(this,snum);break;
+				default:d=new owDevice(this,snum);
+			}
+			devices.push_back(d);
+			if (d!=NULL)	{d->readConfig();}
+		}
+	}
+	//Pruefe nach nicht mehr vorhandenen devices
+	int dpos=0;
+	for(snum_t d:device_nums) {
+		int snum_found=0;
+		for(snum_t fd:found) {
+			if (fd.num==d.num) {snum_found=1;break;}
+		}
+		//Device nicht gefunden, vieleicht nur Fehler?
+		if (!snum_found) {
+			devices[dpos]->lastfound++;
+			log->set(OWLOG_INFO,"%llx not found %i times \n",device_nums[dpos].num,devices[dpos]->lastfound); 
+			
+			if (devices[dpos]->lastfound>2) {
+
+				log->set(OWLOG_INFO,"del device %llx (pos %i)\n",device_nums[dpos].num,dpos);
+			
+				devices_changed=1;
+				delete devices[dpos];
+				device_nums.erase(device_nums.begin()+dpos);
+				devices.erase(devices.begin()+dpos);	
+			//printf("new length %i\n",devices.size());
+				dpos--;
+			} 
+
+		} else {
+			devices[dpos]->lastfound=0;
+		}
+		dpos++;
+		
+	}	
+	return cnt;	
+}
+
+int owInterface::MatchRom(snum_t snum) {
+	Reset();
+/*	sendrecivByte(0x55);
+	usleep(20);
+	for(int i=0;i<8;i++) {
+		sendrecivByte(snum.byte[i]); 
+		usleep(20);
+	}
+	if (log->last()>OWLOG_WARNING) return 0;*/
+	std::vector<uint8_t> cl;
+	cl.push_back(0x55);  //code for Flashing
+	for (int i = 0; i<8; i++) {
+		cl.push_back(snum.byte[i]);
+	}
+	Communicate(&cl, 9, 0);
+
+	return 1;
+}
+int owInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
+	int i=0;
+	data->resize(scount);
+	for(uint8_t v:*data) {
+		(*data)[i]=sendrecivByte(v);i++;
+		usleep(20);
+	}
+	for(i=0;i<rcount;i++) {
+		data->push_back(sendrecivByte(0xFF));
+		usleep(20);
+		
+	}
+	return 0;
+}
+
diff --git a/src/owInterface.h b/src/owInterface.h
index 952f3dc..0370d03 100755
--- a/src/owInterface.h
+++ b/src/owInterface.h
@@ -34,12 +34,28 @@
 #ifndef __OWINTERFACES_H_
 #define __OWINTERFACES_H_
 
+#if defined(WIN) || defined(LINUX)
+#else
+#if defined(_WINDOWS) || defined(__WINDOWS__) || defined(_WIN32) || defined(WIN32)
+#define WIN
+#else
+#define LINUX
+#endif
+#endif
+
+
 #include <vector>
 #include <stdint.h>
 #include <string>
+#ifdef LINUX
 #include <termios.h>
+#endif
 #include <stdarg.h>
 
+#ifdef WIN
+#include <Windows.h>
+
+#endif
 
 class owDevice;
 class owDeviceConfig;
@@ -48,7 +64,7 @@ class owDeviceConfig;
 #if defined(_WINDOWS) || defined(__WINDOWS__) || defined(_WIN32) || defined(WIN32)
    #define USE_WINDOWS_TIME 1
    #include <windows.h>
-   #include "win32/usb.h" // libusb header
+   //#include "win32/usb.h" // libusb header
 #else
    #define USE_WINDOWS_TIME 0
    #include <time.h>
@@ -84,7 +100,12 @@ public:
 		va_list arg;
 		int done;
 		va_start (arg, format);
+#ifdef LINUX
 		done = vsprintf (s, format, arg);
+#endif
+#ifdef WIN
+		done = vsprintf_s(s,300, format, arg);
+#endif
 		va_end (arg);
 		logtext=s;
 		level=llevel;
diff --git a/src/owTMEXWIN.cpp b/src/owTMEXWIN.cpp
new file mode 100644
index 0000000..6905165
--- /dev/null
+++ b/src/owTMEXWIN.cpp
@@ -0,0 +1,122 @@
+// Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the
+//    distribution.
+//  * All advertising materials mentioning features or use of this
+//    software must display the following acknowledgement: This product
+//    includes software developed by tm3d.de and its contributors.
+//  * Neither the name of tm3d.de nor the names of its contributors may
+//    be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+	
+#include <ownet.h>
+
+#include <atlstr.h>
+
+#include <stdio.h>
+#include "owTMEXWIN.h"
+
+
+int owTMEXWIN::InitAdapter(std::string s) {
+	// resu = owi.InitAdapter("{1,6}");
+
+	//  int resu = owi.InitAdapter("{4,5}");
+	char hs[100];
+	sprintf_s(hs, 100, "%s", s.c_str());
+	portnum = owAcquireEx(hs);
+	if (portnum > -1) {
+		owSpeed(portnum, 2);
+		return 1;
+	}
+	return 0;	
+}
+
+
+int owTMEXWIN::owFirst() {
+	uchar SNum[8];
+	int res=owFirst_(portnum, TRUE, FALSE);
+	if (res) {
+		owSerialNum(portnum, &SNum[0], TRUE);
+		for (int i = 0; i<8; i++) ROM_NO[i] = SNum[i];
+	}
+	return res;
+
+}
+int owTMEXWIN::owNext() {
+	uchar SNum[8];
+	int res = owNext_(portnum, TRUE, FALSE);
+	if (res) {
+		owSerialNum(portnum, &SNum[0], TRUE);
+		for (int i = 0; i<8; i++) ROM_NO[i] = SNum[i];
+	}
+	return res;
+
+}
+
+
+void owTMEXWIN::ReleaseAdapter() {
+	owRelease(portnum);
+}
+
+
+int owTMEXWIN::Reset() {
+	return owTouchReset(portnum);
+}
+
+int owTMEXWIN::MatchRom(snum_t snum) {
+	owSerialNum(portnum, snum.byte, FALSE);
+	return owAccess(portnum);
+}
+uint8_t owTMEXWIN::sendrecivByte(uint8_t byte) {
+	return owTouchByte(portnum, byte);
+   			
+}
+uint8_t owTMEXWIN::sendrecivBit(uint8_t bit) {
+	return owTouchBit(portnum, bit);
+	
+}
+
+int owTMEXWIN::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
+	int i = 0;
+	uint8_t buf[400];
+	data->resize(scount);
+	for (uint8_t v : *data) {
+		buf[i++] = v;
+	}
+	for (int j = 0; j < rcount; j++) {
+		buf[i++] = 0xFF;
+	}
+	int ret = owBlock(portnum, FALSE, buf, scount + rcount);
+	if (ret) {
+		for (int j = 0; j < rcount; j++) {
+			data->push_back(buf[scount + j]);
+		}
+	}
+	return ret;
+
+}
+	
diff --git a/src/owTMEXWIN.h b/src/owTMEXWIN.h
new file mode 100644
index 0000000..716766f
--- /dev/null
+++ b/src/owTMEXWIN.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the
+//    distribution.
+//  * All advertising materials mentioning features or use of this
+//    software must display the following acknowledgement: This product
+//    includes software developed by tm3d.de and its contributors.
+//  * Neither the name of tm3d.de nor the names of its contributors may
+//    be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#ifndef __OWTMEXWIN_H_
+#define __OWTMEXWIN_H_
+
+#include "owInterface.h"
+
+class owTMEXWIN :public owInterface {
+protected: 
+	int portnum;
+	int com_init;
+public:
+	owTMEXWIN():owInterface() {
+		portnum=-1;
+		com_init=0;
+	}
+	virtual int InitAdapter(std::string s);
+	virtual int InitAdapter(uint8_t) { return 0; };
+	virtual int Reset();
+	virtual uint8_t sendrecivBit(uint8_t bit);
+	virtual uint8_t sendrecivByte(uint8_t byte);
+	virtual void ReleaseAdapter();
+	virtual int MatchRom(snum_t snum);
+	virtual int owFirst();
+	virtual int owNext();
+	virtual int Communicate(std::vector<uint8_t> *data, int scount, int rcount);
+
+
+	
+};
+
+#endif
diff --git a/src/owTools.h b/src/owTools.h
index 68b5b3a..b4a942c 100755
--- a/src/owTools.h
+++ b/src/owTools.h
@@ -35,9 +35,23 @@
 #ifndef __OWTOOLS_H_
 #define __OWTOOLS_H_
 
+#if defined(_WINDOWS) || defined(__WINDOWS__) || defined(_WIN32) || defined(WIN32)
+#define WIN
+#else
+#define LINUX
+#endif
+
+
+
 #include "owInterface.h"
+#include "owARDUINOInterface.h"
+#ifdef WIN
+#include "owTMEXWIN.h"
+#endif
+
+#ifdef LINUX
 #include "owUSBInterface.h"
 #include "owCOMInterface.h"
 #include "owPiGPioInterface.h"
-#include "owARDUINOInterface.h"
+#endif
 #endif
diff --git a/windows/owTools/crcutil.cpp b/windows/owTools/crcutil.cpp
new file mode 100644
index 0000000..cf1bef8
--- /dev/null
+++ b/windows/owTools/crcutil.cpp
@@ -0,0 +1,119 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//--------------------------------------------------------------------------
+//
+//  crcutil.c - Keeps track of the CRC for 16 and 8 bit operations
+//  version 2.00
+
+// Include files
+#include "ownet.h"
+
+// Local global variables
+ushort utilcrc16[MAX_PORTNUM];
+uchar utilcrc8[MAX_PORTNUM];
+static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
+static uchar dscrc_table[] = {
+        0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
+      157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
+       35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
+      190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
+       70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
+      219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
+      101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
+      248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
+      140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
+       17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
+      175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
+       50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
+      202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
+       87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
+      233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
+      116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
+
+//--------------------------------------------------------------------------
+// Reset crc16 to the value passed in
+//
+// 'reset' - data to set crc16 to.
+//
+void setcrc16(int portnum, ushort reset)
+{
+   utilcrc16[portnum&0x0FF] = reset;
+   return;
+}
+
+//--------------------------------------------------------------------------
+// Reset crc8 to the value passed in
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number is provided to
+//              indicate the symbolic port number.
+// 'reset'    - data to set crc8 to
+//
+void setcrc8(int portnum, uchar reset)
+{
+   utilcrc8[portnum&0x0FF] = reset;
+   return;
+}
+
+//--------------------------------------------------------------------------
+// Calculate a new CRC16 from the input data short.  Return the current
+// CRC16 and also update the global variable CRC16.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number is provided to
+//              indicate the symbolic port number.
+// 'data'     - data to perform a CRC16 on
+//
+// Returns: the current CRC16
+//
+ushort docrc16(int portnum, ushort cdata)
+{
+   cdata = (cdata ^ (utilcrc16[portnum&0x0FF] & 0xff)) & 0xff;
+   utilcrc16[portnum&0x0FF] >>= 8;
+
+   if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4])
+     utilcrc16[portnum&0x0FF] ^= 0xc001;
+
+   cdata <<= 6;
+   utilcrc16[portnum&0x0FF]   ^= cdata;
+   cdata <<= 1;
+   utilcrc16[portnum&0x0FF]   ^= cdata;
+
+   return utilcrc16[portnum&0x0FF];
+}
+
+//--------------------------------------------------------------------------
+// Update the Dallas Semiconductor One Wire CRC (utilcrc8) from the global
+// variable utilcrc8 and the argument.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number is provided to
+//              indicate the symbolic port number.
+// 'x'        - data byte to calculate the 8 bit crc from
+//
+// Returns: the updated utilcrc8.
+//
+uchar docrc8(int portnum, uchar x)
+{
+   utilcrc8[portnum&0x0FF] = dscrc_table[utilcrc8[portnum&0x0FF] ^ x];
+   return utilcrc8[portnum&0x0FF];
+}
diff --git a/windows/owTools/ibfs32.lib b/windows/owTools/ibfs32.lib
new file mode 100644
index 0000000..a856f6e
Binary files /dev/null and b/windows/owTools/ibfs32.lib differ
diff --git a/windows/owTools/owTools.sln b/windows/owTools/owTools.sln
new file mode 100644
index 0000000..e1f65b8
--- /dev/null
+++ b/windows/owTools/owTools.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "owTools", "owTools.vcxproj", "{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Debug|x64.ActiveCfg = Debug|x64
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Debug|x64.Build.0 = Debug|x64
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Debug|x86.ActiveCfg = Debug|Win32
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Debug|x86.Build.0 = Debug|Win32
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Release|x64.ActiveCfg = Release|x64
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Release|x64.Build.0 = Release|x64
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Release|x86.ActiveCfg = Release|Win32
+		{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/windows/owTools/owTools.vcxproj b/windows/owTools/owTools.vcxproj
new file mode 100644
index 0000000..6987402
--- /dev/null
+++ b/windows/owTools/owTools.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{7BC76CAE-ECA9-4C9B-9DE0-3F8449F815B4}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>owTools</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IgnoreImportLibrary>true</IgnoreImportLibrary>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <AdditionalIncludeDirectories>.\windows\owTools;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <AdditionalIncludeDirectories>.\windows\owTools;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\hexfile.h" />
+    <ClInclude Include="..\..\src\owARDUINOInterface.h" />
+    <ClInclude Include="..\..\src\owDeviceConfig.h" />
+    <ClInclude Include="..\..\src\owInterface.h" />
+    <ClInclude Include="..\..\src\owTMEXWIN.h" />
+    <ClInclude Include="..\..\src\owTools.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\hexfile.cpp" />
+    <ClCompile Include="..\..\src\main.cpp" />
+    <ClCompile Include="..\..\src\owARDUINOInterface.cpp" />
+    <ClCompile Include="..\..\src\owDevice.cpp" />
+    <ClCompile Include="..\..\src\owDeviceConfig.cpp" />
+    <ClCompile Include="..\..\src\owInterface.cpp" />
+    <ClCompile Include="..\..\src\owTMEXWIN.cpp" />
+    <ClCompile Include="crcutil.cpp" />
+    <ClCompile Include="owerr.cpp" />
+    <ClCompile Include="tmexlnk.cpp" />
+    <ClCompile Include="tmexnet.cpp" />
+    <ClCompile Include="tmexses.cpp" />
+    <ClCompile Include="tmextran.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <Library Include="ibfs32.lib" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/windows/owTools/owerr.cpp b/windows/owTools/owerr.cpp
new file mode 100644
index 0000000..76c5176
--- /dev/null
+++ b/windows/owTools/owerr.cpp
@@ -0,0 +1,348 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// owerr.c - Library functions for error handling with 1-Wire library
+//
+// Version: 1.00
+//
+
+#include <string.h>
+#ifndef _WIN32_WCE
+#include <stdio.h>
+#endif
+#ifdef _WIN64
+#include <stdio.h>
+#endif
+#include "ownet.h"
+
+#ifndef SIZE_OWERROR_STACK
+   #ifdef SMALL_MEMORY_TARGET
+      //for small memory, only hole 1 error
+      #define SIZE_OWERROR_STACK 1
+   #else
+      #define SIZE_OWERROR_STACK 10
+   #endif
+#endif
+
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+// Error Struct for holding error information.
+// In DEBUG, this will also hold the line number and filename.
+typedef struct
+{
+   int owErrorNum;
+#ifdef DEBUG
+   int lineno;
+   char *filename;
+#endif
+} owErrorStruct;
+
+// Ring-buffer used for stack.
+// In case of overflow, deepest error is over-written.
+static owErrorStruct owErrorStack[SIZE_OWERROR_STACK];
+
+// Stack pointer to top-most error.
+static int owErrorPointer = 0;
+
+
+//---------------------------------------------------------------------------
+// Functions Definitions
+//---------------------------------------------------------------------------
+int owGetErrorNum(void);
+void owClearError(void);
+int owHasErrors(void);
+#ifdef DEBUG
+   void owRaiseError(int,int,char*);
+#else
+   void owRaiseError(int);
+#endif
+#ifndef SMALL_MEMORY_TARGET
+   void owPrintErrorMsg(FILE *);
+   void owPrintErrorMsgStd();
+   char *owGetErrorMsg(int);
+#endif
+
+
+//--------------------------------------------------------------------------
+// The 'owGetErroNum' returns the error code of the top-most error on the
+// error stack.  NOTE: This function has the side effect of popping the
+// current error off the stack.  All successive calls to 'owGetErrorNum'
+// will further clear the error stack.
+//
+// For list of error codes, see 'ownet.h'
+//
+// Returns:   int :  The error code of the top-most error on the stack
+//
+int owGetErrorNum(void)
+{
+   int i = owErrorStack[ owErrorPointer ].owErrorNum;
+   owErrorStack[ owErrorPointer ].owErrorNum = 0;
+   if(!owErrorPointer)
+      owErrorPointer = SIZE_OWERROR_STACK - 1;
+   else
+      owErrorPointer = (owErrorPointer - 1);
+   return i;
+}
+
+//--------------------------------------------------------------------------
+// The 'owClearError' clears all the errors.
+//
+void owClearError(void)
+{
+   owErrorStack[ owErrorPointer ].owErrorNum = 0;
+}
+
+//--------------------------------------------------------------------------
+// The 'owHasErrors' is a boolean test function which tests whether or not
+// a valid error is waiting on the stack.
+//
+// Returns:   TRUE (1) : When there are errors on the stack.
+//            FALSE (0): When stack's errors are set to 0, or NO_ERROR_SET.
+//
+int owHasErrors(void)
+{
+   if(owErrorStack[ owErrorPointer ].owErrorNum)
+      return 1; //TRUE
+   else
+      return 0; //FALSE
+}
+
+#ifdef DEBUG
+   //--------------------------------------------------------------------------
+   // The 'owRaiseError' is the method for raising an error onto the error
+   // stack.
+   //
+   // Arguments:  int err - the error code you wish to raise.
+   //             int lineno - DEBUG only - the line number where it was raised
+   //             char* filename - DEBUG only - the file name where it occured.
+   //
+   void owRaiseError(int err, int lineno, char* filename)
+   {
+      owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK;
+      owErrorStack[ owErrorPointer ].owErrorNum = err;
+      owErrorStack[ owErrorPointer ].lineno = lineno;
+      owErrorStack[ owErrorPointer ].filename = filename;
+   }
+#else
+   //--------------------------------------------------------------------------
+   // The 'owRaiseError' is the method for raising an error onto the error
+   // stack.
+   //
+   // Arguments:  int err - the error code you wish to raise.
+   //
+   void owRaiseError(int err)
+   {
+      owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK;
+      owErrorStack[ owErrorPointer ].owErrorNum = err;
+   }
+#endif
+
+
+// SMALL_MEMORY_TARGET - embedded microcontrollers, where these
+// messaging functions might not make any sense.
+#ifndef SMALL_MEMORY_TARGET
+   //Array of meaningful error messages to associate with codes.
+   //Not used on targets with low memory (i.e. PIC).
+   static char *owErrorMsg[125] =
+   {
+   /*000*/ "No Error Was Set",
+   /*001*/ "No Devices found on 1-Wire Network",
+   /*002*/ "1-Wire Net Reset Failed",
+   /*003*/ "Search ROM Error: Couldn't locate next device on 1-Wire",
+   /*004*/ "Access Failed: Could not select device",
+   /*005*/ "DS2480B Adapter Not Detected",
+   /*006*/ "DS2480B: Wrong Baud",
+   /*007*/ "DS2480B: Bad Response",
+   /*008*/ "Open COM Failed",
+   /*009*/ "Write COM Failed",
+   /*010*/ "Read COM Failed",
+   /*011*/ "Data Block Too Large",
+   /*012*/ "Block Transfer failed",
+   /*013*/ "Program Pulse Failed",
+   /*014*/ "Program Byte Failed",
+   /*015*/ "Write Byte Failed",
+   /*016*/ "Read Byte Failed",
+   /*017*/ "Write Verify Failed",
+   /*018*/ "Read Verify Failed",
+   /*019*/ "Write Scratchpad Failed",
+   /*020*/ "Copy Scratchpad Failed",
+   /*021*/ "Incorrect CRC Length",
+   /*022*/ "CRC Failed",
+   /*023*/ "Failed to acquire a necessary system resource",
+   /*024*/ "Failed to initialize system resource",
+   /*025*/ "Data too long to fit on specified device.",
+   /*026*/ "Read exceeds memory bank end.",
+   /*027*/ "Write exceeds memory bank end.",
+   /*028*/ "Device select failed",
+   /*029*/ "Read Scratch Pad verify failed.",
+   /*030*/ "Copy scratchpad complete not found",
+   /*031*/ "Erase scratchpad complete not found",
+   /*032*/ "Address read back from scrachpad was incorrect",
+   /*033*/ "Read page with extra-info not supported by this memory bank",
+   /*034*/ "Read page packet with extra-info not supported by this memory bank",
+   /*035*/ "Length of packet requested exceeds page size",
+   /*036*/ "Invalid length in packet",
+   /*037*/ "Program pulse required but not available",
+   /*038*/ "Trying to access a read-only memory bank",
+   /*039*/ "Current bank is not general purpose memory",
+   /*040*/ "Read back from write compare is incorrect, page may be locked",
+   /*041*/ "Invalid page number for this memory bank",
+   /*042*/ "Read page with CRC not supported by this memory bank",
+   /*043*/ "Read page with CRC and extra-info not supported by this memory bank",
+   /*044*/ "Read back from write incorrect, could not lock page",
+   /*045*/ "Read back from write incorrect, could not lock redirect byte",
+   /*046*/ "The read of the status was not completed.",
+   /*047*/ "Page redirection not supported by this memory bank",
+   /*048*/ "Lock Page redirection not supported by this memory bank",
+   /*049*/ "Read back byte on EPROM programming did not match.",
+   /*050*/ "Can not write to a page that is locked.",
+   /*051*/ "Can not lock a redirected page that has already been locked.",
+   /*052*/ "Trying to redirect a locked redirected page.",
+   /*053*/ "Trying to lock a page that is already locked.",
+   /*054*/ "Trying to write to a memory bank that is write protected.",
+   /*055*/ "Error due to not matching MAC.",
+   /*056*/ "Memory Bank is write protected.",
+   /*057*/ "Secret is write protected, can not Load First Secret.",
+   /*058*/ "Error in Reading Scratchpad after Computing Next Secret.",
+   /*059*/ "Load Error from Loading First Secret.",
+   /*060*/ "Power delivery required but not available",
+   /*061*/ "Not a valid file name.",
+   /*062*/ "Unable to Create a Directory in this part.",
+   /*063*/ "That file already exists.",
+   /*064*/ "The directory is not empty.",
+   /*065*/ "The wrong type of part for this operation.",
+   /*066*/ "The max len for this file is too small.",
+   /*067*/ "This is not a write once bank.",
+   /*068*/ "The file can not be found.",
+   /*069*/ "There is not enough space available.",
+   /*070*/ "There is not a page to match that bit in the bitmap.",
+   /*071*/ "There are no jobs for EPROM parts.",
+   /*072*/ "Function not supported to modify attributes.",
+   /*073*/ "Handle is not in use.",
+   /*074*/ "Tring to read a write only file.",
+   /*075*/ "There is no handle available for use.",
+   /*076*/ "The directory provided is an invalid directory.",
+   /*077*/ "Handle does not exist.",
+   /*078*/ "Serial Number did not match with current job.",
+   /*079*/ "Can not program EPROM because a non-EPROM part on the network.",
+   /*080*/ "Write protect redirection byte is set.",
+   /*081*/ "There is an inappropriate directory length.",
+   /*082*/ "The file has already been terminated.",
+   /*083*/ "Failed to read memory page of iButton part.",
+   /*084*/ "Failed to match scratchpad of iButton part.",
+   /*085*/ "Failed to erase scratchpad of iButton part.",
+   /*086*/ "Failed to read scratchpad of iButton part.",
+   /*087*/ "Failed to execute SHA function on SHA iButton.",
+   /*088*/ "SHA iButton did not return a status completion byte.",
+   /*089*/ "Write data page failed.",
+   /*090*/ "Copy secret into secret memory pages failed.",
+   /*091*/ "Bind unique secret to iButton failed.",
+   /*092*/ "Could not install secret into user token.",
+   /*093*/ "Transaction Incomplete: signature did not match.",
+   /*094*/ "Transaction Incomplete: could not sign service data.",
+   /*095*/ "User token did not provide a valid authentication response.",
+   /*096*/ "Failed to answer a challenge on the user token.",
+   /*097*/ "Failed to create a challenge on the coprocessor.",
+   /*098*/ "Transaction Incomplete: service data was not valid.",
+   /*099*/ "Transaction Incomplete: service data was not updated.",
+   /*100*/ "Unrecoverable, catastrophic service failure occured.",
+   /*101*/ "Load First Secret from scratchpad data failed.",
+   /*102*/ "Failed to match signature of user's service data.",
+   /*103*/ "Subkey out of range for the DS1991.",
+   /*104*/ "Block ID out of range for the DS1991",
+   /*105*/ "Password is enabled",
+   /*106*/ "Password is invalid",
+   /*107*/ "This memory bank has no read only password",
+   /*108*/ "This memory bank has no read/write password",
+   /*109*/ "1-Wire is shorted",
+   /*110*/ "Error communicating with 1-Wire adapter",
+   /*111*/ "CopyScratchpad failed: Ending Offset must go to end of page",
+   /*112*/ "WriteScratchpad failed: Ending Offset must go to end of page",
+   /*113*/ "Mission can not be stopped while one is not in progress",
+   /*114*/ "Error stopping the mission",
+   /*115*/ "Port number is outside (0,MAX_PORTNUM) interval",
+   /*116*/ "Level of the 1-Wire was not changed",
+   /*117*/ "Both the Read Only and Read Write Passwords must be set",
+   /*118*/ "Failure to change latch state."
+   /*119*/ "Could not open usb port through libusb",
+   /*120*/ "Libusb DS2490 port already opened",
+   /*121*/ "Failed to set libusb configuration",
+   /*122*/ "Failed to claim libusb interface",
+   /*123*/ "Failed to set libusb altinterface",
+   /*124*/ "No adapter found at this port number"
+   };
+
+   char *owGetErrorMsg(int err)
+   {
+      return owErrorMsg[err];
+   }
+
+#ifndef __C51__
+   //--------------------------------------------------------------------------
+   // The 'owPrintErrorMsg' is the method for printing an error from the stack.
+   // The destination for the print is specified by the argument, fileno, which
+   // can be stderr, stdout, or a log file.  In non-debug mode, the output is
+   // of the form:
+   // Error num: Error msg
+   //
+   // In debug-mode, the output is of the form:
+   // Error num: filename line#: Error msg
+   //
+   // NOTE: This function has the side-effect of popping the error off the stack.
+   //
+   // Arguments:  FILE*: the destination for printing.
+   //
+   void owPrintErrorMsg(FILE *filenum)
+   {
+   #ifdef DEBUG
+      int l = owErrorStack[ owErrorPointer ].lineno;
+      char *f = owErrorStack[ owErrorPointer ].filename;
+      int err = owGetErrorNum();
+      fprintf(filenum,"Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]);
+   #else
+      int err = owGetErrorNum();
+      fprintf(filenum,"Error %d: %s\r\n",err,owErrorMsg[err]);
+   #endif
+   }
+#endif //__C51__
+
+   // Same as above, except uses default printf output
+   void owPrintErrorMsgStd()
+   {
+   #ifdef DEBUG
+      int l = owErrorStack[ owErrorPointer ].lineno;
+      char *f = owErrorStack[ owErrorPointer ].filename;
+      int err = owGetErrorNum();
+      printf("Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]);
+   #else
+      int err = owGetErrorNum();
+      printf("Error %d: %s\r\n",err,owErrorMsg[err]);
+   #endif
+   }
+#endif
+
diff --git a/windows/owTools/ownet.h b/windows/owTools/ownet.h
new file mode 100644
index 0000000..dc1d106
--- /dev/null
+++ b/windows/owTools/ownet.h
@@ -0,0 +1,426 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// ownet.h - Include file for 1-Wire Net library
+//
+// Version: 2.10
+//
+// History: 1.02 -> 1.03 Make sure uchar is not defined twice.
+//          1.03 -> 2.00 Changed 'MLan' to 'ow'.
+//          2.00 -> 2.01 Added error handling. Added circular-include check.
+//          2.01 -> 2.10 Added raw memory error handling and SMALLINT
+//          2.10 -> 3.00 Added memory bank functionality
+//                       Added file I/O operations
+//
+
+#ifndef OWNET_H
+#define OWNET_H
+
+//--------------------------------------------------------------//
+// Common Includes to ownet applications
+//--------------------------------------------------------------//
+#include <stdlib.h>
+#include <stdint.h>
+
+
+//--------------------------------------------------------------//
+// Target Specific Information
+//--------------------------------------------------------------//
+//--------------------------------------------------------------//
+// Handhelds (PalmOS, WinCE)
+//--------------------------------------------------------------//
+#ifdef __MC68K__
+   //MC68K is the type of processor in the PILOT
+   //Metrowerk's CodeWarrior defines this symbol
+   #include <string.h>
+   #ifndef strcmp
+      #include <StringMgr.h>
+      #define strcmp StrCompare
+   #endif
+   #include <file_struc.h>
+#endif
+
+#ifdef _WIN32_WCE
+   //All of our projects had this flag defined by default (_WIN32_WCE),
+   //but I'm not 100% positive that this is _the_ definitive
+   //flag to use to identify a WinCE system.
+   #include "WinCElnk.h"
+   #ifndef FILE
+      #define FILE int
+      extern int sprintf(char *buffer, char *format,...);
+      extern void fprintf(FILE *fp, char *format,...);
+      extern void printf(char *format,...);
+   #endif
+#endif
+
+#if !defined(_WIN32_WCE) && !defined(__MC68K__)
+   #include <stdio.h>
+#endif
+
+#ifdef __C51__
+   #define FILE int
+   #define exit(c) return
+   typedef unsigned int ushort;
+   typedef unsigned long ulong;
+   #define SMALLINT uchar
+#endif
+
+#ifdef __ICCMAXQ__
+   #define FILE int
+   #define stdout 0
+   #define stdin  1
+   #define stderr 2
+   typedef unsigned int ushort;
+   typedef unsigned long ulong;
+   #define SMALLINT short
+   #define main micro_main
+   #define real_main main
+   #define SMALL_MEMORY_TARGET
+#endif
+
+
+//--------------------------------------------------------------//
+// Typedefs
+//--------------------------------------------------------------//
+#ifndef SMALLINT
+   //
+   // purpose of smallint is for compile-time changing of formal
+   // parameters and return values of functions.  For each target
+   // machine, an integer is alleged to represent the most "simple"
+   // number representable by that architecture.  This should, in
+   // most cases, produce optimal code for that particular arch.
+   // BUT...  The majority of compilers designed for embedded
+   // processors actually keep an int at 16 bits, although the
+   // architecture might only be comfortable with 8 bits.
+   // The default size of smallint will be the same as that of
+   // an integer, but this allows for easy overriding of that size.
+   //
+   // NOTE:
+   // In all cases where a smallint is used, it is assumed that
+   // decreasing the size of this integer to something as low as
+   // a single byte _will_not_ change the functionality of the
+   // application.  e.g. a loop counter that will iterate through
+   // several kilobytes of data should not be SMALLINT.  The most
+   // common place you'll see smallint is for boolean return types.
+   //
+   #define SMALLINT int
+#endif
+
+// setting max baud
+#ifdef _WINDOWS
+   // 0x02 = PARAMSET_19200
+#define MAX_BAUD 0x02
+#else
+   // 0x06 = PARMSET_115200
+#define MAX_BAUD 0x06
+#endif
+
+#ifndef OW_UCHAR
+   #define OW_UCHAR
+   typedef unsigned char uchar;
+   #if !defined(__MINGW32__) && (defined(__CYGWIN__) || defined(__GNUC__))
+      typedef unsigned long ulong;
+      //ushort already defined in sys/types.h
+      #include <sys/types.h>
+   #else
+      #if defined(_WIN32) || defined(WIN32) || defined(__MC68K__) || defined(_WIN32_WCE) || defined(_DOS)  || defined(_WINDOWS) || defined(__MINGW32__)
+         typedef unsigned short ushort;
+         typedef unsigned long ulong;
+      #endif
+   #endif
+   #ifdef __sun__
+      #include <sys/types.h>
+   #endif
+   #ifdef SDCC
+      //intent of ushort is 2 bytes unsigned.
+      //for ds390 in sdcc, an int, not a short,
+      //is 2 bytes.
+      typedef unsigned int ushort;
+   #endif
+#endif
+
+// general defines
+#define WRITE_FUNCTION 1
+#define READ_FUNCTION  0
+
+// error codes
+// todo: investigate these and replace with new Error Handling library
+#define READ_ERROR    -1
+#define INVALID_DIR   -2
+#define NO_FILE       -3
+#define WRITE_ERROR   -4
+#define WRONG_TYPE    -5
+#define FILE_TOO_BIG  -6
+
+// Misc
+#define FALSE          0
+#define TRUE           1
+
+#ifndef MAX_PORTNUM
+   #define MAX_PORTNUM    16
+#endif
+
+// mode bit flags
+#define MODE_NORMAL                    0x00
+#define MODE_OVERDRIVE                 0x01
+#define MODE_STRONG5                   0x02
+#define MODE_PROGRAM                   0x04
+#define MODE_BREAK                     0x08
+
+// Output flags
+#define LV_ALWAYS          2
+#define LV_OPTIONAL        1
+#define LV_VERBOSE         0
+
+//--------------------------------------------------------------//
+// Error handling
+//--------------------------------------------------------------//
+extern int owGetErrorNum(void);
+extern int owHasErrors(void);
+
+//Clears the stack.
+#define OWERROR_CLEAR() while(owHasErrors()) owGetErrorNum();
+
+#ifdef DEBUG
+   //Raises an exception with extra debug info
+   #define OWERROR(err) owRaiseError(err,__LINE__,__FILE__)
+   extern void owRaiseError(int,int,char*);
+   #define OWASSERT(s,err,ret) if(!(s)){owRaiseError((err),__LINE__,__FILE__);return (ret);}
+#else
+   //Raises an exception with just the error code
+   #define OWERROR(err) owRaiseError(err)
+   extern void owRaiseError(int);
+   #define OWASSERT(s,err,ret) if(!(s)){owRaiseError((err));return (ret);}
+#endif
+
+#ifdef SMALL_MEMORY_TARGET
+   #define OWERROR_DUMP(fileno) /*no-op*/;
+#else
+   //Prints the stack out to the given file.
+   #define OWERROR_DUMP(fileno) while(owHasErrors()) owPrintErrorMsg(fileno);
+   extern void owPrintErrorMsg(FILE *);
+   extern void owPrintErrorMsgStd();
+   extern char *owGetErrorMsg(int);
+#endif
+
+#define OWERROR_NO_ERROR_SET                    0
+#define OWERROR_NO_DEVICES_ON_NET               1
+#define OWERROR_RESET_FAILED                    2
+#define OWERROR_SEARCH_ERROR                    3
+#define OWERROR_ACCESS_FAILED                   4
+#define OWERROR_DS2480_NOT_DETECTED             5
+#define OWERROR_DS2480_WRONG_BAUD               6
+#define OWERROR_DS2480_BAD_RESPONSE             7
+#define OWERROR_OPENCOM_FAILED                  8
+#define OWERROR_WRITECOM_FAILED                 9
+#define OWERROR_READCOM_FAILED                  10
+#define OWERROR_BLOCK_TOO_BIG                   11
+#define OWERROR_BLOCK_FAILED                    12
+#define OWERROR_PROGRAM_PULSE_FAILED            13
+#define OWERROR_PROGRAM_BYTE_FAILED             14
+#define OWERROR_WRITE_BYTE_FAILED               15
+#define OWERROR_READ_BYTE_FAILED                16
+#define OWERROR_WRITE_VERIFY_FAILED             17
+#define OWERROR_READ_VERIFY_FAILED              18
+#define OWERROR_WRITE_SCRATCHPAD_FAILED         19
+#define OWERROR_COPY_SCRATCHPAD_FAILED          20
+#define OWERROR_INCORRECT_CRC_LENGTH            21
+#define OWERROR_CRC_FAILED                      22
+#define OWERROR_GET_SYSTEM_RESOURCE_FAILED      23
+#define OWERROR_SYSTEM_RESOURCE_INIT_FAILED     24
+#define OWERROR_DATA_TOO_LONG                   25
+#define OWERROR_READ_OUT_OF_RANGE               26
+#define OWERROR_WRITE_OUT_OF_RANGE              27
+#define OWERROR_DEVICE_SELECT_FAIL              28
+#define OWERROR_READ_SCRATCHPAD_VERIFY          29
+#define OWERROR_COPY_SCRATCHPAD_NOT_FOUND       30
+#define OWERROR_ERASE_SCRATCHPAD_NOT_FOUND      31
+#define OWERROR_ADDRESS_READ_BACK_FAILED        32
+#define OWERROR_EXTRA_INFO_NOT_SUPPORTED        33
+#define OWERROR_PG_PACKET_WITHOUT_EXTRA         34
+#define OWERROR_PACKET_LENGTH_EXCEEDS_PAGE      35
+#define OWERROR_INVALID_PACKET_LENGTH           36
+#define OWERROR_NO_PROGRAM_PULSE                37
+#define OWERROR_READ_ONLY                       38
+#define OWERROR_NOT_GENERAL_PURPOSE             39
+#define OWERROR_READ_BACK_INCORRECT             40
+#define OWERROR_INVALID_PAGE_NUMBER             41
+#define OWERROR_CRC_NOT_SUPPORTED               42
+#define OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED    43
+#define OWERROR_READ_BACK_NOT_VALID             44
+#define OWERROR_COULD_NOT_LOCK_REDIRECT         45
+#define OWERROR_READ_STATUS_NOT_COMPLETE        46
+#define OWERROR_PAGE_REDIRECTION_NOT_SUPPORTED  47
+#define OWERROR_LOCK_REDIRECTION_NOT_SUPPORTED  48
+#define OWERROR_READBACK_EPROM_FAILED           49
+#define OWERROR_PAGE_LOCKED                     50
+#define OWERROR_LOCKING_REDIRECTED_PAGE_AGAIN   51
+#define OWERROR_REDIRECTED_PAGE                 52
+#define OWERROR_PAGE_ALREADY_LOCKED             53
+#define OWERROR_WRITE_PROTECTED                 54
+#define OWERROR_NONMATCHING_MAC                 55
+#define OWERROR_WRITE_PROTECT                   56
+#define OWERROR_WRITE_PROTECT_SECRET            57
+#define OWERROR_COMPUTE_NEXT_SECRET             58
+#define OWERROR_LOAD_FIRST_SECRET               59
+#define OWERROR_POWER_NOT_AVAILABLE             60
+#define OWERROR_XBAD_FILENAME                   61
+#define OWERROR_XUNABLE_TO_CREATE_DIR           62
+#define OWERROR_REPEAT_FILE                     63
+#define OWERROR_DIRECTORY_NOT_EMPTY             64
+#define OWERROR_WRONG_TYPE                      65
+#define OWERROR_BUFFER_TOO_SMALL                66
+#define OWERROR_NOT_WRITE_ONCE                  67
+#define OWERROR_FILE_NOT_FOUND                  68
+#define OWERROR_OUT_OF_SPACE                    69
+#define OWERROR_TOO_LARGE_BITNUM                70
+#define OWERROR_NO_PROGRAM_JOB                  71
+#define OWERROR_FUNC_NOT_SUP                    72
+#define OWERROR_HANDLE_NOT_USED                 73
+#define OWERROR_FILE_WRITE_ONLY                 74
+#define OWERROR_HANDLE_NOT_AVAIL                75
+#define OWERROR_INVALID_DIRECTORY               76
+#define OWERROR_HANDLE_NOT_EXIST                77
+#define OWERROR_NONMATCHING_SNUM                78
+#define OWERROR_NON_PROGRAM_PARTS               79
+#define OWERROR_PROGRAM_WRITE_PROTECT           80
+#define OWERROR_FILE_READ_ERR                   81
+#define OWERROR_ADDFILE_TERMINATED              82
+#define OWERROR_READ_MEMORY_PAGE_FAILED         83
+#define OWERROR_MATCH_SCRATCHPAD_FAILED         84
+#define OWERROR_ERASE_SCRATCHPAD_FAILED         85
+#define OWERROR_READ_SCRATCHPAD_FAILED          86
+#define OWERROR_SHA_FUNCTION_FAILED             87
+#define OWERROR_NO_COMPLETION_BYTE              88
+#define OWERROR_WRITE_DATA_PAGE_FAILED          89
+#define OWERROR_COPY_SECRET_FAILED              90
+#define OWERROR_BIND_SECRET_FAILED              91
+#define OWERROR_INSTALL_SECRET_FAILED           92
+#define OWERROR_VERIFY_SIG_FAILED               93
+#define OWERROR_SIGN_SERVICE_DATA_FAILED        94
+#define OWERROR_VERIFY_AUTH_RESPONSE_FAILED     95
+#define OWERROR_ANSWER_CHALLENGE_FAILED         96
+#define OWERROR_CREATE_CHALLENGE_FAILED         97
+#define OWERROR_BAD_SERVICE_DATA                98
+#define OWERROR_SERVICE_DATA_NOT_UPDATED        99
+#define OWERROR_CATASTROPHIC_SERVICE_FAILURE    100
+#define OWERROR_LOAD_FIRST_SECRET_FAILED        101
+#define OWERROR_MATCH_SERVICE_SIGNATURE_FAILED  102
+#define OWERROR_KEY_OUT_OF_RANGE                103
+#define OWERROR_BLOCK_ID_OUT_OF_RANGE           104
+#define OWERROR_PASSWORDS_ENABLED               105
+#define OWERROR_PASSWORD_INVALID                106
+#define OWERROR_NO_READ_ONLY_PASSWORD           107
+#define OWERROR_NO_READ_WRITE_PASSWORD          108
+#define OWERROR_OW_SHORTED                      109
+#define OWERROR_ADAPTER_ERROR                   110
+#define OWERROR_EOP_COPY_SCRATCHPAD_FAILED      111
+#define OWERROR_EOP_WRITE_SCRATCHPAD_FAILED     112
+#define OWERROR_HYGRO_STOP_MISSION_UNNECESSARY  113
+#define OWERROR_HYGRO_STOP_MISSION_ERROR        114
+#define OWERROR_PORTNUM_ERROR                   115
+#define OWERROR_LEVEL_FAILED                    116
+#define OWERROR_PASSWORD_NOT_SET                117
+#define OWERROR_LATCH_NOT_SET                   118
+#define OWERROR_LIBUSB_OPEN_FAILED              119
+#define OWERROR_LIBUSB_DEVICE_ALREADY_OPENED    120
+#define OWERROR_LIBUSB_SET_CONFIGURATION_ERROR  121
+#define OWERROR_LIBUSB_CLAIM_INTERFACE_ERROR    122
+#define OWERROR_LIBUSB_SET_ALTINTERFACE_ERROR   123
+#define OWERROR_LIBUSB_NO_ADAPTER_FOUND         124
+   
+
+	   // One Wire functions defined in ownetu.c
+	   SMALLINT  owFirst_(int portnum, SMALLINT do_reset, SMALLINT alarm_only);
+	   SMALLINT  owNext_(int portnum, SMALLINT do_reset, SMALLINT alarm_only);
+	   void      owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read);
+	   void      owFamilySearchSetup(int portnum, SMALLINT search_family);
+	   void      owSkipFamily(int portnum);
+	   SMALLINT  owAccess(int portnum);
+	   SMALLINT  owVerify(int portnum, SMALLINT alarm_only);
+	   SMALLINT  owOverdriveAccess(int portnum);
+
+
+	   // external One Wire functions defined in owsesu.c
+	   SMALLINT owAcquire(int portnum, char *port_zstr);
+	   int      owAcquireEx(char *port_zstr);
+	   void     owRelease(int portnum);
+
+	   // external One Wire functions defined in findtype.c
+	   // SMALLINT FindDevices(int,uchar FamilySN[][8],SMALLINT,int);
+
+	   // external One Wire functions from link layer owllu.c
+	   SMALLINT owTouchReset(int portnum);
+	   SMALLINT owTouchBit(int portnum, SMALLINT sendbit);
+	   SMALLINT owTouchByte(int portnum, SMALLINT sendbyte);
+	   SMALLINT owWriteByte(int portnum, SMALLINT sendbyte);
+	   SMALLINT owReadByte(int portnum);
+	   SMALLINT owSpeed(int portnum, SMALLINT new_speed);
+	   SMALLINT owLevel(int portnum, SMALLINT new_level);
+	   SMALLINT owProgramPulse(int portnum);
+	   SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte);
+	   SMALLINT owReadBytePower(int portnum);
+	   SMALLINT owHasPowerDelivery(int portnum);
+	   SMALLINT owHasProgramPulse(int portnum);
+	   SMALLINT owHasOverDrive(int portnum);
+	   SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse);
+	   // external One Wire global from owllu.c
+	   extern SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE;
+
+	   // external One Wire functions from transaction layer in owtrnu.c
+	   SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len);
+	   SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf);
+	   SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf,
+		   SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type);
+	   SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd,
+		   SMALLINT crc_type, SMALLINT do_access);
+
+	   // link functions
+	   void      msDelay(int len);
+	   long      msGettick(void);
+
+	   // ioutil.c functions prototypes
+	   int  EnterString(char *msg, char *buf, int min, int max);
+	   int  EnterNum(char *msg, int numchars, long *value, long min, long max);
+	   int  EnterHex(char *msg, int numchars, ulong *value);
+	   int  ToHex(char ch);
+	   int  getkeystroke(void);
+	   int  key_abort(void);
+	   void ExitProg(char *msg, int exit_code);
+	   int  getData(uchar *write_buff, int max_len, SMALLINT gethex);
+	   void PrintHex(uchar* buffer, int cnt);
+	   void PrintChars(uchar* buffer, int cnt);
+	   void PrintSerialNum(uchar* buffer);
+
+	   // external functions defined in crcutil.c
+	   void setcrc16(int portnum, ushort reset);
+	   ushort docrc16(int portnum, ushort cdata);
+	   void setcrc8(int portnum, uchar reset);
+	   uchar docrc8(int portnum, uchar x);
+
+	   extern int owInUse;
+
+#endif //OWNET_H
diff --git a/windows/owTools/tmexlnk.cpp b/windows/owTools/tmexlnk.cpp
new file mode 100644
index 0000000..47d22d1
--- /dev/null
+++ b/windows/owTools/tmexlnk.cpp
@@ -0,0 +1,368 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2001 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+//  TMEXLnk.C - Link module to call on TMEX low-level functions to
+//              excersize the general 1-Wire Net functions.
+//              (Requires TMEX 3.11 or newer)
+//
+//  Version: 3.00
+//
+//  History: 1.00 -> 1.01  Return values in owLevel corrected.
+//                         Added function msDelay.
+//           1.02 -> 1.03  Add msGettick, always return owLevel success
+//                         to hide adapters (DS9097E) that do not have
+//                         power delivery capabilities.
+//           1.03 -> 2.00  Changed 'MLan' to 'ow'. Added support for
+//                         multiple ports.
+//           2.10 -> 3.00  Added owReadBitPower and owWriteBytePower
+
+#include "ownet.h"
+#include <windows.h>
+
+// external TMEX variables
+extern long SessionHandle[MAX_PORTNUM];
+extern uchar StateBuffer[MAX_PORTNUM][5120];
+extern "C" short far pascal TMTouchByte(long, short);
+extern "C" short far pascal TMTouchReset(long);
+extern "C" short far pascal TMTouchBit(long, short);
+extern "C" short far pascal TMProgramPulse(long);
+extern "C" short far pascal TMOneWireCom(long, short, short);
+extern "C" short far pascal TMOneWireLevel(long, short, short, short);
+
+// globals
+SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = FALSE; // for compatibility purposes
+
+//--------------------------------------------------------------------------
+// Reset all of the devices on the 1-Wire Net and return the result.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+//
+// Returns: TRUE(1):  presense pulse(s) detected, device(s) reset
+//          FALSE(0): no presense pulses detected
+//
+SMALLINT owTouchReset(int portnum)
+{
+   int result;
+
+   // Assume valid Session
+   result = TMTouchReset(SessionHandle[portnum]);
+
+   // success if the normal or alarm presence
+   if ((result == 1) || (result == 2))
+      return TRUE;
+   else
+      return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Send 1 bit of communication to the 1-Wire Net and return the
+// result 1 bit read from the 1-Wire Net.  The parameter 'sendbit'
+// least significant bit is used and the least significant bit
+// of the result is the return bit.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+// 'sendbit'     - the least significant bit is the bit to send
+//
+// Returns: 0:   0 bit read from sendbit
+//          1:   1 bit read from sendbit
+//
+SMALLINT owTouchBit(int portnum, SMALLINT sendbit)
+{
+   // Assume valid Session
+   return TMTouchBit(SessionHandle[portnum],(short)sendbit);
+}
+
+//--------------------------------------------------------------------------
+// Send 8 bits of communication to the 1-Wire Net and verify that the
+// 8 bits read from the 1-Wire Net is the same (write operation).
+// The parameter 'sendbyte' least significant 8 bits are used.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'sendbyte'   - 8 bits to send (least significant byte)
+//
+// Returns:  TRUE: bytes written and echo was the same
+//           FALSE: echo was not the same
+//
+SMALLINT owTouchByte(int portnum, SMALLINT sendbyte)
+{
+   // Assume valid Session
+   return TMTouchByte(SessionHandle[portnum],(short)sendbyte);
+}
+
+//--------------------------------------------------------------------------
+// Send 8 bits of communication to the MicroLAN and verify that the
+// 8 bits read from the MicroLAN is the same (write operation).
+// The parameter 'sendbyte' least significant 8 bits are used.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'sendbyte'   - 8 bits to send (least significant byte)
+//
+// Returns:  TRUE: bytes written and echo was the same
+//           FALSE: echo was not the same
+//
+SMALLINT owWriteByte(int portnum, SMALLINT sendbyte)
+{
+   return (owTouchByte(portnum,sendbyte) == sendbyte) ? TRUE : FALSE;
+}
+
+//--------------------------------------------------------------------------
+// Send 8 bits of read communication to the 1-Wire Net and and return the
+// result 8 bits read from the 1-Wire Net.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+//
+// Returns:  TRUE:  8 bytes read from 1-Wire Net
+//           FALSE: the 8 bytes were not read
+//
+SMALLINT owReadByte(int portnum)
+{
+   return owTouchByte(portnum,0xFF);
+}
+
+//--------------------------------------------------------------------------
+// Set the 1-Wire Net communucation speed.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'new_speed'  - new speed defined as
+//                MODE_NORMAL     0x00
+//                MODE_OVERDRIVE  0x01
+//
+// Returns:  current 1-Wire Net speed
+//
+SMALLINT owSpeed(int portnum, SMALLINT new_speed)
+{
+   return TMOneWireCom(SessionHandle[portnum],0,(short)new_speed);
+}
+
+//--------------------------------------------------------------------------
+// Set the 1-Wire Net line level.  The values for new_level are
+// as follows:
+//
+// 'portnum'   - number 0 to MAX_PORTNUM-1.  This number is provided to
+//               indicate the symbolic port number.
+// 'new_level' - new level defined as
+//                MODE_NORMAL     0x00
+//                MODE_STRONG5    0x02
+//                MODE_PROGRAM    0x04
+//                MODE_BREAK      0x08 (not supported)
+//
+// Returns:  current 1-Wire Net level
+//
+SMALLINT owLevel(int portnum, SMALLINT new_level)
+{
+   int rslt;
+   int docheck = FALSE;
+
+   // check for DS2480 bug
+   if (((SessionHandle[portnum] & 0x0F0) == 0x050) &&
+       (TMOneWireLevel(SessionHandle[portnum],1,0,0) == 1))
+      docheck = TRUE;
+
+   switch (new_level)
+   {
+      case MODE_NORMAL:
+         rslt = TMOneWireLevel(SessionHandle[portnum],0,0,0);
+         // test code for DS2480 bug
+         if (docheck)
+            TMTouchBit(SessionHandle[portnum],1);
+         break;
+      case MODE_STRONG5:
+         rslt = TMOneWireLevel(SessionHandle[portnum],0,1,0);
+         break;
+      case MODE_PROGRAM:
+         rslt = TMOneWireLevel(SessionHandle[portnum],0,3,0);
+         break;
+      case MODE_BREAK:
+         rslt = TMOneWireLevel(SessionHandle[portnum],0,2,0);
+         break;
+      default:
+         rslt = 0;
+   }
+
+   // Assume TMEX can do it so always return NewLevel
+   return new_level;
+}
+
+//--------------------------------------------------------------------------
+// This procedure creates a fixed 480 microseconds 12 volt pulse
+// on the 1-Wire Net for programming EPROM iButtons.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+//
+// Returns:  TRUE  successful
+//           FALSE program voltage not available
+//
+SMALLINT owProgramPulse(int portnum)
+{
+   return TMProgramPulse(SessionHandle[portnum]);
+}
+
+//--------------------------------------------------------------------------
+//  Description:
+//     Delay for at least 'len' ms
+//
+void msDelay(int len)
+{
+   Sleep(len);
+}
+
+//--------------------------------------------------------------------------
+// Get the current millisecond tick count.  Does not have to represent
+// an actual time, it just needs to be an incrementing timer.
+//
+long msGettick(void)
+{
+   return GetTickCount();
+}
+
+//--------------------------------------------------------------------------
+// Send 8 bits of communication to the 1-Wire Net and verify that the
+// 8 bits read from the 1-Wire Net is the same (write operation).  
+// The parameter 'sendbyte' least significant 8 bits are used.  After the
+// 8 bits are sent change the level of the 1-Wire net.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+// 'sendbyte' - 8 bits to send (least significant byte)
+//
+// Returns:  TRUE: bytes written and echo was the same
+//           FALSE: echo was not the same 
+//
+SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte)
+{
+   // prime for power delivery after byte
+   TMOneWireLevel(SessionHandle[portnum],0,1,2);
+
+   // send the byte and start strong pullup
+   if(TMTouchByte(SessionHandle[portnum],(short)sendbyte) != sendbyte)
+   {
+      TMOneWireLevel(SessionHandle[portnum],0,0,0);
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+//--------------------------------------------------------------------------
+// Read 8 bits of communication to the 1-Wire Net and verify that the
+// 8 bits read from the 1-Wire Net is the same (write operation).  
+// The parameter 'sendbyte' least significant 8 bits are used.  After the
+// 8 bits are read change the level of the 1-Wire net.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+// 'sendbyte' - 8 bits to send (least significant byte)
+//
+// Returns:  TRUE: bytes written and echo was the same
+//           FALSE: echo was not the same 
+//
+SMALLINT owReadBytePower(int portnum)
+{
+   SMALLINT sendbyte = 0xFF;
+
+   // prime for power delivery after byte
+   TMOneWireLevel(SessionHandle[portnum],0,1,2);
+
+   // send the byte and start strong pullup
+   return TMTouchByte(SessionHandle[portnum],(short)sendbyte);
+}
+
+//--------------------------------------------------------------------------
+// Send 1 bit of communication to the 1-Wire Net and verify that the
+// response matches the 'applyPowerResponse' bit and apply power delivery
+// to the 1-Wire net.  Note that some implementations may apply the power
+// first and then turn it off if the response is incorrect.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+// 'applyPowerResponse' - 1 bit response to check, if correct then start
+//                        power delivery 
+//
+// Returns:  TRUE: bit written and response correct, strong pullup now on
+//           FALSE: response incorrect
+//
+SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse)
+{
+   // prime for power delivery after bit
+   TMOneWireLevel(SessionHandle[portnum],0,1,1);
+
+   // send the byte and start strong pullup
+   if(TMTouchBit(SessionHandle[portnum],0x01) != applyPowerResponse)
+   {
+      TMOneWireLevel(SessionHandle[portnum],0,0,0);
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+//--------------------------------------------------------------------------
+// This procedure indicates wether the adapter can deliver power.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+//
+// Returns:  TRUE  because all userial adapters have over drive. 
+//
+SMALLINT owHasPowerDelivery(int portnum)
+{
+   return TRUE;
+}
+
+//--------------------------------------------------------------------------
+// This procedure indicates wether the adapter can deliver power.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+//
+// Returns:  TRUE  because all userial adapters have over drive. 
+//
+SMALLINT owHasOverDrive(int portnum)
+{
+   return TRUE;
+}
+
+//--------------------------------------------------------------------------
+// This procedure creates a fixed 480 microseconds 12 volt pulse 
+// on the 1-Wire Net for programming EPROM iButtons.
+//
+// 'portnum'  - number 0 to MAX_PORTNUM-1.  This number was provided to
+//              OpenCOM to indicate the port number.
+//
+// Returns:  TRUE  program volatage available
+//           FALSE program voltage not available  
+SMALLINT owHasProgramPulse(int portnum)
+{
+   return TMProgramPulse(SessionHandle[portnum]);
+}
\ No newline at end of file
diff --git a/windows/owTools/tmexnet.cpp b/windows/owTools/tmexnet.cpp
new file mode 100644
index 0000000..8712ac8
--- /dev/null
+++ b/windows/owTools/tmexnet.cpp
@@ -0,0 +1,251 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2001 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+//  tmexnet.C - Wrapper class to hook 1-Wire Public Domain API to TMEX API
+//              for network functions.
+//
+//  Version: 3.00
+//
+//
+
+#include "ownet.h"
+#include <windows.h>
+
+uchar StateBuffer[MAX_PORTNUM][5120];
+
+int owInUse = 0;
+
+// external TMEX variables
+extern long SessionHandle[MAX_PORTNUM];
+extern "C" short far pascal TMSearch(long session_handle, void *start_buffer,
+                                 short ResetSearch,  short PerformReset, 
+                                 short SrchCmd);
+extern "C" short pascal TMFirst(long, void *);
+extern "C" short pascal TMNext(long, void *);
+extern "C" short pascal TMAccess(long, void *);
+extern "C" short pascal TMStrongAccess(long, void *);
+extern "C" short pascal TMStrongAlarmAccess(long, void *);
+extern "C" short pascal TMOverAccess(long, void *);
+extern "C" short pascal TMRom(long, void *, short *);
+extern "C" short pascal TMFirstAlarm(long, void *);
+extern "C" short pascal TMNextAlarm(long, void *);
+extern "C" short pascal TMFamilySearchSetup(long, void *, short);
+extern "C" short pascal TMSkipFamily(long, void *);
+extern "C" short pascal TMAutoOverDrive(long, void *, short);
+
+
+//--------------------------------------------------------------------------
+// The 'owFirst' finds the first device on the 1-Wire Net  This function
+// contains one parameter 'alarm_only'.  When
+// 'alarm_only' is TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0.
+// Using the find alarm command 0xEC will limit the search to only
+// 1-Wire devices that are in an 'alarm' state.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'do_reset'   - TRUE (1) perform reset before search, FALSE (0) do not
+//                perform reset before search.
+// 'alarm_only' - TRUE (1) the find alarm command 0xEC is
+//                sent instead of the normal search command 0xF0
+//
+// Returns:   TRUE (1) : when a 1-Wire device was found and it's
+//                        Serial Number placed in the global SerialNum[portnum]
+//            FALSE (0): There are no devices on the 1-Wire Net.
+//
+SMALLINT owFirst_(int portnum, SMALLINT do_reset, SMALLINT alarm_only)
+{
+   return (TMSearch(SessionHandle[portnum], StateBuffer[portnum], 1, 
+                    (short)do_reset, (short)((alarm_only) ? 0xEC : 0xF0)) == 1);
+}
+
+//--------------------------------------------------------------------------
+// The 'owNext' function does a general search.  This function
+// continues from the previos search state. The search state
+// can be reset by using the 'owFirst' function.
+// This function contains one parameter 'alarm_only'.
+// When 'alarm_only' is TRUE (1) the find alarm command
+// 0xEC is sent instead of the normal search command 0xF0.
+// Using the find alarm command 0xEC will limit the search to only
+// 1-Wire devices that are in an 'alarm' state.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'do_reset'   - TRUE (1) perform reset before search, FALSE (0) do not
+//                perform reset before search.
+// 'alarm_only' - TRUE (1) the find alarm command 0xEC is
+//                sent instead of the normal search command 0xF0
+//
+// Returns:   TRUE (1) : when a 1-Wire device was found and it's
+//                       Serial Number placed in the global SerialNum[portnum]
+//            FALSE (0): when no new device was found.  Either the
+//                       last search was the last device or there
+//                       are no devices on the 1-Wire Net.
+//
+SMALLINT owNext_(int portnum, SMALLINT do_reset, SMALLINT alarm_only)
+{
+   return (TMSearch(SessionHandle[portnum], StateBuffer[portnum], 0, 
+                    (short)do_reset, (short)((alarm_only) ? 0xEC : 0xF0)) == 1);
+}
+
+//--------------------------------------------------------------------------
+// The 'owSerialNum' function either reads or sets the SerialNum buffer
+// that is used in the search functions 'owFirst' and 'owNext'.
+// This function contains two parameters, 'serialnum_buf' is a pointer
+// to a buffer provided by the caller.  'serialnum_buf' should point to
+// an array of 8 unsigned chars.  The second parameter is a flag called
+// 'do_read' that is TRUE (1) if the operation is to read and FALSE
+// (0) if the operation is to set the internal SerialNum buffer from
+// the data in the provided buffer.
+//
+// 'portnum'       - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                   indicate the symbolic port number.
+// 'serialnum_buf' - buffer to that contains the serial number to set
+//                   when do_read = FALSE (0) and buffer to get the serial
+//                   number when do_read = TRUE (1).
+// 'do_read'       - flag to indicate reading (1) or setting (0) the current
+//                   serial number.
+//
+void owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read)
+{
+   short ROM[8],i;
+
+   // check if reading or writing
+   if (do_read)
+   {
+      ROM[0] = 0;
+   }
+   else
+   {
+      for (i = 0; i < 8; i++)
+         ROM[i] = serialnum_buf[i];
+   }
+
+   // call TMEX to read or set the current device
+   TMRom(SessionHandle[portnum], StateBuffer[portnum], ROM);
+
+   // place in 'serialnum_buf'
+   if (do_read)
+   {
+      for (i = 0; i < 8; i++)
+         serialnum_buf[i] = (uchar)ROM[i];
+   }
+}
+
+//--------------------------------------------------------------------------
+// Setup the search algorithm to find a certain family of devices
+// the next time a search function is called 'owNext'.
+//
+// 'portnum'       - number 0 to MAX_PORTNUM-1.  This number was provided to
+//                   OpenCOM to indicate the port number.
+// 'search_family' - family code type to set the search algorithm to find
+//                   next.
+//
+void owFamilySearchSetup(int portnum, SMALLINT search_family)
+{
+   TMFamilySearchSetup(SessionHandle[portnum], StateBuffer[portnum], 
+                       (short)search_family);
+}
+
+//--------------------------------------------------------------------------
+// Set the current search state to skip the current family code.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+//
+void owSkipFamily(int portnum)
+{
+   TMSkipFamily(SessionHandle[portnum], StateBuffer[portnum]);
+}
+
+//--------------------------------------------------------------------------
+// The 'owAccess' function resets the 1-Wire and sends a MATCH Serial
+// Number command followed by the current SerialNum code. After this
+// function is complete the 1-Wire device is ready to accept device-specific
+// commands.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+//
+// Returns:   TRUE (1) : reset indicates present and device is ready
+//                       for commands.
+//            FALSE (0): reset does not indicate presence or echos 'writes'
+//                       are not correct.
+//
+SMALLINT owAccess(int portnum)
+{
+   return (TMAccess(SessionHandle[portnum], StateBuffer[portnum]) == 1);
+}
+
+//----------------------------------------------------------------------
+// The function 'owVerify' verifies that the current device
+// is in contact with the 1-Wire Net.
+// Using the find alarm command 0xEC will verify that the device
+// is in contact with the 1-Wire Net and is in an 'alarm' state.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+// 'alarm_only'  - TRUE (1) the find alarm command 0xEC
+//                 is sent instead of the normal search
+//                 command 0xF0.
+//
+// Returns:   TRUE (1) : when the 1-Wire device was verified
+//                       to be on the 1-Wire Net
+//                       with alarm_only == FALSE
+//                       or verified to be on the 1-Wire Net
+//                       AND in an alarm state when
+//                       alarm_only == TRUE.
+//            FALSE (0): the 1-Wire device was not on the
+//                       1-Wire Net or if alarm_only
+//                       == TRUE, the device may be on the
+//                       1-Wire Net but in a non-alarm state.
+//
+SMALLINT owVerify(int portnum, SMALLINT alarm_only)
+{
+   if (alarm_only)
+      return (TMStrongAlarmAccess(SessionHandle[portnum], StateBuffer[portnum]) == 1);
+   else
+      return (TMStrongAccess(SessionHandle[portnum], StateBuffer[portnum]) == 1);
+}
+
+//----------------------------------------------------------------------
+// Perform a overdrive MATCH command to select the 1-Wire device with
+// the address in the ID data register.
+//
+// 'portnum'     - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                 indicate the symbolic port number.
+//
+// Returns:  TRUE: If the device is present on the 1-Wire Net and
+//                 can do overdrive then the device is selected.
+//           FALSE: Device is not present or not capable of overdrive.
+//
+//  *Note: This function could be converted to send DS2480
+//         commands in one packet.
+//
+SMALLINT owOverdriveAccess(int portnum)
+{
+   return (TMOverAccess(SessionHandle[portnum], StateBuffer[portnum]) == 1);
+}
diff --git a/windows/owTools/tmexses.cpp b/windows/owTools/tmexses.cpp
new file mode 100644
index 0000000..5024acb
--- /dev/null
+++ b/windows/owTools/tmexses.cpp
@@ -0,0 +1,216 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2001 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+//  owsestmx.c - Acquire and release a Session on the 1-Wire Net using TMEX.
+//               (Requires TMEX 3.11 or newer)
+//
+//  Version: 2.01
+//
+//  History: 1.03 -> 2.00  Changed 'MLan' to 'ow'. Added support for
+//                         multiple ports.
+//           2.00 -> 2.01  Added support for owError library.
+//
+
+#include <stdio.h>
+#include <windows.h>
+#include "ownet.h"
+
+// external function prototypes
+extern "C" long  far pascal TMExtendedStartSession(short, short, void far *);
+extern "C" short far pascal TMEndSession(long);
+extern "C" short far pascal TMClose(long);
+extern "C" short far pascal TMSetup(long);
+extern "C" short far pascal TMReadDefaultPort(short far *, short far *);
+extern "C" short far pascal TMOneWireCom(
+	long session_handle, // session handle for the desired 1-Wire network
+	short Operation,// Read (1) or Set (0) the communication rate
+	short TimeMode // communication rate number
+	);
+short PortNum=1,PortType=2;
+long  SessionHandle[MAX_PORTNUM];
+SMALLINT handle_init = FALSE;
+
+//---------------------------------------------------------------------------
+// Attempt to acquire a 1-Wire net using a com port and a DS2480 based
+// adapter.
+//
+// 'port_zstr'     - zero terminated port name.  For this platform
+//                   use format {port number, port type}.
+//
+// Returns: port number and -1 if not successful in setting up the port.
+//
+int owAcquireEx(char *port_zstr)
+{
+   int portnum;
+   int string_counter, counter, i, lenmax;
+   char portnum_str[15];
+   char porttype_str[15];
+   void *tmex_options = NULL;
+
+   if(!handle_init)
+   {
+      for(i=0; i<MAX_PORTNUM; i++)
+         SessionHandle[i] = 0;
+      handle_init = TRUE;
+   }
+
+   // check to find first available handle slot
+   for(portnum = 0; portnum<MAX_PORTNUM; portnum++)
+   {
+      if(!SessionHandle[portnum])
+         break;
+   }
+   OWASSERT( portnum<MAX_PORTNUM, OWERROR_PORTNUM_ERROR, -1 );
+
+   // convert the string in port_zstr to be the port number and port type
+   if(port_zstr)
+   {
+      lenmax = strlen(port_zstr);
+      if (lenmax > 12)
+         lenmax = 12;
+      string_counter = 1;
+      counter = 0;
+      do
+      {
+         portnum_str[counter] = port_zstr[string_counter];
+
+         counter++;
+         string_counter++;
+      }
+      while((port_zstr[string_counter] != ',') && (string_counter <= lenmax));
+
+      portnum_str[counter] = '\0';
+
+      string_counter++;
+      counter = 0;
+
+      do
+      {
+         porttype_str[counter] = port_zstr[string_counter];
+
+         counter++;
+         string_counter++;
+      }
+      while((port_zstr[string_counter] != '}') && (string_counter <= lenmax));
+
+      porttype_str[counter] = '\0';
+
+      PortNum = atoi(portnum_str);
+      PortType = atoi(porttype_str);
+   }
+
+   // open a session
+   SessionHandle[portnum] = TMExtendedStartSession(PortNum,PortType,tmex_options);
+
+   // check the session handle
+   if (SessionHandle[portnum] <= 0)
+   {
+      OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED);
+      SessionHandle[portnum] = 0;
+      return -1;
+   }
+
+   // setup the port
+   if (TMSetup(SessionHandle[portnum]) != 1)
+   {
+      TMClose(SessionHandle[portnum]);
+      TMEndSession(SessionHandle[portnum]);
+      OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED);
+      SessionHandle[portnum] = 0;
+      return -1;
+   }
+   
+   return portnum;
+}
+
+//---------------------------------------------------------------------------
+// Attempt to acquire a 1-Wire net using a com port and a DS2480 based
+// adapter.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'port_zstr'  - zero terminated port name.  For this platform
+//                use format COMX where X is the port number.
+//
+// Returns: TRUE - success, COM port opened
+//
+SMALLINT owAcquire(int portnum, char *port_zstr)
+{
+   int i;
+
+   if(!handle_init)
+   {
+      for(i=0; i<MAX_PORTNUM; i++)
+         SessionHandle[i] = 0;
+      handle_init = TRUE;
+   }
+
+   OWASSERT( portnum<MAX_PORTNUM && portnum>=0 && !SessionHandle[portnum],
+             OWERROR_PORTNUM_ERROR, FALSE );
+
+   // read the default PortNum and PortType
+   TMReadDefaultPort(&PortNum,&PortType);
+
+   // convert the string in port_zstr to be the port number
+   PortNum = atoi(port_zstr);
+
+   // open a session
+   SessionHandle[portnum] = TMExtendedStartSession(PortNum,PortType,NULL);
+
+   // check the session handle
+   if (SessionHandle[portnum] <= 0)
+   {
+      OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED);
+      SessionHandle[portnum] = 0;
+      return FALSE;
+   }
+
+   // setup the port
+   if (TMSetup(SessionHandle[portnum]) != 1)
+   {
+      TMClose(SessionHandle[portnum]);
+      TMEndSession(SessionHandle[portnum]);
+      OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED);
+      SessionHandle[portnum] = 0;
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+//---------------------------------------------------------------------------
+// Release the previously acquired a 1-Wire net.
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+//
+void owRelease(int portnum)
+{
+   TMClose(SessionHandle[portnum]);
+   TMEndSession(SessionHandle[portnum]);
+   SessionHandle[portnum] = 0;
+}
+
diff --git a/windows/owTools/tmextran.cpp b/windows/owTools/tmextran.cpp
new file mode 100644
index 0000000..0cfc6dc
--- /dev/null
+++ b/windows/owTools/tmextran.cpp
@@ -0,0 +1,199 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+//  tmexnet.C - Wrapper class to hook 1-Wire Public Domain API to TMEX API
+//              for transport functions.
+//
+//  Version: 3.00
+//
+
+#include "ownet.h"
+#include <windows.h>
+
+// external TMEX variables
+extern long SessionHandle[MAX_PORTNUM];
+extern "C" short far pascal TMBlockIO(long, uchar *, short);
+extern "C" short far pascal TMBlockStream(long, uchar *, short);
+
+//--------------------------------------------------------------------------
+// The 'owBlock' transfers a block of data to and from the
+// 1-Wire Net with an optional reset at the begining of communication.
+// The result is returned in the same buffer.
+//
+// 'do_reset' - cause a owTouchReset to occure at the begining of
+//              communication TRUE(1) or not FALSE(0)
+// 'tran_buf' - pointer to a block of unsigned
+//              chars of length 'TranferLength' that will be sent
+//              to the 1-Wire Net
+// 'tran_len' - length in bytes to transfer
+// Supported devices: all
+//
+// Returns:   TRUE (1) : The optional reset returned a valid
+//                       presence (do_reset == TRUE) or there
+//                       was no reset required.
+//            FALSE (0): The reset did not return a valid prsence
+//                       (do_reset == TRUE).
+//
+//  The maximum tran_len is 64
+//
+SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len)
+{
+   short rslt;
+
+   // check for a block too big
+   if (tran_len > 192)
+   {
+      OWERROR(OWERROR_BLOCK_TOO_BIG);
+      return FALSE;
+   }
+
+   // check if need to do a owTouchReset first
+   if (do_reset)
+      rslt = TMBlockIO(SessionHandle[portnum], tran_buf, (short)tran_len);
+   else
+      rslt = TMBlockStream(SessionHandle[portnum], tran_buf, (short)tran_len);
+
+   return (rslt == tran_len);
+}
+
+//--------------------------------------------------------------------------
+// Write a byte to an EPROM 1-Wire device.
+//
+// Supported devices: crc_type=0(CRC8)
+//                        DS1982
+//                    crc_type=1(CRC16)
+//                        DS1985, DS1986, DS2407
+//
+// 'portnum'    - number 0 to MAX_PORTNUM-1.  This number is provided to
+//                indicate the symbolic port number.
+// 'write_byte' - byte to program
+// 'addr'       - address of byte to program
+// 'write_cmd'  - command used to write (0x0F reg mem, 0x55 status)
+// 'crc_type'   - CRC used (0 CRC8, 1 CRC16)
+// 'do_access'  - Flag to access device for each byte
+//                (0 skip access, 1 do the access)
+//                WARNING, only use do_access=0 if programing the NEXT
+//                byte immediatly after the previous byte.
+//
+// Returns: >=0   success, this is the resulting byte from the program
+//                effort
+//          -1    error, device not connected or program pulse voltage
+//                not available
+//
+SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd,
+                       SMALLINT crc_type, SMALLINT do_access)
+{
+   ushort lastcrc16;
+   uchar lastcrc8;
+
+   // optionally access the device
+   if (do_access)
+   {
+      if (!owAccess(portnum))
+      {
+         OWERROR(OWERROR_ACCESS_FAILED);
+         return -1;
+      }
+
+      // send the write command
+      if (!owWriteByte(portnum,write_cmd))
+      {
+         OWERROR(OWERROR_WRITE_BYTE_FAILED);
+         return -1;
+      }
+
+      // send the address
+      if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8))
+      {
+         OWERROR(OWERROR_WRITE_BYTE_FAILED);
+         return -1;
+      }
+   }
+
+   // send the data to write
+   if (!owWriteByte(portnum,write_byte))
+   {
+      OWERROR(OWERROR_WRITE_BYTE_FAILED);
+      return -1;
+   }
+
+   // read the CRC
+   if (crc_type == 0)
+   {
+      // calculate CRC8
+      if (do_access)
+      {
+         setcrc8(portnum,0);
+         docrc8(portnum,(uchar)write_cmd);
+         docrc8(portnum,(uchar)(addr & 0xFF));
+         docrc8(portnum,(uchar)(addr >> 8));
+      }
+      else
+         setcrc8(portnum,(uchar)(addr & 0xFF));
+
+      docrc8(portnum,(uchar)write_byte);
+      // read and calculate the read crc
+      lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum));
+      // crc should now be 0x00
+      if (lastcrc8 != 0)
+      {
+         OWERROR(OWERROR_CRC_FAILED);
+         return -1;
+      }
+   }
+   else
+   {
+      // CRC16
+      if (do_access)
+      {
+         setcrc16(portnum,0);
+         docrc16(portnum,(ushort)write_cmd);
+         docrc16(portnum,(ushort)(addr & 0xFF));
+         docrc16(portnum,(ushort)(addr >> 8));
+      }
+      else
+         setcrc16(portnum,(ushort)addr);
+      docrc16(portnum,(ushort)write_byte);
+      // read and calculate the read crc
+      docrc16(portnum,(ushort)owReadByte(portnum));
+      lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum));
+      // crc should now be 0xB001
+      if (lastcrc16 != 0xB001)
+         return -1;
+   }
+
+   // send the program pulse
+   if (!owProgramPulse(portnum))
+   {
+      OWERROR(OWERROR_PROGRAM_PULSE_FAILED);
+      return -1;
+   }
+
+   // read back and return the resulting byte
+   return owReadByte(portnum);
+}
+
+