Source file: /~heha/messtech/virtex.zip/PROG_B1.C

#include <string.h>
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
//#define epp
#define BYTEREV 2	/* Byte-Reversion (Motorola) */
#define BITREV 4	/* Bit-Reversion (krankhaft) */

typedef unsigned long ULONG;
typedef unsigned int  UINT;
typedef unsigned char UCHAR;
typedef float TREAL;
typedef struct {
 int verz[16];
 TREAL frequenz;	/* in MHz */
 UINT CodeWortPos;
 UINT CodeWortNeg;
 UINT MaskePos;
 UINT MaskeNeg;
 UINT Pulslen;
 ULONG Zykluszeit;
}TConfig,*PConfig;
//################################################################################
//# global values
//################################################################################
UINT LptBase= 0x378;
TREAL fosz=16.0;	/*MHz*/
/* Current Config */
ULONG IcdWort;
int IcdWortLen;
TConfig cc={{0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1},0.96,0x1FFF,0x0000,-1,-1,4,100000};
/* Vorberechnete Konfigurationen */
TConfig pc[5]={
 {{0,1,2,3,4,4,5,5,5,5,5,4,4,3,2,1},		  1,0x1FFF,0x0000,-1,-1,4,100000},
 {{0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0},	  5,0xF00F,0xE0F0,-1,-1,4,100000},
 {{0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0},	 10,0x00F0,0x100F,-1,-1,4,100000},
 {{8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1},		 33.3333,0x9001,0x0000,0x0F30,0x0F30,4,100000},
 {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},	100,0x1FFF,0x0000,-1,-1,4,100000}};

UCHAR bitrev(UCHAR b) {
/* Bitreversion (Spiegelung) im Byte */
 UCHAR c;
 int i;
 for (c=0,i=8; i--;) {
  c<<=1;
  if (b&1) c|=1;
  b>>=1;
 }
 return c;
}

int bitcalc(TREAL fdesired) {
 TREAL fintern,pq,f,ff;	/*in MHz*/
 int ip,iq,p,q,m,i;
 ULONG bits;			/*22 bits*/
 UCHAR *bptr;
 if (fdesired<(TREAL)50/128) return 0;
 if (fdesired>100) return 0;
 for (fintern=fdesired, m=0; fintern<50; fintern*=2, m++);
 pq=fintern/(fosz*2);
 ff=1E30;
 for (iq=3; iq<=129; iq++) {
  ip=(int)(pq*iq+0.5);
  f=fabs((TREAL)ip/iq-pq);
  if ((ip>=4) && (ip<=130) && (f<ff)) {
   p=ip;
   q=iq;
   ff=f;			/* Minimalen Fehler suchen */
  }
 }
 bits=(p-3);			/* Bits zusammensetzen */
 bits=bits<<1|1;
 bits=bits<<3|m;
 bits=bits<<7|(q-2);
 bits=bits<<4|(fintern>=80?8:0);

 IcdWort=m=0;	/* Bits umkehren und "stuffen" */
 IcdWortLen=22;
 for (i=22; i--; ) {
  IcdWort>>=1;
  if (bits&1) {
   IcdWort|=0x80000000;
   if (++m==3) {
    IcdWort>>=1;	/* Null einschieben */
    IcdWortLen++;
    m=0;
   }
  }else{
   m=0;
  }
  bits>>=1;
 }
 IcdWort>>=(32-IcdWortLen);	/* wieder lsb-bündig machen */
 return 1;
}

TREAL bitshow(int silent) {
/* reverse Rechnung und Anzeige (zur Kontrolle) */
 ULONG bits,iw;
 int i,p,q,m,d,iwl;
 TREAL f,fi;
 char s[32];
 UCHAR *bptr;	/* Byte-Zeiger */

 iw=IcdWort;
 bits=m=0;
 iwl=IcdWortLen;		/* Gesamt-Bitzähler (muß 22 ergeben) */
 for (i=IcdWortLen; i--; ) {
  bits>>=1;
  if (iw&1) {
   bits|=0x80000000;
   if (++m==3) {
    iw>>=1;
    if (iw&1 && !silent)
      puts("FEHLER: mehr als 3 aufeinanderfolgende 1-Bits!");
    iwl--;
    i--;
    m=0;
   }
  }else{
   m=0;
  }
  iw>>=1;
 }
 bits>>=(32-iwl);		/* schön rechtsbündig machen */
 if (!silent) {
  if (iwl!=22) puts("FEHLER: resultierende Bitzahl ungleich 22!");
  ultoa(bits,s,2);
  printf("Bits \"ohne Füllung\" und umgekehrt: %022s (%06lXh)\n",s,bits);
 }
 i=bits&0x0F; bits>>=4;	/* Bitfelder extrahieren (portabel statt STRUCT) */
 q=(bits&0x7F)+2; bits>>=7;
 m=bits&0x07; bits>>=3;
 d=bits&0x01; bits>>=1;
 p=(bits&0x7F)+3;
 if (!silent) printf("p=%d, d=%d, m=%d, q=%d, i=%d\n",p,d,m,q,i);
 fi=2*fosz*p/q;
 m=1<<m;
 f=fi/m;
 if (!silent) {
  printf("f(intern)=%1.6gMHz, f(extern)=%1.6gMHz\n",fi,f);
  if ((fi<80)&&(i!=0)||(fi>=80)&&(i!=8)) puts("FEHLER: i ungültig!");
  if (fi<50 || fi>100) puts("FEHLER: f(intern) ungültig!");
 }
 return f;
}

char* code2str(char *sp) {
/* Umwandlung Sendecode in Sendesignalfolge (ASCII-Kunst:-)
 * liefert Zeiger auf String-Ende (auf die Null) */
 UINT p,n;
 p=cc.CodeWortPos&0x1FFF; n=cc.CodeWortNeg&0x1FFF;
 while (p || n) {
  *sp=' ';
  if (p&1) *sp='^';
  if (n&1) *sp='v';
  if (n&p&1) *sp='#';
  sp++;
  p>>=1;
  n>>=1;
 }
 *sp='\0';
 return sp;
}

int str2code(char *s) {
/* benutzerfreundlichere ternäre Sendesignalfolgen-Eingabe ("Code") */
 UINT p,n;
 int i;
 p=n=0;
 i=13;
 for ( ;*s && i ;s++) {
  switch (tolower(*s)) {
   case '#': p>>=1; n>>=1; p|=0x1000; n|=0x1000; i--; break;
	/* Eingabe der eigentlich verbotenen Kombination ermöglichen */
   case 'p':
   case '^':
   case '+':
   case 'h':
   case '1': p>>=1; n>>=1; p|=0x1000; i--; break;
   case 'n':
   case 'v':
   case 'L':
   case '-': p>>=1; n>>=1; n|=0x1000; i--; break;
   case '0':
   case '.':
   case ' ': p>>=1; n>>=1; i--; break;
   default: puts("Falsche Eingabe!"); return 0;
  }/*switch*/
 }/*for*/
 p>>=i; n>>=i;		/* rechtsbündig machen */
 if (~p&~n&1) {
  puts("Ungültige Eingabe (Startbit [LSB] muß <>0 sein)");
  return 0;
 }
 cc.CodeWortPos=p;
 cc.CodeWortNeg=n;
 return 1;
}

void KanalInfo(void){
 int i;
 char s[64], *sp;

 puts(" (^=pos, v=neg)\n");
 for (i=0; i<16; i++) {
  printf(" Kanal %2d : %-3d ",i,cc.verz[i]);
  if (cc.verz[i]<40) {
   memset(s,'·',sizeof(s));
   sp=s+cc.verz[i];
  }else{
   strcpy(s,"-->  ");
   sp=s+5;
  }
  code2str(sp);
  puts(s);
 }
}

int input(const char *prompt,char *data, int datalen) {
/* Eingabefunktion, liefert Anzahl eingegebener Zeichen und
 * nullterminierten String nach data */
 int i;
 printf("%s: ",prompt);
 fflush(stdout);
 fgets(data,datalen,stdin);
 i=strlen(data);
 if (i && data[i-1]=='\n') {
  data[--i]='\0';	/* ENTER abhacken */
 }
 return i;
}

void more(const char *msg) {
/* ein Prompt vor dem Bildschirmlöschen */
 char s[16];
 printf("%s",msg?msg:" ENTER ");
 fflush(stdout);
 fgets(s,sizeof(s),stdin);
}

void main_menu(void) {
 char s[16];

 puts("");
 puts("\t########################################################");
 puts("\t# TU Chemnitz, Professur Schaltungs- und Systementwurf #");
 puts("\t########################################################");
 puts("");
 printf("    Momentane Konfiguration: "
   "Frequenz = %1.6g MHz, Codewort = %s\n\n",
   cc.frequenz,(code2str(s),s));

 puts("\t\tHauptmenü");
 puts("\t\t─────────\n");
 puts("\t\tLPT-Portadresse . . . . . . . . . (l)");
 puts("\t\tVoreinstellung laden  . . . . . (1-5)");
 puts("\t\tPLL-Oszillatorfrequenz stellen  . (i)");
 puts("\t\tKanalverzögerungen einstellen . . (d)");
 puts("\t\tPulslänge einstellen  . . . . . . (p)");
 puts("\t\tMaske einstellen  . . . . . . . . (m)");
 puts("\t\tZykluszeit einstellen . . . . . . (w)");
 puts("\t\tTernärcode einstellen . . . . . . (c)");
 puts("\t\tStarten . . . . . . . . . . . . . (r)");
 puts("\t\tStarten im Einzelschritt  . . . . (s)");
 puts("\t\tEnde  . . . . . . . . . . . . . (q,e)\n\n");
}


void ConfigStart(void) {
 puts("\n\n\n"
      " Momentane Konfiguration:\n"
      " ────────────────────────\n");
}

void load_pre(int n) {
 cc=pc[n];
 bitcalc(cc.frequenz);
}

//################################################################################
//# Funktion delay
//################################################################################
void delay_menu(void){
 int i;
 char s[16];

 ConfigStart();

 KanalInfo();

 puts("\n\nNeue Kanalverzögerungen:\n────────────────────────\n");
 for (i=0; i<16; i++) {
  sprintf(s,"Kanal %2d",i);
  if (input(s,s,sizeof(s))) cc.verz[i]=atoi(s);	/*keine Leereingabe*/
 }
}

//################################################################################
//# Funktion lpt
//################################################################################
void lpt_port(void){
 int i;
 char s[8];

 ConfigStart();

 printf(" Portadresse ist %03Xh\n\n",LptBase);
 if (input(" Neue Adresse (hex)",s,sizeof(s))) LptBase=strtoul(s,NULL,16);
}

//###############################
//# Funktion Zykluszeit-Eingabe #
//###############################
void enter_Zykluszeit(void){
 int i;
 char s[8];

 ConfigStart();

 printf(" Zykluszeit ist %lu oder %g ms\n\n",cc.Zykluszeit,
   (TREAL)cc.Zykluszeit/cc.frequenz*0.001);
 if (input(" Neue Zykluszeit",s,sizeof(s))) cc.Zykluszeit=strtoul(s,NULL,0);
}

//###############################
//# Funktion Pulslängen-Eingabe #
//###############################
void enter_Pulslen(void){
 int i;
 char s[8];

 ConfigStart();

 printf(" Pulslänge ist %u\n\n",cc.Pulslen);
 if (input(" Neue Pulslänge",s,sizeof(s))) cc.Pulslen=strtoul(s,NULL,0);
}

//###########################
//# Funktion Masken-Eingabe #
//###########################
void enter_Maske(void){
 int i;
 char s[18];

 ConfigStart();
 itoa(cc.MaskePos,s,2);

 printf(" Maske=%sb\n\n",s);
 if (input(" Neue Maske (binär)",s,sizeof(s)))
  cc.MaskePos=cc.MaskeNeg=strtoul(s,NULL,2);
}

//################################################################################
//# Funktion icd
//################################################################################
void icdprog_menu(void){
 char s[32];
 TREAL f;

 ConfigStart();
 ultoa(IcdWort,s,2);
 printf(" Programmierwort: %0*s (%06lXh)\n\n",IcdWortLen,s,IcdWort);
 printf(" Programmierwortlänge: %d\n\n",IcdWortLen);
 bitshow(0);

retry:
 if (input("\n Neue Frequenz [MHz]",s,sizeof(s))) {
  f=strtod(s,NULL);
  if (!bitcalc(f)) {
   puts("FEHLER: Zahl ungültig");
   goto retry;
  }
  cc.frequenz=f;
  puts("");
  bitshow(0);
  more(NULL);
 }
}

//################################################################################
//# Funktion code
//################################################################################
void code_menu(void){
 int i;
 char s[32],*sp;

 ConfigStart();
 ultoa(cc.CodeWortPos,s,2);
 printf(" Codewort positiv: %013s (%04Xh)\n",s,cc.CodeWortPos);
 ultoa(cc.CodeWortNeg,s,2);
 printf(" Codewort negativ: %013s (%04Xh)\n",s,cc.CodeWortNeg);
 code2str(s);
 printf(" Ternärcode zus. : %s\n\n├───────────╢\n",s);
 while (input(" Codewort (P=^=+=1=positiv, N=v=-=negativ, 0=.= =Null)",s,sizeof(s))
  && !str2code(s));
}


//################################################################################
//# Funktion run
//################################################################################
int dreher;

int CheckBusy(void) {
 printf("%c\b","\\|/-"[dreher++&3]);
 return inportb(LptBase+1)&0x80;
}

void ByteOut(int addr,int value, int stepping) {
 int i;
 if (stepping) printf(addr ? "Adresse: %-4d(%02Xh) " :
   "  Datum: %-4d(%02Xh)\n", value, value);
#ifdef epp
 outportb(LptBase+(addr ? 3 : 4),value);
 delay(10);
#else
 outportb(LptBase+0, value);
 outportb(LptBase+0, value);
 outportb(LptBase+0, value);
 outportb(LptBase+2, addr ? 0x0D : 0x07);
 for (i=500; i--; ) if (!CheckBusy()) goto raus;
 putchar('L');				/* Fehler: Leitung klemmt */
raus:
 outportb(LptBase+2, 0x05);
 if (!CheckBusy()) putchar('H');	/* Fehler: Leitung klemmt */
#endif
 if (stepping) more(NULL);
}

void PutByte(UCHAR addr, UCHAR value, int stepping) {
/* Ausgabe Byte <value> auf ECP-Adresse <addr> */
 ByteOut(1,addr,stepping);
 ByteOut(0,value,stepping);
}

void PutWort(UCHAR addr, ULONG value, int vbytes, UCHAR stepping) {
/* Ausgabe eines Wortes <value> mit angebbarer Bytezahl <vbytes>
 * auf aufeinanderfolgende ECP-Adressen <addr>, beginnend mit LSByte */
 UCHAR b;
 if (!vbytes) ByteOut(1,addr,stepping&1);
 if (stepping&BYTEREV) {
  for(addr+=vbytes; vbytes--; ) {	/* absteigende Adressen nehmen */
   b=value&0xFF;
   if (stepping&BITREV) b=bitrev(b);
   PutByte(--addr,b,stepping&1);
   value>>=8;
  }
 }else{
  for(; vbytes--; ) {
   b=value&0xFF;
   if (stepping&BITREV) b=bitrev(b);
   PutByte(addr++,b,stepping&1);
   value>>=8;
  }
 }
}

int run_data(int stepping){
 int i,cycle,cycles=1;
 char s[8];

 puts("\n");
 if (!stepping && input(" Zyklenzahl [1]",s,sizeof(s))) cycles=atoi(s);
 puts("Init LPT-EPP...");
 outportb(LptBase+2,5);
 delay(1000);
 puts("\nBeginn Programmierung ");
 for(cycle=0; cycle<cycles; cycle++) {
  if (!stepping) putchar('.');
  PutWort(0x52,0,0,stepping);
  PutWort(0x00,cc.CodeWortPos,2,stepping);
  PutWort(0x02,cc.CodeWortNeg,2,stepping);
  PutWort(0x14,IcdWort,4,stepping|BITREV);
  PutByte(0x18,IcdWortLen,stepping);
  for (i=0; i<16; i++) {
   PutByte(0x04+i,cc.verz[i],stepping);
  }
  PutByte(0x19,cc.Pulslen,stepping);
  PutWort(0x1A,cc.Zykluszeit,3,stepping|BYTEREV);
  PutWort(0x1D,cc.MaskePos,2,stepping|BITREV);
  PutWort(0x1F,cc.MaskeNeg,2,stepping|BITREV);
  if (stepping) puts("Fertig mit Laden, nun ICD-Programmierung");
  PutWort(0x50,0,0,stepping);
  sleep(1);
  if (stepping) puts("Fertig mit ICD-Programierung, nun Pulsausgabe (Action)");
  PutWort(0x51,0,0,stepping);
  delay(300);
 }
 more("Fertig!");
 return 0;
}

//################################################################################
//# Funktion main
//################################################################################
void main(void) {
 int i;
 char s[8];

 bitcalc(cc.frequenz);

 while (1) {
  main_menu();
retry:
  input("?",s,sizeof(s));
  switch (tolower(*s)) {;
   case 'l': lpt_port(); break;
   case 'f':
   case 'i': icdprog_menu(); break;
   case 'v':
   case 'd': delay_menu(); break;
   case 'z': enter_Zykluszeit(); break;
   case 'p': enter_Pulslen(); break;
   case 'm': enter_Maske(); break;
   case 't':
   case 'c': code_menu();  break;
   case 'r': run_data(0); break;
   case 's': run_data(1); break;
   case '1': load_pre(0); break;
   case '2': load_pre(1); break;
   case '3': load_pre(2); break;
   case '4': load_pre(3); break;
   case '5': load_pre(4); break;
   case 'q':
   case 'e': return;
   default: puts("\t\tUngültige Eingabe!"); goto retry;
  }
 }
}

Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded