unit PP_PGMHW;

{== Ovladani programatoru ==}

{========================================================}
{   (c)DECROS 2000 miho, pefi                            }
{   1.0 - ovladani programatoru pres LPT a ALL03         }
{   1.1 - zmena vystupu cisla portu z DEC na HEX         }
{       - doplneni xDelayMicro(1) u vazby na ALL03       }
{========================================================}


interface

uses DELAY,
     PP_ALL03;

type  Logical=(zero,one,tristate);   { typ pro definovani stavu vystupu }

type PGM = object
     {-- Rodicovsky objekt pro ovladani programatoru --}

     _PortAdr : word;    { adresa portu }
     _Error   : string;  { retezec posledni chyby }

     constructor Init(Port:word);
     {== inicializuje a zapamatuje adresu ==}

     procedure Error(S:string);
     virtual;
     {== vypise chybu ==}

     procedure Info(S:string);
     virtual;
     {== vypise info ==}

     procedure SetVcc(Voltage:real);
     virtual;
     {== nastav napajeni ==}

     procedure SetVpp(Voltage:real);
     virtual;
     {== nastav programovaci napeti ==}

     procedure SetReset(Stat:Logical);
     virtual;
     {== nastav signal RESET dle Stat ==}

     procedure SetData(Stat:Logical);
     virtual;
     {== nastav signal DATA dle Stat ==}

     procedure SetClock(Stat:Logical);
     virtual;
     {== nastav signal CLOCK dle Stat ==}

     function GetData:boolean;
     virtual;
     {== precte stav datoveho vstupu ==}

           end; {object}

type PGM_p=^PGM;

type PGM_LPT = object(PGM)
     {-- Objekt ovladani programatoru pres LPT --}

     _PortStat : byte;

     constructor Init(Port:word);
     {== inicializuje, vstupem je cislo portu ==}

     procedure SetVcc(Voltage:real);
     virtual;
     {== nastav napajeni ==}

     procedure SetVpp(Voltage:real);
     virtual;
     {== nastav programovaci napeti ==}

     procedure SetReset(Stat:Logical);
     virtual;
     {== nastav signal RESET dle Stat ==}

     procedure SetData(Stat:Logical);
     virtual;
     {== nastav signal DATA dle Stat ==}

     procedure SetClock(Stat:Logical);
     virtual;
     {== nastav signal CLOCK dle Stat ==}

     function GetData:boolean;
     virtual;
     {== precte stav datoveho vstupu ==}

               end; {object}

type PGM_LPT_p=^PGM_LPT;

type PGM_ALL = object(PGM)
     {-- Objekt ovladani programatoru ALL03 --}

     _ProgAdr : word;

     constructor Init(Port:word);
     {== inicializuje, vstupem je cislo portu ==}

     procedure SetVcc(Voltage:real);
     virtual;
     {== nastav napajeni ==}

     procedure SetVpp(Voltage:real);
     virtual;
     {== nastav programovaci napeti ==}

     procedure SetReset(Stat:Logical);
     virtual;
     {== nastav signal RESET dle Stat ==}

     procedure SetData(Stat:Logical);
     virtual;
     {== nastav signal DATA dle Stat ==}

     procedure SetClock(Stat:Logical);
     virtual;
     {== nastav signal CLOCK dle Stat ==}

     function GetData:boolean;
     virtual;
     {== precte stav datoveho vstupu ==}

               end; {object}

type PGM_ALL_p=^PGM_ALL;

implementation

function num2str(w:word):string;
{== Prevede cislo na retezec ( jako HEX cislo ) ===}
const prevod:array[0..15]of char=('0','1','2','3','4','5','6','7',
                                  '8','9','A','B','C','D','E','F');
var s:string;
begin s[0]:=#4;
      s[1]:=prevod[(w shr 12) and $F];
      s[2]:=prevod[(w shr  8) and $F];
      s[3]:=prevod[(w shr  4) and $F];
      s[4]:=prevod[(w shr  0) and $F];
      if s[1]='0' then s:=copy(s,2,255);
      if s[1]='0' then s:=copy(s,2,255);
      if s[1]='0' then s:=copy(s,2,255);
      num2str:=s;
end; {num2str}

{========================================================}
{                                                        }
{ Programator prazdny prototyp                           }
{                                                   miho }
{========================================================}

constructor PGM.Init(Port:word);
{== inicializuje a zapamatuje adresu ==}
begin _PortAdr:=0;
end; {Init}

procedure PGM.Error(S:string);
{== vypise chybu ==}
begin _Error:=s;
end; {Error}

procedure PGM.Info(S:string);
{== vypise info ==}
begin writeln('INFO: ',S);
end; {Error}

procedure PGM.SetVcc(Voltage:real);
{== nastav napajeni ==}
begin
end; {SetVcc}

procedure PGM.SetVpp(Voltage:real);
{== nastav programovaci napeti ==}
begin
end; {SetVpp}

procedure PGM.SetReset(Stat:Logical);
{== nastav signal RESET dle Stat ==}
begin
end; {SetReset}

procedure PGM.SetData(Stat:Logical);
{== nastav signal DATA dle Stat ==}
begin
end; {SetData}

procedure PGM.SetClock(Stat:Logical);
{== nastav signal CLOCK dle Stat ==}
begin
end; {SetClock}

function PGM.GetData:boolean;
{== precte stav datoveho vstupu ==}
begin
end; {GetData}

{========================================================}
{                                                        }
{ Programator via printer port                           }
{                                                   miho }
{========================================================}

const LPT_DATA    = $01;   { Datovy vystup - RB7  }
      LPT_DATAOE  = $02;   { Povoleni vystupu     }
      LPT_CLOCK   = $04;   { Hodiny - RB6         }
      LPT_CLOCKOE = $08;   { Povoleni vystupu     }
      LPT_VCC     = $10;   { Zapnuti +5V          }
      LPT_VPP     = $20;   { Zapnuti +12V na MCLR }
      LPT_RES     = $40;   { Pripojeni 0V na MCLR }

      LPT_DATAIN  = $40;   { Maska bitu pro cteni dat }


constructor PGM_LPT.Init(Port:word);
var AdrTab:array[1..3]of word absolute 0:$408;{ tabulka LPT1..LPT3 z BIOSu }
{== inicializuje a zapamatuje adresu ==}
var w:word;
begin _PortAdr:=0;
      _Error:='';
      _PortStat:=0;
      if (port<1) or (port>3) then Error('Invalid Port Number')
                              else _PortAdr:=AdrTab[Port];
      if _PortAdr=0 then Error('Port not Registered in BIOS');
      Info('Port Address '+num2str(_PortAdr)+'H');
      if _Error<>'' then fail;
      if _PortAdr<>0 then system.port[_PortAdr]:=_PortStat;
end; {Init}

procedure PGM_LPT.SetVcc(Voltage:real);
{== nastav napajeni ==}
begin if Voltage = 5.0 then _PortStat:=_PortStat or LPT_VCC
                       else _PortStat:=_PortStat and not LPT_VCC;
      if _PortAdr<>0 then port[_PortAdr]:=_PortStat;
      xDelayMicro(1);
end; {SetVcc}

procedure PGM_LPT.SetVpp(Voltage:real);
{== nastav programovaci napeti ==}
begin if Voltage=13.0
      then _PortStat:= LPT_VPP or ( _PortStat and not LPT_RES )
      else _PortStat:= _PortStat and not LPT_VPP;
      if _PortAdr<>0 then port[_PortAdr]:=_PortStat;
      xDelayMicro(1);
end; {SetVpp}

procedure PGM_LPT.SetReset(Stat:Logical);
{== nastav signal RESET dle Stat ==}
begin case Stat of
      zero : begin SetVpp(0);
                   _PortStat:=_PortStat or LPT_RES;
             end;
      one  : _PortStat:=_PortStat and not LPT_RES;
      end; {case}
      if _PortAdr<>0 then port[_PortAdr]:=_PortStat;
      xDelayMicro(1);
end; {SetReset}

procedure PGM_LPT.SetData(Stat:Logical);
{== nastav signal DATA dle Stat ==}
begin case Stat of
      zero     : _PortStat := ( _PortStat and not LPT_DATA ) or LPT_DATAOE;
      one      : _PortStat := _PortStat or LPT_DATA or LPT_DATAOE;
      tristate : _PortStat := ( _PortStat and not LPT_DATAOE and not LPT_DATA )
      end; {case}
      if _PortAdr<>0 then port[_PortAdr]:=_PortStat;
      xDelayMicro(1);
end; {SetData}

procedure PGM_LPT.SetClock(Stat:Logical);
{== nastav signal CLOCK dle Stat ==}
begin case Stat of
      zero     : _PortStat := ( _PortStat and not LPT_CLOCK ) or LPT_CLOCKOE;
      one      : _PortStat := _PortStat or LPT_CLOCK or LPT_CLOCKOE;
      tristate : _PortStat := ( _PortStat and not LPT_CLOCKOE and not LPT_CLOCK )
      end; {case}
      if _PortAdr<>0 then port[_PortAdr]:=_PortStat;
      xDelayMicro(1);
end; {SetClock}

function PGM_LPT.GetData:boolean;
{== precte stav datoveho vstupu ==}
begin GetData:=(port[_PortAdr+1] and LPT_DATAIN) = LPT_DATAIN;
      xDelayMicro(1);
end; {GetData}


{========================================================}
{                                                        }
{ Programator ALL03                                      }
{                                                   pefi }
{========================================================}

{ Tato cast v podstate jen vola funkce jednotky ProgAll  }

const ALL_VCC   =       30;
      ALL_GND   =       11;
      ALL_VPP   =       10;
      ALL_CLOCK =       28;
      ALL_DATA  =       29;

Constructor PGM_All.Init(Port:Word);
{== provede inicializaci programatoru ==}
begin
  Initialize(Port);
  Gnd11(true); { pripoji zem na vyvodu 11 }
end;{End Init}

procedure PGM_All.SetVcc(Voltage:real);
{== zapina a vypina napajeni ==}
begin
  SetVoltageV1(Voltage);
  if Voltage=0 then ConnectV1(ALL_VCC,false)
               else ConnectV1(ALL_VCC,true);
  xDelayMicro(1);
end;{End SetVcc}

procedure PGM_All.SetVpp(Voltage:real);
{== zapina a vypina programovaci napeti ==}
begin
  SetVoltageV2(Voltage);
  if Voltage=0 then ConnectV2(ALL_VPP,false)
               else ConnectV2(ALL_VPP,true);
  xDelayMicro(1);
end;{EndSetVpp}

procedure PGM_All.SetReset(Stat:Logical);
{== nastavi nebo shodi signal Reset-VPP ==}
begin
  ConnectV2(ALL_VPP,false);{nejdrive nutno Vpp odpojit}
  if Stat = zero then SetBit(ALL_VPP,0)
                 else SetBit(ALL_VPP,1);
  xDelayMicro(1);
end;{EndSetReset}

procedure PGM_All.SetData(Stat:Logical);
{== nastavi nebo shodi signal DATA ==}
begin
  if Stat = zero then SetBit(ALL_DATA,0)
                 else SetBit(ALL_DATA,1);
  xDelayMicro(1);
end;{End SetData}

procedure PGM_All.SetClock(Stat:Logical);
{== nastavi nebo shodi signal CLK ==}
begin
  if Stat = zero then SetBit(ALL_CLOCK,0)
                 else SetBit(ALL_CLOCK,1);
  xDelayMicro(1);
end;{End SetClock}

function PGM_All.GetData:boolean;
var
  stav:byte;
begin
  Stav:=GetBit(ALL_DATA);
  if Stav=1 then GetData:=true
            else GetData:=false;
  xDelayMicro(1);
end;{End GetData}

end.