Jump to content
  • 0

PMOD DA4 on arty a7 35T


Eddie

Question

Hi,

I have a microblaze running on an arty a7 dev board. I have a DA4 connected to JC (i've also connected it to JD and got the same behavior.) I'm using the dpg1/da1 ip, they're identical as far as I can tell. In vitis I'm using the xspi driver that came with the da1/dpg1, again identical. I modified the DA1 Demo a bit to get it to work. There is one problem though: outputs A and C don't work. Quickprint2 is an image of my scope with the yellow line showing output A, Quickprint3 is the yellow line showing B. The blue line is the chip select pin and the purple is the data coming over DIN.

I've verified that there is nothing coming out of the actual chip on output A with a probe as well. I'm pretty sure it's just broken, like maybe I shorted something? Here's my main.c and  DA1 modified driver. I'm just using the DA1 driver to init. Then I just transfer straight to the device. I'm using the Oled rgb as well which is working fine but is commented out below. 

Why aren't the A & C outputs giving me anything with the same code running as the working B,D,E,F,G,H outputs. I am addressing all DACs. I've also tried it with just addressing the individual DACs, same thing, no output on A. B works fine.

 

Thanks for any help!

Ed

 

#include "PmodOLEDrgb.h"
#include "../headers/PmodDA1.h"
#include "sleep.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "../headers/bitmap.h"
#include "xil_types.h"
#include "xspi.h"
#include "xspi_l.h"
#include "xstatus.h"

void DemoInitializeScreen();
void DemoRunScreen();
void DemoCleanupScreen();

void DemoInitializeDa();
void DemoRunDa();
void DemoCleanupDa();

void EnableCaches();
void DisableCaches();

PmodOLEDrgb oledrgb;
PmodDA1 myDevice;

u8 rgbUserFont[] = {
   0x00, 0x04, 0x02, 0x1F, 0x02, 0x04, 0x00, 0x00, // 0x00
   0x0E, 0x1F, 0x15, 0x1F, 0x17, 0x10, 0x1F, 0x0E, // 0x01
   0x00, 0x1F, 0x11, 0x00, 0x00, 0x11, 0x1F, 0x00, // 0x02
   0x00, 0x0A, 0x15, 0x11, 0x0A, 0x04, 0x00, 0x00, // 0x03
   0x07, 0x0C, 0xFA, 0x2F, 0x2F, 0xFA, 0x0C, 0x07  // 0x04
}; // This table defines 5 user characters, although only one is used

int main(void) {
   //DemoInitializeScreen();
   //DemoRunScreen();
   //DemoCleanupScreen();

   DemoInitializeDa();
   DemoRunDa();
   DemoCleanupDa();

   return 0;
}

void DemoInitializeScreen() {
   EnableCaches();
   OLEDrgb_begin(&oledrgb, XPAR_PMODOLEDRGB_0_AXI_LITE_GPIO_BASEADDR,
         XPAR_PMODOLEDRGB_0_AXI_LITE_SPI_BASEADDR);
}

void DemoRunScreen() {
   char ch;

   // Define the user definable characters
   for (ch = 0; ch < 5; ch++) {
      OLEDrgb_DefUserChar(&oledrgb, ch, &rgbUserFont[ch * 8]);
   }

   OLEDrgb_SetCursor(&oledrgb, 2, 1);
   OLEDrgb_PutString(&oledrgb, "Starting Pmod DA1 demo..."); // Default color (green)
   //OLEDrgb_SetCursor(&oledrgb, 4, 4);
   //OLEDrgb_SetFontColor(&oledrgb, OLEDrgb_BuildRGB(0, 0, 255)); // Blue font
   //OLEDrgb_PutString(&oledrgb, "OledRGB");

   //OLEDrgb_SetFontColor(&oledrgb, OLEDrgb_BuildRGB(200, 200, 44));
   //OLEDrgb_SetCursor(&oledrgb, 1, 6);
   //OLEDrgb_PutChar(&oledrgb, 4);

   //OLEDrgb_SetFontColor(&oledrgb, OLEDrgb_BuildRGB(200, 12, 44));
   //OLEDrgb_SetCursor(&oledrgb, 5, 6);
   //OLEDrgb_PutString(&oledrgb, "Demo");
  // OLEDrgb_PutChar(&oledrgb, 0);

   //sleep(5); // Wait 5 seconds

   //OLEDrgb_DrawBitmap(&oledrgb, 0, 0, 95, 63, (u8*) tommy);
}

void DemoCleanupScreen() {
   //DisableCaches();
}

void DemoInitializeDa() {
   EnableCaches();
   DA1_begin(&myDevice, XPAR_PMODDPG1_0_AXI_LITE_SPI_BASEADDR);
}

void DemoRunDa() {

   xil_printf("Starting Pmod DA1 demo...\n\r");
   u8 send[4];
   send[0] = 0b00001000;
   send[1] = 0b00000000;
   send[2] = 0b00000000;
   send[3] = 0b00000001;
   XSpi_Transfer(&myDevice.DA1Spi, send, NULL, 4);
   while (1) {
	   send[0] = 0b00000011;
	   send[1] = 0b11111111;
	   send[2] = 0b11111111;
	   send[3] = 0b00000000;
	   XSpi_Transfer(&myDevice.DA1Spi, send, NULL, 4);

	   send[0] = 0b00000011;
	   send[1] = 0b11110000;
	   send[2] = 0b00000000;
	   send[3] = 0b00000000;
	   XSpi_Transfer(&myDevice.DA1Spi, send, NULL, 4);
      }
}

void DemoCleanupDa() {
   DA1_end(&myDevice);
   DisableCaches();
}

void EnableCaches() {
#ifdef __MICROBLAZE__
#ifdef XPAR_MICROBLAZE_USE_ICACHE
   Xil_ICacheEnable();
#endif
#ifdef XPAR_MICROBLAZE_USE_DCACHE
   Xil_DCacheEnable();
#endif
#endif
}

void DisableCaches() {
#ifdef __MICROBLAZE__
#ifdef XPAR_MICROBLAZE_USE_DCACHE
   Xil_DCacheDisable();
#endif
#ifdef XPAR_MICROBLAZE_USE_ICACHE
   Xil_ICacheDisable();
#endif
#endif
}
/******************************************************************************/
/*                                                                            */
/* PmodDA1.c -- Definitions for the PmodDA1 library                           */
/*                                                                            */
/******************************************************************************/
/* Author: Jon Peyron                                                         */
/* Copyright 2017, Digilent Inc.                                              */
/******************************************************************************/
/* File Description:                                                          */
/*                                                                            */
/* This file defines the DA1 library functions to initialize and use the IP   */
/* core.                                                                      */
/*                                                                            */
/******************************************************************************/
/* Revision History:                                                          */
/*                                                                            */
/*    06/20/2016(JonP):     Created                                           */
/*    04/28/2017(ArtVVB):   Validated                                         */
/*    02/13/2018(atangzwj): Validated for Vivado 2017.4                       */
/*                                                                            */
/******************************************************************************/

/***************************** Include Files *******************************/

#include "../headers/PmodDA1.h"

/************************** Function Definitions ***************************/
XSpi_Config DA1Config =
{
   0,
   0,
   1,
   0,
   1,
   8,
   0,
   0,
   0,
   0,
   0
};

/* ------------------------------------------------------------ */
/*** void DA1_begin(PmodDA1 *InstancePtr, u32 SPI_Address)
**
**   Parameters:
**      InstancePtr: A PmodDA1 object to start
**      SPI_Address: The Base address of the PmodDA1 SPI
**
**   Return Value:
**      None
**
**   Errors:
**      None
**
**   Description:
**      Initialize the PmodDA1.
*/
void DA1_begin(PmodDA1 *InstancePtr, u32 SPI_Address) {
   DA1Config.BaseAddress = SPI_Address;
   DA1_SPIInit(&InstancePtr->DA1Spi);

}

/* ------------------------------------------------------------ */
/*** void DA1_end(PmodDA1 *InstancePtr)
**
**   Parameters:
**      InstancePtr - PmodDA1 object to stop
**
**   Return Value:
**      None
**
**   Errors:
**      None
**
**   Description:
**      Stops the device
*/
void DA1_end(PmodDA1 *InstancePtr) {
   XSpi_Stop(&InstancePtr->DA1Spi);
}

/* ------------------------------------------------------------ */
/*** DA1_SPIInit
**
**   Parameters:
**      None
**
**   Return Value:
**      None
**
**   Errors:
**      None
**
**   Description:
**      Initializes the PmodDA1 SPI.
*/
int DA1_SPIInit(XSpi *SpiInstancePtr) {
   int Status = 1;

   Status = XSpi_CfgInitialize(SpiInstancePtr, &DA1Config,
         DA1Config.BaseAddress);
   if (Status != XST_SUCCESS) {
      return XST_FAILURE;
   }

   u32 options = (XSP_MASTER_OPTION | XSP_CLK_ACTIVE_LOW_OPTION);// | XSP_MANUAL_SSELECT_OPTION;
   Status = XSpi_SetOptions(SpiInstancePtr, options);
   if (Status != XST_SUCCESS) {
      return XST_FAILURE;
   }

   Status = XSpi_SetSlaveSelect(SpiInstancePtr, 1);
   if (Status != XST_SUCCESS) {
      return XST_FAILURE;
   }

   /*
    * Start the SPI driver so that the device is enabled.
    */
   XSpi_Start(SpiInstancePtr);

   /*
    * Disable Global interrupt to use polled mode operation
    */
   XSpi_IntrGlobalDisable(SpiInstancePtr);

   return XST_SUCCESS;
}

/* ------------------------------------------------------------ */
/*** u8 DA1_WriteIntegerValue(PmodDA1 *InstancePtr, u8 bIntegerValue)
**
**   Synopsis:
**      WriteIntegerValue(0x00FF);
**
**   Parameters:
**      InstancePtr - A PmodDA1 object to start
**      bIntegerValue - the 8-bit value to be written to DA converter
**
**   Return Value:
**      u8 - DA1_SPI_ERR_SUCCESS (0)          - Action completed successfully
**         - DA1_SPI_ERR_VAL_OUT_OF_RANGE (1) - Value is not within the
**                                              0x00 - 0xFF range
**   Errors:
**      If module is not initialized (using begin), the function does nothing.
**      Also, see return value.
**
**   Description:
**      If the value is inside the allowed range (0 - 0xFF), this function
**      writes the 12 bits value to the DA converter, by writing 16 bits to SPI
**      and returns the DACSPI1_ERR_SUCCESS status message. If the value is
**      outside the allowed range, the function does nothing and returns the
**      DACSPI1_ERR_VAL_OUT_OF_RANGE message.
**
*/
u8 DA1_WriteIntegerValue(PmodDA1 *InstancePtr, u16 bIntegerValue) {
   u8 send[4];
   u8 bResult = 0;
   u16 dataMaskFirstNib = 0x0F00;
   u16 dataMaskLastByte = 0x00FF;

   send[0] = DA1_SPI_CMD;
   send[1] = DA1_SPI_ADDR << 4 | (bIntegerValue & dataMaskFirstNib) >> 8;
   send[2] = bIntegerValue & dataMaskLastByte;
   send[3] = 0;

   if (bIntegerValue < 0 || bIntegerValue >= (1 << DA1_SPI_NO_BITS)) {
      bResult = DA1_SPI_ERR_VAL_OUT_OF_RANGE;
   } else {
      XSpi_Transfer(&InstancePtr->DA1Spi, send, NULL, 4);
   }
   return bResult;
}

/* ------------------------------------------------------------ */
/*** u8 DA1_WritePhysicalValue(PmodDA1 *InstancePtr, float dPhysicalValue)
**
**   Parameters:
**      InstancePtr    - A PmodDA1 object to start
**      dPhysicalValue - The physical value that must be reconstructed at the
**                       output of the DA converter
**
**   Return Values:
**      u8 - DA1_SPI_ERR_SUCCESS (0)          - Action completed successfully
**         - DA1_SPI_ERR_VAL_OUT_OF_RANGE (1) - The physical value is not inside
**                                              accepted range
**
**   Errors:
**      If module is not initialized (using begin), the function does nothing.
**      Also, see return value.
**
**   Description:
**      The function computes the integer value corresponding to the physical
**      value by considering the reference value as the one corresponding to the
**      maximum integer value (0xFF). If the integer value is within the
**      accepted range (0 - 0xFF), this function writes the 12- bit value to the
**      DA converter, by writing 8 bits to SPI, and returns the
**      DACSPI1_ERR_SUCCESS message. If the integer value is outside the allowed
**      range, the function does nothing and returns the
**      DACSPI1_ERR_VAL_OUT_OF_RANGE message. If the dReference function
**      argument is missing, 3.3 value is used as reference value.
**
*/
u8 DA1_WritePhysicalValue(PmodDA1 *InstancePtr, float dPhysicalValue) {
   u8 status;
   float dReference = 3.3; // The value corresponding to the maximum converter
                           // value (reference voltage). If this parameter is
                           // not provided, it has a default value of 3.3.

   u16 wIntegerValue = dPhysicalValue * (float) (1 << DA1_SPI_NO_BITS)
         / dReference;
   status = DA1_WriteIntegerValue(InstancePtr, wIntegerValue);
   return status;
}

 

DS1Z_QuickPrint2.png

DS1Z_QuickPrint3.png

Link to comment
Share on other sites

2 answers to this question

Recommended Posts

Hi @Eddie,

A couple of us looked into your code and while the data commands you are sending are correct, I think what is happening is that your SPI initialization isn't quite correct for the Pmod DA4.

This is the set of parameters that we used and confirmed worked for all channels for the XSpi_SetOptions function (which you should be changing from the BSP file if you were not already:

XSpi_SetOptions(SpiInstancePtr, (XSP_MASTER_OPTION | XSP_CLK_PHASE_1_OPTION) | XSP_MANUAL_SSELECT_OPTION); //clock idles low, data is valid on second clock edge (in this case, a falling edge), only manipulate chip select at start and end of transfer

so namely, you will need to remove the XSP_CLK_ACTIVE_LOW_OPTION (so the clock idles low) for it to work correctly.

Let me know if you have any questions.

Thanks,
JColvin

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...