Thursday, December 3, 2015

Talking to ZedBoard/Secure Digital (SD) Card mounting and un-mounting

Setting Jumpers

MI05 and MI04 must be set to High (1) as shown in ZedBoard image (Image 1)



Image 1


Voltage Supply Pin or GND is indicated by VADJ and either select 2V5 or 1V8 (seen in Image 2)


Image 2



Now SD Card and the ZedBoard

Opening SDK and connecting the ZedBoard to the terminal properly will prompt: zynq> 

The ZedBoard will be lighten up accordingly to what Image 3 shows. 

Image 3


Mounting the SD Card command:

zynq> mount /dev/mmcb1k0p1 /mnt

Un-mounting the SD Card command:

zynq> unmount  /mnt

The image below shows the mounting process from terminal in SDK (Image 4)



Image 4

Proper command to poweroff the ZedBoard from the terminal:

zynq> poweroff

Image 5 shows this process in the terminal below.



Image 5


OPEN SOURCE LINUX

OPEN SOURCE LINUX

Our Command: opt/Xilinx/SDK/2013.4/gnu/arm/lin/bin

Steps:

1. Need to fetch source codes and then fetch linux kernel

in the terminal: git clone git://github.com/Xilinx/linux-xlnx.git
1.75GB

2. Now U-Boot: git clone git://github.com/Xilinx/U-boot-xlnx.gir

3. Device Tree Gen: git clone git://github.com/Xilinx/device-tree.git

Note: Need to add GPU core on PL


Fall Semester 2015 ZedBoard Research

Tuesday, October 20, 2015

General AXI Properties/About AXI (unfinished)

AXI
-AXI is a type of bus that connects modules on a chip
-two types: Slaves and Masters

AXI Masters
-initiate transactions between modules (transactions can be seen as read/write data being sent back and forth)

AXI Slaves
-respond to initiated transactions made by Masters
-addresses for slave modules can be defined by the user but no two slaves can have any address overlap

AXI Interconnect
-capable of a lot of actions
-connect master and slave modules
-can be hierarchical
-one AXI Interconnect can have up 16 slaves and 16 masters
-can convert 64 bit transactions to 32 bit transactions if needed





AXI Addressing
-Masters send read/write commands through the AXI Interconnect to slaves
-slaves have address ranges that commands from masters must fall into
Examples: UART: 0x40000000-0x40000FFF
                   GPIO: 0x40001000-0x40001FFF
                   RAM: 0x40010000-0x4001FFFF







**The AXI interconnect is a vital piece when assembling a block design in Xilinx Vivado.**


Monday, October 19, 2015

Video Series to understand Petalinux

The following link has a quite lengthy video series Sessions 1-13 that cover parts of the FPGA, what they do, and how they can be used together to ultimately load Petalinux using the ZedBoard.

(Some of the videos on this channel are unrelated, videos can be differentiated by looking at the titles)

Mohammadsadegh Sadri


Monday, July 27, 2015

Exporting Project to SDK for AD9467/Running Example Github Code

This blog follows up the Vivado Hardware design for the AD9467 created in Vivado 2014.2. I then tried to open up the Vivado project in 2014.4, which ran fine. Before exporting to SDK in 2014.4, I had to update some of the ip-blocks in the Block Design because they were designed for 2014.2. There were 13 blocks total that needed to be upgraded. Only 7 upgraded without manual intervention.  I was unable to update the last 6 with an error telling me that the blocks could not be found in the IP Catalog. From some research,  I found that I had to add another IP Repository with the 6 "locked" blocks. Since they were not upgraded, I was unable to customize them; therefore locked.

I am still working on this problem but I wanted to export the project and program the FPGA with the software from:

http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467#using_the_hdl_reference_design 

Select AD9467-FMC-EBZ Reference Design  the following menu:

You will be brought to a Github repository similar to the one found in the Hardware Design. Click the double arrow on the right-hand side of the page and download the ZIP file.  

1. Extract the files to your download directory and copy them to wherever you'd like.

2. Make sure the bitstream is written in Vivado (it should be done for you if you follow the directions in the hardware blog).

3. Export Hardware.

4. Launch SDK ensuring the workspace is the same as the one you've been saving your other projects too.

5. Create a new Empty Application

6. Import the following files to the "src" folder:
/home/zynquser/Downloads/no-OS-master/drivers/AD9467/AD9467.c
/home/zynquser/Downloads/no-OS-master/drivers/AD9467/AD9467.h
/home/zynquser/Downloads/no-OS-master/drivers/AD9517/AD9517.c
/home/zynquser/Downloads/no-OS-master/drivers/AD9517/AD9517.h
/home/zynquser/Downloads/no-OS-master/drivers/AD9517/AD9517_cfg.h
/home/zynquser/Downloads/no-OS-master/AD9467-FMC-EBZ/cf_ad9467.c
/home/zynquser/Downloads/no-OS-master/AD9467-FMC-EBZcf_ad9467.h
/home/zynquser/Downloads/no-OS-master/AD9467-FMC-EBZ/main.c
/home/zynquser/Downloads/no-OS-master/AD9467-FMC-EBZ/spi.c
/home/zynquser/Downloads/no-OS-master/AD9467-FMC-EBZ/spi.h

7. Program the FPGA - there should be no issues here

8. In order to see the output (if you check the main.c file you  will see that there are some initial tests the code runs to ensure proper connection and driver installation), open up gtkterm from the terminal.

9. Check to see which port the UART cable is connected to, usually ttyACM0. Change the permissions using sudo chmod 666 /dev/ttyACM0.

10. Run as -> Launch on Hardware (you should see the program output some print statements)

***Note: We have not connected the AD9467 to any function generator yet, this is just the instructions to load the software onto the Zedboard. Once we get the cables to connect to a function generator, we can practice with some example frequencies and take some data. Then move it to MATLAB, plot it, and see if we can get some meaningful graphs.***



Friday, July 24, 2015

Dr. McColgan's Lab Computer Setup

Workstation 1 (in the annex, shorter desk, closer to McColgan's office):

Hard Drive 1: WDC W10EZEX-75M2NA0    - CentOS 6
Hard Drive 2: ST500DM002-1BD142             - Windows (with Virtual Machine)



Workstation 2 (in the annex, taller desk, near the window):

Hard Drive 1: WDC W10EZEX-75M2NA0    - CentOS 6
Hard Drive 2: ST500DM002-1BD142             - Windows (with Virtual Machine)


During boot-up press F12  (Dell Logo Screen) and select which hard drive you plan to use.

Tuesday, July 21, 2015

Building/Running a Vivado Project from the Tcl Console

***Read through the whole blog before following it step by step. There are notes sprinkled throughout that are helpful to keep in mind. The blog reads as a my own personal trial and error story so some things seem superfluous when they are not! Avoid the same mistakes I made!***


Continuing on the ADC project, we ordered a board called the AD9467-FMC-250EBZ. Searching online and getting help from Joe Kujawski, I found that there is a Github repository filled with a hardware design and pre-written software that should allow us to run a program on the board seamlessly. Here is the link to the Wiki page explaining the board and it functionality:

http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467#using_the_hdl_reference_design

The page above lists links to the Github repository I downloaded the zip file from. I chose the first link (Zed HDL Reference Design) from this download section to navigate to the hardware design:



Once at the new page I simply click the double arrow on the right hand side of the page (<>) to get a new menu which appears directly underneath it:

Before:


After clicking <>:


Notice in the picture above there is an option for "Download Zip". Click this and the download will start automatically. Once downloaded, navigate to your Downloads directory and extract the files to whichever location you choose. I typically go with the strategy of extracting right in the Downloads directory and copying the file to a new one ("Vivado Projects" perhaps) later on. But if I forget where I copy it to I know it is always in the Download folder!

Once extracted I followed the directions from a great tutorial found here:

http://wiki.analog.com/resources/fpga/docs/hdl#building_hdl


Starting with "Building with Vivado," follow the instructions for building the libraries for your project and generating your block design for the project (all done through the Tcl console).

***Note: The project files downloaded from the Github repository are only compatible with Vivado 2014.2. The Virtual Machine I am working on did not have this Xilinx version installed so it is important to check before going ahead with the instructions. Completing the instructions from the tutorial page using Vivado 2014.2 will result in an error from the Tcl console that reads:

ERROR: This project requires Vivado 2014.2.
    while executing
"adi_project_create $project_name"
    (file "./system_project.tcl" line 7)


***Additional Notes: Running the Tcl script for building the libraries loads just fine in 2014.2, but trying to run the project files (generate block diagram) comes up with this error:

ERROR: [BD 5-216] VLNV <analog.com:user:util_i2c_mixer:1.0> is not supported for this version of the tools.
ERROR: [Common 17-39] 'create_bd_cell' failed due to earlier errors.

    while executing
"create_bd_cell -type ip -vlnv analog.com:user:util_i2c_mixer:1.0 sys_i2c_mixer"
    invoked from within
"set sys_i2c_mixer [create_bd_cell -type ip -vlnv analog.com:user:util_i2c_mixer:1.0 sys_i2c_mixer]"
    (file "../../../projects/common/zed/zed_system_bd.tcl" line 66)

    while executing
"source $ad_hdl_dir/projects/common/zed/zed_system_bd.tcl"
    (file "system_bd.tcl" line 2)

    while executing
"source system_bd.tcl"
    (procedure "adi_project_create" line 107)
    invoked from within
"adi_project_create $project_name"

    (file "./system_project.tcl" line 7)


Solving this problem takes awhile whether or not you know what you are doing. It is important to RUN EVERY SINGLE TCL SCRIPT FOUND IN THIS DIRECTORY:

/home/zynquser/Downloads/hdl-master/library

There are roughly 40 .tcl files (Tcl scripts) that need to be run before getting to the next step of the process; loading the project file you need.

Recapping:

1. Download
2. Extract into Downloads folder.
3. Open Vivado 2014.2
4. Build every sub-library listed in:
          /home/zynquser/Downloads/hdl-master/library
         ***This requires entering these instructions for ALL 42 items in the library folder:***
        

Library

We need to build the libraries first. So open the GUI and at the TCL console change the directory to where the libraries are. You must build ALL the libraries (each folder insider the library directory).
cd /home/zynquser/Downloads/hdl-master/library/axi_ad6676
You should see a tcl script axi_ad6676_ip.tcl in this directory. We just need to run that script.
source ./axi_ad9122_ip.tcl
You will see commands being executed, and the GUI will change into a project window. There is nothing to do here, you could browse the source, if you prefer to do synthesis as stand alone and such things. If you are not fancy about it, just quit and continue to build libraries for other cores.



5. Load the project you need: It will be AD9467 for this specific application:

Projects

After building all the libraries (or the ones you are interested in), you can run the project (generate bitstream and export the design to SDK). This is the same procedure as above except for changes in path and tcl file names.
Let's open the GUI again and at the TCL console change the directory to where the project is.
cd //home/zynquser/Downloads/hdl-master/projects/ad9467_fmc/zed
You should see a tcl script system_project.tcl in this directory. We just need to run that script.
source ./system_project.tcl
You will see commands being executed, and the GUI will change into a project window. The script will create a board design in IPI, generate all the IP targets, synthesize the netlist and implementation. It also exports the hardware to SDK.

6. The Tcl script we just ran will take care of everything we usually do with Vivado: Run Synthesis, Run Implementation, Write Bitsream, Export Hardware. In addition the pin assignments for the FMC-LPC portion of the Zedoboard is automated by the Tcl script so no need to go in to I/O Ports and assign specific Sites. The only thing left to do is Launch SDK with your project.

***Although it is somewhat obvious, this is how the AD9467 connects to the Zedboard:***






 It is officially time to Launch SDK and begin loading software onto the Zedboard (Program FPGA). Luckily, there is another Github repository that has pre-written software. I will explain those steps in the next blog post.



Thursday, July 16, 2015

General Info PART 2 - AD9467 - FMC -250EBZ

The AD9467 uses standard Serial Port Interfacing (SPI)

SPI is a synchronous data bus meaning that it uses separate lines for data and a "clock" that keeps both sides in perfect sync. The "clock," as we familiarized ourselves with using the Maxim 11205 ADC, is an oscillating signal that tells the receiver exactly when to sample the bits on the data line. Sometimes the receiver will sample the bits from the data line when the clock goes from HI to LO or when it goes from LO to HI.

Looking at the datasheet for the AD9467, I found that the board comes equipped with three Serial Port Pins: SCLK, SDIO, and CSB.

The falling edge of the CSB, along with the rising edge of the SCLK, determines the start of the framing sequence. During an instruction phase, a 16-bit instruction is transmitted followed by one or more data bytes, which is determined by Bit Field W0 and Bit Field W1. Here is an example of a timing diagram for the board:

As you can see in the diagram, when the CSB line is brought low, the device processes SDIO and SCLK instructions. After the 16-bit instruction set, the CSB goes high, thus ending communication with the other two pins. 

Data can be sent in either MSB (most significant bit) or LSB (least significant) mode. In MSB first mode, the data is transmitted starting with the 16th bit in descending order towards the 1st bit. The opposite is true for LSB first mode. 

Here is a good link regarding interfacing high speed ADCs via SPI:


Additional Notes from Joe:

At a high level, RS232 is single ended and uses a wide voltage swing (the standard actually calls for +/-12V). This has a problem of being pretty high power and being very limited in terms of speed of transmission.  RS232 is susceptible to noise and differences in the sending and receiving ground voltages, so the longer the distance between the source and destination, the more likely it is that there is an error.

LVDS is a current drive system (instead of Voltage drive) which means that it does not care about any differences in the ground potential at the source vs. the destination.  Also, since it is differential, noise will be 'picked up' on both lines at the same time and will be cancelled out.  Finally, LVDS is very high speed compared to RS232 mainly due to the many advantages I already listed.


Tuesday, July 14, 2015

General Info - AD9467 - FMC -250EBZ

The AD9467 is a 16 - bit monolithic, IF sampling analog-to-digital converter (ADC). The board shipped to us has two good data sheets:

Datasheet - http://www.analog.com/media/en/technical-documentation/data-sheets/AD9467.pdf

Board Evaluation Guide - http://www.analog.com/media/en/technical-documentation/evaluation-documentation/UG-200.pdf

Back up two steps and define some important terms from the first sentence:

1) monolithic IC- A monolithic integrated circuit, in general, is a type of IC that is made on the surface of a single crystal semiconductor like a silicon wafer. A process called "planar technology must be used in the single block (monolith) and be interconnected to the insulating layer over the same body of the semiconductor to produce a solid integral monolithic IC.

2) Integrator - integrated based ADC. The input voltage is integrated, compared to a reference voltage, and converted into a digital representation. The integrator uses a reference capacitor which is chosen depending on the bandwidth of the signal. Wikipedia has a good link in its op-amp section explaining an inverting integrator. Replace the resistor connecting the positive input to the output of a differential amplifier and get an inverting amplifier.


3) IF - intermediate frequency sampling - essentially taking an input signal and mixing it with a signal produced by a local oscillator to get what is called a beat or difference frequency. From what I understand the signals are added/subtracted using the principle of superposition and the resulting frequency is more "powerful" in that it is more easily manipulated/amplified/analyzed for a specific application.

3) Wide bandwidth/bandwidth - the difference in the upper and lower frequencies in a set of frequencies. In the radio world, radio companies will purchase a given bandwidth that says they have the right to broadcast over a slice of frequency in the sound spectrum of the geographic location they are located in.

4) NOTES FROM DATASHEET*****"The ADC requires 1.8 V and 3.3 V power supplies and a low voltage differential input clock for full performance operation. No external reference or driver components are required for many applications. Data outputs are LVDS compatible (ANSI-644 compatible) and include the means to reduce the overall current needed for short trace distances. Figure 1. A data clock output (DCO) for capturing data on the output is provided for signaling a new output bit. The internal power-down feature supported via the SPI typically consumes less than 5 mW when disabled. Optional features allow users to implement various selectable operating conditions, including input range, data format select, and output data test patterns. The AD9467 is available in a Pb-free, 72-lead, LFCSP specified over the −40°C to +85°C industrial temperature range."****

 - low voltage differential input clock or the board uses low voltage differential signaling (LVDS) a physical layer characterization describing electrical components that can run aat very low power yet very high speeds - often in combination with twisted pair coaxial cable inputs that reduce electromagnetic interference from other sources.

-DCO - Data Clock Output -

- SPI - Serial Port Interfacing -





Monday, July 13, 2015

Angle Encoder Revisited

I had a couple ideas I wanted to get out onto paper before I forget them regarding the errors that arise with the angle encoder. For the first version of the hardware, with the first two pins of the PMODs being used as a single interrupt, the threshold for which the pin changes from a HI to LO State is unclear. As the encoder shaft spins, the value on one of the pins will shift from 1 to 0 seemingly if there is any voltage above 0.0 V. But this surely cannot be the case. I have tested the chip/Zedboard combination to find where this threshold exists using a voltmeter but have come up empty on my attempts. I hold that the value is changing too quickly for the voltmeter to pickup the incremental changes sent to the Zedboard from the encoder. I know that the value is changing rapidly because I print out the value from "encoded" which is the combination from both encoder pins which should read a 11 10 01 or 00. Moving clockwise should follow the same order over and over and the same follows for counter-clockwise. There must be some noise, instead that is mucking up the cycle causing the algorithm I have written to break down. If I can find this threshold in the PMOD for where the change exists, I should have a properly working angle encoder.

Tuesday, June 30, 2015

Useful Delay Function

It always takes a while to poke around the blog and find the delay function to copy and paste, so here it is:

void delay(int nStopValue)
/**
* \brief       Loop for nStopValue iterations to provide a delay.
* \par         Details
*              It is commonly used with the constant 'ABOUT_ONE_SECOND' defined in maximPMOD.h for
*              setting approximate delays
*
* \param[in]   nStopValue    - number of iterations to loop
*
* \retval      None
*/
{
    int i=0;
    int a=0;

    for(i=0;i<nStopValue;i++)
    {
        a=i;
    }
}


******USE THIS DEFINITION TO PASS INTO THE DELAY FUNCTION******

#define ABOUT_ONE_SECOND 74067512

PMOD used as an Interrupt

Both tutorials 2B and 2d utilize interrupts in the form of the buttons provided on the Zedboard. I decided to use both tutorial codes for reference in programming the rotary encoder for the Viper Telescope.

The rotary/angle encoder is an electro-mechanical chip that converts the angular position of a shaft (usually motor shaft) to a digital value. The encoder we are using will be connected to the motor shaft atop the Viper Telescope and will allow us to determine the position/angle of the telescope based on how far the motors have moved. There are five pins on the chip:

1) CLK
2) DT
3) SW - Resets the encoder to zero (used for calibration)
4) V++ - Power (3.3 Volts is a good operating voltage)
5) Ground

The first two pins CLK and DT are the digital encoding pins. Referring to the Arduino code in Frank/Ryans's blog I found out what these two pins do. Based on which direction the encoder is spun, we get a different sequence of values from each pin. Each pin can only read a 1 or a 0. From testing today, I found that when the shaft is in a "resting mode" the pins will either read both 0 or both 1. You will notice when playing around with the encoder that the shaft moves in specific increments (not a smooth spin, yet more like a gear). There are roughly 20 increments in one full rotation of the shaft. From testing I found that starting at rest a position I will call A, the read value from both pins turns out to be 4. How do I achieve the value of 4 you ask?

Well, in the hardware design I initialized a GPIO to be all INPUTS with a 2 BIT GPIO WIDTH. After that I was able to assign the sites of the GPIO to be the first two pins of the JA PMOD, pins JA1 and JA2. Miranda's blog lists the sites for all the PMOD pins in the implemented design.

So, moving from position A to position B (1 increment in the clockwise direction) I found that the Discrete Read Value on the 2-BIT PMOD Channel I created becomes 0 (instead of 4). So initially I thought that the encoder can only read a 0 or 4 because whether or not I moved in the clockwise or counter-clockwise, I would only get readings of 0 or 4. Then I was more precise with my turning of the shaft and was able to get more values. Halfway in between positions A and B, I get a value of 1 for the read value. From B to halfway to C, I get a value of 3. So a full rotation looks like this:

Position A =    0 = 00
Position A.5 = 1 = 01
Position B =    3 = 11
Position B.5 = 2 = 10
Position C = Position A = 0 = 00 for a full clockwise rotation.



Position A =    0 = 00
Position A.5 = 2 = 10
Position B =    3 = 11
Position B.5 = 1 = 01
Position C = Position A = 0 = 00 for a full clockwise rotation.

The nest step is to work on the interrupt handler that will use the previous read value, combine with the current value in a variable called sum. Depending on the value of sum, I can determine which direction the encoder, and therefore the motor, spun. If it spun clockwise, increase the encoder value by 1 and multiply by 4.5, if it spun counter-clockwise, decrease the encoder value by 1 and multiply it by 4.5


Additional Notes:

1) The interrupt handler for tutorial 2B looks like this:

void BTN_Intr_Handler(void *InstancePtr)
{
// Disable GPIO interrupts
XGpio_InterruptDisable(&BTNInst, BTN_INT);
// Ignore additional button presses
if ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=
BTN_INT) {
return;
}
btn_value = XGpio_DiscreteRead(&BTNInst, 1);
printf("%d \n \r", btn_value);
// Increment counter based on button value
// Reset if centre button pressed
if(btn_value != 1) //led_data = led_data + btn_value;
//else led_data = 0;
    XGpio_DiscreteWrite(&LEDInst, 1, btn_value);
    (void)XGpio_InterruptClear(&BTNInst, BTN_INT);
    // Enable GPIO interrupts
    XGpio_InterruptEnable(&BTNInst, BTN_INT);
}

To me , it seems as if if the interrupt handler is always initialized and sort of lurking, reading, waiting to do something. In this case it is writing to the LEDs the value given by discrete read.

2) When using the virtual machine, it is important to use PuTTY as the terminal interface in Windows. To do so, first get your program ready set in SDK and Program FPGA. Before running the program, check the Device Manager to determine which COM port the Cypress USB UART cable (this is the usb cable from the Zedboard that communicates with the terminal) is connected to. Then open up PuTTy, select Serial, and enter the correct COM port. Be sure to change the BAUD rate to 115200. 

3) It is possible to engage the pull-up/pull-down resistors on an input pin using a couple different ways:
 a) Using Vivado, open the implemented design and check I/O ports (in window drop-down menu) and select the type of resistor you want under the PullType drop-down menu (it's pretty far to the right in the I/O menu)
b) Using SDK, use SetDataDirection to set inputs and outputs. Using DiscreteWrite and writing outputs high will output voltages that you chose in the hardware design. Setting an input high will engage the internal pull-up resistor in each pin of the PMOD.






Final Working Code for Angle Encoder:

#include "xparameters.h"
#include "xgpio.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"
#include <stdio.h>

// Parameter definitions
#define ABOUT_ONE_SECOND 74067512
#define INTC_DEVICE_ID         XPAR_PS7_SCUGIC_0_DEVICE_ID
#define BTNS_DEVICE_ID        XPAR_AXI_GPIO_0_DEVICE_ID
#define LEDS_DEVICE_ID        XPAR_AXI_GPIO_2_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR

#define BTN_INT             XGPIO_IR_CH1_MASK

XGpio LEDInst, BTNInst;
XScuGic INTCInst;
//static int led_data;
static int btn_value;
static int sum;
float angle;
volatile int lastEncoded=0;
volatile long encoderValue=0;
long lastencoderValue = 0;
//----------------------------------------------------
// PROTOTYPE FUNCTIONS
//----------------------------------------------------
static void BTN_Intr_Handler(void *baseaddr_p);
static int InterruptSystemSetup(XScuGic *XScuGicInstancePtr);
static int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr);

//----------------------------------------------------
// INTERRUPT HANDLER FUNCTIONS
// - called by the timer, button interrupt, performs
// - LED flashing
//----------------------------------------------------
void delay(int nStopValue)
/**
* \brief       Loop for nStopValue iterations to provide a delay.
* \par         Details
*              It is commonly used with the constant 'ABOUT_ONE_SECOND' defined in maximPMOD.h for
*              setting approximate delays
*
* \param[in]   nStopValue    - number of iterations to loop
*
* \retval      None
*/
{
    int i=0;
    int a=0;

    for(i=0;i<nStopValue;i++)
    {
        a=i;
    }
}



void BTN_Intr_Handler(void *InstancePtr)
{
    // Disable GPIO interrupts
    XGpio_InterruptDisable(&BTNInst, BTN_INT);
    // Ignore additional button presses
    if ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=
            BTN_INT) {
            return;
        }
    btn_value = XGpio_DiscreteRead(&BTNInst, 1);
    delay(10000);
    printf(" Encoded = %d \n \r", btn_value);
    sum = (lastEncoded <<2) | btn_value;
    delay(10000);
    printf(" Sum = %d \n \r", sum);

     if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;

     if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
     lastEncoded = btn_value; //store this value for next time

     angle=encoderValue*6;
     //printf(" EncoderValue = %ld \n \r", encoderValue);
     //printf(" Angle = %f \n \r", angle);



    // Increment counter based on button value
    // Reset if centre button pressed
    //if(btn_value != 1) //led_data = led_data + btn_value;
    //else led_data = 0;
    XGpio_DiscreteWrite(&LEDInst, 1, btn_value);
    (void)XGpio_InterruptClear(&BTNInst, BTN_INT);
    // Enable GPIO interrupts
    XGpio_InterruptEnable(&BTNInst, BTN_INT);
}

//----------------------------------------------------
// MAIN FUNCTION
//----------------------------------------------------
int main (void)
{
    printf(" Start Program \r \n");
    int status;
  //----------------------------------------------------
  // INITIALIZE THE PERIPHERALS & SET DIRECTIONS OF GPIO
  //----------------------------------------------------
  // Initialise LEDs
  status = XGpio_Initialize(&LEDInst, LEDS_DEVICE_ID);
  if(status != XST_SUCCESS) return XST_FAILURE;
  // Initialise Push Buttons
  status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);
  if(status != XST_SUCCESS) return XST_FAILURE;
  // Set LEDs direction to outputs
  XGpio_SetDataDirection(&LEDInst, 1, 0x00);
  // Set all buttons direction to inputs
  XGpio_SetDataDirection(&BTNInst, 1, 0b11);
  //XGpio_DiscreteWrite(&BTNInst, 1, 0b11);

  // Initialize interrupt controller
// Initialize interrupt controller
  status = IntcInitFunction(INTC_DEVICE_ID, &BTNInst);
  //printf("Status = %d \r \n", status);
  if(status != XST_SUCCESS) return XST_FAILURE;

 /* angle=encoderValue*4.5;
           printf(" Angle = %f \n \r", angle);
           printf(" EncoderValue = %ld \n \r", encoderValue);
           delay(100);
           */






  while(1);


  return 0;
}

//----------------------------------------------------
// INITIAL SETUP FUNCTIONS
//----------------------------------------------------

int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)
{
    // Enable interrupt
    XGpio_InterruptEnable(&BTNInst, BTN_INT);
    XGpio_InterruptGlobalEnable(&BTNInst);

    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                      (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                      XScuGicInstancePtr);
    Xil_ExceptionEnable();


    return XST_SUCCESS;

}

int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr)
{
    XScuGic_Config *IntcConfig;
    int status;

    // Interrupt controller initialisation
    IntcConfig = XScuGic_LookupConfig(DeviceId);
    status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Call to interrupt setup
    status = InterruptSystemSetup(&INTCInst);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Connect GPIO interrupt to handler
    status = XScuGic_Connect(&INTCInst,
                                 INTC_GPIO_INTERRUPT_ID,
                                 (Xil_ExceptionHandler)BTN_Intr_Handler,
                                 (void *)GpioInstancePtr);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Enable GPIO interrupts interrupt
    XGpio_InterruptEnable(GpioInstancePtr, 1);
    XGpio_InterruptGlobalEnable(GpioInstancePtr);

    // Enable GPIO and timer interrupts in the controller
    XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);

    return XST_SUCCESS;
}


*****NOTE: The interrupt handler works well for the most part. Occasionally, when turning the shaft either clockwise or counter-clockwise the pins do not register as I get a value for "sum" that does not match up with any of the "sum" values in the table I made. I have tested the values for "encoded" which is simply the value of 00 01 10 or 11 and sometimes I get an incorrect value from what is actually going on. That error gets compounded when going into the sum loop. I chalked this error up to the fact that I am reading the 2-bit PMOD incorrectly. Therefore I plan on creating two individual read PMODs and then combining the value as seen in the Arduino sample code. Updates coming soon!***** 

Interrupt Link

Link to a good interrupt explanation: (Section 9 - Timer)

http://www.silica.com/fileadmin/02_Products/Productdetails/Xilinx/Zynq_ZedBoard_Vivado_Workshop_ver1.0.pdf

Friday, June 12, 2015

Research Summary



SETTING UP THE HARDWARE DESIGN

1. Select Create new project in Vivado
2. Select ZedBoard Zynq Evaluation and Development Kit from the Boards tab
3. Select Create block design from the left panel
4. Add IP (ZYNQ7 Processing System)
5.1 Run Block Automation
6.2 Add IP (AXI GPIO)
7. Run Connection Automation
8. Add IP (GPIO)
9. Right Click on the right side of the GPIO and make external.
10. Run Connection Automation
11. Double click on the GPIO and customize. Do not select either box that says    all inputs or all outputs. Set the GPIO width by changing 32 to 8.
12. Save block design
13. Validate design
14. Run Synthesis
15. Open Contraints Wizard and under the sources tab, select Leaf Cells. (CAn also input through I/0 ports in the window menu.) Here you should see your 8 pmod connections. Using the following table (which was created using page 3 and 9 of the following link : http://zedboard.org/sites/default/files/documentations/ZedBoard_RevD.2_Schematic_130516.pdf), change the sites to the correct location and make sure I/O Standard is LVMOS33.





PIN        Site        Bit #

JA1         Y11        0
JA2        AA11       1
JA3         Y10        2
JA4        AA9        3
JA7       AB11       4
JA8       AB10       5
JA9        AB9        6
JA10      AA8        7

This makes the proper connections in the Zedboard for the pins of PMOD JA.

16.Run Synthesis
17. Create HDL Wrapper (from sources tab)
18. Generate bitstream
19. Export Hardware (include bitstream)
20. Launch SDK (change workspace)
21. Open new application project
22. Expand project and import src
23. Click General > File System
24. Browse to find directory
25. Xilinx Tools > Program FPGA
26. Under Project Explorer right click to run-as project
27. Launch on Hardware
This image shows the pins of the PMOD and which pins are ground, Vcc, and signals.




SOFTWARE/CODING IN SDK 

  • The following code allows us to read voltages from different pmod pins when different buttons on the zedboard are pushed:

#include "xparameters.h"
#include "xgpio.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"
// Parameter definitions
#define INTC_DEVICE_ID   XPAR_PS7_SCUGIC_0_DEVICE_ID
#define BTNS_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID
#define LEDS_DEVICE_ID  XPAR_AXI_GPIO_1_DEVICE_ID
#define PMOD_JA1_DEVICE_ID XPAR_AXI_GPIO_2_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
#define BTN_INT    XGPIO_IR_CH1_MASK
XGpio LEDInst, BTNInst, PMODJA1Inst;
XScuGic INTCInst;
static int led_data;
static int btn_value;
//----------------------------------------------------
// PROTOTYPE FUNCTIONS
//----------------------------------------------------
static void BTN_Intr_Handler(void *baseaddr_p);
static int InterruptSystemSetup(XScuGic *XScuGicInstancePtr);
static int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr);
//----------------------------------------------------
// INTERRUPT HANDLER FUNCTIONS
// - called by the timer, button interrupt, performs
// - LED flashing
//----------------------------------------------------

void BTN_Intr_Handler(void *InstancePtr)
{
 // Disable GPIO interrupts
 XGpio_InterruptDisable(&BTNInst, BTN_INT);
 // Ignore additional button presses
 if ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=
   BTN_INT) {
   return;
  }
 btn_value = XGpio_DiscreteRead(&BTNInst, 1);
 // Increment counter based on button value
 // Reset if centre button pressed
 if(btn_value != 1) led_data = led_data + btn_value;
 else led_data = 0;
    XGpio_DiscreteWrite(&LEDInst, 1, led_data);
    XGpio_DiscreteWrite(&PMODJA1Inst, 1, led_data);
    (void)XGpio_InterruptClear(&BTNInst, BTN_INT);
    // Enable GPIO interrupts
    XGpio_InterruptEnable(&BTNInst, BTN_INT);
}
//----------------------------------------------------
// MAIN FUNCTION
//----------------------------------------------------
int main (void)
{
  int status;
  //----------------------------------------------------
  // INITIALIZE THE PERIPHERALS & SET DIRECTIONS OF GPIO
  //----------------------------------------------------
  // Initialize PMOD JA1
  status = XGpio_Initialize(&PMODJA1Inst, PMOD_JA1_DEVICE_ID);
  if(status != XST_SUCCESS) return XST_FAILURE;
  // Initialise LEDs
  status = XGpio_Initialize(&LEDInst, LEDS_DEVICE_ID);
  if(status != XST_SUCCESS) return XST_FAILURE;
  // Initialise Push Buttons
  status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);
  if(status != XST_SUCCESS) return XST_FAILURE;
  // Set PMODJA1 direction to for location  76543210   Pin 3 is an input, pin4 is an output
  XGpio_SetDataDirection(&PMODJA1Inst, 1, 0b00001000);
  // Set LEDs direction to outputs
  XGpio_SetDataDirection(&LEDInst, 1, 0x00);
  // Set all buttons direction to inputs
  XGpio_SetDataDirection(&BTNInst, 1, 0xFF);
  // Initialize interrupt controller
  status = IntcInitFunction(INTC_DEVICE_ID, &BTNInst);
  if(status != XST_SUCCESS) return XST_FAILURE;



  while(1);
  return 0;
}
//----------------------------------------------------
// INITIAL SETUP FUNCTIONS
//----------------------------------------------------
int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)
{
 // Enable interrupt
 XGpio_InterruptEnable(&BTNInst, BTN_INT);
 XGpio_InterruptGlobalEnable(&BTNInst);
 Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
              (Xil_ExceptionHandler)XScuGic_InterruptHandler,
              XScuGicInstancePtr);
 Xil_ExceptionEnable();

 return XST_SUCCESS;
}
int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr)
{
 XScuGic_Config *IntcConfig;
 int status;
 // Interrupt controller initialisation
 IntcConfig = XScuGic_LookupConfig(DeviceId);
 status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
 if(status != XST_SUCCESS) return XST_FAILURE;
 // Call to interrupt setup
 status = InterruptSystemSetup(&INTCInst);
 if(status != XST_SUCCESS) return XST_FAILURE;

 // Connect GPIO interrupt to handler
 status = XScuGic_Connect(&INTCInst,
            INTC_GPIO_INTERRUPT_ID,
            (Xil_ExceptionHandler)BTN_Intr_Handler,
            (void *)GpioInstancePtr);
 if(status != XST_SUCCESS) return XST_FAILURE;
 // Enable GPIO interrupts interrupt
 XGpio_InterruptEnable(GpioInstancePtr, 1);
 XGpio_InterruptGlobalEnable(GpioInstancePtr);
 // Enable GPIO and timer interrupts in the controller
 XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);

 return XST_SUCCESS;
}



  • The following code blinks the LEDs and turns the voltages from the pmod on and off.


/* LED_test.c
 *
 *  Created on:  13 June 2013
 *      Author:  Ross Elliot
 *     Version:  1.1
 */

/********************************************************************************************
* VERSION HISTORY
********************************************************************************************
* v1.1 - 27 January 2014
*  GPIO_DEVICE_ID definition updated to reflect new naming conventions in Vivado 2013.3
*  onwards.
*
* v1.0 - 13 June 2013
*  First version created.
*******************************************************************************************/


/********************************************************************************************
 * This file contains an example of using the GPIO driver to provide communication between
 * the Zynq Processing System (PS) and the AXI GPIO block implemented in the Zynq Programmable
 * Logic (PL). The AXI GPIO is connected to the LEDs on the ZedBoard.
 *
 * The provided code demonstrates how to use the GPIO driver to write to the memory mapped AXI
 * GPIO block, which in turn controls the LEDs.
 ********************************************************************************************/


/* Include Files */
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "xil_printf.h"


/* Definitions */
#define GPIO_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID /* GPIO device that LEDs are connected to */
#define LED 0xC3         /* Initial LED value - XX0000XX */
#define PMOD 0xC3         /* Initial LED value - XX0000XX */
#define LED_DELAY 10000000       /* Software delay length */
#define LED_CHANNEL 1        /* GPIO port for LEDs */
#define PMOD_CHANNEL 1        /* GPIO port for PMODs */
#define printf xil_printf       /* smaller, optimised printf */
#define PMOD_JA1_DEVICE_ID  XPAR_AXI_GPIO_1_DEVICE_ID


XGpio Gpio, GpioP;           /* GPIO Device driver instance */


int LEDOutputExample(void)
{


 volatile int Delay;
 int Status;
 int led = LED; /* Hold current LED value. Initialise to LED definition */
 int pmod = PMOD;


  /* GPIO driver initialisation */
  Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID);
  if (Status != XST_SUCCESS) {
   return XST_FAILURE;
  }
  Status = XGpio_Initialize(&GpioP, PMOD_JA1_DEVICE_ID);
   if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }


  /*Set the direction for the LEDs to output. */
  XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0x00);


  /*Set the direction for the LEDs to output. */
    XGpio_SetDataDirection(&GpioP, PMOD_CHANNEL, 0x00);


  /* Loop forever blinking the LED. */
   while (1) {
    /* Write output to the LEDs. */
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, led);


    /* Flip LEDs. */
    led = ~led;


    /* Write output to the LEDs. */
    XGpio_DiscreteWrite(&GpioP, PMOD_CHANNEL, pmod);


    /* Flip LEDs. */
    pmod = ~pmod;


    /* Wait a small amount of time so that the LED blinking is visible. */
    for (Delay = 0; Delay < LED_DELAY; Delay++);
   }


  return XST_SUCCESS; /* Should be unreachable */
}


/* Main function. */
int main(void){


 int Status;


 /* Execute the LED output. */
 Status = LEDOutputExample();
 if (Status != XST_SUCCESS) {
  xil_printf("GPIO output to the LEDs failed!\r\n");
 }


 return 0;
}



  • The following code allows us to push a button from the circuit which makes pin 3 read high and the terminal displays the value 4 (00000100).

/*Pin 3 is connected to a pull-down resistor and a button.  When the button is pressed, the pin reads high and outputs the value 4 to the terminal (gtkterm).  It also turns on an LED. */

/* Include Files */
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "xil_printf.h"
#include "time.h"

/* Definitions */
#define GPIO_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID /* GPIO device that LEDs are connected to */
#define LED 0xFC          /* Initial LED value - XX0000XX */
#define PMOD 0xFC         /* Initial LED value - XX0000XX */
#define LED_DELAY 100000000       /* Software delay length */
#define LED_CHANNEL 1        /* GPIO port for LEDs */
#define PMOD_CHANNEL 1        /* GPIO port for PMODs */
#define printf xil_printf       /* smaller, optimised printf */
#define PMOD_JA1_DEVICE_ID  XPAR_AXI_GPIO_1_DEVICE_ID
#define ABOUT_ONE_SECOND 74067512      //!< approx 1 second delay when used as argument with function delay(numberCyclesToDelay)
// Update this if uBlaze/Zynq CPU core frequency is changed, or if the external memory timing changes.
// Although emprirically tested to 1.0000003 seconds, it is not meant to be used for precise timing purposes

/* Definitions */
#define CLOCK_on 0x08    //high for the clock
#define DATAREADY_high 0x04   //high for data ready pin 3


XGpio Gpio, GpioP;           /* GPIO Device driver instance */





int LEDOutputExample(void)
{


 volatile int Delay;
 int Status;
 int led = LED; /* Hold current LED value. Initialise to LED definition */
 int pmod = PMOD;
 int WritetoLEDs;
 int i;
 u32 x;

  /* GPIO driver initialisation */
  Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID);
  if (Status != XST_SUCCESS) {
   return XST_FAILURE;
  }
  Status = XGpio_Initialize(&GpioP, PMOD_JA1_DEVICE_ID);
   if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }
   delay(ABOUT_ONE_SECOND*5);

  /*Set the direction for the LEDs to output. */
  XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0x00);


  /*Set the direction for the LEDs to output. */
    XGpio_SetDataDirection(&GpioP, PMOD_CHANNEL, 0x04);

    WritetoLEDs =0x01;
    for(i =1;i<8;i++){
        XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, WritetoLEDs);
        delay(ABOUT_ONE_SECOND/2);
        WritetoLEDs=(int)(1<<i);
        XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, WritetoLEDs);
        delay(ABOUT_ONE_SECOND/2);
    }


    printf("Ready to receive.\n \r");
    delay(10);
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);


   while (1) {
       XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);
       delay(10);
       XGpio_DiscreteWrite(&GpioP, PMOD_CHANNEL, 0x00);
    x = XGpio_DiscreteRead(&GpioP,PMOD_CHANNEL);
    delay(10);
        printf("The voltage on pin 3 is %d \n \r",x);
        delay(10);
        while(x==0x04){
            XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x01);
            delay(10);
            XGpio_DiscreteWrite(&GpioP, PMOD_CHANNEL, 0x08);
            delay(10);
            x = XGpio_DiscreteRead(&GpioP,PMOD_CHANNEL);
        }
    /* Wait a small amount of time so that the LED blinking is visible. */
    for (Delay = 0; Delay < LED_DELAY; Delay++);
   }


  return XST_SUCCESS; /* Should be unreachable */
}



void delay(int nStopValue)
/**
* \brief       Loop for nStopValue iterations to provide a delay.
* \par         Details
*              It is commonly used with the constant 'ABOUT_ONE_SECOND' defined in maximPMOD.h for
*              setting approximate delays
*
* \param[in]   nStopValue    - number of iterations to loop
*
* \retval      None
*/
{
    int i=0;
    int a=0;

    for(i=0;i<nStopValue;i++)
    {
        a=i;
    }
}


/* Main function. */
int main(void){


 int Status;


 /* Execute the LED output. */
 Status = LEDOutputExample();
 if (Status != XST_SUCCESS) {
  xil_printf("GPIO output to the LEDs failed!\r\n");
 }


 return 0;
}




  • The following code that allows us to read in a signal from the function generator. (Using the Max11205)
/* Input is on pin 3.  The program reads 8 bits of data sequentially and stores them as an 8 bit value.
The process of storage is shown using the LEDs.  Each bit is shifted to the left.  This is a program to
understand the bit-bang process and how the Maxim Integrated 11205 ADC works.*/

/* Include Files */
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "xil_printf.h"
#include "time.h"

/* Definitions */
#define GPIO_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID /* GPIO device that LEDs are connected to */
#define LED 0xFC          /* Initial LED value - XX0000XX */
#define PMOD 0xFC         /* Initial LED value - XX0000XX */
#define LED_DELAY 100000000       /* Software delay length */
#define LED_CHANNEL 1        /* GPIO port for LEDs */
#define PMOD_CHANNEL 1        /* GPIO port for PMODs */
#define printf xil_printf       /* smaller, optimised printf */
#define PMOD_JA1_DEVICE_ID  XPAR_AXI_GPIO_1_DEVICE_ID
#define ABOUT_ONE_SECOND 74067512      //!< approx 1 second delay when used as argument with function delay(numberCyclesToDelay)
// Update this if uBlaze/Zynq CPU core frequency is changed, or if the external memory timing changes.
// Although emprirically tested to 1.0000003 seconds, it is not meant to be used for precise timing purposes

/* Definitions */
#define CLOCK_on 0x08    //high for the clock
#define DATAREADY_high 0x04   //high for data ready pin 3


XGpio Gpio, GpioP;           /* GPIO Device driver instance */





u32 LEDOutputExample(void)
{


 volatile int Delay;
 int Status;
 int led = LED; /* Hold current LED value. Initialise to LED definition */
 int pmod = PMOD;
 int WritetoLEDs;
 int i;
 u32 x;
 u8 uchPortWriteData=0;
 u8 uchPortReadData=0;
 u32 adcValue=0;


 int nClockCount;
 int uchUseCalibrationMode=0;

  /* GPIO driver initialisation */
  Status = XGpio_Initialize(&Gpio, GPIO_DEVICE_ID);
  if (Status != XST_SUCCESS) {
   return XST_FAILURE;
  }
  Status = XGpio_Initialize(&GpioP, PMOD_JA1_DEVICE_ID);
   if (Status != XST_SUCCESS) {
    return XST_FAILURE;
  }

  /*Set the direction for the LEDs to output. */
  XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0x00);


  /*Set the direction for the PMod - pin 3 is an input, rest are outputs. */
    XGpio_SetDataDirection(&GpioP, PMOD_CHANNEL, 0x04);

    //WritetoLEDs =0x01;
    //for(i =1;i<8;i++){
      //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, WritetoLEDs);
       // delay(ABOUT_ONE_SECOND/3);
       // WritetoLEDs=(int)(1<<i);
   // }


  //  printf("Ready to receive.\n \r");
    //delay(10);
    //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0xFF);

   // XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);

    // First, set the clock and data lines low, and the SS# line high
            // GPIO[3:0] = {SCK, CLR#, MOSI, SS#} // default 'off' is 4'b0101 = 0x05
        //delay(10);
        uchPortWriteData = 0;
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);  // The (1) means write to the only port (#1) on the uBlaze GPIO port
        //delay(10);

        // Wait until RDY# goes high
        //uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        uchPortReadData=0;
        while((uchPortReadData & DATAREADY_high)==0x00)  // keep looping while low
        {
            uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        }

        // Now, wait until RDY# goes low
        uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        while((uchPortReadData & DATAREADY_high)==DATAREADY_high)
        {
            uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        }
 for(i=15;i>=0;i--)
    {
        // Send clock high
        uchPortWriteData |= CLOCK_on;
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);

       // delay(10);  // small delay, then read
        uchPortReadData = XGpio_DiscreteRead(&GpioP,1);
        //delay(10);
        // Shift the GPIO read data to the lowest bit, mask off all the other bits, then shift i (15:0)
        // number of bits to set the appropriate bit in the
        if(((uchPortReadData >> 2) & 0x01)==0x01) // the serial bit is a one, set the bit
        {
            if(i==15)
                adcValue = 0x8000;  // extend the sign of the 2s complement number to bits 31..16, and set bit 15 = 1
            else
                adcValue |= (int)(1 << i);  // bit shift
        }
        uchPortWriteData &= ~CLOCK_on;// Clock in data via negative edge
        XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);
      //  delay(10);
       // XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, adcValue);


        //printf("The Value  %d \n \r", adcValue);

        //storedValues[i]= adcValue;
    }
  
 // The 11205 device requires 25 clocks total to complete a read.
     // We have already sent (16) clocks, so send 9 more clocks.
     // (If self-calibration mode set then we send 10 more clocks.)
     if(uchUseCalibrationMode==1)
         nClockCount = 9;
     else
         nClockCount=9;
     for(i=nClockCount;i>=0;i--)
     {
         // Send clock high
         uchPortWriteData |= CLOCK_on;
         XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);

         //delay(10);  // small delay, then read
         uchPortWriteData &= ~CLOCK_on;// Clock in data via negative edge
         XGpio_DiscreteWrite(&GpioP, 1, uchPortWriteData);
         //delay(10);
     }



      //printf("The ADC Value  %d \n \r", adcValue);

      //XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x01);
     // sleep(1);
     // XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x00);
      //sleep(1);



  return adcValue; /* Should be unreachable */
}



void delay(int nStopValue)
/**
* \brief       Loop for nStopValue iterations to provide a delay.
* \par         Details
*              It is commonly used with the constant 'ABOUT_ONE_SECOND' defined in maximPMOD.h for
*              setting approximate delays
*
* \param[in]   nStopValue    - number of iterations to loop
*
* \retval      None
*/
{
    int i=0;
    int a=0;

    for(i=0;i<nStopValue;i++)
    {
        a=i;
    }
}


/* Main function. */
int main(void){

     u32 storedValues[1000]={};
 int Status;
int j=0;
while(j<1000){
 /* Execute the LED output. */
    storedValues[j] = LEDOutputExample();
    //printf("The J Value  %d \n \r", j );
   // printf("The STORED Values  %d \n \r", storedValues[j]);
    j++;
 }
int k;
printf("The ARRAY Values \n");
  for(k=0; k<1000; k++)
  {

      printf("%d \n \r", storedValues[k]);
  }


 return 0;


(The computer crashed and the final code that we used was not completely saved so some changes may have to be made to this code.)


  • The following MATLAB code is the code that we used to plot the data versus time and the FFT plot
clear all
close all

x = importdata('/home/zynquser/Documents/PMODTESTADC4')



%Even number of values in data file
t=linspace(0,228.5,1000);
X=[t' x];
figure(1)
     xdft = fft(X(:,2));
     % sampling interval -- assuming equal sampling
     DT = X(2,1)-X(1,1);
     % sampling frequency
     Fs = 1/DT;
     DF = Fs/size(X,1);
     freq = 0:DF:Fs/2;
     xdft = xdft(1:length(xdft)/2+1);
     plot(freq,abs(xdft))
figure(2)
plot(t,x,'.')
axis([0 230 0 27000])




%Odd number of values in data file
    

%   xdft = fft(X(:,2));
%      % sampling interval -- assuming equal sampling
%      DT = X(2,1)-X(1,1);
%      % sampling frequency
%      Fs = 1/DT;
%      DF = Fs/size(X,1);
%      freq = 0:DF:Fs/2;
%      xdft = xdft(1:round(length(x)/2));
%      plot(freq,abs(xdft),'.')


USING THE MAXIM11205 CHIP 


The datasheets and user guide for this chip are below.

http://pdfserv.maximintegrated.com/en/an/UG5483.pdf (user guide)
http://datasheets.maximintegrated.com/en/ds/MAX11205.pdf
http://datasheets.maximintegrated.com/en/ds/MAX11205PMB1.pdf



The second page of the second datasheet that is listed has the chart listed below which tells that we will only use pins 3 and 4 when we connect to the Zedboard.


PIN SIGNAL DESCRIPTION
1 N.C. Not connected
2 N.C. Not connected
3 MISO
Data-ready output/serial-data output.
This output serves a dual function.
In addition to the serial-data output
function, the MISO pin also indicates
that the data is ready when it is pulled
logic-low by the IC. Output data
changes on the falling edge of SCLK.
4 SCK
2-wire serial clock. The host must apply
an external clock signal to shift data
out from the IC.
5 GND Ground
6 VCC Power supply






We made the following circuit that will allow us to offset the sine wave so that the wave will go from 0V to 2.8V.




schematic


The connecting this circuit to the max11205 chip and plugging the chip into the pmod on the Zedboard we were able to run the final code listed for SDK.




READING FROM THE TERMINAL - GTKTERM 

 The following link gives a three step process on how to install gtkterm.
http://pkgs.org/centos-6/epel-i386/gtkterm-0.99.5-11.el6.i686.rpm.html


In the first step, this link is provided:
http://dl.fedoraproject.org/pub/epel/6/i386/



Open the previous link and look for:
epel-release-6-8.noarch.rpm
Click on this link and it will download. Then in the downloads folder, or at the bottom of your web browser, click the file to install it.
Then go to the terminal and type the following:
sudo yum install gtkterm
Directions to use gtkterm are in Sven's blog:
http://svenand.blogdrive.com/archive/173.html#.VWh9l9jbJ9A


At the beginning of the blog, it talks about permissions. Following these steps can help with that:
To check for the permissions, open a terminal and type:
          cd ..
          cd ..  (to move all the way out)
          cd dev (must be in this directory)
          ls -l ttyAMC0  (checks the permission)
If the permission is not crw-rw-rw, then type:
          sudo chmod 666 ttyACM0

Then we are able to follow the steps in Sven's blog.





After reading values in the terminal, we were able to save the data by doing file>save and then import that file into Matlab. Using the code listed above, we were able to plot the FFT.

SUCCESS!



NOTE: The following information and graphs are from Joe and we still have to test these ideas.

Change your plot from linear to semilog (and use points instead) :

semilogy(freq,abs(xdft),'.');

This results in a plot that looks like this:

Inline image 1

Sometimes, the plot is a loglog plot and would result in this type of plot:

Inline image 2

In signal processing, the plot is usually done in dB (where dB is 10 log10 P1/P2 for power and 20 log10 V1/V2 for voltage)

This plot has the Y axis as dB (YdB = 10*log10(abs(xdft)/max(abs(xdft(2:end))));  plot(freq(2:end),YdB(2:end),'.')):

Inline image 5

Notice a couple of things in this plot:

1) There is a second peak at around -30dB that is not a harmonic (integer multiple) of the first peak.
2) The noise floor is around -60dB volts (60dB is 10^3 = 1000 which means that the effective resolution of the system is about 2^10 or a 10 bit system)