program Graph61202;

{$NOSHADOW}
{ $W+ Warnings}            {Warnings off}

Device = mega644, VCC = 5;
{ $BOOTRST $01E00}         {Reset Jump to $01E00}

Import SysTick, SerPort, LCDGraphic;

From System Import Float;
From LCDGraphic Import CharSet;     {block CharSet, pixels}

Define
  ProcClock      = 16000000;        {Hertz}
  SysTick        = 10;              {msec}
  StackSize      = $0040, iData;
  FrameSize      = $0080, iData;
  SerPort        = 38400, Stop2;     {Baud, StopBits|Parity}
  RxBuffer       = 8, iData;
  TxBuffer       = 8, iData;
  LCDGraphic     = 128, 64, 8;      {x-pix, y-pix, accesswidth}
  // use the Column mode controller 61202 with 2 cipselects
  LCDgraphMode   = column, iData;   // linear
  DefCharSet     = 'Graphchars.pchr';  {FileName}
  GViewports     = 1, iData;        {logical ViewPorts, scalings}
  TGraphStr      = 16;              {Graphic Text String Length}

Implementation

{$IDATA}

{--------------------------------------------------------------}
{ Type Declarations }

type


{--------------------------------------------------------------}
const
  mybitmap       : array[1..(32*32 div 8) + 2] of byte = 'herz.pbmp';

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
  LCD_DatRD[@PINC]        : byte;
  LCD_DatWR[@PORTC]       : byte;
  LCD_DDR[@DDRC]          : byte;
  LCD_EN[@PORTA, 0]       : Bit;                  {Enabled line}
  LCD_RW[@PORTA, 1]       : Bit;                  {R/W line}
  LCD_DI[@PORTA, 2]       : Bit;                  {D/I line}
  LCD_CS1[@PORTA, 3]      : Bit;                  {LCD_CS1 line}
  LCD_CS2[@PORTA, 4]      : Bit;                  {LCD_CS2 line}
  LCD_RST[@PORTA, 5]      : Bit;                  {LCD_CS2 line}
  LCD_busy[@LCD_DatRD, 7] : Bit;                  {busy bit}
  i                       : integer;
  col                     : Byte;                 {column counter}
  CurRow                  : Byte;                 {storage for 2. controller}
{--------------------------------------------------------------}
  ParamStr:string[40]; // auch für Display
  Param:Float;
  aInt:Integer;
  BarScale1,BarScale2,NeedleScale:Float;
{--------------------------------------------------------------}
{ functions }
Procedure InitPorts;
begin
  LCD_DDR:= 0;                             // all input
  DDRA:= $3F;
  PORTA:= $FF;
  LCD_RST:=false;
  mdelay(100);
  LCD_RST:=true;
  mdelay(100);
end;

Procedure LCDbusy;
var busy : boolean;
begin
{$D-}
  LCD_DI:= false;
  LCD_DDR:= 0;                             // all input
  LCD_RW:= true;
  LCD_EN:= true;
  NOP;
  NOP;
  Repeat
    // enable hightime > 450nsec
    busy:= LCD_busy;
  until not busy;
  LCD_EN:= false;
{$D+}
end;

Procedure WriteLCD( b : Byte; code : Boolean);
begin
{$D-}
  LCDbusy;
  LCD_DI:= code;
  LCD_RW:= false;
  LCD_DDR:= $FF;                           // all output
  LCD_DatWR := b;
  LCD_EN:= true;
  // enable hightime > 450nsec
  NOP;
  NOP;
  NOP;
  LCD_EN:= false;
{$D+}
end;

Procedure GraphInit;
begin
{$D-}
  {write init values controller 2}
  LCD_CS2:= true;
  NOP;
  LCD_CS1:= false;
  LCDbusy;
  WriteLCD(%00111111, false);
  WriteLCD(%11000000, false);
  WriteLCD(%10111000, false);
  WriteLCD(%01000000, false);
  {write init values controller 1}
  LCD_CS1:= true;
  NOP;
  LCD_CS2:= false;
  LCDbusy;
  WriteLCD(%00111111, false);
  WriteLCD(%11000000, false);
  WriteLCD(%10111000, false);
  WriteLCD(%01000000, false);
  {clear display}
{$D+}
  gclrscr(0);
  gdisprefresh;
end;

{$D-}
UserDevice GraphIOS(cmd : byte; arg : byte);
begin
  (* Display Refresh with "GraphIOS" *)
  (* cmd = 0   arg = rowaddr    set rowaddr to arg *)
  (* cmd = 1   arg = pixels     write data byte    *)
  if cmd = 0 then
    // set row addr
    CurRow:= arg;
    LCD_CS1:= true;
    NOP;
    LCD_CS2:= false;
    LCDbusy;
//      uDelay(1);
    WriteLCD(%10111000 + CurRow, false);
    WriteLCD(%01000000, false);
    col:= 0;
  else
    if col = 64 then
      {if column = 64 then switch to controller 2}
      {and set start values for controller 2}
      LCD_CS2:= true;
      NOP;
      LCD_CS1:= false;
      LCDbusy;
//      uDelay(1);
      WriteLCD(%10111000 + CurRow, false);
      WriteLCD(%01000000, false);
      WriteLCD(arg, true);
      inc(col);
    else
      WriteLCD(arg, true);
      inc(col);
    endif;
  endif;
end;
{$D+}

procedure NeedleParamToStr;
var myNachkomma:byte;
begin
  myNachkomma:=4;
  if abs(Param)>=10 then
    myNachkomma:=3;
  endif;
  if abs(Param)>=100 then
    myNachkomma:=2;
  endif;
  if abs(Param)>=1000 then
    myNachkomma:=1;
  endif;
  ParamStr:=floatToStr(Param:0:myNachkomma);
end;

procedure BuildScale(legendStr:String[10]);
//Zeiger nachbilden
var angle: Integer;
  Pxe,Pye,Pxs,Pys:Integer;
begin
//Skala aufbauen
  gOpenView(1,0,0,127,63);
  gDrawRect(0, 0, 127, 63, $ff);
  gSetLineMode(wmsetPix);
  gDrawCircle(64,100,80,$ff);
  gFillCircle(64,100,54,$ff);
  gSetTextJustify(alHorCenter, alVertBottom);
  gSetTextMode(wmsetPix);
  gDrawString(63, 40, 1, 1, TxtRot0, legendStr);
  angle:=0;
  repeat
    RotatePntI(angle, -63, -63, Pxe, Pye);
    RotatePntI(angle, -54, -54, Pxs, Pys);
    Pxe:=Pxe+64;
    Pye:=Pye+100;
    Pxs:=Pxs+64;
    Pys:=Pys+100;
    gdrawline(Pxs,Pys, Pxe,Pye,$ff);
    angle:=angle+18;
  until angle>90;
  angle:=9;
  repeat
    RotatePntI(angle, -59, -59, Pxe, Pye);
    RotatePntI(angle, -54, -54, Pxs, Pys);
    Pxe:=Pxe+64;
    Pye:=Pye+100;
    Pxs:=Pxs+64;
    Pys:=Pys+100;
    gdrawline(Pxs,Pys, Pxe,Pye,$ff);
    angle:=angle+18;
  until angle>90;
end;

procedure ParamNeedle(myParam:float);
//Zeiger nachbilden
var angle: Integer;
  Pxe,Pye,Pxs,Pys:Integer;
begin
  gSetTextJustify(alHorCenter, alVertBottom);
  gSetTextMode(wmclrPix);
  gSetLineMode(wmsetPix);
//  gFillRect(38, 53, 90, 62, $ff); // Digital-Anzeige löschen
  gSetLineMode(wmxorPix);
  Param:=myParam;
  NeedleParamToStr;
  gDrawString(63, 62, 1, 1, TxtRot0, ParamStr);
  Param:=Param*NeedleScale;
  angle:=integer(Param*89)+1; // 1 = 90° = Vollausschlag
  RotatePntI(angle, -63, -63, Pxe, Pye);
  RotatePntI(angle, -40, -40, Pxs, Pys);
  Pxe:=Pxe+64;
  Pye:=Pye+100;
  Pxs:=Pxs+64;
  Pys:=Pys+100;
  gdrawline(Pxs,Pys, Pxe,Pye,$aa);
  gdisprefresh;
  gdrawline(Pxs,Pys, Pxe,Pye,$aa); // gleich wieder löschen
  gSetTextJustify(alHorLeft, alVertBottom);
end;

procedure BuildBar1(legendStr1:String[5]);
//Balkenanzeige nachbilden
var
  Px:Integer;
begin
  gSetTextJustify(alHorRight, alVertBottom);
  gDrawString(127, 46, 1, 1, TxtRot0, legendStr1);
  gSetLineMode(wmxorPix);
  gDrawRect(0, 47, 127, 63, $AA); // Bargraph
  for Px:= 11 to 120 do
    gDrawLine (Px, 48, Px, 62,$55);
    Px:=Px+12;
  endfor;
  gdisprefresh;
  gSetTextJustify(alHorLeft, alVertBottom);
end;

procedure BuildBar2(legendStr1,legendStr2:String[5]);
//Zweifach-Balkenanzeige nachbilden
var
  Px:Integer;
begin
  gSetTextJustify(alHorRight, alVertBottom);
  gDrawString(127, 26, 1, 1, TxtRot0, legendStr1);
  gDrawString(127, 52, 1, 1, TxtRot0, legendStr2);
  gSetLineMode(wmxorPix);
  gDrawRect(0, 27, 127, 37, $AA); // Bargraph
  gDrawRect(0, 53, 127, 63, $AA); // Bargraph
  for Px:= 11 to 120 do
    gDrawLine (Px, 28, Px, 36,$55);
    gDrawLine (Px, 54, Px, 62,$55);
    Px:=Px+12;
  endfor;
  gdisprefresh;
  gSetTextJustify(alHorLeft, alVertBottom);
end;

procedure ParamBar1(myParam:float);
//Balkenanzeige nachbilden
var
  blen:Integer;
begin
  Param:=myParam;
  NeedleParamToStr;
  ParamStr:=padright(ParamStr,8);
  gDrawString(0, 46, 2, 2, TxtRot0, ParamStr);
  Param:=Param*BarScale1;
  blen:=integer(Param*127); // 1 = 127 = Vollausschlag
  gSetLineMode(wmxorPix);
  gFillRect(0, 48, blen, 62, $ff); // Bargraph
  gdisprefresh;
  gFillRect(0, 48, blen, 62, $ff); // gleich wieder löschen
end;


procedure ParamBar2(myParam1,myParam2:float);
//Balkenanzeige nachbilden
var
  blen1,blen2:Integer;
begin
  gSetTextJustify(alHorLeft, alVertBottom);
  gSetTextMode(wmsetPix);
  Param:=myParam1;
  NeedleParamToStr;
  ParamStr:=padright(ParamStr,8);
  Param:=Param*BarScale1;
  gDrawString(0, 26, 2, 1, TxtRot0, ParamStr);
  blen1:=integer(Param*127); // 1 = 127 = Vollausschlag
  Param:=myParam2;
  NeedleParamToStr;
  ParamStr:=padright(ParamStr,8);
  Param:=Param*BarScale2;
  gDrawString(0, 52, 2, 1, TxtRot0, ParamStr);
  blen2:=integer(Param*127); // 1 = 127 = Vollausschlag
  gSetLineMode(wmxorPix);
  gFillRect(0, 28, blen1, 36, $ff); // Bargraph
  gFillRect(0, 54, blen2, 62, $ff); // gleich wieder löschen
  gdisprefresh;
  gFillRect(0, 28, blen1, 36, $ff); // Bargraph
  gFillRect(0, 54, blen2, 62, $ff); // gleich wieder löschen
end;
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
  InitPorts;
  EnableInts;
  GraphInit;

  gOpenView(1,0,0,127,63);
  gSetTextBkGnd(bkNormal);
  gdrawbitmap(0, 0, @mybitmap, wmsetpix);
  
  BarScale1:=0.01;
  BarScale2:=0.01;
  NeedleScale:=0.01;
  
  BuildBar1('mWh');
  for aInt:= 0 to 50 do
    ParamBar1(float(aInt));
    mdelay(30);
  endfor;
  for aInt:= 100 downto 50 do
    ParamBar1(float(aInt));
    mdelay(30);
  endfor;

  mdelay(500);
  gclrscr(0);

  BuildBar2('mAh','Volt');
  for aInt:= 0 to 50 do
    ParamBar2(float(aInt), 50-float(aInt)/2);
    mdelay(30);
  endfor;
  for aInt:= 100 downto 50 do
    ParamBar2(50-float(aInt)/2, float(aInt));
    mdelay(30);
  endfor;

  mdelay(500);

  gclrscr(0);
  gdrawbitmap(0, 0, @mybitmap, wmsetpix);

  BuildScale('Power mW');
//Zeiger bewegen
  for aInt:= 0 to 100 do
    ParamNeedle(float(aInt));
    mdelay(50);
  endfor;
  for aInt:= 100 downto 50 do
    ParamNeedle(float(aInt));
    mdelay(50);
  endfor;

end Graph61202.

