/********************************************************** * Scope Hardware V2 * Scope Soft Ver1.02 * Graphic LCD(Monochrome): SG12864A * * Add Auto Renge Setting / Disp. Volt/div and DC/AC * Add HOLD Function ana Single Trigger * Add SLOPE +/- (POS Edge/ NEG Edge Trigger) * * Condition: * 8MHz External X'tal Oscillator, 10x PLL (8MHzx10= 80MHz) * Fcy=80MHz/2=40MHz, Tcy=25ns * * CPU: PIC24HJ64GP206 * * Original Program: Mr.Gokan(CPU: PIC24HJ12GP202) * Mod. N.Ishii 2012.4.6 ************************************************************/ #include #include "glcd_lib_pic24hj64.h" /// Set Configuration Word: 8MHz External X'tal OSC _FBS(BSS_NO_FLASH & BWRP_WRPROTECT_OFF ) _FGS(GSS_OFF & GCP_OFF & GWRP_OFF ) _FOSCSEL(FNOSC_PRIPLL & IESO_ON) _FOSC(FCKSM_CSECME & OSCIOFNC_OFF & POSCMD_XT ) _FWDT(FWDTEN_OFF & WINDIS_OFF) _FPOR(FPWRT_PWR32) //--------------------------------------------------------------- #define AC_DC_SW PORTFbits.RF5 #define HOLD_RUN_SW PORTFbits.RF4 #define TRIG_MODE_SW PORTCbits.RC13 #define READY_SW PORTCbits.RC14 #define SLOPE_SW PORTDbits.RD7 #define GAIN_A LATDbits.LATD1 #define GAIN_B LATDbits.LATD2 #define ATT_A LATDbits.LATD4 #define ATT_B LATDbits.LATD5 #define AC_DC_A LATDbits.LATD3 //-------------------------------------------------------------- /// A Variable (Global) // Data Buffer for GLCD int Buffer1[192]; int Buffer2[192]; int Index,POT,TSW,VSW; char EndFlag; // DMA_Buffer Location & BufferA/B Change Flag unsigned int BufferA[8] __attribute__((space(dma))); // AN0:Signal unsigned int BufferB[8] __attribute__((space(dma))); // AN2:TRIG unsigned int DmaBuffer = 0; 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 //--------------------------------------------------------------- ///@Function Prottypes void Oscillo(void); void AxisDraw(void); void dotyline(int x0); void dotxline(int y0); void Read_VSW_Set_Renge(void); void Oscillo_single_mode(void); void Single_trigger_mode(void); /************************************************ * Function Main ************************************************/ int main(void){ /* Initialize Clock */ CLKDIVbits.PLLPRE = 0; // PLLPRE=1/2 to 4MHz PLLFBDbits.PLLDIV = 40; // PLLDIV=1/40 to 160MHz CLKDIVbits.PLLPOST = 0; // PLLPOST=1/2 to 80MHz then 40MIPS /* Initialize Port */ AD1PCFGL = 0xFFF8; // AN0-2 are Analog AD1PCFGH = 0xFFFF; // OTHER Digital // Initialize GLCD Control Signal Level LCD_E = 0; LCD_CS1 = 1; LCD_CS2 = 1; LCD_RW = 1; LCD_DI = 1; TRISB = 0x00FF; // LCD_DataPort(RB8-RB15) is output, TSW_IN(RB3-RB5), SLOPE_SW(RB1) is input TRISC = 0xFFFF; // TRG_MODE_SW, READY_SW(RC13, RC14) is input ODCD = 0x003E; // GAIN-A,GAIN-B,AC/DC-A,ATT-A,ATT-B(RD1-TD5) is open dorein out TRISD = 0xF0C0; // LCD_ControlPort(RD0, RD8-RD11) is output TRISF = 0xFFFD; // HOLD/RUN_SW, AC/DC_SW(RF4, RF5) is input, READY_LED(RF1) is output TRISG = 0xFFFE; // TRG_LED(RG0) is output, VSW-1,2,4,8(RG6-RG9) is input CNPU1 = 0x0FE3; // RB3-5, RC13,14, RG6-9 is pull up CNPU2 = 0x0007; // RF4,5, RD7 is pull up /// Set Switch Change Notification Interrupts CNEN1 = 0x0001; // Valid CN0: READY_SW CNEN2 = 0x0003; // Valid CN17: HOLD_RUN_SW, CN16: SLOPE_SW IPC4bits.CNIP = 3; // The Order of Priority: CN INT=6, (DMA5 Defult INT=4) IEC1bits.CNIE = 1; // Enable CN INT LATGbits.LATG0 = 1; // Green LED OFF LATFbits.LATF1 = 1; // Red LED OFF: add 120330 /* Initialize GLCD */ lcd_Init(); lcd_Clear(0); lcd_Str(0, 1, "Soft Ver1.02"); Delay1m(1000); /* Initialize DMA */ DMA5CONbits.AMODE = 0; // Configure DMA for Register indirect mode // with post-increment DMA5CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode DMA5PAD = (volatile unsigned int)&ADC1BUF0; // Point DMA to ADC1BUF0 DMA5CNT = 7; // 8 DMA request DMA5REQ = 13; // Select ADC1 as DMA Request source (IREQ13) DMA5STA = __builtin_dmaoffset(BufferA); // Read New DMA Address A-side DMA5STB = __builtin_dmaoffset(BufferB); // Read New DMA Address B-side IFS3bits.DMA5IF = 0; //Clear the DMA interrupt flag bit IEC3bits.DMA5IE = 1; //Set the DMA interrupt enable bit DMA5CONbits.CHEN=1; // Enable DMA /* Initialize ADC (Set up ADC1 for DMA operation) */ AD1CON1 = 0x0044; // Module Off, 10bit, Format Integer, T3 Trigger, Auto Sample(Only AN0) AD1CON2 = 0x041E; // Vref=AVdd-AVss,Interrupt Timmin=8 Times (Divide Buffer) AD1CON3 = 0x0203; // Acquisition Time=2Tad, 1Tad=3*Tcy (75nsec*14=1.05usec) AD1CON4 = 0x0003; // Allocates 8 words of DMA Buffer to each analog input: add 120308 AD1CHS123= 0x0000; // AD Channel-0,1,2,3 Select AD1CHS0 = 0x0000; // AD Channel-0 Select AD1CSSH = 0x0000; // Not used hight channel: 120222 AD1CSSL = 0x0005; // Auto Scan CH0,2 AD1PCFGL = 0xFFF8; // AD Channel-0,1,2(RA0,1,2) is Aanalog Input AD1CON1bits.ADON = 1; // ADC ON /* Inittalize Timer3:T3= Tcy*PS*n= 0.025uS*1*400 = 10uS */ PR3 = 399; // n = 400 (PR3=n-1): Mod. 0x018F-> 399 T3CON = 0x0000; // T3_OFF, T3_GATE_OFF, T3_PS_1_1, T3_SOURCE_INT /****** Main Loop ****/ while(1){ /* Draw a Graph of Input Wave Data */ EndFlag = 0; // Clear End of Convertion Flag Index = 0; if (TRIG_MODE_SW) { // Trigger is AUTO Mode /* Switching Sampling Period */ TSW = (~PORTB & 0x0038) >> 3; // Read Decimal Dip SW /// Add Branch Set PS3 if (TSW == 7) T3CONbits.TCKPS = 1; // PS3 = 1/8 else T3CONbits.TCKPS = 0; // PS3 = 1/1 switch(TSW){ case 0: PR3 = 79; // 2usec break; case 1: PR3 = 199; // 5usec break; case 2: PR3 = 399; // 10usec break; case 3: PR3 = 799; // 20usec break; case 4: PR3 = 1999; // 50usec break; case 5: PR3 = 3999; // 100usec break; case 6: PR3 = 19999; // 500usec break; case 7: PR3 = 24999; // 5msec break; default:PR3 = 399; // 10usec break; } /// Add Read VSW and Volte Renge Setting Read_VSW_Set_Renge(); /// Add Read AC_DC_SW and Analog SW Contorol if (AC_DC_SW == 0) AC_DC_A = 0; // DC Mode else AC_DC_A = 1; // AC Mode LATFbits.LATF1 = 1; // Red LED OFF READY_flag = 0; ready_status = 0; T3CONbits.TON = 1; // T3ON-> ADC Start while(!EndFlag); Oscillo(); // Disp. Oscillo EndFlag = 0; Index = 0; /// Cheack HOLD_RUN_SW Status while (HOLD_ON_flag) { hold_status = 1; } hold_status = 0; Delay1m(500); } else Single_trigger_mode(); } } /************************************************ * ADC : 2Channel(AN0:Signal, AN2:Triger) 4Times*2 * DMA Interrupt Period = T3_Period*2*4 *************************************************/ void __attribute__((interrupt, auto_psv)) _DMA5Interrupt(void) { // Switch between Primary and Secondary Ping-Pong buffers if(DmaBuffer == 0) { Buffer1[Index++] = BufferA[0]; // 1Times: Buffer <- AN0 Input Data(DMA BUF_A_side) Buffer1[Index++] = BufferA[2]; // 2Times: Buffer <- AN0 Input Data(DMA BUF_A_side) Buffer1[Index++] = BufferA[4]; // 3Times: Buffer <- AN0 Input Data(DMA BUF_A_side) Buffer1[Index++] = BufferA[6]; // 4Times: Buffer <- AN0 Input Data(DMA BUF_A_side) POT = BufferA[7]; // Store is AN2 Trigger Potentio Input ADC Value (DMA BUF_A_side) // POT = (BufferA[1]+BufferA[3]+BufferA[5]+BufferA[7])/4; } else{ Buffer1[Index++] = BufferB[0]; // 1Times: Buffer <- AN0 Input Data(DMA BUF_B_side) Buffer1[Index++] = BufferB[2]; // 2Times: Buffer <- AN0 Input Data(DMA BUF_B_side) Buffer1[Index++] = BufferB[4]; // 3Times: Buffer <- AN0 Input Data(DMA BUF_B_side) Buffer1[Index++] = BufferB[6]; // 4Times: Buffer <- AN0 Input Data(DMA BUF_B_side) POT = BufferB[7]; // Store is AN2 Trigger Potentio Input ADC Value (DMA BUF_B_side) // POT = (BufferB[1]+BufferB[3]+BufferB[5]+BufferA[7])/4; } DmaBuffer ^= 1; // ALT DmaBuffer Flag if(Index >= 192){ // Buffer Full ? T3CONbits.TON = 0; // Buffer Full Then T3 OFF and EOC Flag ON EndFlag = 1; } IFS3bits.DMA5IF = 0; //Clear the DMA5 Interrupt Flag } /******************************************************* * Switch Change Notification Interrupts ********************************************************/ void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) { Delay1m(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 (!SLOPE_SW) { if (POS_flag) POS_flag = 0; else POS_flag = 1; } IFS1bits.CNIF = 0; // Clead CNIF Flag } /******************************************************* * Disp. Oscillo (Disp. Save Buffer Data) * Detect Trigger-> Disp. 128Data from this Position * Not Detect Trigger-> Disp. 128Data from Top Position *******************************************************/ void Oscillo(void){ int i,x; AxisDraw(); // Drawing Coordinate Axis x = 0; // First Data /* Check Trigger */ if (POS_flag) { while((x < 128) && !((Buffer1[x]=POT))){ x++; } } else { // Trigger Slope is negative while((x < 128) && !((Buffer1[x+1]=POT))){ x++; } } /* Detect Trigger-> Disp. 128Data from this Position */ if(x<64){ LATGbits.LATG0 = 0; // Green LED ON Add 110506 for(i=0; i<127; i++){ lcd_Line(i, Buffer1[i+x]/16, i+1, Buffer1[i+x+1]/16); // lcd_Line(i, Buffer2[i+x]/16, i+1, Buffer2[i+x+1]/16); } } /* Not Detect Trigger-> Disp. 128Data from Top Position */ else { LATGbits.LATG0 = 1; // Green LED OFF Add 110506 for(i=0; i<127; i++){ lcd_Line(i, Buffer1[i]/16, i+1, Buffer1[i+1]/16); // lcd_Line(i, Buffer2[i]/16, i+1, Buffer2[i+1]/16); } } } /****************************************************** * Disp. Oscillo and Cheack trigger for Single mode *******************************************************/ void Oscillo_single_trigger(void){ int i,x; x = 0; // First Data /* Check Trigger */ if (POS_flag) { while((x < 128) && !((Buffer1[x]=POT))){ x++; } } else { // Trigger Slope is negative while((x < 128) && !((Buffer1[x+1]=POT))){ x++; } } /// Detect Trigger-> Disp. 128Data from this Position if(x<64){ LATGbits.LATG0 = 0; // Green LED ON LATFbits.LATF1 = 1; // Red LED OFF AxisDraw(); for(i=0; i<127; i++){ lcd_Line(i, Buffer1[i+x]/16, i+1, Buffer1[i+x+1]/16); } READY_flag = 0; // 120328 } /// Not Detect Trigger-> Retry sample else { LATGbits.LATG0 = 1; // Green LED OFF } } /********************************************* * 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; LATFbits.LATF1 = 0; // Red LED ON T3CONbits.TON = 1; // T3ON-> ADC Start while(!EndFlag); Oscillo_single_trigger(); } } /*************************************************************** * Drawing Coordinate Axis (Add. Disp. DC/AC, Voite/div 120217) ****************************************************************/ void AxisDraw(void){ lcd_Clear(0); lcd_Line(0, 0, 0, 63); // Y axis dotyline(54); dotyline(107); lcd_Line(0, 32, 127, 32); // X axis dotxline(49); dotxline(17); /* Disp.SLOPE */ if (POS_flag == 1) lcd_Str(0,12,"SLOPE+"); else lcd_Str(0,12,"SLOPE-"); /* Disp. HOLD */ if (HOLD_ON_flag == 1) lcd_Str(0,1,"HOLD"); else lcd_Str(0,1," "); /* Disp. AC/DC */ if (AC_DC_SW == 0) lcd_Str(7,0,"DC"); else lcd_Str(7,0,"AC"); /* Disp. Unit Time Axis (msec/div) */ switch(TSW){ case 0: lcd_Str(7,11,"0.2mS/D"); break; case 1: lcd_Str(7,11,"0.5mS/D"); break; case 2: lcd_Str(7,11,"1.0mS/D"); break; case 3: lcd_Str(7,11,"2.0mS/D"); break; /// Add Disp. Unit Time Axis case 4: lcd_Str(7,11,"5.0mS/D"); break; case 5: lcd_Str(7,11,"10mS/D"); break; case 6: lcd_Str(7,11,"50mS/D"); break; case 7: lcd_Str(7,11,"500mS/D"); break; default:lcd_Str(7,11,"0.5mS/D"); break; } /* Disp. Unit Volt Axis (V/D or mV/D) */ switch(VSW){ case 0: lcd_Str(7,3,"15mV/D"); break; case 1: lcd_Str(7,3,"30mV/D"); break; case 2: lcd_Str(7,3,"75mV/D"); break; case 3: lcd_Str(7,3,"0.15V/D"); break; case 4: lcd_Str(7,3,"0.25V/D"); break; case 5: lcd_Str(7,3,"0.3V/D"); break; case 6: lcd_Str(7,3,"0.5V/D"); break; case 7: lcd_Str(7,3,"0.75V/D"); break; case 8: lcd_Str(7,3,"1.25V/D"); break; case 9: lcd_Str(7,3,"1.5V/D"); break; case 10:lcd_Str(7,3,"2.5V/D"); break; case 11:lcd_Str(7,3,"3.0V/D"); break; case 12:lcd_Str(7,3,"7.5V/D"); break; case 13:lcd_Str(7,3,"15V/D"); break; default:lcd_Str(7,3,"1.5V/D"); break; } } /******************************************* * Assist Line X Coordinate Axis (Dot Line) ********************************************/ void dotxline(int y0){ int i; for(i=0; i<128; i+=3) lcd_Pixel(i, y0-1, 1); } /******************************************* * Assist Line Y Coordinate Axis (Dot Line) ********************************************/ void dotyline(int x0){ int i; for(i=0; i<64; i+=3) lcd_Pixel(x0-1, i, 1); } //---------------------------------------------------------------- /**************************************************** * Read VSW_SW (Volt Renge SW) and Analog SW Setting *****************************************************/ void Read_VSW_Set_Renge(void) { VSW = (~PORTG & 0x03C0) >> 6; // Read Hex Dip SW switch(VSW) { case 0: ATT_A = 0; // 15mV/div ATT_B = 0; GAIN_A = 1; GAIN_B = 1; break; case 1: ATT_A = 0; // 30mV/div ATT_B = 0; GAIN_A = 0; GAIN_B = 1; break; case 2: ATT_A = 0; // 75mV/div ATT_B = 0; GAIN_A = 1; GAIN_B = 0; break; case 3: ATT_A = 0; // 150mV/div ATT_B = 0; GAIN_A = 0; GAIN_B = 0; break; case 4: ATT_A = 0; // 250mV/div ATT_B = 1; GAIN_A = 1; GAIN_B = 1; break; case 5: ATT_A = 1; // 300mV/div ATT_B = 0; GAIN_A = 0; GAIN_B = 1; break; case 6: ATT_A = 0; // 500mV/div ATT_B = 1; GAIN_A =0; GAIN_B = 1; break; case 7: ATT_A = 1; //750mV/div ATT_B = 0; GAIN_A = 1; GAIN_B =0; break; case 8: ATT_A = 0; //1250mV/div ATT_B = 1; GAIN_A = 1; GAIN_B =0; break; case 9: ATT_A = 1; // 1500mV/div ATT_B = 0; GAIN_A = 0; GAIN_B = 0; break; case 10: ATT_A = 0; // 2500mV/div ATT_B = 1; GAIN_A = 0; GAIN_B = 0; break; case 11: ATT_A = 1; // 3000mV/div ATT_B = 1; GAIN_A = 0; GAIN_B = 1; break; case 12: ATT_A = 1; // 7500mV/div ATT_B = 1; GAIN_A = 1; GAIN_B = 0; break; case 13: ATT_A = 1; // 15V/div ATT_B = 1; GAIN_A = 0; GAIN_B = 0; break; default: ATT_A = 1; // 1500mV/div ATT_B = 0; GAIN_A = 0; GAIN_B = 0; break; } }