/**
 * @fileOverview LPCXpresso1769の物理ピンを制御するクラスを定義する。
 */

(function(){
var DEV=LPCXpresso1769;
var BCF=DEV._BCF;
var EE=DEV._EE;
var isUndef=MiMicLib.isUndef;

/**
 * LPCXPresso1769.Pin (Pin)クラスのコンストラクタ。
 * ピン識別子を元に、MCUに関連付けらしたPinインスタンスを生成する。
 * Pinクラスは、MCUの物理ピン単位に、操作インタフェイスを定義する。
 * PINSEL,PINMODE,PINMODE_ODレジスタを管理する。
 * @name LPCXpresso1769.Pin
 * @constructor
 * @param {object as LPCXpresso1769.Mcu} i_mcu
 * インスタンスを結びつけるMcuオブジェクト。
 * @param {object as ピン識別子} i_pin
 * 生成するピンのピン識別子。
 * @param {object as associative array} i_opt
 * インスタンス生成と同時にsetOpt関数で設定する値。省略時は無視する。
 * 詳細はsetOpt関数を参照。
 * このクラスは、上位クラスへピンの基本的な操作機能を提供する為のものであり、ユーザが直接使用することは（あまり）ない。
 * この関数は、MiMicの管理しているピン（ENET_?）も操作することが出来るが、操作してしまうとMiMicRemoteMcuとのコネクションが破壊されるので、注意すること。
 * @example
 * //create pin instance at P0[0]
 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”);
 * var pin=new LPCXpresso1769.Pin(mcu,LPCXpresso.P0[0]);
 */
DEV.Pin=function Pin(i_mcu,i_pin,i_opt)
{
	try{
		if(isUndef(i_pin)){
			throw new MiMicException(EE.INVALID_PIN);
		}
		this._mcu=i_mcu;
		this._pininfo=DEV.getPinRegInfo(i_pin);
		//オプション設定するならする。
		if(!isUndef(i_opt)){
			this.setOpt(i_opt);
		}
	}catch(e){
		throw new MiMicException(e);
	}
}
DEV.Pin.prototype=
{	
	_PINSEL:[0x4002C000,0x4002C004,0x4002C008,0x4002C00C,0x4002C010,null,null,0x4002C0C0,null,0x4002C024,0x4002C028],
	_PINMODE:[0x4002C040,0x4002C044,0x4002C048,0x4002C04C,0x4002C050,0x4002C054,0x4002C058,0x4002C05C,null,0x4002C064],
	_PINMODE_OD:[0x4002C068,0x4002C06C,0x4002C070,0x4002C074,0x4002C078],
	_pininfo:null,
	_mcu:null,


	/**
	 * setPinのBCを生成します。
	 @private
	 @param i_opt
	 setOptBcを参照してください。
	 @return
	 BCフラグメントを返します。
	 */
	BCF_setOpt:function BCF_setOpt(i_opt,i_db)
	{
		try{
			var bc="";
			//PINFUNC,PINMODEのbit位置
			//pinsel
			if(!isUndef(i_opt.sel)){
				
				//pinselAddrを得る
				bc+=BCF.setBit(this._PINSEL[this._pininfo.s],0x00000003,i_opt.sel,this._pininfo.smb,i_db);
			}
			//pinmode
			if(!isUndef(i_opt.mode)){
				if(this._pininfo.m==null){
					throw new MiMicException(EE.INVALID_CFG,"The pin does not support PINMODE. pininfo.");
				}
				bc+=BCF.setBit(this._PINMODE[this._pininfo.m],0x00000003,i_opt.mode,this._pininfo.smb,i_db);
			}
			//pinmode_od
			if(!isUndef(i_opt.od)){
				if(this._pininfo.o==null){
					throw new MiMicException(EE.INVALID_CFG,"The pin does not support PINMODE_OD. pininfo.");
				}
				bc+=BCF.setBit(this._PINMODE_OD[this._pininfo.o],0x00000001,i_opt.od,this._pininfo.ob,i_db);
			}
			return bc;
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * ピンにオプションパラメータをセットする。
	 * 関数は、物理ピンのレジスタに、i_optで与えられる値を設定する。
	 * 関数は、レジスタの位置に合わせてパラメータ値を自動的にシフトする。
	 * @name LPCXpresso1769.Pin#setOpt
	 * @function
	 * @param {object as associative array} i_opt
	 * ピンコンフィグレーションのパラメタである。必要な値を格納した連想配列で指定する。
	 * 全ての値を省略することは出来ない。連想配列のメンバは以下の通り。
	 * <pre>{sel,mode,od}</pre>
	 * <ul>
	 * <li>sel:int - 2bitのint値。 PINSEL? レジスタに指定する値。UM10360 Chapter8.LPC17xx Pin connect block を参照。</li>
	 * <li>mode:int - 1bitのint値。PINMODE? レジスタに指定する値。UM10360 Chapter8.LPC17xx Pin connect block を参照。</li>
	 * <li>od:int - 1bitのbit値　PINMODE_OD? レジスタに指定する値。UM10360 Chapter8.LPC17xx Pin connect block を参照。</li>
	 * </ul>
	 * @example
	 * //set GPIO,mode=1,open drain=0
	 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”);
	 * var pin=new LPCXpresso1769.Pin(mcu,LPCXpresso.P2[3]);
	 * pin.setOpt({sel:0,mode:1,od:0});	 
	 */
	setOpt:function setOpt(i_opt)
	{
		try{
			var db=new Array();
			var bc=this.BCF_setOpt(i_opt,db);
			if(bc.length==0){
				throw new MiMicException("i_opt is empty or invalid.");
			}
			//MiMicBCを生成して実行
			this._mcu.callMiMicWithCheck(bc+BCF.END,db);
		}catch(e){
			throw new MiMicException(e);
		}
		return;
	}
}

}());