Nasty 4-channel logic analyser using dsPIC30F4011

This post is about a quick and dirty 4-channel logic analyser that I hacked together to get a snapshot of four parallel binary signals from something I was building. I just want to quickly capture this information here for the time being – I’ll come back to add a proper description in due course.

Features:

  • sampling rate: 1MHz (very approximate – method of timing is UGLY!)
  • buffer size: 2048 samples
  • number of channels: 4
  • input pins: RD0, RD1, RD2, RD3 (pins 23, 18, 22, 19 respectively)
  • sample size: 4 bits (1 bit per channel)
  • delay between sampling bursts: 0.2 seconds (plus frame transmit time)
  • baud rate: 38400 b/s
  • serial data output: U1ATX (pin 15)
  • PC software: Python script (see below), using matplotlib to graph data

Here’s what it looked like when I ran the Python data receiving script in the console (I had already powered up the dsPIC logic analyser circuit, plugged in the PL2303HX USB-serial converter and confirmed that it was showing up as COM22):

logicanalyser_console

This is the graph it produced:

logicanalyser_graph

dsPIC code:

//
// main.c - Logic Analyser program for dsPIC30F4011
//
// Written by Ted Burke
// Last updated 8-1-2013
//

#include <xc.h>
#include <libpic30.h>
#include <stdio.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

#define N 512

// data buffer
unsigned int data[N];

int main()
{
	int n;
	
	// Setup UART
	U1BRG = 48;				// 38400 baud @ 30 MIPS
	U1MODEbits.ALTIO = 1;	// Use alternate pins U1ATX and U1ARX
	U1MODEbits.UARTEN = 1;	// Enable UART

	while(1)
	{
		// Capture data
		for (n=0 ; n<N ; ++n)
		{
			// Read 4 samples (each sample comprises 4 bits, one
			// bit from each of the 4 digital inputs in port D).
			data[n] = PORTD << 12; __delay32(30);
			data[n] += PORTD << 8; __delay32(30);
			data[n] += PORTD << 4; __delay32(30);
			data[n] += PORTD; __delay32(30);
		}
		
		// Transmit data
		printf("frame\n");
		for (n=0 ; n<N ; ++n)
		{
			if (data[n] & (1<<12)) printf("1,"); else printf("0,");
			if (data[n] & (1<<13)) printf("1,"); else printf("0,");
			if (data[n] & (1<<14)) printf("1,"); else printf("0,");
			if (data[n] & (1<<15)) printf("1\n"); else printf("0\n");
			if (data[n] & (1<<8)) printf("1,"); else printf("0,");
			if (data[n] & (1<<9)) printf("1,"); else printf("0,");
			if (data[n] & (1<<10)) printf("1,"); else printf("0,");
			if (data[n] & (1<<11)) printf("1\n"); else printf("0\n");
			if (data[n] & (1<<4)) printf("1,"); else printf("0,");
			if (data[n] & (1<<5)) printf("1,"); else printf("0,");
			if (data[n] & (1<<6)) printf("1,"); else printf("0,");
			if (data[n] & (1<<7)) printf("1\n"); else printf("0\n");
			if (data[n] & 1) printf("1,"); else printf("0,");
			if (data[n] & 2) printf("1,"); else printf("0,");
			if (data[n] & 4) printf("1,"); else printf("0,");
			if (data[n] & 8) printf("1\n"); else printf("0\n");
		}
		
		__delay32(6000000); // 0.2 second delay
	}
	
	return 0;
}

Python code:

#
# Logic Analyser Python program
#
# Written by Ted Burke
# Last updated 8-1-2013
#

# import modules
import serial
import numpy
import matplotlib.pyplot as plt

# Open serial port COM22
# Note that COM22 is port number 21
print("Opening serial port")
s = serial.Serial()
s.baudrate = 38400
s.timeout = 2
s.port = 21
s.open()

# Look out for frame start
print("Seeking frame start")
line = ""
while line != "frame":
	line = s.readline()
	line = line[0:5]

data = numpy.zeros((2048,4),numpy.int8)

# Parse incoming frame data
print("Parsing data")
for n in range(2048):
	line = s.readline()
	words = line.split(',')
	for m in range(4):
		data[n][m] = int(words[m]) + 2*m

# Close serial port
print("Closing serial port")
s.close()

# Plot graph of data
print("Plotting data")
plt.plot(data)
plt.ylim(-0.5,7.5)
plt.xlim(0,200)
plt.show()
Advertisements
This entry was posted in PIC and tagged , , , , , , , , . Bookmark the permalink.

2 Responses to Nasty 4-channel logic analyser using dsPIC30F4011

  1. karthik says:

    using internal oscillator is good long run?

    • batchloaf says:

      Hi Karthik,

      There shouldn’t be any problem using the internal oscilator for a long time. However, from the outset, the frequency of the internal oscillator is going to be a bit variable. You can adjust the frequency slightly using the in-built calibration feature, but it may still vary over time, especially with temperature (since it’s an RC oscillator). I expect that the oscillator frequency could be out by a few per cent when you use the internal RC oscillator – if that’s a problem in your application you should consider an alternative.

      If you want very accurate and stable frequency, I definitely recommend using an external crystal, which will only add a few cents to your total cost. All you need is a crystal and a couple of small capacitors. You need to change one line of code to select the external crystal oscillator and if your crystal has a different frequency than what you have been using with the internal RC oscillator, then you will need to adjust your time delays etc in your program for the new instruction cycle Tcy.

      Let me know if you need me to explain that more or if you’re not sure how to connect the crystal.

      Ted

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s