/****************************************************************************** * * Title : commonCommunicationLoop.c * Version 0.0 * * Description:commonCommunicationLoop_thread routine. * Distributes access to shared VME between all * Rods in the crate on round-robin basis. * * Author: Lukas Tomasek, tomasekl@fzu.cz * ******************************************************************************/ /****************************************************************************** * Header files * ******************************************************************************/ #include "communicationLoop.h" #include "uirUtility.h" #include "primListHandler.h" #include "textBuffersHandler.h" #include "threadUtility.h" #include "hostUtility.h" #include "comRegDfns.h" #include "mainUir.h" #include "vmeHpiUtility.h" #include "rodInit.h" #include "RccExtControl.h" static int sendExternalList(struct HOST *host); /****************************************************************************** * Global functions * ******************************************************************************/ /*============================================================================= * commonCommunicationLoop_thread() *============================================================================= * * Distributes access to VME between all Rods in the crate on round-robin * basis. * * Input: ->global - pointer to global struct variable defined in * globalDefinitions.h; * Output: -> can return only SUCCESS. * * Note: This is a thread routine - calling is WIN32 dependent(WINAPI), so * number of input parameters (1), input type (32b. pointer to input parameters), * and return type (DWORD, ERROR_ID is 32b) are MANDATORY. */ ERROR_ID WINAPI communicationLoop_thread(struct GLOBAL_VARIABLES *global) { ERROR_ID errorId=SUCCESS; struct HOST *host; int status; /* LW CVI function return status */ unsigned char hostIndex=0; /* current active Host/Rod */ unsigned char interruptIndex; unsigned char counter; UINT32 oldValue; unsigned char oldSlot; double displayTime=0; int value; double time; double displayRefreshTime[MAXRODS]; double dspMonitorRefreshTime[MAXRODS]; double fpgaMonitorRefreshTime[MAXRODS]; int capture; UINT32 debugReg[2]; char inputText[300]; int i; GetCtrlVal(global->panel.main, MAIN_REFRESH_PERIOD, &global->option.displayRefreshPeriodInSec); GetCtrlVal(global->panel.main, MAIN_REFRESH_DISP, (int*)&global->option.displayRefresh); GetCtrlVal(global->panel.main, MAIN_FPGA_MONITOR_PERIOD, &global->option.fpgaMonitorPeriodInSec); GetCtrlVal(global->panel.main, MAIN_FPGA_MONITOR_REFRESH, &global->option.fpgaMonitorOn); GetCtrlVal(global->panel.main, MAIN_DSP_MONITOR_PERIOD, &global->option.dspMonitorPeriodInSec); GetCtrlVal(global->panel.main, MAIN_DSP_MONITOR_REFRESH, &global->option.fpgaMonitorOn); memset(displayRefreshTime, 0, MAXRODS * sizeof(double)); memset(dspMonitorRefreshTime, 0, MAXRODS * sizeof(double)); memset(fpgaMonitorRefreshTime, 0, MAXRODS * sizeof(double)); /* intit shared memory for External client */ status=sharedMemoryOpen(); if(status!=0){ ERROR_CHECK(PROGRAM_WARNING, sharedMemoryOpen()); } /* * repeat loop until programExit */ while(global->option.programExit!=TRUE){ for(hostIndex=0; (hostIndexoption.programExit!=TRUE); ++hostIndex){ if(global->option.stopCommLoop){ /* suspend thread * - thread is resumed from loadExitHost.c when at least one host(ie. global->hostCount>0) is running; * - also rusume/suspend button in MainWindow */ SetCtrlVal(global->panel.main, MAIN_COMM_LOOP_RUNNING, 0); global->option.commLoopRunning=FALSE; errorId=suspendThread(global->communLoopThread.handle); /* =suspendThread(GetCurrentThread()) */ ERROR_CHECK(errorId, suspendThread()); SetCtrlVal(global->panel.main, MAIN_COMM_LOOP_RUNNING, 1); global->option.commLoopRunning=TRUE; continue; } Sleep(0); /* don't usurp too much processor time, esp. when no datatransfer load (pooling loop has no additional delay!) */ /* assign active host, which has VME access in this round */ host=global->host[hostIndex]; if((host==NULL)||(host->option.hostExit==TRUE)||(host->option.rodEnabled==FALSE)){ /* Host/Rod not loaded */ continue; } if(global->option.displayRefresh==REFRESH_RUNTIME){ /* update slotNumber on display */ SetCtrlVal(global->panel.main, MAIN_ACTIVE_SLOT, host->slotNumber); } if(host->rodInitialized==FALSE){ errorId=rodInit(host); ERROR_CHECK(errorId, rodInit(host)); if(errorId!=SUCCESS) continue; }; if(host->commandReady){ host->commandReady=0; //!!! errorId=(global->commandFunction[host->command->id])(COMMAND_EXECUTION, host->command, host->slotNumber, 0); HOST_ERROR_CHECK(errorId, host, commandFunction()); host->commandStatus=errorId; /* resume cmdListExecution */ errorId=setEvent(host->commandDone_event); HOST_ERROR_CHECK(errorId, host, setEvent()); } GetCtrlVal(host->panel.parent, ROD_CAPTURE, &capture); if(capture){ /* occupancy distribution mode */ errorId=RWmaster(READ, host->slotNumber, DEBUG_MODE_CFG_REG_ADDR, debugReg, 2, HPIA_AUTOINCREMENT, 0); ERROR_CHECK(errorId, RWmaster()); if((((debugReg[0]>>12)&0x3F)==0x24)&&((debugReg[1]&0xC0)!=0)){ errorId=FEoccupancy(host); HOST_ERROR_CHECK(errorId, host, FEoccupancy()); } } #if 0 /* read RodStatusReg0and1 and save to local variables */ errorId=readRodStatusRegs(host->slotNumber, host->rodStatusReg); if(errorId!=SUCCESS){ hostError(__FILE__,__LINE__, VME_ERROR, host, "readRodStatusRegs(rodStatusReg)"); host->option.rodEnabled=FALSE; SetCtrlVal(host->panel.parent, ROD_HOST_RUNNING, 0); continue; } #else /* read RodStatusReg0and1 and save to local variables */ for(i=0, global->option.disableVmeError=1; i<11; i++){ if(i>9) global->option.disableVmeError=0; errorId=readRodStatusRegs(host->slotNumber, host->rodStatusReg); if(errorId==SUCCESS) break; Sleep(100); // give HPI some time to process RW_MODULE_DATA primitive } global->option.disableVmeError=0; if(errorId!=SUCCESS){ hostError(__FILE__,__LINE__, VME_ERROR, host, "readRodStatusRegs(rodStatusReg)"); host->option.rodEnabled=FALSE; SetCtrlVal(host->panel.parent, ROD_HOST_RUNNING, 0); continue; } #endif if(READ_BIT(host->rodStatusReg[0], SR_RUNNING)==0){ HOST_ERROR_CHECK(errorId, host, SR_RUNNING==0 - MDSP is not running!); } if(global->option.displayRefresh==REFRESH_RUNTIME){ displayRodStatusReg0(host); GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_ROD_STAT_REG1, host->rodStatusReg[1], &oldValue); } if(global->option.displayRefresh==REFRESH_ON){ /* refresh "Timer" display */ time=Timer(); if((time-displayRefreshTime[hostIndex])>global->option.displayRefreshPeriodInSec) { /* update slotNumber on display */ GET_AND_SET_CTRL_VAL(global->panel.main, MAIN_ACTIVE_SLOT, host->slotNumber, (UINT8*)&oldValue); displayRodStatusReg0(host); displayVmeCommandReg0(host); GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_LIST_INDEX, host->listIndex, &oldValue); ; GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_ROD_STAT_REG1, host->rodStatusReg[1], &oldValue); GET_AND_SET_CTRL_VAL(host->panel.parent, ROD_LIST_REPEAT_COUNTER, host->primListRepCounter, &oldValue); displayRefreshTime[hostIndex]=time; } } if(global->option.fpgaMonitorOn){ /* refresh fpga status */ time=Timer(); if((time-fpgaMonitorRefreshTime[hostIndex])>global->option.fpgaMonitorPeriodInSec) { errorId=refreshFpgaStatus(host); HOST_ERROR_CHECK(errorId, host, refreshFpgaStatus()); fpgaMonitorRefreshTime[hostIndex]=time; } } if(global->option.dspMonitorOn){ /* refresh dsp status */ GetPanelAttribute (host->panel.dspMonitor, ATTR_VISIBLE, &value); /* refresh only if panel is visible */ time=Timer(); if((value)&&((time-dspMonitorRefreshTime[hostIndex])>global->option.dspMonitorPeriodInSec)) { errorId=refreshDspRegs(host); HOST_ERROR_CHECK(errorId, host, refreshDspRegs()); dspMonitorRefreshTime[hostIndex]=time; } } /* errorBuffHandler */ errorId=textBufferHandler(host, ERR_BUFF, ERR_BUFF_BASE); HOST_ERROR_CHECK(errorId, host, textBufferHandler(ERROR_BUFF)); /* infoBuffHandler */ errorId=textBufferHandler(host, INFO_BUFF, INFO_BUFF_BASE); HOST_ERROR_CHECK(errorId, host, textBufferHandler(INFO_BUFF)); /* diagBuffHandler */ errorId=textBufferHandler(host, DIAG_BUFF, DIAG_BUFF_BASE); HOST_ERROR_CHECK(errorId, host, textBufferHandler(DIAG_BUFF)); /* xferBuffHandler */ errorId=textBufferHandler(host, XFER_BUFF, XFER_BUFF_BASE); HOST_ERROR_CHECK(errorId, host, textBufferHandler(XFER_BUFF)); /* primList and repList handler */ errorId=listHandler(host, &host->listHandlerState); HOST_ERROR_CHECK(errorId, host, listHandler(host)); /* send external list if ready */ status=sendExternalList(host); if(status!=0){ ERROR_CHECK(PROGRAM_WARNING, sendExternalList()); } } } /* close shared memory */ status=sharedMemoryClose(); if(status!=0){ ERROR_CHECK(PROGRAM_WARNING, sharedMemoryClose()); } return(SUCCESS); } /*============================================================================= * sendExternalList() *=============================================================================*/ static int sendExternalList(struct HOST *host){ const int panel=global.panel.main; int status; static int listExecuting=0; if((host->slotNumber!=sharedMemPtr->slotNumber)||(sharedMemPtr->executingFlag==0)){ return(0); // empty } if((host->cmdListExecState!=CMDLISTEXEC_IDLE)||(host->primListReady)){ return(0); // busy } SetCtrlVal(panel, MAIN_EXT_EXEC, sharedMemPtr->executingFlag); if(listExecuting) { sharedMemPtr->executingFlag=0; // clear executing flag!! SetCtrlVal(panel, MAIN_EXT_EXEC, sharedMemPtr->executingFlag); listExecuting=0; } SetCtrlVal(panel, MAIN_SLOT_NUMBER, sharedMemPtr->slotNumber); SetCtrlVal(panel, MAIN_EXT_LIST_TYPE, sharedMemPtr->listType); switch(sharedMemPtr->listType){ case CMD_LIST_FILE: SetCtrlVal(panel, MAIN_CLIST_FILE, sharedMemPtr->listFileName); SetCtrlVal(panel, MAIN_CLIST_REP, sharedMemPtr->numRepetitions); status=sendListToAll(panel, MAIN_SEND_COMMAND_LIST, EVENT_COMMIT, 0, 0, 0); if(status!=0){ return(-1); } listExecuting=1; break; case MLIST_FILE: SetCtrlVal(panel, MAIN_PLIST_FILE, sharedMemPtr->listFileName); SetCtrlVal(panel, MAIN_PLIST_REP, sharedMemPtr->numRepetitions); status=sendListToAll(panel, MAIN_SEND_LIST, EVENT_COMMIT, 0, 0, 0); if(status!=0){ return(-1); } listExecuting=1; break; case RAW_PRIM_LIST: // NOT READY YET break; } return(0); } /*============================================================================= * sendExternalList() *=============================================================================*/ static int executeExtRawList(struct HOST *host, unsigned int repetitions){ ERROR_ID errorId; int status; UINT32 tableLength; if(host->option.rodEnabled==0) return(-1); if((host->cmdListExecState!=CMDLISTEXEC_IDLE)||(host->primListReady)){ HOST_ERROR_CHECK(PROGRAM_ERROR, host, Cannot execute PrimList - CmdListExecution is busy!!); return(-1); } host->option.repeatExecNotBuild=1; SetCtrlVal(host->panel.parent, ROD_REPEAT_BUILD_EXEC,1); host->option.primListRepetitions=repetitions; SetCtrlVal(host->panel.parent, ROD_NUMBER_OF_LIST_REP, repetitions); host->primListReady=RAW_EXTERNAL_LIST; displayCmdListExecBusy(host); return(SUCCESS); } /******************************************************************************/