Close

Digital Sniffer

A project log for Multimeter +

Dual input 24 bit Multimeter with USB interface, single channel 10 bit USB oscilloscope, PWM out, 2 Ch Data-logger, R, C, Digital sniffer.

romanRoman 07/02/2016 at 15:330 Comments

I am currently working on the Digital Sniffer. The following image show the interface schematics.

Expansion Port:

Signal is applied to Pin 1 of the SNSR1 connector. Pin 2 is the ground return. Signal is buffered and inverted by the Q43, NDS7002, MOSFET. D24 is used to protect Q43 from overvoltage condition. Passing the buffer, the signal is applied to PIN 93 MCU. RG14 is an interrupt pin CN81. CN81 is the Input Change Notification pin. The input change notification function of the I/O ports allows the PIC24FJ256GA110 family of devices to generate interrupt requests to the processor in response to a change of state on selected input pins. This feature is capable of detecting input change of states even in Sleep mode, when the clocks are disabled.

MCU:

Interrupt is initialized inside init_logic_analyzer() function.

PIC24FJ256GA110:

// <editor-fold defaultstate="collapsed" desc="Initialize CN82 on RG15 Interrupt">
    CNEN6bits.CN82IE    	= 1; // Enable interrupt on CN82 RG15 2N7002
    CNPD6bits.CN82PDE   = 0;    	// Pull down disable
    CNPU6bits.CN82PUE   = 0;    	// Pull up disable
    CNEN6bits.CN81IE    	= 1;    	// Enable interrupt on CN81 RG14
    CNPD6bits.CN81PDE   = 0;    	// Pull down disable
    CNPU6bits.CN81PUE   = 0;    	// Pull up disable
    IEC1bits.CNIE       	= 1;    	// Enable interrupt on pin change
    IFS1bits.CNIF       	= 0;    	// Clear the flag
    IPC4bits.CNIP       	= 4;    	// Interrupt priority 4  
    // </editor-fold>            
    flags = 13;         // Indicates that the Logic Analyzer has been initialized.    
    return;
}
Once interrupt is initialized it is ready to read input from

SNSR1 PIN1.

OSCILLATOR data:

Primary oscillator = 7.3728MHZ

Phase Lock Loop:

XTPLL = 4 x PLL = 7.3728MHZ x 4 = 29.4912MHz

FCY = XTPLL/2 = 14.7456MHz. FCY is defined as XTPLL/2

The processor clock source is divided by two to produce the internal instruction

cycle clock, FCY.

TCY = 1 / FCY = 1 / 14.7456MHz = 0.067817 us

INTERRUPT PROCESSING TIMING

Figure 8-3 shows the sequence of events when a peripheral interrupt is asserted during a
one-cycle instruction. The interrupt process takes four instruction cycles. Each cycle is numbered
in Figure 8-3 for reference.

The interrupt process takes four instruction cycles.

TINTERRUPT = TCY * 4 = 0.067817 * 4 = 0.271 us

FMAX-INTERRUPT = 1 / 0.271 us = 3.69 MHz

Each instruction has Fetch and Execute parts. It takes TCY

for each instruction (oscillator).

It looks like I have 16 - 17 instructions in the ISR, then

T = TINTERRUPT + 17 * 0.067817 = 1.017 us + 0.271 us = 1.363us

Max input data-stream frequency is:

FDATA = 1 / 1.363 = 0.7 MHz

I have tested Multimeter+ with max frequency of 500 kHz. Its kind of slow for a logic Analyzer, but for a regular multimeter it adds value.

The following code triggers on every CIN interrupt and shifts in a bit of data.

// Global
volatile WORD_VAL timer[8];
extern volatile unsigned int  TMR1 __attribute__((__sfr__));
volatile DWORD_VAL NmbrOfBits;
volatile WORD_VAL TimeBase;
volatile unsigned long ints;
volatile unsigned char mask_l;                            
void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void){
    // Time interval = Number of counts * Time of one count
    timer[0].Val = (WORD)(TMR1 * 68);            
    NmbrOfBits.Val = timer[0].Val / TimeBase.Val;
    TMR1 = 0;
    if (LAcntr < 2048){
        if (NmbrOfBits.Val == 0){
            goto skip;          // Skip all
        }
        else if (NmbrOfBits.Val == 1){                       // 7 bits left 
                // Input is inverted !_RG14 is actually _RG14.
                // If RG15 is low set current bit to zero with mask_h = 0xFE
                if (_RG14) {
                    voltage_msb[LAcntr] = mask_h;  // mask_h  is initialized to 0b1111 1110
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // ~mask_h = 0b0000 0001
                }                     
        }
        else if (NmbrOfBits.Val == 2){
                // <editor-fold defaultstate="collapsed" desc="2 bit">   
                mask_h = mask_h << 1; // 1111 1110 << 1 = 1111 1100
                // Input is inverted !_RG14 is actually _RG14.
                // If RG15 is low set current bit to zero with mask_h = 0x0b11111100
                if (_RG14) { 
                    voltage_msb[LAcntr] = mask_h;  // mask_h << 1  = 0b1111 1100
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // ~mask_h << 1 = 0b0000 0011
                }                
                // </editor-fold>
            }
            else if (NmbrOfBits.Val == 3){
                // <editor-fold defaultstate="collapsed" desc="3 bit">     
                mask_h = mask_h << 2; // 1111 1110 << 2 = 1111 1000
                if (_RG14) { // Input is inverted !_RG14 is actually _RG14. If RG14 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] = mask_h;  // mask_h  << 2 = 0b1111 1000
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // ~mask_h << 2 = 0b0000 0111
                }                
                // </editor-fold>
            }
            else if (NmbrOfBits.Val == 4){                  // 0000 0001 << 4 = 0001 0000
                // <editor-fold defaultstate="collapsed" desc="4 bit"> 
                mask_h = mask_h << 3; // 1111 1110 << 3 = 1111 0000
                if (_RG14) { // Input is inverted !_RG14 is actually _RG14. If RG14 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] = mask_h;  // mask_h << 3  = 0b1111 0000
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // ~mask_h << 3 = 0b0000 1111
                }                
                // </editor-fold>
            }
            else if (NmbrOfBits.Val == 5){                  // 0000 0001 << 5 = 0010 0000
                // <editor-fold defaultstate="collapsed" desc="5 bit">  
                mask_h = mask_h << 4; // 1111 1110 << 4 = 1110 0000
                if (_RG14) { // Input is inverted !_RG14 is actually _RG14. If RG14 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] = mask_h; // LAcntr is incremented when byte of data has been shifted
                } else { // If RG14 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // Turn on bit zero (mask_l = 0x01). If the first bit is one save one in voltage_msb[0] bit 0
                }                
                // </editor-fold>
            }
            else if (NmbrOfBits.Val == 6){                  // 0000 0001 << 6 = 0100 0000
                // <editor-fold defaultstate="collapsed" desc="6 bit">   
                mask_h = mask_h << 5; // 1111 1110 << 5 = 1100 0000
                if (_RG14) { // If RG15 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] = mask_h; // LAcntr is incremented when byte of data has been shifted
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // Turn on bit zero (mask_l = 0x01). If the first bit is one save one in voltage_msb[0] bit 0
                }
                
                // </editor-fold>
            }
            else if (NmbrOfBits.Val == 7){                  // 0000 0001 << 7 = 1000 0000
                // <editor-fold defaultstate="collapsed" desc="7 bit">
                mask_h = mask_h << 6; // 1111 1110 << 6 = 1000 0000
                if (_RG14) { // If RG15 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] = mask_h; // LAcntr is incremented when byte of data has been shifted
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; // Turn on bit zero (mask_l = 0x01). If the first bit is one save one in voltage_msb[0] bit 0
                }
                
                // </editor-fold>
            }
            else if (NmbrOfBits.Val == 8){                  // 0000 0001 << 7 = 0000 0000
                // <editor-fold defaultstate="collapsed" desc="8 bit">
                mask_h = mask_h << 7; // 1111 1110 << 7 = 0000 0000
                //mask_l = mask_l << 8;
                if (_RG14) { // If RG15 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] = mask_h; // LAcntr is incremented when byte of data has been shifted
                } else { // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h; //Turn on bit zero (mask_l = 0x01). If the first bit is one save one in voltage_msb[0] bit 0
                }
                
                // </editor-fold>               
            }          
            else { // If time lapse is more then 8 bit
                //mask_l = mask_l << 8;                     // Indicate full byte has been received
                mask_h = mask_h << 7;                       // This will indicate that a full byte has been received
                if (_RG14) {                                // If RG15 is low set current bit to zero with mask_h = 0x0b11111100
                    voltage_msb[LAcntr] =  mask_h;     // LAcntr is incremented when byte of data has been shifted
                } else {                                    // If RG15 is high set current bit to one with mask_h = 0x01
                    voltage_msb[LAcntr] = ~mask_h;     // Turn on bit zero (mask_l = 0x01). If the first bit is one save one in voltage_msb[0] bit 0
                }
                LAcntr++;               // Increment byte count 
                mask_h  = 0xFE;         // Reset mask for the new byte
                //mask_l  = 0x01;         // Reset mask for the new byte                 
                if(NmbrOfBits.Val > 8){
                    NmbrOfBits.Val = NmbrOfBits.Val - 8;
                    goto start2047;
                }               
                else
                    mask_h == 0x00;     // Exit to if (mask_l == 0x00)                         
            }    
        


}

Discussions