Numeryx Home

NCPLUS

Copyright © 1988, 2007 by Gil Hagiz
Certificate of Registration No. TXu 894-323
United States Copyright Office

The code below is part of the copyright registration
That's about 10% of the entire code

{NCPLUS.PAS  Copyright (C) 1988, 1999 by Gil Hagiz}

Program NCPLUS;

{$I nodebug}
{$M $8000, $20000, $A0000}

uses
Dos,
crt,
ed,                    {link to the editor}
ugrp,                  {screen}
uvar,                  {nc vars}
ini,                   {read INI file}
tbu,                   {Teach box unit}
ncpar,                 {parameter table}
tools,                 {tool file}
Errors,                {alpha-graphic messages}
math,                  {arithmetics}
coord,                 {AZ,EL,CYL}
trans,                 {Transformation}
loc,                   {location file}
iop,                   {I/O}
cpl,                   {compiler}
jigs,
ncrun,                 {runtime lib}
ncg,                   {G code dispatcher}
nc,                    {display, main loops}
logo;                  {log on, log out}


BEGIN
NCversion:= 'NCPLUS 2000';
logon;
repeat
  cncmain;
until logoff;
END.



{LOGO.PAS  Copyright (C) 1988, 1999 by Gil Hagiz}

Unit logo;
interface
{$I nodebug}

Uses
dos,
crt,
screen,
files,
ugrp,
windows,
kboard,
cvar,
mesg,
parser,
helpme,
ed,
uvar,
ini,
tbu,
errors,
trans,
iop,
cpl,
ncrun,
nc;

procedure logon;
function logoff:boolean;

(*============================================================*)
Implementation

{$I Copyrt}

const
  secretcode = '123';
  devOK:boolean=false;

procedure openscreen(col,cursor:word);
var txt:linestr;
begin
openwindow(10,9,70,16,col,cursor);
getini('vendor',txt);
title(txt);
center(NCversion,1);
center(CR,2);
end;

procedure fatalerror(const s:string);
begin
BootLog(getmessage(807)+s,11);
offline:=true;
directvideo:=false; checksnow:=false;
openscreen(bkred+7,$2000);
center(getmessage(807),4);
center(getmessage(808),6);
textattr:=bkred+white; center(s,5);
ouch; ouch;
while keyready do ;
inkey; halt(12);
end;

procedure isSuper(su:boolean);
begin
if prog1='' then begin
  security:= 2-byte(su or (inkey=secretkey));  {security= 1 or 2}
  if security=superuser then begin
    center(getmessage(804),6);
    inkey;
  end;
end else
  inkey;
closewindow;
oldscreen;
end;

function copyparam:char; assembler;   {txtl:=copy(txtl,2,length(txtl))}
ASM;
        cld
        les     si,txtladdr
        mov     di,si
        xor     ax,ax
        lodsb
        dec     ax
        mov     cx,ax
        stosb            {set length; inc di}
        lodsb            {al= first char; inc si}
        rep     movsb
        and     al,5Fh
end;

function opendev:boolean; assembler; {read data from device}
ASM;                                   {read constants}
        mov     ax,04402h              {read device IOCTL}
        mov     cx,5                   {byte count}
        mov     bx,word ptr cncdrv
        push    ds
        mov     dx,seg cmd9A
        mov     ds,dx
        mov     dx,offset cmd9A        {cmd=9Ah}
        int     21h
        pop     ds
        jc      @err

        mov     ax,04402h              {read device IOCTL}
        mov     cx,7                   {byte count}
        mov     dx,offset devdata      {NCRUN, ds= segment}
        mov     bx,word ptr cncdrv     {handle}
        int     21h                    {DS:DX= ptr to data block}
@err:
        mov     al,1                   {CF=1 @ error}
        sbb     al,0
        mov     devOK,al
end;

procedure logon;
var i,j : word;
  e:extstr;
  binfile:boolean;
  src:text;
  txt:linestr;
label portsOK;

begin
ASM;    {increase number of file handles to 30}
        mov     ax,6700h
        mov     bx,30
        int     21h
@1:
end;
selfdir:='';
INIfile:=myname+'.INI';
boot(true);                      {open boot log file}
BootLog(Fexpand(paramstr(0)),10);
for i:=1 to paramcount do begin
  txtl:=paramstr(i);
  BootLog(' '+txtl,10);
  case copyparam of
  'S': if txtl=secretcode then security:=superuser;
  'O': offline:=true;
  '@': begin
         Fsplit(fexpand(txtl),selfdir,txtl,e);
         if length(txtl) or length(e) <>0 then INIfile:=txtl+e;
       end;
  end; {case}
end;
bootLog('',11);
i:=1;
if selfdir='' then begin
  selfdir:=mydir; dec(i);
end else
  HelpDir:=@selfdir;
Fassign(INIsrc,selfdir+INIfile);
txt:=getmessage(809)+INIsrc.pname;
j:=word(dostype(INIsrc.pname)=1);
if i>j  then fatalerror(txt);
BootLog(txt,j);

readINIfile;
txt:=Mydir+Modelname;
if not SetModel(modelname) then fatalerror(txt);
if modelname<>'' then BootLog(txt,1);

txt2long;
openscreen(bkblue+white,$2000);

if not offline then begin
  reset(cncdrv);
  offline:=ioresult<>0;
end;
if offline then begin
  ASM   or      pflags,20h end;
  center(getmessage(805),4);
end;
if not (offline or opendev) then fatalerror('CNCSERVO');
feed60:=65536.0/(60*irqs);

ASM;
        mov     bx,-1
        mov     ax,MemSeg
        mov     di,wr16
        call    dword ptr IOdd
        jc      portsOK
end;
fatalerror('CNCPORTS');
portsOK:

MavLen:=MavBuff*2 div irqt;
getmem(Mav,MavLen*(axes+1));   {Moving Average and output buffers}
fillchar(Mav^,MavLen*(axes+1),0);
setTB;                         {must be before CNX}

{load CNX file}
if catch(exception) or runcc then begin
  BootLog(Xfile.pname,0);
  if security<>superuser then fatalerror(CNXfile);
  error:=false;
end;

{load the PLC file}
LoadPLC;
BootLog(selfdir+PLCfile,word(not error));
if error and (security<>superuser) then fatalerror(PLCfile);
error:=false;

if not loadgraph then fatalerror(mydir+vgafile);
BootLog(mydir+vgafile,1);

if not offline then LeadInit;
fillchar(home,sizeof(home),#0);
assign(src,selfdir+updatefile);
reset(src); tic:=ioresult;
if tic=0 then begin
  for j:=1 to maxhomes do begin
    for i:=1 to sysaxes do read(src,home[j,i]);
    readln(src);
  end;
  for i:=1 to sysaxes do readln(src,xpos[i],oldcorr[i]);
  readln(src,curHH);
  inc(tic,ioresult); close(src);
end;
beep(1000,200);
if tic<>0 then beep(1000,200);
BootLog(selfdir+updatefile,word(tic=0));
for i:=1 to axes do
   if (xpos[i]<nlimit[i]) or (xpos[i]>plimit[i]) then
       xpos[i]:=(plimit[i]+nlimit[i]) div 2;
delay(1000);
center(getmessage(469),6);
isSuper(security=superuser);

BootLog(getmessage(811),word(devok));         {servo}
BootLog(getmessage(812),word(TBOK));          {TB}
BootLog(getmessage(813),word(IOok));          {IO}
BootLog(getmessage(820)+stgi(Memram),11);     {Free Ram}
boot(false); {close boot log file}

CNCinit;
end;    {logon}

function logoff:boolean;
begin
openscreen(bkred+white,$607);
warning(idw,$104);
center(getmessage(806),6); gotoxy(wherex-2,wherey);
isSuper(false);
logoff:=key or $20 = byte('y');
end;

END.



{NC.PAS  Copyright (C) 1988, 1998 by Gil Hagiz}

Unit nc;

INTERFACE



{$I debug}
{.$DEFINE Mtst}  {call motion not from interrupt}
{.$DEFINE DISK}  {Virtual disk for a host}
Uses
Dos,
crt,
files,                 {virtual files}
screen,                {screen routines}
ghmouse,               {mouse support}
ugrp,                  {VGA interface}
windows,               {A/N windows}
Dosshell,              {Find, copy, shell}
kboard,                {Key-board}
cvar,                  {common vars}
edscrn1,               {Fast screen routines}
Helpme,                {display help}
mesg,                  {messages pickup}
dir,                   {dir pickup}
parser,                {Line parsing}
table,                 {table routines}
ed,                    {Editor}
uvar,                  {nc vars}
{$IFDEF DISK}
udisk,                 {virtual disk}
{$ENDIF}
ini,                   {read INI file}
tbu,                   {Teach box unit}
ncpar,                 {parameter table}
tools,                 {Tool table}
Errors,                {screen messages A/N and graphics}
math,                  {sin, cos, tan}
coord,                 {AZ, EL, CYL}
trans,                 {Robot transformations}
loc,                   {location handling}
iop,                   {Input/Outout}
cpl,                   {compliler}
ncrun,                 {Run time lib}
ncg;                   {G code dispatcher}

procedure CNCinit;
procedure leadinit;
procedure cncmain;
procedure oldscreen;
function runcc:boolean;
procedure writetime;

procedure cmd9A;                {far}

var
  cncdrv: file;
(* ========================================================== *)
IMPLEMENTATION

var
zooming, xzoom,yzoom,zzoom:double;
xyzzoom : array[0..2] of double absolute xzoom;
exitsave: pointer;
oldint70: pointer;
oldint00: pointer;
Ndisplay: longint;
pixels  : longint;
OldFeedLow, OldFeedMult, oldoffs, old399 : word;
FewBuffers, tracerr, timer, timer0, oldtimer0, oldtimer1:word;
xcar,ycar,xiso,yiso : integer;
zoomst : string[5];
htab, lastaxis, oldsngle : byte;
findv : boolean;
DosDir : dirstr;

var
Csize:array[0..2] of word;
Cshift:array[0..2] of word;
Cneg :array[0..2] of integer;
corr0:array[0..2] of integer;
CorFile   : Frec;
timeoffs:word;
timeattr:byte;

const
LeadPtr : array [1..sysaxes] of bufptr=(nil,nil,nil,nil,nil,nil,nil,nil);
LeadNow : array [1..sysaxes] of word= (0,0,0,0,0,0,0,0);
zoom    : allaxes = (400,400,400,400, 400,400,400,400);
trctmp  : array [1..sysaxes] of word= (0,0,0,0, 0,0,0,0);
sn30    : single=0.5;
cs30    : single=0.866;
oldindex: longint=-1;
accel   : word = $80;
decel   : word = $80;
vtime   : word = 50;      { .01 sec for dwell }
vref    : word = 50;
spind   : word = 0;
HW      : integer=0;      {hand wheel}
fe      : integer = 0;    {following error}
axis    : word = 0;
zoomc   : integer = 0;
oldaxes : word = $FFFF;
myAxis  : word = $FFFF;   {used in Axis Misc}

ModuloN : word = 1;       {used in simulation}
divisor : word = 20;      {20 ms time-constant for simulation}

feedstr : string[12]=' Feed=   . %';   {mesg 410}

oldmode : modet  = none;
modename: modet  = none;
TBold   : byte = 0;
CorrFlag :boolean = false;

ntsflName: array [1..5] of char = 'NTSFL';

modecol : array [modet] of word=(
                {auto}    bkblue +white,
                {manual}  bkgreen+white,
                {chktrc}  bkmagenta+white,
                {chkref}  bkgreen,
                {setref}  bkred+white,
                {sethome} bkwhite+blink+red,
                {mdi}     bkcyan+blue,
                {teach}   bkred+blink+yellow,
                {none}    bkblue+blue);         {%%%1-29-96}

modeHlp : array [modet] of string[10]=(
                {auto}    '[GENERAL]',
                {manual}  '[GENERAL]',
                {chktrc}  '[CHKTRC]',
                {chkref}  '[CHKREF]',
                {setref}  '[SETREF]',
                {sethome} '[SETHOME]',
                {mdi}     '[MDI]',
                {teach}   '[TEACH]',
                {nop}     '');

topcolor : array [boolean] of byte = (bkcyan,bkblue+white);
axiscolor: array [boolean] of byte = (yellow, lightcyan);
imstr    : array [boolean] of string[6] = (' MM   ',' INCH ');

firstaxis: byte = 1;
SecondTime:boolean=false;

{$L ncl}

procedure myint15;                      external;
procedure oldint15;                     external;
procedure clrbuff;                      external;
procedure motion;  far;                 external;
procedure Simulation;                   external;
procedure res70;                        external;
procedure prep70;                       external;
procedure cmd9A;                        external;
procedure clrtrc;  far;                 external;
procedure skip;                         external;
procedure newfeed;                      external;
procedure updateX(xxDI:word);far;       external;
procedure GoASM;                        external;
function  trace:boolean;                external;
function  trcerr(axs:word):integer;FAR; external;
function  ready:boolean;                external;
procedure writetime;                    external;
  { write BIOS time directly to screen}
procedure CMOSwr;                       external;
function  CMOSrd:byte;                  external;

procedure graphics(s:boolean); forward;
procedure corr3d(on:boolean);  FAR; forward;

procedure PLCmesg; FAR;           {called from KBOARD}
begin
if trace then begin
  if not SecondTime then begin
    SecondTime:=true;             {avoid recursive calls}
    callcc(106);
    error:=true;                  {to skip BreakP}
    errors.err(199+byte(Moving>0),-1,axisname[tracerr]);
  end;
end else
  SecondTime:=false;
if MousEvent=0 then begin
  GetMouseEvent(plcvars[90]);
  if InWindow and 2 <> 0 then begin
    MousMove:=$FF;              {non active}
    if (MousLft>=2) and (MousRegion<>EntryNo) then KB(1220+MousRegion);
    if MousLft=1 then           {Release Left Button}
      if Mousregion=0 then KB(27) else KB(13);
  end;
end;
if plc1flag<>0 then plc02;
{$IFDEF DISK}
if diskOK then getKB;           {get char from virtual drive}
{$ENDIF}
end;

{$IFDEF Mtst}
procedure motion1; FAR ;assembler;
ASM;
end;
{$ENDIF}

procedure spoil(num:word);  assembler;
const spoiler : longint = $795B3D1F;
{olds[num]:=olds[num] xor spoiler}
ASM;
        mov     ax,word ptr spoiler
        mov     bx,num
        add     bx,bx
        xor     word ptr [bx+olds-18],ax  {olds[9..vars]}
db      66h
        ror     word ptr spoiler,1
end;

function diowrite:boolean; assembler;
const
  devcmd : word = 0;                   {driver write data block}
{$IFDEF Mtst}
  devptr : pointer= @motion1;
{$ELSE}
  devptr : pointer= @motion;           {first byte of devcmd is junk}
{$ENDIF}
ASM;                                   {now enable interrupts}
        mov     ax,04403h              {write device IOCTL}
        mov     cx,5                   {byte count}
        mov     dx,offset devcmd+1     {ds= segment}
        mov     bx,word ptr cncdrv
        int     21h                    {DS:DX= ptr to data block}
        mov     al,0                   {CF=1 @ error}
        rcl     al,1
end;

(**************************************************************)
                     procedure initalways;
                 {for CS after Hold or CS in MDI}
(**************************************************************)
begin
clrbuff;
buffers[0].feed:=vtime;
buffers[0].feedratio:=100;      {non zero}
skipPort:=0;
end;

(**************************************************************)
               procedure shortbuff(short:byte); FAR;
(**************************************************************)
begin
if short in [1..maxbuffers-1] then begin
  if tracing=0 then begin
    tracing:=short; v64H:=1; fewbuffers:=short;
    Buffers[tracing].next:=ofs(buffers);
  end;
end else begin    {default}
  Buffers[tracing].next:=ofs(buffers[succ(tracing)]);
  tracing:=0; v64H:=0; fewbuffers:=maxbuffers;
end;
initalways;
end;

(**************************************************************)
                      procedure init;
(**************************************************************)
begin
shortbuff(0);       {does InitAlways}
ToolComp:=false; prevtc:=0; rt:=0; par[prt]:=0;
ptr0:=0; ptr1:=0;
end;

procedure initCS; assembler;
ASM;
        call    init
        call    runinit
end;

procedure irqon;
begin
{$IFNDEF Mtst}
if offline then
  prep70
else begin
  reset(cncdrv);
  InOutRes:=0;;
  diowrite;          {enable interrupts}
end;
{$ENDIF}
irq:=true;
if not graphnow then loader;    {%%%02-05-94}
end;

procedure irqoff;
begin
if Ractual or Rdesired <> 0 then RotExactStop;
if offline then res70
           else close(cncdrv);
InOutRes:=0;
irq:=false;
end;

procedure cc100(k:integer); {call cc-100 with #199:=k}
begin
dbli(par[199])[1]:=k;
dbli(par[199])[4]:=-1;
callcc(100);                     {#199=k}
end;

function runcc:boolean;    {true --> error}
begin
{Run the CNX file, assume failure}
runcc:=true;
Fassign(Xfile,selfdir+CNXFile);
Fptr:=@Xfile;
if getCPLfile=0 then begin
  initCS;
  while Readline do CNC;
  BootLog(Xfile.pname,1);
  runcc:=false;
  if TBnew then cc100(-1);
end;
end;   {runcc}

procedure indicator(i:runmodet);
begin
if error then exit;
runmode:=i;
writetext(getmessage(400+word(runmode)), 44, 1, topcolor[runmode in 
[reseti,runi]]);
end;

procedure isometric;
begin
if graphic then begin
  iso:=not iso;
  pageselect(iso);
end;
end;

procedure dryrn(s:integer);
begin
if mode=setref then s:=0;   {%%%06-17-96}
tac:=dryrun;
if s>=0 then begin
  if dryrun<>s then dryrun:=s else dryrun:=0;
end else
  if not graphnow and (dryrun>=2) then dryrun:=0;
case dryrun of
 0 : writetext('         ',25,1,bkblue);        { 9 }
 1 : writetext(getmessage(412),25,1,bkcyan);    {DRYRUN}
2,6: begin
       if not graphic then graphics(true);
       word(pixels):=0;
       if dbli(par[stop])[4]<0 then
         pixels:=round(-par[stop]);             {in search}
       writetext(getmessage(413),25,1,white);   {TEST}
     end;
end;
if (tac>=2) or (dryrun>=2) then updatepos;
end;

procedure restoreNTSFL;
var j:word;
begin
if GraphScr then exit;
for j:=11 to 15 do begin
  if big[j]<>0 then bigtext(ntsflName[j-10],hor[j],ver[j],yellow,big[j]);
end;
imdisplay:=true;  {restores NTSFL}
for tic:=9 to vars do spoil(tic);
ASM
db      66h
        inc     word ptr Ndisplay
end;
resNTSFL:=false;
end;


procedure restoreaxes(key:integer);
var tmpaxes:byte;
    col    : byte;
    i,j    : byte;
    visible:boolean;
begin
if (CurWindow<>0) or graphScr then exit;
if mode=chktrc then tmpaxes:=0 else tmpaxes:=displayaxes-1;
case key of
(*1072 {UP} : if firstaxis>1 then dec(firstaxis);
1080 {DN} : inc(firstaxis);*)
1..8      : if key<firstaxis
              then firstaxis:=key
              else if key>lastaxis then firstaxis:=key-tmpaxes;
{else     : re-display }
end; {case}
if firstaxis>axes-tmpaxes then firstaxis:=axes-tmpaxes;
lastaxis:=firstaxis+tmpaxes;
axis:=firstaxis-1;
if (tmpaxes=0) and not (mode in [auto,MDI]) then handaxis:=firstaxis;
oldhand:=handaxis;
visible:=false;
for i:=firstaxis to lastaxis do         {Display axis names}
  if big[i]<>0 then begin
    j:=i-firstaxis+1;
    if i=handaxis then begin
      col:=$8F;
      visible:=true;                      {blink the selected axis}
    end else
      col:=axiscolor[xlat[i] and raxes <> 0];
    bigtext(axisname[i],hor[j],ver[j],col,big[i]);
  end;
if not visible then handaxis:=0;
disflagset;
end;

procedure writemode;
begin
writetext(getmessage(490+word(modename)),65,1,modecol[modename]);
end;

procedure writeUnit;
begin
writetext(imstr[inchNow],2,1,topcolor[inchsys=inchNow]);
end;

procedure GetHoldMode;      {Reset or Hold}
begin
with Fptr^ do
RunMode:=runmodet((mode=$D7B3) and ((block<>0) or (BufPos<>prg00)));
end;

procedure topline;    {re-write top line}
begin
edsetcursor($2000);          { no cursor }
BlueTop;
dryrn(-1);
inc(OldFeedMult);
writemode;
writeUnit;
indicator(RunMode);
inc(oldoffs,10);
inc(oldsngle);
oldaxes:=useH;
end;             {TopLine}

procedure newplace;
begin
if mode <>MDI then begin
  if not graphnow then
  ASM;                           {clear screen}
          mov     es,segb800
          mov     di,160         {row=2}
          mov     cx,80*23       {23 rows}
          xor     ax,ax
          CLD
          rep     stosw          {clear 23 rows}

          cmp     kanji,0
          jz      @9

          mov     di,160         {if Kanji, copy to screen}
          mov     cx,80*23
          mov     ah,0FFh
          int     10h
  @9:
  end;
  fillchar(big,sizeof(big),#0);
end;
dbli(par[190])[4]:=-1;
dblw(par[190])[1]:=word(mode)+2;
if graphic then dbli(par[190])[1]:=1;
RST:=0;
callcc(114);     {sets places}
oldhand:=$FFFF;  {calls restoreaxes() later}
resNTSFL:=true;  {calls restoreNTSFL later}
end;

procedure drawscreen;
var i:integer;
begin
nosound;
if not error then topline;
imdisplay:=true;
newplace;
if modename<>MDI then WRprogname;
end;

procedure ProgReset;
begin
repeat until PopPrg=0; spp:=0;
toolcomp:=false;
getprogname;
end;

procedure M2;
begin
callcc(2);
ExactStop;
ProgReset;
Nrun:=0;
Npof:=0;
initCS;
callcc(107);
end;

procedure runauto;
begin
if Fptr^.mode<>$D7B3 then Exit;
if RunMode=Reseti then begin
  initCS;
  Nrun:=0;
  Npof:=0;
  if dryrun>=2 then movfam(ofs(grany),ofs(grand));
end else begin
  initalways;
  dooffset(o);
end;
if key<>1198 then begin
  callcc(107);  {if not running CNX file}
  indicator(runi);              {change mode after cc-107}
end else
  runmode:=edit;                {for run-time errors}
repeat
  if not Readline then break;   {false if RST or EOF}
  Hold:=0;
  CNC;
until hold <> 0;

ExactStop;
if RST=0 then begin
  case hold of
 0,1 : begin           {End, Single,m0}
         if dryrun>=2 then begin
           for tic:=1 to axes do grand[tic]:=grand[tic]+flzero[tic];
         end;
         if Model='C' then grand[Z3]:=grand[Z3]-ZT;
         home[posHome]:=grand;
         curHH:=Vaxes;
         callcc(0);
         exit;
       end;
   2 : M2;
  end;
  if Curwindow<>0 then begin
    CloseAllWin;
    oldscreen;
  end;
end;
end;            { RunAuto }

procedure runMDI;
begin
  initalways;
  Hold:=0;
  CNC;  { line has already been read }
  ExactStop;
  if RST=0 then
    if hold=2 then M2;
  mode:=savemode;
end;       { runMDI }

procedure cycle_start;
begin
if mode=Auto then begin
  runAuto;
end else begin
  indicator(runi);
  case mode of
     MDI : runMDI;
  setref : begin initCS; No_stop:=false; Corr3d(false); callcc(103); end;
  chkref : begin initCS; No_stop:=false; callcc(113); end;
    else   ouch;
  end;
end;
GetHoldMode;
indicator(RunMode);
No_stop:=true;
end;

procedure goedit(run_error:boolean);
begin
error:=false;
if mode=MDI then begin
  doMDI(run_error);
  GetHoldMode;
  drawscreen;
end else begin
  IrqOff;                      {disable interrupts}
  mode:=auto;
  if not graphic then begin
    textmode(co80); directvideo:=not Kanji; checksnow:=false;
  end;
  prgsp:=0;
  runmode:=edit;               {indication for the error routine}
  doedit(run_error);
  IrqOn;                       {enable interrupts, Loader}
  GetHoldMode;
  if graphic then
    graphics(false)
  else
    drawscreen;
end;
if v70<>0 then getwheel;
end;  {goedit}

function grp:boolean; assembler;
const msw=$819E; {exp*2 of 15872}
ASM;
        mov     ax,word ptr xzoom+6
        add     ax,ax
        cmp     ax,msw
        jae     @exit
        mov     ax,word ptr yzoom+6
        add     ax,ax
        cmp     ax,msw
        jae     @exit
        mov     ax,word ptr zzoom+6
        add     ax,ax
        cmp     ax,msw
        jb      @0
@exit:
        mov     al,1
        jmp     @9
@0:
{ycar:=y*aspect;}
        fld     aspect          {a         }
        fld     yzoom           {a,y       }
        fld     st              {a,y,y     }
        fmul    st,st(2)        {a,y, y*a  }
        fistp   ycar            {a,y       }

{xcar:=x;}
        fld     xzoom
        fist    xcar            {a,y,x     }

{xiso:=(y+x) * cos(30);}
        fld     st(1)           {a,y,x,y   }
        fadd    st,st(1)        {a,y,x, x+y}
        fmul    cs30
        fistp   xiso            {a,y,x     }

{yiso:=((y-x)*sin(30)+z ) * aspect;}
        fsub                    {a,y-x     }
        fmul    sn30            {a,(y-x)/2 }
        fadd    zzoom           {a,(y-x)/2+z }
        fmul
        fistp   yiso
        xor     ax,ax
@9:
end;

procedure setzoom;
begin                   {zoom= .010 to 10.0}
zooming:=exp(ln10*zoomc/6);
str(zooming:5:(12-zoomc) div 6, zoomst); { (12-zoomc) div 6 --> 1,2,3}
zooming:=zoomratio*zooming;
for tic:=1 to axes do zoom[tic]:=zooming*MetricS[tic];
writetext(getmessage(485)+zoomst,65,2,white);
end;

procedure graphline; FAR;
const
  oldxc:integer=0;
  oldyc:integer=0;
  oldxi:integer=0;
  oldyi:integer=0;
label Exitpoint;
begin
if not graphnow then exit;
xzoom:=(grand[xyz[17]]-testzero[xyz[17]])*zooming;
yzoom:=(grand[xyz[18]]-testzero[xyz[18]])*zooming;
if zh=0 then dblw(zzoom)[4]:=0
        else zzoom:=(grand[xyz[19]]-testzero[xyz[19]])*zooming;
if grp then goto ExitPoint;

case gg of
0,10,20 : graphptr^.style:=LEDs;
else      graphptr^.style:=$FFFF;
end;
setline(hx+oldxc, hy-oldyc, hx+xcar, hy-Ycar,2);
setline(hx+oldxi, hy-oldyi, hx+xiso, hy-yiso,4);

oldxc:=xcar; oldyc:=Ycar;
oldxi:=xiso; oldyi:=yiso;
Exitpoint:
if (abs(xcar)<word(pixels)) and (abs(ycar)<word(pixels)) then sngle:=3;
hold:=sngle and 1;
end;

procedure dographic;
begin
xzoom:=(xpos[xyz[17]]-graphzero[xyz[17]])*zoom[xyz[17]];
yzoom:=(xpos[xyz[18]]-graphzero[xyz[18]])*zoom[xyz[18]];
if zh=0 then
  dblw(zzoom)[4]:=0
else
  zzoom:=(xpos[xyz[19]]-graphzero[xyz[19]])*zoom[xyz[19]];
if grp then exit;
setpixel(hx+xcar, hy-Ycar, 2);
setpixel(hx+xiso, hy-yiso, 4);
end;

procedure restorefeed;
const feedaddr : pointer=@feedstr[7];
var col:word;
begin
OldFeedMult:=FeedMult; OldFeedLow:=FeedLow;
ASM;
    mov     ax,feedMult
    mov     bx,2000
    mul     bx
    add     ax,ax
    adc     dx,0
    mov     tic,dx
end;

case tic of
      0  : col:=bkred+blink+white;
  1..999 : col:=bkcyan;
    1000 : col:=bkblue+white;
    else   col:=bkwhite+red;
end; {case}
if FeedLow=0 then col:=bkred+blink+white
             else if FeedLow<FeedMult then col:=bkred+white;
case FeedLow of
  0 : col:=bkred+blink+white;
  1 : col:=bkblue+white;
else
  if FeedLow<FeedMult then
    col:=bkred+white
  else
    case tic of
         0  : col:=bkred+blink+white;
     1..999 : col:=bkcyan;
       1000 : col:=bkblue+white;
   else       col:=bkwhite+red;
   end; {case}
end;

str(tic:4, TBfeed);
ASM;
    or      TBset,1       {flag for TB display}
    mov     si,offset TBfeed+1
    les     di,feedaddr
    cld
    movsw
    movsb
    inc     di       {skip the decimal point}
    movsb
end;
writetext(FeedStr, 52,1, col); { 12 }
end;

procedure SaveUpdateFile;
var dst:text; i,j:integer;
begin
assign(dst,selfdir+updatefile);
rewrite(dst);
if IOresult=0 then begin
  for j:=1 to maxhomes do begin
    for i:=1 to sysaxes do write(dst,' ',home[j,i]:10:4);
    writeln(dst);
  end;
  for i:=1 to sysaxes do writeln(dst,xpos[i],' ',oldcorr[i]);
  writeln(dst,curHH);
  close(dst); InOutRes:=0;;
end;
end;

procedure dotopline;
begin
if error then exit;   {do not overwrite error message}

if (Vaxes<>oldaxes) and (useH<>0) then begin
  oldaxes:=Vaxes; str(VaxesL, TBhh);
  writetext('H'+char($2B+vaxesH shl 1)+TBhh,9,1,bkblue+white);
  ASM; or TBset,8; end;     {flag for TB display}
end;

if offsno<>oldoffs then begin
  oldoffs:=offsno;
  writetext(getmessage(414)+stg(offsno)+' ',13,1,topcolor[offsNo=o]);
end;

if sngle<>oldsngle then begin
  oldsngle:=sngle;
  if odd(sngle) then writetext(getmessage(411),35,1, bkcyan)     { 8  SINGLE}
           else writetext('        ',35,1, bkblue);
end;

if mode<>oldmode then begin
  if mode>none then mode:=none;
  if modename<>teach then modename:=mode;
  if (mode<>MDI) or (oldmode<>sethome) then writemode;
  if (mode=sethome) and (oldmode=mdi) then SaveUpdateFile;
  OneAxis:=false;
  case mode of
    chktrc,
    chkref,                              {%%%05-09-93}
    setref : begin
               oneaxis:=true;
               vaxes:=0; dooffset(0);
               if (mode=chktrc) or graphic then
                 graphics(graphic);              {A/N}
             end;
   sethome : begin
               if graphic then graphics(true);
               disflagset;
               if offsno<3 then dooffset(4);
             end;
      MDI  : begin
               savemode:=oldmode;
               if graphic then begin
                 graphics(true);
                 Exit;             {update axis display}
               end;
             end;
     end;            {case mode}

  if oldmode=MDI then EDchangeattribute(80,1,2,black);
  handaxis:=0;
  CorrFlag:=false;
  dryrn(0);         {%%%06-17-96}
  oldmode:=mode;
  disflagset;
  newplace;
  if mode=MDI then
    goedit(false)
  else begin
    WRprogname;
  end;
  if LinTC<>oldTC then TConst(oldTC);
end;               {oldmode<>mode}

if (FeedMult<>OldFeedMult) or (FeedLow<>OldFeedLow) then RestoreFeed;
end;


procedure addcorr; assembler;
{ax= new correction
 si= axis 0,2,4,...}
ASM;
        mov     [si+offset corrPLC],ax  {corrPLC[axis]:=newcorr}
        mov     bx,si
        cmp     CorrFlag,0
        jnz     @1

        mov     dx,ax                   {DX too}
        xchg    dx,[si+offset oldcorr]  {oldcorr[axis]:=newcorr}
        sub     ax,dx                   {AX= newcorr-oldcorr[axis]}
        add     [si+bx+offset corr],ax  {inc(twoint(corr[axis]).lo, dcorr)}
        ret
@1:
        mov     [si+offset oldcorr],ax  {oldcorr[axis]:=newcorr}
db      66h,98h                         {cwde}
db      66h
        sub     word ptr [si+bx+Xpos],ax {one command}
end;


procedure AxisMisc; assembler;
var tmp:longint;
const an360:single=360.0;
ASM;
        xor     cx,cx
        mov     di,myAxis
        inc     di
        cmp     di,axes
        jb      @1
        je      @3D                     {3D correction}
        xor     di,di
@1:
        mov     myAxis,di               {myAxis= 0..axes-1}
        mov     si,di                   {SI= byte ptr}
        shl     di,2                    {DI= dword ptr}

        {must be one command or use CLI/STI}
        xchg    cx,word ptr [di+corr+2] {+1 or -1}
        test    cx,cx
        jz      @99                     {exit if no motion}

        {flag for updating the display, written here for time saving}
        mov     al,byte ptr [si+xlat+1] {xlat begins from zero}
        or      disflag,al              {al= 1,2,4,8..$80}
        mov     ah,1
        or      Moving,ax

        lea     bx,[si+1]               {BX= axis - 1..axes}
        cmp     bx,ASpin
        jne     @noSpin
        {correct Xpos +-180 deg for Spindle}
        fild    Sp360                   {Sp360}
        cli
{*********************** no interrupts}
        fild    dword ptr [di+xpos]     {Sp360, Xpos}
db      0D9h,0F5h        {fprem1}       {Sp360, Remainder(st/st(1))}
        cmp     Ractual,0               {is spindle running?}
        jz      @Stand                  {jmp if not}
        fist    dword ptr [di+xpos]     {corrected Xpos- +- 180}
@Stand:
{*********************** no interrupts end}
        sti
        fstp    st(1)                   {pop Sp360}
        cmp     bx,BSpin
        jne     @noSpin1
        fmul    an360                   {mul by 360 for RPM spindle}
        jmp     @noSpin1                {Xpos}
@noSpin:                                {regular axis}
        {convert position to mm}
        fild    dword ptr [di+xpos]     {Xpos}
@noSpin1:
        mov     bx,di                   {DI+BX= qword ptr}
        fmul    qword ptr [di+bx+metricS]
        fistp   dword ptr tmp           {tmp:=round(xpos[i]*metricS[i])}
        {time saving before wait}
        add     si,si                   {SI= word ptr}
        fwait
        mov     ax,word ptr tmp         {AX= current position mm}
        mov     [si+offset v21],ax      {PLC #21 to #28}

        and     cl,corr1                {0 or 1}
        test    cx,[si+offset LeadNow]  {0=no table}
        jz      @99                     {exit if no table}
                                        {find table}
        les     di,[di+offset LeadPtr]  {ES:DI= ptr to table}
{Table Rec= Max:word, shr:word, Negative:word; data:array[0..Max] of word}
        mov     cx,es:[di+2]            {CX= shift const}
        mov     bx,word ptr tmp         {BX= current position mm}
        sub     bx,es:[di+4]            {BX= ofs from most negative}
        jg      @3                      {jmp if position > negative}
        xor     bx,bx
@3:
        clc                             {in case cl=0}
        shr     bx,cl                   {BX= weighted current position}
        adc     bx,0                    {rounding}
        add     bx,bx                   {byte to word ptr}
        cmp     bx,es:[di]              {cmp bx,Max byte}
        jb      @4
        mov     bx,es:[di]              {if BX > Max then BX:= Max}
@4:
        mov     ax,es:[di+bx+6]         {AX= new correction}
        call    addcorr                 {SI= axis- 0,2,4..}
        jmp     @99
@3D:
{3D correction}                         {CX=0}
        mov     myAxis,di               {myAxis= 0..axes}
        cmp     corr3,cl
        jz      @99

        mov     di,4                    {begin with Z}
        xor     ax,ax
        xor     dx,dx
        jmp     @11
@10:                                    {loop for z,y,x index}
        mov     cx,word ptr [di+offset Csize]
        inc     cx
        mul     cx                      {dx=0 until 3rd mul}

@11:
        mov     si,[di+offset v21]   {PLC #21 to #28}
        mov     cx,[di+offset Cshift]   {CX= shift const}
        sub     si,[di+offset Cneg]
        jg      @13
        xor     si,si                   {if SI < Min then SI:=0}
@13:
        clc                             {in case cl=0}
        shr     si,cl                   {SI= weighted current position}
        adc     si,0                    {rounding}
        cmp     si,[di+offset Csize]    {cmp SI,Max}
        jb      @14
        mov     si,[di+offset Csize]    {if SI > Max then SI:= Max}
@14:
        add     ax,si
        adc     dx,0
        sub     di,2
        jns     @10                     {loop for table's z,y,x}

        cmp     ax,word ptr oldindex    {dx:ax= new index}
        jne     @15
        cmp     dx,word ptr oldindex+2
        je      @99
@15:
        mov     word ptr oldindex,ax
        mov     word ptr oldindex+2,dx

        push    ds
        push    offset corfile
        push    dx
        push    ax
        call    Rseek

        push    ds
        push    offset corfile
        push    ds
        push    offset corr0
        call    readR                   {read record into corr0}
        mov     si,4                    {SI= axis- 4,2,0}
@16:
        mov     ax,[si+offset corr0]    {AX= new correction}
        call    addcorr
        sub     si,2
        jns     @16
@99:
end;


(**************************************************************)
                       procedure display;
(**************************************************************)
{  6    9  3  15   8    25   9    35  8    44  8    53   11     65    16
  INCH | H+5 | OFFS #1 | DRY-RUN | SINGLE |  HOLD  | FEED=12.3%| REFERENCE 
TEST
}
const
feedL    : word=0;
feedH    : integer=0;
numstr   : string[79]='';

var
trcmm    : double;
XDisplay : double;
longfeed : longint absolute feedL;
trcunit  : longint;
trc,vtab : integer;
hpos,vpos: byte;
TBmodeW  : word absolute TBmode;
size     : byte;
color    : byte;
sign     : shortint;
minstr,maxstr:string[20];

label noN;

begin
if CurWindow>0 then exit;

if (TBnow xor TBold) >=$80 then begin
  TBold:=TBnow;
  modename:=none;
  if oldmode=mode then oldmode:=none;
  if TBnow>=$80 then begin
    if graphic then graphics(true);
    dryrn(0);
    modename:=teach;
  end;
  if TBnew then cc100(-1);    {update TB screen}
end;
DoTopLine;                    {%%%1998-03-18}
if (dryrun>=2) and not odd(sngle) then exit;
if (TBmodeW and $8080 =$8000) and (TBset<>0) and (TBout=0) then TBupdate;

if resNTSFL then restoreNTSFL;

if handaxis<>oldhand then begin
  if handaxis>axes then handaxis:=0;
  restoreaxes(handaxis);
  if handaxis=0 then oneaxis:=false;
end;
if axis<lastaxis then begin
  inc(axis);
  tic:=axis-firstaxis+1;
  vpos:=ver[tic];
  hpos:=hor[tic];
  size:=big[tic] and 3;
  if (disflag and xlat[axis] <> 0 ) or (mode=chktrc) then begin
    disflag:=disflag and not xlat[axis];
    case mode of
    setref:XDisplay:=(xpos[axis]-abszero[axis])*scaled[axis];
    chktrc:begin
             trc:=trcerr(axis);
             XDisplay:=scaled[axis]*trc;
             if vactual<=1 then begin
               if Pflags<0 then
                 ASM;
                     mov   ax,trc
                     cwd
                     add   ax,dx
                     xor   ax,dx   {ax= abs(trc)}

                     shl   ax,6    {ax*64}
                     push  ax
                     call  sound
                 end;
             end else begin {vactual>1 , vactual = mm/min }
               trcmm:=abs(MetricS[axis]*fe);
               if jogL<>0 then begin
                 str(trcmm*60000/feed:wd+2:1,maxstr);
                 bigtext(maxstr,hor[12]+big[12],ver[12],yellow,big[12]);
               end;
               timer0:=timer shr 5;
               if timer0<>oldtimer0 then begin
                 oldtimer0:=timer0;
                 inc(htab);if htab>79 then htab:=79;
                 trcunit:=round(trcmm*points*ffg0[axis]);
                 vtab:=word(trcunit) div points;
                 if vtab>23 then vtab:=23;
                 writepel(char(word(trcunit) mod points + $A0),
                          htab,24-vtab,yellow);
               end;
             end;
           end; {chktrc}
    else     {not chktrc or setref}
      if mode=sethome then begin
        str((nlimit[axis]-xpos[axis])*scaled[axis]:dig:fd,minstr);
        str((plimit[axis]-xpos[axis])*scaled[axis]:dig:fd,maxstr);
        writetext(getmessage(483)+maxstr,50,vpos,lightgreen);
        writetext(getmessage(484)+minstr,50,succ(vpos),lightred);
      end;
      if dryrun and 2 <> 0 then begin
        v399:=0;
        XDisplay:=grany[axis]/metricS[axis]*scaleD[axis];
      end else begin
        XDisplay:= scaled[axis] * xpos[axis];
        if axis=diff1 then
          XDisplay:=XDisplay - xpos[diff0] * DiffScale;
        if Model<>'M' then
          XDisplay:=XDisplay - FixD[axis];
        if (Model='C') and (axis=Z3) and (g53F<>0) then
          Xdisplay:=Xdisplay - par[pzt];
      end;
      if v399=1 then
        XDisplay:=
         (daddy[axis]+flaxis[axis])/metricS[axis]*scaleD[axis]-XDisplay;
    end; {case mode}

    if size<>0 then begin
{$IFDEF DISK}
      if diskOK then Disk^.AxisPos[axis]:=XDisplay;
{$ENDIF}
      str(XDisplay:dig:fd,numst);
      bignum(axis,hpos+size,vpos,
             axiscolor[xlat[axis] and raxes <> 0],size);
    end;
  end; {disflag<>0}

end else begin
  axis:=pred(firstaxis);
  timer0:=timer and $1FF;

  if not graphnow and (timer0<>oldtimer1) then begin
    oldtimer1:=timer0; writetime;
  end;

  if v399<>old399 then begin
    old399:=v399;
    disflagset;
  end;

  if imdisplay then begin
    disflag:=$FF;
    ASM
    db  66h
        inc     word ptr Ndisplay
    end;
    for tic:=12 to 15 do begin
      spoil(tic);
      size:=big[tic];
      if size<>0 then
        bigtext('  ',hor[tic]+(byte(tic=14) shl 1 + 5) * size,
                     ver[tic],black,size);
    end;
    if not error then writeUnit;     {do not overwrite error message}
    imdisplay:=false;
  end;

  if big[11]<>0 then begin           {N display}
    ASM;
        mov     ax,v390
        dec     ax
        jz      @1
        jns     @2
  @0:
  db    66h
        mov     ax,word ptr nn          {#390=0}
        jmp     @9
  @2:                                   {#390=2}
  db    66h
        mov     ax,word ptr Npof
        jmp     @9
  @1:                                   {#390=1}
  db    66h
        mov     ax,word ptr Nrun
  @9:
  db    66h
        cmp     word ptr Ndisplay,ax
        je      noN
  db    66h
        mov     word ptr Ndisplay,ax
    end;
    str(nn:5,TBnn); str(Ndisplay:wd,numstr);
    size:=big[11] and 3;
    bigtext(numstr+' ',hor[11]+size,ver[11],yellow,size);
    ASM;    or      TBset,2; end;     {flag for TB display}
  noN:
  end;

  if (curtool<>olds[12]) and (big[12]<>0) then begin
    olds[12]:=curtool;
    size:=big[12] and 3;
    str(curtool:wd,numstr);
    bigtext(numstr,hor[12]+size,ver[12],yellow,size);
  end;

  if (spindle<>olds[13]) and (big[13]<>0) then begin
    olds[13]:=spindle; str(spindle:wd, numstr);
    size:=big[13] and 3;
    bigtext(numstr,hor[13]+size,ver[13],yellow,size);
  end;

  feedL:=feed;                                      {08-23-92}
  if (feedL<>olds[14]) and (big[14]<>0) then begin
    olds[14]:=feedL;
    if inchNow then str(FintF*0.03937*longfeed:8:2,numstr)   { 1/25.4 }
               else str(feedL:6,numstr);
    size:=big[14] and 3;
    bigtext(numstr,hor[14]+size,ver[14],yellow,size);
  end;

  if (l<>olds[15]) and (big[15]<>0) then begin
    olds[15]:=l; str(l:5,TBll);
    size:=big[15] and 3;
    bigtext(MMspace+TBll,hor[15]+size,ver[15],yellow,size);
    ASM;    or      TBset,4; end;     {flag for TB display}
  end;

  for tic:=16 to vars do
    if big[tic]<>0 then begin
      tac:=word(plcvars[tic+PLCbase]);
      if tac<>olds[tic] then begin
        olds[tic]:=tac;
        sign:=shortint(big[tic]);
        size:=abs(sign);
        toe:=wd;
        color:=Pcol[tic];
        if size>=$10 then begin
          toe:=size shr 4;
          size:=size and 7;
        end;
        if byte(sign)=$80 then begin
          numstr:=GetPLCmesg(tac and $FF,false);
          if hi(tac)<>0 then color:=hi(tac);
          writetext(numstr,hor[tic]+1,ver[tic],color);
        end else begin
          if sign<0 then
            str(integer(tac):toe,numstr)
          else
            str(tac:toe,numstr);
          bigtext(numstr,hor[tic]+size,ver[tic],color,size);
        end;
      end;
    end;
{====================}
{    DoTopLine;  %%%1998-03-18}
end;
end;

{$I graph0}     {%%%01-31-94}

(**************************************************************)
                procedure background; FAR;
(**************************************************************)
const oldtime:word=0;
begin
{$IFDEF Mtst}
{for tic:=1 to 10000 do ;Simulation;}
if movinf<>0 then PAR[1]:=PAR[1]+20;
for tic:=1 to 20 do motion;
{$ENDIF}
goASM;
ASM;
        mov     cx,v70
        jcxz    @9
        mov     ax,timer
        shr     ax,cl          {check every 2**n msec}
        cmp     ax,oldtime
        je      @9
        mov     oldtime,ax
        call    getwheel
        add     HandWheel,ax
@9:
end;
if HW<>0 then newfeed;

TBloop;

AxisMisc;                  {%%%05-14-95}

if not GraphScr then begin {%%%01-31-94}
  display;
  if graphnow then dographic;
end else begin
  DoTopLine;
  DoGraph0;        {in Graph0.pas}
end;
end; { background }

procedure graphics(s:boolean);
var x,y:word;
begin
graphic:=graphic xor s;
if graphic then begin
  gograph;
  pageselect(iso);
  drawscreen;
  setzoom;
end else begin
  goAlpha;                             {graphnow:=false}
  checksnow:=false;
  loader;
  drawscreen;
end;
end; {graphics}

procedure oldscreen;  assembler;
ASM;
        mov     al,kanji
        or      al,graphic
        jz      @0
        push    0
        call    graphics   {if Kanji or graphic then draw screen}
@0:
end;

procedure test(sw:word); FAR;
begin
case sw of
 0 : if graphic then graphics(true);       {Alpha}
 1 : begin
       CloseAllWin;
       if dryrun<2 then dryrn(6);          {set test}
       graphics(false);                    {clear screen}
     end;
2,3: pageselect(boolean(sw-2));
end; {case}
end;        {test}

procedure getTBfeed;  assembler;
{  key:=key-1200;
  if lo(key)<=TeachTable[0] then begin
    FeedSelector:=TeachTable[key];
    FeedMult:=FeedTable[FeedSelector]
  end;}
ASM;
        mov     ax,key
        mov     bx,offset TeachTable
        sub     ax,1200                 {AX= 1..10}
        cmp     al,[bx]                 {length of table}
        ja      @exit
        xlat                            {get value from table}
        mov     FeedSelector,ax
        add     ax,ax                   {byte to word}
        mov     bx,ax
        mov     ax,word ptr [bx+FeedTable]
        mov     FeedMult,ax
@exit:
end;

procedure ChkJogReleased;   {called if JogL<>0}
begin
if TBnow>=$80 then begin
  TBloop;
  if TBkey<>0 then Exit;
end else begin
  if (mem[seg0040:$17] and $C = $C) or (JogL>=$80) then Exit;
end;
SKP:=true;
JogL:=0;          {Don't call again}
end;

function buffClear:boolean; assembler;
ASM;
        xor     ax,ax
        mov     bx,axes
        les     si,mav
        cld
@loop:
        mov     di,si
        mov     cx,LinTC0
        repz    scasw
        jnz     @exit0
        add     si,mavLen
        dec     bx
        jnz     @loop
        inc     ax
@exit0:
end;


(**************************************************************

                    W A I T I N G   L O O P

***************************************************************)
procedure go_wait(ExitFlag:word);  FAR;
var done:boolean;
begin
RSTer:=0;          {flag to disable RST}
repeat
goASM;

plcmesg;

if (JogL<>0) and (jogH=0) then ChkJogReleased;

{SKP:=(RST<>0) or SKP or
      (skipPort<>0) and ((port[skipPort] and mask0)=mask1);

      Port returns True data        %%%12-23-92
      Skip:= port and mask0 = mask1;

      mask0= bits to detect.
      off:mask1=0     --> detects comp bits
      on: mask1=bits  --> detects true bits,
      all:mask1=bits,  mask0=FF}
ASM;
        xor     ax,ax
        cmp     SKP,al         
        jnz     @9             {already done - exit}
        cmp     RST,al
        jnz     @8             {SKP:=RST}
        mov     bx,SkipPort
        cmp     bx,ax          {no port}
        jz      @9
        cmp     bl,inport
        jbe     @1             {jmp if real port}
        add     bx,bx          {PLC var - byte to word offset}
        mov     ax,word ptr [bx+plcvars]
        jmp     @2
@1:
        mov     di,rd8
        call    dword ptr IOdd
@2:
        and     ax,mask0
        cmp     ax,mask1
        lahf              {40h=equal}

        xor     ah,mask2  {40h for Toggle}
        test    ah,40h
        je      @9
@8:
        mov     SKP,1
@9:
end;

{findv--> false enables assignment into vhigh}
findv:=not SKP and (runmode<>dwelli);

if SKP then begin
  vhigh:=1;              {decel and stop}
  no_decel:=false;
  if (RST=0) and (dblw(par[190])[1]=0) and (dbli(par[190])[4]=-1) then begin
    skip;
    inc(dblw(par[190])[1]);        {#190:=1}
  end;
  if Vactual<=1 then clrbuff;  {and exit by 'if READY'}
end;

if ready then begin
  case ExitFlag of
   0: done:=true;
   1: done:=decelflag and (Vactual<=minfeed);
   {%%%05-21-1999: don't build buffers if feed=0}
   else done:=(FeedMult<>0) or SKP;
  end;
  if done then begin
    if Pflags<0 then nosound;
    if no_decel or BuffClear then begin
      if SKP then
         {for i:=1 to axes do
          if g53f=0 then
            par[190+i]:=xskip[i]*metricS[i]
          else
            par[190+i]:=xskip[i]*scaled[i])-fixD[i];}
          ASM;
                  xor     bx,bx
                  xor     cx,cx
                  xor     di,di
                  mov     si,offset MetricS
                  cmp     g53F,cl
                  jz      @1
                  inc     cx
                  mov     si,offset scaleD
          @1:
                  fild    dword ptr [bx+xskip]
                  fmul    qword ptr [si]
                  jcxz    @2
                  fsub    qword ptr [di+fixD]
          @2:
                  fstp    qword ptr [di+par+191*8]
                  add     di,8
                  add     si,8
                  add     bx,4
                  cmp     bx,axis4
                  jb      @1
          end;
      Exit;
    end;
  end;
end;

if Pflags<0 then sound(Vactual shr 4);

if keyready then begin {Keypressed}
  CurKey:=0;
  case key of
   1063 : {F5 } dryrn(1);
1201..1210 : getTBfeed;
   1111 : {ALT-F8} SKP:=skipPort>0;
(*   1072 , {UP ARROW}
   1080 : {DN ARROW} if handaxis=0 then restoreaxes(key); *)
   1112 : {ALT-F9} if runmode=dwelli then begin
                     SKP:=true;
                     Exit;
                   end else
                     feedMult:=feedtable[feedselector];
   1106 : {ALT-F3} isometric;
    $1B : {ESC} RST:=1;
  else CurKey:=Key;
  end;
end;    {if keypressed}
background;
until false;
end;

procedure breakNow; FAR;
begin
exactstop;
toolcomp:=false;
updatepos;
end;    { breakNow }


procedure dwell(dly:double);  FAR;
var numstr:string[20]; tmp:double; time:longint;
oldfeed0,i,q:word; oldmode:runmodet; oldstop:boolean;
begin
{timer:=0;}
if not irq then exit;
if dryrun=2 then dly:=0.05;
oldstop:=no_stop;
oldfeed0:=feed0;
no_stop:=false;
exactstop;
oldmode:=runmode; runmode:=dwelli;
dly:=dly*10;
fillchar(xnew,axes*4,#0);
findv:=false;
feed0:=vtime;                   {1 pulse per 0.01 sec}
vactual:=vtime; vhigh:=vtime; vdesired:=vtime;
lenRatio:=1;                    {Feed display = 0  %%%10-23-97}
largest:=round(frac(dly)*10);
feedratio:=round(131.0*1024/irqs);
dly:=int(dly);
moving:=$8000;
no_decel:=dly>=1;
if largest>0 then begin makebuffer; go_wait(0);  end;
if no_decel then begin
  indicator(dwelli);
  largest:=10; tmp:=dly;
  while (dly>-Fewbuffers) and not SKP do begin
    makebuffer; go_wait(0); dly:=dly-1;
    q:=0;
    for i:=0 to fewbuffers do inc(q, buffers[i].qCnt);
    tmp:=abs((q/10+dly)/10);

    str(tmp:12:1,numstr);
    writetext(numstr+' ', 51,1, yellow); { 13 }
  end;
  clrbuff;
  inc(OldFeedMult);
indicator(oldmode);
RestoreFeed;
end;
runmode:=oldmode;
SKP:=false; skipPort:=0;
no_stop:=oldstop;
feed0:=oldfeed0;
moving:=0;
(*writetext(stg(timer),2,23,yellow);*)
end;


(**********************************************************

***************      J O G G I N G      *******************

JOG********************************************************)

procedure jog(JogLo:byte); FAR;
var
tmploc:locrec;

label exitpoint;

begin
updatepos;
if (word(handaxis-1)>=axes) and (JogLo<6) then goto exitpoint;
case mode of
mdi,auto,sethome : goto exitpoint;
chktrc : begin drawscreen; htab:=0; end;
end;     {case}

if (word(handaxis-1) < 3) and wristmode and (JogLo<5) then begin
  wrist; {trans %%%02-14-1999, axis and direction are taken from PLC}
end else begin
  ZerInc1:=false;
  case JogLo of
  2,3 : begin
          daddy[handaxis]:= 0;
          if handaxis=ASpin then ZerInc1:=true;
        end;
  1 : begin
        if (Vaxes=0) or ((VaxesL or 1 <>5 ) and (handaxis or 1 =5)) then
          if mode<>setref then begin
            daddy[handaxis]:=
              plimit[handaxis]*MetricS[handaxis]-flzero[handaxis];
              if (Model='C') and (g53F<>0)
                 and (handaxis=Z3) then daddy[Z3]:=daddy[Z3]-zt;
          end else
            daddy[handaxis]:= daddy[handaxis]+
                (plimit[handaxis]-nlimit[handaxis])*MetricS[handaxis]
        else
          daddy[handaxis]:=postravel[handaxis];
        if (mode<>setref) and (grany[handaxis]>daddy[handaxis]) then
          errors.err(127,0,axisname[handaxis]);
      end;
  4 : begin
        if (Vaxes=0) or ((VaxesL or 1 <>5 ) and (handaxis or 1 =5)) then
          if mode<>setref then begin
            daddy[handaxis]:=
              nlimit[handaxis]*MetricS[handaxis]-flzero[handaxis];
              if (Model='C') and (g53F<>0)
                 and (handaxis=Z3) then daddy[Z3]:=daddy[Z3]-zt;
          end else
            daddy[handaxis]:=daddy[handaxis]-
                 (plimit[handaxis]-nlimit[handaxis])*MetricS[handaxis]
        else
          daddy[handaxis]:=negtravel[handaxis];
        if (mode<>setref) and (grany[handaxis]<daddy[handaxis]) then
          errors.err(128,0,axisname[handaxis]);
      end;
6,7 : begin
        if prgname='' then goto exitpoint;
        getloc(L,tmploc,true);
        if not validH(abs(tmploc.h)) then goto exitpoint;
        Vaxes:=tmploc.h;
        move(tmploc.x,daddy,sizeof(axes5));
        if Vaxes<>oldVax then begin
          oldVax:=Vaxes;
          getGrany;
        end;
      end;
  end; {case}
end;
{Manual and Teach Motion}
lineaxes:=$FF;            {all axes}
if (Vaxes<>0) or (mode=chktrc) and (DryRun=0) then begin
  feed0:=Fmax;
  if LinTC<>oldTC then TConst(oldTC);
  g1;
end else begin
  g0;
end;
exactstop;

updatepos;
if (jogLo<>0) and (TBnow>=$80) then begin
  TBnow:=$81;
  if TBnew then cc100(0);
end;
exitpoint:
while jogL<>0 do begin background; ChkJogReleased; end;
{topline;}
end;            { JOG }


(**************************************************************)
         procedure manual_command(manualaxis:word); FAR;
(**************************************************************)
begin
if (mode=mdi) or (mode=auto) or (manualaxis>axes) then
  ouch
else begin
  if toolcomp then errors.err(203,-1,'');
  handaxis:=manualaxis;
end;
end;



procedure doreset;

var saveL:word; saveNN:longint;

begin

RST:=0;

error:=false;
outfree:=$FFFF;
KillGraph0;
CloseAllWin;
nosound;
handaxis:=0;
par[stop]:=0;
saveNN:=nn;
ProgReset;
if not graphnow then begin
  oldscreen;
  if not (graphic or Kanji) then drawscreen;
end;
updatepos;
case mode of
     MDI : mode:=auto;
  SetHome: ;
else
  callcc(102);
  saveL:=L;
  initCS;
  l:=saveL;
  ll:=l;
  nn:=saveNN;
end;
indicator(reseti);
end; { do reset }


function cncDOS(txt:comstr; clr:boolean):integer; FAR;
{if no extension then load command.com }
var dir0:pathstr; name:namestr; ext:extstr;
    Space:integer;
begin
if no_decel then exactstop;      {%%%12-13-94}
{Strip leading blanks}
while (txt<>'') and (txt[1]=' ') do Delete(txt,1,1);
{Find end of command}
Space:=pos(' ',txt)-1;
if Space<0 then Space:=length(txt);
Fsplit(copy(txt,1,Space),dir0,name,ext);

if ext<>'' then begin
  txt:=copy(txt, Space+2,length(txt));
  if dir0='' then dir0:=mydir;
  ASM;
        mov     ax,5F5Fh
        and     [bp+offset ext+2],ax
        and     [bp+offset ext+4],al
  end;
  if (ext<>'.EXE') and (ext<>'.COM') then errors.err(153,n,ext);
  dir0:=dir0+name+ext;
end else
  dir0:='';
if not irq then                   {while in Boot}
  dbli(par[DosErr])[1]:=execdos(dir0,txt)
else begin
  if clr then
    if graphnow then
      goAlpha
    else begin
      textmode(co80); directvideo:=not kanji; checksnow:=false;
    end;
  IrqOff;
  dbli(par[DosErr])[1]:=execdos(dir0,txt);
  IrqOn;
  if clr then begin
    graphics(false);
    putdate;
  end;
end;
DosExit:=DosExitCode;              {%%% 01-09-93}
cncDOS:=dbli(par[DosErr])[1];      {%%% 09-20-92}
dbli(par[DosErr])[4]:=-1;
RST:=0;
end;    {cncDOS}

procedure getsecurity;
begin
if (prog1<>'') and (cncDOS(prog1,true)=0) then begin
  DosExit:=DosExit and $F;              {%%% 02-28-97}
  if DosExit>0 then security:=DosExit;
end;
end;

procedure newpath;
begin
ChangePath;
getdir(0,curdir);
putINI(curdir,'Dir');
putINI(DefExtension,'Ext');
end;

function MainMenu:boolean;
begin
  KillGraph0;
  MainMenu:=false;
  goAlpha;
  dbli(par[190])[4]:=-1;  dblw(par[190])[1]:=1;
  callcc(110);
{          =110
           openwindow( )     This is programmed in the CNX file
           print menu
           #190=readkey
           closewindow
           local routines
           mend
}
  CloseAllWin;                          {For RST<>0}
  keyready;                             {if KB was used}
  case key of
 1200  :  kb(key);                       {RUN}
  $30  :  GetSecurity;
  $31  :  mode:=modet(2);
  $32  :  mode:=modet(3);
  $34  :  GOIOTest;
  $35  :  begin newpath; topline; end;
secretkey:  if compiled then begin
            ErrorPtr:=round(par[200]);
            GoEdit(true);
          end;
  1068 :  begin
            GoEdit(false);
            mode:=auto;                 {%%%04-17-94}
            exit;
          end;
  1079 :  begin MainMenu:=true; EXIT; end; {LogOff}
   end;
  oldscreen;
end;     { Main Menu }

procedure saveloc;        {@F4}
var exist : boolean;
begin
exist:=false;
case TBnow and $8F of
 0 : begin
       save_loc(exist);
       if exist then begin                   {location exists}
         char(Key):= 'Y';                    {Assume 'Y', if CC not found}
         dbli(par[190])[4]:=-1;
         dblw(par[190])[1]:=2;
         callcc(110);                        {ask Yes or No}
       { openwindow( )                        programmed in CNX file
         print menu
         #190=readkey
         closewindow
         mend
       }
         if Curwindow<>0 then begin
           CloseAllWin;
           oldscreen;
         end;
         keyready;
         if char(key and $5F) = 'Y' then begin
           save_loc(exist);            {overwrite location}
         end;
       end;
       Exit;                  {%%%02-18-96}
     end;
$80: begin
       if not save_loc(exist) then Exit;
       ASM;
         mov     al,exist          {if exist then inc(TBnow,3)}
         add     ax,ax                      {else inc(TBnow,1)}
         inc     ax                {81--> beep, OK, 80}
         add     TBnow,al          {83--> beep, sure?, 82}
       end;
     end;
$82: begin
       exist:=true;
       save_loc(exist);
       dec(TBnow);                 {81--> beep, OK, 80}
     end;
 end;
if not exist or TBnew then cc100(0)   {%%%06-23-93 02-18-96}
                                      {print SURE? or OK}
end;

(**************************************************************)
procedure leadinit;         {called from LogOn}
begin
txtl:=selfdir+leadcorr+'.0';
for tic:=1 to axes do begin
  inc(txtl[leng]);
  LeadNow[tic]:=integer(getfile(txtl,LeadPtr[tic])<>0); {0 or 1}
  if LeadNow[tic]<>0 then BootLog(txtl,1);
end;

fassign(corfile,selfdir+leadcorr+'.XYZ');
if dostype(corfile.pname)=1 then BootLog(corfile.pname,1);

end;

procedure CNCinit;         {called from LogOn}
begin
while keyready do;
if security<>superuser then getsecurity;
inchNow:=not inchsys; initCS;  {forces unitIM to re-calculate}
if curdir='' then newpath;
pc:=0;
Fptr:=@Cfile;
irqOn;                     {enable interrupts}
graphics(false);           {draw screen}
breakNow;
while mode<>oldmode do begin
  error:=false;
  background;
end;
end;

(**************************************************************)
procedure disprogram(MCC:boolean);  { display program listing }
(**************************************************************)
type stp=^string;
var i: word;

linenum:longint; j,pp:word;
begin
if MCC then begin
  Fptr:=@Xfile;
end else begin
  Fptr:=@Cfile;
end;
if Fptr^.mode=$D7B3 then begin
  SavePtr:=Fptr^.CurPos;
  openwindow(1,3,80,24, white,$2000);
  writeln('Len= ',Fsize(Fptr^));
  Rseek(Fptr^,prg00);
  while not feof(Fptr^) do begin
    readP(Fptr^,prgP);
    if prgL=0 then begin
      writeln('Text');
      linenum:=0;
      readB(Cfile,linenum,3);
      Rseek(Cfile,linenum);
      continue;
    end;
    pp:=4;
    ASM;
          mov     ax,word ptr [prgB+2]
          xor     dx,dx
          mov     dl,byte ptr [prgB+1]
          cmp     dl,0FFh
          jne     @1
          mov     pp,2
          xor     ax,ax
          xor     dx,dx
    @1:
          mov     word ptr linenum+2,dx
          mov     word ptr linenum,ax
    end;
    write(linenum:8,': ');
    if wptr(@prgb[1])^=$BDFF then  {prog name}
      write(stp(@prgP[3])^)
    else
      while pp<=prgL do begin
        write(hexb(prgB[pp]),' ');
        inc(pp);
      end;
    if keyready and (key=$1B) then break;
    writeln; delay(50);
  end;
  Bseek(Fptr^,SavePtr);
  inkey; closewindow;
end;
Fptr:=@Cfile;
end;


(**************************************************************)

procedure cncmain;
begin  {CNCMAIN}
repeat                     { Main Waiting loop }

if catch(exception) and error then begin    {Trap for Run time error}
  JogL:=0;
  ASM;
        les     bx,Fptr
        mov     ax,Frec(es:[bx]).block
        mul     BufSize
        add     ax,Frec(es:[bx]).BufPos
        xor     bx,bx          {DX:AX= file position for next line}
        mov     bl,prgL
        add     bx,1
        sub     bx,pc          {BX = positive}
        sub     ax,bx
        sbb     dx,0
        mov     word ptr Errorptr+2,dx
        mov     word ptr Errorptr,ax
  end;

  if (runmode>=runi)    {Run, Dwell}
     and
  ((word(Fptr)<>ofs(Xfile))) {not inside CC}
     and
   Compiled            {source exists in editor}
     and
   (security<=superuser+1)
     and
    (TBnow<$80)        {not in Teach}
     and
  (mode in [Auto,MDI]) then begin {we are here if there are no Calls}
    goedit(true);       {will draw screen}
    {return here from a run-time error.
     GoEdit sets a new exception so a fresh start is required}
    continue;
  end else begin
    tmpstr:=Fptr^.pname;
    par[200]:=ErrorPtr;
    ProgReset;
    oldscreen;                  {draws graphic screen}
    callcc(108);                {display error message}
  end;
end;
if odd(RST) then KB(27); {2= ESC pressed}
ASM;
{vactual:=0; RST:=0; SKP:=false; byte(lineaxes):=0;}
{Override:=$FFFF}
        xor     ax,ax
        cmp     byte ptr RST,al
        jz      @1
        mov     byte ptr lineaxes,al {do not cancel in HOLD}
@1:
        cmp     Vactual,1
        ja      @2
        mov     lenR,ax
@2:
        mov     word ptr RST,ax
        mov     skp,al
        mov     Moving,ax
        dec     ax
        mov     Override,ax
end;

background;

if sngle=3 then begin       {end of Search}
  Sngle:=1; callcc(112);
end;

if KBflag and $1008 = $1008 then callcc(105);

if Vaxes<>oldVax then begin        {after incHH or H in MDI}
  oldVax:=Vaxes;
  transforward;
end;

if (TBnow<$80) and (mode<>auto) and (mem[seg0040:$17] and $C = $C) then
  if handaxis<>0 then
    JogL:=succ(mem[seg0040:$18] and 3)
  else
    if (security=superuser) and (modename=manual) then
      JogL:=5+mem[seg0040:$18] and 3; {%%%5-23-92}


if (TBnow>=$80) or TBnew then begin
  if TBpressed<>0 then begin
    TBpressed:=0;
    cc100(TBkey);
  end;
end;

if JogL<>0 then begin
  init;
  if JogH = 0 then JOG(JogL and $7F)
              else begin
                callcc(111);
                while jogL<>0 do begin background; ChkJogReleased; end;
              end;
  continue;
end;

if keyready then begin {Keypressed}
  if word(kbd-$61)<$1A then dec(Kbd,$20);  {upcase}
  callcc(101);
  case Kbd of
    0 : ;
  $1B : DoReset;
1198..1200: begin    {%%%12-05-92 1198 for CNX}
         RST:=0;
         mode:=auto;
         if key=1199 then progreset;
         if key=1198 then Fptr:=@CPLfile;
         cycle_start;
        end;
  1059: begin {F1}
          RunMode:=Edit;
          goAlpha;
          if TBnow>=$80 then begin
            ASM;  and TBnow,7Fh; end;
            if not Help(modeHlp[teach],454) then
              ASM;  or  TBnow,80h; end;
          end else begin
            if (mode<>auto) or (prgname='') or
               (GetHelp(Cfile, prgLong^[1],word(prgLong^[2]),453)) then
              Help(modeHlp[modename],0);
          end;
          GetHoldMode;
          oldscreen;
        end;

       $21,$22 : if security=superuser then disprogram(Kbd=$22);

       1060: {F2} begin
               KillGraph0;
               goAlpha;
               dbli(par[190])[4]:=-1;  dblw(par[190])[1]:=3;
               tmpstr:=CPLdir+'*'+CPLext;
               callcc(110);             {%%%03-18-94}
               {=110
                 The last command should be:
                 putstr('')   (to ignore directory)
                   or
                 putstr(CPLdir$+'........')
               mend}
               CloseAllWin;             {For RST<>0}
               if (tmpstr<>'') and (RST=0) and PickDir(tmpstr) then begin 
{for ESC}
                 Fclose(Cfile);
                 Fptr:=@Cfile;
                 getCPL(tmpStr,0);
               end;
               oldscreen;
             end;
       1061: {F3} graphics(dryrun<2);
       1106:{@F3} isometric;

       1065: {F7} mode:=manual;
  13,  1066: {F8} mode:=MDI;
       1067: {F9} mode:=auto;
       1110:{@F7} mode:=setref;
       1111:{@F8} mode:=sethome;
       1112:{@F9} cycle_start;

       1068:{F10} if MainMenu then EXIT;   {LogOff}  {%%%01-25-93}
       1133:{F11} if prog3<>'' then cncDOS(prog3,true);
       1139:{@F11}if prog4<>'' then cncDOS(prog4,true);

       1138:{^F12} begin
                 goAlpha;
                 EditTool;
                 RST:=0;
                 callcc(119);
                 oldscreen;
             end;
       1134:{F12} if prgname<>'' then begin
               goAlpha;
               Editloc;
               oldscreen;
             end else ouch;
       1140:{@F12} begin
               goAlpha;
               Editpar;
               oldscreen;
             end;

        1120..1129: {alt1..alt0}
               begin
                 dec(Kbd,1119);
                 if Kbd=10 then Kbd:=0;
                 dooffset(Kbd);
                 if runmode=reseti then o:=Kbd;
               end;

        1077 : if graphnow and (zoomc<6) then begin inc(zoomc); setzoom; end;
        {right arrow}

        1075 : if graphnow and (zoomc>-12) then begin dec(zoomc); setzoom; 
end;
        {left arrow}

(*        1072 {UP},
        1080 {DN} : restoreaxes(key); *)

        $41..$43,  {ABC UVW XYZ}
        $55..$5A  : manual_command(caddr[Kbd]-7);

        1201..1210: getTBfeed;
      else
        if mode=manual then
          case Kbd of  {case 3}
            1107:{@F4} saveloc;
            1063: {F5} if word(l-1)<65533 then inc(l);
            1108:{@F5} if l>1 then dec(l);
                 {F5 canceled}
          end {case 3}
        else
          case Kbd of  {case 4}
            1063: {F5} dryrn(1);
            1108:{@F5} dryrn(2);
          end; {case 4}
  end;  {case 1}
end else begin {if no keypressed}
  Kbd:=0;
  if not error then callcc(101);        {%%% 1998-08-10}
end;
until false;
end;

{$R-,S-}
Procedure divZ;  assembler;
{
caller flags    BP+6
caller seg      BP+4
caller ofs      BP+2
caller bp       BP     pushed by this routine

upon entry: DX:AX - Caller data
RET address- beginning of the div instruction, including prefixes}
ASM;
        push    bp        {save bp}
        mov     bp,sp     {set up stack frame}
        push    ds        {save ds}
        push    si        {save si}
        mov     si,[bp+2]
        mov     ds,[bp+4] {DS:SI= ptr to offending instruction}
        cld
@1:
        lodsb             {Search F6 - div command}
        and     al,0F6h
        cmp     al,0F6h
        jne     @1        {loop indefinitely, nothing else can be done}

        lodsb             {load second instruction byte}
        and     al,0C7h   {mask mode, r/m}
        cmp     al,6
        je      @2        {2 byte direct memory operand}
        and     al,0C0h
        cmp     al,080h
        jne     @3
@2:
        inc     si        {2 byte indirect mem operand}
        jmp     @4
@3:
        cmp     al,040h
        jne     @5        {no displacement}
@4:
        inc     si        {1 byte indirect}
@5:
        mov     [bp+2],si {new return address}
        sar     dx,15     {DX= sign}
        mov     ax,7FFFh  {AX=7FFFh}
        add     ax,dx     {AX=7FFFh or 7FFEh}
        xor     ax,dx     {AX=8001h if negative}
        pop     si        {resume saved registers}
        pop     ds
        pop     bp
        IRET
end;


procedure cleanup; FAR;
begin
exitproc:=exitsave;
ASM;
        mov     ax,4Fh
        mov     es,ax
        xor     di,di
        cld
        mov     ax,exitcode
        stosw
db      66h
        mov     ax,word ptr erroraddr
db      66h
        stosw
end;
setintvec($15,pointer(@oldint15^));
Setintvec(0,oldint00);
if offline then res70
           else close(cncdrv);
InOutRes:=0;
SaveUpdateFile;
ChDir(DosDir);
IOcleanup;         {Disable PLC, clear digital IO}
callcc(125);
nosound;
textmode(OrigMode);
end;

{$IFDEF debug}
{$R+}
{$ENDIF}

procedure initialization;
var i,j,io:word;
const xc = 68;
      yc = 1; { xc=69-1, yc=2-1; time position }
begin
getdir(0,DosDir);

timeoffs:=yc*160+2*xc;
timeattr:=lightgreen;

getintvec($15,pointer(@oldint15^));
setintvec($15,@myint15);

getintvec($70,oldint70);

getintvec(0,oldint00);
setintvec(0,@divZ);

exitsave:=exitproc;
exitproc:=@cleanup;
xold:=xpos; fillchar(oldb,sizeof(oldb),#0);
assign(cncdrv,'CNCSERVO');             {device driver}
getwheel;
getwheel;
end;

procedure Pscreen;   FAR;
var oldcursor : word absolute 0:$460;
    cursorsaved:word;
const st:string[2]='00';
begin
if prog2<>'' then begin
  cursorsaved:=oldcursor;
  beep(1034,100);
  irqoff;
  byte(st[1]):=$30+byte(graphnow or Kanji or GraphScr); {0 = alpha}
  byte(st[2]):=$30+byte(graphnow and not GraphScr);
  if st[2]<>'0' then inc(st[2],byte(iso));
  {0=normal, 1=proj, 2=iso}
  if execdos(prog2, st)<>0 then ouch else beep(1034,100);
  irqon;
  edsetcursor(cursorsaved);
  nosound;
end;
end;

procedure SetRefCorr;
var i:word;
begin
CorrFlag:=true;
MyAxis:=$FFFF;
for i:=1 to axes do begin
  twoint(corr[i]).hi:=1;
  AxisMisc;
end;
oldindex:=-1;
AxisMisc;
CorrFlag:=false;
end;

procedure Corr3D(on:boolean);
begin
corr3:=0;
corr1:=byte(on);
if on then begin
  freset(corfile,6);
  if ioresult=0 then begin
    corr3:=1;
    readb(Corfile,Csize,18);
    corfile.base:=18;
  end;
  SetRefCorr;
    {for tic:=1 to axes+1 do begin
       oldcorr[tic]:=corr;
       dec(xpos[tic],oldcorr[tic]);
       disflag:=...
     end;}
end else begin
  Fclose(Corfile);
  for tic:=1 to axes do begin
    inc(xpos[tic],oldcorr[tic]);
    oldcorr[tic]:=0;
    corrPLC[tic]:=0;
    asm; or disflag,0FFh end;
  end;
end;
corr13d:=corr13;
updatepos;
end;


BEGIN
dwellp    :=dwell;     {NCRUN, NCG}
graphlinep:=graphline;
go_waitp  :=go_wait;   {NCG}
breakp    :=breakNow;  {NCG}
clrtrcp   :=clrtrc;    {NCRUN}
oldscreenp:=oldscreen; {NCRUN}
cncdosp   :=cncdos;    {NCRUN}
updatep   :=updateX;   {NCRUN}
shortbuffP:=shortbuff; {NCRUN}
PLCmesgp  :=PLCmesg;   {KBOARD}
Pscreenp  :=Pscreen;   {KBOARD}
Graph0P   :=Graph0;    {RUNTIME}
backP     :=background;{RUNTIME}
corr3dP   :=corr3D;    {RUNTIME}
trcerrP   :=trcerr;    {RUNTIME}
testP     :=test;      {RUNTIME}
plcfunc[-10]:=@clrtrc;

initialization;
feedstr:=getmessage(410);
END.


Title NCL.ASM, CNC Motion routines, Copyright 1988, 1999 by Gil Hagiz
        .386
Include buffer.asm
dseg    segment dword public 'data' use16
        extrn   dryrun:byte, handaxis:word, TBnow:byte
        extrn   oldw:byte, OneAxis:word, FeedLow:word
        extrn   FeedMult:word, FeedSelector:word, FeedTable:word
        extrn   xpos:word, abszero:dword, PosBuf:word, remain:word
        extrn   vdesired:word,accel:word, decel:word, override:word
        extrn   oldint70:word, vactual:word,axes:word
        extrn   vfrac:word, vhigh:word, fe:word, findv:byte
        extrn   outgroup:dword, outnow:word, outbits:word, outfree:word
        extrn   buffin:word, buffout:word, buffers:word
        extrn   par:word, lenR:word, decelflag:byte, PLCtrc:word
        extrn   no_decel:byte, RST:byte, SKP:byte;
        extrn   tracerr:word, float:byte, disflag:byte
        extrn   corr:word, timer:word, timer1:word, xskip:dword
        extrn   totalAS:word, axis4:word, irqt:word
        extrn   trctmp:word, oldcorr:word, LinTC0:word
        extrn   Plimit:word, Nlimit:word, plc0:dword,PLCin:word
        extrn   Fcorr1:word, Follower:word, Fgain1:word
        extrn   Fcorr2:word, Follower2:word, Fgain2:word
        extrn   Mav:dword, rem:word, totMav:word, Lcount:word
        extrn   HW:word, HandWheel:word, mavLen:word
        extrn   ASpin:word, Rdesired:word, Ractual:word,Raccel:word
        extrn   Rratio:word, fmode:word, Spindle:word
        extrn   LowX:word, Fly:word, FLrate:word
        extrn   divisor:word, ModuloN:word,feeds100:word, feedtime:word
        extrn   Kanji:byte, TimeOffs:word, TimeAttr:byte, segB800:word

Rfrac   dw      (?)
Zfrc1   dw      (?)
Zfrc2   dw      (?)
frc3    dw      (?)
frc4    dw      (?)
align   4
position  dd    0,0,0,0,0,0,0,0         ;absolute position
servo   dd      0,0,0,0,0,0,0,0         ;servo - trace error
total   dd      0,0,0,0,0,0,0,0         ;trace error fractions
dseg    ends

        extrn   doOutput:far

eoi     equ 20h
inta00  equ 20h
intb00  equ 0A0h
intb01  equ 0A1h

;--------------------------------------;

code    segment dword public use16

        assume  cs:code, ds:dseg, es:dseg

        public  newfeed, myint15, oldint15, Motion
        public  ready, Simulation, skip, goASM, cmd9A, updateX
        public  trace, clrbuff, clrtrc, trcerr, prep70, res70
        public  writetime,CMOSwr, CMOSrd

;---------------------------------------;
        db 'Copyright (C) 1988 by Gil Hagiz '
;---------------------------------------;
;       clear buffer
;buffout:=ofs(buffers); buffin:=buffout;
;q0:=0; q1:=0; q2:=0; q3:=0; q4:=0;....... qlast:=0;
;TotalAS:=0;
;---------------------------------------;
clrbuff proc    near
        cli
        mov     ax,offset buffers
        mov     buffin,ax
        mov     buffout,ax
        mov     dx,ax
        mov     di,ax

        xor     eax,eax
        mov     dword ptr totalAS,eax
clr0:
        mov     [di+qq],eax
        mov     [di+qOut],ax
        mov     di,[di]
        cmp     di,dx
        jne     short clr0

        sti
        ret
clrbuff endp

;---------------------------------------;
;       waiting loop
;
;This function returns Buffer-Ready.
;If No_decel is true then ready is true when at least
;one buffer is empty.
;If No_decel is false then ready is true when all
;buffers are empty
;
;---------------------------------------;
ready   proc    near
        xor     eax,eax                 ;assume false
        mov     si,buffin
        mov     bx,buffout
        cmp     bx,[si]                 ;ptr to next buffer
        je      short ready1            ;all buffers are full
        add     al, no_decel            ;zero= deceleration
        jnz     short ready1            ;ready:=no_decel
        mov     si, buffout             ;wait for all buffers empty
        cmp     si, buffin              ;equal= last buffer
        jne     short ready1
        cmp     eax,[si+qq]             ;is buffer empty?
        jnz     short ready1
        inc     ax
ready1:
        ret
ready   endp

;---------------------------------------;
;     update floating axes and outputs
;---------------------------------------;
goASM   proc    near                    ;delayed output
        BSF     bx,outnow               ;bx= bit position 0..F
        jz      short Floats            ;if zero BX= no change
        BTS     outfree,bx
        BTR     outnow,bx
        shl     bx,2
        xor     eax,eax
        xchg    [bx+outgroup],eax
        push    eax
        call    doOutput
        jmp     short goASM             ;see if more
Floats:
        mov     bl,1
        mov     bh,float
        xor     di,di
float1:
        test    bl,bh
        jz      short float2            ;not floating
        or      cx,-1
        stc                             ;CF=1
        call    cs:dword ptr drvofs     ;cx=-1
        test    ax,ax
        jz      short float2            ;no change
        sub     [di+xpos], ax           ;update absolute position
        sbb     [di+xpos+2],dx
        or      disflag,bl              ;update display flag
float2:
        shl     bl,1
        add     di,4
        cmp     di,axis4
        jb      short float1
        ret
goASM   endp