"use strict";

/*
 * Copyright 2016 Freescale Semiconductor, Inc.
 * Copyright 2016-2018 NXP
 * To be used with MCUXpresso Config Tools under its Software License Agreement.
 */
/* Script to generate code for Pins tool version 4.0 */
//
//

// "CMSIS" or "SDK"; SDK style can contain CMSIS access to registers
var codeStyle = "SDK";         
//var codeStyle = "CMSIS";      

// "SDK" or "nonSDK"; It affects include (fsl_common.h, fsl_) generating
var projectType = "SDK";       
//var projectType = "";

// Enables/Disables clock gate enable generation. It overrides the setting from the tool. This line is commented normally.
//var clockGateGeneration = true;     
//var clockGateGeneration = false; 

// Main part of generated files name
var chFileName = "pin_mux";

// Preprocessor condition is header file, typically #ifndef _PIN_MUX_H_ , "#define _PIN_MUX_H_"
var moduleName = "pin_mux";

var identifierPrefixes = new Array();                   // Array of identifier prefixes of each user function
// First part of signal called signal function for GPIO signal (signal format is <signal function>, <signal channel>). It is used for generation of direction defines in h file.
var GPIOSignalFunction = "gpio_io";                     // Fixed name of the GPIO signal function on RT1050 instead of wrong "GPIO"
// Style for generating direction defines in h file
var directionDefineFormat = {
  // It determines the position of symbol on a line with #define, e.g. "PIN0_IDX" on "#define PIN0_IDX                         0u   /*!< Pin number for pin 0 in a port */" 
  defineNameColumn: 7,
  // It determines the position of last character of value on a line with #define, e.g. "0u" on "#define PIN0_IDX                         0u   /*!< Pin number for pin 0 in a port */" 
  defineValueEndColumn: 79,
  // It determines the position of comment on a line with #define, e.g. "/*!< Pin number for pin 0 in a port */" on "#define PIN0_IDX                         0u   /*!< Pin number for pin 0 in a port */" 
  defineCommentColumn: 82
}

var cCodeCommentColumn = 45;
//var defineNameColumn = 7;
//var defineValueEndColumn = 37;
//var defineCommentColumn = 40;

// Default style for generating defines
var defaultDefineFormat = {
  // It determines the position of symbol on a line with #define, e.g. "PIN0_IDX" on "#define PIN0_IDX                         0u   /*!< Pin number for pin 0 in a port */" 
  defineNameColumn: 7,
  // It determines the position of last character of value on a line with #define, e.g. "0u" on "#define PIN0_IDX                         0u   /*!< Pin number for pin 0 in a port */" 
  defineValueEndColumn: 42,
  // It determines the position of comment on a line with #define, e.g. "/*!< Pin number for pin 0 in a port */" on "#define PIN0_IDX                         0u   /*!< Pin number for pin 0 in a port */" 
  defineCommentColumn: 45
}

// Root peripheral name of IOMUXC peripheral
var iomuxcPeripheralName = "IOMUXC";
// Root register name of IOMUXC MUX Control Register
var iomuxcControlRegisterName = "IOMUXC_SW_MUX_CTL";
// Root register name of IOMUXC MUX Control Register
var iomuxc_snvs_ControlRegisterName = "IOMUXC_SNVS_SW_MUX_CTL";
// Bit-field name of Pin Mux Control bit-field in IOMUXC Control Register
var pinMuxControlBitName = "MUX_MODE";

// Root register name of IOMUXC Pad Control Register
var iomuxcPadControlRegisterName = 'IOMUXC_SW_PAD_CTL'
// Root register name of IOMUXC Pad Control Register
var iomuxc_snvsPadControlRegisterName = 'IOMUXC_SNVS_SW_PAD_CTL'
// Mask of Pin Mux Control bit-field in IOMUXC Mux Control Register. For both SDK and CMSIS code style generation.
var pinMuxControlBitMask = 0x7;
// Width of Pin Mux Control bit-field in IOMUXC Mux Control Register.
var portMuxWidth = 3;

// Root peripheral name of XBAR peripheral
var xbarPeripheralName = "XBAR";
// Root register name of Crossbar Select Register
var xbarSelRegisterName = "SEL";
// Root register name of Crossbar Control Register
var xbarControlRegisterName = "CTRL";
// Root peripheral name of DMA peripheral
var dmaPeripheralName = "DMA";
// Root peripheral name of DMAMUX peripheral
var dmaMuxPeripheralName = "DMAMUX";
// Root register name of Dmamux Channel Config Register
var dmaMuxChannelConfigRegisterName = "CHCFG";
// Mask of SOURCE bit-field in CHCFG register.
var dmaMuxSourceBitMask = 0x7F;
// Offset of SOURCE bit-field in CHCFG register.
var dmaMuxSourceBitOffset = 0;
// Root peripheral name of TRGMUX peripheral
var trgmuxPeripheralName = "TRGMUX";
// Bit-field name of SEL bit-field in TRGMUX register
var trgmuxSelBitFieldName = "SEL";
// Register alias of TRGMUX registers
var trgmuxRegisterAlias = "TRGCFG[";

// Global array of messages
var messageList = new Array();

// Global Java.type definition for BigInteger
var BigInteger = Java.type("java.math.BigInteger");

/**
 * Prints a message on console
 * repetitively - if false the same message is not printed more than once
 * returns nothing
 */
function logMessage(message, repetitively) {
  var index = messageList.indexOf(message);
  if (index == -1) {
    messageList.push(message);
  }
  var variant = "Unknown processor";
  if (cpuVariant != null) {
    variant = cpuVariant;
  }
  if (repetitively || (index == -1)) {
    PExOut.log(variant + ": " + message);
  }
}


/* PE DEBUG mode flag */
//var PE_DEBUG = PExScript.getMacroSymbol("PE_DEBUG");


var testMode = true;
var registerDatabaseObject = PExProcessor.getRegistersDB();

var warning_message = "/***********************************************************************************************************************\n";
warning_message    += " * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file\n";
warning_message    += " * will be overwritten if the respective MCUXpresso Config Tools is used to update this file.\n";
warning_message    += " **********************************************************************************************************************/\n";

/**
 * Gets Pad Name from register name
 * registerName - full register name
 * returns Pad name (e.g. PTD5 from SW_MUX_CTL_PAD_PTD5)
 */
function getPadName(registerName) {
    var pinName = null;
    if ( registerName.indexOf('SW_PAD_CTL_GRP_') >=0 )
        pinName = registerName.split(/SW_PAD_CTL_/)
    else
        pinName = registerName.split(/PAD_/);
    return pinName = pinName[pinName.length-1];
}

/**
 * Gets part name according to bitValDb name
 * bitValDbName -- reference to database register bit field value
 * returns part name string (e.g. LPSPI3_PCS0 from SW_MUX_CTL_PAD_MUX_MODE_ALT3_lpspi3_PCS0)
 */
function getNamePartStr(bitValDbName) {
    
    // var NamePartStr = bitValDbName.replace(/_PT/,'_GPIO');
    // PExOut.log(NamePartStr);
    // NamePartStr = NamePartStr.split(/ALT[0-9]+_/);
    // NamePartStr = NamePartStr.slice(NamePartStr.length-1).join("_").toUpperCase();
    var NamePartStr = bitValDbName.split(":")[2];
    NamePartStr = NamePartStr.split(" ")[1];
    return NamePartStr;

}

/**
 * Gets bitwise or. Native bitwise operation in Javascript works only with 31-bit numbers because of implicit conversion to signed 32-bit integer.
 * a - value 1
 * b - value 2
 * returns result of bitwise OR
 */
function getBitwiseOr(a,b) {
  if (a < 0 || b < 0) {
    logMessage("One of operands (" + a + ", " + b + ") is negative number.", true);
  }
  var result = 0;
  var mask = 0xFFFF;
  var divisor = mask + 1;
  var i = 0;
  while ((a != 0) || (b != 0)) {
    var r = ((a & mask) | (b & mask));
    for (var j = 0; j < i; j++) {
      r *= divisor;
    }
    result += r;
    a = Math.floor(a / divisor);
    b = Math.floor(b / divisor);
    i++;
  }
  return result;
}

/**
 * Gets bitwise xor. Native bitwise operation in Javascript works only with 31-bit numbers because of implicit conversion to signed 32-bit integer.
 * a - value 1
 * b - value 2
 * returns result of bitwise XOR
 */
function getBitwiseXor(a,b) {
  if (a < 0 || b < 0) {
    PExOut.log("One of operands (" + a + ", " + b + ") is negative number.");
  }
  var result = 0;
  var mask = 0xFFFF;
  var divisor = mask + 1;
  var i = 0;
  while ((a != 0) || (b != 0)) {
    var r = ((a & mask) ^ (b & mask));
    for (var j = 0; j < i; j++) {
      r *= divisor;
    }
    result += r;
    a = Math.floor(a / divisor);
    b = Math.floor(b / divisor);
    i++;
  }
  return result;
}


/**
 * Gets bitwise and. Native bitwise operation in Javascript works only with 31-bit numbers because of implicit conversion to signed 32-bit integer.
 * a - value 1
 * b - value 2
 * returns result of bitwise AND
 */
function getBitwiseAnd(a,b) {
  if (a < 0 || b < 0) {
    PExOut.log("One of operands (" + a + ", " + b + ") is negative number.");
  }
  var result = 0;
  var mask = 0xFFFF;
  var divisor = mask + 1;
  var i = 0;
  while ((a != 0) && (b != 0)) {
    var r = ((a & mask) & (b & mask));
    for (var j = 0; j < i; j++) {
      r *= divisor;
    }
    result += r;
    a = Math.floor(a / divisor);
    b = Math.floor(b / divisor);
    i++;
  }
  return result;
}

/**
 * Gets bitwise 32-bit neg. Native bitwise operation in Javascript works only with 31-bit numbers because of implicit conversion to signed 32-bit integer.
 * a - value
 * returns result of bitwise 32-bit NEG
 */
function getBitwiseNeg32(a) {
  if (a < 0) {
    PExOut.log("Operand (" + a + ") is negative number.");
  }
  return getBitwiseXor(a,0xFFFFFFFF);
}

/**
 * Gets value shifted left by a number. Native bitwise operation in Javascript works only with 31-bit numbers because of implicit conversion to signed 32-bit integer.
 * a - value which is shifted left by n 
 * n - number
 * returns shifted value
 */
function getBitwiseShiftLeft(a, n) {
  if (a < 0 || n < 0) {
    PExOut.log("One of operands (" + a + ", " + n + ") is negative number.");
  }
 return (a * Math.pow(2, n));
}


// Analyzing processor register database on XBAR, DMAMUX, TRGMUX,... existing, number of DMA instances,... And loading given informations in order to mapping on SDK functions.
var globalPcrMask = 0;
if (registerDatabaseObject != null) {
  var peripherals = registerDatabaseObject.getPeripherals();
  if (codeStyle == "SDK") {
    var loadXbar = false;
    var loadDmamux = false;
    var loadTrgmux = false;
    var dbIsXBARA = false;
    var dbIsXBARB = false;
    var dmaCount = 0;

    for (var ip = 0; ip < peripherals.length; ip++) {
      var peripheralName = peripherals[ip].getName();

      if (peripheralName.indexOf(xbarPeripheralName) >= 0) {
        loadXbar = true;  
      }
      if (peripheralName.indexOf(dmaMuxPeripheralName) >= 0) {
        loadDmamux = true;  
      }
       if (peripheralName.indexOf(trgmuxPeripheralName) >= 0) {
         loadTrgmux = true;  
       }
      if ((peripheralName.indexOf(dmaPeripheralName) >= 0) && (peripheralName.indexOf(dmaMuxPeripheralName) < 0)) {
        dmaCount += 1;  
      }
      if (peripheralName.indexOf(xbarPeripheralName + 'A') >= 0) {
        dbIsXBARA = true;
      }
      if (peripheralName.indexOf(xbarPeripheralName + 'B') >= 0) {
        dbIsXBARB = true;
      }
    }

    var cpuVariant = PExScript.getMacroSymbol('CPUvariant');
    var xbarModulesAB = false;
    if (dbIsXBARA || dbIsXBARB) {
      // XBAR is supported by two modules XBARA and/or XBARB
      xbarModulesAB = true;
    }
    // Loading given informations in order to mapping on SDK functions
    if (cpuVariant != null) {
      var loadingPath = "";
      if (loadXbar) {
        loadingPath = cpuVariant.valueOf() + "/XBAR.js";
        var xbarInputSignal = PExProcessor.loadPersistentObject("xbar_input_signal", loadingPath);
        var xbarOutputSignal = PExProcessor.loadPersistentObject("xbar_output_signal", loadingPath);
        if (xbarInputSignal == null || xbarOutputSignal == null) {
          logMessage('There is problem with loading ' + loadingPath, false);
        }
      }
      if (loadDmamux) {
        loadingPath = cpuVariant.valueOf() + "/DMAMUX.js";
        var dmaRequestSource = PExProcessor.loadPersistentObject("dma_request_source", loadingPath);
        if (dmaRequestSource == null) {
          logMessage('There is problem with loading ' + loadingPath);
        }
      }
       if (loadTrgmux) {
         loadingPath = cpuVariant.valueOf() + "/TRGMUX.js";
         var trgmuxDevice = PExProcessor.loadPersistentObject("trgmux_device", loadingPath);
         var trgmuxSource = PExProcessor.loadPersistentObject("trgmux_source", loadingPath);
         if (trgmuxDevice == null || trgmuxSource == null) {
           logMessage('There is problem with loading ' + loadingPath, false);
         }
      }
    }
    else {
      PExOut.log('CPUvariant not found.');
    }
  }  
}


function isNotBoundedPin(coordinates) {
  if(/-/.test(coordinates) || /\//.test(coordinates)) {
    return true;
  }
  return false;
}


// Preparation of other information, such as Clock gate generation enable/disable, configuration strategies for getting right set register configuration for given user function
var allComponents = PExProject.getAllComponents();      // Each component represents one user function
var configurationStrategies = new Array();              // Configuration strategies for getting right set register configuration for given user function
var componentCoreIds = new Array();                     // Core IDs array. It says core id for each user function
var componentClockGateGeneration = new Array();         // Clock gate generation enabling options array. It says clock gate generation enabling option for each user function 
var textOptions = null;
for (var pc = 0; pc < allComponents.length; pc++) {
  var funcNameItem = allComponents[pc].findItemBySymbol("FunctionName");
  if (funcNameItem != null) {
    configurationStrategies[pc] = funcNameItem.getText();
  }
  textOptions = allComponents[pc].getComponentOptions();
  if (textOptions != null) {
    var options = JSON.parse(textOptions);
    componentCoreIds.push(options["coreID"]);
    if (typeof(clockGateGeneration) == "undefined") {
      componentClockGateGeneration.push(options["enableClock"]);
    }
    else {
      componentClockGateGeneration.push(clockGateGeneration);
    }
    var identifierPrefix = options["prefix"];
    if(identifierPrefix == null) {
        identifierPrefixes.push((configurationStrategies[pc] + "_").toUpperCase());
    }
    else {
      identifierPrefixes.push(identifierPrefix);
    }    
  }
}
var configurationStrategy=null;

// get multi-core information
var coreIds = null;
var coreListTxt = PExProcessor.getCoresList();
if (coreListTxt != null) {
  coreIds = Object.keys(JSON.parse(coreListTxt));
}

// generate code only for cores with non-empty configurations
var notEmptyCoreIds = new Array();
for (var coreIndex in coreIds) {
  var coreId = coreIds[coreIndex];
  if (componentCoreIds.indexOf(coreId) > -1) {
    notEmptyCoreIds.push(coreId);
  }
}

// Initial state of helping variables because of including SDK modules in generated code
var include_fsl_xbar = {
  present: false, 
  pcs: new Array()
};
var include_fsl_xbara = {
  present: false, 
  pcs: new Array()
};
var include_fsl_xbarb = {
  present: false, 
  pcs: new Array()
};
var include_fsl_dmamux = {
  present: false,
  pcs: new Array()
};
var include_fsl_iomuxc = {
  present: false, 
  pcs: new Array()
};
var include_fsl_trgmux = {
  present: false,
  pcs: new Array()
};

/* c indentation 2 */
var cIndent2 = '  ';
/* c indentation 4 */
var cIndent4 = '    ';
/* c indentation 6 */
var cIndent6 = '      ';
/* c indentation 8 */
var cIndent8 = '        ';
/* c indentation 12 */
var cIndent12 = '            ';
/* c indentation 16 */
var cIndent16 = '                ';
/**
 * Gets string value for usage within the set bit-field macro statement for clearing set bits
 * dbBitField - database bit field object to get bit field mask string
 * returns bit field mask string out of XML register database using CMSIS alias attribute value (e.g. PORT_PCR_MUX_MASK)
 */
function getBitFieldMaskStr(dbBitField) {
    var bitFieldMaskAlias = dbBitField.getAlias("CMSIS");
    return bitFieldMaskAlias.replace("(x)", "_MASK");
}

/**
 * Gets string value for usage within the set bit-field macro statement for clearing set bits
 * dbBitField - database bit field object to get bit field mask string
 * returns bit field mask string out of XML register database using CMSIS alias attribute value (e.g. PORT_PCR_MUX(x))
 */
function getBitFieldStr(dbBitField) {
    return dbBitField.getAlias("CMSIS");
}

/**
 * Gets register name string in order to access the register in printed code 
 * registerName - full register name (e.g. TRGMUX_FTM1)
 * returns register name string for access in code (e.g. "TRGCFG[11]")
 */
function getRegisterNameStr(registerName) {
    var dbRegister = registerDatabaseObject.getRegisterByFullName(registerName);
    var dbPeripheral = getDbPeripheralByFullNameObj(registerName); // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName);
    return ((dbPeripheral != null) ? dbPeripheral.getName() : iomuxcPeripheralName) + "->" + dbRegister.getAlias("CMSIS"); // FIXED: default iomuxcPeripheralName = "IOMUXC" applied when dbPeripheral is null!
}

/**
 * Gets parent peripheral pf the register by the given register full name string 
 * registerName - full register name (e.g. IOMUXC_GPR_GPR0)
 * returns object of given peripheral from register database for further processing in JS code (e.g. "IOMUXC_GPR" peripheral object) or NULL
 * NOTE: Code is applicable to override incorrect API implementation of getPeripheralByFullName within MCUX v4 for some i.MX peripherals
 */
function getDbPeripheralByFullNameObj(registerName) {
  if (registerName != null) {
    var dbPeripheral = registerDatabaseObject.getPeripheralByFullName(registerName); // get peripheral name by the API first
    // WORKAROUND: for some peripherals the API of getPeripheralByFullName doesn't work correctly within PINS/MCUX v4 implementation, so the override must be applied.
    if (registerName.indexOf("IOMUXC_SNVS_") > -1) {
      dbPeripheral = registerDatabaseObject.getPeripheral("IOMUXC_SNVS");           // dbPeripheral should be "IOMUXC_SNVS"
    }
    if (registerName.indexOf("IOMUXC_GPR_") > -1) {
      dbPeripheral = registerDatabaseObject.getPeripheral("IOMUXC_GPR");            // dbPeripheral should be "IOMUXC_GPR"
    }
    return dbPeripheral; // return correct peripheral object for given registerDatabaseObject
  }
  return null;
}

/**
 * Gets peripheral name string in order to further application of the peripheral name in printed code.
 * registerName - full register name string
 * returns string of the given peripheral name
 */
function getDbPeripheralByFullNameStr(registerName) {
  var dbPeripheral = getDbPeripheralByFullNameObj(registerName);
  if (dbPeripheral != null) {
    return dbPeripheral.getName();  // return given peripheral name string
  }
  return "";
}

/**
 * Gets value converted to hex format 
 * bitFieldValueX - number for conversion
 * returns converted value (e.g. 0x0Fu)
 */
function getNumberConvertedToHex(bitFieldValueX) {
  // HOTFIX: Need to be modified otherwise the statement cause javax.script.ScriptException for java.lang.Long.toString(16) call.
  //var hexNumberPart = bitFieldValueX.toString(16).toUpperCase();

  // FIXED: Use conversion to a BigInteger before toString() is applied, instead of direct usage bitFieldValueX.toString(16) - evaluated as working in JRE 1.8, build 1.8.0_144-b01
  // var BigInteger = Java.type("java.math.BigInteger");
  var bigIntBitFieldValueX = new BigInteger(bitFieldValueX.toString());

  var hexNumberPart = bigIntBitFieldValueX.toString(16).toUpperCase(); // COMMENT: Here is the .toString(16) call acceptable and working as expected, because of BigInteger conversion before :)
  // 
  if(hexNumberPart.length % 2 == 1) {
    hexNumberPart = "0" + hexNumberPart;
  }
  return ("0x" + hexNumberPart + "u");
}


/**
 * Removes '.' at the end of the description if it is there
 * descr - string which contains a description, e.g. "CMP1 Output output assigned to XBARB_IN1 input."
 * returns improved string, e.g "CMP1 Output output assigned to XBARB_IN1 input"
 */
function removeLastDotFromDescription(descr) {
  var firstDotPosition = descr.indexOf('.');
  var lastPos = descr.length - 1;
  while (descr.charAt(lastPos) == ' ') {
    lastPos--;
  }
  if (descr.charAt(lastPos) == '.') {
    lastPos--;
  }
  return (descr.substring(0, lastPos + 1));
}

/**
 * Gets formatted constant definition string
 * code - string which contains a code
 * comment - string which contains a comment
 * format - determines format of the line with #define. It is optional parameter. If it is null then defaultDefineFormat is used
 * returns constant definition string, e.g #define SOPT_ADCAALTTRGEN_XBAR 0x00u  // ADCA alternate trigger enable: XBARA ...
 */
function getConstantDefinitionStr(name, value, comment, format) {
  if (format == null) {
    var f = defaultDefineFormat;
  }
  else {
    var f = format;
  }
  var line = "#define ";
  for (var c = line.length; c <= f.defineNameColumn; c++) {
    line = line + " ";
  }
  line += name + " ";
  for (var c = line.length; c <= (f.defineValueEndColumn - value.length); c++) {
    line = line + " ";
  }
  line += value + " ";
  for (var c = line.length; c <= f.defineCommentColumn; c++) {
    line = line + " ";
  }
  line += "/*!< " + comment + " */";
  return (line);
}


/**
 * Adds a comment on a column
 * code - string which contains a code
 * comment - string which contains a comment
 * returns <code>     {a column}// comment
 */
function addCCodeComment(code, comment) {
    var line = code + " ";
    for (var c = line.length; c <= cCodeCommentColumn; c++) {
      line = line + " ";
    }
    return (line + "/* " + comment + " */");
}


/**
 * Gets whole line including comment which set bit field starting with "|"
 * dbBitField - reference to database bit field
 * bitFieldValueX - numeric value used if bit field value is empty
 * bfVal - bit field value, e.g. PCR_SRE_PCR_SRE_FASLT
 * bfDescr - bit field description, e.g. Slew Rate Enable: Fast slew rate is configured on the corresponding pin, if the pin is configured as a digital output.  
 * returns e.g. | PORT_PCR_SRE(PCR_SRE_PCR_SRE_FASLT) // Slew Rate Enable: Fast slew rate is configured on the corresponding pin, if the pin is configured as a digital output. 
 *           or | DMAMUX_CHCFG_SOURCE(0x02u)       // DMA Channel Source (Slot): 0x02u"
 */
function getBitFieldSetMaskString(dbBitField, bitFieldValueX, bfVal, bfDescr) {
  if (bfVal == "") {
    bfVal = getNumberConvertedToHex(bitFieldValueX);
    if (bfDescr == "") {
      bfDescr = dbBitField.getDescription() + ": " + bfVal;
    }
  }
  return (addCCodeComment(cIndent6 + '| ' + getBitFieldStr(dbBitField).replace("(x)",  "(" + bfVal + ")"), bfDescr));
}


/**
 * Gets description for bit field configuration in format <bit field description paarameter> (typically contains bit field description): <bit field value description corresponding to a value in bitFieldValueX>
 * dbBitFieldValues - bit field values
 * bitFieldValueX - numeric value used if bit field value is empty
 * bitFieldDescription - bit field description, e.g. "Slew Rate Enable" or "DMA Channel Source (Slot)"  
 * returns e.g. "Slew Rate Enable: Fast slew rate is configured on the corresponding pin, if the pin is configured as a digital output." 
 *           or "DMA Channel Source (Slot): 0x02u"
 */
function getBitFieldSetMaskDescription(dbBitFieldValues, bitFieldValueX, bitFieldDescription) {
  var bfDescr = "";
  if (dbBitFieldValues != null) {
    for (var v = 0; v < dbBitFieldValues.length; v++) {
      if (dbBitFieldValues[v].getValue() == bitFieldValueX) {
        bfDescr = bitFieldDescription + ": " + dbBitFieldValues[v].getDescription();
      }
    }
  }
  if (bfDescr == "") {
    bfDescr = bitFieldDescription + ": " + getNumberConvertedToHex(bitFieldValueX);
  }
  return bfDescr;
}

/** 
 * Get description for given numeric bit field value, if not found empty description returned.
 * dbBitFieldValues - bit field values
 * bitFieldValueX - numeric value of the bit field 
 * returns bit field value description read from current registersDB
 */
function getBitFieldValueDescription(dbBitFieldValues, bitFieldValueX) {
  var bfDescr = "";
  if (dbBitFieldValues != null) {
    for (var v = 0; v < dbBitFieldValues.length; v++) {
      if (dbBitFieldValues[v].getValue() == bitFieldValueX) {
        bfDescr = dbBitFieldValues[v].getDescription();
      }
    }
  }
  return bfDescr;
}

/**
 * Gets pin part name according to selected pin function (according to pin routing)
 * registerName - full register name which is modified
 * mask - mask of register bits which are modified
 * returns pin part name (e.g. UART1_TX)
 */
function getSelectedPinNamePartStr(registerName, mask) {
  var itemList = PExProcessor.getOwnerPropertiesForRegisterFromPrphsModel(registerName, java.math.BigInteger.valueOf(mask), false, configurationStrategy, null);
  var selectedPinNameParts = new Array();
  for (var iItem in itemList) {
    var pinNamePart = itemList[iItem].getSelectedPinNamePart();
    if (selectedPinNameParts.indexOf(pinNamePart) == -1) {
      selectedPinNameParts.push(pinNamePart);
    }
  }
  return selectedPinNameParts.join(", ");
}
/**
 * Gets reset value of register from database
 * dbReg - reference to database register
 * returns reset value
 */
function getResetValue(dbReg) {
  var value = java.math.BigInteger.valueOf(0);
  var dbBitFields = dbReg.getBitFields();
  for (var fi = 0; fi < dbBitFields.length; fi++) {
    var dbBitField = dbBitFields[fi];
    value |= dbBitField.getResetValue().longValue() << dbBitField.getOffset();
  }
  return (value);
}
/**
 * Gets register mask of no read only bits
 * dbReg - reference to database register
 * returns non read only mask
 */
function getNonReadOnlyMask(dbReg) {
  var mask = java.math.BigInteger.valueOf(0);
  var dbBitFields = dbReg.getBitFields();
  for (var fi = 0; fi < dbBitFields.length; fi++) {
    var dbBitField = dbBitFields[fi];
    if (dbBitField.isReadOnly()) {
      mask |= dbBitField.getRegisterMask().longValue();
    }
  }
  return (dbReg.getMask().longValue() ^ mask);
}
/**
 * Registers constant definition into constant definitions list in order to print them into output code. 
 * objName - object name in constant definitions collection; the same as name; if a number is inside, the number is normalize because of sorting
 * name - name of symbolic constant
 * value - value of symbolic constant
 * comment - comment for symbolic constant
 * valueType type of value:
 *     - index (number is not converted to hex)
 *     - mask or another from index (number is converted to hex)      
 * configurationConstantDefinitionList - reference to constant definition list for a configuration     
 * return no value
 */
function registerConstantDefinition(objName, name, value, comment, valueType, configurationConstantDefinitionList) {
  var def = configurationConstantDefinitionList[objName];
  if (def == null) {
    configurationConstantDefinitionList[objName] = new Object();
    configurationConstantDefinitionList[objName].name = name;
    configurationConstantDefinitionList[objName].value = value;
    configurationConstantDefinitionList[objName].comment = comment;
    if (valueType == 'index') {
      configurationConstantDefinitionList[objName].indexType = '';
    }
  }
}


/**
 * Convert number to string and adding zeroes on the left so that resulting string has length 3
 * x - number
 * return converted number
 */
function normalizeNumberStr(x) {
  var str = x.toString();
  while (str.length < 3) {
    str = '0' + str;
  }
  return str;
}

/**
 * Analyzes bit fields of the register and do requested action, e.g. printing configuration CMSIS code, finding constant for definitions. 
 * reg - reference to registers specified by registerName, registerClrMask and registerSetMask 
 * action - defines action:
 *   - print - writes CMSIS code into ouput
 *   - constantDefinitions - gets array of constants specified by name, value and description for both clr and set masks    
 *   - onlyMaskConstantDefinitions - gets array of constants specified by name, value and description with MASK at the end of the name
 * configurationConstantDefinitionList - reference to constant definition list for a configuration     
 * return no value
 */
function processRegister(reg, action, configurationConstantDefinitionList) {
        var retValue = '';
        switch (action) {
          case "constantDefinitions":
            var registerClrSetMask = getBitwiseOr(reg.registerClrMask, reg.registerSetMask);
            break;
          default:
            var registerClrSetMask = getBitwiseOr(reg.registerClrMask, reg.registerSetMask);
        }
        var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
        if (reg.registerName == "IOMUXC_GPR_GPR6") {
          if (registerClrSetMask != 0) {
            if (dbRegister != null) {
              var dbBitFields = dbRegister.getBitFields();
              var bitFieldClrMasksString = new Array();
              var bitFieldSetMasksString = new Array();
              for (var fi = 0; fi < dbBitFields.length; fi++) {
                var bitFieldMask = dbBitFields[fi].getRegisterMask().doubleValue();
                var str = getSafeBitFieldBy0MaskStr(reg, dbBitFields[fi]);
                if (str != "") {
                  bitFieldClrMasksString.push(str);
                }
                if ((getBitwiseAnd(bitFieldMask,registerClrSetMask)) > 0) {
                  var registerName = dbRegister.getName();
                  var bitFieldName = dbBitFields[fi].getName();
                  var bfVal = "";
                  var bfValValue = "";
                  var bfDescr = "";
                  var dbBitFieldValues = dbBitFields[fi].getValues();
                  var bitFieldValueX = getBitwiseAnd(reg.registerSetMask, bitFieldMask) >>> dbBitFields[fi].getOffset();
                  if (dbBitFields[fi].isArray()) {
                    var itemWidth = dbBitFields[fi].getItemWidth();
                    var width = dbBitFields[fi].getWidth();
                    var numberOfItems = width / itemWidth;
                    var itemRegisterMask = 0;
                    for (var i = 0; i < itemWidth; i++) {
                      itemRegisterMask = getBitwiseOr(itemRegisterMask, getBitwiseShiftLeft(1, i));
                    }
                    itemRegisterMask = getBitwiseShiftLeft(itemRegisterMask, dbBitFields[fi].getOffset());
                    for (var fai = 0; fai < numberOfItems; fai++) {
                      var itemMask = getBitwiseShiftLeft(itemRegisterMask, (fai * itemWidth));
                      if (getBitwiseAnd(itemMask, registerClrSetMask)) {
                        var defName = getBitFieldArrayMaskStr(dbBitFields[fi],fai) + '_MASK';
                        bitFieldClrMasksString.push(defName);
                        switch (action) {
                          case "constantDefinitions":
                          case "onlyMaskConstantDefinitions":
                            registerConstantDefinition(defName, defName, itemMask, dbBitFields[fi].getDescription() + " Mask for item " + fai + ".", 'mask', configurationConstantDefinitionList)
                            retValue = getBitFieldArrayXMaskStr(dbBitFields[fi]) + '_MASK';
                            break;
                        }
                      }
                      if (itemWidth == 1) {
                        if (getBitwiseAnd(itemMask, registerClrSetMask)) {
                          if (dbBitFieldValues != null) {
                            for (var v = 0; v < dbBitFieldValues.length; v++) {
                              var bitFieldValueXItemMask = getBitwiseAnd(bitFieldValueX, itemMask);
                              if (getBitwiseAnd((getBitwiseShiftLeft(dbBitFieldValues[v].getValue(), (fai * itemWidth))), itemMask) == bitFieldValueXItemMask) {
                                bfVal = getBitFieldArrayValueXStr(dbBitFieldValues, bitFieldValueXItemMask >>> (fai * itemWidth)).replace('x',fai);
                                bfDescr = dbBitFields[fi].getDescription() + ": " + dbBitFieldValues[v].getDescription();
                                switch (action) {
                                  case "print":
                                    bitFieldSetMasksString.push(getBitFieldSetMaskString(dbBitFields[fi], bitFieldValueX, bfVal, bfDescr));
                                    break;
                                  case "constantDefinitions":
                                    bfValValue = getBitwiseShiftLeft(dbBitFieldValues[v].getValue(), (fai * itemWidth));
                                    registerConstantDefinition(bfVal, bfVal, bfValValue, bfDescr, 'mask', configurationConstantDefinitionList);
                                    break;
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                  else {
                    bitFieldClrMasksString.push(getBitFieldMaskStr(dbBitFields[fi]));
                    if (!testMode && action == "print" && registerName.indexOf(portControlRegisterName) >= 0 && bitFieldName == pinMuxControlBitName) {
                      if (!isPinDisabled(reg.registerName, portMuxMask)) {
                        var comment = 'PORT' + getGpioInitialsStr(reg.registerName) + ' (pin ' + getSelectedPinCoordinatesStr(reg.registerName, portMuxMask) + ') is configured as ' + getSelectedPinNamePartStr(reg.registerName, portMuxMask);
                      }
                      else {
                        var comment = 'PORT' + getGpioInitialsStr(reg.registerName) + ' (pin ' + getSelectedPinCoordinatesStr(reg.registerName, portMuxMask) + ') is disabled';
                      }
                      bfDescr = dbBitFields[fi].getDescription() + ": " + comment;
                    }
                    if (dbBitFieldValues != null) {         
                      for (var v = 0; v < dbBitFieldValues.length; v++) {
                        if (dbBitFieldValues[v].getValue() == bitFieldValueX) {
                          bfVal = dbBitFieldValues[v].getName();
                          bfValValue = dbBitFieldValues[v].getValue().doubleValue();
                        }
                      }
                    }
                    if (bfDescr == "") {
                      bfDescr = getBitFieldSetMaskDescription(dbBitFieldValues,bitFieldValueX,dbBitFields[fi].getDescription());
                    }                
                    switch (action) {
                      case "print":
                        bitFieldSetMasksString.push(getBitFieldSetMaskString(dbBitFields[fi], bitFieldValueX, bfVal, bfDescr));
                        break;
                      case "constantDefinitions":
                        if (bfVal != "") {
                          registerConstantDefinition(bfVal, bfVal, bfValValue, bfDescr, 'mask', configurationConstantDefinitionList);
                        }
                        break;
                    }
                  }
                }
              }
              switch (action) {
                case "print":
                  var bitFieldClrMasksJoinedString = bitFieldClrMasksString.join(" | ");
                  var accessRegisterName = getRegisterNameStr(reg.registerName);
                  PExOut.gen(cIndent2 + accessRegisterName + ' = ((' + accessRegisterName + ' &');
                  PExOut.gen(addCCodeComment((cIndent4 + '(~(' + bitFieldClrMasksJoinedString + ')))'), 'Mask bits to zero which are setting'));
                  for (var mi = 0; mi < bitFieldSetMasksString.length; mi++) {
                    PExOut.gen(bitFieldSetMasksString[mi]);          
                  }
                  PExOut.gen(cIndent4 + ');');
                  break;
              }
            }
            else {
              PExOut.gen(cIndent2 + "/* There is no register " + reg.registerName + " in register database. */");          
            }
          }
        }
        if (retValue != '') {
          return retValue;
        }
}


// List of peripherals which are related to pin muxing. Do not add normal peripherals like ADC, TPM, PDB, etc. No register shoul be initialized because of pin muxing.
// If this happens then a message is logged. Launching "Generate All Pins Configuration" action in the tool and taking a look into log is good to check a signal_configuration.xml on this.
var enableClockTable = {
  "IOMUXC": {"state": "kCLOCK_Iomuxc", "comment": ""},
  "DMAMUX": {"state": "kCLOCK_Dma", "comment": ""},
  "IOMUXC_SNVS": {"state": "kCLOCK_IomuxcSnvs", "comment": ""},
  "XBARA1": {"state": "kCLOCK_Xbar1", "comment": ""},
  "XBARB2": {"state": "kCLOCK_Xbar2", "comment": ""},
  "XBARB3": {"state": "kCLOCK_Xbar3", "comment": ""},
}
/**
 * Puts calling CLOCK_EnableClock including const data structure which defines pin functional properties and pin muxing into output 
 * accessRegs - reference to registers to be configured with theirs values
 * return no value; just prining into ouput
 */
function printEnableClock(accessRegs) {
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var clockGateName = reg.registerName;
  var enableClockTableItem = enableClockTable[clockGateName];
  if (enableClockTableItem != null) {
    var comment = enableClockTableItem.comment;
    if (comment == "") {
      comment = reg.comment;
      /* Fix naming issue: IPMUX1 shall be IOMUX1 */
      comment = comment.replace(/IPMUX/,'IOMUX');

    }
    PExOut.gen(addCCodeComment(cIndent2 + 'CLOCK_EnableClock(' + enableClockTableItem.state + ');', comment));  // HOTFIX: Fixed enable clock comment alignment
    reg.writeFunctions = null;
  }
  else {
    
    PExOut.log('The peripheral ' + clockGateName + ' is not in clock gate table. Probably in generated code, there is configured register which should not be (e.g. of ADC, TPM, PDB,...). Then check processor data. If not then enableClockTable should be updated in pins tool driver.');
    if (testMode) {
      PExOut.gen(cIndent2 + '#error The peripheral ' + clockGateName + ' is not in clock gate table. Probably in generated code, there is configured register which should not be (e.g. of ADC, TPM, PDB,...). Then check processor data. If not then enableClockTable should be updated in pins tool driver.');
    }
  }
}


/**
 * Registers using SDK function CLOCK_EnableClock 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions) 
 * return no value
 */
function enrolEnableClock (reg, writeFunctions) {
  var writeFunc = new Object();
  writeFunc.printFunction = printEnableClock;
  writeFunc.accessRegisters = new Array();
  var accessRegister = new Object();
  accessRegister.register = reg;
  writeFunc.accessRegisters.push(accessRegister);
  var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
  reg.registerClrMask = 0;
  reg.registerSetMask = 0;
  if (reg.writeFunctions == null) {
    reg.writeFunctions = new Array();
  }
  reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
}

/**
 * Puts calling XBAR_SetSignalsConnection  
 * accessRegs - reference to registers to be configured with theirs values
 * return no value; just prining into ouput
 */
function printXbarSetSignalsConnection (accessRegs) {
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var registerName = reg.registerName;
  var dbPeripheralName = getDbPeripheralByFullNameStr(registerName);  // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName).getName();
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var registerClrSetMask = getBitwiseOr(accessRegister.clrMask, accessRegister.setMask);
  var dbBitFields = dbRegister.getBitFields();
  var orValue = '0x100';
  if (xbarModulesAB) {
    if (dbPeripheralName == 'XBARB2') {
      var xbarModulePrefix = 'XBARB';
      orValue = '0x200';
    }
    else if (dbPeripheralName == 'XBARB3') {
      var xbarModulePrefix = 'XBARB';
      orValue = '0x300';
    }
    else {
      var xbarModulePrefix = 'XBARA';
    }    
  }
  else {
    var xbarModulePrefix = 'XBAR';
  }
  for (var fi = 0; fi < dbBitFields.length; fi++) {
    var bitFieldMask = dbBitFields[fi].getRegisterMask().doubleValue();
    if (getBitwiseAnd(bitFieldMask, registerClrSetMask) > 0) {
      var bitFieldName = dbBitFields[fi].getName();
      var bitFieldValueX = getBitwiseAnd(accessRegister.setMask, bitFieldMask) >>> dbBitFields[fi].getOffset();
      var input = xbarInputSignal[dbPeripheralName][(bitFieldValueX + '|' + orValue).valueOf()];
      var otuputIndex = bitFieldName.substring(bitFieldName.indexOf(xbarSelRegisterName) + xbarSelRegisterName.length);
      var output = xbarOutputSignal[dbPeripheralName][(otuputIndex + '|' + orValue).valueOf()];
      if (input != null && output != null) {  
        var bfDescr = "";
        bfDescr = removeLastDotFromDescription(input[0].description) + ' is connected to ' + removeLastDotFromDescription(output[0].description);
        PExOut.gen(addCCodeComment(cIndent2 + xbarModulePrefix + '_SetSignalsConnection(' + dbPeripheralName + ', ' + input[0].id + ', ' + output[0].id + ');', bfDescr));
      }
      else {
        logMessage("Unexpected status during SDK function XBAR_SetSignalsConnection printing.", false);
      }
    }
  }
  reg.writeFunctions = null;
}


/**
 * Registers using SDK function XBAR_SetSignalsConnection 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions) 
 * pc - index of pin configuration (routing function/Pins component)
 * return no value
 */
function enrolXbarSetSignalsConnection (reg, writeFunctions, pc) {
  var registerName = reg.registerName;
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  if (xbarInputSignal != null && xbarOutputSignal != null && registerName.indexOf(xbarPeripheralName) >= 0 && registerName.indexOf(xbarSelRegisterName) >= 0 && registerName.indexOf('IOMUX') < 0) {
    var writeFunc = new Object();
    writeFunc.printFunction = printXbarSetSignalsConnection;
    writeFunc.accessRegisters = new Array();
    var accessRegister = new Object();
    accessRegister.register = reg;
    accessRegister.clrMask = reg.registerClrMask;
    accessRegister.setMask = reg.registerSetMask;
    writeFunc.accessRegisters.push(accessRegister);
    var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
    reg.registerClrMask = 0;
    reg.registerSetMask = 0;
    if (reg.writeFunctions == null) {
      reg.writeFunctions = new Array();
    }
    reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
    if (xbarModulesAB) {
      if (registerName.indexOf(xbarPeripheralName + 'A') >= 0) {
        include_fsl_xbara['present'] = true;
        include_fsl_xbara['pcs'].push(pc);
      }
      else {
        include_fsl_xbarb['present'] = true;
        include_fsl_xbarb['pcs'].push(pc);
      }
    }
    else {
      include_fsl_xbar['present'] = true;
      include_fsl_xbar['pcs'].push(pc);
    }
  }
}


var xbarActiveEdgeTable = {
  "0": {"state": "_EdgeNone", "description": "Edge detection status bit never asserts"}, 
  "1": {"state": "_EdgeRising", "description": "Edge detection status bit asserts on rising edges"}, 
  "2": {"state": "_EdgeFalling", "description": "Edge detection status bit asserts on falling edges"}, 
  "3": {"state": "_EdgeRisingAndFalling", "description": "Edge detection status bit asserts on rising and falling edges"}, 
}
var xbarRequestTypeTable = {
  "0": {"state": "_RequestDisable", "description": "Interrupt and DMA are disabled"}, 
  "1": {"state": "_RequestDMAEnable", "description": "DMA enabled, interrupt disabled"}, 
  "2": {"state": "_RequestInterruptEnalbe", "description": "Interrupt enabled, DMA disabled"}, 
}

/**
 * Puts calling XBAR_SetOutputSignalConfig  
 * accessRegs - reference to registers to be configured with theirs values
 * return no value
 */
function printXbarSetOutputSignalConfig (accessRegs) {
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var registerName = reg.registerName;
  var dbPeripheralName = getDbPeripheralByFullNameStr(registerName);  // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName).getName();
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var registerClrSetMask = getBitwiseOr(accessRegister.clrMask, accessRegister.setMask);
  var dbBitFields = dbRegister.getBitFields();
  var offset = 8;
  var configurableMask = 0x0F;
  if (xbarModulesAB) {
    if (dbPeripheralName == 'XBARB') {
      var xbarModulePrefix = 'XBARB';
    }
    else {
      var xbarModulePrefix = 'XBARA';
    }    
  }
  else {
    var xbarModulePrefix = 'XBAR';
  }
  var orValue = '0x100';
  if (dbPeripheralName == 'XBARB') {
    orValue = '0x200';
  }  
  for (var i = 0; i < 2; i++) {
    if (getBitwiseAnd(registerClrSetMask, (getBitwiseShiftLeft(configurableMask, (offset * i)))) > 0) {
      for (var fi = 0; fi < dbBitFields.length; fi++) {
        var bitFieldMask = dbBitFields[fi].getRegisterMask().doubleValue();
        var bitFieldName = dbBitFields[fi].getName();
        if (bitFieldMask == getBitwiseShiftLeft(0x01, (offset * i))) {
          var otuputIndex = bitFieldName.substring(bitFieldName.length() - 1);
          var output = xbarOutputSignal[dbPeripheralName][(otuputIndex + '|' + orValue).valueOf()];
          var bitFieldValueX = getBitwiseAnd(accessRegister.setMask, bitFieldMask) >>> dbBitFields[fi].getOffset();
        }
        if (bitFieldMask == getBitwiseShiftLeft(0x02, (offset * i))) {
          bitFieldValueX = getBitwiseOr(bitFieldValueX, getBitwiseShiftLeft(getBitwiseAnd(accessRegister.setMask, bitFieldMask) >>> dbBitFields[fi].getOffset(), 1));
          var requestType = xbarRequestTypeTable[bitFieldValueX];
        }
        if (bitFieldMask == getBitwiseShiftLeft(0x0C, (offset * i))) {
          var bitFieldValueX = getBitwiseAnd(accessRegister.setMask, bitFieldMask) >>> dbBitFields[fi].getOffset();
          var activeEdge = xbarActiveEdgeTable[bitFieldValueX];
        }
      }
      if (output != null && requestType != null  && activeEdge != null) {
        PExOut.gen(addCCodeComment(cIndent2 + xbarModulePrefix + '_SetOutputSignalConfig(' + dbPeripheralName + ', ' + output[0].id + ',', 'Configure ' + removeLastDotFromDescription(output[0].description)));
        PExOut.gen(cIndent4 + '&((' + (xbarModulePrefix).toLowerCase() + '_control_config_t){');
        PExOut.gen(addCCodeComment(cIndent6 + '.activeEdge = k' + xbarModulePrefix + activeEdge.state + ',', activeEdge.description));
        PExOut.gen(addCCodeComment(cIndent6 + '.requestType = k' + xbarModulePrefix + requestType.state, requestType.description));
        PExOut.gen(cIndent2 + '}));');
      }
      else {
        logMessage("Unexpected status during SDK function XBAR_SetOutputSignalConfig printing.", false);
      }
    }
  }  
  reg.writeFunctions = null;
} 
  
  
/**
 * Registers using SDK function XBAR_SetOutputSignalConfig 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions)
 * pc - index of pin configuration (routing function/Pins component)
 * return no value
 */
function enrolXbarSetOutputSignalConfig(reg, writeFunctions, pc) {
  var registerName = reg.registerName;
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var configurableMask = 0x0F0F;
  if (xbarInputSignal != null && xbarOutputSignal != null && registerName.indexOf(xbarPeripheralName) >= 0 && registerName.indexOf(xbarControlRegisterName) >= 0) {
    var writeFunc = new Object();
    writeFunc.printFunction = printXbarSetOutputSignalConfig;
    writeFunc.accessRegisters = new Array();
    var accessRegister = new Object();
    accessRegister.register = reg;
    accessRegister.clrMask = reg.registerClrMask;
    accessRegister.setMask = reg.registerSetMask;
    writeFunc.accessRegisters.push(accessRegister);
    var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
    reg.registerClrMask = getBitwiseAnd(reg.registerClrMask, getBitwiseNeg32(configurableMask));
    reg.registerSetMask = getBitwiseAnd(reg.registerSetMask, getBitwiseNeg32(configurableMask));
    if (reg.writeFunctions == null) {
      reg.writeFunctions = new Array();
    }
    reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
    include_fsl_xbar['present'] = true;
    include_fsl_xbar['pcs'].push(pc);
  }
}
/**
 * Puts calling DMAMUX_SetSource into output 
 * accessRegs - reference to registers to be configured with values
 * return no value; just prining into ouput
 */
function printDmaMuxSetSource(accessRegs) {
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var registerName = reg.registerName;
  var dbPeripheralName = getDbPeripheralByFullNameStr(registerName);  // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName).getName();
  var channel = accessRegister.channel;
  var source = accessRegister.source;
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var dbBitFields = dbRegister.getBitFields();
  var orValue = '0x100';
  var peripheralName = null;
  
  peripheralName = dmaMuxPeripheralName;

  PExOut.log('DMA  ' + peripheralName);
  var requestSource = dmaRequestSource[peripheralName][(source.toString() + '|' + orValue.toString()).valueOf()];
  if (requestSource != null) {
    var selectedRequestSource = requestSource[0];
    // If there is more enums with the same values, then the longest enum id containing name of routed peripheral is choosen. 
    // If there is no enum id containing routed peripheral name then the longest enum id is selected. 
    if (requestSource.length > 1) {
      var routedPeripheralNames = getRoutedPeripheralNames(registerName, accessRegister.configurableMask);
      var enums = new Array();
      for (var p = 0; p < routedPeripheralNames.length; p++) {
        for (var e = 0; e < requestSource.length; e++) {
          if (requestSource[e].id.indexOf(routedPeripheralNames[p]) >= 0) {
            if (enums.indexOf(requestSource[e]) == -1) {
              enums.push(requestSource[e]);
            }
          }
        }
      }
      if (enums.length == 1) {
        var selectedRequestSource = enums[0];
      }
      else {  
        if (enums.length > 1) {
          var enumsKeys = Object.keys(enums).sort(function(a,b){
            return (enums[a].id.length - enums[b].id.length);
          });
          selectedRequestSource = enums[enumsKeys[enumsKeys.length - 1]];
        }
        else {  //if (enums.length < 1)
          var requestSourceKeys = Object.keys(requestSource).sort(function(a,b){
            return (requestSource[a].id.length - requestSource[b].id.length);
          });
          selectedRequestSource = requestSource[requestSourceKeys[requestSourceKeys.length - 1]];
        }
      }
    }
  }
  if (selectedRequestSource != null) { 
    var bfDescr = '';
    for (var fi = 0; fi < dbBitFields.length; fi++) {
      var bitFieldMask = dbBitFields[fi].getRegisterMask().doubleValue();
      if (getBitwiseAnd(bitFieldMask, dmaMuxSourceBitMask) > 0) {
        bfDescr = dbBitFields[fi].getDescription() + " " + channel +': ' + selectedRequestSource.description;
      }
    }
    PExOut.gen(addCCodeComment(cIndent2 + 'DMAMUX_SetSource(' + dbPeripheralName + ', DMA_CHANNEL' + channel + '_IDX, (uint8_t)' + selectedRequestSource.id + ');', bfDescr));
    //PExOut.gen(addCCodeComment(cIndent2 + 'DMAMUX_SetSource(' + dbPeripheralName + ', DMA_CHANNEL' + channel + '_IDX, ' + selectedRequestSource.id + ');', bfDescr));
  }
  reg.writeFunctions = null;
}


/**
 * Registers using SDK function DMAMUX_SetSource 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions) 
 * configurationConstantDefinitionList - given configuration where constant definitions are added
 * pc - index of pin configuration (routing function/Pins component)
 * return no value
 */
function enrolDmaMuxSetSource(reg, writeFunctions, configurationConstantDefinitionList, pc) {
  var registerName = reg.registerName;

  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var configurableMask = dmaMuxSourceBitMask;
  var writeFunc = new Object();
  if ((dmaRequestSource != null) && (registerName.indexOf(dmaMuxPeripheralName) >= 0)  && (registerName.indexOf(dmaMuxChannelConfigRegisterName) >= 0)) {
    var setValMask = getBitwiseAnd(getBitwiseOr(reg.registerClrMask, reg.registerSetMask), configurableMask);
    if (getBitwiseXor(setValMask, configurableMask) == 0) {
      var setValue = getBitwiseAnd(reg.registerSetMask, setValMask);
      var channel = registerName.substring(registerName.indexOf(dmaMuxChannelConfigRegisterName) + dmaMuxChannelConfigRegisterName.length);
      var source = getBitwiseAnd(setValue, dmaMuxSourceBitMask) >>> dmaMuxSourceBitOffset;
      registerConstantDefinition('DMA_CHANNEL' + normalizeNumberStr(channel) + '_IDX', 'DMA_CHANNEL' + channel + '_IDX', channel, 'Channel number for DMA channel ' + channel, 'index', configurationConstantDefinitionList);
      //registerConstantDefinition('DMA_REQUEST' + normalizeNumberStr(source) + '_IDX', 'DMA_REQUEST' + source + '_IDX', source, 'Channel source ' + source + ' which is used to trigger DMA transfer', 'index', configurationConstantDefinitionList);
      writeFunc.printFunction = printDmaMuxSetSource;
      writeFunc.accessRegisters = new Array();
      var accessRegister = new Object();
      accessRegister.register = reg;
      accessRegister.setValue = setValue;
      accessRegister.configurableMask = configurableMask;
      accessRegister.channel = channel;
      accessRegister.source = source;
      writeFunc.accessRegisters.push(accessRegister);
      if (writeFunctions != null)
      {
          var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
          if (reg.writeFunctions == null) 
          {
              reg.writeFunctions = new Array();
          }
          reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
      }

      reg.registerClrMask = getBitwiseAnd(reg.registerClrMask, getBitwiseNeg32(configurableMask));
      reg.registerSetMask = getBitwiseAnd(reg.registerSetMask, getBitwiseNeg32(configurableMask));

      include_fsl_dmamux['present'] = true;
      include_fsl_dmamux['pcs'].push(pc);
    }
  }
}

/**
 * Puts calling IOMUXC_SetPinMux into output 
 * accessRegs - reference to registers to be configured with values
 * return no value; just prining into ouput
 */
function printIomuxcSetPinMux(accessRegs) {
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var registerName = reg.registerName;
  var dbPeripheralName = getDbPeripheralByFullNameStr(registerName);  // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName).getName();
  var dbRegister = registerDatabaseObject.getRegisterByFullName(registerName);
    // prepare print data as expanded bit field value modififation writes into specified register(s), i.e. correspond to legacy IOMUX tool output

  var regDbBitFields = dbRegister.getBitFields();

  var regMacroData = new Array();  // register data object containing the lines of code and its comment, it will be printed into the output file
  // process all register bit fields
    
    for (var fi = 0; fi < regDbBitFields.length; fi++) {
        var bfName = regDbBitFields[fi].getName();

        var bfMaskVal = regDbBitFields[fi].getRegisterMask().longValue();
        
        var bfMaskHex = getNumberConvertedToHex(bfMaskVal, false);
        
        var bfLineStr = new Object(); //line data object containing the one line of code and comment for specific bit field 
        //
        
        var bitField = dbRegister.findBitFieldByName(bfName); // search for bit field by name
        //PExOut.log('second' + reg.registerSetMask);
        var bitValDb = bitField.findValueByRegisterValue(new BigInteger(reg.registerSetMask)); // find bit field value written by set value
        //PExOut.log('dbPeripheralName: '+ dbPeripheralName);
        if (bitValDb != null) {
            if(registerName.indexOf('SW_MUX_CTL') >= 0)
            {
                switch (bfName) {
                case "MUX_MODE":
                    //bfLineStr.code = 'IOMUXC_' + getPadName(dbRegister.registerName) +'_'+ getSelectedPinNamePartStr(dbRegister.registerName, 0xf);
                    if(registerName.indexOf('IOMUXC_SNVS') == 0)
                    {
                        bfLineStr.code = 'IOMUXC_SNVS_' + getPadName(registerName) +'_'+ getNamePartStr(bitValDb.getDescription());
                    }
                    else
                    {
                        bfLineStr.code = 'IOMUXC_' + getPadName(registerName) +'_'+ getNamePartStr(bitValDb.getDescription());
                    }
                    // bfLineStr.code = 'IOMUXC_' + getPadName(registerName) +'_'+ getNamePartStr(bitValDb.getDescription());
                    bfLineStr.comment = getPadName(registerName) + ' is configured as ' + getNamePartStr(bitValDb.getDescription());
                    PadFuncIDArray.push(bfLineStr.code);
                    break;
                case "SION":
                    //bfLineStr.code = bitValDb.getValue().toString(10) + 'U';
                    bfLineStr.code = bitValDb.getValue().toString() + 'U';  // HOTFIX: Can we use just toString() here ??? Expecting bitValDb.getValue() already is decimal number - confirmation required!
                    bfLineStr.comment = bitField.getDescription().replace(' Field.', ' Field') + ': ' + bitValDb.getDescription().split('.')[0];
                    break;
                default:
                    break;
              }
               //bfLineStr.comment = bitField.getDescription().replace(' Field.', ' Field') + ': ' + bitValDb.getDescription().split('.')[0];
               regMacroData.push(bfLineStr); // store bit field related line content for printing ...
            }
        }
      }
  // var gpioNameIndex = getGpioInitialsStr(registerName);
  // var coordinates = getSelectedPinCoordinatesStr(registerName, portMuxMask);
  // var configTableMask = setPinConfigTable[pinMuxControlBitMask];
  // var configTableMaskValueState = configTableMask[(getBitwiseAnd(accessRegister.setValue, pinMuxControlBitMask) >>> configTableMask.offset)].state;
  // if (!isPinDisabled(registerName, portMuxMask)) {
    // var comment = 'PORT' + gpioNameIndex + ' (pin ' + coordinates + ') is configured as ' + getSelectedPinNamePartStr(registerName, portMuxMask);
  // }
  // else {
    // var comment = 'PORT' + gpioNameIndex + ' (pin ' + coordinates + ') is disabled';
  // }
  //PExOut.gen(addCCodeComment(cIndent2 + 'IOMUXC_SetPinMux(' + regMacroData[0].code + ', ' + regMacroData[1].code + ');', regMacroData[0].comment + ';' + regMacroData[1].comment));
  printRegisterMacro('IOMUXC_SetPinMux(', null, regMacroData); // print complete register macro content
  reg.writeFunctions = null;
}

/**
 * Registers using SDK function IOMUXC_SetPinMux 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions) 
 * configurationConstantDefinitionList - given configuration where constant definitions are added
 * pc - index of pin configuration (routing function/Pins component)
 * return no value
 */
function enrolIomuxcSetPinMux(reg, writeFunctions, configurationConstantDefinitionList, pc) {
  var registerName = reg.registerName;
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var configurableMask = pinMuxControlBitMask;
  var writeFunc = new Object();
  if ((registerName.indexOf(iomuxcControlRegisterName) >= 0) || ( (registerName.indexOf(iomuxc_snvs_ControlRegisterName) >= 0))) {
    var setValMask = getBitwiseAnd(getBitwiseOr(reg.registerClrMask, reg.registerSetMask), configurableMask);
    if (getBitwiseXor(setValMask, configurableMask) == 0) {
      //var defValue = getGpioIndexStr(registerName);
      //registerConstantDefinition('PIN' + normalizeNumberStr(defValue) + '_IDX', 'PIN' + defValue + '_IDX', defValue, 'Pin number for pin ' + defValue + ' in a port', 'index', configurationConstantDefinitionList);
      writeFunc.printFunction = printIomuxcSetPinMux;
      writeFunc.accessRegisters = new Array();
      var accessRegister = new Object();
      accessRegister.register = reg;
      accessRegister.setValue = getBitwiseAnd(reg.registerSetMask, setValMask);
      accessRegister.configurableMask = configurableMask;
      writeFunc.accessRegisters.push(accessRegister);
      var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
      //reg.registerClrMask = getBitwiseAnd(reg.registerClrMask, getBitwiseNeg32(pinMuxControlBitMask));
      //reg.registerSetMask = getBitwiseAnd(reg.registerSetMask, getBitwiseNeg32(pinMuxControlBitMask));
      if (reg.writeFunctions == null) {
        reg.writeFunctions = new Array();
      }
      reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
      include_fsl_iomuxc['present'] = true;
      include_fsl_iomuxc['pcs'].push(pc);
    }
  }
}


var trgmuxTriggerInputTable = {
  "0": {"state": "kTRGMUX_TriggerInput0", "description": "The MUX select for peripheral trigger input 0"}, 
  "1": {"state": "kTRGMUX_TriggerInput1", "description": "The MUX select for peripheral trigger input 1"}, 
  "2": {"state": "kTRGMUX_TriggerInput2", "description": "The MUX select for peripheral trigger input 2"}, 
  "3": {"state": "kTRGMUX_TriggerInput3", "description": "The MUX select for peripheral trigger input 3"}, 
}

/**
 * Puts calling TRGMUX_SetTriggerSource  
 * accessRegs - reference to registers to be configured with theirs values
 * return no value; just prining into ouput
 */
function printTrgmuxSetTriggerSource(accessRegs) {
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var registerName = reg.registerName;
  var dbPeripheralName = getDbPeripheralByFullNameStr(registerName);  // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName).getName();
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var registerClrSetMask = getBitwiseOr(accessRegister.clrMask, accessRegister.setMask);
  var dbBitFields = dbRegister.getBitFields();
  for (var fi = 0; fi < dbBitFields.length; fi++) {
    var bitFieldMask = dbBitFields[fi].getRegisterMask().doubleValue();
    if (getBitwiseAnd(bitFieldMask, registerClrSetMask) > 0) {
      var bitFieldName = dbBitFields[fi].getName();
      if (bitFieldName.indexOf(trgmuxSelBitFieldName) >= 0) {
        var bitFieldValueX = getBitwiseAnd(accessRegister.setMask, bitFieldMask) >>> dbBitFields[fi].getOffset();
        var registerAlias = getRegisterNameStr(registerName);
        var deviceIndex = registerAlias.substring(registerAlias.indexOf(trgmuxRegisterAlias) + trgmuxRegisterAlias.length, registerAlias.indexOf(']'));
        var device = trgmuxDevice[dbPeripheralName][deviceIndex];
        var inputIndex = bitFieldName.substring(bitFieldName.indexOf(trgmuxSelBitFieldName) + trgmuxSelBitFieldName.length);
        var input = trgmuxTriggerInputTable[inputIndex];
        var source = trgmuxSource[dbPeripheralName][bitFieldValueX];
        if (device != null && input != null && source != null) {  
          var bfDescr = "";
          bfDescr = removeLastDotFromDescription(source[0].description) + ' as ' + removeLastDotFromDescription(device[0].description) + ' ' + inputIndex;
          PExOut.gen(addCCodeComment(cIndent2 + 'TRGMUX_SetTriggerSource(' + dbPeripheralName + ', ' + device[0].id + ', ' + input.state + ', ' + source[0].id + ');', bfDescr));
        }
        else {
          PExOut.log("Unexpected status during SDK function TRGMUX_SetTriggerSource printing.", false);
        }
      }
    }
  }
  reg.writeFunctions = null;
}


/**
 * Registers using SDK function TRGMUX_SetTriggerSource 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions) 
 * configurationConstantDefinitionList - given configuration where constant definitions are added
 * pc - index of pin configuration (routing function/Pins component)
 * return no value
 */
function enrolTrgmuxSetTriggerSource(reg, writeFunctions, configurationConstantDefinitionList, pc) {
  var registerName = reg.registerName;
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  if (trgmuxDevice != null && trgmuxSource != null && registerName.indexOf(trgmuxPeripheralName) >= 0) {
    var writeFunc = new Object();
    writeFunc.printFunction = printTrgmuxSetTriggerSource;
    writeFunc.accessRegisters = new Array();
    var accessRegister = new Object();
    accessRegister.register = reg;
    accessRegister.clrMask = reg.registerClrMask;
    accessRegister.setMask = reg.registerSetMask;
    writeFunc.accessRegisters.push(accessRegister);
    var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
    reg.registerClrMask = 0;
    reg.registerSetMask = 0;
    if (reg.writeFunctions == null) {
      reg.writeFunctions = new Array();
    }
    reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
    include_fsl_trgmux['present'] = true;
    include_fsl_trgmux['pcs'].push(pc);
  }
}

/**
 * Puts calling IOMUXC_SetPinConfig into output 
 * accessRegs - reference to registers to be configured with values
 * return no value; just prining into ouput
 */
function printIomuxcSetPinConfig(accessRegs) {
    
  var accessRegister = accessRegs[0];
  var reg = accessRegister.register;
  var registerName = reg.registerName;
  
  //PExOut.log('second' + reg.registerName);
  if(registerName.indexOf('SW_PAD_CTL') >= 0)
    {
        var comment = '';
        var commentArray = new Array();
        var dbRegister = registerDatabaseObject.getRegisterByFullName(registerName);
        var regDbBitFields = dbRegister.getBitFields();

        var regMacroData = new Array();  // register data object containing the lines of code and its comment, it will be printed into the output file
        // process all register bit fields
        // PExOut.log('[Debug]:' + reg.registerName + '  ' + reg.registerSetMask + '   ');
        var regMask = 0xFFFFFFFF;
        var setValue = (getResetValue(dbRegister) & (regMask ^ reg.registerClrMask)) | (reg.registerSetMask); // full value used for 'WR' macro
        for (var fi = 0; fi < regDbBitFields.length; fi++) {
            var bfName = regDbBitFields[fi].getName();
            var bfValues = regDbBitFields[fi].getValues();
            if (bfValues.length > 0) {
              var bfMaskVal = regDbBitFields[fi].getRegisterMask().longValue();
              var bfValue = getBitwiseAnd(setValue, bfMaskVal) >>> regDbBitFields[fi].getOffset();
              var bfDesc = getBitFieldValueDescription(bfValues, bfValue); //HOTFIX: get bfValue description by real value instead of using as index for bfValues[bfValue].getDescription();
              var bfLineStr = new Object(); //line data object containing the one line of code and comment for specific bit field
              var bitField = dbRegister.findBitFieldByName(bfName); // search for bit field by name
              comment = bitField.getDescription().replace(' Field.', ' Field') + ': ' + bfDesc;
              commentArray.push(comment);
            }
        }
        var padName = getPadName(registerName);
        var macroFound = 'no';
        for (var i in PadFuncIDArray)
        {
        if (PadFuncIDArray[i].indexOf(padName) >= 0)
        {
            bfLineStr.code = PadFuncIDArray[i];
            bfLineStr.comment = padName + ' PAD functional properties :';
            regMacroData.push(bfLineStr);
            macroFound = 'yes';
            break;
        }
        }
        if (macroFound == 'no')
        {
            if(registerName.indexOf('IOMUXC_SNVS') == 0)
            {
            bfLineStr.code = 'IOMUXC_SNVS_' + padName;
            }
            else
            {
            bfLineStr.code = 'IOMUXC_' + padName;    
            }
            bfLineStr.comment = padName +' PAD functional properties :';
            regMacroData.push(bfLineStr);
        }
        var bfLineStr = new Object();
        bfLineStr.code = getNumberConvertedToHex(setValue,false);
        //PExOut.log('reach here' + bfLineStr.code);
        bfLineStr.comment = commentArray.join('\r\n'+ cIndent16 + cIndent16 + cIndent16 + ' ');
        regMacroData.push(bfLineStr);
        printRegisterMacro('IOMUXC_SetPinConfig(', null, regMacroData); // print complete register macro content
        reg.writeFunctions = null;
    }

}


/**
 * Registers using SDK function IOMUXC_SetPinConfig 
 * reg - register defined by name, clr mask and set mask
 * writeFunctions - reference to writeFunctions array (collection of data for SDK write functions) 
 * configurationConstantDefinitionList - given configuration where constant definitions are added
 * pc - index of pin configuration (routing function/Pins component)
 * return no value
 */
function enrolIomuxcSetPinConfig(reg, writeFunctions, configurationConstantDefinitionList, pc) {
  var registerName = reg.registerName;
  
  var dbRegister = registerDatabaseObject.getRegisterByFullName(reg.registerName);
  var configurableMask = pinMuxControlBitMask;
  var writeFunc = new Object();
  if ((registerName.indexOf(iomuxcPadControlRegisterName) >= 0) || (registerName.indexOf(iomuxc_snvsPadControlRegisterName) >= 0) ) {
    //  PExOut.log('hlherer' + registerName);
    var setValMask = getBitwiseAnd(getBitwiseOr(reg.registerClrMask, reg.registerSetMask), configurableMask);

    //var defValue = getGpioIndexStr(registerName);
    //registerConstantDefinition('PIN' + normalizeNumberStr(defValue) + '_IDX', 'PIN' + defValue + '_IDX', defValue, 'Pin number for pin ' + defValue + ' in a port', 'index', configurationConstantDefinitionList);
    writeFunc.printFunction = printIomuxcSetPinConfig;
    writeFunc.accessRegisters = new Array();
    var accessRegister = new Object();
    accessRegister.register = reg;
    accessRegister.setValue = getBitwiseAnd(reg.registerSetMask, setValMask);
    accessRegister.configurableMask = configurableMask;
    writeFunc.accessRegisters.push(accessRegister);
    var writeFunctionsIndex = writeFunctions.push(writeFunc) - 1;
    //reg.registerClrMask = getBitwiseAnd(reg.registerClrMask, getBitwiseNeg32(pinMuxControlBitMask));
    //reg.registerSetMask = getBitwiseAnd(reg.registerSetMask, getBitwiseNeg32(pinMuxControlBitMask));
    if (reg.writeFunctions == null) {
    reg.writeFunctions = new Array();
    }
    reg.writeFunctions.push(writeFunctions[writeFunctionsIndex]);
    include_fsl_iomuxc['present'] = true;
    include_fsl_iomuxc['pcs'].push(pc);

  }
}

/** 
 * Prints constant definitions for one configuration
 * configuration - given configuration where constant definitions is added
 * return value - no data; just printing into output 
 */
function printOneDefinitionConstantSet(configuration) {
      var printedAnything = false;
      var configurationConstantDefinitionList = constantDefinitionList[configuration];
      var configurationConstantDefinitionKeys = Object.keys(configurationConstantDefinitionList).sort();
      for (var d = 0; d < configurationConstantDefinitionKeys.length; d++) {
        var configurationConstantDefinition = configurationConstantDefinitionList[configurationConstantDefinitionKeys[d]];
        var defName = configurationConstantDefinition.name;
        if (configurationConstantDefinition.indexType == null) {
          var value = getNumberConvertedToHex(configurationConstantDefinition.value);
        }
        else {
          var value = configurationConstantDefinition.value + 'u';
        }
        var defLine = getConstantDefinitionStr(defName, value, configurationConstantDefinition.comment);
        if (defName in printedConstantDefinitionList) {
          if (avoidDefineRedefinition) {
            PExOut.gen("// " + defLine);
          }
          else {
            PExOut.gen(defLine);
          }
        }
        else {
          PExOut.gen(defLine);
          printedConstantDefinitionList[defName] = configuration;
          printedAnything = true;
        }
      }
      return printedAnything;
}


/**
 * Print a clock register 
 * reg - register defined by name, clr mask and set mask
 * return no value
 */
function printClockRegister(reg) {
        if (codeStyle == "SDK") {      //MUX bity/ SDK funkce
          var writeClockFunctions = reg.writeFunctions;
          if (writeClockFunctions != null) {
            for (var wf=0; wf < writeClockFunctions.length; wf++) {
              writeClockFunctions[wf].printFunction(writeClockFunctions[wf].accessRegisters);
            }
          } 
        }
}

/**
 * Print a register 
 * reg - register defined by name, clr mask and set mask
 * return no value
 */
function printRegister(reg) {
    
    if (codeStyle == "SDK") {
          var writeFunctions = reg.writeFunctions;
          //PExOut.log('123r5234 is ');
          if (writeFunctions != null) {
            for (var wf=0; wf < writeFunctions.length; wf++) {
                //PExOut.log('writeFunctions is ' + Object.keys(writeFunctions[wf].printFunction));
              writeFunctions[wf].printFunction(writeFunctions[wf].accessRegisters);
            }
          } 
    }
    processRegister(reg, "print");
}

/** 
 * Analyzes register settings for pin muxing and functional pin properties (electrical features) from the tool.
 * It iterates through all steps and registers and finding and collecting clock gate configurations 
 * pc - index of configuration/function (internally component)
 * configurationSteps - array of configuration register steps 
 */
function analyzeRegisterConfigurationSequence(pc, configurationSteps) {
        /* Analyzing returned data. Iteration through all registers and finding and collecting clock gate configurations */
        registerList[pc] = new Object();

        var configurationRegisterList = registerList[pc];
        clockGateRegisterList[pc] = new Object();
        var configurationClockGateRegisterList = clockGateRegisterList[pc];
        for (var si = 0; si < configurationSteps.length; si++) {
          var configurationStepName = configurationSteps[si].getName(); 
          var configurationStepDescription = configurationSteps[si].getDescription(); 
          var configurationRegisters = configurationSteps[si].getRegistersConfigurations();
          //PExOut.log('he101'+ Object.keys(registerList[pc]));
          for (var ri = 0; ri < configurationRegisters.length; ri++) {
            //var registerDesc = configurationRegisters[ri];
            var registerName = configurationRegisters[ri].getRegisterName();
            var dbPeripheral = getDbPeripheralByFullNameObj(registerName); // WORKAROUND: registerDatabaseObject.getPeripheralByFullName(registerName);
            var dbRegister = registerDatabaseObject.getRegisterByFullName(registerName);
            if ((dbPeripheral != null) && (dbRegister != null)) {
              if ((!testMode && componentClockGateGeneration[pc]) || (testMode && componentClockGateGeneration[0])) {
                /* ***** Preparation of clock gate configuration lists ***** */
                var clockGate = registerDatabaseObject.getClockGate(dbPeripheral, dbRegister);
                if (clockGate != null) {
                  var clockGateRegisterFullName = clockGate.getControlPeripheralName() + "_" + clockGate.getControlRegisterName();
                  var clockGateField = clockGate.getControlBitField();
                  var clockGateStates = clockGate.getStates();
                  if (clockGateField != null) {
                    for (var gindex = 0;gindex < clockGateStates.length; gindex++) {
                      var aGState = clockGateStates[gindex];
                      var clockGateShiftedValue = getBitwiseShiftLeft(aGState.getValue(), clockGateField.getOffset());
                      if (aGState.getName() == "enabled") {
                        if (codeStyle == "CMSIS") {
                          var reg = configurationClockGateRegisterList[clockGateRegisterFullName];
                          if (reg != null) {
                            reg.registerSetMask = getBitwiseOr(reg.registerSetMask, clockGateShiftedValue);
                            reg.registerClrMask = getBitwiseOr(reg.registerClrMask, getBitwiseXor(clockGateShiftedValue, clockGateField.getRegisterMask().doubleValue()));
                            
                            
                          }
                          else {
                            configurationClockGateRegisterList[clockGateRegisterFullName] = new Object();
                            configurationClockGateRegisterList[clockGateRegisterFullName].registerName = clockGateRegisterFullName;
                            configurationClockGateRegisterList[clockGateRegisterFullName].registerClrMask = getBitwiseXor(clockGateShiftedValue, clockGateField.getRegisterMask().doubleValue());
                            configurationClockGateRegisterList[clockGateRegisterFullName].registerSetMask = clockGateShiftedValue;
                          }
                        }
                        else {
                          var clockGateName = clockGate.getName();
                          
                          configurationClockGateRegisterList[clockGateName] = new Object();
                          configurationClockGateRegisterList[clockGateName].registerName = clockGateName;
                          configurationClockGateRegisterList[clockGateName].registerClrMask = getBitwiseXor(clockGateShiftedValue, clockGateField.getRegisterMask().doubleValue());
                          configurationClockGateRegisterList[clockGateName].registerSetMask = clockGateShiftedValue;
                          configurationClockGateRegisterList[clockGateName].comment = getBitFieldSetMaskDescription(clockGateField.getValues(),aGState.getValue(),clockGateField.getDescription());
                        }
                      }
                    }
                  }
                }
              }
              /* ***** Preparation of pin muxing, functional property register configuration lists ***** */
            configurationRegisterList[registerName] = new Object();
            configurationRegisterList[registerName].registerName = registerName;
            //configurationRegisterList[registerName].registerMuxCtrl = dbRegister; // save DB register for mux control
            //configurationRegisterList[registerName].registerPadCtrl = registerDatabaseObject.getRegisterByFullName(registerName.replace('SW_MUX_CTL','SW_PAD_CTL')); // save DB register for pad control
            configurationRegisterList[registerName].registerClrMask = configurationRegisters[ri].getClrRegMask();
            configurationRegisterList[registerName].registerSetMask = configurationRegisters[ri].getSetRegMask();
            }
          }
        }
}


/**
 * In case of SDK generation style, there are called functions which check each register setting and detect recognize appropriate SDK function usage.
 * These enrol functions register corresponding print functions and data for them. They also mask registerClrMask and registerSetMask accordingly.
 * pc - index of pin configuration (routing function/Pins component)
 * ccd - index of configuration constant definition
 */
function enrolSdkFunctions(pc, ccd) {
  var configurationClockGateRegisterList = clockGateRegisterList[pc];
  writeClockFunctions[pc] = new Array();
  var configurationWriteClockFunctions = writeClockFunctions[pc];

  for (var r in configurationClockGateRegisterList) {
    enrolEnableClock(configurationClockGateRegisterList[r], configurationWriteClockFunctions);
  }
  var configurationRegisterList = registerList[pc];
  //PExOut.log('helllogaa'+ Object.keys(configurationRegisterList));
  var configurationConstantDefinitionList = constantDefinitionList[ccd];
  for (var r in configurationRegisterList) {
    // enrolPortSetPinConfig(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList);
    // enrolPortSetPinMux(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList);
    // enrolPortDisablePinsDigitalFilter(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList);
    // enrolPortEnablePinsDigitalFilter(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList);
    enrolXbarSetSignalsConnection(configurationRegisterList[r], configurationWriteClockFunctions, pc);
    enrolXbarSetOutputSignalConfig(configurationRegisterList[r], configurationWriteClockFunctions, pc);
    enrolIomuxcSetPinMux(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList, pc);
    enrolDmaMuxSetSource(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList, pc);
    enrolIomuxcSetPinConfig(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList, pc);
    enrolTrgmuxSetTriggerSource(configurationRegisterList[r], configurationWriteClockFunctions, configurationConstantDefinitionList, pc);
  }
}

/**
 * Gets "and" mask in order to safe e.g. w1c interrupt status flags in a register.
 * reg - register object (register name and clr and set mask to be configured)
 * dbBitField - database bit filed object 
 */
function getSafeBitFieldBy0MaskStr(reg, dbBitField) {
  var str = "";
  var bitFieldAccess = dbBitField.getAccessId();
  if (bitFieldAccess == "W1C") {
    str = getBitFieldMaskStr(dbBitField);
  }
  return str;
}

/**
 *  Get padded comment string aligned to column
 *  commentString - string of code comment to be padded by spaces from left
 *  length - length of previous code string
 */
function getCodeCommentPadding(commentString, length) {
  var str = commentString.toString();
  var len = length;
  while (len < 40) {
    str = ' ' + str;
    len++;
  }
  return str;
}

/** 
 * Processes register configuration sequence for all pin function configurations to C code
 * coreId - cpu core id
 */
function processRegisterConfigurationSequence(coreId) {
    
      for (var pc = 0; pc < allComponents.length; pc++) {                             // Pin configuration represented by tables in the UI of the tool
      if (coreId == componentCoreIds[pc]) {  
        /* Getting register settings for pin muxing and functional pin properties (electrical features) from the tool. There are not included register settings for properties with default/reset values (text with cursive font) */
        constantDefinitionList[pc] = new Object();
        var configurationSteps = PExProcessor.getRegisterConfigurationSequence(true,configurationStrategies[pc],null);   // exclude automatic, given function, all steps
        
        analyzeRegisterConfigurationSequence(pc,configurationSteps);
        //PExOut.log('after'+ Object.keys(configurationRegisterList));
      }
    }
      /* In case of SDK generation style, there are called functions which check each register setting and detect recognize appropriate SDK function usage.
        These enrol functions register corresponding print functions and data for them. They also mask registerClrMask and registerSetMask accordingly. */
    if (codeStyle == "SDK") {
      for (var pc = 0; pc < allComponents.length; pc++) {                             // Pin configuration represented by tables in the UI of the tool
        if (coreId == componentCoreIds[pc]) {  
          enrolSdkFunctions(pc,pc);
        }
      }
    }
}


/**
 *  Prints register macro code from dataArray for given name
 *  name - name of the register write macro
 *  setValue - written value (currently not used)
 *  dataArray - data content from register bit field macros written
 */
function printRegisterMacro(name, setValue, dataArray) {
  PExOut.gen(cIndent2 + name);
  for (var li = 0; li < dataArray.length; li++) {
    if (li != (dataArray.length - 1)) {
      PExOut.gen(cIndent6 + dataArray[li].code + ',  ' + getCodeCommentPadding('/* ' + dataArray[li].comment + ' */', dataArray[li].code.length + 3));
    }
    else {
      PExOut.gen(cIndent6 + dataArray[li].code + '); ' + getCodeCommentPadding('/* ' + dataArray[li].comment + ' */', dataArray[li].code.length + 3));
    }
  }
  // nothing to return, just printing data output
}

/** 
 * Prints register configurations for one configuration
 * configuration - given configuration where constant definitions is added
 * return value - no data; just printing into output 
 */
function printOneRegisterConfiguration(configuration) {
      var printedAnything = false;
      /* ***** Clock gate enable ***** */
      var configurationRegisterList = clockGateRegisterList[configuration];
      for (var r in configurationRegisterList) {
        printClockRegister(configurationRegisterList[r]);
        printedAnything = true;
      }
      if (printedAnything) {
        PExOut.gen('');
      }
      /* ***** Pin muxing, functional property Register configurations ***** */
      var configurationRegisterList = registerList[configuration];
      //PExOut.log(Object.keys(configurationRegisterList));
      //PExOut.log(configurationRegisterList instanceof Array);
      // Deal with SW_MUX register first to generate macro
      for (var r in configurationRegisterList) {
          
         if(r.indexOf('SW_PAD_CTL') < 0)
         {
            printRegister(configurationRegisterList[r]);
         }
      }
      // for (var i in PadFuncIDArray)
      // {
          // PExOut.log('macro is ' + PadFuncIDArray[i]);
      // }
      // Deal with SW_PAD register
      for (var r in configurationRegisterList) {
        if(r.indexOf('SW_PAD_CTL') >= 0)
        {
            //PExOut.log('r is ' + r);
            printRegister(configurationRegisterList[r]);
        }
      }
}


// Direction enumeration definition
var directionEnumDefinition = [
"/*! @brief Direction type  */",
"typedef enum _pin_mux_direction",
"{",
"  kPIN_MUX_DirectionInput = 0U,         /* Input direction */",
"  kPIN_MUX_DirectionOutput = 1U,        /* Output direction */",
"  kPIN_MUX_DirectionInputOrOutput = 2U  /* Input or output direction */",
"} pin_mux_direction_t;"
]

/** 
 * Prints direction definitions for one configuration
 * configuration - given configuration where constant definitions is added
 * return value - no data; just printing into output 
 */
function printDirectionDefines(configuration) {
  var pin_listProperty = allComponents[configuration].findItemBySymbol("pin_list");
  var numOfItems = pin_listProperty.getItemsCount();
  for (var i = 0; i < numOfItems; i++) {
    var dirItem = allComponents[configuration].findItemBySymbol("direction" + i);
    var pinItem = allComponents[configuration].findItemBySymbol("pin_signal" + i);
    var peripheralItem = allComponents[configuration].findItemBySymbol("peripheral" + i);
    var signalItem = allComponents[configuration].findItemBySymbol("signal" + i);
    if (dirItem != null && pinItem != null && peripheralItem != null && signalItem != null) {
      if (dirItem.getError() == null && pinItem.getError() == null && peripheralItem.getError() == null && signalItem.getError() == null && !dirItem.isReadOnlyInUI()) {
        printLegacy_1_0_Direction(configuration, pinItem, peripheralItem, signalItem, dirItem);
      }
    }
  }
}

function printLegacy_1_0_Direction(configuration, pinItem, peripheralItem, signalItem, dirItem){
  var signal = (peripheralItem.getTextValue() + "_" + signalItem.getTextValue().replace(GPIOSignalFunction + ",", "").replace(",", "").replace(" ", "")).toUpperCase();
  var comment = "Direction of " + signal + " signal";
  var name = identifierPrefixes[configuration] + signal + "_DIRECTION";
  switch (dirItem.getTextValue()) {
    case "INPUT":
      PExOut.gen(getConstantDefinitionStr(name, "kPIN_MUX_DirectionInput", comment, directionDefineFormat));
      break;
    case "OUTPUT":
      PExOut.gen(getConstantDefinitionStr(name, "kPIN_MUX_DirectionOutput", comment, directionDefineFormat));
      break;
    case "INPUT/OUTPUT":
      PExOut.gen(getConstantDefinitionStr(name, "kPIN_MUX_DirectionInputOrOutput", comment, directionDefineFormat));
      break;
    default:
  }
}

function printCommonIdentifierDefine(identifierDescriptor, identifierBody, oneIdentifier) {
  PExOut.gen(getConstantDefinitionStr(
    identifierBody + "_PIN_NAME",
    identifierDescriptor.routeTo,
    "Pin name",
    directionDefineFormat
  ));
  PExOut.gen(getConstantDefinitionStr(
    identifierBody + "_LABEL",
    "\"" + identifierDescriptor.label.replace("\\", "\\\\").replace("\"", "\\\"") + "\"",
    "Label",
    directionDefineFormat
  ));
  PExOut.gen(getConstantDefinitionStr(
    identifierBody + "_NAME",
    "\"" + oneIdentifier + "\"",
    "Identifier name",
    directionDefineFormat
  ));
  var directionText = null;
  switch (identifierDescriptor.direction) {
    case "INPUT":
      directionText = "kPIN_MUX_DirectionInput";
      break;
    case "OUTPUT":
      directionText = "kPIN_MUX_DirectionOutput";
      break;
    case "INPUT/OUTPUT":
      directionText = "kPIN_MUX_DirectionInputOrOutput";
      break;
    default:
  };
  if(directionText != null) {
    PExOut.gen(getConstantDefinitionStr(
      identifierBody + "_DIRECTION",
      directionText,
      "Direction",
      directionDefineFormat
    ));
  };
}

function printGeneralIdentifierDefine(identifierDescriptor) {
  var identifierArray = identifierDescriptor.identifier.split(";");
  for(var identifierIndex in identifierArray) {
    var oneIdentifier = identifierArray[identifierIndex];
    
    // var identifierBody = "BOARD_" + oneIdentifier;                            // Fixed default usage of "BOARD_" prefix for all general identifiers, 
    var identifierBody = identifierDescriptor.prefix + oneIdentifier;            // functional group name string used instead as a prefix for generated macros
    // PExOut.gen(identifierDescriptor.prefix);
    PExOut.gen(getConstantDefinitionStr(
      identifierBody + "_PERIPHERAL",
      identifierDescriptor.peripheral,
      "Device name: " + identifierDescriptor.peripheral,
      directionDefineFormat
    ));
    PExOut.gen(getConstantDefinitionStr(
      identifierBody + "_SIGNAL",
      identifierDescriptor.signal,
      identifierDescriptor.peripheral +" signal: " + identifierDescriptor.signal,
      directionDefineFormat
    ));
    if(identifierDescriptor.channel != null) {
      var channelNumber = parseInt(identifierDescriptor.channel); // get channel number as int
      PExOut.gen(getConstantDefinitionStr(
        identifierBody + "_CHANNEL",
        // Fixed value of the channel to be defined within generated macro based on detection if the channel is "not-a-number" (NaN), i.e. "PHASE, B" or number of given channel, i.e. "1U"
        (isNaN(channelNumber) ? identifierDescriptor.channel : channelNumber.toString() + "U" ),
        identifierDescriptor.peripheral +
          (identifierDescriptor.signal.toUpperCase() == "CH" ? " channel: " : " " + identifierDescriptor.signal + " channel: " ) +
          // (identifierDescriptor.signal.toUpperCase() == "CH" ? " channel: " : " channel: " + identifierDescriptor.signal + ", " ) + // FIXME: Enable this for future data update, e.g. for v4.1
          identifierDescriptor.channel,
        directionDefineFormat
      ));
    };
    printCommonIdentifierDefine(identifierDescriptor, identifierBody, oneIdentifier);
  }
  return true;
}

function printGpioIdentifierDefine(identifierDescriptor) {
  if(identifierDescriptor.signal != GPIOSignalFunction) {
    return false;
  }
  if(identifierDescriptor.channel == null) {
    return false;
  }
  var channelNumber = parseInt(identifierDescriptor.channel);
  if(isNaN(channelNumber)) {
    return false;
  }
  var identifierArray = identifierDescriptor.identifier.split(";");
  for(var identifierIndex in identifierArray) {
    var oneIdentifier = identifierArray[identifierIndex];
    var identifierBody = identifierDescriptor.prefix + oneIdentifier;
    PExOut.gen(getConstantDefinitionStr(
      identifierBody + "_GPIO",
      identifierDescriptor.peripheral,
      "GPIO device name: " + identifierDescriptor.peripheral,
      directionDefineFormat
    ));
    var PortDeviceName = identifierDescriptor.peripheral.replace(GPIOSignalFunction, "PORT")
    PExOut.gen(getConstantDefinitionStr(
      identifierBody + "_PORT",
      PortDeviceName,
      "PORT device name: " + PortDeviceName,
      directionDefineFormat
    ));
    PExOut.gen(getConstantDefinitionStr(
      identifierBody + "_GPIO_PIN",
      channelNumber.toString() + "U",
      PortDeviceName + " pin index: " + channelNumber.toString(),
      directionDefineFormat
    ));
    printCommonIdentifierDefine(identifierDescriptor, identifierBody, oneIdentifier);
  }
  return true;
}

function printIdentifierDefineTitleComment(pinItem, labelText) {
  var PinIdentifier = null;
  var configurationSteps = pinItem.getRegisterConfigurationSequence()
  for(var stepIndex = 0; stepIndex < configurationSteps.length; stepIndex++) {
    var configurationStep = configurationSteps[stepIndex];
    var registersConfigurations = configurationStep.getRegistersConfigurations();
    for(var configurationIndex = 0; configurationIndex < registersConfigurations.length; configurationIndex++) {
      var registerName = registersConfigurations[configurationIndex].getRegisterName();
      var nameSubMatches = registerName.match(/PORT([A-Z])_PCR(\d+)/);
      if(nameSubMatches != null) {
        if(nameSubMatches.length == 3) {
          PinIdentifier = "PORT" + nameSubMatches[1] + nameSubMatches[2];
          break;
        }
      }
    }
    if(PinIdentifier != null) {
      break;
    }
  }
  if(PinIdentifier == null) {
    PinIdentifier = pinItem.getSelectedPinNamePart();
  }
  var titleCommentLine = "";
  titleCommentLine += PinIdentifier;
  var pinCoordinate = pinItem.getSelectedPinCoordinates();
  var pinHasNumber = ! /^[A-Z]\d+$/.test(pinCoordinate);
  var isNotBounded = isNotBoundedPin(pinCoordinate);
  var compositePinName = pinItem.getTextValue();
  if(pinCoordinate != "") {
    titleCommentLine += " (" + (isNotBounded?("n/b pin"):((pinHasNumber? "number " : "coord ") + pinCoordinate)) + ")";
  };
  if((labelText != null) && (labelText != "")) {
    titleCommentLine += ", " + labelText;
  }
  else if(PinIdentifier != compositePinName) {
    titleCommentLine += ", " + compositePinName;
  }
  else if(pinCoordinate == "") {
    titleCommentLine += " internal signal";
  }
  PExOut.gen("/* " + titleCommentLine + " */");
}

function printIdentifierDefines(configuration) {
  var pin_listProperty = allComponents[configuration].findItemBySymbol("pin_list");
  var identifierPrefix = identifierPrefixes[configuration];
  var numOfItems = pin_listProperty.getItemsCount();
  // PExOut.log("----------------------------------------------------------------------------");
  // PExOut.log(identifierPrefix);
  // PExOut.log(numOfItems);
  // PExOut.log(configuration);
  for (var i = 0; i < numOfItems; i++) {
    var pinItem = allComponents[configuration].findItemBySymbol("pin_signal" + i);
    var peripheralItem = allComponents[configuration].findItemBySymbol("peripheral" + i);
    var signalItem = allComponents[configuration].findItemBySymbol("signal" + i);
    var identifierItem = allComponents[configuration].findItemBySymbol("identifier" + i);
    var labelItem = allComponents[configuration].findItemBySymbol("label" + i);
    var dirItem = allComponents[configuration].findItemBySymbol("direction" + i);
    if (pinItem != null && peripheralItem != null && signalItem != null && identifierItem != null) {
      if (pinItem.getError() == null && peripheralItem.getError() == null && signalItem.getError() == null && identifierItem.getError() == null) {
        var identifierText = identifierItem.getTextValue();
        // PExOut.log(identifierText);
        if(identifierText != "") {
          var signalChannelArray = signalItem.getTextValue().split(", ");
          var identifierDescriptor = {
            prefix: identifierPrefix,
            identifier: identifierText,
            peripheral: peripheralItem.getTextValue(),
            signal: signalChannelArray[0],
            channel: null,
            routeTo: pinItem.getSelectedPinNamePart(),
            direction: null,
            label: null
          };
          if(signalChannelArray.length > 1) {
            identifierDescriptor.channel = signalChannelArray[1];
          }
          var labelText = null;
          if(labelItem != null) {
            if(labelItem.getError() == null) {
              labelText = labelItem.getTextValue();
              identifierDescriptor.label = labelText;
            }
          };
          if(dirItem != null) {
            if((dirItem.getError() == null) && (!dirItem.isReadOnlyInUI())) {
              var dirText = dirItem.getTextValue();
              identifierDescriptor.direction = dirText;
            }
          };
          printIdentifierDefineTitleComment(pinItem, labelText);
          if( ! printGpioIdentifierDefine(identifierDescriptor)) {
            printGeneralIdentifierDefine(identifierDescriptor);
          };
          PExOut.gen("");
        }
      }
    }
    else if(pinItem != null && peripheralItem != null && signalItem != null && dirItem != null) {
      if(pinItem.getError() == null && peripheralItem.getError() == null && signalItem.getError() == null && dirItem.getError() == null && (!dirItem.isReadOnlyInUI())) {
        printLegacy_1_0_Direction(configuration, pinItem, peripheralItem, signalItem, dirItem);
      };
    };
  }
}




/** Copyright used for C code files - corresponds to Kinetis */
var headerCopyright = [
"/*",
" * The Clear BSD License",
" * Copyright 2017-2018 NXP",
" * All rights reserved.",
" *",
" * Redistribution and use in source and binary forms, with or without modification,",
" * are permitted (subject to the limitations in the disclaimer below) provided",
" * that the following conditions are met:",
" *",
" * o Redistributions of source code must retain the above copyright notice, this list",
" *   of conditions and the following disclaimer.",
" *",
" * o Redistributions in binary form must reproduce the above copyright notice, this",
" *   list of conditions and the following disclaimer in the documentation and/or",
" *   other materials provided with the distribution.",
" *",
" * o Neither the name of the copyright holder nor the names of its",
" *   contributors may be used to endorse or promote products derived from this",
" *   software without specific prior written permission.",
" *",
" * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.",
" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND",
" * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED",
" * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE",
" * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR",
" * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES",
" * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;",
" * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON",
" * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT",
" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS",
" * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
" */",
""
]

/* Prints string array
 * array - string array (one item on one line)
 * stringAtBeginningOfEachLine - string which is placed at the beginning of each line
 * stringAtBeginningOfFirstLine - string which is placed at the beginning of the first line
 * return value - no data; just printing into output 
 */
function printStringArray(array, stringAtBeginningOfEachLine, stringAtBeginningOfFirstLine) {
  if (array.length > 0) {
    for (var lineIndex = 0; lineIndex < array.length; lineIndex++) {
      var line = array[lineIndex];
      if (lineIndex == 0) {
        line = stringAtBeginningOfFirstLine + line;  
      }
      line = stringAtBeginningOfEachLine + line;
      PExOut.gen(line);
    }
  }
}


function createDependency(module, component) {
  var dependency = { 
    resourceType: "SWComponent" ,
    resourceId: "platform.drivers." + module,
    description: "Pins initialization requires the " + module.toUpperCase() + " Driver in the project.",
    problem_level: 2,
    source: "Pins." + configurationStrategies[component],
    features:
    [{ feature_name: "enabled",
        evaluation: "equal",
        configuration: getEnabledCoreId(coreListTxt),
        data: [{
          value: "true",
          unit: null,
          min:  null,
          max: null
       }]
    }]   
  }
  return dependency;
}

var pushedDependencies = {};

function dependencyPushed(dependency) {
    if (!(pushedDependencies[dependency.source])) {
      return false;
    }
    return ((pushedDependencies[dependency.source]).indexOf(dependency.resourceId) > -1);
}

function savePushedDependency(dependency) {
  if (!(pushedDependencies[dependency.source])) {
    pushedDependencies[dependency.source] = new Array();
  }
  pushedDependencies[dependency.source].push(dependency.resourceId);
}

function pushDependency(dependencyHelper, dependency) {
  if (!(dependencyPushed(dependency))) {
    dependencyHelper.addDependency(dependency);
    savePushedDependency(dependency);
  }
}

function registerDependencies() {
  if (projectType == "SDK") {
    var dependencyHelper = scriptApi.getDependencyHelper();

    for (var pc = 0; pc < configurationStrategies.length; pc++){
      pushDependency(dependencyHelper, createDependency('common', pc));
    }

    // if (include_fsl_port['present']) {
    //   for (var pc = 0; pc < include_fsl_port.pcs.length; pc++) {
    //     pushDependency(dependencyHelper, createDependency('port', include_fsl_port['pcs'][pc]));
    //   }
    // }

    if (include_fsl_iomuxc['present']) {
      for (var pc = 0; pc < include_fsl_iomuxc.pcs.length; pc++) {
        pushDependency(dependencyHelper, createDependency('iomuxc', include_fsl_iomuxc['pcs'][pc]));
      }
    }

    if (include_fsl_dmamux['present']) {
      for (var pc = 0; pc < include_fsl_dmamux.pcs.length; pc++) {
        pushDependency(dependencyHelper, createDependency('dmamux', include_fsl_dmamux['pcs'][pc]));
      }
    }

    if (include_fsl_trgmux['present']) {
      for (var pc = 0; pc < include_fsl_trgmux.pcs.length; pc++) {
        pushDependency(dependencyHelper, createDependency('trgmux', include_fsl_trgmux['pcs'][pc]));
      }
    }

    if (xbarModulesAB) {
      if (include_fsl_xbara['present']) {
        for (var pc = 0; pc < include_fsl_xbara.pcs.length; pc++) {
          pushDependency(dependencyHelper, createDependency('xbara', include_fsl_xbara['pcs'][pc]));
        }
      }
      if (include_fsl_xbarb['present']) {
        for (var pc = 0; pc < include_fsl_xbarb.pcs.length; pc++) {
          pushDependency(dependencyHelper, createDependency('xbarb', include_fsl_xbarb['pcs'][pc]));
        }
      }
    }
    else {
      if (include_fsl_xbar['present']) {
        for (var pc = 0; pc < include_fsl_xbar.pcs.length; pc++) {
          pushDependency(dependencyHelper, createDependency('xbar', include_fsl_xbar['pcs'][pc]));
        }
      }
    }
  }
}

function printIncludes() {
    if (projectType == "SDK") {
      //PExOut.gen('#include <stdbool.h>');
      //PExOut.gen('#include \"fsl_device_registers.h\"');
      //PExOut.gen('#include \"fsl_clock.h\"');
      PExOut.gen('#include \"fsl_common.h\"');
      if (xbarModulesAB) {
        if (include_fsl_xbara['present']) {
          PExOut.gen('#include \"fsl_xbara.h\"');
        }
      if (include_fsl_xbarb['present']) {
          PExOut.gen('#include \"fsl_xbarb.h\"');
        }
      }
      else {
        if (include_fsl_xbar['present']) {
          PExOut.gen('#include \"fsl_xbar.h\"');
        }
      }

      if (include_fsl_dmamux['present']) {
        PExOut.gen('#include \"fsl_dmamux.h\"');
      }
      if (include_fsl_iomuxc['present']) {
        PExOut.gen('#include \"fsl_iomuxc.h\"');
      }
      if (include_fsl_trgmux['present']) {
        PExOut.gen('#include \"fsl_trgmux.h\"');
      }
    }
    else {
        PExOut.gen('#include \".h\"');
    }
}

var constantDefinitionList = null;    // List of constant definition for used bit field values in register setting
var printedConstantDefinitionList = null;  // Already printed constant definitions. The purpose is avoid to duplicity in case of more configuration/function/tabs in the tool
var writeClockFunctions = null;       // Data container for write functions which print invoking SDK functions for clock gate enabling
var writeFunctions = null;             // Data container for write functions which print invoking SDK functions 
var clockGateRegisterList = null;     // List of registers for clock gate enable; register is defined by name, clear mask and set mask 
var registerList = null;              // List of registers for pin muxing and pin functional properties; register is defined by name, clear mask and set mask 
var PadFuncIDArray = null;            // List of Pad function ID macro for IOMUXC sdk API


function getEnabledCoreId (coreListTxt) {
  var coreList = JSON.parse(coreListTxt);
  var coreIds = Object.keys(coreList);
  for (var coreId = 0; coreId < coreIds.length; coreId++) {
    if (coreList[coreIds[coreId]]['enabled']) {
      return coreIds[coreId];
    }
  }
  return null;
}

function printInitFunction (initFunctions) {
    PExOut.gen('');
    PExOut.gen('/* FUNCTION ************************************************************************************************************');
    PExOut.gen(' * ');
    PExOut.gen(' * Function Name : BOARD_InitBootPins');
    PExOut.gen(' * Description   : Calls initialization functions.');
    PExOut.gen(' * ');
    PExOut.gen(' * END ****************************************************************************************************************/');
    PExOut.gen('void BOARD_InitBootPins(void) {');
    // get list of configurations called as init functions
    for (var i = 0; i < initFunctions.length; i++) {
      var initFunction = initFunctions[i];
      PExOut.gen('    ' + initFunction + '();');
    }
    PExOut.gen('}');
}

function declareInitFunction() {
  PExOut.gen('');
  PExOut.gen('/*!');
  PExOut.gen(' * @brief Calls initialization functions.');
  PExOut.gen(' *');
  PExOut.gen(' */');
  PExOut.gen('void BOARD_InitBootPins(void);');
  PExOut.gen('');
}

function getInitFunctions() {
  var initFunctions = [];

  for (var pc = 0; pc < allComponents.length; pc++) {
    var functionJSON = JSON.parse(allComponents[pc].getComponentOptions());

    if (functionJSON['callFromInitBoot']) {
      initFunctions.push(functionJSON['FunctionName']);
    }
  }
  return initFunctions;
}

/* Creates h and c file and prints theirs body.
 * configuration - given configuration where constant definitions is added
 * return value - no data; just printing into output 
 */
function printDriver() {
  for (var coreIndex in notEmptyCoreIds) {
    /** create module name suffix for multicore */
    var coreId = notEmptyCoreIds[coreIndex];
    var moduleNameSuffix = "";
    //
    constantDefinitionList = new Object();
    printedConstantDefinitionList = new Object();
    writeClockFunctions = new Object();
    writeFunctions = new Array();
    clockGateRegisterList = new Object(); 
    registerList = new Object();
    PadFuncIDArray = new Array();

    /** pre-process register configuration sequence content(s) */
    
    processRegisterConfigurationSequence(coreId);
  
    // continue writing output files ...

    /** Generate header .H file - "chFileName".h */
    
    PExOut.setOutputFile(chFileName + moduleNameSuffix + ".h");
//    printStringArray(headerCopyright, '', '');
    PExOut.gen(warning_message);
  
    PExOut.gen('#ifndef _' + (moduleName + moduleNameSuffix).toUpperCase() + '_H_');
    PExOut.gen('#define _' + (moduleName + moduleNameSuffix).toUpperCase() + '_H_');
    PExOut.gen('');

    PExOut.gen('/***********************************************************************************************************************');
    PExOut.gen(' * Definitions');
    PExOut.gen(' **********************************************************************************************************************/');
    PExOut.gen('');
    printStringArray(directionEnumDefinition, '', '');                           // Fixed missing direction type enum definition
    
    PExOut.gen('');
    PExOut.gen('/*!');
    PExOut.gen(' * @addtogroup ' + moduleName + moduleNameSuffix);
    PExOut.gen(' * @{');
    PExOut.gen(' */');
    PExOut.gen('');
  
    PExOut.gen('/***********************************************************************************************************************');
    PExOut.gen(' * API');
    PExOut.gen(' **********************************************************************************************************************/');
    PExOut.gen('');
    PExOut.gen('#if defined(__cplusplus)');
    PExOut.gen('extern \"C\" {');
    PExOut.gen('#endif');
    declareInitFunction();
  
    for (var pc = 0; pc < allComponents.length; pc++) {                          // Pin configuration represented by tables in the UI of the tool
      if (coreId == componentCoreIds[pc]) {
        configurationStrategy = configurationStrategies[pc];
        printIdentifierDefines(pc);                                                 // When legacy _DIRECTION line is required, call printDirectionDefines(pc);
        PExOut.gen('');        
        PExOut.gen('/*!');
        printStringArray(allComponents[pc].getDescription(), ' * ', '@brief ');
//        PExOut.gen(' * @brief Initializes selected pins.');
//        PExOut.gen(' *');
//        PExOut.gen(' * This function executes configuration of muxing/routing and'); 
//        PExOut.gen(' * optionally electrical features of selected pins.');
        PExOut.gen(' *');
        PExOut.gen(' */');
        PExOut.gen('void ' + configurationStrategy + '(void);');
        PExOut.gen('');
      }
    }

    PExOut.gen('#if defined(__cplusplus)');
    PExOut.gen('}');
    PExOut.gen('#endif');
    PExOut.gen('');
    PExOut.gen('/*!');
    PExOut.gen(' * @}');
    PExOut.gen(' */');
    PExOut.gen('#endif /* _' + (moduleName + moduleNameSuffix).toUpperCase() + '_H_ */');
    PExOut.gen('');
    PExOut.gen('/***********************************************************************************************************************');
    PExOut.gen(' * EOF');
    PExOut.gen(' **********************************************************************************************************************/');

    /** Generate C code file - "chFileName".c */
    PExOut.setOutputFile(chFileName + moduleNameSuffix + ".c");
//    printStringArray(headerCopyright, '', '');
    PExOut.gen(warning_message);

    // FIXED: For tools V4 modified YAML state generation according to UI option - MEX preferences > YAML in C sources > Generate YAML
    if (PExProject.getYamlState() != null) {
      PExOut.gen('/*');
      PExOut.gen(PExProject.getYamlState());
      PExOut.gen(' */');
    }
    PExOut.gen('');
    registerDependencies();                                                      // Required for checking to ensure all project dependencies on .h modules fulfilled
    printIncludes();
    PExOut.gen('#include \"' + chFileName + moduleNameSuffix + '.h\"');

    // FIXED: Generate common init boot function for all the ones that has been marked as to be called from default initialization function
    var initFunctions = getInitFunctions();
    printInitFunction(initFunctions);

    for (var pc = 0; pc < allComponents.length; pc++) {                          // Pin configuration represented by tables in the UI of the tool
      if (coreId == componentCoreIds[pc]) {
        configurationStrategy = configurationStrategies[pc];
        PExOut.gen('');
        if (printOneDefinitionConstantSet(pc)) {
          PExOut.gen('');
        }
        // FIXED: For tools V4 modified YAML state generation according to UI option - MEX preferences > YAML in C sources > Generate YAML
        if (allComponents[pc].getYamlState() != null) {
          PExOut.gen('/*');
          PExOut.gen(allComponents[pc].getYamlState());                          // Function configuration details as YAML description got from the tool
          PExOut.gen(' */'); 
        }
        PExOut.gen('');
        PExOut.gen('/* FUNCTION ************************************************************************************************************');
        PExOut.gen(' *');
        PExOut.gen(' * Function Name : ' + configurationStrategy);
        printStringArray(allComponents[pc].getDescription(), ' * ', 'Description   : ');
//        PExOut.gen(' * Description   : This function executes configuration of muxing/routing and'); 
//        PExOut.gen(' * optionally electrical features of selected pins.');
        PExOut.gen(' *');
        PExOut.gen(' * END ****************************************************************************************************************/');
        PExOut.gen('void ' + configurationStrategy + '(void) {');
        printOneRegisterConfiguration(pc);

        PExOut.gen('}');
        PExOut.gen('');
      }
    }
  
    PExOut.gen('/***********************************************************************************************************************');
    PExOut.gen(' * EOF');
    PExOut.gen(' **********************************************************************************************************************/');
  }
}

// calls main C code generation function
printDriver();

//eof.