dsk-disp.cc

//*************************************************************************
//  MODULE : Disk Animation animator for the RCOS O/S simulator           *
//  AUTHOR : Ron Chernich                                                 *
//  PURPOSE: Routines to graphically emulate disk spin, head positioning, *
//           data transfer and queued request status for the disk system. *
//  HISTORY:                                                              *
//   23-AUG-94  First Simple implementation.                              *
//*************************************************************************

#include "dsk-disp.hh"

extern UINT16 nWinFgColor[];
extern UINT16 nWinBgColor[];


///////////////////////////////////////////////////////////////////////////
// Fix heads at track 00 and calculate platter centre location and radius..
//
DiskAnim::DiskAnim (UINT16 nId, UINT16 nTmax) :
  nLid(nId), nTracks(nTmax)
{
  nDiskRad = nTracks + (INDEX_RAD * 5) + HUB_RAD;
  PtSpinPos.x = (X_MARGIN+nDiskRad) + (nLid*X_MARGIN) + (nLid*nDiskRad*2);
  PtSpinPos.y = SYS_Height + 5 + nDiskRad;
  PtIndexPos.x = PtSpinPos.x;
  PtIndexPos.y = PtSpinPos.y - (HUB_RAD + (2 * INDEX_RAD));
  nHeadPosY = PtSpinPos.y + nDiskRad - INDEX_RAD - HEAD_Y;
}

//////////////////
// Re-draw the complete disk unit - platter, heads and transfer queue.
//
void DiskAnim::Paint (void)
{
  INT16 n = (INT16)DSK_DISP;
  Mickey.AutoPointer(PtSpinPos.x - nDiskRad, PtSpinPos.y - nDiskRad,
                     PtSpinPos.x + nDiskRad, PtSpinPos.y + nDiskRad);
  GfxCircle(PtSpinPos.x, PtSpinPos.y, nDiskRad, GFX_Fill, PLATTER_COLOR);
  GfxCircle(PtSpinPos.x, PtSpinPos.y, nDiskRad, GFX_Frame, TQ_BDR);
  GfxPattern(GFX_HalfTone);
  GfxTextColorBg(nWinBgColor[n]);
  GfxCircle(PtSpinPos.x, PtSpinPos.y, HUB_RAD, GFX_Fill, nWinFgColor[n]);
  GfxCircle(PtSpinPos.x, PtSpinPos.y, HUB_RAD, GFX_Frame, TQ_BDR);
  GfxPattern(GFX_Solid);
  GfxCircle(PtIndexPos.x, PtIndexPos.y, INDEX_RAD, GFX_Fill,
    (PtIndexPos.x - PtSpinPos.x) ? IDX_NORM_COLOR : IDX_SENSE_COLOR);
  GfxCircle(PtIndexPos.x, PtIndexPos.y, INDEX_RAD, GFX_Frame, TQ_BDR);
  Mickey.ShowPointer();
  DiskSeek(0);
  PaintTQ();
}

//////////////////
// simulate head movement of  tracks.  If  is zero,
// we are probably doing a display refresh, so don't bother to erase
// the old position, just re-draw.
//
void DiskAnim::DiskSeek (INT16 nDelta)
{
  Mickey.AutoPointer(PtSpinPos.x + HEAD_X, PtSpinPos.y + HUB_RAD,
                     PtSpinPos.y + HEAD_X, PtSpinPos.y + nDiskRad + TQ_GAP);
  point p1(PtSpinPos.x - (HEAD_X / 2), nHeadPosY);
  point p2(PtSpinPos.x + (HEAD_X / 2), nHeadPosY + HEAD_Y);
  if (nDelta) {
    GfxRect(p1.x, p1.y, p2.x, p2.y, GFX_Fill, PLATTER_COLOR);
    nHeadPosY -= nDelta;
    p1.y -= nDelta;
    p2.y -= nDelta;
  }
  GfxRect(p1.x, p1.y, p2.x, p2.y, GFX_Fill, HEAD_COLOR);
  GfxRect(p1.x, p1.y, p2.x, p2.y, GFX_Frame, TQ_BDR);
  UINT16 x = PtSpinPos.x - (ARM_X / 2);
  UINT16 y = PtSpinPos.y + nDiskRad + TQ_GAP;
  for (int i = 0; i < ARM_X; i++, x++) {
    GfxTextColor((i && (i < ARM_X-1)) ? HEAD_COLOR : TQ_BDR);
    GfxMoveTo(x, p2.y);
    GfxLineTo(x, y);
  }
  Mickey.ShowPointer();
}

///////////////////
// The passed value  is the current angle (in degrees) of
// the index hole relative to the index sensor (at zero degrees).
// erase the old index hole, calculate and store the new position,
// then redraw. If it happens to be near the sensor LED, hilight it.
//
void DiskAnim::DiskSpin (UINT16 nTheta)
{
  INT16 nBound = HUB_RAD + (4 * INDEX_RAD);
  INT16 nArc = nBound - (2 * INDEX_RAD);
  Mickey.AutoPointer(PtSpinPos.x - nBound, PtSpinPos.y - nBound,
                     PtSpinPos.x + nBound, PtSpinPos.y + nBound);
  GfxCircle(PtIndexPos.x, PtIndexPos.y, INDEX_RAD, GFX_Fill, PLATTER_COLOR);
  INT16 dx = PtSpinPos.x - (INT16)(cos(nTheta) * nArc);
  INT16 dy = PtSpinPos.y + (INT16)(sin(nTheta) * nArc);
  BOOL bSense = 
    ((abs(dx-PtSpinPos.x) <= INDEX_RAD*2) && (dy < PtSpinPos.y)) ?
    TRUE : FALSE;
  GfxCircle(dx, dy, INDEX_RAD, GFX_Fill,
    (bSense) ? IDX_SENSE_COLOR : IDX_NORM_COLOR);
  GfxCircle(dx, dy, INDEX_RAD, GFX_Frame, TQ_BDR);
  PtIndexPos.x = dx;
  PtIndexPos.y = dy;
  Mickey.ShowPointer();
}

////////////////////
// draw the full transfer queue box..
//
void DiskAnim::PaintTQ (void)
{ 
  char  st[32];
  INT16 i, x, y;
  UINT16 k = (TQ_WIDTH / 2);
  point p1(PtSpinPos);
  p1.x -= k;
  p1.y += (nDiskRad + TQ_GAP);
  point p2(p1);
  p2.x += TQ_WIDTH;
  p2.y += TQ_HEIGHT;
  static char *szHdr[TQ_COLS] = { "PID", "Opr", "Trk", "Sec", "Hd" };

  Mickey.AutoPointer(p1.x, p1.y, p2.x, p2.y);
  GfxSetClip(p1.x, p1.y, p2.x, p2.y);
  GfxRect(p1.x, p1.y, p2.x, p2.y, GFX_Fill, TQ_BG_COLOR);
  GfxRect(p1.x, p1.y, p2.x, p1.y+TQ_CELL_Y, GFX_Fill, TQ_HDR_COLOR);
  GfxRect(p1.x, p1.y, p2.x, p2.y, GFX_Frame, TQ_BDR);
  GfxMoveTo(CPROC_X2, CPROC_Y), GfxLineTo(CPROC_X2, CPROC_Y+CPROC_DY);
  for (i = 0, x = p1.x+4; i < TQ_COLS; i++, x += TQ_CELL_X) {
    GfxTextColor(SLOT_TXT);
    GfxText(x, p1.y+((SLOT_DY-GfxTextHeight())/2), szHdr[i], GFX_Transparent);
    GfxTextColor(TQ_BDR);
    GfxMoveTo(x-4, p1.y), GfxLineTo(x-4, p2.y);
  }
  for (i = 0, y = p1.y; i < TQ_ROWS; i++, y += TQ_CELL_Y)
    GfxMoveTo(p1.x, y), GfxLineTo(p2.x, y);
  GfxClrClip();
  sprintf(st, "Unit %c:", 'A'+nLid);
  GfxTextColor(TQ_TXT_COLOR);
  p2.x = PtSpinPos.x - (GfxTextExtent(st) / 2);
  p2.y += (GfxTextHeight() / 2);
  GfxText(p2.x, p2.y, st, GFX_Transparent);
  Mickey.ShowPointer();
}

//////////////////
// If the passed pointer is null
//
void DiskAnim::RefreshTQ (TransQ *pT, INT16 nStart)
{
  char  st[32];
  point p1(PtSpinPos);
  p1.x -= (TQ_WIDTH / 2);
  p1.y += nDiskRad + TQ_GAP + TQ_CELL_Y;

  Mickey.AutoPointer(p1.x, p1.y, p1.x+TQ_WIDTH, p1.y+TQ_HEIGHT);
  GfxTextColor(TQ_TXT_COLOR);
  for (UINT16 idx = nStart; idx < TQ_ROWS-1; idx++) {
    GfxSetClip(p1.x+1, p1.y+1, p1.x+TQ_WIDTH-2, p1.y+TQ_CELL_Y-2);
    point p2(p1);
    p2.x++, p2.y++;
    point p3(p1);
    p3.x += TQ_CELL_X - 1;
    p3.y += TQ_CELL_Y - 1;
    pT->Peek(idx);
    for (INT16 jdx = 0; jdx < TQ_COLS; jdx++) {
      GfxRect(p2.x, p2.y, p3.x, p3.y, GFX_Fill, TQ_BG_COLOR);
      if (idx < pT->GetLen()) {
        GfxTextColor(TQ_TXT_COLOR);
        switch (jdx) {
          case 0 : 
            if (MAX_PROC <= pT->GetPid())
               strcpy(st, "Sys");
            else
               sprintf(st, "P%X",  pT->GetPid());
            break;
          case 2 : sprintf(st, "%02d", pT->GetTrk()); break;
          case 3 : sprintf(st, "%02d", pT->GetSec()); break;
          case 4 : sprintf(st, "%02d", pT->GetSid()); break;
          case 1 :
            sprintf(st, "  %c", (pT->IsRead() ? 'R' : 'W'));
            GfxTextColor(pT->IsRead() ? READ_COLOR : WRITE_COLOR); 
            break;
        }
        GfxText(p2.x+4, p1.y+((SLOT_DY-GfxTextHeight())/2), st, GFX_Transparent);
      }
      p2.x += TQ_CELL_X, p3.x += TQ_CELL_X;
    }
    GfxClrClip();
    p1.y += TQ_CELL_Y;
  }
  Mickey.ShowPointer();
}


/********************************** eof **********************************/