<?xml version="1.0" encoding="UTF-8"?>

<!--================================================================-->
<!-- Copyright 2003 P&P Software GmbH                               -->
<!--================================================================-->

<!--===================================================================
Generator meta-component for the Matlab wrapper for the OBS Framework.
A "Matlab wrapper" wraps code that generated by the autocode facility of
Matlab and makes it possible to integrate that code within an application
instantiated from the OBS Framework. The Matlab wrapper is given the
form of a component that extends the OBS Framework class
"ControlBlockFloatDbPar".

This XSLT program generates the body of the Matlab wrapper class.

This XSLT program process an XML file that describes the target Matlab
routine. 
===================================================================-->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.1"
    xmlns:lxslt="http://xml.apache.org/xslt"
    xmlns:redirect="org.apache.xalan.lib.Redirect"
    extension-element-prefixes="redirect">

<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes" method="text"/>

<!--===================================================================
       Include general utility rules
===================================================================-->
 <xsl:include href="ClassNameFromPath.xsl"/>
 <xsl:include href="ClassIdFromClassName.xsl"/>
<!--===================================================================
      Top-level rule 
===================================================================-->
<xsl:template match="/ObsApplication/ControllerManagement/ControlAction/ControlBlock">
<!--===================================================================
      Define general-purpose variables
 ===================================================================-->  
  <xsl:variable name="ClassName">
        <xsl:call-template name="ClassNameFromPath">
              <xsl:with-param name="path" select="MatlabWrapper/@type"/>
        </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="ClassId">
        <xsl:call-template name="ClassIdFromClassName">
              <xsl:with-param name="className" select="$ClassName"/>
        </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="Desc" select="MatlabWrapper/Description"/>
  <xsl:variable name="NumberOfInputs" select="count(Input)"/>
  <xsl:variable name="NumberOfOutputs" select="count(Output)"/>
  <xsl:variable name="NumberOfParameters" select="count(Parameter)"/>
  <xsl:variable name="StepFunct" select="MatlabWrapper/StepFunction/@value"/>
  <xsl:variable name="InitFunct" select="MatlabWrapper/InitFunction/@value"/>
  <xsl:variable name="MatlabHeader" select="MatlabWrapper/MatlabCodeHeaderFile/@value"/>
  <xsl:variable name="CodeDir" select="'../'"/>
  <xsl:variable name="TargetFile" select="concat('/Projects/ObsFramework/src/cpp/',MatlabWrapper/@type)"/>     
            
  Generating code for class <xsl:value-of select="$ClassName"/> in files <xsl:value-of select="$TargetFile"/>.cpp

  <!-- Check whether writing to an output file is possible -->
  <xsl:if test="not(element-available('xsl:document'))">
        FATAL ERROR: the xsl:document element is not supported. Header files cannot be written! This element
        is normally supported only in version 1.1 of XSL.
  </xsl:if>
            
  <!-- ===================================================================================
         Create the output file  
          ===================================================================================-->
  <xsl:document href="{$TargetFile}.cpp" omit-xml-declaration="yes" method="text">  
<!--===================================================================
      Start Code Generation
      ===================================================================-->  
//
// Copyright 2003 P&amp;P Software GmbH - All Rights Reserved
//
// <xsl:value-of select="$ClassName"/>.cpp
//
// This is an automatically generated file

#include "<xsl:value-of select="$CodeDir"/>GeneralInclude/CompilerSwitches.h"
#include "<xsl:value-of select="$CodeDir"/>GeneralInclude/DebugSupport.h"
#include "<xsl:value-of select="$CodeDir"/>GeneralInclude/BasicTypes.h"
#include "<xsl:value-of select="$CodeDir"/>GeneralInclude/ClassId.h"
#include "<xsl:value-of select="$CodeDir"/>GeneralInclude/Constants.h"
#include "<xsl:value-of select="$CodeDir"/>Data/DC_DataItem.h"
#include "<xsl:value-of select="$CodeDir"/>Data/DataPool.h"
#include "<xsl:value-of select="$ClassName"/>.h"

unsigned int <xsl:value-of select="$ClassName"/>::numberOfInstances=0;

<xsl:value-of select="$ClassName"/>::<xsl:value-of select="$ClassName"/>() {
    // The Simulink model is NOT reentrant, thus we
    // can only have one instance of this object
    assert(numberOfInstances==0);
    numberOfInstances++;

    numberOfInputs=<xsl:value-of select="$NumberOfInputs"/>;
    numberOfOutputs=<xsl:value-of select="$NumberOfOutputs"/>;
    numberOfParameters=<xsl:value-of select="$NumberOfParameters"/>;

#ifdef HAVE_SIMULINK
    modelStep         =<xsl:value-of select="$StepFunct"/>;
    modelInitialize   =<xsl:value-of select="$InitFunct"/>;

    modelInputs       =new real_T*[numberOfInputs];
    modelOutputs      =new real_T*[numberOfOutputs];
    modelParameters   =new real_T*[numberOfParameters];

    modelInputs[0]    =&amp;Input;
    modelOutputs[0]   =&amp;Output;<xsl:for-each select="Parameter">
    modelParameters[<xsl:value-of select="position()"/>-1]=&amp;<xsl:value-of select="Name/@value"/>;</xsl:for-each>
#endif

    setNumberOfStates(0);
    setNumberOfInputs(numberOfInputs);
    setNumberOfOutputs(numberOfOutputs);
    setNumberOfParameters(numberOfParameters);

    setClassId(<xsl:value-of select="$ClassId"/>);

    // Initialize the Simulink model
    reset();
}

void <xsl:value-of select="$ClassName"/>::propagateState() {
#ifdef HAVE_SIMULINK
    for (unsigned int i=0; i&lt;numberOfParameters; i++)
        *modelParameters[i]=(real_T)p[i];
<xsl:if test="DataPoolLink">
    DataPool* pDP = CC_RootObject::getDataPool();
</xsl:if>
    for (unsigned int i=0; i&lt;numberOfInputs; i++)
        *modelInputs[i]=(real_T)<xsl:text/>
<xsl:choose>
  <xsl:when test="CopyLink">u[i]</xsl:when>
  <xsl:when test="PointerLink">*pU[i]</xsl:when>
  <xsl:when test="DataItemLink">pDIU[i]->getFloatValue()</xsl:when>
  <xsl:when test="DataPoolLink">pDP->getFloatValue(dpu[i])</xsl:when>
</xsl:choose>;
#endif
}

void <xsl:value-of select="$ClassName"/>::updateOutput() {
#ifdef HAVE_SIMULINK
    modelStep();
<xsl:if test="DataPoolLink">
    DataPool* pDP = CC_RootObject::getDataPool();
</xsl:if>
    for (unsigned int i=0;i&lt;numberOfOutputs;i++)
        <xsl:text/>
<xsl:choose>
  <xsl:when test="CopyLink">y[i]=(TD_Float)*modelOutputs[i];</xsl:when>
  <xsl:when test="PointerLink">*pY[i]=(TD_Float)*modelOutputs[i];</xsl:when>
  <xsl:when test="DataItemLink">pDIY[i]->setFloatValue((TD_Float)*modelOutputs[i]);</xsl:when>
  <xsl:when test="DataPoolLink">pDP->setFloatValue(dpy[i],(TD_Float)*modelOutputs[i])</xsl:when>
</xsl:choose>
#endif
}

void <xsl:value-of select="$ClassName"/>::reset() {
#ifdef HAVE_SIMULINK
        modelInitialize(1);
#endif
}
</xsl:document>
</xsl:template>

</xsl:stylesheet>

