/* Filename: tw523.c ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º TW523 Control Program º º for an IBM PC Clone º º driver software º º Jonathan M. Chattin º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */ #include int pindx = 0; /* port index */ int pbase = 0; /* base of port */ int zero = 0; /* zero crossing flag */ int rdtmr = 0; /* read timer address */ /* transmit translation table */ int tbltx[] = {0x6,0x7,0x4,0x5,0x8,0x9,0xa,0xb, 0xe,0xf,0xc,0xd,0x0,0x1,0x2,0x3}; /* receive translation table */ int tblrx[] = {0xc,0xd,0xe,0xf,0x2,0x3,0x0,0x1, 0x4,0x5,0x6,0x7,0xa,0xb,0x8,0x9}; int tw523ok(int index) { int i, zcnt; int far *ptable; if((index < 0)||(index > 6)) /* ensure valid index */ return(-1); pindx = index; /* assign global */ if(atorxt() != 0) /* must find read timer */ return(-2); ptable = MK_FP(0, 0x400); /* get port table pointer */ pbase = ptable[pindx]; /* get base */ if(pbase == 0) /* invalid port */ return(-3); if(pindx < 4) outportb(pbase + 4, 1); /* init RS232 signals */ else { outportb(pbase, 0); /* init parallel signals */ outportb(pbase + 2, 0); } for(i = 0; i < 250; i++) /* delay for power-up */ dly1000(); testz(); /* clear status */ for(zcnt = 0, i = 0; i < 20; i++) /* in 20 ms */ { dly1000(); if(testz()) /* should be 2 or 3 zero xings */ zcnt++; } if((zcnt != 2) && (zcnt != 3)) /* 2 or 3 zero xings ? */ return(-4); /* oops no tw523 there */ testz(); /* clear status */ disable(); while(testz() == 0); /* wait for zero xing */ for(i = 0; i < 7; i++) /* check duty cycle */ dly1000(); /* wait 7ms */ if(testz()) /* better not be zero xing */ { enable(); return(-5); /* oops bad tw523 there */ } dly1000(); /* delay 2.6 more ms */ dly1000(); dly0600(); if(!testz()) /* better be zero xing */ { enable(); return(-6); /* oops bad tw523 there */ } enable(); return(0); /* yes, all is fine */ } sendx10(int house, int unfu) { int i; for(i = 0; i < 2; i++) /* send transmissions 2x */ { send1(); send1(); send1(); send0(); sendb(house & 0x1); sendb(house & 0x2); sendb(house & 0x4); sendb(house & 0x8); sendb(unfu & 0x1); sendb(unfu & 0x2); sendb(unfu & 0x4); sendb(unfu & 0x8); sendb(unfu & 0x10); } waitz(); /* always wait a bit */ waitz(); waitz(); waitz(); waitz(); waitz(); } int recvx10(int *house, int *unfu) /* receive a code if available */ { int i; if(!recvh()) /* check for sync */ return(1); /* no, quit */ if(!recvh()) /* check for sync */ return(-1); /* no, quit */ for(i = 0; i < 3; i++) /* prevent endless loop */ { if(recvh() == 0) /* wait for sync done */ break; } if(i == 3) /* if in loop too long */ return(-2); *house = 0; /* init return values */ *unfu = 0; *house |= recvb() ? 0x1 : 0 ; *house |= recvb() ? 0x2 : 0 ; *house |= recvb() ? 0x4 : 0 ; *house |= recvb() ? 0x8 : 0 ; *unfu |= recvb() ? 0x1 : 0 ; *unfu |= recvb() ? 0x2 : 0 ; *unfu |= recvb() ? 0x4 : 0 ; *unfu |= recvb() ? 0x8 : 0 ; *unfu |= recvb() ? 0x10: 0 ; return(0); /* mark valid reception */ } sendb(int bit) /* send a full bit */ { if(bit) { send1(); send0(); } else { send0(); send1(); } } send1() /* send a half bit 1 */ { if(pindx < 4) /* if serial */ { disable(); waitz(); outportb(pbase + 4, 3); dly1000(); outportb(pbase + 4, 1); dly1778(); outportb(pbase + 4, 3); dly1000(); outportb(pbase + 4, 1); dly1778(); outportb(pbase + 4, 3); dly1000(); outportb(pbase + 4, 1); enable(); } else /* if parallel */ { disable(); waitz(); outportb(pbase, 0xff); dly1000(); outportb(pbase, 0x00); dly1778(); outportb(pbase, 0xff); dly1000(); outportb(pbase, 0x00); dly1778(); outportb(pbase, 0xff); dly1000(); outportb(pbase, 0x00); enable(); } } send0() /* send a half bit 0 */ { waitz(); } int recvb() /* receive full bit */ { int retc; retc = recvh(); /* get bit value */ waitz(); /* discard next half bit */ return(retc); } int recvh() /* get the half bit on the line */ { int retc; disable(); waitz(); dly0600(); retc = samprcv(); enable(); return(retc); } int samprcv() /* sample the half bit on the line */ { if(pindx < 4) { if(inportb(pbase + 6) & 0x10) return(1); else return(0); } else { if(inportb(pbase + 2) & 0x02) return(1); else return(0); } } waitz() /* wait for zero xing */ { while(!testz()); } int testz() /* test for zero xing */ { int temp; if(pindx < 4) return((inportb(pbase + 6) & 2) ? 1 : 0); else { temp = zero; /* remember previous zero */ zero = inportb(pbase + 2) & 0x08; /* get new zero */ return((zero ^ temp) ? 1 : 0); } } int atorxt() /* find terminal count bit */ { int x, i, j; x = inportb(0x61); x = (x & 0xfc) | 0x01; outportb(0x61, x); /* enable gate disable speaker */ outportb(0x43, 0xb6); /* set mode */ outportb(0x42, 0x00); /* set time constant */ outportb(0x42, 0x01); for(rdtmr = 0x61; rdtmr <= 0x62; rdtmr++) { x = inportb(rdtmr) & 0x20; for(j = 0, i = 0; i < 1000; i++) { if(x == (inportb(rdtmr) & 0x20)) continue; /* no change in bit */ x ^= 0x20; j++; } if(j >= 4) /* if 4+ transitions */ return(0); /* found correct bit */ } return(-1); /* timer read not found */ } dly0600() /* delay 0.600ms */ { int x; x = inportb(0x61); x = (x & 0xfc) | 0x01; outportb(0x61, x); /* enable gate disable speaker */ outportb(0x43, 0xb0); /* set mode */ outportb(0x42, 0xac); /* set time constant */ outportb(0x42, 0x02); while((inportb(rdtmr) & 0x20) == 0); } dly1000() /* delay 1ms */ { int x; x = inportb(0x61); x = (x & 0xfc) | 0x01; outportb(0x61, x); /* enable gate disable speaker */ outportb(0x43, 0xb0); /* set mode */ outportb(0x42, 0x89); /* set time constant */ outportb(0x42, 0x04); while((inportb(rdtmr) & 0x20) == 0); } dly1778() /* delay 1.778ms */ { int x; x = inportb(0x61); x = (x & 0xfc) | 0x01; outportb(0x61, x); /* enable gate disable speaker */ outportb(0x43, 0xb0); /* set mode */ outportb(0x42, 0x29); /* set time constant */ outportb(0x42, 0x08); while((inportb(rdtmr) & 0x20) == 0); }