/** * \file main.cpp * * \brief DSP side main routine for DSP Hello World application. * The DSP simply sets itself up, and then waits for a * message from the ARM, to which it replies. * * o 0 * | / Copyright (c) 2005-2010 * (CL)---o Critical Link, LLC * \ * O */ #include #include #include #include #include #include "core/cl_ipc_inbound.h" #include "core/cl_ipc_outbound.h" enum MsgCommand { eReadFromARM, eWriteToARM, eReadFromDSP, eWriteToDSP }; enum MsgTypes { eGlobalFixture, eLibrary, eGlobalUser, eGlobalSerialPort, eGlobalScannerJog, eFeature, eFeatureData, eFeatureDataSource, eFeatureExpressions, eFeatureFixture, eFeatureMeasurement, eFeatureSegmentList, eGlobalDigitalInputs, eGlobalDigitalOutputs, eGlobalFactory, eDebugText }; typedef struct { MsgTypes type; MsgCommand command; } Header; typedef struct { Header header; char textMessage[100]; // 100 bytes for now } DebugText; typedef struct { Header header; char fixtureName[33]; int fixtureID; int fixtureTencoderpe; int fixtureURR; int fixtureHomeMethod; int fixtureZeroMethod; int fixtureMotion; int fixtureDirection; int fixtureOrientation; double fixtureLinearTravel; double fixtureRotaryTravel; int motorPresent; int motorPort; int motorRotation; double motorGearRatioIn; double motorGearRationOut; int motorType; int motorMaxSpeed; int motorStepsPerRevolution; char motorAcceleration[16]; // todo int encoderPresent; int encoderPort; int encoderRotation; double encoderGearRatioIn; double encoderGearRationOut; int encoderResolution; int encoderIndexPresent; int encoderIndexInput; int encoderIndexIsHome; int encoderIndexIsEndOfTravel; int encoderQuadratureMode; int homeSensorPresent; int homeSensorInput; int homeSensorType; int homeSensorDirection; int endOfTravelSensorPresent; int endOfTravelSensorInput; int endOfTravelSensorType; int endOfTravelSensorDirection; char inputMapping[5]; // todo char outputMapping[8]; // todo double pulleyDiam; int pulleyUnits; } GlobalFixture_str ; typedef struct { Header header; int SerialNumber; double AnalogCalMinValue; double AnalogCalMaxValue; double AnalogCalGain; double AnalogOffset; int LowPowerScannerType; int LowPowerValue; int CalibrationUnits; double CalibrationSmallPart; double CalibrationLargePart; double CalibrationmValue; double CalibrationbValue; char CalibrationDate[20]; } GlobalFactory_str ; typedef struct { Header header; int DigInputID; int ActivationType; int FunctionID; } GlobalDigitalInputs_str ; typedef struct { Header header; int DigOutputID; int Polarity; int Latched; int ServerID; } GlobalDigitalOutputs_str ; typedef struct { Header header; int SerialPortID; int BaudRate; int ParityBits; int DataBits; int StopBits; int FlowControl; int ProtocolFlag; int DataFlag; } GlobalSerialPort_str ; typedef struct { Header header; int FeatureID; int LibraryToFeatureKey; char Name[16]; int AdvanceMode; int AdvanceDelay; double SizeOffset; double PositionOffset; int URRUnits; int URRResolution; int URRRounding; int DataSourceExpressionType; int DataSource_op; int Sequence; double ToleranceRejectPlus; double ToleranceRejectMinus; double ToleranceWarningPlus; double ToleranceWarningMinus; double ToleranceNominal; bool ToleranceRejectEnablePlus; bool ToleranceRejectEnableMinus; bool ToleranceWarningEnablePlus; bool ToleranceWarningEnableMinus; int UseFixtureToCollectData; int UseFixtureForAutoPositioning; double UserSingleMasterSize; } Feature_str ; typedef struct { Header header; int FeatureToDataKey; int LibraryToDataKey; char Label[16]; int DisplayLine; int SerialPortSelected; int UseAsLimits; } FeatureData_str ; typedef struct { Header header; int FeatureToDataKey; int LibraryToDataKey; int TermType; double TermConstanst; int TermFeatureID; int TermID; } FeatureDataSource_str ; typedef struct { Header header; int FeatureToDataKey; int LibraryToDataKey; int Segment ; } FeatureSegmentList_str ; typedef struct { Header header; int FeatureToDataKey; int LibraryToDataKey; int Type; int EdgeCount; int GlassMode; int InternalRefFlag; int LowerRefFlag; int UpperRefFlag; int PartSegmentIndex; int PartModeFlag; int SamplingMode; int AveragingMode; int AveragingPeriod; int GoodScans; int EnterDelayMode; int EnterDelayPeriod; char FormatString[34]; int PolledFlag; } FeatureMeasurement_str ; typedef struct { Header header; int FeatureToDataKey; int LibraryToDataKey; int LineOrder; char ExpressionText[50]; } FeatureExpressions_str ; typedef struct { Header header; int FeatureToDataKey; int LibraryToDataKey; int FixtureID; int DisableMotorAfterMove; int IDODWALLComputeWall; int MeasurementMode; int UsageMode; int AutomaticShankDiamFlag; double Speed; int StepMode; int ReturnPosition; int NumberOfMeasurementPositions; double TotalDistance; double StartPosition; double ShankDiameter; } FeatureFixture_str ; typedef struct { Header header; int ScannerJogID; double mOffset; double bOffset; double LowSize; double HighSize; } GlobalScannerJog_str ; typedef struct { Header header; char LanguageName[20]; char LanguagePrefix[5]; char Password[8]; int PowerUpLocked; int AllowNominalChanges; int AllowRemastering; int AllowLibraryChanges; int AdvancedScreenOperation; int AutoScrollEnable; int AudibleAlarm; int FlipScreen180; int ScannerDoubleDiff; int LatchScanErrors; int IgnoreScanErrors; char IPAddress[20]; int ButtonsDefined; int ButtonID_1; int ButtonID_2; int ButtonID_3; } GlobalUser_str ; typedef struct { Header header; int LibraryID; char LibraryName[16]; double UserDualPointMasterSize1; double UserDualPointMasterSize2; double AlarmDuration; int AlarmEnable; int SQCBatchSize; int SQCBatchClearAtEndOfBatch; int SQCBatchPrintAtEndOfBatch; int FeatureCount; int SerialDOFAutoSendFlag; int SerialDOFAutoSendDelay; int SerialDOFDateTimeFlag; int SerialDOFLabelFlag; int SerialDOFHeaderType; int SerialDOFRequestorType; char SerialDOFRequestorString[5]; int SerialDOFSeparatorType; char SerialDOFSeparatorString[5]; int SerialDOFTerminatorType; char SerialDOFTerminatorString[5]; int SerialDOFDecimalFlag; int SerialDOFSignFlag; double LegacySlideCounterPerInch; int ReportSelected1; int ReportSelected2; int ReportSelected3; int ReportSelected4; char ReportUserTitle[33]; int ReportPrinterPort; int ReportDisableHeaderAndFooter; int ReportDisableFormFeed; int URRUnits; int URRResolution; int URRRounding; } Library_str ; typedef union { Header header; DebugText debugMsg; Library_str library; GlobalFixture_str globalFixture; GlobalUser_str globalUser; GlobalScannerJog_str globalScannerJog; FeatureFixture_str featureFixture; FeatureExpressions_str featureExpressions; FeatureMeasurement_str featureMeasurement; FeatureSegmentList_str featureSegmentList; FeatureDataSource_str featureDataSource; FeatureData_str featureData; Feature_str feature; GlobalFactory_str globalFactory; GlobalDigitalInputs_str globalDigitalInputs; GlobalDigitalOutputs_str globalDigitalOutputs; GlobalSerialPort_str globalSerialPort; } allTypes; allTypes messageA2D; // message data between DSP and ARM using namespace MityDSP; // Forward declarations void init(); void debugPrint(char *buffer); int handleInboundMessage(void *apBuffer, uint32_t anLength, void *apUserArg) ; int handleInboundMessageBM(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; // semaphore for waiting on messages SEM_Handle msgRecvd; #include "core/DspSerial.h" #include "core/DspFpgaSerial.h" #define RS232_SERIAL_BASE 0x66000080 /* ********************* void trySerialPort() { int bytes, rv; unsigned int my_base_addr = RS232_SERIAL_BASE; // was 0xE000001C; unsigned int my_vector = 6; char input[32], output[32]; tcDspFpgaSerial *my_port; // create a serial interface my_port = new tcDspFpgaSerial((void *)my_base_addr, my_vector, 38400, 8, 1, tcDspFpgaSerial::gnUART_NOPARITY); // start using the port my_port->enable(true); // send something... sprintf(output, "Testing..1..2..3.."); bytes = strlen(output); rv = my_port->put((void *)output, bytes); if (rv != bytes) { printf("Failed, only sent %1d of %1d bytes\n", rv, bytes); } // receive something... bytes = sizeof(input); rv = my_port->get((void *)input, bytes); printf("Received %1d bytes of data\n", rv); } ****************** */ extern "C" { typedef unsigned int u_8 ; MityDSP::tcDspFpgaSerial *Com1; MityDSP::tcDspSerial *Com2; bool Com1_initialized=false; bool Com2_initialized=false; typedef struct serialPort_str { MityDSP::tcSerial *Com; bool initialized; void (*rx_func)(u_8 c, u_8 stat); } serialPort; void (*rx_func1)(u_8 c, u_8 stat) = NULL; void (*rx_func2)(u_8 c, u_8 stat) = NULL; extern "C" int StartMonitorTask1(void); extern "C" int StartMonitorTask2(void); } serialPort spCom[2]; char gBuffer[200]; #define Sec2tick(x) (1000*x) #define GGE_PRIO 9 void ser1_task() { int count=0; int idx=0; static char buf[64]; while (!Com1_initialized) TSK_sleep(Sec2tick(1)); while (1) { //if (count == 0) { count = strlen(gBuffer); //sprintf(buf,"%s %d\n", gBuffer, idx++); int j=0, k=0; for (int i=0; i < count; i++){ if ((int)gBuffer[i] < 32) { k=sprintf(&buf[j], "*%2x!", (unsigned char)gBuffer[i]); j = j+k; } else { buf[j] = gBuffer[i]; j++; } } buf[j]=0; count = j; //} Com1->put(buf, count, 0, 0); TSK_sleep(1250); /*count = Com1->get(buf, 60, 1000); if (count && Com1_initialized && (rx_func1 != NULL)) { idx = 0; while(idx < count) rx_func1(buf[idx++],0); } else { TSK_sleep(5); }*/ } } extern "C" int StartMonitorTask1(void) { TSK_Handle task; TSK_Attrs attrs; attrs = TSK_ATTRS; attrs.priority = GGE_PRIO; attrs.name = "ser1_task"; task = TSK_create((Fxn)ser1_task, &attrs); if(task) return 1; else return 0; } void ser2_task() { int count; int idx=0; static int flipper; static char buf[64]; char workingBuffer[100]; // just some junk while (!Com2_initialized) TSK_sleep(Sec2tick(1)); while (1) { /*count = sprintf(buf, "hello world #2 %d\n", idx++); Com2->put(buf, count, 0, 0); TSK_sleep(1250);*/ /**/ count = Com2->get(buf, 64, 500); if (count && Com2_initialized && Com1_initialized ) { // copy the data to a global buffer and... sprintf(gBuffer, "%s", buf); unsigned char command = gBuffer[0]; if (command == 208 && gBuffer[1] == '0' && gBuffer[2] == '2') { // was a byte request..for 02 // send back some sort of string flipper++; count = sprintf(workingBuffer, "%c02%02d",0xe0, flipper); if (flipper > 5) flipper = 0; sprintf(gBuffer, "%s!!!!", workingBuffer); Com2->put(workingBuffer,count,0,0); } else { command = command + 0x10; count = sprintf(workingBuffer, "%c%c%c%02d",command, gBuffer[1], gBuffer[2], flipper); Com2->put(workingBuffer,count,0,0); } //} else { gBuffer[count] = NULL; } else if (count == 0) { sprintf(gBuffer, "empty string %d ", idx++); } if (count && Com2_initialized && (rx_func2 != NULL)) { idx = 0; while(idx < count) rx_func2(buf[idx++],0); } else { TSK_sleep(5); } /* */ } } extern "C" int StartMonitorTask2(void) { TSK_Handle task; TSK_Attrs attrs; attrs = TSK_ATTRS; attrs.priority = GGE_PRIO; attrs.name = "ser1_task"; task = TSK_create((Fxn)ser2_task, &attrs); if(task) return 1; else return 0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This routine actually creates the comm port. It is not to be called // directly by users. /////////////////////////////////////////////////////////////////////////////// extern "C" void InitSerPort(serialPort *xPort, int style, int baud, u_8 dbits, u_8 parity, u_8 sbits, u_8 hnd_shk, void (*rx_func)(u_8 c, u_8 stat)) { // PORT tmp; MityDSP::tcDspSerial::tsConfig Cfg; int DBitsCfg,SbitsCfg,PrtyCfg; DBitsCfg = dbits; switch(parity) { case 'e': case 'E': PrtyCfg = MityDSP::tcDspFpgaSerial::gnUART_EVENPARITY; Cfg.parity = MityDSP::tcDspSerial::tsConfig::even; break; case 'o': case 'O': PrtyCfg = MityDSP::tcDspFpgaSerial::gnUART_ODDPARITY; Cfg.parity = MityDSP::tcDspSerial::tsConfig::odd; break; case 'n': case 'N': PrtyCfg = MityDSP::tcDspFpgaSerial::gnUART_NOPARITY; Cfg.parity = MityDSP::tcDspSerial::tsConfig::none; break; } SbitsCfg = sbits; if(style == 1) { xPort->Com = new MityDSP::tcDspFpgaSerial((void *)RS232_SERIAL_BASE, baud, DBitsCfg, SbitsCfg, PrtyCfg, false); xPort->rx_func = rx_func; } else { xPort->Com = MityDSP::tcDspSerial::GetInstance(MityDSP::tcDspSerial::UART0); Cfg.baud = baud; Cfg.databits = DBitsCfg; Cfg.stopbits = SbitsCfg; Cfg.hw_flowcontrol = false; Com2->configure(&Cfg); xPort->rx_func = rx_func; StartMonitorTask2(); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This is the main initialization call to create the comm ports. It should // be called before interrupts are enabled /////////////////////////////////////////////////////////////////////////////// extern "C" void InitSerPortX(serialPort *xPort, int style, int baud) { xPort->Com = 0; xPort->initialized = false; InitSerPort(xPort, style, baud, 8, 'n', 1, 0, 0); xPort->initialized = true; } extern "C" void InitSerPortndc(u_8 port, u_8 io, int baud, u_8 dbits, u_8 parity, u_8 sbits, u_8 hnd_shk, void (*rx_func)(u_8 c, u_8 stat)) { // PORT tmp; MityDSP::tcDspSerial::tsConfig Cfg; int DBitsCfg,SbitsCfg,PrtyCfg; DBitsCfg = dbits; switch(parity) { case 'e': case 'E': PrtyCfg = MityDSP::tcDspFpgaSerial::gnUART_EVENPARITY; Cfg.parity = MityDSP::tcDspSerial::tsConfig::even; break; case 'o': case 'O': PrtyCfg = MityDSP::tcDspFpgaSerial::gnUART_ODDPARITY; Cfg.parity = MityDSP::tcDspSerial::tsConfig::odd; break; case 'n': case 'N': PrtyCfg = MityDSP::tcDspFpgaSerial::gnUART_NOPARITY; Cfg.parity = MityDSP::tcDspSerial::tsConfig::none; break; } SbitsCfg = sbits; if(port == 1) { Com1 = new MityDSP::tcDspFpgaSerial((void *)RS232_SERIAL_BASE, baud, DBitsCfg, SbitsCfg, PrtyCfg, false); rx_func1 = rx_func; StartMonitorTask1(); } else { Com2 = MityDSP::tcDspSerial::GetInstance(MityDSP::tcDspSerial::UART0); Cfg.baud = baud; Cfg.databits = DBitsCfg; Cfg.stopbits = SbitsCfg; Cfg.hw_flowcontrol = false; Com2->configure(&Cfg); rx_func2 = rx_func; StartMonitorTask2(); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This is the main initialization call to create the comm ports. It should // be called before interrupts are enabled /////////////////////////////////////////////////////////////////////////////// extern "C" void InitSerPorts(int baud1, int baud2) { Com1 = 0; Com2 = 0; Com1_initialized = false; Com2_initialized = false; InitSerPortndc(1, 0, baud1, 8, 'n', 1, 0, 0); InitSerPortndc(2, 0, baud2, 8, 'n', 1, 0, 0); Com1_initialized = true; Com2_initialized = true; } /** * Main routine. */ int main(int argc, char* argv[]) { int bWaitForMe = argc; int iCounter = 0; int iCounter2 = 0; while (bWaitForMe) { iCounter++; // wait for the debugger here.... if (iCounter > 10000) { iCounter2++; iCounter = 0; } } // initialize the DSPLink system tcCL_IPCInit::GetInstance(); msgRecvd = SEM_create(0, NULL); // 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); // according to loc_init.c:loc_init it appears the first port is the 232 and the second one is the 422 // InitSerPorts(baud232, baud422); // This will create a task for each serial port. /* * InitSerPortX(&spCom[0], 1, 38400); //. TBD use enum for style of serial port either FPGA or plain DSP StartMonitorTask1(); InitSerPortX(&spCom[1], 2, 38400); StartMonitorTask2();*/ // we're done exit and leave the tasks going... return 0; } /** * Initialize the inbound and outbound IPC objects. * * \return None. */ 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(handleInboundMessageBM, (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(sizeof(messageA2D) + 1); // Make sure we received a valid buffer if (NULL != lpMessageBuffer) { // create a debug message for the first one... sprintf(messageA2D.debugMsg.textMessage, "%s", lpReturnMessage); messageA2D.debugMsg.header.type = eDebugText; // Copy our message to the buffer memcpy(lpMessageBuffer, &messageA2D, sizeof(messageA2D)); // Send first message to the ARM gpOutbound->SendMessage(lpMessageBuffer); } // now wait on msgs from the ARM bool keepGoing=true; while (keepGoing) { SEM_pend(msgRecvd, SYS_FOREVER); // msg rcv'd... now what... } } /** * Callback function that handles messages from the ARM. * * \param apBuffer Pointer to message buffer. * \param anLength Length of message. * \param apUserArg Pointer to user defined argument * * \return 0 on sucess. */ int handleInboundMessage(void* apBuffer, uint32_t anLength, void* apUserArg) { int retval = 0; // The return message to the ARM char lpReturnMessage[] = "Hello World. DSP Received Message = \'"; // Buffer for return message char* lpMessageBuffer = NULL; // Obtain a dsplink buffer for the return message lpMessageBuffer = (char*)gpOutbound->GetBuffer(strlen(lpReturnMessage) + strlen((const char*)apBuffer) + 2); // Make sure we received a valid buffer if (NULL != lpMessageBuffer) { // Copy our message to the buffer strcpy(lpMessageBuffer, lpReturnMessage); // Append the received message to the buffer strcpy((char*)&lpMessageBuffer[strlen(lpReturnMessage)], (const char *)apBuffer); // Null terminate the string lpMessageBuffer[strlen(lpMessageBuffer)+1] = 0; // Append the closing quotation lpMessageBuffer[strlen(lpMessageBuffer)] = '\''; // Send the message back to the ARM retval = gpOutbound->SendMessage(lpMessageBuffer); } else { retval = -1; } return retval; } /** * Callback function that handles messages from the ARM. * * \param apBuffer Pointer to message buffer. * \param anLength Length of message. * \param apUserArg Pointer to user defined argument * * \return 0 on sucess. */ int handleInboundMessageBM(void* apBuffer, uint32_t anLength, void* apUserArg) { int retval = 0; // Buffer for return message char* lpMessageBuffer = NULL; // Obtain a dsplink buffer for the return message lpMessageBuffer = (char*)gpOutbound->GetBuffer(sizeof(messageA2D)); // Make sure we received a valid buffer if (NULL != lpMessageBuffer) { // Process message from ARM here... // extract msg type from message memcpy(&messageA2D, apBuffer, anLength); switch (messageA2D.header.type) { case eLibrary: // for fun just increment some values and send back to ARM messageA2D.library.FeatureCount++; messageA2D.library.SQCBatchSize++; messageA2D.library.header.command = eWriteToARM; break; }; // Copy our message to the buffer memcpy(lpMessageBuffer, &messageA2D, sizeof(messageA2D)); // Send the message back to the ARM retval = gpOutbound->SendMessage(lpMessageBuffer); SEM_post(msgRecvd); // trigger that we have recv'd and responded to the ARM Message. gpOutbound->ReturnBuffer(apBuffer); } else { retval = -1; } return retval; } /** * Function for sending debug messages to the ARM. * * \param buffer Null terminated string to be printed. * * \return None. */ 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); } }