Digital Sniffer


I am currently working on the Digital Sniffer.

The following image shows 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:

The interrupt is initialized inside init_logic_analyzer() function.

		PIC24FJ256GA110 interrupt initialization:
		
		// <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 is defined as XTPLL/2

FCY = XTPLL/2 = 14.7456MHz.

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.

Input Change Notification

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. Depending on the device pin count, there are up to 81 external inputs that may be selected (enabled) for generating an interrupt request on a change of state. _CNInterrupt(void) interrupt triggers on every CIN change of state. PIC24FJ256GA110 interrupt routine shifts in a bit of data on every CIN change. Files on Github


// Global Variables
volatile WORD_VAL timer[8];
extern volatile unsigned int  TMR1 __attribute__((__sfr__));
volatile DWORD_VAL NmbrOfBits;					// Number of bits received
volatile WORD_VAL TimeBase;					// Data rate entered from PC user interface 
volatile unsigned long ints;
volatile unsigned char mask_l;   


                         
void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void){
    TimeGap = (DWORD)(TMR1 * 68);				//n-sec. Time interval (n-sec) = Number of counts * Time of one count           
    NmbrOfBits.Val = TimeGap / TimeBase.Val;	//Number of bits based on the time interval
    TMR1 = 0;
    
/*
 *  ____      ____
 * |    |    |    |
 * |    |    |    |
 * |    |____|    |
 * 0    1    2    3 
 */    
    
start2047:    
    if (LAcntr < 2048){
        if (NmbrOfBits.Val == 0){
            goto skip;          // Skip all
        }
        else if (NmbrOfBits.Val == 1){                       // 7 bits left 
                // Input is inverted,so !_RG14 is actually _RG14.
                // If RG14 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 RG14 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
                // Input is inverted !_RG14 is actually _RG14. 
                //If RG14 is low set current bit to zero with mask_h = 0x0b11111100
                if (_RG14) {
                    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
                // Input is inverted !_RG14 is actually _RG14. 
                // If RG14 is low set current bit to zero with mask_h = 0x0b11111100
                if (_RG14) {
                    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
                // Input is inverted !_RG14 is actually _RG14. 
                //If RG14 is low set current bit to zero with mask_h = 0x0b11111100
                if (_RG14) {
                	// LAcntr is incremented when byte of data has been shifted 
                    voltage_msb[LAcntr] = mask_h;
                } else { // If RG14 is high set current bit to one with mask_h = 0x01
                	// Turn on bit zero (mask_l = 0x01).
                	// If the first bit is one save one in voltage_msb[0] bit 0
                    voltage_msb[LAcntr] = ~mask_h;
                }                
                // </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
                	// Turn on bit zero (mask_l = 0x01).
                	// If the first bit is one save one in voltage_msb[0] bit 0
                    voltage_msb[LAcntr] = ~mask_h;
                }
                
                // </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
                	// Turn on bit zero (mask_l = 0x01). 
                	// If the first bit is one save one in voltage_msb[0] bit 0
                    voltage_msb[LAcntr] = ~mask_h;
                }
                
                // </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
                	// Turn on bit zero (mask_l = 0x01). 
                	// If the first bit is one save one in voltage_msb[0] bit 0
                    voltage_msb[LAcntr] = ~mask_h;
                }
                
                // </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
                	// Turn on bit zero (mask_l = 0x01). 
                	// If the first bit is one save one in voltage_msb[0] bit 0
                    voltage_msb[LAcntr] = ~mask_h; 
                }
                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)                         
            }    
        


}



>