using System;
using System.Collections.Generic;
using System.Collections;
using MiMic.CsApi;


namespace MiMic.CsApi.LPC1769
{
	public class Peripheral:MiMicClass
	{
		/**
		 * option container for Peripheral class.
		 */
		public class Option
		{
			public UInt32? power;
			public UInt32? clock;
			public Option(UInt32? i_power,UInt32? i_clock)
			{
				this.power=i_power;
				this.clock=i_clock;
			}
			public Option(Option s)
			{
				if(s!=null){
					this.power=s.power;
					this.clock=s.clock;
				}
			}
			public static Option Option_DEFAULT=new Option(null,null);
		}
		public Peripheral(Mcu i_mcu,PeripheralId i_phl,Option i_opt)
		{
			if(i_phl==null){
				throw new MiMicException();
			}
			this._mcu=i_mcu;
			this._phl=i_phl;
			//オプション設定するならする。
			if(i_opt!=null){
				this.setOpt(i_opt);
			}
		}
		private static UInt32[] _PCLKSEL={0x400FC1A8,0x400FC1AC};
		private static UInt32 	_PCONP=0x400FC0C4;
		private PeripheralId _phl=null;
		private Mcu _mcu=null;
		private UInt32 _cache_pclk=0;
		internal string BCF_setOpt(Option i_opt,List<UInt32> i_db)
		{
			string bc="";
			//pconp
			if(i_opt.power!=null){
				if(this._phl[2]==null){
					throw new MiMicException("The pin does not support PCONP.");
				}
				//pinselAddrを得る
				bc+=LPCXpresso1769._BCF.setBit(Peripheral._PCONP,0x00000001,(UInt32)i_opt.power,(int)this._phl[2],i_db);
			}
			//clock
			if(i_opt.clock!=null){
				if(this._phl[0]==null){
					throw new MiMicException("The pin does not support PCLKSEL.");
				}
				//キャッシュ更新
				this._cache_pclk=(UInt32)i_opt.clock;
				bc+=LPCXpresso1769._BCF.setBit(Peripheral._PCLKSEL[(int)this._phl[0]],0x00000003,(UInt32)i_opt.clock,(int)this._phl[1],i_db);
			}
			return bc;
		}
		public void setOpt(Option i_opt)
		{
			List<UInt32> db=new List<UInt32>();
			string 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+LPCXpresso1769._BCF.END,db);
			return;		
		}
		public UInt32 getPCLK()
		{
			//倍率変換テーブル
			UInt32[] m={4,1,2,0};
			UInt32 t=m[this._cache_pclk];
			UInt32 r;
			if(t==0){
				if(this._phl==LPCXpresso1769.PHL.CAN1 || this._phl==LPCXpresso1769.PHL.CAN2){
					r=this._mcu.getClockInfo().cclk/6;
				}else{
					r=this._mcu.getClockInfo().cclk/8;
				}
			}else{
				r=this._mcu.getClockInfo().cclk/t;
			}
			return r;
		}
	}

}

