/** * @file ADS5560.cpp * @author James Thesing * @version 1.0 * * @section LICENSE * * * o 0 * | / Copyright (c) 2005-2011 * (CL)---o Critical Link, LLC * \ * O * * * @section DESCRIPTION * * This class handles exercising the ADS5560 on the DSP. Input data is * acquired through an analog source, and capture data is sent back * to the ARM. */ #include "ADS5560.h" #include "core/DspUpp.h" #include "core/DspSyscfg.h" #include "core/chipconfig.h" #include "core/cl_ipc_inbound.h" #include "core/cl_ipc_outbound.h" #include #include #include #include #include #include #include using namespace std; using namespace MityDSP; const int BUFF_SIZE = 32000; //size of buffers used in upp link const int SAMPLE_SIZE = 200000; //amount of data to collect //set up buffers #pragma DATA_ALIGN( 64 ); int16_t buff1[ BUFF_SIZE ]; int16_t buff2[ BUFF_SIZE ]; int16_t buff3[ BUFF_SIZE ]; // Forward declarations string convertInt(int number); void init(); void debugPrint( char *buffer ); int handleInboundMessage( void *apBuffer, uint32_t anLength, void *apUserArg ) ; // Object for sending debug messages (these are received and printed to stdout by tcDspApp) tcCL_IPCOutbound* gpDebug; // Object for sending GPPMSGQ1 messages that the ARM will receive tcCL_IPCOutbound* gpOutbound; // Object for receiving DSPMSGQ0 messages that the DSP will receive tcCL_IPCInbound* gpInbound; // Initialize static member variables ADS5560* ADS5560::mpUppSignal = NULL; // uPP configuration record static const tcDspUpp::tsDspUppConfig gsUppConfig = { 4, // Interrupt level. Must be between 4 and 15. 9, // Chan A DMA thread handling priority 9, // Chan B DMA thread handling priority tcDspUpp::eeTransmit, // Directionality of Channel A. tcDspUpp::eeReceive, // Directionality of Channel B. tcDspUpp::ee16Bit, // Chan A data bit width. tcDspUpp::ee16Bit, // Chan B data bit width. false, // Use XData[7:0] for ChanA[15:8] even if ChanB is // disabled. See Table 3 in uPP User's Guide for details. 4, // Size of MBX for Channel A. 4, // Size of MBX for Channel B. 1, // Clock divider for Channel A (37.5 MHz output clock) // (only in transmit mode). See Section 2.1.1 in uPP User's // Guide for details. Value must be between 1 and 16. 0, // Clock divider for Channel B // (only in transmit mode). See Section 2.1.1 in uPP User's // Guide for details. Value must be between 1 and 16. tcDspUpp::ee256Bytes, // Chan A Transmit Thresh tcDspUpp::ee256Bytes, // Chan A Receive Thresh tcDspUpp::ee256Bytes, // Chan B Transmit Thresh tcDspUpp::ee256Bytes, // Chan B Receive Thresh false, // Do not use Chan A start signal false, // Do not use Chan B start signal //tcDspUpp::eeUPP_2xTXCLK, // Using external 2xTxClk for Transmit tcDspUpp::eePLL0_SYSCLK2, 0 // uPP DMA Master Priority }; /** * Private Constructor - initializes the digital output logic */ ADS5560::ADS5560() : mpDspUpp(NULL) , meXmitChan(tcDspUpp::eeChanA) , mhXmitMbx(NULL) , meRecvChan(tcDspUpp::eeChanB) , mhRecvMbx(NULL) , filled(false) { char debug2[] = "getting instance of DSPuPP\n"; char debug3[] = "configuring UPP\n"; char debug4[] = "upp configured\n"; // Get instance of DspUpp debugPrint(debug2); mpDspUpp = tcDspUpp::getInstance(); // Configure uPP debugPrint(debug3); if (0 != mpDspUpp->initialize(&gsUppConfig)) { char debug1[] = "failed configuring upp"; debugPrint(debug1); } else { debugPrint(debug4); // Get the receive and transmit mailboxes mhXmitMbx = mpDspUpp->getMBX(meXmitChan); mhRecvMbx = mpDspUpp->getMBX(meRecvChan); } //while(lbWaitForMe == true){}; } /** * Initializes the DSP link and registers message handler */ void init() { // Message to ARM core. char lpReturnMessage[] = "DSP Initialization finished."; // Buffer for return message char* lpMessageBuffer = NULL; // Create the outbound debug link gpDebug = new tcCL_IPCOutbound("debug"); // Create the inbound link for messages to the DSP gpInbound = new tcCL_IPCInbound(); gpInbound->Open("DSPMSGQ0", 8); // Create the outbound controller for sending messages to the ARM gpOutbound = new tcCL_IPCOutbound("GPPMSGQ1"); if (NULL != gpInbound) { // Register a callback function to handle messages from the ARM gpInbound->RegisterCallback(handleInboundMessage, (void*)NULL); } // Now that initialization is complete, let the ARM know with a message // Obtain a dsplink buffer for the return message lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(lpReturnMessage) + 1); // Make sure we received a valid buffer if (NULL != lpMessageBuffer) { // Copy our message to the buffer strcpy(lpMessageBuffer, lpReturnMessage); // Send the message back to the ARM gpOutbound->SendMessage(lpMessageBuffer); } } /** * Gets data from the upp interface * @param SAMPLE_SIZE amount of samples to collect */ void ADS5560::getData( int SAMPLE_SIZE ){ char debug1[] = "failed to send received buffer to upp\n"; char debug7[] = "failed to send data\n "; int dataR = 0; //keep track of amount of data collected bool finished = false; //do not calculate if already done //get a receive mailbox tcDspUpp::tsMbxMsg lsRecvMbxMsg; int16_t* lpMessageBuffer = NULL; //turn on ADC by writing to register 0x66000202 unsigned short *ptr = ( unsigned short* )0x66000202; *ptr = 1; //send buffers to upp to fill if (0 != mpDspUpp->receive(meRecvChan, (uint8_t*)buff1, (uint16_t)(BUFF_SIZE * 2) ) ) { debugPrint(debug1); } if (0 != mpDspUpp->receive(meRecvChan, (uint8_t*)buff2, (uint16_t)(BUFF_SIZE * 2) ) ) { debugPrint(debug1); } if (0 != mpDspUpp->receive(meRecvChan, (uint8_t*)buff3, (uint16_t)(BUFF_SIZE * 2) ) ) { debugPrint(debug1); } // Wait for receive to finish, send data to ARM and give // upp buffer back while( !finished ) { MBX_pend(mhRecvMbx, &lsRecvMbxMsg, SYS_FOREVER); //get finished buffer lpMessageBuffer = (int16_t*)gpOutbound->GetBuffer(sizeof(int16_t)*BUFF_SIZE); if (NULL != lpMessageBuffer) { // Copy uppData to the send buffer memmove(lpMessageBuffer, lsRecvMbxMsg.pBufPtr ,sizeof(int16_t)*BUFF_SIZE ); // Send the message back to the ARM gpOutbound->SendMessage(lpMessageBuffer); //send buffer to upp to fill if (0 != mpDspUpp->receive(meRecvChan, (uint8_t*)lsRecvMbxMsg.pBufPtr, (uint16_t)(BUFF_SIZE * 2) ) ) { debugPrint(debug1); } //check to see if enough samples have been collected if (dataR < (SAMPLE_SIZE - BUFF_SIZE)) { dataR += BUFF_SIZE; } else { //loop break when enough data collected finished = true; } } else { debugPrint(debug7); } } //turn off ADC by writing to register 0x66000202 *ptr = 0; } /** * Return instance of object or create one to enforce * singleton use */ ADS5560* ADS5560::getInstance() { if (NULL == mpUppSignal) mpUppSignal = new ADS5560(); return mpUppSignal; } /** * Destructor */ ADS5560::~ADS5560() { } /** * Main routine for DSPAPP */ int main(int argc, char* argv[]) { // initialize the DSPLink system tcCL_IPCInit::GetInstance(); // Launch an initialization task TSK_Attrs* lpAttrs = new TSK_Attrs; *lpAttrs = TSK_ATTRS; lpAttrs->name = "Initialize"; lpAttrs->stacksize = 8192*2; lpAttrs->priority = 5; TSK_create((Fxn)init,lpAttrs); return 0; } /** * handles messages received from the arm * @param apBuffer buffer location of message * @param anLength length of buffer used * @param apUserArg user given arguments * @return 0; */ int handleInboundMessage(void* apBuffer, uint32_t anLength, void* apUserArg) { char debug1[] = "Failure to communicate with arm\n"; char returnMsg[] = "DSP App finished\n"; char* lpMessageBuffer = NULL; lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(returnMsg) + 1); if (NULL != lpMessageBuffer) { // Copy message to the buffer strcpy(lpMessageBuffer, returnMsg); } else { debugPrint( debug1 ); } ADS5560* mhUppSignal = ADS5560::getInstance(); mhUppSignal->getData( SAMPLE_SIZE ); gpOutbound->SendMessage( lpMessageBuffer ); return 0; } /** * prints a character array through a debug IPC object * output is: "[DSP] " * @param pMsg - character array of message to print */ void debugPrint(char* pMsg) { // The length of the message to be sent int len = strlen(pMsg); // Pointer to dsplink buffer where to write the message char* pBuffer; // Make sure the debug IPC outbound object has been initialized if (gpDebug == NULL) return; // Get a buffer for the message pBuffer = (char *)gpDebug->GetBuffer(len+1); // Check that the buffer is valid if (pBuffer) { // Copy the message to the buffer strcpy(pBuffer, pMsg); // Send the message gpDebug->SendMessage(pBuffer); } }