/**************************************************************** * easy_audio_fft_analyzer * * 512ポイントは固定にし、サンプル周波数を、切替えられる * ようにした。(リセット時に読込む簡易的な方法にした。) * 次の3種類にし、分解能も選べるようにした。 * @ 32kサンプル/512ポイント= 分解能:62.5Hz *    表示Fレンジ= 0〜 約8kHz(62.5Hz × 128dot) * A 16kサンプル/512ポイント= 分解能:31.25Hz *    表示Fレンジ= 0〜 約4kHz(31.25Hz × 128dot) * B 8kサンプル/512ポイント= 分解能:15.625Hz *    表示Fレンジ= 0〜 約2kHz(15.625Hz × 128dot) * * Graphic LCD(Monochrome): SG12864A * * Condition: * 8MHz External X'tal Oscillator, 10x PLL (8MHzx10= 80MHz) * Fcy=80MHz/2=40MHz, Tcy=25ns * * CPU: dsPIC33FJ64GP802 * * 2016.5.12 N.Ishii * 2016.5.14 N.Ishii * FFT表示の時のループ数を半分(256→ 128)に修正 * 2016.5.16 N.Ishii * CNPU2 = 0x0080;→ このプルアップ設定(液晶のストローブ信号)は不要なので削除 ******************************************************************/ #include "p33FJ64GP802.h" #include "glcd_lib.h" #include /*** コンフィギュレーション設定 80MHz ***/ _FOSCSEL(FNOSC_PRIPLL & IESO_OFF); // Prim OSC _FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_XT); _FWDT(FWDTEN_OFF); _FPOR(ALTI2C_OFF & FPWRT_PWR32); _FICD(JTAGEN_OFF & ICS_PGD1); #define powerOf2 9 #define fftPoints (1<= 64) ypos= 63; lcd_Line(i, 10, i, ypos); ypos_old[i]= ypos; // 今回のY座標データを、オールド配列に転送し次回の比較要素とする } } else { // 2回目以降のFFT表示 // for(i=0;i<256;i++){ // これでも見た目、正常に動いていたので気が付かなかった。 for(i=0;i<128;i++){ // 512ポイントFFTだが、液晶の表示分解能が、X方向128dotなので、ループ数を、128に修正 160514 ypos= 10 + lcdData[i]/3; if(ypos >= 64) ypos= 63; if(ypos != ypos_old[i]) { // 前のレベル(Y座標)と、今回のレベルが違っていたら以下を実行 if(ypos > ypos_old[i]) { // 今回のレベルが大きい場合 lcd_Line(i, ypos_old[i], i, ypos); // プラス分のみライン描画 } if(ypos < ypos_old[i]) { // 今回のレベルが小さい場合 for(j= ypos+1; j< ypos_old[i]+1; j++) { lcd_Pixel(i, j, 0); // その分のドットをオフ(消去)する } } } // (前のレベル(Y座標)と、今回のレベルが同じだったら何もしない) ypos_old[i]= ypos; // 今回のY座標データを、次回の比較要素とするため、オールド配列に転送 } } } writePoint++; if ( writePoint == fftPoints ) { writePoint = 0; fast_flag= 0; } IFS0bits.AD1IF = 0; // clear A/D interuppt flag } // Main routine int main(void) { /// Initialize Clock OSCCON = 0x00300; // PRIPLL指定 CLKDIV = 0x0100; // クロックの分周1:2に設定 PLLFBD = 0x0026; // 40倍 8MHz÷2×40÷2 = 80MHz /// Initialize Port AD1PCFGL = 0xFFFA; // AD Channel-0,2(RA0,2) is Aanalog Input RA1(AN1)デジタル出力⇒ デバッグLED LATB = 0xFF7F; // only LCD_E is low // TRISA = 0x000F; // RA4のみ出力 TRISA = 0x000D; // RA1,RA4 is Out, Other is Inpu TRISB = 0x000F; // ポートの入出力モード設定 CNPU1 = 0x00E0; // RB1,2,3 pull up // CNPU2 = 0x0080; // このプルアップ設定(液晶のストローブ信号)は不要。無くても動く。 160516 LATAbits.LATA1 = 1; // Green LED OFF lcd_Init(); // GLCD初期化 lcd_Clear(0); lcd_Str(0, 0, "Start FFT"); Delay1m(1000); lcd_Clear(0); /// 下部X座標軸の目盛描画 lcd_Line(0, 10, 127, 10); // 下部X座標軸 // 目盛描画 for(i= 0; i < 128; i+= 4){ lcd_Line(i, 10, i, 9); } /// ADC設定 AD1CON1bits.ADON= 0; // ADC OFF AD1CHS0= 0x0000; // AN0ピンを、CH0のサンプルホールドに接続 AD1CON1= 0x8444; // AD ON, 12bitADC, 整数, T3同期, 自動サンプルON AD1CON2= 0x0000; // 常にCH0を変換しアドレス0から書込み AD1CON3= 0x0210; // Tad= 16Tcy, Tsamp= 2Tad AD1CSSL= 0x0000; // 入力スキャンしない /// サンプル周期の切替え(T3設定例:T3= Tcy*PS*n= 0.025uS*1*1250 = 31.25uS(32kHz)) sw = (PORTB & 0x000E) >> 1; // リセット時に、Decimal Dip SWを読込む switch(sw){ case 0: PR3 = 1249; // 31.25uS(32kHz) lcd_Str(7,9,"250Hz/div"); // デビジョン表示 break; case 1: PR3 = 2499; // 62.5uS(16kHz) lcd_Str(7,9,"125Hz/div"); // デビジョン表示 break; case 2: PR3 = 4999; // 125uS(8kHz) lcd_Str(7,8,"62.5Hz/div"); // デビジョン表示 break; default:PR3 = 1249; // 31.25uS(32kHz) lcd_Str(7,9,"250Hz/div"); // デビジョン表示 break; } T3CON = 0x0000; // T3_OFF, T3_GATE_OFF, T3_PS_1_1, T3_SOURCE_INT // enable interrupt IEC0bits.AD1IE = 1; // Enable ADC INT writePoint = 0; Delay1m(500); // P_ON時のインパルスノイズ入力をFFT表示させない為の遅延 T3CONbits.TON = 1; // T3ON-> ADC Start // main loop while(1) { // A/D result store in resultData } }