概要
PTGとは
dsPIC33CHシリーズにはPTGモジュールがマスターコアに1ch搭載されています。
PTGとは「Peripheral Trigger Generator」の頭文字をとった用語で、ソフトウェアでは実装困難な複雑なトリガも、ハードウェアでシーケンス的にトリガを発生できる機能となっております。
具体的な用途としまして、電力演算機能などを実装する際に毎周期事に数μsecタイミングをずらしながらインターリーブサンプリングする事で、正確な電力が求められるようになります。

このような手法の事を等価時間サンプリングといいます。これに関しては以下のサイトを参考してください。
ペリフェラルの構造
PTGモジュールの概略ブロック図は以下の通りです。
PTGQUExレジスタにコマンドを書いて各種イベントの状態によりシーケンスが切り替わります。これらはCPUと無関係に動作します。

ハードウェア構成とタイミング
今回のハードウェア構成は少々複雑になっています。
- RAMには0から355degまで、5degステップ(72データ)のサイン波データを格納します。
- SCCP2モジュールが3.6MHzごとにDMA0に転送トリガを送出します。
- DMA0はRAMからDAC1Hに順次データを転送します。自動リピートモードにして有る為、3.6MHz/72 ≒ 50kHzのサイン波がDAC1Hから出力されます。
- PTGはその立ち上がりタイミングから1周期目は0、2、4…と2usecごとに18usecまで、2周期目は0.5、2.5、4.5..と2usecごとに18.5usecまで、3周期目は1、3、5..と2usecごとに19usecまで、4周期目は1.5、3.5、5.5…と2usecごとに19.5usecまでサンプリングをします。(fig.4)
- DMA1によってAD変換結果はRAMに自動的に格納されます。


レジスタ
PTG関連のレジスタは以下の15種類です。
| レジスタ名 | 機能 | 説明 |
| PTGCST | PTG Control /Status Low Register | PTG 制御/ ステータスレジスタ |
| PTGCONH | PTG Control /Status High Register | PTG 制御レジスタ |
| PTGT0LIM PTGT1LIM | PTG Timer0/1 Limit Register | PTG Timer0/1制限レジスタ |
| PTGSDLIM | PTG Step Delay Limit Register | PTG ステップ遅延値( ステップ命令の開始から完了までの間に追加するPTG クロック数) を保持します。 |
| PTGC0LIM PTGC1LIM | PTG Counter 0/1 Limit Register | PTGJMPC0/1ステップ命令のループ繰り返し数を指定します。 |
| PTGHOLD | PTG Hold Register | PTGCOPY 命令を使ってPTGTxLIM、PTGCxLIM、PTGSDLIM、PTGL0 レジスタのいずれかにコピーするユーザ指定データを保持します。 |
| PTGADJ | PTG Adjust Register | PTGADD 命令を使ってPTGTxLIM、PTGCxLIM、PTGSDLIM、PTGL0 レジスタのいずれかに加算するユーザ指定データを保持します。 |
| PTGL0 PTGL1 | PTG Literal0 Register | PTGCTRL 命令を使ってAD1CHS0 レジスタに書き込む 16 ビット値を保持します。 |
| PTGBTE | PTG Broadcast Trigger Enable Register | ブロードキャストトリガ用の設定をします。 |
| PTGQPTR | PTG Step Queue Pointer Register | PTGのキューポインタを示します |
| PTGQUEn | PTG Step Queue Pointer n Register | PTGのキューの動作を示します |
ソースコード
(fig.3)のブロック図のように、すべてハードウェアで波形生成からAD変換まで完了させるため、初期設定後はCPUとしては何も行いません。
コンフィグレーション設定についてはコンフィグレーション設定に記載しております。
コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。
クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。
コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。
/*------------------------------------------------------------------------------*/
/* @file PTGSample.c */
/* @brief PTGでAD変換を行う */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
/*------------------------------------------------------------------------------*/
/* 定数定義*/
/*------------------------------------------------------------------------------*/
/* PTG Commands */
#define PTG_CMD_CTRL(x) ((0x0 << 4) | ((x) & 0x0F))
#define PTG_CMD_ADD(x) ((0x2 << 3) | ((x) & 0x07))
#define PTG_CMD_COPY(x) ((0x3 << 3) | ((x) & 0x07))
#define PTG_CMD_STRB(x) ((0x1 << 5) | ((x) & 0x1F))
#define PTG_CMD_WHI(x) ((0x4 << 4) | ((x) & 0x0F))
#define PTG_CMD_WLO(x) ((0x5 << 4) | ((x) & 0x0F))
#define PTG_CMD_IRQ(x) ((0x7 << 4) | ((x) & 0x0F))
#define PTG_CMD_TRIG(x) ((0x4 << 5) | ((x) & 0x1F))
#define PTG_CMD_JMP(x) ((0x5 << 5) | ((x) & 0x1F))
#define PTG_CMD_JMPC0(x) ((0x6 << 5) | ((x) & 0x1F))
#define PTG_CMD_JMPC1(x) ((0x7 << 5) | ((x) & 0x1F))
#define PTG_QUE_ADRS_0 ( 0u )
#define PTG_QUE_ADRS_1 ( 1u )
#define PTG_QUE_ADRS_2 ( 2u )
#define PTG_QUE_ADRS_3 ( 3u )
#define PTG_QUE_ADRS_4 ( 4u )
#define PTG_QUE_ADRS_5 ( 5u )
#define PTG_QUE_ADRS_6 ( 6u )
#define PTG_QUE_ADRS_7 ( 7u )
#define PTG_QUE_ADRS_8 ( 8u )
#define PTG_QUE_ADRS_9 ( 9u )
#define PTG_QUE_ADRS_10 ( 10u )
#define PTG_QUE_ADRS_11 ( 11u )
#define PTG_QUE_ADRS_12 ( 12u )
#define PTG_QUE_ADRS_13 ( 13u )
#define PTG_QUE_ADRS_14 ( 14u )
#define PTG_QUE_ADRS_15 ( 15u )
#define PTG_QUE_ADRS_16 ( 16u )
#define PTG_QUE_ADRS_17 ( 17u )
#define PTG_QUE_ADRS_18 ( 18u )
#define PTG_QUE_ADRS_19 ( 19u )
#define PTG_QUE_ADRS_20 ( 20u )
#define PTG_QUE_ADRS_21 ( 21u )
#define PTG_QUE_ADRS_22 ( 22u )
#define PTG_QUE_ADRS_23 ( 23u )
#define PTG_QUE_ADRS_24 ( 24u )
#define PTG_QUE_ADRS_25 ( 25u )
#define PTG_QUE_ADRS_26 ( 26u )
#define PTG_QUE_ADRS_27 ( 27u )
#define PTG_QUE_ADRS_28 ( 28u )
#define PTG_QUE_ADRS_29 ( 29u )
#define PTG_QUE_ADRS_30 ( 30u )
#define PTG_QUE_ADRS_31 ( 31u )
#define PTG_WHI_WLO_MASTER_PWM1 ( 0u )
#define PTG_WHI_WLO_MASTER_PWM2 ( 1u )
#define PTG_WHI_WLO_MASTER_PWM3 ( 2u )
#define PTG_WHI_WLO_MASTER_PWM4 ( 3u )
#define PTG_WHI_WLO_SLAVE_PWM1 ( 4u )
#define PTG_WHI_WLO_SLAVE_PWM2 ( 5u )
#define PTG_WHI_WLO_SLAVE_PWM3 ( 6u )
#define PTG_WHI_WLO_MASTER_SCCP4 ( 7u )
#define PTG_WHI_WLO_SLAVE_SCCP4 ( 8u )
#define PTG_WHI_WLO_MASTER_CMP1 ( 9u )
#define PTG_WHI_WLO_SLAVE_CMP1 ( 10u )
#define PTG_WHI_WLO_SLAVE_CMP2 ( 11u )
#define PTG_WHI_WLO_SLAVE_CMP3 ( 12u )
#define PTG_WHI_WLO_MASTER_ADCDGI ( 13u )
#define PTG_WHI_WLO_SLAVE_ADCDGI ( 14u )
#define PTG_WHI_WLO_INT2 ( 15u )
#define PTG_TRG_MASTER_ADCTS ( 12u )
#define PTG_TRG_SLAVE_ADCTS ( 13u )
#define PTG_TRG_MASTER_PPSO_RP46 ( 24u )
#define PTG_TRG_MASTER_PPSO_RP47 ( 25u )
#define PTG_TRG_MASTER_PPSI_RP6 ( 26u )
#define PTG_TRG_MASTER_PPSI_RP7 ( 27u )
#define PTG_TRG_SLAVE_PPSO_RP46 ( 28u )
#define PTG_TRG_SLAVE_PPSO_RP47 ( 29u )
#define PTG_TRG_SLAVE_PPSI_RP6 ( 30u )
#define PTG_TRG_SLAVE_PPSI_RP7 ( 31u )
#define PTG_IRPT_0 ( 0u )
#define PTG_IRPT_1 ( 1u )
#define PTG_IRPT_2 ( 2u )
#define PTG_IRPT_3 ( 3u )
#define PTG_IRPT_4 ( 4u )
#define PTG_IRPT_5 ( 5u )
#define PTG_IRPT_6 ( 6u )
#define PTG_IRPT_7 ( 7u )
#define PTG_CTRL_STEP_DELAY_DIS ( 2u )
#define PTG_CTRL_STEP_DELAY_ENA ( 6u )
#define PTG_CTRL_T0_WAIT ( 8u )
#define PTG_CTRL_T1_WAIT ( 9u )
#define PTG_CTRL_SFT_TRG_LEV_WAIT ( 10u )
#define PTG_CTRL_SFT_TRG_EDG_WAI ( 11u )
#define PTG_CTRL_C0_STROBE ( 12u )
#define PTG_CTRL_C1_STROBE ( 13u )
#define PTG_CTRL_L0_STROBE ( 14u )
#define PTG_CTRL_TRG_DENERATE ( 15u )
#define PTG_COPY_C0_LIMIT ( 0u )
#define PTG_COPY_C1_LIMIT ( 1u )
#define PTG_COPY_T0_LIMIT ( 2u )
#define PTG_COPY_T1_LIMIT ( 3u )
#define PTG_COPY_STEP_DELAY ( 4u )
#define PTG_COPY_LITERAL0 ( 5u )
#define PTG_ADD_C0_LIMIT ( 0u )
#define PTG_ADD_C1_LIMIT ( 1u )
#define PTG_ADD_T0_LIMIT ( 2u )
#define PTG_ADD_T1_LIMIT ( 3u )
#define PTG_ADD_STEP_DELAY ( 4u )
#define PTG_ADD_LITERAL0 ( 5u )
/*------------------------------------------------------------------------------*/
/*変数定義*/
/*------------------------------------------------------------------------------*/
unsigned int cu2l_Data[] =
{
2047 ,2212 ,2376 ,2538 ,2696 ,
2849 ,2997 ,3136 ,3268 ,3390 ,
3502 ,3603 ,3692 ,3768 ,3832 ,
3882 ,3918 ,3939 ,3947 ,3939 ,
3918 ,3882 ,3832 ,3768 ,3692 ,
3603 ,3502 ,3390 ,3268 ,3136 ,
2997 ,2849 ,2696 ,2538 ,2376 ,
2212 ,2047 ,1881 ,1717 ,1555 ,
1397 ,1244 ,1097 ,957 ,825 ,
703 ,591 ,490 ,401 ,325 ,
261 ,211 ,175 ,154 ,147 ,
154 ,175 ,211 ,261 ,325 ,
401 ,490 ,591 ,703 ,825 ,
957 ,1097 ,1244 ,1397 ,1555 ,
1717 ,1881
};
unsigned int u2g_ADCData[24];
/*------------------------------------------------------------------------------*/
/* プロトタイプ宣言*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* クロック設定 */
/*------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*------------------------------------------------------------------------------*/
/* Main関数 */
/*------------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
/*--------------------------------------------------------------------------*/
/* クロック初期化*/
/*--------------------------------------------------------------------------*/
vds_Main_Init_Clock_Register(); /* クロック初期化 */
/*--------------------------------------------------------------------------*/
/* GPIO初期化*/
/*--------------------------------------------------------------------------*/
TRISEbits.TRISE0 = 0u; /* LED1 */
ANSELAbits.ANSELA0 = 1u; /* RA0ピンはアナログピン(ポテンション入力)*/
ANSELBbits.ANSELB2 = 1u; /* RB2ピンはアナログピン(DACOUT1) */
RPOR19bits.RP71R = 23u; /* RGB LED GREEN[CMP1] */
/*--------------------------------------------------------------------------*/
/* CMP初期化*/
/*--------------------------------------------------------------------------*/
DACCTRL1L = 0x0000u;
DACCTRL1Lbits.CLKSEL = 0u; /* DACクロック源( 0 = AFVCO/2 = 500MHz) */
DACCTRL1Lbits.CLKDIV = 0u; /* DACクロックディバイダ (0 = 1/1) */
DACCTRL1Lbits.FCLKDIV = 7u; /* コンパレータフィルタクロックディバイダ*/
DACCTRL1Lbits.DACON = 1u; /* モジュール有効化(0 = 無効,1 = 有効) */
DACCTRL2H = 0x001Au; /* 移行開始からの時間 */
DACCTRL2L = 0x0055u; /* 遷移モードの継続時間 */
DAC1CONH = 0x0000u;
DAC1CONL = 0x0000u;
DAC1CONLbits.INSEL = 0u; /* コンパレータ入力ソース*/
DAC1CONLbits.HYSSEL = 1u; /* コンパレータヒステリシス (1 = 15mV) */
DAC1CONLbits.DACOEN = 1u; /* DAC外部出力 (0 = 無効,1 = 有効) */
DAC1DATH = 0x0000u; /* コンパレータ比較値上限 */
DAC1DATL = 0x0000u; /* コンパレータ比較値下限 */
/*--------------------------------------------------------------------------*/
/* DAC1の有効化*/
/*--------------------------------------------------------------------------*/
DAC1CONLbits.DACEN = 1u; /* DAC1の有効化 */
/*--------------------------------------------------------------------------*/
/* SCCP2の間隔でDAC出力*/
/* [嵌り事]TimerモードではDAC出力タイミングの周期はPRHで設定*/
/* [嵌り事]OCモードではDAC出力タイミングの周期はPRL,RAL!=RABで設定*/
/*--------------------------------------------------------------------------*/
CCP2CON1L = 0x0000u;
CCP2CON1H = 0x0000u;
CCP2CON2H = 0x0000u;
CCP2CON2Hbits.AUXOUT = 1u; /* イベント時補助出力信号選択ビット*/
CCP2PRL = 24u; /* 周期(PWMモード) */
CCP2PRH = 24u; /* 周期(タイマーモード) */
CCP2RAL = 13u; /* 立ち上がりタイミング(PWMモード) */
CCP2RBL = 0u; /* 立ち下がりタイミング(PWMモード) */
CCP2CON1Lbits.CCPON = 1u;
/*--------------------------------------------------------------------------*/
/* DMA初期化 */
/*--------------------------------------------------------------------------*/
DMAH = 0xC000u; /* DMA転送最大アドレス */
DMAL = 0x080u; /* DMA転送最小アドレス */
DMACON = 0x0000u;
DMACONbits.DMAEN = 1u; /* DMAモジュール有効化 */
DMACONbits.PRSSEL = 1u; /* ラウンドロビン方式 */
DMACH0 = 0x0000u;
DMACH0bits.SAMODE = 1u; /* 送信元アドレスをインクリメントする */
DMACH0bits.DAMODE = 0u; /* 受信元アドレスは固定 */
DMACH0bits.TRMODE = 1u; /* 繰り返し、ワンショットモード */
DMACH0bits.RELOAD = 1u; /* 自動でリロードする */
DMACH0bits.SIZE = 0u; /* 16bit転送モード */
DMAINT0 = 0x0000u;
DMAINT0bits.CHSEL = 0x0C; /* トリガイベント = SCCP2 */
DMASRC0 = (unsigned int)&cu2l_Data; /* 送信元データは cu2l_Data[] */
DMADST0 = (unsigned int)&DAC1DATH; /* 送信先はDAC1DATHレジスタ */
DMACNT0 = 71u; /* 送信カウントは72(71 + 1)回 */
DMACH1 = 0x0000u;
DMACH1bits.SAMODE = 0u; /* 送信元アドレスは固定 */
DMACH1bits.DAMODE = 1u; /* 受信元アドレスをインクリメントする */
DMACH1bits.TRMODE = 1u; /* 繰り返し、ワンショットモード */
DMACH1bits.RELOAD = 1u; /* 自動でリロードする */
DMACH1bits.SIZE = 0u; /* 16bit転送モード */
DMAINT1 = 0x0000u;
DMAINT1bits.CHSEL = 0x2F; /* トリガイベント = ADCdone AN7 */
DMASRC1 = (unsigned int)&ADCBUF7; /* 送信元データは cu2l_Data[] */
DMADST1 = (unsigned short int)&u2g_ADCData; /* 送信先はDAC1DATHレジスタ */
DMACNT1 = 40u; /* 送信カウントは40回 */
DMACH0bits.CHEN = 1u; /* DMA0チャンネルを有効にする */
IFS0bits.DMA0IF = 0u;
DMACH1bits.CHEN = 1u; /* DMA1チャンネルを有効にする */
IFS0bits.DMA1IF = 0u;
/*--------------------------------------------------------------------------*/
/* AD初期化*/
/*--------------------------------------------------------------------------*/
ADCON1L = 0x0000u;
ADCON1H = 0x0000u;
ADCON2L = 0x0000u;
ADCON2H = 0x0000u;
ADCON3L = 0x0000u;
ADCON3H = 0x0000u;
ADCON5H = 0x0000u;
ADTRIG0L = 0x0000u;
ADTRIG0H = 0x0000u;
ADTRIG1L = 0x0000u;
ADTRIG1H = 0x0000u;
ADTRIG2L = 0x0000u;
ADTRIG2H = 0x0000u;
ADTRIG3L = 0x0000u;
ADTRIG3H = 0x0000u;
ADTRIG4L = 0x0000u;
ADTRIG4H = 0x0000u;
ADTRIG5L = 0x0000u;
ADLVLTRGL = 0x0000u;
ADLVLTRGH = 0x0000u;
ADCMP0CON = 0x0000u;
ADCMP0ENL = 0x0000u;
ADCMP0ENH = 0x0000u;
/***** AD制御レジスタの設定 ******/
ADCON1Hbits.SHRRES = 3u; /* シェアADC分解能 (3 = 12bit) */
ADCON2Lbits.SHRADCS = 2u; /* シェアADCクロックディバイダ (2 = 4Clock) */
ADCON2Hbits.SHRSAMC = 4u; /* シェアADCサンプル時間 (3 = 4TAD) */
ADCON3Lbits.CNVCHSEL = 0u; /* ソフトウェアAD入力(0 =AN0入力)(Don't Care) */
ADCON3Hbits.CLKSEL = 2u; /* ADCクロックソース (2 = AFVCODIV) */
ADCON3Hbits.CLKDIV = 2u; /* ADCクロックディバイダ(2 = 3Clock)*/
ADCON5Hbits.WARMTIME = 15u; /* ウォームアップ時間(15 = 32768Clock) */
/***** ADトリガ―の設定 ******/
ADTRIG1Hbits.TRGSRC7 = 0x1E; /* AN7入力のトリガ設定(PTG) */
/***** AD割り込みの設定(重要) ******/
ADIELbits.IE7 = 1u;
IEC6bits.ADCAN7IE = 0u;
/***** ADの有効化 ******/
ADCON1Lbits.ADON = 1u; /* ADC全体のパワーON */
ADCON5Lbits.SHRPWR = 1u; /* シェアADCのパワーON */
while(ADCON5Lbits.SHRRDY == 0u){;}
ADCON3Hbits.SHREN = 1u; /* シェアADCの有効化 */
/*--------------------------------------------------------------------------*/
/* PTG初期化 */
/*--------------------------------------------------------------------------*/
PTGCST = 0x0000u;
PTGCON = 0x0000u;
PTGCONbits.PTGWDT = 0u; /* PTGウォッチドッグタイムアウトカウント*/
PTGCONbits.PTGPWD = 8u; /* PTGトリガ出力パルス幅ビット (8PTG clock)*/
PTGCONbits.PTGDIV = 0u; /* PTGモジュールクロックプリスケーラ*/
PTGCONbits.PTGCLK = 0u; /* PTGモジュール クロック源選択ビット (0 = FP)*/
PTGBTE = 0x0000u;
PTGBTEH = 0x0000u;
PTGHOLD = 0u; /* 0us / FP = 90Mhz*/
PTGT0LIM = 0u;
PTGT1LIM = 180u - 3; /* 2us - 3Step / FP = 90Mhz*/
PTGSDLIM = 0x0000u;
PTGC0LIM = 9u; /* 全10回 */
PTGC1LIM = 0x0003u; /* 全4回 */
PTGADJ = 45u; /* 500ns / FP = 90Mhz*/
PTGL0 = 0x0000u;
PTGQPTR = 0x0000u;
/* コンパレータ1のトリガを待つ */
PTGQUE0bits.STEP0 = PTG_CMD_WHI(PTG_WHI_WLO_MASTER_CMP1) ;
/* PTG Timer0スタート&ウェイト */
PTGQUE0bits.STEP1 = PTG_CMD_CTRL(PTG_CTRL_T0_WAIT);
/* PTG 割り込み0を生成 */
PTGQUE1bits.STEP2 = PTG_CMD_IRQ(PTG_IRPT_0) ;
/* Master ADCへトリガを出力 */
PTGQUE1bits.STEP3 = PTG_CMD_TRIG(PTG_TRG_MASTER_ADCTS);
/* PTG Timer1スタート&ウェイト */
PTGQUE2bits.STEP4 = PTG_CMD_CTRL(PTG_CTRL_T1_WAIT);
/* if(PTGC0 != PTGC0LIM){PTGC0++;GoTo STEP3} */
PTGQUE2bits.STEP5 = PTG_CMD_JMPC0(PTG_QUE_ADRS_3);
/* PTGT0LIM += PTGADJ */
PTGQUE3bits.STEP6 = PTG_CMD_ADD(PTG_ADD_T0_LIMIT);
/* if(PTGC1 != PTGC1LIM){PTGC1++;GoTo STEP0} */
PTGQUE3bits.STEP7 = PTG_CMD_JMPC1(PTG_QUE_ADRS_0);
/* PTG 割り込み1を生成 */
PTGQUE4bits.STEP8 = PTG_CMD_IRQ(PTG_IRPT_1);
/* PTGT0LIM += PTGHOLD*/
PTGQUE4bits.STEP9 = PTG_CMD_COPY(PTG_COPY_T0_LIMIT);
/* GoTo PTG QUE0 */
PTGQUE5bits.STEP10 = PTG_CMD_JMP(PTG_QUE_ADRS_0);
PTGCSTbits.PTGEN = 1u;
PTGCSTbits.PTGSTRT = 1;
/*--------------------------------------------------------------------------*/
/* 有効化*/
/*--------------------------------------------------------------------------*/
CCP3CON1Lbits.CCPON = 1u;
/*--------------------------------------------------------------------------*/
/* メインルーチン*/
/*--------------------------------------------------------------------------*/
while(1)
{
}
}
結果
AD変換結果をCSVに出力させた結果です。 1周期目が青、2周期目が赤、3周期目が緑、4周期目が紫の項目でそれぞれ2usecずつ計10回のサンプリングを行っています。周期開始のサンプリング時間を毎回0.5usecずつ加算した値を遅延させています。 (fig.6)

これを実時間としてプロットすると以下のように4周期分のデータになります。 (fig.7) これでもサイン波だとは認識できそうです。

等価時間サンプリングの考えから重ねて表示させると以下のようになり、サイン波が0.5usec毎の分解能で取得できています。 (fig.8)

まとめ
- PTGモジュールはCPUとは独立して動作し、条件分岐によって様々なトリガを発生可能
- PTGモジュールを使用すると等価時間サンプリングが容易に構成可能


コメント