/* In the following C language code, 1- wire I/O is accomplished using the serial port of an IBM PC or compatible. The serial port must be capable of a 115,200 bps data rate. Setup must be called before any of the touch functions to verify the existence of the specified com port and initialize it. -------------------------------------------------------------------- The setup function makes sure that the com port number passed to it is from 1 to 4 and has a valid address associated with it. */ #include <ctype.h> #include <stdio.h> #include <dos.h> typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; static uchar com_port; /* 0x2F8 = COM2 */ static char *TouchMemStatus[5] = { " 0 no presence detect", " 1 presence pulse no alarm", " 2 alarm followed by presence", " 3 short circuit to ground", " 4 no com port found" }; #define FL 0 #define TR 1 uchar Setup (uchar CmPt) { uint far *ptr = (uint far *) 0x00400000; uint SPA; com_port = CmPt; /* check to see if it is a valid com port number and address */ SPA = *(ptr + CmPt - 1); /* get the address */ if (CmPt < 1 || CmPt > 4 || !SPA) return FL; /* serial port initialization */ outportb (SPA + 3, 0x83); /* set DLAB */ outportb (SPA, 0x01); /* bit rate is 115200 */ outportb (SPA + 1, 0x00); outportb (SPA + 3, 0x03); /* 8 dta, 1 stp, no par */ outportb (SPA + 1, 0x00); /* no interrupts */ outportb (SPA + 4, 0x03); /* RTS and DTR on */ printf("COM port #%d at 0x%0x\n", com_port, SPA); return TR; } /*------------------------------------------------------------------------ * Do a reset on the 1 wire port and return * 0 no presence detect * 1 presence pulse no alarm * 2 alarm followed by presence * 3 short circuit to ground * 4 no com port found * * The global variable 'com_port' must be set to the com port that the * DS9097 COM Port Adapter is attached to before calling this routine. * */ uchar TouchReset (void) { uint SPA, F, X, Y, tmp, trst = 0; uint far *ptr = (uint far *) 0x00400000; ulong far *sysclk = (ulong far *) 0x0040006c; ulong M; /* get the serial port address */ SPA = *(ptr + com_port - 1); /* return if there is no address */ if (!SPA) return 4; /* serial port initialization */ outportb (SPA + 3, 0x83); /* set DLAB */ outportb (SPA, 0x01); /* bit rate is 115200 */ outportb (SPA + 1, 0x00); outportb (SPA + 3, 0x03); /* 8 dta, 1 stp, no par */ outportb (SPA + 1, 0x00); /* no interrupts */ outportb (SPA + 4, 0x03); /* RTS and DTR on */ /* Initialize the time limit */ M = *sysclk + 1; /* loop to clear the buffers */ do { tmp = inportb (SPA + 5) & 0x60; } while (tmp != 0x60); /* flush input */ while (inportb (SPA + 5) & 0x1) X = inportb (SPA); outportb (SPA + 3, 0x83); /* set DLAB */ outportb (SPA + 1, 0x00); /* baud rate is 10473 */ outportb (SPA, 0x0B); outportb (SPA + 3, 0x03); /* 8 dta, 1 stp, no par */ outportb (SPA, 0xF0); /* send the reset pulse */ /* wait until character back or timeout */ do { Y = inportb (SPA + 5); F = Y & 0x1; } while (!F && (*sysclk <= M)); if (F) X = inportb (SPA); else return 3; if (X != 0xF0) /* if more bits back than sent then there */ { /* is a device if framing error or break */ trst = TR; if ((Y & 0x18) != 0) { trst = 2; /* loop to clear the buffers */ do { tmp = inportb (SPA + 5) & 0x60; } while (tmp != 0x60); /* wait until character back or timeout */ do { Y = inportb (SPA + 5); F = Y & 0x1; } while (!F && (*sysclk <= M)); if (F) X = inportb (SPA); else return 3; } } outportb (SPA + 3, 0x83); /* set DLAB */ outportb (SPA, 0x01); /* bit rate is 115200 */ outportb (SPA + 3, 0x03); /* 8 dta, 1 stp, no par */ return trst; } /*------------------------------------------------------------------------ * This is the 1- Wire routine 'TouchByte', sometimes called 'DataByte'. * It transmits 8 bits onto the 1- Wire data line and receives 8 bits * concurrently. The global variable 'com_port' must be set to the * com port that the serial brick is attached to before calling this * routine. This com port must also be set to 115200 baud, 8 dta, 1 stp, * and no parity. This routine returns the uchar 8 bit value received. * If it times out waiting for a character then 0xFF is returned. */ uchar TouchByte (uchar outch) { uchar inch = 0, sendbit, Mask = 1; uint SPA; uint far *ptr = (uint far *) 0x00400000; ulong far *sysclk = (ulong far *) 0x0040006c; ulong M; /* get the serial port address */ SPA = *(ptr + com_port - 1); /* Initialize the time limit */ M = *sysclk + 2; /* wait to TBE and TSRE */ do { } while ((inportb (SPA + 5) & 0x60) != 0x60); /* flush input */ while ((inportb (SPA + 5) & 0x1)) inportb (SPA); /* get first bit ready to go out */ sendbit = (outch & 0x1) ? 0xFF : 0x00; /* loop to send and receive 8 bits */ do { outportb (SPA, sendbit); /* send out the bit */ /* get next bit ready to go out */ Mask <<= 1; sendbit = (outch & Mask) ? 0xFF : 0x00; /* shift input char over ready for next bit */ inch >>= 1; /* loop to look for the incoming bit */ for (;;) { /* return if out of time */ if (*sysclk > M) return 0xFF; if (inportb (SPA + 5) & 0x01) { inch |= ((inportb (SPA) & 0x01) ? 0x80 : 0x00); break; } } } while (Mask); return inch; /* return the input char */ } static uchar rom[8]; void ReadRom(void) { int i; uchar code; TouchReset(); TouchByte(0x33); for (i=0; i < 8; i++) rom[i] = TouchByte(0xFF); } #define DEVICE_ID (uchar)rom[0] #define SERIAL (unsigned long )(*((unsigned long *)(rom+1))) #define CRC (uchar)rom[7] uchar ReadMem(uint address) { TouchReset(); TouchByte(0xCC); TouchByte(0xF0); TouchByte(address & 0x00FF); TouchByte((address >> 8) & 0x00FF); return TouchByte(0xFF); } void DumpMemory(void) { uint address; TouchReset(); TouchByte(0xCC); TouchByte(0xF0); TouchByte(0x00); TouchByte(0x00); for (address = 0; address < 128; address++) { uchar asc[17]; asc[16] = '\0'; if(address % 16 == 0) printf("\n%04X ",address); printf("%02X ", (asc[address % 16] = TouchByte(0xFF))); if(address % 16 == 15) { int i; for (i = 0; i < 16; i++) if (!isalnum(asc[i])) asc[i] = '.'; printf("%16s",asc); } } printf("\n"); TouchReset(); } #define TB(x) printf("TouchByte(0x%02X)= 0x%02X\n", (x), TouchByte(x)) uchar WriteMem(uint address, uchar data) { uchar TA1, TA2, ES; TA1 = (uchar)address; TA2 = (uchar)(address >> 8); /* Write to scratchpad */ TouchReset(); TouchByte(0xCC); TouchByte(0x0F); TouchByte(TA1); TouchByte(TA2); TouchByte(data); /* Read from scratchpad */ TouchReset(); TouchByte(0xCC); TouchByte(0xAA); if ( TouchByte(0xFF) != TA1 ) printf("Error: Invalid LOW address return\n"); if ( TouchByte(0xFF) != TA2 ) printf("Error: Invalid HIGH address return\n"); if ( (ES = TouchByte(0xFF)) & 0x40) printf("Error: Overflow\n"); if ( TouchByte(0xFF) != data) printf("Invalid data returned\n"); /* COPY scratchpad */ TouchReset(); TouchByte(0xCC); TouchByte(0x55); TouchByte(TA1); TouchByte(TA2); TouchByte(ES); return 0; } int main() { uchar status; uint address; uchar data; uint single; uint portnum = 2; char filename[150]; FILE *fp; Setup(portnum); /* COM port number */ status = TouchReset(); printf("TouchReset: %s\n", TouchMemStatus[status]); ReadRom(); printf("Device ID: %d, Serial number: %08lX\, CRC: 0x%0X\n", DEVICE_ID, SERIAL, CRC); for (;;) { fflush(stdin); printf("1:Dump 2:Single 3:Polute 4:Load 5:Save mem. 6:Port num 7:Exit >>>"); switch(getchar()) { case '1': ReadRom(); printf("Device ID: %d, Serial number: %08lX\, CRC: 0x%0X\n", DEVICE_ID, SERIAL, CRC); DumpMemory(); break; case '2': printf("Address (hex):"); scanf("%x", &single); printf("Data (hex):"); scanf("%x", &data); printf("Writting : (%04x) <- %02x\n", single, data); WriteMem(single, data); break; case '3': printf("Data for polution (hex):"); scanf("%X", &data); for(address = 0 ; address < 128; address++) WriteMem(address, data); break; case '4': printf("Filename to read:"); scanf("%s", filename); fp = fopen(filename, "r"); if (fp == NULL) { perror(filename); break; } for (address = 0; address < 128; address++) { fscanf(fp, "%x", &data); printf("%02x%c", data, address % 16 == 15 ? '\n' : ' '); WriteMem(address, data); } fclose(fp); break; case '5': printf("Filename to write:"); scanf("%s", filename); fp = fopen(filename, "w"); if (fp == NULL) { perror(filename); break; } for (address = 0; address < 128; address++) { data = ReadMem(address); fprintf(fp, "%02x%c", data, address % 16 == 15 ? '\n' : ' '); } fclose(fp); break; case '6': printf("COM port number (1,2):"); scanf("%d", &portnum); Setup(portnum); /* COM port number */ status = TouchReset(); printf("TouchReset: %s\n", TouchMemStatus[status]); break; case '7': return 0; default: printf("Input error\n"); } } }