home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 138.DIGITIZE.PAS < prev    next >
Pascal/Delphi Source File  |  1988-10-18  |  21KB  |  503 lines

  1. (****************************************************************************)
  2. (***                                                                      ***)
  3. (***  Digitizer is to read data directly from the digitizing pad, then    ***)
  4. (***  perform analysis on that data until it represents the "actual"      ***)
  5. (***  waveform in the photograph. The digitizer used is the Micro         ***)
  6. (***  Digi-Pad 6"x6" Electromagnetic Type 7 digitizer from GTCO Corp.     ***)
  7. (***  The input parameter DataToDigitize determines whether to digitize   ***)
  8. (***  time or frequency domain data.                                      ***)
  9. (***                                                                      ***)
  10. (****************************************************************************)
  11.  
  12. UNIT DigitizeWaveform;
  13.  
  14. INTERFACE
  15. USES
  16. {$IFDEF DOSCrt}
  17.    DOSCrt,
  18. {$ELSE}
  19.    Crt,
  20. {$ENDIF}
  21.    Extended_Reals,
  22.    TextOps,
  23.    Async,
  24.    Graph,
  25.    DrawGraf,
  26.    Global,
  27.    GraphText;
  28.  
  29. PROCEDURE Digitizer ( DataToDigitize : CHAR);
  30.  
  31.  
  32. PROCEDURE Digitize_Wave;
  33.  
  34.  
  35. (****************************************************************************)
  36.  
  37. IMPLEMENTATION
  38.  
  39.  
  40. CONST
  41.    Reset_Command    = 'RS';         { Reset digitizer to power-up        }
  42.    Point_Command    = 'P1';         { Set digitizer to point input       }
  43.    parity           = 'N';           { Set digitizer to no parity         }
  44.    baud_rate        = 9600;          { Set digitizer to 9600 Baud         }
  45.    data_bits        = 8;             { Set digitizer to 8 bits per word   }
  46.    stop_bits        = 2;             { Set digitizer to two stop bits     }
  47.    PauseLength      = 250;           { Pause after sending commands       }
  48.    ShortPauseLength = 100;           { Delay between digitizer bytes      }
  49.    MinX             = 100;           { Left edge of digitizer work area   }
  50.    MaxX             = 2000;          { Right edge of digitizer work area  }
  51.    MinY             = 200;           { Bottom edge of digitizer work area }
  52.    MaxY             = 1800;          { Top edge of digitizer work area    }
  53.    NormSize : byte  = 1;             { Normal size of default font        }
  54.  
  55. VAR
  56.    ch1,ch2,ch3,ch4,ch5 : CHAR;        { input from digitizer              }
  57.        in2,in3,in4,in5 : INTEGER;     { INTEGER (ch)                      }
  58.    INCOMING            : BOOLEAN;     { valid data coming from digitizer? }
  59.    EMPTY               : BOOLEAN;     { is input buffer empty?            }
  60.    VALID_PORT          : BOOLEAN;     { is a device connected to COM?     }
  61.    quit                : CHAR;        { done viewing picture?             }
  62.    min_time            : REAL;        { minimum time                      }
  63.    max_time            : REAL;        { maximum time                      }
  64.    min_amplitude       : REAL;        { minimum amplitude                 }
  65.    max_amplitude       : REAL;        { maximum amplitude                 }
  66.    horiz_units         : string;      { horizontal axis units             }
  67.    vert_units          : string;      { vertical axis units               }
  68.    leftx               : INTEGER;     { Left edge of window boundary      }
  69.    rightx              : INTEGER;     { Right edge of window boundary     }
  70.    topy                : INTEGER;     { Top edge of window boundary       }
  71.    bottomy             : INTEGER;     { Bottom edge of window boundary    }
  72.    FreqDATA            : BOOLEAN;     { DataToDigitize = 'F'?             }
  73.  
  74. {----------------------------------------------------------------------------}
  75. {-                                                                          -}
  76. {-    Rotate_Waveform transforms each point (x',y') in oblique              -}
  77. {-    coordinates to point (x,y) in rectangular coordinates. This is        -}
  78. {-    done to ensure true horizontal and vertical axes. The specific        -}
  79. {-    steps performed are                                                   -}
  80. {-        1. Calculate true origin; set equal to (x1,y1).                   -}
  81. {-        2. Determine scaling factors and units.                           -}
  82. {-        3. Transform oblique coordinates to rectangular coordinates.      -}
  83. {-        4. Eliminate coordinate axes information.                         -}
  84. {-        5. Eliminate non-sequential data points.                          -}
  85. {-                                                                          -}
  86. {----------------------------------------------------------------------------}
  87.  
  88. PROCEDURE Rotate_Waveform;
  89.  
  90.    CONST
  91.       epsilon = 1;
  92.  
  93.    VAR
  94.       x0,y0           : REAL;            { coordinates of true origin   }
  95.       mr              : REAL;            { slope of radius axis         }
  96.       mx              : REAL;            { slope of digitized x axis    }
  97.       my              : REAL;            { slope of digitized y axis    }
  98.       r               : REAL;            { magnitude of radius vector   }
  99.       rx              : REAL;            { length of digitized x axis   }
  100.       ry              : REAL;            { length of digitized y axis   }
  101.       theta           : REAL;            { phase of radius vector       }
  102.       phi             : REAL;
  103.       omega           : REAL;
  104.       i               : INTEGER;         { counter variable             }
  105.       j               : INTEGER;         { counter variable             }
  106.       k               : INTEGER;         { counter variable             }
  107.       dummy           : string;          { time plus multiplier, units  }
  108.       total_amplitude : REAL;            { amp/div * number of div      }
  109.       xfactor         : REAL;            { x scaling factor             }
  110.       yfactor         : REAL;            { y scaling factor             }
  111.       delta_x         : REAL;            { diff between x coor, origin  }
  112.       delta_y         : REAL;            { diff between y coor, origin  }
  113.  
  114.    BEGIN   {Rotate_Waveform}
  115.       ClrScr;
  116.       {-      Calculate origin     -}
  117.       mx:=(TempYPtr^[2]-TempYPtr^[1])/(TempXPtr^[2]-TempXPtr^[1]);
  118.       IF (ABS (TempXPtr^[4]-TempXPtr^[3]) < epsilon)
  119.          THEN x0:=0.5*(TempXPtr^[3]+TempXPtr^[4])
  120.          ELSE BEGIN
  121.             my:=(TempYPtr^[4]-TempYPtr^[3])/(TempXPtr^[4]-TempXPtr^[3]);
  122.             x0:=(TempYPtr^[2]-TempYPtr^[3]+my*TempXPtr^[3]
  123.                                           -mx*TempXPtr^[2])/(my-mx);
  124.          END;   {ELSE}
  125.       y0:=TempYPtr^[2]+mx*(x0-TempXPtr^[2]);
  126.       TempXPtr^[0]:=x0;
  127.       TempYPtr^[0]:=y0;
  128.  
  129.       {-     Determine scaling factors     -}
  130.       delta_x:=TempXPtr^[2]-x0;
  131.       delta_y:=TempYPtr^[2]-y0;
  132.       rx:=sqrt(sqr(delta_x)+sqr(delta_y));
  133.       delta_x:=TempXPtr^[4]-TempXPtr^[3];
  134.       delta_y:=TempYPtr^[4]-TempYPtr^[3];
  135.       ry:=sqrt(sqr(delta_x)+sqr(delta_y));
  136.  
  137.       IF FreqDATA
  138.          THEN BEGIN
  139.             Write ('Minimum frequency: ');  ReadLn (dummy);
  140.             String_To_Value (dummy,min_time,horiz_units);
  141.             Write ('Maximum frequency: ');  ReadLn (dummy);
  142.             String_To_Value (dummy,max_time,horiz_units);
  143.             xfactor:=(max_time-min_time)/rx;
  144.             Write ('Minimum amplitude: ');  ReadLn (dummy);
  145.             String_To_Value (dummy,min_amplitude,vert_units);
  146.             Write ('Maximum amplitude: ');  ReadLn (dummy);
  147.             String_To_Value (dummy,max_amplitude,vert_units);
  148.             yfactor:=(max_amplitude-min_amplitude)/ry;
  149.          END   {THEN}
  150.          ELSE BEGIN
  151.             min_time:=0;
  152.             Write ('Maximum time: ');    ReadLn (dummy);
  153.             String_To_Value (dummy,max_time,horiz_units);
  154.             xfactor:=max_time/rx;
  155.             min_amplitude:=0;
  156.             Write ('Total amplitude: '); ReadLn (dummy);
  157.             String_To_Value (dummy,max_amplitude,vert_units);
  158.             yfactor:=max_amplitude/ry;
  159.          END;   {ELSE}
  160.  
  161.       {-   Switch from input coordinates to rectangular coordinates      -}
  162.       delta_x:=TempXPtr^[2]-x0;
  163.       delta_y:=TempYPtr^[2]-y0;
  164.       theta:=arctan (delta_y/delta_x);
  165.       delta_y:=TempYPtr^[3]-y0;
  166.       IF delta_y < epsilon
  167.          THEN BEGIN
  168.             delta_y:=TempYPtr^[4]-y0;
  169.             delta_x:=TempXPtr^[4]-x0;
  170.             IF delta_x < epsilon
  171.                THEN phi:=-0.5*PI
  172.                ELSE phi:=arctan (delta_y/delta_x);
  173.          END   {THEN}
  174.          ELSE BEGIN
  175.             delta_x:=TempXPtr^[3]-x0;
  176.             IF delta_x < epsilon
  177.                THEN phi:=0.5*PI
  178.                ELSE phi:=arctan (delta_y/delta_x);
  179.          END;   {ELSE}
  180.       omega:=phi-theta;
  181.       FOR i:=5 TO NumPoints + 4 DO BEGIN
  182.          delta_x:=(TempXPtr^[i]-x0)*cos(theta)+
  183.                   (TempYPtr^[i]-y0)*cos(omega+theta);
  184.          delta_y:=(TempXPtr^[i]-x0)*sin(theta)+
  185.                   (TempYPtr^[i]-y0)*sin(omega+theta);
  186.          TempXPtr^[i]:=(delta_x*xfactor + min_time);
  187.          TempYPtr^[i]:=(delta_y*yfactor + min_amplitude);
  188.       END;   {FOR}
  189.  
  190.       {-     Eliminate coordinate axes, non-sequential information.     -}
  191.       IF FreqDATA
  192.          THEN BEGIN
  193.             TempXPtr^[0]:=TempXPtr^[5];
  194.             TempYPtr^[0]:=TempYPtr^[5];
  195.             i:=1;
  196.          END   {THEN}
  197.          ELSE BEGIN
  198.             TempXPtr^[0]:=0;
  199.             TempYPtr^[0]:=0;
  200.             TempXPtr^[1]:=TempXPtr^[5];
  201.             TempYPtr^[1]:=TempYPtr^[5];
  202.             i:=2;
  203.             INC (NumPoints,1);
  204.          END;   {ELSE}
  205.       j:=6;
  206.       k:=0;
  207.       REPEAT
  208.          WHILE TempXPtr^[j] <= TempXPtr^[i-1] DO BEGIN
  209.             INC (j,1);
  210.             INC (k,1);
  211.          END;   {WHILE}
  212.          TempXPtr^[i]:=TempXPtr^[j];
  213.          TempYPtr^[i]:=TempYPtr^[j];
  214.          INC (i,1);
  215.          INC (j,1);
  216.       UNTIL (i+k=NumPoints);
  217.       DEC (NumPoints,k);
  218.    END;   {Rotate_Waveforms}
  219.  
  220.  
  221. {----------------------------------------------------------------------------}
  222. {-                                                                          -}
  223. {-    Draw_waveform sets up a window for drawing the digitized waveform,    -}
  224. {-    then draws it.                                                        -}
  225. {-                                                                          -}
  226. {----------------------------------------------------------------------------}
  227.  
  228. PROCEDURE Draw_Waveform;
  229.  
  230.    VAR
  231.       error  : BYTE;
  232.       i      : INTEGER;
  233.       xdelay : REAL;
  234.       ydelay : REAL;
  235.  
  236.    BEGIN   {Draw_Waveform}
  237.       ClearViewPort;
  238.       leftx:=SUCC(GetMaxX) div 8;
  239.       rightx:=7*leftx;
  240.       bottomy:=3*(SUCC(GetMaxY) div 8);
  241.       topy:=7*(GetMaxY div 8);
  242.       DrawGraph (TempXPtr,TempYPtr,NumPoints,Linear,leftx,topy,
  243.                       rightx,bottomy,xdelay,ydelay,'','',error);
  244.    END;   {Draw_Waveform}
  245.  
  246. {----------------------------------------------------------------------------}
  247. {-                                                                          -}
  248. {-    Initialize_Digitizer opens the COM port (port SerialPort, as          -}
  249. {-    selected from the Advanced Options Menu; the default is COM1:)        -}
  250. {-    then sends commands to the digitizer to reset it to power up          -}
  251. {-    conditions, then set it to the point mode. The input buffer is        -}
  252. {-    then emptied.                                                         -}
  253. {-                                                                          -}
  254. {----------------------------------------------------------------------------}
  255.  
  256. PROCEDURE Initialize_Digitizer;
  257.  
  258.    BEGIN   {Initialize_Digitizer}
  259.       VALID_PORT:=TRUE;
  260.       Async_Init;
  261.       IF NOT Async_Open (SerialPort,baud_rate,parity,data_bits,stop_bits)
  262.          THEN BEGIN
  263.             Write ('Invalid port!');
  264.             VALID_PORT:=FALSE;
  265.          END   {THEN}
  266.          ELSE BEGIN
  267.             Async_Send_String (Reset_Command);
  268.             Async_Send_String (Point_Command);
  269.             Delay (PauseLength);
  270.             REPEAT UNTIL NOT Async_Buffer_Check (ch1);
  271.          END;   {ELSE}
  272.    END;   {Initialize_Digitizer}
  273.  
  274. {----------------------------------------------------------------------------}
  275. {-                                                                          -}
  276. {-    Read_Digitizer tests if there is a character in the input buffer.     -}
  277. {-    If yes, then the next four characters are read. (The Digi-Pad         -}
  278. {-    digitizer uses five bytes per input point.) The input buffer is       -}
  279. {-    then emptied. Note that a delay MUST occur between each buffer        -}
  280. {-    check, or the computer will not recognize the information.            -}
  281. {-                                                                          -}
  282. {----------------------------------------------------------------------------}
  283.  
  284. PROCEDURE Read_Digitizer;
  285.  
  286.    BEGIN   {Read_Digitizer}
  287.            WRITEtext('here at 1',1,1);
  288.       IF ASYNC_BUFFER_CHECK (CH1) THEN WRITETEXT('ASYNC BUFFER CHECK = TRUE',1,15)
  289.          ELSE WRITETEXT('ASYNC BUFFER CHECK = FALSE',1,15);
  290.       IF Async_Buffer_Check (ch1) THEN BEGIN
  291.            writetext('here at 14',1,14);
  292.          Delay (PauseLength);
  293.            WRITEtext('here at 2',1,2);
  294.          IF Async_Buffer_Check (ch2) THEN in2:=INTEGER(ch2) AND $3F;
  295.          Delay (PauseLength);
  296.          IF Async_Buffer_Check (ch3) THEN in3:=INTEGER(ch3) AND $3F;
  297.          Delay (PauseLength);
  298.          IF Async_Buffer_Check (ch4) THEN in4:=INTEGER(ch4) AND $3F;
  299.          Delay (PauseLength);
  300.          IF Async_Buffer_Check (ch5) THEN in5:=INTEGER(ch5) AND $3F;
  301.            DELAY (PAUSELENGTH);
  302.            WRITEtext('here at 3',1,3);
  303.          INC (i,1);
  304.            WRITEtext('here at 4',1,4);
  305.          TempXPtr^[i]:=(in3 shl 6) OR in2;
  306.          TempYPtr^[i]:=(in5 shl 6) OR in4;
  307.          PutPixel (round(TempXPtr^[i]),round(TempYPtr^[i]),white);
  308.            WRITEtext('here at 5',1,5);
  309.          REPEAT UNTIL NOT Async_Buffer_Check (ch1);
  310.            WRITEtext('here at 6',1,6);
  311.        END;   {IF}
  312.        delay(2000);
  313.    END;   {Read_Digitizer}
  314.  
  315. {----------------------------------------------------------------------------}
  316. {-                                                                          -}
  317. {-    Read_Keyboard detects either an ENTER or ESCAPE key being pressed,    -}
  318. {-    otherwise, keyboard input is ignored.                                 -}
  319. {-                                                                          -}
  320. {----------------------------------------------------------------------------}
  321.  
  322. PROCEDURE Read_Keyboard (VAR DONE : BOOLEAN);
  323.  
  324.    BEGIN   {Read_Keyboard}
  325.       DONE:=FALSE;
  326.          writetext('here at 7',1,7);
  327.       IF keypressed THEN BEGIN
  328.          writetext('here at 8',1,8);
  329.          ch1:=ReadKey;
  330.          IF ch1 = ENTER
  331.             THEN DONE:=TRUE
  332.          ELSE IF ch1 = ESC
  333.             THEN BEGIN
  334.                 writetext('here at 9',1,9);
  335.                PutPixel (round(TempXPtr^[i]),round(TempYPtr^[i]),black);
  336.                DEC (i,1);
  337.                SetColor (DrawColor);
  338.             END;   {ELSE-IF}
  339.       END;   {IF}
  340.    END;   {Read_Keyboard}
  341.  
  342. {----------------------------------------------------------------------------}
  343. {-                                                                          -}
  344. {-    Set_Up_Axes uses the first two points input as the left and right     -}
  345. {-    enpoints of the x axis, and the next two points as the top and        -}
  346. {-    bottom of the y axis.                                                 -}
  347. {-                                                                          -}
  348. {----------------------------------------------------------------------------}
  349.  
  350. PROCEDURE Set_Up_Axes;
  351.  
  352.    VAR
  353.       correct : CHAR;
  354.       dummy   : BOOLEAN;
  355.  
  356.    BEGIN   {Set_Up_Axes}
  357.       delay(4000);
  358.       REPEAT
  359.          writetext ('here at 10',1,10);
  360.          WriteText ('Enter x axis coordinates: ',22,21);
  361.          writetext ('here at 11',1,11);
  362.          i:=0;
  363.          REPEAT
  364.             Read_Digitizer;
  365.             Read_Keyboard (dummy);
  366.                writetext('here at 12',1,12);
  367.                DELAY(3000);
  368.                CLEARVIEWPORT;
  369.          UNTIL i=2;
  370.                writetext('here at 13',1,13);
  371.          Line (round(TempXPtr^[1]),round(TempYPtr^[1]),
  372.                round(TempXPtr^[2]),round(TempYPtr^[2]));
  373.          WriteText ('Enter y axis coordinates: ',22,21);
  374.          REPEAT
  375.             Read_Digitizer;
  376.             Read_Keyboard (dummy);
  377.          UNTIL i=4;
  378.          Line (round(TempXPtr^[3]),round(TempYPtr^[3]),
  379.                round(TempXPtr^[4]),round(TempYPtr^[4]));
  380.          WriteText ('Are axes correct?         ',22,21);
  381.          Buzzer;
  382.          correct:=UpCase(ReadKey);
  383.          IF (correct = 'Y') THEN Exit;        { Quit when axes are correct. }
  384.          ClearViewport;
  385.          SetViewPort (MinX,MinY,MaxX,MaxY,ClipOn);
  386.       UNTIL FALSE;
  387.    END;   {Set_Up_Axes}
  388.  
  389. {----------------------------------------------------------------------------}
  390. {-                                                                          -}
  391. {-    Add_Comments is used to store descriptive information with the data   -}
  392. {-    as comments. These descriptors include                                -}
  393. {-       1. Test Point.                                                     -}
  394. {-       2. Test Type.                                                      -}
  395. {-       3. Attenuation factor.                                             -}
  396. {-       4. Probe Number.                                                   -}
  397. {-       5. x-axis units.                                                   -}
  398. {-       6. y-axis units.                                                   -}
  399. {-       7. Any additional comments.                                        -}
  400. {-                                                                          -}
  401. {----------------------------------------------------------------------------}
  402.  
  403. PROCEDURE Add_Comments;
  404.  
  405.    VAR
  406.       i  : INTEGER;
  407.       st : string[80];
  408.  
  409.    BEGIN
  410.       ClrScr;
  411.       Write ('Test Point:   '); ReadLn (st); info[1]:='Test Point:   '+st;
  412.       Write ('Test Type:    '); ReadLn (st); info[2]:='Test Type:    '+st;
  413.       Write ('Attenuation:  '); ReadLn (st); info[3]:='Attenuation:  '+st;
  414.       Write ('Probe Number: '); ReadLn (st); info[4]:='Probe Number: '+st;
  415.       Write ('Comments:     '); ReadLn (st); info[7]:='Comments:     '+st;
  416.       info[5]:='X-Axis units: '+horiz_units;
  417.       info[6]:='Y-Axis units: '+vert_units;
  418.       FOR i:=8 TO MaxInfo DO info[i]:=blank;
  419.    END;   {Add_Comments}
  420.  
  421. {----------------------------------------------------------------------------}
  422.  
  423. PROCEDURE Digitizer ( DataToDigitize : CHAR);
  424.  
  425.    VAR
  426.       STOP : BOOLEAN;     { done yet?                         }
  427.       i    : INTEGER;     { counter variable                  }
  428.  
  429.    BEGIN   {Digitizer}
  430.       FreqDATA:=(DataToDigitize = 'F');
  431.       SetGraphMode (GraphMode);
  432.       SetViewPort (MinX,MinY,MaxX,MaxY,ClipOn);
  433.       SetColor (DrawColor);
  434.       STOP:=FALSE;
  435.       Initialize_Digitizer;
  436.       IF VALID_PORT THEN BEGIN
  437.          REPEAT UNTIL NOT Async_Buffer_Check (ch1);
  438.          WHILE keypressed DO ch1:=ReadKey;
  439.          Set_Up_Axes;
  440.          WriteText ('Enter x,y coordinate pairs.            ',22,21);
  441.          WriteText ('Press ESC to erase, or ENTER to finish.',22,23);
  442.          REPEAT
  443.             Read_Digitizer;
  444.             Read_Keyboard (STOP);
  445.          UNTIL STOP;
  446.          ClearLine (22,21,40);
  447.          ClearLine (22,23,40);
  448.          NumPoints:=i-4;
  449.          IF (NumPoints >= 5)
  450.             THEN BEGIN
  451.                RestoreCrtMode;
  452.                Rotate_Waveform;
  453.                Add_Comments;
  454.                SetGraphMode (GraphMode);
  455.                Draw_Waveform;
  456.                Async_Send_String (Reset_Command);
  457.                Async_Close;
  458.                WriteText ('Strike any key to return to Main Menu.',22,20);
  459.                ORIG:=TRUE;
  460.                TRANS:=FALSE;
  461.                ACCEPT:=FALSE;
  462.                time^:=TempXPtr^;
  463.                ampl^:=TempYPtr^;
  464.             END   {THEN}
  465.             ELSE BEGIN
  466.                WriteText ('Too few points input. ',22,21);
  467.                WriteText ('Strike any key to continue ...',22,23);
  468.                ORIG:=FALSE;
  469.                TRANS:=FALSE;
  470.                ACCEPT:=FALSE;
  471.             END;   {ELSE}
  472.          Quit:=ReadKey;
  473.       END;   {IF VALID_PORT}
  474.       RestoreCRTMode;
  475.       TextColor (ForeColor);
  476.       TextBackground (BackColor);
  477.       ClrScr;
  478.    END;   {Digitizer}
  479.  
  480. {----------------------------------------------------------------------------}
  481.  
  482. PROCEDURE Digitize_Wave;
  483.  
  484.    VAR
  485.       ch : CHAR;
  486.  
  487.    BEGIN   {Digitize_Wave}
  488.       IF (SerialPort <> 0) THEN BEGIN
  489.          GotoXY (StartColumn,23);
  490.          Write ('Digitize time or frequency data (T/F)? ');
  491.          REPEAT
  492.             ch:=UpCase(ReadKey);
  493.          UNTIL (ch IN ['T','F',ENTER]);
  494.          IF (ch = ENTER)
  495.             THEN Digitizer ('T')
  496.             ELSE Digitizer (ch);
  497.       END;   {IF}
  498.    END;   {Digitize_Wave}
  499.  
  500. (****************************************************************************)
  501.  
  502. BEGIN   {Initialization}
  503. END.   {Initialization}