1 /** 2 * @fileOverview LPCXpresso1769のPwmペリフェラル、ピンを制御するクラスを定義する。 3 */ 4 (function(){ 5 var DEV=LPCXpresso1769; 6 var BCF=DEV._BCF; 7 var EE=DEV._EE; 8 var isUndef=MiMicLib.isUndef; 9 var cloneAssoc=MiMicLib.cloneAssoc; 10 11 12 13 /** 14 * LPCXPresso1769.Pwm (Pwm)クラスのコンストラクタ。 15 * MCUに関連付けしたPwmペリフェラルを生成する。 16 * Pwmクラスは、PWM1ペリフェラルを管理して、PWMペリフェラル全体の設定を管理する。 17 * Pwmの分解能は、無指定の場合25MHz(1/4クロック)設定である。関数は、PWMのマッチレジスタ以外に、PCR,CTCR,TCRを同時に初期化する。 18 * @name LPCXpresso1769.Pwm 19 * @constructor 20 * @param {object as LPCXpresso1769.Mcu} i_mcu 21 * インスタンスを結びつけるMcuオブジェクト。 22 * @param {aobject as associative array} i_opt 23 * インスタンス生成と同時にsetOpt関数でセットする値を指定する。省略時は、{freq:100,phl:{power:1,clock:0}}である。 24 * 詳細は、setOpt関数を参照。 25 * @example 26 * //create PWM pheripheral 27 * var mcu=new LPCXpresso1769.Mcu("192.168.0.39"); 28 * var pwm=new LPCXpresso1769.Pwm(mcu,""); 29 */ 30 DEV.Pwm=function Pwm(i_mcu,i_opt) 31 { 32 try{ 33 this._mcu=i_mcu; 34 //PHL生成。 35 this._phl=new DEV.Peripheral(i_mcu,DEV.PHL.PWM1); 36 //設定値のロード 37 var opt=isUndef(i_opt)?{phl:{}}: 38 {//i_optある。 39 phl:isUndef(i_opt.phl)?{}:cloneAssoc(i_opt.phl), 40 freq:i_opt.freq 41 }; 42 //デフォルト値設定 43 if(isUndef(opt.phl.power)){opt.phl.power=1;}; 44 if(isUndef(opt.phl.clock)){opt.phl.clock=0;}; 45 if(isUndef(opt.freq)){opt.freq=100;} 46 47 var bc=""; 48 var db=new Array(); 49 //optionの設定 50 bc+=this.BCF_setOpt(opt,db); 51 bc+=BCF.setMem(this._PC,0x0,db); 52 //PCR 53 bc+=BCF.setMem(this._PCR,0x0,db); 54 //CTCR 55 bc+=BCF.setMem(this._CTCR,0x0,db); 56 //TCRに値設定(カウンタとPWMモードを無効化) 57 bc+=BCF.setMem(this._TCR,0x0,db); 58 bc+=BCF.setMem(this._TC,0x0,db); 59 //TCRに値設定(カウンタとPWMモードを有効化) 60 bc+=BCF.setMem(this._TCR,0x9,db); 61 //初期化 62 this._mcu.callMiMicWithCheck(bc+BCF.END,db); 63 //ペリフェラルをMCUに登録 64 this._mcu.registerPhl(this,"PWM"); 65 }catch(e){ 66 throw new MiMicException(e); 67 } 68 69 } 70 DEV.Pwm.prototype= 71 { 72 _cache:{ 73 mr0:0 74 }, 75 _TCR:0x40018004, 76 _TC:0x40018008, 77 _PR:0x4001800C, 78 _PC:0x40018010, 79 _MCR:0x40018018, 80 _PCR:0x4001804C, 81 _LER:0x40018050, 82 _CTCR:0x40018070, 83 _MRn:[0x40018018,0x4001801C,0x40018020,0x40018024,0x40018040,0x40018044,0x40018048], 84 _phl:null, 85 _mcu:null, 86 87 /** 88 * @private 89 */ 90 BCF_setOpt:function BCF_setOpt(i_opt,i_db) 91 { 92 try{ 93 var bc=""; 94 var mr0; 95 //ペリフェラルの設定 96 if(!isUndef(i_opt.phl)){ 97 bc+=this._phl.BCF_setOpt(i_opt.phl,i_db); 98 } 99 if(!isUndef(i_opt.freq)){ 100 //サイクル(Hz)とペリフェラルのクロックから、MR0のサイクルを決定 101 mr0=Math.round(this._phl.getPCLK()/i_opt.freq); 102 if(mr0<=0){ 103 //ペリフェラルクロック小さすぎワロタ 104 throw new MiMicException("The peripheral clock too small."); 105 } 106 //MR0に値設定 107 bc+=this.BCF_setMRn(0,mr0,i_db); 108 //LERにビットセット 109 bc+=this.BCF_setLER(0,i_db); 110 this._cache.mr0=mr0; 111 } 112 return bc; 113 }catch(e){ 114 throw new MiMicException(e); 115 } 116 }, 117 BCF_setLER:function BCF_setLER(i_ch,i_db) 118 { 119 try{ 120 //LERにビットをセット 121 return BCF.setBit(this._LER,0x01,0x01,i_ch,i_db); 122 }catch(e){ 123 throw new MiMicException(e); 124 } 125 }, 126 BCF_setLERs:function BCF_setLERs(i_mask,i_value,i_db) 127 { 128 try{ 129 //LERにビットをセット 130 return BCF.setBit(this._LER,i_mask,i_value*i_mask,0,i_db); 131 }catch(e){ 132 throw new MiMicException(e); 133 } 134 }, 135 136 /** 137 * MRnに値を設定するBC 138 @private 139 */ 140 BCF_setMRn:function BCF_setMRn(i_ch,i_val,i_db) 141 { 142 try{ 143 return BCF.setMem(this._MRn[i_ch],i_val,i_db); 144 }catch(e){ 145 throw new MiMicException(e); 146 } 147 }, 148 BCF_setMRnByDuty:function BCF_setMRnByDuty(i_ch,i_duty,i_db) 149 { 150 try{ 151 return this.BCF_setMRn(i_ch,Math.round(i_duty*this._cache.mr0),i_db); 152 }catch(e){ 153 throw new MiMicException(e); 154 } 155 }, 156 /** 157 * PCRに値を設定するBC 158 i_ch=1の場合、エッジモードは無視します。 159 @private 160 @param i_mask 161 @param i_edge 162 エッジモード(1/0) 163 @param i_en 164 有効/無効の選択 165 */ 166 BCF_setPCRbits:function BCF_setPCRbits(i_mask,i_edge,i_en,i_db) 167 { 168 try{ 169 var m,v; 170 m=v=0; 171 if(!isUndef(i_edge)){ 172 var t=0xff&i_mask; 173 v|=i_edge*t; 174 m|=t; 175 } 176 if(!isUndef(i_en)){ 177 var t=0xff00&i_mask; 178 v|=(i_en*t); 179 m|=t; 180 } 181 //ビットの設定 182 return BCF.setBit(this._PCR,m,v,0,i_db); 183 }catch(e){ 184 throw new MiMicException(e); 185 } 186 }, 187 188 /** 189 * Pwmペリフェラルに値を設定する。 190 * 設定する値は、全てのPWMチャンネル(PIN)に共通な項目である。 191 * @name LPCXpresso1769.Pwm#setOpt 192 * @function 193 * @param {object as associative array} i_opt 194 * GPIOピンのコンフィグレーションパラメタである。必要な値を格納した連想配列で指定する。 195 * 全ての値を省略することは出来ない。連想配列のメンバは以下の通り。 196 * <pre>{freq:int,phl:object as associative array}</pre> 197 * <ul> 198 * <li>freq - PWMの基本周波数(Hz)である。この値は、全てのPWMチャンネルで共通である。</li> 199 * <li>phl - ペリフェラルの共通パラメタである。LPCXpresso1769.Peripheral.setOpt関数のi_optに渡すパラメタである。詳細はLPCXpresso1769.Peripheral.setOptを参照。</li> 200 * </ul> 201 * @example 202 * //create PWM (logical)peripheral 203 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”); 204 * var pwm=new LPCXpresso1769.Pwm(mcu); 205 * pwm.setOpt({freq:1000}); 206 */ 207 setOpt:function setOpt(i_opt) 208 { 209 try{ 210 var db=new Array(); 211 var bc=this.BCF_setOpt(i_opt,db); 212 this._mcu.callMiMicWithCheck(bc+BCF.END,db); 213 }catch(e){ 214 throw new MiMicException(e); 215 } 216 }, 217 /** 218 * PWM機能を持つピンを取得する。 219 * ピン識別子で指定されるピンをPWMペリフェラルと結合して、PwmPinを生成する。 220 * 関数は、PwmPinオブジェクトのコンストラクタをコールして、PwmPinを生成する。失敗すると、例外をスローする。 221 * 生成ルールについての詳細は、PwmPinを参照。 222 * @name LPCXpresso1769.Pwm#getPin 223 * @function 224 * @param {object as ピン識別子} i_pin 225 * PWM機能を割り当てるPINの識別子である。 226 * @param {object as associative array} i_opt 227 * PemPinのコンストラクタに渡すオプション値。省略時は{duty:0,enable:1,pin:{sel:auto}}である。 228 * @return {object as LPCXpresso1769.PwmPin} 229 * LPCXpresso1769.PwmPinクラスのオブジェクトである。 230 * @example 231 * //create 100hz d=0.5 pwm 232 * var mcu=new LPCXpresso1769.Mcu("192.168.0.39"); 233 * var pwm=new LPCXpresso1769.Pwm(mcu); 234 * var pwmpin=pwm.getPin(LPCXpresso1769.P2[0],{duty:0.5}); 235 */ 236 getPin:function getPin(i_pin,i_opt) 237 { 238 try{ 239 return new DEV.PwmPin(this,i_pin,i_opt); 240 }catch(e){ 241 throw new MiMicException(e); 242 } 243 }, 244 /** 245 * PWM機能を持つポート(Pin集合)を取得する。 246 * ピン識別子で指定されるピンのセットをPWMペリフェラルと結合して、PwmPortを生成する。 247 * 関数は、PwmPortのコンストラクタをコールする。 248 * 生成ルールについては、PwmPort関数を参照すること。 249 * @name LPCXpresso1769.Pwm#getPort 250 * @function 251 * @param {array[ピン識別子]} i_pin 252 * Pwm機能を割り当てるPINの識別子の配列である。値は、LPCXpresso1769.Pn[m]のメンバ変数である。 253 * @param {object as associative array} i_opt 254 * AdcPortのコンストラクタに渡すオプション値。省略時はundefinedである。詳細はLPCXpresso1769.PwmPort.setOptを参照。 255 * @return {object as LPCXpresso1769.PwmPort} 256 * LPCXpresso1769.PwmPortクラスのオブジェクトである。 257 * @example 258 * //create 2AdcPort that has 2 pins. 259 * var mcu=new LPCXpresso1769.Mcu("192.168.0.39"); 260 * var pwm=new LPCXpresso1769.Pwm(mcu); 261 * var port=pwm.getPort([LPCXpresso1769.P0[23],LPCXpresso1769.P0[24]]); 262 */ 263 getPort:function getPort(i_pins,i_opt) 264 { 265 try{ 266 return new DEV.PwmPort(this,i_pins,i_opt); 267 }catch(e){ 268 throw new MiMicException(e); 269 } 270 } 271 } 272 273 /** 274 * Pwm pinからPwmInfoを取得 275 * @private 276 */ 277 function pin2PwmPinInfo(i_pin) 278 { 279 try{ 280 //pinの完全な機能名を得る。(得られれば機能がある。) 281 var fn=DEV.completePinFunctionName(i_pin,"PWM"); 282 //portとbitを得る(AD0だけしか管理しないよ) 283 var a=fn.substring(2).split("."); 284 var r={port:0,ch:parseInt(a[1]),pin_sel:DEV.getPinSelByFunctionName(i_pin,fn)}; 285 if(!isNaN(r.ch)){ 286 return r; 287 } 288 throw new MiMicException(EE.INVALID_CFG,"The pin has not PWM fuction."); 289 }catch(e){ 290 throw new MiMicException(e); 291 } 292 } 293 /** 294 * Pwmペリフェラルと複数のPin識別子から、シングルエッジPwmポートを構成する。 295 * Pwmペリフェラルオブジェクトにピン識別子の配列で指定されたピンを関連付けて、PWM機能を持つポートを生成する。 296 * 関数は、ピン識別子を元に、それぞれのピンがPWM機能に接続できるかを調べる。 297 * ピンにPWM機能を割り当てられない場合、例外が発生する。どのピンにPWM機能が割り当てられるかは、MCUのスペックシートを参照すること。 298 * PWMポートは、複数の同一周期のPWMピンのデューティ比を、同期して操作するときに便利である。 299 * @constructor 300 * @name LPCXpresso1769.PwmPort 301 * @param {object as LPCXpresso1769.Pwm} i_pwm 302 * インスタンスを結びつけるPwmオブジェクト。 303 * @param {array[pin識別子]} i_pins 304 * ピン識別子の配列。指定できるのは、LPCXpresso1796.P?[?]である。 305 * @param {object as associative array} i_opt 306 * setOpt関数のi_optに渡すパラメタである。省略可能。省略時は{duty:100,enable:1,pin{sel:auto}}を設定する。 307 * autoは、関数が自動的に決定するPINSELの値である。詳細はsetOpt関数を参照。 308 * dutyをピン毎に設定する場合は、setDuty関数を使うこと。 309 * @example 310 * //create PWM1.0,PWM1.1 311 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”); 312 * var pwm=new LPCXpresso1769.Pwm(mcu,{freq:100}); 313 * var port=new LPCXpresso1769.PwmPort(pwm,[LPCXpresso1769.P2[0],LPCXpresso1769.P2[1]]); 314 */ 315 DEV.PwmPort=function PwmPort(i_pwm,i_pins,i_opt) 316 { 317 try{ 318 this._pwm=i_pwm; 319 //ピンセットを取得 320 this._pins=new Array(); 321 //pinに変換する。 322 for(var i=0;i<i_pins.length;i++){ 323 this._pins.push(pin2PwmPinInfo(i_pins[i])); 324 } 325 //pinが全て同じポートに所属しているか確認 326 var p=this._pins[0].port; 327 for(var i=1;i<this._pins.length;i++){ 328 if(p!=this._pins[1].port){ 329 throw new MiMicException("Invalid pin combination."); 330 } 331 } 332 //ポートの生成 333 this._port=new DEV.Port(i_pwm._mcu,i_pins); 334 this._port_no=p; 335 336 this._ler_mask=0; 337 this._pcr_mask=0; 338 for(var i=0;i<this._pins.length;i++){ 339 this._ler_mask|=(0x1<<this._pins[i].ch); 340 this._pcr_mask|=(0x101<<this._pins[i].ch); 341 } 342 var opt=isUndef(i_opt)?{pin:{}}: 343 { 344 pin:isUndef(i_opt.pin)?{}:cloneAssoc(i_opt.pin), 345 duty:i_opt.duty, 346 enable:i_opt.enable 347 }; 348 //デフォルト値のロード 349 if(isUndef(opt.pin.sel)){opt.pin.sel=this._PINSEL_AUTO_DETECT;} 350 if(isUndef(opt.duty)){opt.duty=0;} 351 if(isUndef(opt.enable)){opt.enable=1;} 352 this.setOpt(opt); 353 }catch(e){ 354 throw new MiMicException(e); 355 } 356 } 357 DEV.PwmPort.prototype= 358 { 359 _PINSEL_AUTO_DETECT:0x0fffffff, 360 _pwm:null, 361 _pins:null, 362 _port_no:0, 363 _port:null, 364 _pcr_mask:0, 365 _ler_mask:0, 366 /** 367 * PWMポートにオプション値を設定する。 368 * 関数は、ポートを構成する全てのピンに、同じ値を設定する。 369 * 設定可能な値は、LPCXpresso1769.PwmPin#setOptと同じである。 370 * @name LPCXpresso1769.PwmPort#setOpt 371 * @function 372 * @param {object as associative array} i_opt 373 * LPCXpresso1769.PwmPin#setOptを参照。 374 * @example 375 * var mcu=new LPCXpresso1769.Mcu("192.168.128.39",true); 376 * var pwm=mcu.getPeripheral("PWM",{freq:100}); 377 * var port=pwm.getPort([LPCXpresso1769.P2[0]]); 378 * port.setOpt({enable:0}); 379 */ 380 setOpt:function setOpt(i_opt) 381 { 382 try{ 383 var db=new Array(); 384 //BCの生成 385 var bc=""; 386 //i_optの展開 387 if(!isUndef(i_opt.pin)){ 388 var optset=new Array(); 389 for(var i=0;i<this._pins.length;i++){ 390 //pinselが_PINSEL_AUTO_DETECTならばauto。そうでなければundefinedも含めて設定 391 var s=(i_opt.pin.sel==this._PINSEL_AUTO_DETECT)?this._pins[i].pin_sel:i_opt.pin.sel; 392 optset.push({sel:s,mode:i_opt.pin.mode,od:i_opt.pin.od}); 393 } 394 //portの設定 395 bc+=this._port.BCF_setOpts(optset,db); 396 } 397 //PCRに値設定 398 if(!isUndef(i_opt.enable)){ 399 bc+=this._pwm.BCF_setPCRbits(this._pcr_mask,0,i_opt.enable,db); 400 } 401 //デューティ比を 402 if(!isUndef(i_opt.duty)){ 403 //デューティ比を設定 404 for(var i=0;i<this._pins.length;i++){ 405 bc+=this._pwm.BCF_setMRnByDuty(this._pins[i].ch,i_opt.duty,db); 406 } 407 //LERにセット 408 bc+=this._pwm.BCF_setLERs(this._ler_mask,1,db); 409 } 410 this._pwm._mcu.callMiMicWithCheck(bc+BCF.END,db); 411 return; 412 }catch(e){ 413 throw new MiMicException(e); 414 } 415 }, 416 /** 417 * PWMポートのデューティ比をまとめて変更する。 418 * @name LPCXpresso1769.PwmPort#setDutys 419 * @function 420 * @param {array[double]} i_duty_array 421 * デューティ比の配列である。0.0<=n<=1.0のdouble値を指定する。 422 * ポートを構成するピンの数だけ指定する。変更しないピンには、undefinedを指定すること。 423 * @example 424 * varmcu=new LPCXpresso1769.Mcu("192.168.128.39",true); 425 * var pwm=mcu.getPeripheral("PWM",{freq:100}); 426 * var port=pwm.getPort([LPCXpresso1769.P2[0],LPCXpresso1769.P2[1]]); 427 * pwm.setDutys([0.5,0.0]);//PWM0=0.5,PWM1=0.0 428 * pwm.setDutys([undefined,0.0]);//PWM1=0.0 429 */ 430 setDutys:function setDutys(i_duty_array) 431 { 432 try{ 433 if(i_duty_array.length!=this._pins.length){ 434 throw new MiMicException(); 435 } 436 var bc=""; 437 var db=new Array(); 438 //デューティ比をまとめてセット 439 for(var i=0;i<this._pins.length;i++){ 440 if(!isUndef(i_duty_array[i])){ 441 bc+=this._pwm.BCF_setMRnByDuty(this._pins[i].ch,i_duty_array[i],db); 442 } 443 } 444 //LERにセット 445 bc+=this._pwm.BCF_setLERs(this._ler_mask,1,db); 446 this._pwm._mcu.callMiMicWithCheck(bc+BCF.END,db); 447 }catch(e){ 448 throw new MiMicException(e); 449 } 450 } 451 } 452 /** 453 * PwmペリフェラルとPin識別子から、シングルエッジPwmピンを構成する。 454 * Pwmペリフェラルオブジェクトにピン識別子で指定されたピンを関連付けて、PWM機能を持つピンを生成する。 455 * 関数は、ピン識別子を元に、そのピンがPWM機能に接続できるかを調べる。ピンにPWM機能を割り当てられない場合、例外が発生する。どのピンにPWM機能が割り当てられるかは、MCUのスペックシートを参照すること。 456 * ピンがPWM機能を持たない場合、例外が発生する。 457 * @constructor 458 * @name LPCXpresso1769.PwmPin 459 * @param {object as LPCXpresso1769.Pwm} i_pwm 460 * インスタンスを結びつけるAdcオブジェクト。 461 * @param {object as pin識別子} i_pin 462 * ピン識別子。指定できるのは、LPCXpresso1796.P?[?]である。 463 * @param {object as associative array} i_opt 464 * setOpt関数のi_optに渡すパラメタである。省略可能。省略時は{duty:100,enable:1,pin{sel:auto}}を設定する。 465 * autoは、関数が自動的に決定するPINSELの値である。詳細はsetOpt関数を参照。 466 * @example 467 * //create PWM1.0 468 * var mcu=new LPCXpresso1769.Mcu(“192.168.0.39”); 469 * var pwm=new LPCXpresso1769.Pwm(mcu,{freq:100}); 470 * var pwmpin=new LPCXpresso1769.PwmPin(pwm,P2[0]); 471 */ 472 DEV.PwmPin=function PwmPin(i_pwm,i_pin,i_opt) 473 { 474 try{ 475 //1pinのポートとして実装 476 this._pport=new DEV.PwmPort(i_pwm,[i_pin],i_opt); 477 }catch(e){ 478 throw new MiMicException(e); 479 } 480 } 481 482 DEV.PwmPin.prototype= 483 { 484 _pport:null, 485 486 /** 487 * PWMピンにオプション値を設定する。 488 * @name LPCXpresso1769.PwmPin#setOpt 489 * @function 490 * @param {object as associative array} i_opt 491 * PWMピンのコンフィグレーションパラメタである。必要な値を格納した連想配列で指定する。 492 * 全ての値を省略することは出来ない。連想配列のメンバは以下の通り。 493 * <pre>{pin:{associative array},enable:int,duty:double}</pre> 494 * <ul> 495 * <li>pin - LPCXpresso1769.Pin#setOpt関数のi_optに渡すパラメタである。</li> 496 * <li>enable - PWMの有効/無効を切り替える。1で有効。</li> 497 * <li>duty - デューティ比である。0.0<=n<=1.0のdouble値を指定する。</li> 498 * </ul> 499 * @example 500 * var mcu=new LPCXpresso1769.Mcu("192.168.128.39",true); 501 * var pwm=mcu.getPeripheral("PWM",{freq:100}); 502 * var pin=pwm.getPin(LPCXpresso1769.P2[0]); 503 * pin.setOpt({duty:0}); 504 */ 505 setOpt:function setOpt(i_opt) 506 { 507 try{ 508 this._pport.setOpt(i_opt); 509 }catch(e){ 510 throw new MiMicException(e); 511 } 512 }, 513 /** 514 * PWMのデューティ比を変更する。 515 * @name LPCXpresso1769.PwmPin#setDuty 516 * @function 517 * @param {double} i_duty 518 * デューティ比である。0.0<=n<=1.0のdouble値を指定する。 519 * @example 520 * varmcu=new LPCXpresso1769.Mcu("192.168.128.39",true); 521 * var pwm=mcu.getPeripheral("PWM",{freq:100}); 522 * pwmpin=pwm.getPin(LPCXpresso1769.P2[0]); 523 * pwmpin.setDuty(0.5); 524 */ 525 setDuty:function setDuty(i_duty) 526 { 527 try{ 528 this._pport.setDutys([i_duty]); 529 }catch(e){ 530 throw new MiMicException(e); 531 } 532 } 533 } 534 535 536 537 }()); 538