Tuesday, December 22, 2015

Prj 141 - DDC Software (Part 4)

Following on in the walk through of the Spartan6 LX9 with Beaglebone Black and ADC, after the signal block and the digital block is the interfacing and control software.  The software is organized into several separate layers.  These are factored to achieve different objectives and provide varying levels of flexibility, compatibility and performance.  A summary diagram of that organization is shown below.
BeagleBoneBlack Software Organization for Digital Down Converter
Starting at the bottom, there is the Beagle Bone Black GPIO hardware.  The only digital pins required are those necessary for a bi-directional SPI interface.  These signals are always taken from an I board.  This board uses sets of 6 pins and includes power enable controls for the device along with a digital switch to isolate the io pins.  Depending on the I board port used the pins can be accessed directly from user space or have a device tree applied to make the pins accessible to the PRUs.  Port 2 of the I board has the pins accessible to the PRUs via register 30/31, while all other port have all pins directly accessible to the CPU.

The Xtst utility is the simplest and accesses the GPIO pins directly from user space.  This utility accepts simple command line primitives to read and write words to the SPI interface.  These can be strung together using Bash scripts to accomplish higher level programming operations that can be repeated.  The advantage is simplicity – no PRU code is required.  The down side is the SPI performance is quite low.  These scripts are good for simple tests of new VHDL focusing on the SPI and digital operations.

The PRU0/1 software manipulates the SPI pins directly and is capable of high speed serial operations.  When using the PRUs all SPI accesses pass through them.  The only non PRU access to the port/board are the power enables which are separate lines on the I board and are controlled by its software.  The PRU interface to CPU software is simple and limited to two basic commands: SPI word read/write, and SPI streaming read.  The CPU writes a command and parameters to a PRU SRAM memory location.  If the command is a read/write the results are returned to the SRAM and the PRU signals its conclusion by clearing the SRAM command.  If the command is streaming, the PRU continuously reads the SPI interface saving the results to a DRAM circular buffer accessible by the CPU.  The PRUs update the DRAM head pointer in their SRAM.  While streaming, the PRU checks for a new or different command every 2048 SPI words read.  PRU0 actually controls the GPIO pins for the SPI while PRU1 writes the streamed samples to DRAM.  This is a similar approach used successfully in other projects (e.g. PRU benchmarks,  10MSPS ADC rev1, and rev2)   PRU0 controls the speed of the SPI interface by how many 5nS instruction cycles it uses between SPI clock transitions.  A nominal value of 40 clock (200nS) or 4.8MBits/second was tested using a 6” IDC cable producing error free transfers.

The X board software interfaces with the PRU code via PRU SRAM for SPI accesses and DRAM for streaming samples.  This software provides a standardized ADC interface (get 2k samples, flush samples, get samples per second, …) and a standardized mixer interface (set LO frequency in Hertz).  The X board software deals with the FPGA programming model to configure the mixer frequency, stream samples 2k at a time, select the FPGA fifo source stream (i.e. pick an internal channel of data), and configure an internal test pattern for use or actual ADC inputs.  Depending on the fifo source stream selected the format and rate of the data changes.  For example the raw ADC data is unsigned 12 bit real samples at the sample rate (e.g. 10MSP or 66MSPS).  The final output source is the decimated IQ data stream which may be 100k samples per second of 16 bit signed I values and 16 signed bit Q values.

The Xboard  interface is used by the standalone Xutil software to provide high level and higher performance tests of ADC/Mixer operations.  Like Xtst, this is a command line utility with which operations can be strung together via Bash scripts.  Specific tests of interest include the ability to snapshot 2k of samples and save to a CSV for analysis and the ability to continuously monitor a fixed pattern test to evaluate SPI error rates and speed.

Finally the X board interface can be used with other existing utilities (via the common ADC and Mixer interfaces) .  Examples include a general workbench server that ties together multiple hardware modules (examples of ADC power spectra estimation and here and multi-board control here and source code); a SDR Server (examples here and here and source code), an ADC Http viewer (source code with examples to be covered in a future post).

Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

Friday, November 27, 2015

Prj141 - DDC Digital Block (Part 3)

Following on in the walk through of the Spartan LX9 with ADC and BBB, after the Signal Processing Block is the digital interface block.  The basic approach was not changed from the first digital testing approach here, however, lots of practical items were incorporated based on lessons learned during the rest of the development.  A block diagram of the digital interface and control is shown below.
DDC Digital Control and Data Interface
The digital control block is clocked by a 48 MHz digital clock from a DCM originating from a 12MHz clock (generated on the XuLA2 board for its USB programming interface).  While the sample clock could be used, this allows the digital section to work without the sample clock being present (partially populated boards or boards with defects).  The ADC sample clock is provided to the digital section for counting and in diagnosing newly fabricated boards.

The SPI interface represents a separate and asynchronous clock domain.  It is driven by SS and SCLK from the host computer.  It latches SO and SI at the start/end of being BSY, where BSY is determined by the SPI  SS and SCLK count. 

The port controller is a finite state machine which starts when the SPI stops being busy.  At this point the SI or serial input word just received is parsed and acted upon.  The lower 4 bits of this word determine which port (0 or 1) will be read (or written).  In the case of a write the FSM take the upper 12 bits of the serial input word and writes them to the appropriate port.  For a read, the FSM reads 16 bits from the specified port and latches them into SO or the serial output word for the next SPI transaction.

For simplicity port 0 is always connected to register 0.  This register has a couple of light weight controls and status.  One of the key sets of bits in register 0 is the P1 selects bits which determine which register is currently connected to port 1.

The register definitions are fully specified in the VHDL top level readme.txt.  The key registers are R0(control previously mentioned), R1 (FIFO data), R3 (Fifo source select and test pattern generator control), and R6/R7 (PINC or frequency control of signal block NCO/DDS local oscillator). 

The other registers are utility registers used to debug and test boards, software or VHDL.  I must admit I under estimated the need for and value of these.  The firmware version is available to keep your sanity and make sure you programmed the image you thought you did.  The sample clock counter lets the software test to see if there really is a valid sample clock present (and you can expect any FIFO samples).  The digital clock counter is a good simple internal test available to the software interface along with the counter on the number of port 1 reads.  Like-wise the LED outputs on register 0 allow basic simple scripts to check a board and firmware for SPI connectivity.

Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

Sunday, November 15, 2015

Prj141 - Digital Down Converter Signal Block (Part2)

The signal block of the FPGA (overview here) is a simple digital down converter.  You could just use a Xilinx core, however, since this was my first project with VHDL I wanted to assemble the pieces myself (and I wasn't sure I could correctly use the generated core as are geared to multi-channel and much more complicated applications, besides that, it is more interesting and instructive to walk through a full DDC on your own at least once).  A block diagram of the signal block is shown below.
Single Channel Digital Down Converter Block Diagram
The VHDL source is here.  The signal processing block is a single channel digital down converter using separate Xilinx cores.  The 12 bit ADC signal comes in at the left and is formatted (unsigned to signed conversion). There is a mux which selects the ADC stream or an internally generated test pattern to be sent to separate I and Q multipliers (S_s12 in the block diagram).  The multipliers are driven by the sin and cos outputs of a Xilinx DDS generated core.  The DDS frequency is controlled by its phase increment register.  This register is written by a FSM in the AXI register block.  It takes a 16 bit wide set of discretes, buffers them and when they change writes the new value to the DDS core.

The output of the multipliers is fed into a CIC filter generated core.  The CIC is on the order of N=4 while the decimation is on the order of 50 to 300.  (the exact parameters depend on both the sample clock rate populated on the board and the detailed design of the filters downstream).

The CIC outputs are sent to a compensation FIR filter generated core.  The FIR filter is designed to compensate for the droop in the pass band of the CIC filter as well as to provide antialiasing for a decimate by 2 at this stage.  There are several good applications notes from both Xilinx and Altera on balancing the tradeoffs with CIC filters and FIR filters and decimation.

The low rate signal data from the I and Q chains is taken from the CFIRS by the IQ writer block and written to the FIFO a pair of samples at a time.  This block is implemented as a FSM which waits until both I and Q samples are ready and then writes both values to the FIFO.  Care needs to be taken at this step since the FIFO data can easily be shifted by 1 during starts/stops/resets.  If this happens the consumer of the data ends up reading I(n),Q(n+1) as a complex sample which represents a phase shift and results in not truly quadrature signals.  For this reason the FSM includes special logic to write a pair of samples or none at all.

Lastly, there is a mux which selects which data is presented to the FIFO write signals.  Based on the FSS (Fifo Source Select) discretes, samples from any point in the processing string can be sent to the FIFO. The FS designator on the block diagram shows the setting to select data from that point in the chain.  This capability might sound like a nicety, but is absolutely essential to developing, debugging, and integrating the software and firmware.

Similarly, the test pattern generator is immensely useful for a couple of reasons.  First it allows the use of clean known digital signals.  These can be specified at a precise frequency and amplitude.  Second, it serves as a reference for down stream software development without having to have a physical signal generator attached to the system.

There are a couple of other important aspects not shown on the block diagram for brevity and clarity. The entire signal processing block is driven by the ADC sample clock and is designed to work from 10MHz to 66MHz.  There is an internal reset used to reset the filters (i.e. ensure they all start on the same sample and have no residual samples from previous operations).  This is driven by the FIFO reset from the control section.

Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

Friday, October 30, 2015

Prj 141 - Spartan6 LX9, ADC, and BBB (Part1)

With some work on the VHDL another unit was constructed with an ADC.  One of the advantages of using an FPGA assembly like the XuLA2 is that it can be moved from one carrier application board to another.  The schematic is shown in the previous post.  A picture of the final assembly is shown below.
Prj 141 Unit #2.  BeagleBoneBlack with SPI interface board at left.  Right hand side is ADC carrier (purple) with XuLA2 including a Spartan6 LX9 (green).
The one white wire shown is a regulator enable that I decided at the last minute to statically pull up rather than drive from the FPGA.

The VHDL was developed incrementally from the base digital/SPI interface into a single channel digital down converter.  All of the VHDL is available here.  The summary block diagram is shown below.
Block Diagram of Digital Down Converter for Spartan LX9 with SPI Interface
The inputs to the FPGA (Spartan6 LX9) are a 12 bit ADC input with sample clock, a 12MHZ digital clock input and a SPI interface.  The outputs are 4 LEDs for testing and a SPI output.  The sample clock is designed to be 10MHz to 100MHz.  All IO pins and timing constraints are specified in the UCF file.  The top level break down includes a digital block for interfacing to the processor, a signal block for interfacing with the ADC and processing the signal.  A 4k x16 bit FIFO buffers the data from the signal processing to the control block and processor.  The control block gets a digital clock which is multiplied up by 4 using a DCM to interface with the processor SPI.  It also receives a copy of the ADC sample clock for testing and diagnostic purposes.  The control block receives a status set of discretes from the signal block and provides to the signal block a set of control discretes.  The TPG discretes control the internal generation of test patterns, the FSS (Fifo Source Select) determines which internal signals are placed in the sample FIFO between the signal processing and digital interface and the PINC (Phase increment) determines the frequency setting of the signal block DDS or NCO that gets mixed with the ADC input.

There are two major clock domains within the part: the sample clock and the digital clock.  The signal processing block is driven entirely by the sample clock while the control block is driven completely by the digital clock (from the DCM).  All information between the blocks is through a FIFO with separate clocks or via discretes that are re-clock synchronized at the destination.

A couple follow on posts walk through some of the details.

Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

Tuesday, September 29, 2015

FPGAs and VHDL on a budget

The Beagle Bone Black (BBB) and its PRU go a long way to building non-trivial projects (e.g. all of the boards in gallery1 and gallery2 including a  Level controlled RF synthesizer10MSPS ADC, and multistage SDRs.)  Having a simple, flexible, low-cost FPGA available started to become very appealing.  In looking around at various FPGA boards the XuLA2 Spartan6 LX9 caught my attention for several reasons. First the pin out is extremely simple (40 pin DIN at 900x100 mil spacing), second it has enough IO pins to be usable with ADCs, DACs, and an SPI but not so many as to be cumbersome, third it includes an SDRAM which could come in handy, and finally the cost is low enough that I could afford to purchase multiples and not worry about loosing one due to mistakes on the bench.
The near term goal was to interface the FPGA to an ADC and a BBB and the longer term goal being to eventually incorporate an NCO, digital mixer and filters.  I am also not a VHDL expert so things needed to progress incrementally.  Given this, I created a simple board as a carrier for the XuLA2 that included an SPI interface, LEDs and an ADC.  The schematic of that board is below.
XuLA2 and ADC carrier board schematic.
The idea is that there is enough on the board to develop and test an SPI interface and then populate the rest of the board with a 12 bit ADC.  The ADC and sample clock oscillator are pin compatible from 10MSPS up to 66MSPS (depending on how much you want to spend and can use).  Below is a picture of the first unit partially populated with only LEDs, SPI interface, and XuLA2. It is connected to a BBB via an SPI interface using the GPIOs through an Beagle Bone Black interface board.
Beagle Bone Black with interface cape at left.  XuLA2 w/ Spartan 6 LX9 on ADC carrier on right.

The first FPGA image developed included an SPI interface with an internal control register and a couple of counters (block diagram below).
Block diagram of VHDL for LX9 digital interface.

The SPI block serializes data into SI and out from SO.  The port controller is a finite state machine that uses the SI as a 16 bit command. The low 4 bits specify whether the transaction is a read or write and which port to read and write from while the upper 12 bits serve as the data.  Reads and writes with port 0 always go to register 0 (R0).  This is the primary control register which includes settings for the LEDS, ADC sampling enable and selecting what hardware is multiplexed to port 1.  Reads and writes with port 1 can be to a secondary set of control registers (R1 and R2), a set of counters, or a FIFO which crosses the system clock and ADC sample clock domains.  The overall programming model then becomes writing a command (and reading the results from the previous command since the serial data is clocked out concurrent with clocking in the write data).  For streaming operations, the port 1 selector is first configured to connect to the FIFO and then a stream of read-port-1 commands are issued.

This approach worked well.  It has enough complexity to serve as a non-trivial, applied learning exercise yet is simple enough to be tractable to debug without lots of test equipment and tools.  The SPI programming can be easily driven by and changed in the BBB user space C code. This means you can slow down transactions to seconds and verify things on the target hardware with the LEDs. The counters allow pattern verification of reads at all speeds and check the integrity of the interface.

Prj141 Schematic
Prj141 Overview
Prj141 Digital Down Converter
Prj141 Digital Interface
Prj141 Software
Prj141 Filter Design
Prj141 Filter Evaluation
Prj141 LX9 Utilization
Prj141 Higher Sampling Rates

HTML5 Canvas Experiment

After having completed the simple html/css/javascript synthesizer application (described in Part1Part2Part3, Part4) I wanted to evaluate using an HTML5 canvas for an instrumentation like display.  There are lots of good graphic packages available, however, I did not find one that seemed to offer basic and simple xy plots suitable for what I wanted to do with a browser based instrument.  For me the real keys were: a) simplicity where I could understand the code and tailor it, b) ability to graph 500 – 2k work of xy points every 50mS or so, c) basic measurement things like envelopes, memories, peak picking, a cursor, and markers.  Given this and the desire to spend a little more time advancing my javascript comfort level with non-trivial examples I decided to build a simple version of a similar Java display I have used (illustrated in the posts on ADC and spectrum analyzer experiments).

The package was developed as a standalone file with a couple of test drivers.  The tests themselves run in the browser and require no back end server to drive them.  The source code is at BREC/Js and a browser executable demo is here.  An image of one of the unit tests is below.

Example of HTML Canvas used to graph signals.  Browser demo available here.
The example has several buttons along the bottom.  The "run" button causes internal updates to the XY sequence displayed.  In the default case this is just a sinusoid with a up and down chirping frequency.

The "marker" button displays 10 markers.  These start out as predefined values on a sinusoid.  If you click anywhere on the canvas, marker 9 moves to that position.

The "peaks" button toggles peak picking.  When peak picking is on, markers 0 - 8 are taken over and assigned automatically to peaks found.  Marker 9 still follows the last canvas clicked location.

The "memshow" button toggles the display of a XY sequence in memory.  This is shown in light blue. The "mem" button captures the currently displayed sequence into the memory.

The "envelope" button toggles an envelope history.  When enabled the envelope is initialized and displayed.  When toggled off the envelope is hidden and not active.

The "function" button toggles between two internally generated XY series.  The first is the chirped sinusoid, the second is a spectrum like signal with two peaks and some random noise.

Saturday, September 12, 2015

Browser controlled synthesizer (Part4)

The fourth step in constructing a simple webpage controlled RF synthesizer is the mechanical assembly and packaging. (The previous steps are described in  part3part2, and part1)

Originally I had visions of constructing shields on the boards in RF sensitive areas and packaging the entire setup in a nice professional small case.  Let’s just say I’m learning…  Rather than getting hung up on the difficulties and errors in this regard I decided to forge ahead.  All I really needed was a dust cover.  The real concern is just protecting the electronics from having a tool fall on them or more likely a SMA connector brush across them as the cable flips over unexpectedly while reconfiguring a setup. To this end I decided to use some scrap plywood and acrylic.  The plywood provides enough mass that the instrument doesn’t get dragged around on the bench with cable tension and is sturdy enough that you can stack things on top of it.  Granted, it provides no shielding and I’m not entirely sure of the ESD properties.  Same for the acrylic face plate.  The face plate is thin enough that you can get the connectors through it and you can at least see the LEDs to know if it is powered on and should be working.  The following are a couple of pictures of the assembly. 
BBB Browser Controlled RF Synthesizer on Mounting Plate

Synthesizer with dust cover
The example below captures the control panel during a sweep along with the measured spectrum.
Browser based control panel.  Sweeps from 37MHz to 67MHz (1MHz steps) and from 0dBm to -30 dBm (1dBm steps).  At the time of capture the output at that steps was at 50MHz/-13dBm.

Spectrum of output.  There is a 30dB pad between the generator and the analyzer.  You can see the 3rd harmonic of the low frequency portion of the scan on the far right near 74MHz.
Similar sweeps and single frequency outputs are achievable through 2GHz.  Beyond this point the amplifiers used start to lose gain and the level drops and level control is reduced.  The following captures a sweep across 1.4GHz - 1.5GHz in 5MHz steps.
Constant level sweep from 1400MHz - 1500MHz in 5MHz steps.  Output at -5dBm with 30dB pad between analyzer and synthesizer.

Friday, August 28, 2015

Browser controlled RF synthesizer (Part3)

The third step in constructing a simple webpage controlled RF synthesizer is the application level software. (The previous step was described here with the hardware described here)

Since all of the interfacing software is in C/C++, I wanted to use a light weight http server framework that I could build application specific C++ code into.  I did not want to use gateways or other scripts for performance reasons, not so much for this particular activity but for others which might require higher performance between the http command and the hardware.  There are a couple of good packages available for these purposes.  After a small amount of experimentation I decided to use libmicrohttpd.  It is pretty basic and doesn’t get in your way for simple servers like this.

Once you have the hardware control software and an http server framework, the next step is to decide on the building blocks for the actual user interface itself.  In support of this, there are a dizzying array of software packages including jQuery and Dojo.  For this particular application I wanted to start simple and use basic html, css, and javascript.

The browser component is structured as a simple table with a CSS defined border and cell entry formats.  The basic actions buttons with the numeric inputs being text box forms.  An example is shown below.
Browser Control Panel for Synthesizer

The buttons at the top allow the application software to be restarted, the BeagleBone Black to be rebooted, or the current configuration parameters to be saved persistently (and used at next power up).  The shutdown button is only for testing and is not required for use.  The box below that indicates if the browser is actually connected to the device, the time on the device (which should update every second if everything is working), the PLL lock status at the given frequency and the output level as currently read from the device.  The next set of control buttons allows the device to run, sweep, and continuously monitor the output power level.  The “run” actually will just power on or off the synthesizer boards allowing you to quiesce everything in case you are wondering where a certain signal is coming from.  The level monitoring allows an output level update, constant monitoring (~100Hz) or to be completely quiet – again in case there are questions about where a certain signal is coming from.  The final panel allows user inputs of various parameters and shows the currently in effect values.  These allow for a single constant frequency and level setting (start parameters), or a sweep in both frequency and level (from start to stop values) along with step sizes when sweeping for both level and frequency.  While sweeping the time at any given frequency and level can be configured from 0 (as fast as the device can step) to seconds using the “DwellTime” value.

This application is simple enough that it doesn’t merit a full MVC (model view controller) approach, however, a simplified variant is used – mostly to evaluate the approach.  The browser client code is here while the server code is here.

The state coming back from the server is expressed as a single JSON object.  This is easy to parse in javascript.  To keep things responsive the state is requested from the server using http query every 100mS.  The state variable contains all of the elements in the display.  The JSON object is then used to update all of the DIVS in the page.  This represents a single HTTP GET on the “getstate” URL and keeps the client parsing very simple along with the response construction. Each user input generates a HTTP GET on the “setstate” URL with the values being a name/value pair.  Again, this keeps the HTTPD server parsing simple and allows for easy testing with human synthesizable commands.  The network API is then simple enough that control can also be scripted using WGET. An external host can use bash scripts to control the device for automated test setups.

The use of HTTP GET is not in line with network security and best practices, however, there is nothing secure about this device.  It was intended for use on a dedicated and isolated network with other instruments.  There is no login to prevent conflicts among users/sessions. The server will server up any file on the BBB.  I am sure there are numerous other security holes within the configuration of the BBB Linux configuration as I have it setup.  The whole point of this is simplicity and experimentation.

The one final interesting portion to note is the persistent configuration saving feature.  Once you get things setup for a particular measurement it is exceedingly useful to be able to save it and then later just power on the device and have it start working like you wanted to without even having to attach to it with an Ethernet or  browser.  The BBB file system is mounted read only for robustness.  The state parameters are read from a file on startup.  When the server receives a save configuration command, the file system is re-mounted read/write, the configuration file with the current parameters written and then the root file system re-mounted read only.  This produces a small window in time during which the device root file system may be vulnerable to interruptions.  In practice, this has not proven to be a problem as the entire re-mount, write 200 bytes, re-mount operation occurs within milliseconds.  If you are prepared to re-partition the eMMC on the BBB one could create a small spare partition and read/write the configuration file through a raw block device.  This side steps any file system checks and integrity concerns.  

Saturday, August 15, 2015

Browser controlled RF synthesizer (Part2)

The second step in assembling the synthesizer (based on this hardware) is configuring the BBB Linux distribution.

An older rev B BeagleBone Black is used as the primary control board.  This uses Angstrom Linux. I cannot speak to the differences between this and rev C with Debian distributions.  I will say that I find the Angstrom distribution slightly more difficult to work with as I am accustomed to the standard unix utilities and configuration approach.  Angstrom’s use of select packages such as connman and busybox help resource footprint but often send me to the web searching for how to do basic system administration and configuration actions I have done for years.  Said differently, I believe you can do all of these and at least as easily with Debian on a rev C board.

The following steps are in the notes.txt file in the  BREC/SynHttpd software. The text here provides a little more background and narrative beyond the terse command notes.

The first step is to disable a set of default services that are not used and that use the http default port 80.  There are plenty of good tutorials on the web and all boil down to “systemctl disable <svc>”, where <svc> is cloud9.service, gateone.service, bonescript.service, bonescript.socket, bonescript-autorun.service, avahi-daemon.service, gdm.service, and mpd.service.

The next step is to setup the synthesizer application to start automatically at boot time.  Again, there are plenty of good tutorials on the web and there are examples in the BREC/Scripts directory of the software.  I configured a service to start a bash script via systemd.  The main script is placed in /home/root with the rest of the executables and the script launches the actual applications.  To me, systemd has quirks like crond, you don’t have the exact same environment as your normal shell (just enough to throw things off) and the configuration files take some getting used to.  You can use “systemctl status <service you defined>” to check on the application and its children’s status and see any stdio.  It takes some getting used to.  There are items to be aware of like exiting with a good status or having your processes “cleaned up” for you.  You need to start the applications and get them in the background before a predefined time limit or the service process tree is killed as being hung.  All of these things can be adjusted in the configuration files or in your startup script – you just have to pick an approach and understand the subtleties of the configuration you have defined. There are also issues to be aware of with starting so quickly on boot.  One of particular importance is “/dev/uio0” not being present for a brief period of time.  This is the special file the libpru code uses to access the PRU.  I found that startup services I created would randomly seem to not start.  It turned out that sometimes by the time they went to open the pru the special file was available and sometimes not.  By just checking for the existence of the special file in the startup of the service script the service reliably starts every time.

So at this point you have a BBB that lets you start your own web service on startup.  The next step is to safely allow shutdowns without other action.  To do this the root disk is mounted as read only. There are several examples on the web as well as a sample /etc/fstab in the BREC/SynHttpd/fstab-ro file.  To make root writeable you just issue “mount –o remount,rw /” and everything is back to a standard writeable file system. I have to admit this works really well and consider using this on normal development boards where I write to the root partition.  A read only root file system speeds the boot time but also helps when working with a new board and linux gets powered down without warning.  There are posts and comments on the web regarding early perceived issues with a read only file system on BBB (e.g. applications could not access the gpio pins through sysfs), however, I experienced no issues – everything works as expected including all device interfacing and other system services.

Thursday, July 30, 2015

Constructing a simple browser controlled RF synthesizer (Part1)

Now that I had a set of modules lying around that have served their initial purpose I had to figure out another boondoggle (or just send them to the recycling center - if you are the kind of person reading this type of material you need no explanation regarding the value of boondoggles versus putting something on the shelf...)

Existing modules with a BeagleBone Black were assembled to produce a frequency synthesizer. The frequency range is 37 – 2000 MHz (CW, square wave) with at least a few kHz of resolution. The level is controllable 0dBm to -30dBm with an accuracy of +/-2 dBm.  For simplicity it uses an external 5V power supply with 100Mb/s Ethernet and web browser user interface.  You can purchase instruments like this on eBay for $200 - $600 from a few sources.  They generally have wider output level ranges and support the full frequency range of the ADF4351, come in smaller packages, and are USB only.  You won’t save yourself any money by building your own (but you’ll have more fun and learn a lot more…).

The idea is to have an  “instrument like” device – something you can plug in, turn on, use, and then turn off.  I did not want to have to spend lots of time drudging up utilities on the PC or worry about shutting the device down properly.  This is part of the reason for focusing on a web browser based control approach (and I wanted to get some hands on experience with embedded web techniques and technologies).

The basic aspects of this project are:
a) Digital and RF Hardware
b) BBB Linux Configuration
c) User Interface Software
d) Packaging

The notes are broken into multiple posts focusing on each of the steps above. The hardware involved was developed in pieces over time and is described in this entry.  In short, an ADF4351 is used as the synthesizer source and the level is controlled using an amplifier with digital step attenuator and a LTC5587 power meter. The basic control software adjusts the attenuator and synthesizer output until the final output is at the desired level.

Sunday, July 12, 2015

Single stage SDR experiment

After spending a lot of time trying to understand and evaluate the ADC distortion and noise artifacts I decided to try something different with the ADC board.  Previously I built a 1MSPS serial ADC board and mixer, amplifier and filter board.  These could be arranged in various configurations. One of those was a single IF SDR.  I wanted to try the same setup with the new ADC and some of the other mixer and amplifier boards constructed. The following is a picture of that setup.
Single IF SDR using various boards with Beaglebone Black.  See text for description of boards and links.
While it may appear somewhat rubegoldberg-esqe it is actually pretty rewarding to be able to build a set of modules and software and connect them together with a few cables and make something work.

The setup is for a FM broadcast receiver.  The signal enters at the bottom center board on its left input.  This is a Prj133 synthesizer with mixer board controlled via an SPI interface.  There are no image rejection filters for simplicity.  The output is a 10.7MHz IF exiting the board at the right. The IF is amplified in the upper right board which is a Prj135 amplifier, attenuator, power meter board, again controlled via SPI.  The amplified output (exiting the top of the board) is passed through a 10.7MHz bandpass filter using two cascaded ceramic filters.  A single filter is sufficient, however, all of the filters I have built use a 2x cascade for ADC harmonic rejection testing.  This creates a little more loss than I need or like but it was sitting there ready ... Having it hanging there in mid air also creates the appearance of putting the "rube" with the "goldberg"... but it was good enough for a quick test.  The filtered signal enters the ADC board on the center left.  You can see the SMA input but nothing else as the board is mounted on top of a Beaglebone Black but under another board (if you look at the stand offs you see 3 sets high).  The board on top of the ADC is a Prj136 interface board which provides 3 ports of discrete IO (which can be software configured for SPI control) and +5V of power.

The software on the BBB is the same as used in previous projects (single stage IF two stage IF).  It supports an amature radio control protocol interface which allows multiple PC SDR packages to be used.  The only difference is that the 10MSPS ADC stream is downsampled to 2.5MSPS (the ethernet bandwidth does not support the full 10MSPS nor does the BBB processing).  This is still larger than the serial ADC sample rate of 1MSPS so it is a little different and the distortion is better.

The clip below is a screen capture of using the SDR to move around the dial.  A VHF set of rabbit ears was used for the antenna, however, it was below ground (i.e. in a basement).  The NOAA NBFM signal takes a few seconds for the software to lock well (I believe this is an issue with my software configuration, not the hardware).


Thursday, June 25, 2015

ADC without Amplifier

In an effort to evaluate the ADC harmonic distortion and spur clusters I decided to create a variant of the ADC board which did not have the amplifier (earlier version).  This allows me to revisit the ground plane, add resistors to the digital lines and re-layout the sample clock signal.  It ends up being as close to the ADC reference design as possible.
BeagleBone ADC board with transformer input.
The first unit anti aliasing filter was not populated to allow evaluation at multiple frequencies.  Two different regulators were tried - the original 150mA and a 300mA version.

Constructed ADC board with transformer input and no amplifier. ADC anti-aliasing filter not populated.  TCXO in upper right, input transformer at lower right, ADC right of upper center, regulator and reset on left.
As in previous measurements, a DDS at 10.640MHz was used as the input.  This was filtered through a 2x 10.7MHz ceramic filter.  Without the amplifer this setup was not able to drive full scale, rather -3dBFS.  That spectrum is shown below.
-3dBFS 10.640MHz input
HD2 is still -79dBc and the spur clusters are present at the same levels and locations as the same version of the board with amplifier ( HD2 compare and spur cluster compare).  The grounded input spectrum looked similar to the previous versions with the amplifier (flat at -107dBc with small clusters at 2MHz and 4MHz in the -100dBFS range).

The continued presence of the spur clusters is disappointing but I am out of ideas on the root cause and decided to put it away for a while and move on to other topics.

Saturday, June 13, 2015

Prj137 ADC Spur Clusters

The spur clusters from the previous work proved to be an evasive problem.  Very little changes the location or the level. The structure seems to indicate there are many harmonics present based on the clustering.  To better understand this I walked the source up and down to see which ways the clusters moved (i.e. in even or odd nyquist intervals).  A capture of that is below.
Spur cluster walk from 10.640MHz up in steps of a few kHz.
Using the even/odd interval, I then stepped the fundamental by a few kHz for several steps and captured the peak of each cluster.  A fundamental delta of 10kHz moves the clusters 10kHz, not some multiple.  This told me I was looking at a modulation, not a set of harmonics of something.  If you put all of this into a spreadsheet and play around ruling out things based on even/odd nyquist and unrolling a given peak to all of the frequencies it could be you get the following table.
Spur cluster peak unrolling across Nyquist intervals
The cluster peaks are under "ADC (MHz)" and the color codings of cells match up the expected frequency the cluster represents after folding.  The rows at the bottom capture the delta in MHz of the peak from the fundamental at 10.640MHz.  So for the highest peaks of the spur clusters they appear to be 2MHz from the fundamental and appear to me to be switching power supply noise, evaluated here.  The lower spurs within the cluster would then be the AM modulated signals of the higher harmonics of the 2MHz switching impulses folded around the Nyquist regions.

Indeed, you can do the same thing at a lower sampling rate.  This both shows the fine scale structure and the harmonic spurs and verifies the above unrolling at a different set of frequencies. The following is a 2.5MSPS capture of a 10.640MHz input signal.
10.640MHz input signal using 2.5MSPS showing the spur cluster internal structure.
Numerous attempts were made to ameliorate the clusters.  This included adding/changing the supply chokes and bypass coupling.  As previously, these made no impact.  Additional ground ties were added, and removed - again with no impact.  The next logical step (in my mind) is to understand if these are coming from the amplifier or the ADC and to remove as much of the circuitry as possible.  This means backing up to a just the ADC and a transformer input - basically mirroring the ADC evaluation unit circuit.

Saturday, May 30, 2015

Prj137 Onboard BPF

Given the state of HD2 from the previous post with the BBB 10MSPS ADC board, I used Elsie to design a 3rd order BPF centered at 10.7MHz with a 3.5MHz bandwidth.  It takes a bit of trial and error to arrive at a synthesizable filter (i.e. one that uses standard values and is not overly sensitive to part value variations).  The intent is not to provide complete band rejection, rather to limit the noise from folded Nyquist bands and to knock down any harmonics created by the FDA.  The filter values along with a spice run are shown below.
SPICE steup of FDA with BPF prior to ADC.
The 902pF shunt capacitor is an 820pF with a 82pF stacked on top (the target was 900pF however these were unavailable at reasonable prices and shipping times).

BPF Filter Response
For comparison purpose the first spectrum below is the same measurement setup with no filter.  In this case (and all following) the gain has been reduced using an Rf=100, Rg=25 (this was one of the attempts to see if gain was exacerbating the harmonic distortion).

Av=4, Filtered DDS source at 10.640Mhz, no FDA-ADC filtering.
Rather than just populating the entire filter and seeing what happened, I decided to populate each stage and evaluate HD2/HD3 and the noise floor.  I chose to evaluate the center shunt stage first since I thought this had the best chance of producing expected results without imbalancing the differential arms.  Those results are below.
Av=4, Filtered DDS source at 10.640MHz with shunt stage of FDA-ADC BPF populate.
At first it seems worse, however, the noise floor has been reduced by the BPF limiting the folding noise across Nyquist zones.  This presents the illusion of the spurs being more prominent not because they have risen but because the floor as dropped.  HD2 is now roughly -74dBc and HD3 is not noticeable.  I did not pause to measure the gain and evaluate the filter insertion loss.  If one stage was good more must be better...  Unfortunately, this wasn't true.  Adding the first series made things slightly worse and with a higher noise floor.  Adding the second series stage and final BPF stage helped HD2 slightly but retained a slightly higher and tilted noise floor.  Addition of the final LPF (shunt C and series 5 ohm resistors) returned things to slightly better than the above.  The results from this configuration are shown below.
Av=4, Filtered DDS source at 10.640 MHz with 3 stage BPF.
HD2 is now approximately -80dBc but HD3 is similar but a little higher.  Interestingly enough, in no case did the spur clusters ever change.  These are now the dominant (and unexplained) feature.

At this point it was time to total up the bill for all of the filtering.  I knew the insertion loss was creeping up since the DDS level had to be adjust up to hit nearly full scale on the ADC.  I decided to return the FDA to a high gain previously used Rf=493 and evaluate the results.
Rg=25, Rf=493, Filtered DDS source at 10.640MHz with 3 stage BPF.
As expected the spectrum did not change with the increased gain. Using the same technique as in previous gain measurements, the gain was measured as Av=15.6(15dB) but Rg/Rf indicated it should be Av=9.9(20dB).  The FDA datasheet indicates this type of gain is readily supported by the device at this frequency so it looks like the insertion loss is 5dB for the 3rd order BPF.  This is higher than I had hoped for, however, I did not use the highest Q components made, rather the best ones in stock for these values at the time.

So in the end it appears the higher than expected HD2/HD3 response is predominantly deriving from the FDA and how it is being used.  Taking them down to a reasonable level adds components and increased gain needs on the FDA.  This seems like a losing game.  I may have been better off placing all of the desired gain off board, then filtering, and then conducting the differential conversion on the board with a transformer.

This is still usable for my purposes, however, the spur clusters merit some attention.  Originally I had attributed them to DDS artifacts, however, it became clear this was not the case when using a source comprised of a synthesizer and mixer.  In both cases the spurs are identical in level and structure and follow the fundamental in frequency and level.

Saturday, May 16, 2015

Prj137 HD2

Continuing with the ADC and having data on the noise floor and amplifier gain, the next step is to revisit the harmonic distortion of the board.  Previous efforts on earlier boards left me with questions regarding how much of the second harmonic (HD2) response observed was from the device versus the source and filters. When measuring a strong signal it is difficult to assess the harmonic content since even good spectrum analyzers will have a harmonic response themselves larger than I am trying to investigate with a 12 bit ADC.  The basic test filter I use is a 2x cascaded 10.7 MHz ceramic with a 3dB pad between them and a LC match from 50 ohms to 330 ohms.  The vendor does not provide a broadband filter response so I have always been left wondering what the actual response is at the harmonics (best case 50dB of rejection, worst case ...).  To address this I decided to construct a notch filter and focus only on HD2.

Below is the filter schematic and spice simulation.  I used the Elsie software package and selected L/C values I had on hand for a 50 ohm termination and notch response at HD2 for a 10.7MHz signal.
Notch Filter for Approximately 21.4Hz (HD2 of 10.7MHz signal)
The filter was constructed on some scrap PCB using an Xacto knife to cut the pads.  It is a bit tedious and care must be taken to do this away from other boards to avoid copper shavings landing where you don't want them but for small things it is faster than waiting for a board.
Constructed HD2 Notch Filter
The response of the filter was measured with a spectrum analyzer set at an input level of -15dBm. The response was scanned in large increments to save time hence the steps in the response.
Measured Response of Filter
The rejection in the range of interest is -50 to -70 dB and I trust the results in measuring the notch response more than than the harmonic response since the total input signal level is low causing less uncertainty regarding the measurement device behavior.

Using the above notch filter and a 10.7MHz BPF and ADC Unit#1 the following spectra was obtained with a synthesizer/mixer source (non-DDS).
ADC measurement of 10.640 MHz input through notch filter and BPF.
Unfortunately, HD2 is only ~65dBc.  This is significantly less than expected.  In addition there are several spur clusters besides HD2 and HD3 (markers 3,4,5,6). In fact, this is worse than the 74dBc from an earlier version of the board at lower levels.  With this measurement, there is no question regarding the input level of HD2; the notch should provide in excess of 50dB of HD2 rejection, the source HD2 is measured at least -40dBc, and the ceramic filter should provide another 25-50dB of HD2 reduction.

My first estimate was that the distortion was occuring in the fully differential amplifier (FDA). The datasheet shows -80dBc to -90dBc for HD2 and HD3 under various feedback configurations and loads at 10MHz using a 2Vpp output and a single ended input. There is a figure showing 10dB of variation in this with different common mode voltages (near the range I am operating using the ADC common mode voltage output).

In an effort to probe the FDA contribution, I changed the gain of the FDA down and up (ensuring all resistors were 1%).  In no case did this change HD2, HD3 or the spur clusters levels.

The last aspect of this which I can think of is that my input resistor is small compared to general applications referenced in the datasheet.  The exact impacts of this on distortion are not clear to me (if any).

In the update of the board, a BPF filter was added between the ADC and FDA just for this concern. The next step is to leverage the filter and monitor response changes in HD2/HD3 and the spur clusters with the idea being if they are attenuated the FDA is the source, if not, the ADC is the prime contributor.

Saturday, May 2, 2015

Prj137 Fully Differential Amplifier Gain

With a better understanding of the noise floor and spurs on the ADC board I wanted to check the actual gain produced by the buffer amplifier.

The gain was measured by Tee’ing a DDS output, post filter, to the oscilloscope (with 1M impedance), and into the ADC.  The DDS attenuation was varied to produce different levels that were measured on the scope and with the ADC in dBFS and counts.  The value of using counts is that the dbFS has small deviations from expected (0.9dB).  I believe this is due to an error in my windowing amplitude correction.  The ADC count levels are obtained using the peak picking on the time series with the offset found by “peaks” on a no-input signal.  The values are all 16 bit normalized.  The full scale is 1V. The following table captures measured values and those values processed to produce a voltage gain.
ADC values with input using Rf=294,Rg=25 ohms.
I trust the large value oscilloscope readings more than the smaller ones (scale had to change and I'm not completely sure of the calibration across scales).  Using the ADC count reading the voltage gain is roughly 5.3 (14.5dB).  The expected gain is 294/25=11.8 (21.4dB), however, this is fully differential gain on a differential input.  The actual and measured input is only half of a differential signal so in this configuration we would expect the single ended input gain to be half or 5.9 (15.4dB, or 6dB lower).  To me this agrees well and is fine for my purposes, however, my intuition and mental calculations with differential signals is not what it should be.  I often apply the wrong factor (multiply by 2 when the quantity should have been divided by 2 or the other way around). Just for sanity, I decided to use SPICE to verify the setup.  Normally I use TINA Spice, however, I had difficulty integrating the LT supplied subckt model (OTA nodes weren't transcribing well). After a brief learning curve I had the circuit below working in LTSpice.

ADC board FDA Spice Model
The application notes from TI and ADI do a good job of walking through the gain calculation and input impedance.  The short summary of that is that the differential feedback network increases the input impedance of the Rg (R7) resistor.  By using 25 ohms, the final input impedance is close to (but not exact) 50 ohms and matched with the source.  We want the feedback in both paths to see a load impedance that is the same.  The combined impedance a the input or top leg is 25 (Rg) +50 (Rsrc) ohms so the resistor on the bottom path is set to 75 ohms.

The following is a spice AC Bode plot of the single ended input and output voltages.  The single ended input is less than 0dB as it is referenced to the source (pre source output impedance).  It is a little less than a 6dB drop so the input impedance of the amplifier is not exactly 50 ohms (which we knew from the calculations but close enough using standard resistor values).  The output is +11.5dB from the reference with the difference between input and output being 15.6dB.
SPICE AC Gain. SEin=-4.5dB, SEout=11.6dB, Voltage gain=15.6dB w/ 8 degree phase variance across the span.
This simulation is a nice validation of the calculations and final circuit, however, it is still a little off from the measured values and does not include the LPF at the ADC.  The following model does that with the corresponding Bode plot of just Vout-se/Vin-se.
SPICE model with output LPF and ADC input model.
The ADC input model is not very sophisticated. I am not clear on how to properly model the sample and hold input while switching (here a simple parallel RC combination is used). The figure below captures the AC analysis. At 10.7MHz the gain is showing 15dB.
Magnitude and Phase of Vout-se/Vin-se with LPF and ADC model.
This is still a half dB off but well within my expectations and needs.

Saturday, April 18, 2015

Prj137 BBB and ADC Spurs

While the overall noise floor of the updated ADC was quite good, a couple of low level spurs were present that I wanted to understand.  These show up at 2.004699MHz and 2x (~4MHz) on the particular unit under test.  After unrolling the spurs and taking measurements at a couple of different sampling frequencies they began to really look like 2 and 4MHz, not some higher frequency.  On a quick review of the data sheets for the parts on the board and BBB the first candidate was the BBB primary regulator (TPS65217C). This includes a switching regulator operating at 1.95MHz to 2.55MHz (nominally 2.25MHz).

In a quick attempt, a 10uF bypass capacitor was added across C106 on the SYS_5V supply.  This did make a few dB of improvement in the spurs so I thought I was on the right track. Another 10nF shunt capacitor was added on C119 but to no additional help.

Just to get myself calibrated, the first spur is on the order of -93dBFS which translates into 22uV RMS.  The ADP150 datasheet shows a power supply rejection ratio (PSSR) of -35dB to -40dB for 2MHz and 4MHz.  The amplifier datasheet quotes at least 55dB of PSSR.  The ADC does not quote a PSSR but one would expect at least 20dB - 60 dB.  The board has separate analog and digital power which are decoupled with a SMT choke.  Given all of this I expected to be able to see the source of noise of the board using just a simple scope probe.  On poking around on the board both digital, analog, and supply input - no luck, nothing even close.

In an attempt to do better than a simple oscilloscope probe, a white wire from SYS_5V pin was brought out to a 10uF on a spare SMT pad on the board.  This was then jumpered to an SMA connect which was then attached to a spectrum analyzer.  A picture of that setup is below.
SYS_5V spurious measurement
Low frequency scans were taken with the BBB off and with it on and the ADC operating for comparison.  Those results are below.
Low frequency spectrum with BBB powered off and with it on and ADC operating.
The really low frequency response of the SA used may not be so great (only quoted down to 1MHz), however, the spurs at 2MHz and 4MHz are clear.  The rest of the spectrum up to 100MHz was investigated as well (just to make sure that the source really wasn't a higher frequency and rolling into the low end).  The spectrum was clear (other than the 10MHz ADC sample clock harmonics) while the ADC was operating.

The 2MHz spur at -65dBm above corresponds to roughly 126uV RMS while the -93dBFS from the ADC spectrum corresponds to 22uV.  126/22 = 5.7 which translates to -15dB of attenuation. The bottom line being there is not a whole lot of PSSR compared to what one would expect.

Just to make sure I wasn't doing something silly like pushing the regulator too hard and causing problems I decided to revisit the current consumption budget on the board re-checking the dynamic component.  The following table captures that.
ADC Board Current Consumption
Even factoring in the current from digital and clock IO and using a full swing signal from the amplifier (which this measurement does not have), the current draw on the regulator is a little over half its rating.  Even if the digital line load capacitance is twice what this assumes, the current load would be two thirds the rated 150mA.

With the above in hand, I went back to the board to evaluate the spectrum at different points on the supply using the same setup as above.  The following graph compares the spectrum at the 5V source, 3.3V on-board regulator output and the 3.3V regulated output after the supply choke into the analog section.
Low frequency spectrum of supply line at various points on the ADC board.
No surprises here at the 2MHz noise.  The 4MHz is interesting in that sometimes the noise is pronounced but generally quite low and not noticable on this measurement.  (The envelope history of the analyzer is used so it depends on how long you observe it for and what you are doing - a "shutdown -h now" always creates a period of 4MHz activity).

At this point it seemed that the noise was more subtle than just supply ripple.  With that idea I revisited ground loops (where you won't directly see the currents only the artifacts afterwards and points at which you cannot access for measurement).  The ADI MT-031 application note does a good job going through the various aspects of mixed signal grounding in different environments. With this I realized I did exactly the wrong thing by isolating the analog ground plane with a choke. This would have been ok if I had directly tied the two together at the ADC (as one of the examples in the paper shows).  Fortunately, this was easily addressed by removing the choke (L101) and jumpering across the exposed ground plane edges near the ADC.  The spectrum below was taken with that configuration.
50 ohm grounded input with jumpered grounds
The spurs at 2MHz and 4MHz have dropped about 3dB relative to the choke coupled ground and are now at -100dBFS (marker 3) and -95dBFS (marker 1).

So in the end, the noise environment on the ADC ok.  Even factoring in recommended PCB layout techniques and best practices with ADCs (at least as best as I could do with the tradeoffs presented in a 2" x 3" two layer PCB) there are still switching related spurs.