/*
 * Copyright 2016 Freescale Semiconductor
 * Copyright 2016-2017 NXP
 * To be used with KEx Tools. See Software License Agreement of KEx Tools.
 */

var HwAbstr = {

  /**
   * Returns Mcu series
   *
   * @param gen Clock code generation object
   * @return Mcu series, e.g. "Kinetis L"
   */
  getMcuFamily: function(gen) {
    return gen.profile.getMcuInfo().getSeries();
  },
  
  /**
   * Returns currently set Power mode for the configuration
   *
   * @param cfg Current configuration.
   * @return Power mode setting
   */
  getPowerMode: function(cfg) {
    // return Power mode for a given configuration
    return cfg.getValueAsText("powerMode");
  },
    
  /* Checks all configurations on general settings and reports errors, warnings and info.
   * Typically external oscillator settings related to balast connected to the processor. 
   * E.g. settings of capacitors should be the same for all configurations.
   * return value - no data 
   */
  checkGeneralSettings: function() {
    
    var theSame = HwAbstr.isSettingSameInAllConfigurations("SCG.SOSC_CLK.outFreq", "sosc", "asInteger");
    if (theSame != null && !theSame) {
      scriptApi.logWarning("System OSC frequency is not the same in all configurations in which the oscillator is used. Constant BOARD_XTAL0_CLK_HZ cannot be defined.");
    }
    var theSame = HwAbstr.isSettingSameInAllConfigurations("OSC_CR_SYS_OSC_CAP_LOAD_CFG", "osc");
    if (theSame != null && !theSame) {
      scriptApi.logWarning("OSC capacitors load is not the same in all configurations in which the oscillator is used.");
    }
    var theSame = HwAbstr.isSettingSameInAllConfigurations("RTC_CR_OSC_CAP_LOAD_CFG", "rtcUsed");
    if (theSame != null && !theSame) {
      scriptApi.logWarning("RTC capacitors load is not the same in all configurations in which RTC oscillator is used.");
    }
  },
  
  
  /* Checks all configurations and reports errors, warnings and info.
   * return value - no data 
   */
  checkConfigurations: function() {
    for (var i = 0; i < Gen.configs.length; i++) {
      var tempCfg = Gen.configs[i];
      var powerMode = this.getPowerMode(tempCfg);
      // SOSC or SIRC are used for VLPR and VLPW
      if (powerMode == "VLPR" || powerMode == "VLPW") {
        scriptApi.logError(tempCfg.getName() + " configuration: Entry to " + powerMode + " power mode is not allowed in " + scgMode + " SCG mode.");
      }
      if ((HwAbstr.isClockElementUsed(tempCfg,"pccUSB0Clk")) && (!HwAbstr.isUsbClkSrcFIRC(tempCfg)))
      {
        scriptApi.logError(tempCfg.getName() + ": FIRC DIV1 CLK shall be selected when use USB.");
      }
    }  
  },


  /* Checks if the setting is the same in all configurations where the setting exists and valid.
   * The validity is determined by second parameter
   * Parameter settingId - clock setting 
   * Parameter enableId - the setting of each configuration is checked only if this element is enabled  
   * Parameter getMethod - asInteger - getValueAsInteger function is used; otherwise getValueAsText is used 
   * return - true/false/null 
   */
  isSettingSameInAllConfigurations: function(settingId, enableId, getMethod) {
    var value = null;
    var result = true;
    for (var cfgIndex = 0; cfgIndex < Gen.configs.length; cfgIndex++) {
      var tempCfg = Gen.configs[cfgIndex];
      if (enableId == null || (HwAbstr.clockElementExist(tempCfg, enableId) && HwAbstr.isClockElementUsed(tempCfg, enableId))) {
        var setting = tempCfg.getValueAsText(settingId);
        if (setting != null) {
          if (getMethod == "asInteger") {
            setting = tempCfg.getValueAsInteger(settingId);
          }
          if (value == null) {
            value = setting;
          }
          else {
            if (value != setting) {
              result = false;
            }
          }
        }
      } 
    }
    if (value == null) {
      return null;
    }
    return result;
  },
  
  
  /* Get array of setting values for all configurations where the setting exists and valid.
   * The validity is determined by second parameter
   * Parameter settingId - clock setting 
   * Parameter enableId - the setting of each configuration is checked only if this element is enabled  
   * Parameter getMethod - asInteger - getValueAsInteger function is used; otherwise getValueAsText is used 
   * return - array of values 
   */
  getSettingValuesForAllConfigurations: function(settingId, enableId, getMethod) {
    var result = new Array();
    for (var cfgIndex = 0; cfgIndex < Gen.configs.length; cfgIndex++) {
      var tempCfg = Gen.configs[cfgIndex];
      if (enableId == null || (HwAbstr.clockElementExist(tempCfg, enableId) && HwAbstr.isClockElementUsed(tempCfg, enableId))) {
        var setting = tempCfg.getValueAsText(settingId);
        if (setting != null) {
          if (getMethod == "asInteger") {
            setting = tempCfg.getValueAsInteger(settingId);
          }
          if (result.indexOf(setting) == -1) {
            result.push(setting);
          }
        }
      } 
    }
    return result;
  },

  /**
   * Returns whether 24MHz OSC power down mode is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isPowerDownModeEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("XTALOSC24M::MISC0","XTAL_24M_PWD") == 1) ? true : false;
  },

  /**
   * Returns whether 24M OSC internal RC clock is used
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isInternalRcClockUsed: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("XTALOSC24M::LOWPWR_CTRL","OSC_SEL") == 1) ? true : false;
  },

  /**
   * Returns whether 24M OSC internal RC clock is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isInternalRcEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("XTALOSC24M::LOWPWR_CTRL","RC_OSC_EN") == 1) ? true : false;
  },

  /**
   * Returns Osc ready count
   *
   * @param cfg Clock configuration object
   * return value osc ready count 
   */
  getOscReadyCount: function(cfg) {
    return cfg.getBitFieldValueAsBigInteger("CCM::CCR","OSCNT");
  },

  /**
   * Returns Whether PLL is active 
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - true or false
   */
  isPllActive: function(cfg, index) {
    switch (index) {
      case "1":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ARM","POWERDOWN") == 0) ? true : false;
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","POWERDOWN") == 0) ? true : false;
      case "3":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","POWER") == 1) ? true : false;
      case "4":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","POWERDOWN") == 0) ? true : false;
      case "5":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","POWERDOWN") == 0) ? true : false;
      case "6":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","POWERDOWN") == 0) ? true : false;
      case "7":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","POWER") == 1) ? true : false;
      default:                         
        return false;                  
    }
  },

  /**
   * Returns Bypass clock source of PLL
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - 0 or 1
   */
  getPllBypassClkSrc: function(cfg, index) {
    switch (index) {
      case "1":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ARM","BYPASS_CLK_SRC");
      case "2":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","BYPASS_CLK_SRC"); 
      case "3":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","BYPASS_CLK_SRC");
      case "4":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","BYPASS_CLK_SRC");
      case "5":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","BYPASS_CLK_SRC");
      case "6":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","BYPASS_CLK_SRC");
      case "7":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","BYPASS_CLK_SRC");
      default:                         
        return false;                  
    }
  },

  /**
   * Returns loop divider of PLL
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - value of loop divider
   */
  getPllLoopDivider: function(cfg, index) {
    switch (index) {
      case "1":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ARM","DIV_SELECT");
      case "2":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","DIV_SELECT"); 
      case "3":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","DIV_SELECT");
      case "4":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","DIV_SELECT");
      case "5":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","DIV_SELECT");
      case "6":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","DIV_SELECT");
      case "7":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","DIV_SELECT");
      default:                         
        return false;                  
    }
  },

  /**
   * Returns numerator value of PLL
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - value of numerator
   */
  getPllNumerator: function(cfg, index) {
    switch (index) {
      case "4":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO_NUM","A");
      case "5":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO_NUM","A");
      default:                         
        return false;                  
    }
  },

  /**
   * Returns denominator value of PLL
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - value of denominator
   */
  getPllDenominator: function(cfg, index) {
    switch (index) {
      case "4":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO_DENOM","B");
      case "5":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO_DENOM","B");
      default:                         
        return false;                  
    }
  },

  /**
   * Returns post divider value of PLL
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - value of post divider
   */
  getPllPostDivider: function(cfg, index) {
    switch (index) {
      case "4":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","POST_DIV_SELECT");
      case "5":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","POST_DIV_SELECT");
      default:                         
        return false;                  
    }
  },

  /**
   * Returns audio divider MSB value of Audio PLL
   *
   * @param cfg Clock configuration object
   * return value - value of audio divider MSB value
   */
  getAudioDividerMSB: function(cfg) {
      return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::MISC2","AUDIO_DIV_MSB");
  },

  /**
   * Returns audio divider LSB value of Audio PLL
   *
   * @param cfg Clock configuration object
   * return value - value of audio divider LSB value
   */
  getAudioDividerLSB: function(cfg) {
      return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::MISC2","AUDIO_DIV_LSB");
  },

  /**
   * Returns video divider value of Video PLL
   *
   * @param cfg Clock configuration object
   * return value - value of video divider value
   */
  getVideoDivider: function(cfg) {
      return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::MISC2","VIDEO_DIV");
  },

  /**
   * Returns whether PLL clock output disabled
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - true or false 
   */
  isPllClkOutDisabled: function(cfg, index) {
    switch (index) {
      case "1":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ARM","ENABLE") == 0) ? true : false;
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","ENABLE") == 0) ? true : false; 
      case "3":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","ENABLE") == 0) ? true : false;
      case "4":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","ENABLE") == 0) ? true : false;
      case "5":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","ENABLE") == 0) ? true : false;
      case "6":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","ENABLE") == 0) ? true : false;
      case "7":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","ENABLE") == 0) ? true : false;
      default:                         
        return false;                  
    }
  },

  /**
   * Returns whether System PFD enabled
   *
   * @param cfg Clock configuration object
   * @param index pfd type
   * return value - true or false 
   */
  isSysPfdEnabled: function(cfg, index) {
    switch (index) {
      case "0":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD0_CLKGATE") == 0) ? true : false; 
      case "1":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD1_CLKGATE") == 0) ? true : false;
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD2_CLKGATE") == 0) ? true : false; 
      case "3":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD3_CLKGATE") == 0) ? true : false; 
      default:                         
        return true;                  
    }
  },

  /**
   * Returns whether Usb PLL output for USBPHY is enabled
   *
   * @param cfg Clock configuration object
   * @param index usb instance
   * return value - true or false 
   */
  isUsbPllOutputForUsbphyEnabled: function(cfg, index) {
    switch (index) {
      case "1":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","EN_USB_CLKS") == 1) ? true : false;
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","EN_USB_CLKS") == 1) ? true : false; 
      default:                         
        return true;                  
    }
  },


  /**
   * Returns whether Usb1 PFD enabled
   *
   * @param cfg Clock configuration object
   * @param index pfd type
   * return value - true or false 
   */
  isUsb1PfdEnabled: function(cfg, index) {
    switch (index) {
      case "0":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD0_CLKGATE") == 0) ? true : false; 
      case "1":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD1_CLKGATE") == 0) ? true : false;
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD2_CLKGATE") == 0) ? true : false; 
      case "3":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD3_CLKGATE") == 0) ? true : false; 
      default:                         
        return true;                  
    }
  },

  /**
   * Returns System PFD fractional divide value
   *
   * @param cfg Clock configuration object
   * @param index pfd type
   * return value - true or false 
   */
  getSysPfdFrac: function(cfg, index) {
    switch (index) {
      case "0":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD0_FRAC"); 
      case "1":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD1_FRAC");
      case "2":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD2_FRAC"); 
      case "3":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_528","PFD3_FRAC"); 
      default:                         
        return true;                  
    }
  },

  /**
   * Returns Usb1 PFD fractional divide value
   *
   * @param cfg Clock configuration object
   * @param index pfd type
   * return value - true or false 
   */
  getUsb1PfdFrac: function(cfg, index) {
    switch (index) {
      case "0":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD0_FRAC"); 
      case "1":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD1_FRAC");
      case "2":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD2_FRAC"); 
      case "3":
        return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PFD_480","PFD3_FRAC"); 
      default:                         
        return true;                  
    }
  },

  /**
   * Returns whether PFD offset enabled
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - true or false 
   */
  isPfdOffsetEnabled: function(cfg, index) {
    switch (index) {
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","PFD_OFFSET_EN") == 1) ? true : false;
      case "4":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","PFD_OFFSET_EN") == 1) ? true : false; 
      case "5":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","PFD_OFFSET_EN") == 1) ? true : false; 
      case "6":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","PFD_OFFSET_EN") == 1) ? true : false; 		
      default:                         
        return false;                  
    }
  },

  /**
   * Returns whether ARM PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isArmPllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ARM","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether System PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isSysPllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether Usb1 PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isUsb1PllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether Usb2 PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isUsb2PllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether Audio PLL is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isAudioPllEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","POWERDOWN") == 0) ? true : false;
  },

  /**
   * Returns whether Audio PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isAudioPllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether Video PLL is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isVideoPllEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","POWERDOWN") == 0) ? true : false;
  },

  /**
   * Returns whether Video PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isVideoPllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether Enet PLL is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isEnetPllEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","POWERDOWN") == 0) ? true : false;
  },

  /**
   * Returns whether Enet1 PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isEnet1PllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","ENABLE") == 1) ? true : false;
  },

  /**
   * Returns whether Enet2 PLL output is enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isEnet2PllOutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","ENET_25M_REF_EN") == 1) ? true : false;
  },

  /**
   * Returns whether correct 1MHz clock is used
   *
   * @param cfg Clock configuration object
   * return value - true or false 
   */
  isCorrect1mClockUsed: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("XTALOSC24M::OSC_CONFIG2","MUX_1M") == 1) ? true : false;
  },

  /**
   * Returns whether pll is bypassed
   *
   * @param cfg Clock configuration object
   * @param index PLL type
   * return value - true or false 
   */
  isPllBypassed: function(cfg, index) {
    switch (index) {
      case "1":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ARM","BYPASS") == 1) ? true : false;
      case "2":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_SYS","BYPASS") == 1) ? true : false;
      case "3":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB1","BYPASS") == 1) ? true : false;
      case "4":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_AUDIO","BYPASS") == 1) ? true : false;
      case "5":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_VIDEO","BYPASS") == 1) ? true : false;
      case "6":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_ENET","BYPASS") == 1) ? true : false;
      case "7":
        return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::PLL_USB2","BYPASS") == 1) ? true : false;
      default:                         
        return true;                  
    }
  },

  /**
   * Returns lvds1 clock mux
   *
   * @param cfg Clock configuration object
   * return value - clock mux value
   */
  getLvds1ClkMux: function(cfg) {
    return cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::MISC1","LVDS1_CLK_SEL");
  },

  /**
   * Returns whether Clk1 set as input
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isClk1InputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::MISC1","LVDSCLK1_IBEN") == 1)? true : false;
  },

  /**
   * Returns whether Clk1 set as output
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isClk1OutputEnabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM_ANALOG::MISC1","LVDSCLK1_OBEN") == 1)? true : false;
  },

  /**
   * Returns whether Clko1 enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isClko1Enabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLKO1_EN") == 1)? true : false;
  },

  /**
   * Returns clock out 1 mux
   *
   * @param cfg Clock configuration object
   * return value - clock mux value
   */
  getClko1Mux: function(cfg) {
    return cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLKO1_SEL");
  },

  /**
   * Returns clock out 1 div
   *
   * @param cfg Clock configuration object
   * return value - clock mux value
   */
  getClko1Div: function(cfg) {
    return cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLKO1_DIV");
  },

  /**
   * Returns whether Clko1 drives Clko2
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isClko2Drived: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLK_OUT_SEL") == 1)? true : false;
  },

  /**
   * Returns whether Clko2 enabled
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isClko2Enabled: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLKO2_EN") == 1)? true : false;
  },

  /**
   * Returns clock out 2 mux
   *
   * @param cfg Clock configuration object
   * return value - clock mux value
   */
  getClko2Mux: function(cfg) {
    return cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLKO2_SEL");
  },

  /**
   * Returns clock out 2 div
   *
   * @param cfg Clock configuration object
   * return value - clock mux value
   */
  getClko2Div: function(cfg) {
    return cfg.getBitFieldValueAsBigInteger("CCM::CCOSR","CLKO2_DIV");
  },
  
  /**
   * Returns whether over sample rate is 32 or 64
   *
   * @param cfg Clock configuration object
   * return value - selected rate 32 or 64
   */
  selectedMqsOverSampleRate: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR2","MQS_OVERSAMPLE") == 1)? 64 : 32;
  },

  /**
   * Returns whether Enet Tx clock source is taken from pin
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isEnetTxClockSourcePin: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR1","ENET1_CLK_SEL") == 1)? true : false;
  },
  
  /**
   * Returns whether 1 MHz clock source is selected
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isGpt1selectorSet1: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR5","VREF_1M_CLK_GPT1") == 1)? true : false;
  },
  
  /**
   * Returns whether 1 MHz clock source is selected
   *
   * @param cfg Clock configuration object
   * return value - true or false
   */
  isGpt2selectorSet1: function(cfg) {
    return (cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR5","VREF_1M_CLK_GPT2") == 1)? true : false;
  },
  
  /**
   * Returns clock mux
   *
   * @param cfg Clock configuration object
   * @param mux clock selector name
   * return value - clock mux value
   */
  getClockMux: function(cfg, mux) {
    switch (mux) {
      case "kCLOCK_Pll3SwMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CCSR","PLL3_SW_CLK_SEL");

      case "kCLOCK_PeriphMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","PERIPH_CLK_SEL");
      case "kCLOCK_SemcAltMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","SEMC_ALT_CLK_SEL"); 
      case "kCLOCK_SemcMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","SEMC_CLK_SEL");

      case "kCLOCK_PrePeriphMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCMR","PRE_PERIPH_CLK_SEL");
      case "kCLOCK_TraceMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCMR","TRACE_CLK_SEL"); 
      case "kCLOCK_PeriphClk2Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCMR","PERIPH_CLK2_SEL"); 
      case "kCLOCK_LpspiMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCMR","LPSPI_CLK_SEL");

      case "kCLOCK_FlexspiMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","FLEXSPI_CLK_SEL");
      case "kCLOCK_Usdhc2Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","USDHC2_CLK_SEL"); 
      case "kCLOCK_Usdhc1Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","USDHC1_CLK_SEL");
      case "kCLOCK_Sai3Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","SAI3_CLK_SEL"); 
      case "kCLOCK_Sai2Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","SAI2_CLK_SEL"); 
      case "kCLOCK_Sai1Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","SAI1_CLK_SEL"); 
      case "kCLOCK_PerclkMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","PERCLK_CLK_SEL");

      case "kCLOCK_Flexio2Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR2","FLEXIO2_CLK_SEL");
      case "kCLOCK_CanMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR2","CAN_CLK_SEL");

      case "kCLOCK_UartMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR1","UART_CLK_SEL");

      case "kCLOCK_SpdifMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CDCDR","SPDIF0_CLK_SEL");
      case "kCLOCK_Flexio1Mux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CDCDR","FLEXIO1_CLK_SEL");

      case "kCLOCK_Lpi2cMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR2","LPI2C_CLK_SEL");
      case "kCLOCK_LcdifPreMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR2","LCDIF_PRE_CLK_SEL");
//      case "kCLOCK_LcdifMux":
//        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR2","LCDIF_CLK_SEL");

      case "kCLOCK_CsiMux":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR3","CSI_CLK_SEL");
      case "kIOMUXC_GPR_SAI1MClk1Sel":
        return cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR1","SAI1_MCLK1_SEL");
      case "kIOMUXC_GPR_SAI1MClk2Sel":
        return cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR1","SAI1_MCLK2_SEL");
      case "kIOMUXC_GPR_SAI1MClk3Sel":
        return cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR1","SAI1_MCLK3_SEL");
      case "kIOMUXC_GPR_SAI2MClk3Sel":
        return cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR1","SAI2_MCLK3_SEL");
      case "kIOMUXC_GPR_SAI3MClk3Sel":
        return cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR1","SAI3_MCLK3_SEL");
      default:
        return 0;                  
    }
  },

  /**
   * Returns clock divider
   *
   * @param cfg Clock configuration object
   * @param div clock divider name
   * return value - clock divide value
   */
  getClockDiv: function(cfg, div) {
    switch (div) {
      case "kCLOCK_ArmDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CACRR","ARM_PODF");

      case "kCLOCK_PeriphClk2Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","PERIPH_CLK2_PODF");
      case "kCLOCK_SemcDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","SEMC_PODF");
      case "kCLOCK_AhbDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","AHB_PODF");
      case "kCLOCK_IpgDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCDR","IPG_PODF");

      case "kCLOCK_LpspiDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCMR","LPSPI_PODF");
      case "kCLOCK_LcdifDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CBCMR","LCDIF_PODF");

      case "kCLOCK_FlexspiDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","FLEXSPI_PODF");
      case "kCLOCK_PerclkDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR1","PERCLK_PODF");

      case "kCLOCK_CanDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCMR2","CAN_CLK_PODF");

      case "kCLOCK_TraceDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR1","TRACE_PODF");
      case "kCLOCK_Usdhc2Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR1","USDHC2_PODF");
      case "kCLOCK_Usdhc1Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR1","USDHC1_PODF");
      case "kCLOCK_UartDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR1","UART_CLK_PODF");

      case "kCLOCK_Flexio2Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS1CDR","FLEXIO2_CLK_PODF");
      case "kCLOCK_Sai3PreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS1CDR","SAI3_CLK_PRED");
      case "kCLOCK_Sai3Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS1CDR","SAI3_CLK_PODF");
      case "kCLOCK_Flexio2PreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS1CDR","FLEXIO2_CLK_PRED");
      case "kCLOCK_Sai1PreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS1CDR","SAI1_CLK_PRED");
      case "kCLOCK_Sai1Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS1CDR","SAI1_CLK_PODF");

      case "kCLOCK_Sai2PreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS2CDR","SAI2_CLK_PRED");
      case "kCLOCK_Sai2Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CS2CDR","SAI2_CLK_PODF");

      case "kCLOCK_Spdif0PreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CDCDR","SPDIF0_CLK_PRED");
      case "kCLOCK_Spdif0Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CDCDR","SPDIF0_CLK_PODF");
      case "kCLOCK_Flexio1PreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CDCDR","FLEXIO1_CLK_PRED");
      case "kCLOCK_Flexio1Div":
        return cfg.getBitFieldValueAsBigInteger("CCM::CDCDR","FLEXIO1_CLK_PODF");

      case "kCLOCK_Lpi2cDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR2","LPI2C_CLK_PODF");
      case "kCLOCK_LcdifPreDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR2","LCDIF_PRED");

      case "kCLOCK_CsiDiv":
        return cfg.getBitFieldValueAsBigInteger("CCM::CSCDR3","CSI_PODF");
      case "kIOMUXC_MqsDiv":
        return cfg.getBitFieldValueAsBigInteger("IOMUXC_GPR::GPR2","MQS_CLK_DIV");
      default:
        return 0;
    }
  },

  /**
   * Returns bit-field value
   *
   * @param cfg Clock configuration object
   * @param bitFieldId Bit-field id, see this.bitFields
   * return Bit-field value  
   */
  getBitFieldValue: function(cfg, bitFieldId) {
    var bitField = this.bitFields[bitFieldId];
    if (bitField == null) {
      scriptApi.logError("[DEBUG] Function HwAbstr.getBitFieldValue() doesn't support bit-field " + bitField);
      return -1; 
    }
    var value = cfg.getBitFieldValueAsBigInteger(bitField[0], bitField[1]);
    if (value == null) {
      scriptApi.logError("[DEBUG] Unknown value for " + bitField[0] + "[" + bitField[1] + "]"); 
    } 
    return (value);
  },
 
  // Object which access element/component ids. It is used in functions clockElementExist and isClockElementUsed
  clockIds: {
      "osc" : "XTALOSC24M.OSC",
      "rtcOsc" : "XTALOSC24M.RTC_OSC",
      "clk1mSrc" : "XTALOSC24M.CLK_1M_SRC",
      "armPll" : "CCM_ANALOG.PLL1",
      "sysPll" : "CCM_ANALOG.PLL2",
      "usb1Pll" : "CCM_ANALOG.PLL3",
      "audioPll" : "CCM_ANALOG.PLL4",
      "videoPll" : "CCM_ANALOG.PLL5",
      "enetPll" : "CCM_ANALOG.PLL6",
      "usb2Pll" : "CCM_ANALOG.PLL7",
      "clk1" : "CCM_ANALOG.CLK1",
  },

  /**
   * Returns whether a clock element/component exists
   *
   * @param cfg Clock configuration object
   * @param id Setting id, see this.clockIds
   * return value - true or false 
   */
  clockElementExist: function(cfg, id) {
    if (cfg == null) {
      scriptApi.logError("[DEBUG] Function HwAbstr.clockElementExist() doesn't get right configuration (" + id + ")");
    }
    var settingId = this.clockIds[id];
    if (settingId == null) {
      scriptApi.logError("[DEBUG] Function HwAbstr.clockElementExist() doesn't support setting " + id);
      return false; 
    }
    //settingId +=  ".enable";
    return cfg.existsId(settingId);
  },

  /**
   * Returns whether a clock element is used
   *
   * @param cfg Clock configuration object
   * @param id Setting id, see this.clockIds
   * return value - true or false 
   */
  isClockElementUsed: function(cfg, id) {
    var settingId = this.clockIds[id];
    if (settingId == null) {
      scriptApi.logError("[DEBUG] Function HwAbstr.isClockElementUsed() doesn't support setting " + id);
      return false; 
    }
    settingId +=  ".enable";
    var setting = cfg.getValueAsText(settingId);
    if (setting == null) {
      scriptApi.logError("[DEBUG] Unknown id: " + settingId); 
      return false; 
    } 
    return (setting == "true");
  },
                
} // HwAbstr object prototype


