#include <stdio.h>
#include <math.h>
#include <dos.h>

#define n360    3600         /* scale  3600 -- 360 degree */
#define n180    1800         /* shift  south=1800         */
#define slit    12
#define t_gap   28
#define d120    30           /* origion 120 */

#define p824    788

#define xstep 192
#define ystep 144
#define dtime   1
#define ss    1.2                /* 1.25 time speed */
#define WORD  unsigned short
#define wBaseAddr 0x240

double pi,twopi,phi,sphi,cphi;
double angle,alpha,delta,s0;
int z0,z1,z2,z3;

main(ac,av)
int ac; char *av[];
{
  char c;
  int i,j;
  float t,d,t1,d1;
  int gap,dummy,k,p0,p1,p2,p3;
  int time_count;

  WORD  dx,dy;
  float x,y;
  if(ac<3){
    printf("\n\t  Usage: disptmc 15.0  0\n");
    printf("\n\t  means: RA_direct +, 15 arcsec/sec; Dec not moved\n");
    printf("\n\t         disptmc 200 -400.9");
    printf("\n\t  means: RA +, 200.0 arcsec/sec; Dec -, 400.9 arcsec/sec\n");
    printf("\n\t  speed: RA  0, 0.046~2000\n");
    printf("\t\t 0.046 <+-0.001   90~0.01   300~0.1   880~1  2000 >2\n");
    printf("\n\t  speed  Dec 0, 0.035~1500\n");
    printf("\t\t 0.035 <+-0.001   76~0.01   275~0.1   776~1  1500 >2\n");
    printf("\n\t   Notice: while RA=(80~120), motor has noice\n");
    exit(0);
  }
  sscanf(av[1],"%f",&x);
  dx=1; if(x<0.){ dx=0; x=-x; }
  if(x>2000.)goto toofast;

  sscanf(av[2],"%f",&y);
  dy=1; if(y<0.){ dy=0; y=-y; }
  if(y>1500.)goto toofast;

  k=0;  if(dx)k+=4;  if(dy==0)k+=8;

  outportb(wBaseAddr+5,k);
  startcw(1,&x,xstep);
  startcw(3,&y,ystep);
  printf("START move\n");

  wpos(1,0);
  for(i=0;i<21;i++)for(j=0;j<80;j++)printf(" ");
  time_count=25;
  pi=4.*atan(1.);  twopi=pi+pi;
  phi=(40.+23/60.+36/3600.)*pi/180.;
  sphi=sin(phi); cphi=cos(phi);
  goto l11;

l10:       /* get current time_angle & delta position */
  sleep(1);
l11:
  p0=take_dome();
  take_4(4);
  d=z2+z1/60.+z0/3600.;
  if(z3==1)d+=100.; if(z3==10)d=-d;
  take_4(0);
  t=z3+z2/60.+z1/3600.;
  if(z3>5&&z3<19)printf("\7");

  wpos(3,0);
  tak();                     /* display 4 row & for get s0 */
  angle=t/12.*pi;
  alpha=s0/12.*pi-angle;
  delta=d/180.*pi;
  zen();
  galactic();
  if(keyin()!=-1)goto stopmove;

  printf("\nreal_disp--> p0: %04d %4d\n",p0,time_count);
  p1=aa(t,d,&gap);
  t+=0.3;
  p2=aa(t,d,&dummy);  /* get 20 minute_after position */
  if(p1==0){ printf("too low "); goto l10; }
  printf("should_be--> p1: %04d %4d\n",p1,gap);
  printf("20min_late-> p2: %04d\n",p2);
  if(p2 > p1) { p3=p1+gap; if(p2 < p3) { p3=p2; gap=p3-p1; } }
  else {p3=p1-gap; if(p2 > p3) { p3=p2; gap=p1-p3; } }
  printf("will_be----> p3: %04d",p3);
/* get display position */
  dummy=p1-p0; if(dummy<0)dummy=-dummy;
  time_count++;
  k=p3-p0; if(k<0)k=-k; k/=4;    if(k>gap)time_count++;
  if(time_count<d120)goto l10;
/*  printf("\ndummy gap p0 %d %d %d",dummy,gap,p0); */
  if(dummy<=gap||p2==0||dummy<20)goto l10;
/* turn */
  if(p3 > p0) printf(" ++++%5d",p3-p0);
  if(p3 < p0) printf(" ----%5d",p0-p3);
  s_dome(p3);
  time_count=0;        /* avoid +-moving no stop */
  goto l10;

stopmove:
  wpos(18,1);
  stopcw(1,&x,xstep);
  stopcw(3,&y,ystep);
  printf("STOP move\n");
  outportb(wBaseAddr+5,0xff);  /* switch off */
  printf("\n\t******** STOP MOVE (switch to normal status) *********\n");
  for(i=0;i<3;i++)for(j=0;j<80;j++)printf(" ");
  exit(0);
toofast:
  printf("\n\n\t Set parameter error, too fast!\n");
}

tak()
{
  int seg,off,i,j,k;
  int iy,im,id;
  double d1,d2;
  unsigned t[4];
  long a;
  seg=peek(0,0x22);
  off=peek(0,0x1fc);
  for(i=0;i<4;i++){t[i]=peek(seg,off); off+=2;}
  a=(long)t[1]*0x10000+t[0];      /* beijing time */
  i=a/36000; a%=36000; i-=8;
  j=a/600;   a%=600;  k=a/10;    off=a%10;
  d2=(i+j/60.+k/3600.+off/36000.)/24.;
  asm mov ah,2ah
  asm int 21h
  asm mov iy,cx
  asm mov id,dx
  im=id/256; id%=256;
  if(i>=16)id--;
  printf("UT %d %02d %02d  %02d:%02d:%02d\n",iy,im,id,i,j,k);
  fjd(iy,im,id,&d1);
  d1+=d2;
  printf("JD %0.5lf\n",d1);
  s0=(long)t[3]*0x10000+t[2];      /* sidereal time */
  s0=s0/36000.;
}

aa(t,d,hh)
float t,d;
int *hh;
{
  double delta,hour,sinh,cosh,sinA,cosA,a,h;
  double s_delta,c_delta,s_hour,c_hour;
  int ia;
  delta=d*twopi/360.;
  hour=t*twopi/24.;
  s_delta=sin(delta); c_delta=cos(delta);
  s_hour=sin(hour);   c_hour=cos(hour);
  sinh=sphi*s_delta+cphi*c_delta*c_hour;
  cosh=sqrt(1.-sinh*sinh);
  sinA=c_delta*s_hour/cosh;
  cosA=(sphi*c_delta*c_hour-cphi*s_delta)/cosh;
  h=atan(sinh/cosh);
  a=atan(sinA/cosA);
  if(cosA < 0.) a+=pi;
  if(a > pi )a-=twopi;
  a=a*180./pi;
  a=a*n360/360.+n180+0.5;
  ia=a;
  *hh= (h < 1.57) ? slit/cos(h) : 399;
  if(*hh>399)*hh=399;
/*
   a: unit in display; if a=0 then mean star too low;
   h: dome_slit width in difference high angle;
*/
  return(ia);
}

wpos(x,y)
int x,y;
{
  asm mov dh,x
  asm mov dl,y
  asm mov bh,0
  asm mov ah,2
  asm int 10h
}

s_dome(p1)
int p1;
{
  char a[5];
  int  i;
  i=p1; if(i>=3600)i-=3600;
  sprintf(a,"%04d",i);
  if(peek(0,0x26e)!=0)return;       /* 41205 */
  for(i=0;i<4;i++)pokeb(0,0x2ea+i,a[i]);  pokeb(0,0x2e9,'D');
}

take_dome()     /* [8]+[9]*100 */
{
  char b[5];
  int i;
  for(i=0;i<4;i++)b[i]=peekb(0,0x2fa+i); b[4]=0; sscanf(b,"%d",&i);
  return (i);
}

take_4(int n)     /* zd=0+n,zs=1+n,zm=2+n,zh=3+n */
{
  int off;
  off=0x1e0+n;
  z0=peekb(0,off);
  z1=peekb(0,off+1);
  z2=peekb(0,off+2);
  z3=peekb(0,off+3);
  return;
}

keyin()
{
  asm mov ah,6
  asm mov dl,0ffh
  asm int 21h
  asm mov cx,0ffffh
  asm jz keyin1
  asm mov ah,0
  asm mov cx,ax
keyin1:
  return (_CX);
}

fjd(iy,im,id,d1)
int iy,im,id;
double *d1;
{
  int i,j;
  double d0=2433338.5;
  i=(im+9)*0.09;
  i=(i+iy-1900)*1.75+0.01;
  j=30.56*im;
  j=(iy-1950)*367+id+j-i;
  *d1=d0+j;
}

/* ** GALACTIC  converts celestial coordinates */
galactic()
{
  float a0,theta,l0;
  float x1,x2,xl,xb,cn2;
  cn2=pi/180.;
  a0=282.25*cn2;
  theta=62.6*cn2;
  l0=33.0*cn2;
  x1=cos(delta)*cos(alpha-a0);
  x2=cos(delta)*sin(alpha-a0)*cos(theta)+sin(delta)*sin(theta);
  xl=atan2(x2,x1)+l0;  if(xl<0)xl+=2.0*pi;
  xb=asin(sin(delta)*cos(theta)-cos(delta)*sin(alpha-a0)*sin(theta));
  printf("xl %f\n",xl);
  printf("xb %f\n",xb);
}

zen()
{
  double x,z;
  x=sin(delta)*sphi+cos(delta)*cos(angle)*cphi;
  z=sqrt(1.-x*x);
  z=90.-atan2(x,z)*180./pi;
  x=1./x-1.;
  x=1.+x-x*(0.0018167+x*(0.002875+x*0.0008083));
  printf("Zen  %f\n",z);
  printf("Mass %f\n",x);
}


startcw(char chip, float *xy, WORD step)
{
  float f,x,z;
  WORD  i,j,k;
  x=*xy;
  if(x<=0.)return;
               j=512;
  if(x>step/64)j=32;
  if(x>step/8) j=2;
  f=8000./j;
  z=f*step/x+0.5; if(z>65535)z=65535; k=z;
/*printf("set Frequcenc: %d %d\n",j,k);*/
  tmc10_c1(chip,j);
  if(j>2)goto l20;
  i=20000;
/*printf("startFreq: %d-%d\n",(int)(f*step/i),i);*/
  if(i>k){ tmc10_c2(chip,i);  delay50(dtime);}
L10:
  if(i>k){
    tmc10_c2(chip,i);  delay50(dtime);
    printf(".");
    i/=ss;
    goto L10;
  }
l20:
  tmc10_c2(chip,k);
}

stopcw(char chip, float *xy, WORD step)
{
  float f,x,z;
  WORD  i,j,k;
  x=*xy;
  if(x<=0.)return;
               j=512;
  if(x>step/64)j=32;
  if(x>step/8) j=2;
  f=8000./j;
  z=f*step/x+0.5; if(z>65535)z=65535; k=z;
  tmc10_c1(chip,j);
  if(j>2)goto l30;
  i=20000;
L20:
  if(k<i){
    k*=ss;
    tmc10_c2(chip,k); delay50(dtime);
    printf(".");
    goto L20;
  }
l30:
/*outportb(wBaseAddr+3,0x30);      change to counter status, no signal out */
  tmc10_c2(chip,65535);
  tmc10_c1(chip,65535);
}

tmc10_c1(char chip, WORD speed)
{
  outportb(wBaseAddr+4,chip);
  outportb(wBaseAddr+3,0x76);
  outportb(wBaseAddr+1,speed&0xff);
  outportb(wBaseAddr+1,speed>>8);
}

tmc10_c2(char chip, WORD speed)
{
  outportb(wBaseAddr+4,chip);
  outportb(wBaseAddr+3,0xb6);
  outportb(wBaseAddr+2,speed&0xff);
  outportb(wBaseAddr+2,speed>>8);
}

delay50(int i)
{
  int j,k,m;
  m=0;
  j=peek(0,0x46c);
l10:
  k=peek(0,0x46c);
  if(j==k)goto l10;
  m++;
  if(m>i)return;
  j=k;
  goto l10;
}
/*
main()
{
  unsigned int step=192,i,j;
  long k;
  float x,f;
  for(i=1;i<9000;i++){ x=i*0.1;
  j=512;
  if(x>step/64)j=32;
  if(x>step/8)j=2;
  f=8000./j;
  k=f*step/x;
  printf("%6.1f %d %ld\n",x,j,k);
  }
}
*/
