/************************************************************** * ソース名:Easy_6CH_LogAna_V1.C * * <実験版との違い> * @ サンプル周期に、400uS(20mS/D)と、1.0mS(50mS/D)を追加 * A SW類のプルアップを、全て、PICの内部プルアップに変更 * * 2.8インチQVGA液晶モジュール(aitendo): M028C9325TP * 320x240ドット 16ビットカラー 横置き表示 * * Condition: * 8MHz External X'tal Oscillator, 20x PLL (8MHzx20= 160MHz) * Fcy=160MHz/2=80MHz, Tcy=12.5ns * * CPU: PIC32MX340F256H * * N.Ishii 2014.8.20 ***************************************************************/ #include /* PIC32 peripheral library */ #include "colorlcd_libdsPICVH.h" #include /// コンフィギュレーション設定 // CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off #pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2 #pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1 #pragma config FWDTEN=OFF, ICESEL=ICS_PGx2 //------------------------------------------------------------ #define HOLD_RUN_SW PORTBbits.RB0 #define TRIG_SLOPE_SW PORTBbits.RB1 // トリガはCH1の立上り、立下りの2種類のみとした #define TRIG_MODE_SW PORTGbits.RG6 #define READY_SW PORTGbits.RG7 #define CH1 0x01 #define CH2 0x02 #define CH3 0x04 #define CH4 0x08 #define CH5 0x10 #define CH6 0x20 //------------------------------------------------------------ /// メッセージテーブル char str_Start[] = "Easy 6CH LogAna V1"; char str_WaitTrig[] = "Waiting for trigger"; char str_1us[] = "50uS/D SMP= 1uS"; char str_2us[] = "0.1mS/D SMP= 2uS"; char str_4us[] = "0.2mS/D SMP= 4uS"; char str_10us[] = "0.5mS/D SMP= 10uS"; char str_20us[] = "1mS/D SMP= 20uS"; char str_40us[] = "2mS/D SMP= 40uS"; char str_100us[]= "5mS/D SMP= 100uS"; char str_200us[]= "10mS/D SMP= 200uS"; char str_400us[]= "20mS/D SMP= 400uS"; char str_1_0ms[]= "50mS/D SMP= 1.0mS"; /// A Variable (Global) /// Data Buffer for GLCD unsigned short Buffer[512]; unsigned short Index,SW; unsigned short Dummy; char EndFlag; char HOLD_ON_flag = 0; char hold_status = 0; char READY_flag = 0; char ready_status = 0; char POS_flag = 1; // Defult Trigger Slope is positive unsigned short ptr; // バッファ読出しポインタ unsigned short Xpos= 0; /// 注意:Glcd_Line関数で扱う原点(0,0)は、左下角だが、 /// Glcd_Pixcel関数で扱う原点(0,0)は、左上角なので /// Yポジション(CH1 Lowレベル位置)の変数が、2個必要 unsigned short Ypos_line= 208; // Glcd_Line関数(エッジ描画で使用)の、CH1 Lowレベル位置初期化 unsigned short Ypos_dot= 31; // Glcd_Pixcel関数(レベル描画で使用)の、CH1 Lowレベル位置初期化 /// Function Prottypes void LogAna(void); void AxisDraw(void); void LogicCheck_and_GlcdDraw(char channel, unsigned short Xtrg, unsigned short color); void LogAna_single_trigger(void); void Single_trigger_mode(void); //void itostring(char digit, unsigned int data, char *buffer); /************************************************ * Function Main ************************************************/ int main(void) { //システム最適設定 SYSTEMConfigPerformance(80000000); mJTAGPortEnable(DEBUG_JTAGPORT_OFF); // JTAGを無効化 //I/O設定 AD1PCFG = 0xFFFF; //I/O設定 TRISB = 0xFFFF; // RB0:HOLD_SW, RB1:TRG_SLOPE_SW, RB2:DSW-1,RB3:DSW-2、RB4:DSW-4、RB5:DSW-8入力、他未使用ピンも入力設定 TRISD = 0xFF07; // LCD_RS,CS,WR,RESET:全て出力・HOLD_LED:出力・SW2-5:入力、他未使用ピンは入力設定 TRISE = 0x0000; // LCDデータバス(DB0-DB7)オール出力 TRISF = 0xFFFF; // RF0-5:CH1-6入力(5Vトレラント・ピン) TRISG = 0xFEFF; // RG6:TRIG_MODE_SW, RG7:READY_SW入力, RG8:READY_LED出力 LATDbits.LATD3 = 1; // HOLD_LED消灯 LATGbits.LATG8 = 1; // READY_LED消灯 // 液晶表示器の初期化 Glcd_Init(); Glcd_Clear(BLACK); Glcd_Str(0, 0, str_Start, CYAN, BLACK); delay_ms(1000); /// Timer3:T3初期設定= Tcy*PS*n= 0.0125uS*2*400 = 10uS PR3 = 399; // n = 400 (PR3=n-1 OpenTimer3(T3_OFF | T3_SOURCE_INT | T3_PS_1_2, PR3); // タイマ3割り込み設定 ConfigIntTimer3(T3_INT_ON | T3_INT_PRIOR_7); /// スイッチ状態変化割込み許可 mCNOpen(CN_ON, CN2_ENABLE | CN3_ENABLE | CN9_ENABLE, CN2_PULLUP_ENABLE| CN3_PULLUP_ENABLE| CN4_PULLUP_ENABLE| CN5_PULLUP_ENABLE| CN6_PULLUP_ENABLE | CN7_PULLUP_ENABLE | CN8_PULLUP_ENABLE | CN9_PULLUP_ENABLE); // CN機能使用SW:HOLD_SW, TRIG_SLOPE_SW, READY_SW // 内部プルアップ使用SW:全てのSW // ダミー入力で、PIC内外の状態を一致させ、割込み要因をリセットする // これがないと、CN割込み許可直後に割込みが発生してしまうことがある!!(→ 実際に割込みが発生してしまった) // (尚、簡易4CHロジアナの実験ソフトでは、これがなくても問題は起こらなかった) Dummy= PORTB; Dummy= PORTG; mCNClearIntFlag(); //割り込みフラグクリア ConfigIntCN(CHANGE_INT_ON | CHANGE_INT_PRI_2); // 割り込み有効化 // マルチベクタ割り込み設定、割り込み許可 INTEnableSystemMultiVectoredInt(); //// メイン・ループ while(1){ /// Inittalize Variable Index = 0; EndFlag = 0; ConfigIntCN(CHANGE_INT_ON | CHANGE_INT_PRI_2); // CN割り込み有効化 if (TRIG_MODE_SW) { // Trigger is Normal Mode /// Switching Sampling Period SW = (~PORTB & 0x003C) >> 2; // Read Decimal Dip SW switch(SW){ case 0: PR3 = 39; // 1usec break; case 1: PR3 = 79; // 2usec break; case 2: PR3 = 159; // 4usec break; case 3: PR3 = 399; // 10usec break; case 4: PR3 = 799; // 20usec break; case 5: PR3 = 1599; // 40usec break; case 6: PR3 = 3999; // 100usec break; case 7: PR3 = 7999; // 200usec break; case 8: PR3 = 15999; // 400usec break; case 9: PR3 = 39999; // 1000usec break; default:PR3 = 399; // 10usec break; } LATGbits.LATG8 = 1; // Red LED OFF READY_flag = 0; ready_status = 0; T3CONbits.TON = 1; // T3ON-> CH入力サンプリング開始 while(!EndFlag); LogAna(); // Disp. LogAna EndFlag = 0; Index = 0; /// Cheack HOLD_RUN_SW Status while (HOLD_ON_flag) { hold_status = 1; } hold_status = 0; delay_ms(1000); // Disp. is 1.0Sec Period } else Single_trigger_mode(); } } /*********************************************************** * T3割込み処理 * CH入力サンプル〜 メモリーにロジックレベル・データ格納 ************************************************************/ void __ISR(12, ipl7) T3Handler(void) { mT3ClearIntFlag(); //割り込みフラグクリア // LATDbits.LATD3 = ~LATDbits.LATD3; Buffer[Index] = PORTF & 0x3F; // 6CH分のデータをバッファへ格納 ++Index; if(Index >= 512) { // Buffer Full ? T3CONbits.TON = 0; // Buffer Full Then T3 OFF EndFlag = 1; // and End Flag ON } } /********************************************* * スイッチ状態変化割り込み処理 * HOLD SW, TRIG_MODE_SW **********************************************/ void __ISR(26, ipl2) CNHandler(void){ delay_ms(10); // スイッチ安定待ち if (!hold_status) { // hold_status -> 0: RUN if (!HOLD_RUN_SW) HOLD_ON_flag = 1; } else { // hold_status -> 1: HOLD_ON Loop if (!HOLD_RUN_SW) HOLD_ON_flag = 0; } if (ready_status) { if (!READY_SW) READY_flag = 1; } if (!TRIG_SLOPE_SW) { if (POS_flag) POS_flag = 0; else POS_flag = 1; } delay_ms(10); // スイッチON->OFF時の、チャッタ回避 Dummy= PORTB; // 状態合わせ Dummy= PORTG; mCNClearIntFlag(); //割り込みフラグクリア } /************************************************************** * トリガ検知を行った後、保存したロジックレベル・データを読出し * ロジアナ表示する ***************************************************************/ void LogAna(void){ unsigned short i, x; AxisDraw(); // 座標表示 x= 0; /// Check Trigger if (POS_flag) { // Trigger Slope is positive while((x < 192) && !(((Buffer[x] & CH1) == 0) && ((Buffer[x+1] & CH1) == 1))) { x++; } } else { // Trigger Slope is negative while((x < 192) && !(((Buffer[x] & CH1) == 1) && ((Buffer[x+1] & CH1) == 0))) { x++; } } //// Detect Trigger-> Disp. 320Data from this Position if(x<128){ /// 液晶の、1画面分(横:320dot)に各CHのロジック状態を描画する for(ptr= 0; ptr< 320; ptr++) { LogicCheck_and_GlcdDraw(CH1, x, MAGENTA); // CH1ロジック状態描画 Ypos_line= 174; // CH2の基準線に描画移動 Ypos_dot= 65; LogicCheck_and_GlcdDraw(CH2, x, GREEN); // CH2ロジック状態描画 Ypos_line= 140; // CH3の基準線に描画移動 Ypos_dot= 99; LogicCheck_and_GlcdDraw(CH3, x, CYAN); // CH3ロジック状態描画 Ypos_line= 106; // CH4の基準線に描画移動 Ypos_dot= 133; LogicCheck_and_GlcdDraw(CH4, x, YELLOW); // CH4ロジック状態描画 Ypos_line= 72; // CH5の基準線に描画移動 Ypos_dot= 167; LogicCheck_and_GlcdDraw(CH5, x, ORANGE); // CH5ロジック状態描画 Ypos_line= 38; // CH6の基準線に描画移動 Ypos_dot= 201; LogicCheck_and_GlcdDraw(CH6, x, BLUE); // CH6ロジック状態描画 Ypos_dot= 31; // Yポジション初期化 Ypos_line= 208; Xpos++; // Xポジションを1つ進める } Xpos= 0; } /// Not Detect Trigger-> Disp. "Waiting for trigger" else Glcd_Str(0, 0, str_WaitTrig, WHITE, BLACK); } /****************************************************** * Disp. Oscillo and Cheack trigger for Single mode *******************************************************/ void LogAna_single_trigger(void){ unsigned short i, x; x= 0; // First Data /// Check Trigger if (POS_flag) { // Trigger Slope is positive while((x < 192) && !((Buffer[x] & CH1) == 0 && (Buffer[x+1] & CH1) == 1)) { x++; } } else { // Trigger Slope is negative while((x < 192) && !((Buffer[x] & CH1) == 1 && (Buffer[x+1] & CH1) == 0)) { x++; } } //// Detect Trigger-> Disp. 320Data from this Position if(x<128){ LATGbits.LATG8 = 1; // Ready LED OFF AxisDraw(); /// 液晶の、1画面分(横:320dot)に各CHのロジック状態を描画する for(ptr= 0; ptr< 320; ptr++) { LogicCheck_and_GlcdDraw(CH1, x, MAGENTA); // CH1ロジック状態描画 Ypos_line= 174; // CH2の基準線に描画移動 Ypos_dot= 65; LogicCheck_and_GlcdDraw(CH2, x, GREEN); // CH2ロジック状態描画 Ypos_line= 140; // CH3の基準線に描画移動 Ypos_dot= 99; LogicCheck_and_GlcdDraw(CH3, x, CYAN); // CH3ロジック状態描画 Ypos_line= 106; // CH4の基準線に描画移動 Ypos_dot= 133; LogicCheck_and_GlcdDraw(CH4, x, YELLOW); // CH4ロジック状態描画 Ypos_line= 72; // CH5の基準線に描画移動 Ypos_dot= 167; LogicCheck_and_GlcdDraw(CH5, x, ORANGE); // CH5ロジック状態描画 Ypos_line= 38; // CH6の基準線に描画移動 Ypos_dot= 201; LogicCheck_and_GlcdDraw(CH6, x, BLUE); // CH6ロジック状態描画 Ypos_dot= 31; // Yポジション初期化 Ypos_line= 208; Xpos++; // Xポジションを1つ進める } Xpos= 0; READY_flag = 0; } /// トリガ未検知の場合は何もしない } /********************************************* * Single_trigger_mode **********************************************/ void Single_trigger_mode(void) { hold_status = 1; while ((!READY_flag) && (!TRIG_MODE_SW)) { ready_status = 1; } if (!TRIG_MODE_SW) { ready_status = 0; LATGbits.LATG8 = 0; // Ready LED ON T3CONbits.TON = 1; // T3ON-> CH入力サンプリング開始 while(!EndFlag); // T3割込み処理へ:6CH分のデータ収集 LogAna_single_trigger(); // 6CH分のデータ収集が全て終了したら、ロジアナ表示する } } /****************************************** * Drawing Coordinate Axis *******************************************/ void AxisDraw(void){ int i; Glcd_Clear(BLACK); /// X、Y座標軸表示 for(i=0; i<319; i+=50) Glcd_Line(i, 0, i, 239, BROWN); // Y axis Glcd_Line(0, 0, 319, 0, BROWN); // 最下位ライン:下外枠ライン Glcd_Line(0, 38, 319, 38, BROWN); // X axis :6CH Lowレベルライン for(i=72; i<209; i+=34) Glcd_Line(0, i, 319, i, BROWN); // X axis :5CH〜 1CH Lowレベルライン Glcd_Line(0, 239, 319, 239, BROWN); // 最上位ライン:上外枠ライン /// サンプル周期表示 switch(SW){ case 0: Glcd_Str(8, 16, str_1us, WHITE, BLACK); break; case 1: Glcd_Str(8, 16, str_2us, WHITE, BLACK); break; case 2: Glcd_Str(8, 16, str_4us, WHITE, BLACK); break; case 3: Glcd_Str(8, 16, str_10us, WHITE, BLACK); break; case 4: Glcd_Str(8, 16, str_20us, WHITE, BLACK); break; case 5: Glcd_Str(8, 16, str_40us, WHITE, BLACK); break; case 6: Glcd_Str(8, 16, str_100us, WHITE, BLACK); break; case 7: Glcd_Str(8, 16, str_200us, WHITE, BLACK); break; case 8: Glcd_Str(8, 16, str_400us, WHITE, BLACK); break; case 9: Glcd_Str(8, 16, str_1_0ms, WHITE, BLACK); break; default:Glcd_Str(8, 16, str_10us, WHITE, BLACK); break; } /// TRGエッジ表示 if (POS_flag) Glcd_Char(7, 16, 0x8D, YELLOW, BLACK); // TRG+表示 else Glcd_Char(7, 16, 0x8E, YELLOW, BLACK); // TRG-表示 /// Disp. HOLD LED if (HOLD_ON_flag == 1) LATDbits.LATD3 = 0; else LATDbits.LATD3 = 1; } /************************************************************ * ロジック・レベル・バッファの内容を、引数により * 各CH毎に、チェックし、ロジック・レベル状態を液晶に描画する * 判断すべきロジック・レベル状態は、以下の4種類 * @ Hiレベル(変化なし) * A Loレベル(変化なし) * B 立上りエッジ * C 立下りエッジ * * 引数:channel * 0x01:CH1 * 0x02:CH2 * 0x04:CH3 * 0x08:CH4 * 0x10:CH5 * 0x20:CH6 * * Xtrg * トリガ検知点のバッファ位置(x変数の値が代入される) * * color * MAGENTA (CH1) * GREEN (CH2) * CYAN (CH3) * YELLOW (CH4) * ORANGE (CH5) * BLUE (CH6) *************************************************************/ void LogicCheck_and_GlcdDraw(char channel, unsigned short Xtrg, unsigned short color){ char shift; if (channel == CH1) shift= 0; if (channel == CH2) shift= 1; if (channel == CH3) shift= 2; if (channel == CH4) shift= 3; if (channel == CH5) shift= 4; if (channel == CH6) shift= 5; if (((Buffer[ptr+Xtrg] & channel) >> shift == 0) && ((Buffer[ptr+Xtrg+1] & channel) >> shift == 0)) { // Lowレベル検知なので以下の、ドット描画を行う Glcd_Pixel(Xpos, Ypos_dot, color); } if (((Buffer[ptr+Xtrg] & channel) >> shift == 1) && ((Buffer[ptr+Xtrg+1] & channel) >> shift == 1)) { // Hiレベル検知なので以下の、ドット描画を行う Glcd_Pixel(Xpos, Ypos_dot-19, color); } if (((Buffer[ptr+Xtrg] & channel) >> shift == 0) && ((Buffer[ptr+Xtrg+1] & channel) >> shift == 1)) { // 立上りエッジ検知なので以下の、ライン描画を行う Glcd_Line(Xpos, Ypos_line, Xpos, Ypos_line+19, color); } if (((Buffer[ptr+Xtrg] & channel) >> shift == 1) && ((Buffer[ptr+Xtrg+1] & channel) >> shift == 0)) { // 立下りエッジ検知なので以下の、ライン描画を行う Glcd_Line(Xpos, Ypos_line+19, Xpos, Ypos_line, color); } } /* ///////////////////////////////////////// // 数値から文字列に変換 ///////////////////////////////////////// void itostring(char digit, unsigned int data, char *buffer){ char i; buffer += digit; // 文字列の最後 for(i=digit; i>0; i--) { // 最下位桁から上位へ buffer--; // ポインター1 *buffer = (data % 10) + '0'; // その桁数値を文字にして格納 data = data / 10; // 桁-1 } } */