Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Perghel Alin-Marian
Published

Spectrum Analyzer for Industrial Applications

Spectrum Analyzer using Zybo Z7 board, PMOD AD2 and Processing v3.x for displaying the spectral lines.

BeginnerWork in progress2,058
Spectrum Analyzer for Industrial Applications

Things used in this project

Story

Read more

Code

C code

C/C++
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include "platform.h"
#include "xil_printf.h"
#include <xgpio.h>
#include "xparameters.h"
#include "sleep.h"
#include "PmodAD2.h"

// FSM Statuses
#define RESET 0
#define WRITE 1
#define READ 2
#define PROCESSING 3
#define CHECK_RFFD 4
#define SHOW 5
#define READ_AD 6

// function prototipes
void one_clock(u16 data_write);
bool check_rffd();
bool check_valid();

int state = 0;
int count = 0;
int read_count = 0;
u16 value = 0;
u16 data_write = 0x0000;
u32 dft_data = 0x00000000;
u8 exp_data = 0x00;
#define num_points 120

u16 xk_re[num_points - 1];
u16 xk_im[num_points - 1];
u16 analog_signal[num_points -1];

XGpio gpio, gpio2;
PmodAD2 analog_in;

int main()
{
	XGpio_Initialize(&gpio, XPAR_AXI_GPIO_0_DEVICE_ID);
	XGpio_SetDataDirection(&gpio, 1, 0x0); // channel 1 OUTPUT
	XGpio_SetDataDirection(&gpio, 2, 0xF); // channel 2 INPUT

	XGpio_Initialize(&gpio2, XPAR_AXI_GPIO_1_DEVICE_ID);
	XGpio_SetDataDirection(&gpio2, 1, 0xF); // channel 1 INPUT
	XGpio_SetDataDirection(&gpio2, 2, 0x0); // channel 2 OUTPUT

	// set transform length (D'8' = 120 points;
	XGpio_DiscreteWrite(&gpio2, 2, 0x08);

	AD2_begin(&analog_in, XPAR_PMODAD2_0_AXI_LITE_IIC_BASEADDR, AD2_IIC_ADDR);
	AD2_WriteConfig(&analog_in, 0x10);

	init_platform();
    //print("Platform init\n\r");

    while(1){
    	switch(state){
    	case RESET:
    		// clear = 1 (bit 14);
    		data_write = 0x4000;
    		XGpio_DiscreteWrite(&gpio, 1, data_write);
    		// CLK
    		one_clock(data_write);
    		// clear = 0 (bit 14);
    		data_write = data_write & 0xBFFF;
    		//xil_printf("DFT Reset\n\r");
    		if(check_rffd()){
    			count = 0;
    			state = READ_AD;
    		}else{
    			state = RESET;
    		}
    		break;
    	case READ_AD:
    		for(int i = 0; i <= num_points; i++){
        		int an1 = 0;
        		int an2 = 0;
    			usleep(250);
    			value = 0;

    			AD2_ReadConv(&analog_in, &value);
				value = value & AD2_DATA_MASK;
				an1 = value;

				value = 0;
				AD2_ReadConv(&analog_in, &value);
				value = value & AD2_DATA_MASK;
				an2 = value;

    			analog_signal[i] = ((an1 + an2) / 2)/2; // average of 2 readings
    			//xil_printf("%d \n\r", value);
    		}
			state = WRITE;
    		break;
    	case WRITE:

    		data_write = 0x0;
    		//XN RE to DFT
    		data_write = data_write | analog_signal[count];
    		// if count = 0 then set FD_IN
    		if(count == 0){
    			data_write = data_write | 0x2000;
    		}
    		XGpio_DiscreteWrite(&gpio, 1, data_write);

    		// CLK
    		one_clock(data_write);
    		count = count + 1;

    		if(count == num_points-1){
    			count = 0;
    			data_write = 0x0;
    			state = PROCESSING;
    		}else{
    			state = WRITE;
    		}
    		break;
    	case READ:
    		dft_data = 0;
    		dft_data = XGpio_DiscreteRead(&gpio, 2);

    		xk_re[read_count] = dft_data & 0x00000FFF;
    		//xk_im[read_count] = dft_data & 0x00FFF000;

    		one_clock(data_write);

    		if(read_count == 0){
				exp_data = XGpio_DiscreteRead(&gpio2, 1);
				//xil_printf("%d\n",exp_data);

			}
    		read_count = read_count + 1;
    		if(check_valid()){
				state = READ;
			}else{
				state = SHOW;
			}
    		break;
    	case SHOW:
    		//xil_printf("ready");
    		for(int i = 0; i <= num_points-1; i++){
    			if(i==(num_points-1)){
    				xil_printf("%d\n",xk_re[i]);
    			}else{
    				xil_printf("%d,",xk_re[i]);
    			}
    		}
    		state = RESET;
    		break;
    	case PROCESSING:
    		one_clock(data_write);
    		// check data_valid
    		if(check_valid()){
    			read_count = 0;
    			state = READ;
    		}else{
    			state = PROCESSING;
    		}
    		break;
    	default:break;
    	}
    }

    cleanup_platform();
    return 0;
}

void one_clock(u16 data_write){
	data_write = data_write | 0x8000;
	XGpio_DiscreteWrite(&gpio, 1, data_write);
	usleep(1);
	data_write = data_write & 0x7FFF;
	XGpio_DiscreteWrite(&gpio, 1, data_write);
}

bool check_rffd(){
	u32 data = XGpio_DiscreteRead(&gpio, 2);
	if((data & 0x08000000) > 0 ){
		return true;
	}else{
		return false;
	}
}

bool check_valid(){
	u32 data = XGpio_DiscreteRead(&gpio, 2);
	if((data & 0x02000000) > 0 ){
		return true;
	}else{
		return false;
	}
}

Show Spectrum

Processing
import processing.serial.*;

int wnd_w = 1200;
int wnd_h = 450;
int nr_points = 120;
Serial serial;
String val;

void setup(){
  // hardcoded due to issue 4893
  size(1200, 450);
  background(200);
  frameRate(30);
  
  String portName = Serial.list()[1];
   serial = new Serial(this, portName, 115200);
   serial.bufferUntil(10);
}

void draw(){
    background(200);

  //serial.write(0);
  println(val);
  
  if(val != null){
    int values[] = int(split(val, ','));
    
    for(int i=0; i<=nr_points/2; i++){
      int spectr_line_val = int(map(values[i], 0, 4095, 0, 100));
      draw_spectr_line(i, spectr_line_val);
    }
  }
}

void serialEvent(Serial p){
 val = p.readString(); 
}

void draw_spectr_line(int pos, int value){
  stroke(255,255,255);
  int rect_w = wnd_w / nr_points;
  float rect_h = map(value, 0, 100, 0, 400);
  int x = pos * rect_w;
  stroke(255,255,255);
  rect(x, wnd_h, rect_w, - rect_h);
  redraw();
}

DFT Controller module

VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity dft_controller is
    Port ( ps_input : in STD_LOGIC_VECTOR (15 downto 0);
           ps_output : out STD_LOGIC_VECTOR (31 downto 0);
           ps_out_re : out STD_LOGIC_VECTOR (11 downto 0);
           ps_in_re : in STD_LOGIC_VECTOR (11 downto 0);
           ps_in_im : in STD_LOGIC_VECTOR (11 downto 0);
           clk : out STD_LOGIC;
           clear : out STD_LOGIC;
           fwd_inv : out STD_LOGIC;
           fd_out : in STD_LOGIC;
           fd_in : out STD_LOGIC;
           rffd : in STD_LOGIC;
           data_valid : in STD_LOGIC);
end dft_controller;

architecture Behavioral of dft_controller is

begin
-- output --
clk <= ps_input(15);
clear <= ps_input(14);
fd_in <= ps_input(13);
ps_out_re(11 downto 0) <= ps_input(11 downto 0);
-- input --
ps_output(11 downto 0) <= ps_in_re(11 downto 0);
ps_output(23 downto 12) <= ps_in_im(11 downto 0);
ps_output(25) <= data_valid;
ps_output(26) <= fd_out;
ps_output(27) <= rffd;
fwd_inv <= '1';

end Behavioral;

Credits

Perghel Alin-Marian

Perghel Alin-Marian

1 project • 0 followers
Web Developer, Student @ Petru Maior University - Tîrgu Mureș

Comments