/*
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");
}
}
}