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

/**
 * このクラスは、GPIOペリフェラルを管理します。
 */
DEV.Gpio=function Gpio(i_mcu)
{
	try{
		this._mcu=i_mcu;
		i_mcu.registerPhy(this,"GPIO");
	}catch(e){
		throw new MiMicException(e);
	}
}
DEV.Gpio.prototype={
	_FIO_DIR :[0x2009C000,0x2009C020,0x2009C040,0x2009C060,0x2009C080],
	_FIO_PIN :[0x2009C014,0x2009C034,0x2009C054,0x2009C074,0x2009C094],
	_FIO_SET :[0x2009C018,0x2009C038,0x2009C058,0x2009C078,0x2009C098],
	_FIO_CLR :[0x2009C01C,0x2009C03C,0x2009C05C,0x2009C07C,0x2009C09C],
	_FIO_MASK:[0x2009C010,0x2009C030,0x2009C050,0x2009C070,0x2009C090],
	_mcu:null,
	/**
	 * ピン用のBCF生成関数
	 */
	BCF_setDir:function BCF_setDir(i_ch,i_bit,i_dir,i_db)
	{
		try{
			return BCF.setBit(this._FIO_DIR[i_ch],0x00000001,i_dir,i_bit,i_db);
		}catch(e){
			throw new MiMicException(e);
		}
	},
	BCF_setValue:function BCF_setValue(i_ch,i_bit,i_val,i_db)
	{
		/*GPIOレジスタにセットするBC
		SGET #0;//GPIOの値レジスタアドレス
		SGET #1;//GPIOのMASKレジスタアドレス
		SGET #2;//MASKレジスタの値
		MPUT #2,#1;//MASK設定
		LD #2,0xffffffff
		MPUT #2,#0;//値セット
		*/		
		try{
			if(i_val){
				i_db.push(this._FIO_SET[i_ch],this._FIO_MASK[i_ch],~(0x00000001<<i_bit));
			}else{
				i_db.push(this._FIO_CLR[i_ch],this._FIO_MASK[i_ch],~(0x00000001<<i_bit));
			}
			return "EA00EA01EA02DF0201FB02ffffffffDF0200";
		}catch(e){
			throw new MiMicException(e);
		}
	},
	BCF_getValue:function BCF_getValue(i_ch,i_bit,i_db)
	{
		/*GPIOレジスタからとってくるBC
		SGET #0;//GPIOの値レジスタアドレス
		SGET #1;//GPIOのMASKレジスタアドレス
		SGET #2;//MASKレジスタの値
		MSET #2,#1;//MASK設定
		MGET #3,#0;//値取得
		SPUT #3;//SPUT
		 */
		try{
			i_db.push(this._FIO_PIN[i_ch],this._FIO_MASK[i_ch],~(0x00000001<<i_bit));
			return "EA00EA01EA02DF0201DB0300EE03";
		}catch(e){
			throw new MiMicException(e);
		}		
	},
	/**
	 * @see API manual
	 */
	getPin:function createPin(i_pin,i_opt)
	{
		try{
			return new DEV.GpioPin(this,i_pin,i_opt);
		}catch(e){
			throw new MiMicException(e);
		}
	}

}

/**
 * @see API manual
 */
DEV.GpioPin=function GpioPin(i_gpio,i_pin,i_opt)
{
	try{
		//PINを作る。
		this._gpio=i_gpio;
		this._pin=new DEV.Pin(i_gpio._mcu,i_pin);
		//pinからGPIOに関するピン情報を計算。
		this._gpioinfo=function(i_pin)
		{
			//pinの完全な機能名を得る。(得られれば機能がある。)
			var func_name=DEV.completePinFunctionName(i_pin,"GPIO");
			//pin名からポートとビットを得る。
			var a=func_name.substring(4).split(".");
			//pin情報を構成。
			var r={port:parseInt(a[0]),bit:parseInt(a[1]),pin_sel:DEV.getPinSelByFunctionName(i_pin,func_name)};
			if(!isNaN(r.port) && !isNaN(r.bit)){
				return r;
			}
			throw new MiMicException(EE.INVALID_CFG,"The pin has not GPIO fuction.");
		}(i_pin);
		if(isUndef(i_opt)){
			//optionが無いときは、GPIO化だけ。
			this.setOpt({sel:this._gpioinfo.pin_sel});
		}else{
			//optionがあるときはGPIO化と、pinコンフィギュレーションの継承
			this.setOpt(i_opt);
		}
	}catch(e){
		throw new MiMicException(e);
	}
}
DEV.GpioPin.prototype=
{
	_gpio:null,
	_pin:null,//LPCXpressoのpin
	_gpioinfo:null,//GPIOの情報{port,bit}
	/**
	 * @see API manual
	 */
	setOpt:function setOpt(i_opt)
	{
		try{
			var bc="";
			var db=new Array();
			//dirの設定
			if(!isUndef(i_opt.dir)){
				bc+=this._gpio.BCF_setDir(this._gpioinfo.port,this._gpioinfo.bit,i_opt.dir,db);
			}
			//pinselの値
			if(isUndef(i_opt.pin)){
				//pinコンフィギュレーションが無いとき
				bc+=this._pin.BCF_setOpt({sel:this._gpioinfo.pin_sel},db);
			}else{
				//pinコンフィギュレーションがあるとき
				var t=i_opt.pin.sel;//待避
				i_opt.pin.sel=this._gpioinfo.pin_sel;//selの上書き
				bc+=this._pin.BCF_setOpt(i_opt.pin,db);
				i_opt.pin.sel=t;
			}
			//実行なう
			//MiMicBCを生成して実行
			this._gpio._mcu.callMiMicWithCheck(bc+BCF.END,db);
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * @see API manual.
	 */
	setValue:function setValue(i_val)
	{
		try{
			var bc="";
			var db=new Array();
			bc+=this._gpio.BCF_setValue(this._gpioinfo.port,this._gpioinfo.bit,i_val,db);
			this._gpio._mcu.callMiMicWithCheck(bc+BCF.END,db);
		}catch(e){
			throw new MiMicException(e);
		}
	},	
	/**
	 * @see API manual.
	 */
	getValue:function getValue()
	{

		try{
			var bc="";
			var db=new Array();
			bc+=this._gpio.BCF_getValue(this._gpioinfo.port,this._gpioinfo.bit,db);
			var ret=this._gpio._mcu.callMiMicWithCheck(bc+BCF.END,db);
			return (ret.stream[0]>>this._gpioinfo.bit)&0x01;
		}catch(e){
			throw new MiMicException(e);
		}
	},
	/**
	 * ビットパターンを出力します。
	 @param i_val_array
	 Array[int]:ビットパターンです。[0,1,0,1]の場合、0,1,0,1の順に、パターンを出力します。
	 最大数は20です。
	 @remark
	 最適化対象
	 */
	outPatt:function outPatt(i_val_array)
	{
		try{
			var bc="";
			var db=new Array();
			for(var i=0;i<i_val_array.length;i++){
				bc+=this._gpio.BCF_setValue(this._gpioinfo.port,this._gpioinfo.bit,i_val_array[i],db);
			}
			this._gpio._mcu.callMiMicWithCheck(bc+BCF.END,db);
		}catch(e){
			throw new MiMicException(e);
		}
	},
	
}

}());
