/**
 * @fileOverview LPCXpresso1769の、ADコンバータペリフェラル、ピンの制御クラスを定義する。
 */
(function(){
var DEV=LPCXpresso1769;
var BCF=DEV._BCF;
var EE=DEV._EE;
var isUndef=MiMicLib.isUndef;



/**
 * LPCXPresso1769.Adc (Adc)クラスのコンストラクタ。
 * MCUに関連付けしたADペリフェラルを生成する。
 * ADペリフェラルは、MCUのADCペリフェラル全体を管理する。
 * 関数は、ADCRレジスタのPDN,BURSTを1にセットする。
 * ADCペリフェラルはバーストモードで動作し、サンプリングレートは200KHz固定である。取得タイミングの制御はハードウェア依存である。
 * @constructor
 * @name LPCXpresso1769.Adc
 * @param {object as LPCXpresso1769.Mcu} i_mcu
 * インスタンスを結びつけるMcuオブジェクト。
 * @param {object} i_opt
 * インスタンス生成と同時にsetOpt関数で設定する値。省略時は、{phl:{power:1}}とみなす。
 * 詳細はsetOpt関数を参照。 
 * @example
 * //create AD (logical)pheripheral
 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”);
 * var ad=new LPCXpresso1769.Adc(mcu); 
 */
DEV.Adc=function Adc(i_mcu,i_opt)
{
	try{
		this._mcu=i_mcu;
		//PHL生成。
		this._phl=new DEV.Peripheral(i_mcu,DEV.PHL.ADC);
		//設定値のロード
		var opt=isUndef(i_opt)?{phl:{}}:
		{//i_optある。
			phl:isUndef(i_opt.phl)?{}:cloneAssoc(i_opt.phl),
		};
		//デフォルト値設定
		if(isUndef(opt.phl.power)){opt.phl.power=1;};

		//初期化。
		var bc="";
		var db=new Array();
		bc+=this.BCF_setOpt(opt,db);
		//0x00210000(PDN,BURSTを1)
		bc+=BCF.setMem(this._AD0CR,0x00200400,db);
		bc+=BCF.setMem(this._AD0CR,0x00210400,db);
		//
		this._mcu.callMiMicWithCheck(bc+BCF.END,db);
		//ペリフェラルをMCUに登録
		this._mcu.registerPhl(this,"ADC");
	}catch(e){
		throw new MiMicException(e);
	}

}
DEV.Adc.prototype=
{
	_PHL_DEF:{power:1},
	_AD0CR:0x40034000,
	_AD0DR:[0x40034010,0x40034014,0x40034018,0x4003401C,0x40034020,0x40034024,0x40034028,0x4003402C],
	_phl:null,
	_mcu:null,

	BCF_setOpt:function BCF_setOpt(i_opt,i_db)
	{
		try{
			var bc="";
			if(!isUndef(i_opt.phl)){
				bc+=this._phl.BCF_setOpt(i_opt.phl,i_db);
			}
			return bc;
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * AD0CRのSELフィールドの値を更新するBC
	 @private
	 */
	BCF_setSel:function BCF_setSel(i_bit,i_val,i_db)
	{
		try{
			return BCF.setBit(this._AD0CR,0x00000001,i_val,i_bit,i_db);
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * n番のAD0DRの値を得るBC
	 @private
	 */
	BCF_getAD0DR:function BCF_getAD0DR(i_ch,i_db)
	{
		try{
			return BCF.getMem(this._AD0DR[i_ch],i_db);
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * ADCペリフェラルに、i_optのオプション値を設定する。
	 * @name LPCXpresso1769.Adc#setOpt
	 * @function
	 * @param {object as associative array} i_opt
	 * ADCペリフェラルのコンフィグレーションパラメタである。必要な値を格納した連想配列で指定する。
	 * 全ての値を省略することは出来ない。連想配列のメンバは以下の通り。
	 * <pre>{phl:object as associative array}</pre>
	 * <ul>
	 * <li>phl - LPCXpresso1769.Peripheral#setOpt関数のi_optに渡すパラメタである。</li>
	 * </ul>
	 * @example
	 * //AD power on/off
	 * //create AD (logical)pheripheral
	 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”);
	 * var ad=new LPCXpresso1769.Adc(mcu);
	 * ad.setOpt(phl:{power:0});
	 */
	setOpt:function setOpt(i_opt)
	{
		try{
			var db=new Array();
			var bc=this.BCF_setOpt(i_opt,db);
			this._mcu.callMiMicWithCheck(bc+BCF.END,db);
		}catch(e){
			throw new MiMicException(e);
		}
	},	
	/**
	 * AD機能を持つピンを取得する。
	 * ピン識別子で指定されるピンをADペリフェラルと結合して、AdcPinを生成する。
	 * 関数は、AdcPinオブジェクトのコンストラクタをコールして、AdcPinを生成する。失敗すると、例外をスローする。
	 * 生成ルールについての詳細は、AdcPinを参照。
	 * @name LPCXpresso1769.Adc#getPin
	 * @function
	 * @param {object as ピン識別子} i_pin
	 * AD機能を割り当てるPINの識別子である。値は、LPCXpresso1769.Pn[m]のメンバ変数である。
	 * @param {object as associative array} i_opt
	 * AdcPinのコンストラクタに渡すオプション値。省略時はundefinedである。詳細はLPCXpresso1769.AdcPinのコンストラクタを参照。
	 * @return {object as LPCXpresso1769.AdcPin}
	 * LPCXpresso1769.AdcPinクラスのオブジェクトである。
	 * @example
	 * //create AdcPin
	 * var mcu=new LPCXpresso1769.Mcu("192.168.0.39");
	 * var adc=new LPCXpresso1769.Adc(mcu);
	 * var adpin=adc.getPin(LPCXpresso1769.P0[23]);
	 */
	getPin:function getPin(i_pin,i_opt)
	{
		try{
			return new DEV.AdcPin(this,i_pin,i_opt);
		}catch(e){
			throw new MiMicException(e);
		}
	}	
}

/**
 * LPCXPresso1769.AdcPin (AdcPin)クラスのコンストラクタ。
 * Adcペリフェラルオブジェクトにピン識別子で指定されたピンを関連付けて、AD機能を持つピンを生成する。
 * 関数は、ピン識別子を元に、そのピンがAD機能に接続できるかを調べる。ピンにAD機能を割り当てられない場合、例外が発生する。どのピンにAD機能が割り当てられるかは、MCUのスペックシートを参照すること。
 * ピンがAD機能を持たない場合、例外が発生する。
 * @constructor
 * @name LPCXpresso1769.AdcPin
 * @param {object as LPCXpresso1769.Adc} i_adc
 * インスタンスを結びつけるAdcオブジェクト。
 * @param {object as pin識別子} i_pin
 * ピン識別子。指定できるのは、LPCXpresso1796.P?[?]である。
 * @param {object as associative array} i_opt
 * setOpt関数のi_optに渡すパラメタである。省略可能。省略時は{pin:{sel:auto}}を設定する。
 * autoは、関数が自動的に決定するPINSELの値である。詳細はsetOpt関数を参照。 
 * @example
 * /create AD0.0
 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”);
 * var adc=new LPCXpresso1769.Adc(mcu);
 * var adcpin=new  LPCXpresso1769.AdcPin(adc,P0[23]); 
 */
DEV.AdcPin=function AdcPin(i_adc,i_pin,i_opt)
{
	try{
		this._adc=i_adc;
		//PINがAD持ってるか確認
		this._pin=new DEV.Pin(i_adc._mcu,i_pin);
		//PinNameからピン情報を得る。
		this._adinfo=function(i_pin){
			//pinの完全な機能名を得る。(得られれば機能がある。)
			var func_name=DEV.completePinFunctionName(i_pin,"AD");
			//portとbitを得る(AD0だけしか管理しないよ)
			var a=func_name.substring(2).split(".");
			var r={port:0,ch:parseInt(a[1]),pin_sel:DEV.getPinSelByFunctionName(i_pin,func_name)};
			if(!isNaN(r.ch)){
				return r;
			}
			throw new MiMicException(EE.INVALID_CFG,"The pin has not AD fuction.");
		}(i_pin);
		var opt=isUndef(i_opt)?{pin:{}}:
		{
			pin:isUndef(i_opt.pin)?{}:cloneAssoc(i_opt.pin)
		};
		//AD0CR-SELの値(強制0)
		opt.sel=1;
		//デフォルト値
		if(isUndef(opt.pin.sel)){opt.pin.sel=this._adinfo.pin_sel;}
		//オプション設定
		this.setOpt(opt);
	}catch(e){
		throw new MiMicException(e);
	}
}

DEV.AdcPin.prototype=
{
	_adc:null,
	_pin:null,
	_adinfo:null,
	/**
	 * ピンからAD変換した値を得る。
	 * @name LPCXpresso1769.AdcPin#getValue
	 * @function
	 * @return {int}
	 * 12bitのAD変換値を返す。値の意味は、UM10360 Chapter 29: LPC17xx Analog-to-Digital Converter (ADC)を参照。
	 * @example
	 * //show value of AD0.0 pin
	 * var mcu=new LPCXpresso1769.Mcu("192.168.0.39");
	 * var pin=mcu.getPin("AD0.0");
	 * alert(pin.getValue());	 
	 */
	getValue:function getValue()
	{
		try{
			//メモリから値取得
			var db=new Array();
			var bc=this._adc.BCF_getAD0DR(this._adinfo.ch,db);
			var ret=this._adc._mcu.callMiMicWithCheck(bc+BCF.END,db);
			return (ret.stream[0]>>4)&0x00000fff;
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * ADピンにオプション値を設定する。
	 * @name LPCXpresso1769.AdcPin#setOpt
	 * @function
	 * @param {object as associative array} i_opt
	 * ADピンのコンフィグレーションパラメタである。必要な値を格納した連想配列で指定する。
	 * 全ての値を省略することは出来ない。連想配列のメンバは以下の通り。
	 * <pre>{pin:object as associative array}</pre>
	 * <ul>
	 * <li>pin - LPCXpresso1769.Pin#setOpt関数のi_optに渡すパラメタである。</li>
	 * </ul>
	 */	
	setOpt:function setOpt(i_opt)
	{
		try{
			var bc="";
			var db=new Array();
			if(!isUndef(i_opt.pin)){
				bc+=this._pin.BCF_setOpt(i_opt.pin,db);
			}
			//隠し
			if(!isUndef(i_opt.sel)){
				bc+=this._adc.BCF_setSel(this._adinfo.ch,i_opt.sel,db);
			}
			this._adc._mcu.callMiMicWithCheck(bc+BCF.END,db);
			return;
		}catch(e){
			throw new MiMicException(e);
		}
	}
}
	


}());
