/*@@var:*/
variables
{
  const word wChannelsPerCard = 4;       // 4 measurement channels per card
  const word wCardCntMax      = 16;      // max. supported cards
  const word wRelayMsgCntMax  = 4;       // 4 cards per message
  const word wCardCanMask     = 0xFFF0;  // use 4 low bits for card addressing
  const word wMeasChannels    = 10;      // max. number of measurement channels
  const word wTimeStampRange  = 4096;    // use 12 bit time stamp
  const word wBufferSize      = 10000;   // measurement buffer size
  const word wBufferOffset    = 5000;    // start output if buffer is filled 50%
  const long lCanTimeout      = 100;     // 100ms timeout for incoming CAN messages
  const long lMeasDelay       = 100;     // 100ms delay between measurement and display
  const long lMsgCycle        = 20;      // 20ms CAN message cycle time

  const word wAddMsgBusNone  = 0;       // bus used for additional message
  const word wAddMsgBusCan   = 1;
  const word wAddMsgBusLin   = 2;

  Timer   timerMeasTick;     // 100µs tick
  msTimer timerMeasStart;    // delay between measurement and display
  msTimer timerTimeoutTick;  // timeout calculation for CAN messages
  msTimer timerMsgTimer;     // used for transmission of CAN messages

  message MsgCommon       CommonMessage;
  message MsgRelayCtrl_00 RelayMessage;
  message mDiag_Req_00    DiagReqMessage;
  message mDiag_Res_00    DiagResMessage;

  char cSwVersion[11] = "B4Al32----";

  int     nTestStart[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

  int     nMeasValue   [wMeasChannels][wBufferSize];              // input buffer: measurement values
  dword   dwTimeStamp  [wMeasChannels][wBufferSize];              // input buffer: time stamps

  word    wPtrIn       [wMeasChannels] = { 0,0,0,0,0,0,0,0,0,0 }; // write pointer for input buffer
  word    wPtrOut      [wMeasChannels] = { 0,0,0,0,0,0,0,0,0,0 }; // read pointer for input buffer
  word    wTimeStampMem[wMeasChannels] = { 0,0,0,0,0,0,0,0,0,0 }; // 12 bit time stamp of last CAN message
  dword   dwTimeOffset [wMeasChannels] = { 0,0,0,0,0,0,0,0,0,0 }; // accumulated time stamp
  float   fDispOffset  [wMeasChannels] = { 0,0,0,0,0,0,0,0,0,0 }; // for output calibration

  dword   dwMeasTick;    // 100µs tick

  byte    byRelayMsgActive[wRelayMsgCntMax] = { 0,0,0,0 }; // 1 if corresponding message is activated
  word    wRelayCtrlWord  [wCardCntMax]     = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; // 1 word per card

  byte    byMeasStart   = 0;
  byte    byMeasActive  = 0;
  byte    byMeasStopped = 0;
}
/*@@end*/

/*@@timer:timerMeasTick:*/
on timer timerMeasTick
{
  word wCh;

  dwMeasTick += 1;

  for(wCh=0; wCh<wMeasChannels; wCh++)
  {
    if(wPtrIn[wCh] != wPtrOut[wCh])            // new data available?
    {
      if(wCh == @sys_Measure::nBufferMonitor)  // monitor on this channel active?
      {
        if(wPtrIn[wCh] >= wPtrOut[wCh])
        {
          @sys_Measure::nBufferUsage = wPtrIn[wCh] - wPtrOut[wCh];
        }
        else
        {
          @sys_Measure::nBufferUsage = wBufferSize + wPtrIn[wCh] - wPtrOut[wCh];
        }
      }

      if(dwMeasTick >= dwTimeStamp[wCh][wPtrOut[wCh]])
      {
        @sys_Measure::afOutput[wCh] = (float)  nMeasValue[wCh][wPtrOut[wCh]]
                                             / @sys_Measure::anDivisor[wCh]
                                             + fDispOffset            [wCh];

        wPtrOut[wCh] = IncBufferPtr(wPtrOut[wCh]);

        if(wPtrIn[wCh] == wPtrOut[wCh])
        {
          byMeasStopped = 1;
        }
      }
    }
  }

  if(byMeasStopped == 0)
  {
    // continue masurement cycle at 100µs rate
    setTimer(timerMeasTick, 0, 100000);
  }
}
/*@@end*/

/*@@timer:timerTimeoutTick:*/
on timer timerTimeoutTick
{
  stop();
}
/*@@end*/

/*@@msg:*:*/
on message *
{
  word wCard;

  switch(this.ID & wCardCanMask)
  {
    case MsgCardDetect_00.ID:
      wCard = this.ID - MsgCardDetect_00.ID;

      @sys_Control::anAvailableCard[wCard] = 1;
      @sys_Control::anCurrentRange [wCard] = this.byte(0);  // TBD

      if(this.char(4) != 0)
      {
        cSwVersion[6]  = this.char(4);
        cSwVersion[7]  = this.char(5);
        cSwVersion[8]  = this.char(6);
        cSwVersion[9]  = this.char(7);
        cSwVersion[10] = '\0';

        SysSetVariableString(sysvar::sys_Control::sSwVersion, cSwVersion);
      }

      if(nTestStart[wCard])
      {
        msgBeep(0);
      }
      else
      {
        nTestStart[wCard] = 1;
      }
      break;

    case mDiag_Res_00.ID:
      DiagResMessage.qword(0) = this.qword(0);
      EvaluateDiagResponse(this.ID - mDiag_Res_00.ID);
      break;

    default:
      if((@sysAddMsg::nBusType == wAddMsgBusCan) && (this.ID == @sysAddMsg::nID))
      {
        StoreAdditionalMeasurement(this.qword(0));
      }
      break;
  }
}
/*@@end*/

/*@@caplFunc:StartOutput():*///function
StartOutput(void)
{
  if((byMeasActive == 0) && (byMeasStopped == 0))
  {
    byMeasActive = 1;
 
    // initiate measurement tick event at once
    setTimer(timerMeasTick, 0, 0);
  }
}
/*@@end*/

/*@@caplFunc:IncBufferPtr(word):*///function
word IncBufferPtr(word p)
{
  p++;

  if(p >= wBufferSize)
  {
    p = 0;
  }

  return p;
}
/*@@end*/

/*@@timer:timerMeasStart:*/
on timer timerMeasStart
{
  StartOutput();
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure4 (0x7C4):*/
on message MsgRtMeasure4
{
  StoreMeasurementWithTimeStamp( 4, $SigRtMeasure4_Data0,     $SigRtMeasure4_Data1,
                                    $SigRtMeasure4_TimeStamp, $SigRtMeasure4_TimeOffset);
}
/*@@end*/

/*@@linmsg:*:*/
on linMessage *
{
  if(@sysAddMsg::nBusType == wAddMsgBusLin)
  {
    if(this.ID == @sysAddMsg::nID)
    {
      StoreAdditionalMeasurement(this.qword(0));
    }
  }
}
/*@@end*/

/*@@timer:timerMsgTimer:*/
on timer timerMsgTimer
{
  word w;

  output(CommonMessage);

  for(w=0; w<wRelayMsgCntMax; w++)
  {
    if(byRelayMsgActive[w] != 0)
    {
      RelayMessage.SigRelayCtrl_00 = wRelayCtrlWord[4 * w    ];
      RelayMessage.SigRelayCtrl_01 = wRelayCtrlWord[4 * w + 1];
      RelayMessage.SigRelayCtrl_02 = wRelayCtrlWord[4 * w + 2];
      RelayMessage.SigRelayCtrl_03 = wRelayCtrlWord[4 * w + 3];
      RelayMessage.ID = MsgRelayCtrl_00.ID + w;
      output(RelayMessage);
    }
  }

  setTimer(timerMsgTimer, lMsgCycle);
}
/*@@end*/

/*@@startStart:Start:*/
on start
{
  CommonMessage.SigCommon_RelayActive = 1;
  CommonMessage.SigCommon_CardDetect  = 1;

  @sys_Measure::anDivisor[0] = getProfileInt("SCALING", "Divisor0", 1, "Measure.ini");
  @sys_Measure::anDivisor[1] = getProfileInt("SCALING", "Divisor1", 1, "Measure.ini");
  @sys_Measure::anDivisor[2] = getProfileInt("SCALING", "Divisor2", 1, "Measure.ini");
  @sys_Measure::anDivisor[3] = getProfileInt("SCALING", "Divisor3", 1, "Measure.ini");
  @sys_Measure::anDivisor[4] = getProfileInt("SCALING", "Divisor4", 1, "Measure.ini");
  @sys_Measure::anDivisor[5] = getProfileInt("SCALING", "Divisor5", 1, "Measure.ini");
  @sys_Measure::anDivisor[6] = getProfileInt("SCALING", "Divisor6", 1, "Measure.ini");
  @sys_Measure::anDivisor[7] = getProfileInt("SCALING", "Divisor7", 1, "Measure.ini");
  @sys_Measure::anDivisor[8] = getProfileInt("SCALING", "Divisor8", 1, "Measure.ini");
  @sys_Measure::anDivisor[9] = getProfileInt("SCALING", "Divisor9", 1, "Measure.ini");

  SysSetVariableString(sysvar::sys_Control::sSwVersion, cSwVersion);

  setTimer(timerMsgTimer, lMsgCycle);
}
/*@@end*/

/*@@sysvarUpdate:sys_Control::anAvailableCard:*/
on sysvar_update sysvar::sys_Control::anAvailableCard
{
  int i;

  for(i=0; i<wCardCntMax; i++)
  {
    if(@sys_Control::anAvailableCard[i] != 0)
    {
      byRelayMsgActive[i/4] = 1;
    }
  }
}
/*@@end*/

/*@@sysvarUpdate:sys_Control::nMeasEnable:*/
on sysvar_update sysvar::sys_Control::nMeasEnable
{
  CommonMessage.SigCommon_MeasEnable  = @sys_Control::nMeasEnable;
}
/*@@end*/

/*@@caplFunc:StoreMeasurementWithTimeStamp(word,int,int,word,word):*///function
StoreMeasurementWithTimeStamp (word  wChannel, int nData0, int nData1, word wTimeStamp, word wTimeOffset)
{
  dword dwTimeStampAbs;

  if(wTimeStamp < wTimeStampMem[wChannel])  // overflow of 12 bit time stamp
  {
    dwTimeOffset[wChannel] = dwTimeOffset[wChannel] + wTimeStampRange;
  }

  wTimeStampMem[wChannel] = wTimeStamp;

  dwTimeStampAbs = dwTimeOffset[wChannel] + wTimeStamp;
  // now dwTimeStampAbs contains the absolute time stamp since measurement start

  nMeasValue [wChannel][wPtrIn[wChannel]] = nData0;
  dwTimeStamp[wChannel][wPtrIn[wChannel]] = dwTimeStampAbs;
  wPtrIn[wChannel] = IncBufferPtr(wPtrIn[wChannel]);

  nMeasValue [wChannel][wPtrIn[wChannel]] = nData1;
  dwTimeStamp[wChannel][wPtrIn[wChannel]] = dwTimeStampAbs + wTimeOffset;
  wPtrIn[wChannel] = IncBufferPtr(wPtrIn[wChannel]);

  cancelTimer(timerTimeoutTick);
  setTimer(timerTimeoutTick, lCanTimeout);

  if(byMeasStart == 0)
  {
    byMeasStart = 1;
    setTimer(timerMeasStart, lMeasDelay);
  }

  if(wPtrIn[wChannel] >= wBufferOffset)
  {
    StartOutput();
  }
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure0 (0x7C0):*/
on message MsgRtMeasure0
{
  StoreMeasurementWithTimeStamp( 0, $SigRtMeasure0_Data0,     $SigRtMeasure0_Data1,
                                    $SigRtMeasure0_TimeStamp, $SigRtMeasure0_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure1 (0x7C1):*/
on message MsgRtMeasure1
{
  StoreMeasurementWithTimeStamp( 1, $SigRtMeasure1_Data0,     $SigRtMeasure1_Data1,
                                    $SigRtMeasure1_TimeStamp, $SigRtMeasure1_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure2 (0x7C2):*/
on message MsgRtMeasure2
{
  StoreMeasurementWithTimeStamp( 2, $SigRtMeasure2_Data0,     $SigRtMeasure2_Data1,
                                    $SigRtMeasure2_TimeStamp, $SigRtMeasure2_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure3 (0x7C3):*/
on message MsgRtMeasure3
{
  StoreMeasurementWithTimeStamp( 3, $SigRtMeasure3_Data0,     $SigRtMeasure3_Data1,
                                    $SigRtMeasure3_TimeStamp, $SigRtMeasure3_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure5 (0x7C5):*/
on message MsgRtMeasure5
{
  StoreMeasurementWithTimeStamp( 5, $SigRtMeasure5_Data0,     $SigRtMeasure5_Data1,
                                    $SigRtMeasure5_TimeStamp, $SigRtMeasure5_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure6 (0x7C6):*/
on message MsgRtMeasure6
{
  StoreMeasurementWithTimeStamp( 6, $SigRtMeasure6_Data0,     $SigRtMeasure6_Data1,
                                    $SigRtMeasure6_TimeStamp, $SigRtMeasure6_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure7 (0x7C7):*/
on message MsgRtMeasure7
{
  StoreMeasurementWithTimeStamp( 7, $SigRtMeasure7_Data0,     $SigRtMeasure7_Data1,
                                    $SigRtMeasure7_TimeStamp, $SigRtMeasure7_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure8 (0x7C8):*/
on message MsgRtMeasure8
{
  StoreMeasurementWithTimeStamp( 8, $SigRtMeasure8_Data0,     $SigRtMeasure8_Data1,
                                    $SigRtMeasure8_TimeStamp, $SigRtMeasure8_TimeOffset);
}
/*@@end*/

/*@@msg:CAN1.Al32::MsgRtMeasure9 (0x7C9):*/
on message MsgRtMeasure9
{
  StoreMeasurementWithTimeStamp( 9, $SigRtMeasure9_Data0,     $SigRtMeasure9_Data1,
                                    $SigRtMeasure9_TimeStamp, $SigRtMeasure9_TimeOffset);
}
/*@@end*/

/*@@caplFunc:CreateRelayCtrlWord(word):*///function
word CreateRelayCtrlWord (word wCard)
{
  word wRelayCtrlWord;
  word w;

  wRelayCtrlWord = 0;

  for(w=0; w<wChannelsPerCard; w++)
  {
    wRelayCtrlWord = wRelayCtrlWord | @sys_Control::anRelay_OL [4 * wCard + w] << (4 * w    );
    wRelayCtrlWord = wRelayCtrlWord | @sys_Control::anRelay_SC1[4 * wCard + w] << (4 * w + 1);
    wRelayCtrlWord = wRelayCtrlWord | @sys_Control::anRelay_SC2[4 * wCard + w] << (4 * w + 2);
    wRelayCtrlWord = wRelayCtrlWord | @sys_Control::anRelay_SC3[4 * wCard + w] << (4 * w + 3);
  }

  return wRelayCtrlWord;
}
/*@@end*/

/*@@sysvarChange:sys_User::OlRelayOnOff:*/
on sysvar sys_User::OlRelayOnOff
{
  word wOnOff = 0;
  word w;

  if(@this)
  {
    wOnOff = !wOnOff;

    for(w=0; w<wCardCntMax; w++)
    {
      if((wOnOff == 0) || (@sys_Control::anAvailableCard[w] != 0))
      {
        @sys_Control::anRelay_OL[4 * w    ] = wOnOff;
        @sys_Control::anRelay_OL[4 * w + 1] = wOnOff;
        @sys_Control::anRelay_OL[4 * w + 2] = wOnOff;
        @sys_Control::anRelay_OL[4 * w + 3] = wOnOff;
      }
    }
  }
}
/*@@end*/

/*@@sysvarChange:sys_User::StartMeasure:*/
on sysvar sys_User::StartMeasure
{
  if(@sys_User::StartMeasure)
  {
    @sys_Control::nMeasEnable = 1;
  }
}
/*@@end*/

/*@@sysvarChange:sys_User::StopMeasure:*/
on sysvar sys_User::StopMeasure
{
  if(@sys_User::StopMeasure)
  {
    @sys_Control::nMeasEnable = 0;
  }
}
/*@@end*/

/*@@sysvarChange:sys_Control::anActiveCard:*/
on sysvar sys_Control::anActiveCard
{
  int i;

  for(i=0; i<wCardCntMax; i++)
  {
    if(@sys_Control::anAvailableCard[i] != 0)  // check only if card present
    {
      if(@sys_Control::anActiveCard[i] != 0)   // card selected
      {
        if(@sys_Control::nActiveCard != i)     // not previously selected
        {
          @sys_Control::nActiveCard = i;       // set new selection
          break;
        }
      }
    }
  }

  for(i=0; i<wCardCntMax; i++)
  {
    if(i == @sys_Control::nActiveCard)
    {
      @sys_Control::anActiveCard[i] = 1;  // set new selection
    }
    else
    {
      @sys_Control::anActiveCard[i] = 0;  // delete invalid selections
    }
  }
}
/*@@end*/

/*@@sysvarChange:(sys_Control::anRelay_OL | sys_Control::anRelay_SC1 | sys_Control::anRelay_SC2 | sys_Control::anRelay_SC3):*/
on sysvar ( sysvar::sys_Control::anRelay_OL 
          | sysvar::sys_Control::anRelay_SC1
          | sysvar::sys_Control::anRelay_SC2
          | sysvar::sys_Control::anRelay_SC3 )
{
  word w;

  for(w=0; w<wCardCntMax; w++)
  {
    if(@sys_Control::anAvailableCard[w] != 0)
    {
      wRelayCtrlWord[w] = CreateRelayCtrlWord(w);
    }
    else
    {
      ClearRelaySysvar(w);
    }
  }
}
/*@@end*/

/*@@caplFunc:ClearRelaySysvar(word):*///function
ClearRelaySysvar (word wCard)
{
  word w;

  for(w=0; w<wChannelsPerCard; w++)
  {
    @sys_Control::anRelay_OL [4 * wCard + w] = 0;
    @sys_Control::anRelay_SC1[4 * wCard + w] = 0;
    @sys_Control::anRelay_SC2[4 * wCard + w] = 0;
    @sys_Control::anRelay_SC3[4 * wCard + w] = 0;
  }
}
/*@@end*/

/*@@caplFunc:StoreAdditionalMeasurement(qword):*///function
StoreAdditionalMeasurement (qword qwMessage)
{
  word  wChannel;
  dword dwTimeStampAbs;

  wChannel = @sysAddMsg::nChannel;

  if(byMeasActive != 0)
  {
    int  nValue;
    word wLo;
    word wHi;

    wHi = qwMessage >> @sysAddMsg::anBitPos[1];
    wLo = qwMessage >> @sysAddMsg::anBitPos[0];

    wHi = wHi & ((1 << @sysAddMsg::anSize[1]) - 1);
    wLo = wLo & ((1 << @sysAddMsg::anSize[0]) - 1);

    wHi = wHi << (16 -  @sysAddMsg::anSize[1]);
    wLo = wLo << (16 - (@sysAddMsg::anSize[0] + @sysAddMsg::anSize[1]));

    nValue = wHi | wLo;
    nValue = nValue >> (16 - (@sysAddMsg::anSize[0] + @sysAddMsg::anSize[1]));

    dwTimeStampAbs = dwMeasTick + lMeasDelay * 10;  // add measurement delay in 100µs resolution

    nMeasValue [wChannel][wPtrIn[wChannel]] = nValue;
    dwTimeStamp[wChannel][wPtrIn[wChannel]] = dwTimeStampAbs;
    wPtrIn[wChannel] = IncBufferPtr(wPtrIn[wChannel]);
  }
}
/*@@end*/

/*@@key:'c':*/
on key 'c'
{
}
/*@@end*/

/*@@sysvarChange:sys_User::Adapt:*/
on sysvar sys_User::Adapt
{
  if(@sys_User::Adapt)
  {
    fDispOffset[@sys_Measure::nAdaptDest] = @sys_Measure::afOutput[@sys_Measure::nAdaptSrc]
                                          - @sys_Measure::afOutput[@sys_Measure::nAdaptDest];
  }
}
/*@@end*/

/*@@preStop:PreStop:*/
on preStop
{
  writeProfileInt("SCALING", "Divisor0", @sys_Measure::anDivisor[0], "Measure.ini");
  writeProfileInt("SCALING", "Divisor1", @sys_Measure::anDivisor[1], "Measure.ini");
  writeProfileInt("SCALING", "Divisor2", @sys_Measure::anDivisor[2], "Measure.ini");
  writeProfileInt("SCALING", "Divisor3", @sys_Measure::anDivisor[3], "Measure.ini");
  writeProfileInt("SCALING", "Divisor4", @sys_Measure::anDivisor[4], "Measure.ini");
  writeProfileInt("SCALING", "Divisor5", @sys_Measure::anDivisor[5], "Measure.ini");
  writeProfileInt("SCALING", "Divisor6", @sys_Measure::anDivisor[6], "Measure.ini");
  writeProfileInt("SCALING", "Divisor7", @sys_Measure::anDivisor[7], "Measure.ini");
  writeProfileInt("SCALING", "Divisor8", @sys_Measure::anDivisor[8], "Measure.ini");
  writeProfileInt("SCALING", "Divisor9", @sys_Measure::anDivisor[9], "Measure.ini");
}
/*@@end*/

/*@@sysvarChange:sys_Diag::Arg8:*/
on sysvar sys_Diag::Arg8
{
  DiagReqMessage.byte(3) = @sys_Diag::Arg8[0];
  DiagReqMessage.byte(4) = @sys_Diag::Arg8[1];
  DiagReqMessage.byte(5) = @sys_Diag::Arg8[2];
  DiagReqMessage.byte(6) = @sys_Diag::Arg8[3];
  DiagReqMessage.byte(7) = @sys_Diag::Arg8[4];

  @sys_Diag::Arg16[0] = DiagReqMessage.int(3);
  @sys_Diag::Arg16[1] = DiagReqMessage.int(5);
}
/*@@end*/

/*@@sysvarChange:sys_Diag::Arg16:*/
on sysvar sys_Diag::Arg16
{
  DiagReqMessage.int(3) = @sys_Diag::Arg16[0];
  DiagReqMessage.int(5) = @sys_Diag::Arg16[1];

  @sys_Diag::Arg8[0] = DiagReqMessage.byte(3);
  @sys_Diag::Arg8[1] = DiagReqMessage.byte(4);
  @sys_Diag::Arg8[2] = DiagReqMessage.byte(5);
  @sys_Diag::Arg8[3] = DiagReqMessage.byte(6);
}
/*@@end*/

/*@@envVar:MeasType:*/
on envVar MeasType
{
  @sys_Diag::Arg8[1] = getValue(MeasType);
}
/*@@end*/

/*@@sysvarChange:sys_Diag::Execute:*/
on sysvar sys_Diag::Execute
{
  if(@this)
  {
    DiagReqMessage.ID      = mDiag_Req_00.ID + @sys_Control::nActiveCard;
    DiagReqMessage.byte(0) = 0x07;
    DiagReqMessage.byte(1) = 0xBA;
    DiagReqMessage.byte(2) = getValue(DiagCmd);

    output(DiagReqMessage);

    @sys_Diag::CmdSuccess = 0;
  }
}
/*@@end*/

/*@@caplFunc:EvaluateDiagResponse(int):*///function
EvaluateDiagResponse (int nCard)
{
  @sys_Diag::Ret8[0]  = DiagResMessage.byte(2);
  @sys_Diag::Ret8[1]  = DiagResMessage.byte(3);
  @sys_Diag::Ret8[2]  = DiagResMessage.byte(4);
  @sys_Diag::Ret8[3]  = DiagResMessage.byte(5);
  @sys_Diag::Ret8[4]  = DiagResMessage.byte(6);
  @sys_Diag::Ret8[5]  = DiagResMessage.byte(7);

  @sys_Diag::Ret16[0] = DiagResMessage.int(2);
  @sys_Diag::Ret16[1] = DiagResMessage.int(4);
  @sys_Diag::Ret16[2] = DiagResMessage.int(6);

  @sys_Diag::CmdSuccess = ! @sys_Diag::Ret8[0];
}
/*@@end*/

/*@@key:*:*/
on key *
{
  if((this >= '0') && (this <= '9'))
  {
    @sys_Control::anActiveCard[this - '0'] = 1;
  }
}
/*@@end*/

