program Lisa_Linie_web;

{ $BOOTRST $00C00}         {Reset Jump to $00C00}
{$NOSHADOW}
{ $W+ Warnings}            {Warnings off}

Device = mega8, VCC = 5;

Import SysTick, PWMport1A, PWMport1B, ADCPort, LCDmultiPort,  TWImaster;

From System Import  LongInt, PIDs;

Define
  ProcClock      = 16000000;        {Hertz}
  SysTick        = 10;             {msec}
  StackSize      = $0064, iData;
  FrameSize      = $0064, iData;
  ADCchans       = 2, iData;
  ADCpresc       = 8;
  PWMres1        = 8;              {bits}
  PWMpresc1      = 64;
  TWIpresc       = TWI_BR400;
  LCDmultiPort   = I2C_TWI;
  LCDrows_M      = 4;             {rows}
  LCDcolumns_M   = 20;             {columns per line}
  LCDtype_M      = 0073;

Implementation

{$IDATA}

{--------------------------------------------------------------}
{ Type Declarations }

type


{--------------------------------------------------------------}
{ Const Declarations }


{--------------------------------------------------------------}
{ Var Declarations }
{$EEPROM}
var
  Pwert          : integer;
  Iwert          : integer;
  Dwert          : integer;
  Swert          : integer;
  abwert         : byte;
  spwert         : word;
{$IDATA}
var
  Pid1           : PIDcontrol[500, 2];
  P              : integer;
  I              : integer;
  D              : integer;
  s              : integer;
  ADC1           : word;
  tempw          : word;
  temp           : byte;
  dividlimit     : word;
  PWM_2[@tempw]  : byte;
  Stelle         : word;
  Sensor         : byte;
  gleich         : byte;
  a              : byte;
  b              : byte;
  c              : byte;
  ramp           : word;
  temps          : word;
  e              : byte;
  f              : byte;
  Linie          : byte;
  Taste1[@PinC, 3]     : bit;
  Hilfsvariable  : byte;
  Gleichbit[@Hilfsvariable, 2]: bit;
  Flag[@Hilfsvariable, 3]    : bit;
  liniewarda[@Hilfsvariable, 4]: bit;
  zaehler        : byte;
  divid          : word;
  PosX           : integer;
  liniealt       : byte;
  MRX[@PortB, 4] : bit;                        //Motor 1
  MRY[@PortB, 5] : bit;                        //Motor 1
  MLX[@PortC, 0] : bit;                        //Motor 2
  MLY[@PortB, 0] : bit;                        //Motor 2
  Taster         : byte;
  links          : word;
  links8[@links] : byte;
  rechts         : word;
  r              : integer;
  l              : integer;
  rechts8[@rechts]     : byte;
  speed          : word;
  bla            : byte;
  ble            : byte;
  abzw           : byte;
  ab             : byte;
  zweigzeit      : word;
  her            : word;


{--------------------------------------------------------------}
{ functions }
procedure InitPorts;
begin
  PortB:= %00000000;
  DDRB:=  %00111111;
  DDRC:= %00000001;
  PortC:= %00001000;
  PortD:= %11111111;
end InitPorts;


procedure Init_I2C;
begin
  LCDsetup_M(LCD_m1);
  LCDcursor_M(LCD_m1, false, false);
end Init_I2C;


procedure md;
begin
  mdelay(100);
end md;

procedure leerlcd;
begin
  write(LCDout_m, ' ');
end leerlcd;


procedure Startbild;
begin
  LCDclr_m(LCD_m1);
  md;
  write(LCDout_m, 'T ' + #31 + ' 26R' + #31 + ' ' + #31 + #31 + #31 + #31 + '  ' + #31 + #31 + '  I');
  md;
  write(LCDout_m, 'E ' + #31 + '    ' + #31 + ' ' + #31 + '    ' + #31 + '  ' + #31 + ' W');
  md;
  write(LCDout_m, 'A ' + #31 + '    ' + #31 + '    ' + #31 + ' ' + #31 + #31 + #31 + #31 + ' A');
  md;
  write(LCDout_m, 'M ' + #31 + #31 + #31 + #31 + ' ' + #31 +  ' ' + #31 + #31 + #31 + #31 + ' ' + #31 + '  ' + #31 + ' N');
  md;
  md;
  md;
  LCDxy_m(LCD_m1, 4, 0);
  leerlcd;
  leerlcd;
  leerlcd;
end Startbild;


procedure Spannungsanzeige;
begin
  ADC1:= GetAdc(2);
  if ADC1 > 129 then
    tempw := adc1 - 129;
    tempw := tempw * 622;
    tempw := tempw div 100;
  else
    tempw := 0;
  endif;
  if ADC1 > 170 then
    tempw := 255;
    dividlimit := 13;
  endif;
  if ADC1 < 130 then
    Stelle := Stelle + 1;
    dividlimit := 10;
    if Stelle > 9000 then
      stelle := 0;
    endif;
    if stelle < 5500 then
      tempw := 0;
    else
      tempw := 255;
    endif;
  endif;
  ocr2 := PWM_2;
end Spannungsanzeige;


procedure Debug;
begin
  LCDxy_m(LCD_m1, 0, 0);
  write(LCDout_m, 'Sn:');
  LCDxy_m(LCD_m1, 3, 0);

  if sensor < 100 then
    leerlcd;
  endif;

  if sensor < 10 then
    leerlcd;
  endif;

  write(LCDout_m, bytetostr(sensor));
  LCDxy_m(LCD_m1, 7, 0);
  write(LCDout_m, 'PX:');
  LCDxy_m(LCD_m1, 10, 0);
  if abs(posx) < 100 then
    leerlcd;
  endif;
  if abs(posx) < 10 then
    leerlcd;
  endif;
  if posx > - 1 then
    leerlcd;
  endif;
  write(LCDout_m, inttostr(PosX));
  LCDxy_m(LCD_m1, 15, 0);
  write(LCDout_m, 'L:');

  LCDxy_m(LCD_m1, 17, 0);
  if linie < 10 then
    leerlcd;
  endif;
  write(LCDout_m, bytetostr(linie));
  LCDxy_m(LCD_m1, 0, 1);
  write(LCDout_m, 'P: ' + inttostr(P) + ' ');
  LCDxy_m(LCD_m1, 7, 1);
  write(LCDout_m, 'I: ' + inttostr(I) + ' ');
  LCDxy_m(LCD_m1, 14, 1);
  write(LCDout_m, 'D: ' + inttostr(D) + ' ');
  LCDxy_m(LCD_m1, 0, 2);
  write(LCDout_m, 'S: ' + inttostr(S) + ' ');
  LCDxy_m(LCD_m1, 6, 2);
  write(LCDout_m, 'Li' + f );

  if links < 100 then
    leerlcd;
  endif;

  if links < 10 then
    leerlcd;
  endif;

  write(LCDout_m, inttostr(links));
  LCDxy_m(LCD_m1, 13, 2);
  write(LCDout_m, 'Re' + e );

  if rechts < 100 then
    leerlcd;
  endif;

  if rechts < 10 then
    leerlcd;
  endif;

  write(LCDout_m, inttostr(rechts));

  LCDxy_m(LCD_m1, 0, 3);
  write(LCDout_m, 'A' + bytetostr(abzw) ); // + 'G' + bytetostr(gleich));
  LCDxy_m(LCD_m1, 3, 3);
  write(LCDout_m, 'M' );
end Debug;


procedure vorre;
begin
  MRX := 0;
  MRY := 1;
  e:= 26;
end vorre;


procedure ruere;
begin
  MRX := 1;
  MRY := 0;
  e:= 27;
end ruere;


procedure vorli;
begin
  MLX := 1;
  MLY := 0;
  f:= 26;
end vorli;


procedure rueli;
begin
  MLX := 0;
  MLY := 1;
  f:= 27;
end rueli;


procedure stopli;
begin
  MLX := 1;
  MLY := 1;
end stopli;


procedure stopre;
begin
  MRX := 1;
  MRY := 1;
end stopre;


procedure I2CTaster;
begin
  Taster := LCDportInp_M(LCD_m1);
end I2CTaster;


procedure menu;
begin
  LCDxy_m(LCD_m1, 6, 3);
  write(LCDout_m, 'P+ P- I+ I-  1');

  if (Taster and %00010000) = 0 then
    P := P + 1;
  elsif (Taster and %00100000) = 0 then
    P := P - 1;
  elsif  (Taster and %01000000) = 0 then
    I := I + 1;
  elsif  (Taster and %10000000) = 0 then
    I := I - 1;
  endif;
end menu;


procedure menu1;
begin
  LCDxy_m(LCD_m1, 6, 3);
  write(LCDout_m, 'D+ D- S+ S-  2');
  if (Taster and %00010000) = 0 then
    D := D + 1;
  elsif (Taster and %00100000) = 0 then
    D := D - 1;
  elsif  (Taster and %01000000) = 0 then
    S := S + 1;
  elsif  (Taster and %10000000) = 0 then
    S := S - 1;
  endif;
end menu1;


procedure menu2;
begin
  LCDxy_m(LCD_m1, 6, 3);
  write(LCDout_m, 'V+ V-');
  LCDxy_m(LCD_m1, 12, 3);
  write(LCDout_m, inttostr(temps) + ' ');
  LCDxy_m(LCD_m1, 19, 3);
  write(LCDout_m, '3');
  if (Taster and %00010000) = 0 then
    temps := temps + 1;
  elsif (Taster and %00100000) = 0 then
    temps := temps - 1;
  endif;
end menu2;


procedure menu3;
begin
  LCDxy_m(LCD_m1, 6, 3);
  write(LCDout_m, 'A+ A- ab:' + bytetostr(ab) + ' ');
  LCDxy_m(LCD_m1, 19, 3);
  write(LCDout_m, '4');
  if (Taster and %00010000) = 0 then
    ab := ab + 1;
  elsif (Taster and %00100000) = 0 then
    ab := ab - 1;
  endif;
end menu3;


procedure menu4;
begin
  LCDxy_m(LCD_m1, 2, 3);
  write(LCDout_m, ' M  Speich.?  Ja 5');
  if (Taster and %10000000) = 0 then
    Pwert := P;
    Iwert := I;
    Dwert := D;
    Swert := S;
    abwert := ab;
    spwert := temps;
  endif;
end menu4;

//------------------------------------------------- LINIE ----------------------

procedure linielesen;
begin
  linie := 0;
  liniewarda := 0;
  zaehler:= 0;
  Sensor := PinD;
  b := 1;
  gleich := 0;
  Gleichbit := sensor And 1;

  For a:= 0 to 7 do     // Sensor umrechnen in einen Wert für Linie zw. 10 und 80
    If (Sensor and b) = 0 then

      If Gleichbit = false then
      else
        Gleichbit := 0;
        Gleich := gleich + 1;
      endif;
    else
      If Gleichbit = false then

        Gleichbit := 1;
        gleich := gleich + 1;
      endif;
      c := a + 1;
      c := c *5;
      linie := linie + c;
      zaehler := zaehler + 1;
    endif;
    b := b * 2;
  EndFor;
end linielesen;


procedure liniechecken;
begin
  if (sensor and 1) = 0  then
    if gleich > 2 then
      b := 1;
      gleich := 0;
      Gleichbit := sensor And 1;

      For a:= 0 to 7 do     // Sensor umrechnen in einen Wert für Linie zw. 10 und 80
        If (Sensor and b) = 0 then

          If Gleichbit = false then
          else
            Gleichbit := 0;
            Gleich := gleich + 1;

            if liniewarda = false then
            else
              a := 7;
            endif;

          endif;

        else
          // Sensorbit = 1 (Linie da)
          liniewarda := 1;
          If Gleichbit = false then
            Gleichbit := 1;
            gleich := gleich + 1;
          endif;
          c := a + 1;
          c := c *5;
          linie := linie + c;
          zaehler := zaehler + 1;
        endif;
        b := b * 2;
      EndFor;
    endif;
  else
    if gleich > 1 then
      abzw := abzw + 1;
    endif;
  endif;
end liniechecken;

{---------------------------------- { Main Program } ----------------------------}
{ Main Program }
{$IDATA}

begin
  initports;
  P := Pwert;
  I := Iwert;
  D := Dwert;
  S := Swert;
  ab := abwert;
  Pid1.pFactor:= P;
  Pid1.iFactor := I;
  Pid1.dFactor:= D;
  Pid1.sFactor:= S;
  Pid1.Nominal:= 0;
  init_i2c;
  TCCR2 := %01110010;
  EnableInts;
  Startbild;
  md;
  repeat
    Spannungsanzeige;
    md;
  until not Taste1;
  md;
  //pid.nominal := 45;
  temps:= spwert;
  vorre;
  vorli;
  ramp := 1000;

  loop

    if ramp > 0 then
      speed := 100;
      ramp := ramp - 1;
    else
      if not flag then
        speed := temps;
      endif;
    endif;

    Pid1.pFactor:= P;
    Pid1.iFactor := I;
    Pid1.dFactor:= D;
    Pid1.sFactor:= S;
    linielesen;
    liniechecken;
    if zaehler = 0 then

      if her > 10 then        // her wenn linie nicht mehr da

        If Liniealt > 34 then
          linie := 70;
          rueli;
          vorre;
        else
          linie := 0;
          vorli;
          ruere;
        endif;

      else

        vorre;
        rueli;
      endif;
      links := 255;
      rechts := 255;

    else

      If abzw > ab then
        repeat
          vorli;
          vorre;

          if not flag then
            PWMport1A:= 250; //links;
            PWMport1B:= 100; //rechts;
          endif;

          Sensor := PinD;
          ocr2 := 0;

        until (sensor and 128) = 0;

        repeat
          ruere;
          vorli;
          linielesen;
          bla := 0;
          if (sensor and 1) = 1 then
            if gleich = 1 then
              bla := 128;
            endif;
          endif;
          ocr2 := 255;
        until bla = 128;

        abzw := 0;
        her := 0;

      else
        her := her + 1;

        Linie := Linie div zaehler;
        Linie := Linie *2;
        Liniealt := Linie;
        linie := linie - 10;
// ----------- P I D berechnen lassen ----------
        Pid1.Actual:= integer(linie) - 35;
        PosX:= Pid1.Execute; // wenn Posx minus dann nach links
        l := integer(speed) + integer(posx);

        if l < 0 then
          rueli;
          links := word(abs(l));
        else
          vorli;
          links := word(l);
        endif;

        r := integer(speed) - integer(posx);

        if r < 0 then
          ruere;
          rechts := word(abs(r));
        else
          vorre;
          rechts := word(r);
        endif;

        if rechts > 255 then
          rechts := 255;
        endif;
        if links > 255 then
          links := 255;
        endif;

      endif;

    endif;

    ///----------------

    If flag then
      debug;
      I2CTaster;
      PWMport1A:= 0;
      PWMport1B:= 0;

      if (Taster and %00001000) = 0 then
        ble := ble + 1;
        md;
        md;
        LCDclr_m(LCD_m1);
      endif;

      case ble of
        0 : menu;
          |
        1 : menu1;
          |
        2 : menu2;
          |
        3 : menu3;
          |
        4 : menu4;
          |
      else
        ble := 0;
      endcase;

    else
      PWMport1A:= links;
      PWMport1B:= rechts;
    endif;

    Spannungsanzeige;

    if not taste1 then
      md;
      md;
      toggle(flag);

      if flag then
        LCDclr_m(LCD_m1);
      else
        ramp:= 1000;
      endif;

    endif;

  endloop;

end Lisa_Linie_web.


