// ================================================================================================ // FUNCTION : wiProcess_WaitForThread // ------------------------------------------------------------------------------------------------ // ================================================================================================ wiStatus wiProcess_WaitForThread(wiUInt ThreadIndex) { if (InvalidRange(ThreadIndex, 1, WISE_MAX_THREADINDEX)) return WI_ERROR_PARAMETER1; #if defined WISE_USE_PTHREADS { void *pVoid; int rc = pthread_join(ThreadData[ThreadIndex].Thread, &pVoid); if (rc != 0) { wiUtil_WriteLogFile("pthread_join returned %d\n",rc); return WI_ERROR; } return WI_SUCCESS; } #elif defined WIN32 { DWORD TimeOut = 0xFFFFFFFF; // milliseconds wiStatus status; DWORD dwStatus; WaitForMultipleObjects(1, &(ThreadData[ThreadIndex].Thread), TRUE, TimeOut); GetExitCodeThread(ThreadData[ThreadIndex].Thread, &dwStatus); status = (wiStatus)dwStatus; if (status != WI_SUCCESS) wiUtil_WriteLogFile("ExitCode for ThreadIndex = %d returned 0x%08X\n", ThreadIndex, dwStatus); if (status < WI_SUCCESS) XSTATUS(status); return WI_SUCCESS; } #else return STATUS(WI_ERROR_NO_MULTITHREAD_SUPPORT); #endif }
Range::Range(const CHARRANGE& range, LONG total_length) { // Check if this is an invalid range. if(range.cpMin==-1 && range.cpMax==-1) { *this = InvalidRange(); } else { DCHECK_GE(range.cpMin, 0); set_start(range.cpMin); // {0,-1} is the "whole range" but that doesn't mean much out of context, // so use the |total_length| parameter. if(range.cpMax == -1) { DCHECK_EQ(0, range.cpMin); DCHECK_NE(-1, total_length); set_end(total_length); } else { set_end(range.cpMax); } } }
// ================================================================================================ // FUNCTION : wiProcess_InitializeThreadIndex() // ------------------------------------------------------------------------------------------------ // ================================================================================================ wiStatus wiProcess_InitializeThreadIndex(unsigned ThreadIndex) { if (InvalidRange(ThreadIndex, 1, WISE_MAX_THREADINDEX)) return WI_ERROR_PARAMETER1; #if defined WISE_USE_PTHREADS { void *lpvData = wiMalloc(sizeof(int)); if (!lpvData) return STATUS(WI_ERROR_MEMORY_ALLOCATION); pthread_setspecific(wiProcessKey, lpvData); (*(unsigned int *)lpvData) = ThreadIndex; return WI_SUCCESS; } #elif defined WIN32 { LPVOID lpvData; lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(int)); TlsSetValue(dwTlsIndex, lpvData); (*(unsigned int *)lpvData) = ThreadIndex; return WI_SUCCESS; } #else return STATUS(WI_ERROR_NO_MULTITHREAD_SUPPORT); #endif }
// ================================================================================================ // FUNCTION : wiPHY_Command // ------------------------------------------------------------------------------------------------ // Purpose : Execute a method command // Parameters: command -- WIPHY_* instruction from wiPHY.h // ================================================================================================ wiStatus wiPHY_Command(int command) { if (Verbose) wiPrintf(" wiPHY_Command(0x%08X)\n",command); if (InvalidRange(command, 0x00010000, 0x7FFF0000)) return WI_ERROR_PARAMETER2; if (!ActiveMethod) return WI_ERROR_INVALID_METHOD; XSTATUS( ActiveMethod->fn(command, ActiveMethod) ); return WI_SUCCESS; }
// ================================================================================================ // FUNCTION : wiPHY_GetData // ------------------------------------------------------------------------------------------------ // Purpose : Retrieve the value of a data element from the method // Parameters: param -- WIPHY_* parameter code from wiPHY.h // pValue -- Ptr->variable in which the value is returned // ================================================================================================ wiStatus wiPHY_GetData(int param, void *pdata) { if (Verbose) wiPrintf(" wiPHY_GetData(0x%08X, *)\n",param); if (!ActiveMethod) return WI_ERROR_INVALID_METHOD; if (InvalidRange(param, 0x0001, 0xFFFF)) return WI_ERROR_PARAMETER1; if (!pdata) return WI_ERROR_PARAMETER3; XSTATUS( ActiveMethod->fn(WIPHY_GET_DATA | param, pdata) ); return WI_SUCCESS; }
Range Range::Intersect(const Range& range) const { size_t min = std::max(GetMin(), range.GetMin()); size_t max = std::min(GetMax(), range.GetMax()); if(min >= max) // No intersection. { return InvalidRange(); } return Range(min, max); }
// ================================================================================================ // FUNCTION : wiPHY_RX // ------------------------------------------------------------------------------------------------ // Purpose : Call the PHY receiver function // Parameters: nBytes -- Number of octets (bytes) in the data array // data -- Data byte buffer (by reference) // Nr -- Number of samples in r // R -- Array of sample arrays // ================================================================================================ wiStatus wiPHY_RX(int *nBytes, wiUWORD *data[], int Nr, wiComplex *R[]) { if (Verbose) wiPrintf(" wiPHY_RX(*, *, %d, *)\n",Nr); if (!Initialized) return WI_ERROR_MODULE_NOT_INITIALIZED; if (!ActiveMethod) return WI_ERROR_INVALID_METHOD; if (!data) return WI_ERROR_PARAMETER2; if (InvalidRange(Nr, 100, 1<<30)) return WI_ERROR_PARAMETER3; if (!R) return WI_ERROR_PARAMETER4; if (!R[0]) return WI_ERROR_PARAMETER4; XSTATUS( ActiveMethod->RxFn(nBytes, data, Nr, R) ); return WI_SUCCESS; }
// ================================================================================================ // FUNCTION : wiProcess_CloseThread // ------------------------------------------------------------------------------------------------ // ================================================================================================ wiStatus wiProcess_CloseThread(wiUInt ThreadIndex) { if (InvalidRange(ThreadIndex, 1, WISE_MAX_THREADINDEX)) return WI_ERROR_PARAMETER1; ThreadData[ThreadIndex].ThreadInUse = WI_FALSE; #if defined WISE_USE_PTHREADS return WI_SUCCESS; #elif defined WIN32 CloseHandle(ThreadData[ThreadIndex].Thread); return WI_SUCCESS; #else return STATUS(WI_ERROR_NO_MULTITHREAD_SUPPORT); #endif }
// ================================================================================================ // FUNCTION : wiPHY_TX // ------------------------------------------------------------------------------------------------ // Purpose : Call the PHY transmit function // Parameters: bps -- PHY transmission rate (bps) // nBytes -- Number of octets (bytes) in the data array // data -- Data byte buffer // Ns -- Number of samples in s (by reference) // S -- Pointer to internal array s (by reference) // Fs -- Sample rate for channel model (Hz) // Prms -- Complex transmit power (rms) // ================================================================================================ wiStatus wiPHY_TX(double bps, int nBytes, wiUWORD *data, int *Ns, wiComplex **S[], double *Fs, double *Prms) { if (Verbose) wiPrintf(" wiPHY_TX(%d, *, *, *)\n",nBytes); if (!Initialized) return WI_ERROR_MODULE_NOT_INITIALIZED; if (!ActiveMethod) return WI_ERROR_INVALID_METHOD; if (InvalidRange(nBytes, 1, 65536)) return WI_ERROR_PARAMETER1; if (!data) return WI_ERROR_PARAMETER2; if (!Ns) return WI_ERROR_PARAMETER3; if (!S) return WI_ERROR_PARAMETER4; if (!Fs) return WI_ERROR_PARAMETER5; XSTATUS( ActiveMethod->TxFn(bps, nBytes, data, Ns, S, Fs, Prms) ); return WI_SUCCESS; }
// ================================================================================================ // FUNCTION : wiProcess_ReleaseThreadIndex() // ------------------------------------------------------------------------------------------------ // ================================================================================================ wiStatus wiProcess_ReleaseThreadIndex(unsigned ThreadIndex) { if (InvalidRange(ThreadIndex, 1, WISE_MAX_THREADINDEX)) return WI_ERROR_PARAMETER1; #if defined WISE_USE_PTHREADS { void *lpvData = pthread_getspecific(wiProcessKey); WIFREE(lpvData); pthread_setspecific(wiProcessKey, NULL); return WI_SUCCESS; } #elif defined WIN32 { LPVOID lpvData; lpvData = TlsGetValue(dwTlsIndex); LocalFree((HLOCAL)lpvData); return WI_SUCCESS; } #else return STATUS(WI_ERROR_NO_MULTITHREAD_SUPPORT); #endif }
bool Range::IsValid() const { return *this != InvalidRange(); }
wiStatus CalcEVM_Mojave_RX(int *Length, wiUWORD *data[], int Nr, wiComplex *R[]) { static Mojave_CtrlState inReg, outReg; // top-level control signals static Mojave_DataConvCtrlState DataConvIn, DataConvOut; // data converter control static Mojave_RadioDigitalIO RadioSigOut = {0}; // radio/RF signals wiComplex s[2] = {0}; Mojave_RX_State *pRX; MojaveRegisters *pReg; bMojave_RX_State *pbRX; if (Verbose) wiPrintf(" CalcEVM_RX(@x%08X,@x%08X,%d,@x%08X)\n",Length,data,Nr,R); if (InvalidRange(Nr, 400, 1<<28)) return STATUS(WI_ERROR_PARAMETER3); if (!R ) return STATUS(WI_ERROR_PARAMETER4); if (!R[0]) return STATUS(WI_ERROR_PARAMETER4); XSTATUS( Mojave_StatePointer(NULL, &pRX, &pReg )); XSTATUS(bMojave_StatePointer(&pbRX)); // ---------------------------- // Check Baseband Configuration // ---------------------------- if (pReg->RXMode.w2 != 1) { wiUtil_WriteLogFile("Mojave RXMode must be set to 1 when used with CalcEVM\n"); return STATUS(WI_ERROR); } if (pReg->PathSel.w2 != 1) { wiUtil_WriteLogFile("Mojave PathSel must be set to 1 when used with CalcEVM\n"); return STATUS(WI_ERROR); } pRX->EVM.Enabled = 1; // force EVM calculation to be enabled // ---------------------------------------------- // Resize Arrays for excess receive signal length // ---------------------------------------------- if (!pbRX->N44 || ((unsigned)Nr != pRX->rLength)) { pRX->rLength = Nr; pbRX->N44 = Nr * 44/80 + 2; // +2 for rounding and initial clock index=1 XSTATUS( Mojave_RX_AllocateMemory() ); XSTATUS( bMojave_RX_AllocateMemory() ); } // ------------------------------------------ // Restart the PHY modules for the new packet // ------------------------------------------ XSTATUS( Mojave_RX_Restart(pbRX) ); // baseband restart Mojave_RX_ClockGenerator(1); // reset clock generator inReg.bRXEnB = 1; // reset state for bRXEnB inReg.State = outReg.State = 0; // reset RX/Top control state // --------------------------- // Clear the event/fault flags // --------------------------- pRX->EventFlag.word = 0; pRX->Fault = 0; pRX->x_ofs = -1; // ---------------------------------------------------------------- // RECEIVER ------------------------------------------------------- // Clocked Operation With Mixed Clock/Symbol/Packet Timing Accuracy // ...the base clock is 80 MHz; all other timing is derived // ---------------------------------------------------------------- while (pRX->k40 < pRX->Nr) { Mojave_RX_ClockGenerator(0); // generate next clock edge(s) // ----------------------------- // PHY RX at Base Rate of 80 MHz // ----------------------------- if (pRX->clock.posedgeCLK80MHz) { // ------------------------- // Clock Registers at 80 MHz // ------------------------- DataConvOut = DataConvIn; outReg = inReg; // ----------------------------------------- // Data Conversion - Analog-to-Digital (ADC) // ----------------------------------------- if (pRX->clock.posedgeCLK40MHz) { if (R[0]) s[0] = R[0][pRX->k80]; if (R[1]) s[1] = R[1][pRX->k80]; Mojave_ADC(DataConvIn, &DataConvOut, s[0], s[1], pRX->qReal[0]+pRX->k40, pRX->qImag[0]+pRX->k40, pRX->qReal[1]+pRX->k40, pRX->qImag[1]+pRX->k40); } // ---------------------------------- // Digital Baseband Receiver (Mojave) // ---------------------------------- XSTATUS( Mojave_RX(0, &RadioSigOut, &DataConvIn, DataConvOut, &inReg, outReg) ); } } // ---------------- // Extract EVM Data // ---------------- { int i, j, k; // int du=pRX->x_ofs+82+144; //82 for FFT delay; 144: LPF+16 for SIG GI. Starting point of SIG; int du=82; //du is set to be consistant with Dakota; State.EVM.W_EVMdB = 0.0; for (i=0; i< 64; i++) State.EVM.h[i] = pRX->EVM.h[0][i]; State.EVM.N_SYM = pRX->EVM.N_SYM; State.EVM.Se2 = pRX->EVM.Se2[0]; State.EVM.EVM = pRX->EVM.EVM[0]; State.EVM.cCFO = pRX->EVM.cCFO*10e6/pi/16; State.EVM.fCFO = pRX->EVM.fCFO*10e6/pi/16; for (i=0; i< 64; i++) State.EVM.cSe2[i] = pRX->EVM.cSe2[0][i]; for (i=0; i<State.EVM.N_SYM; i++) State.EVM.nSe2[i] = pRX->EVM.nSe2[0][i]; if (!pRX->Fault) { if (State.EVM.x) wiFree(State.EVM.x); State.EVM.x = (wiComplex *)wiCalloc(64 * (State.EVM.N_SYM+1), sizeof(wiComplex)); if (!State.EVM.x) return STATUS(WI_ERROR_MEMORY_ALLOCATION); if (State.EVM.u) wiFree(State.EVM.u); State.EVM.u=(wiComplex *)wiCalloc(pRX->Nu-du, sizeof(wiComplex)); if (!State.EVM.u) return STATUS(WI_ERROR_MEMORY_ALLOCATION); for (i=k=0; i<=pRX->EVM.N_SYM; i++) { for (j=0; j<64; j++, k++) { State.EVM.x[k] = pRX->EVM.x[0][j][i]; } } for (i=0; i<(int)(pRX->Nu-du); i++) { State.EVM.u[i].Real=(double) pRX->uReal[0][i+du].word; State.EVM.u[i].Imag=(double) pRX->uImag[0][i+du].word; } } } // ----------------------------------------------- // Return PSDU and Length (drop 8 byte PHY header) // ----------------------------------------------- if (Length) *Length = pRX->N_PHY_RX_WR - 8; if (data) *data = pRX->PHY_RX_D + 8; return WI_SUCCESS; }
// ================================================================================================ // FUNCTION : wiPHY_SetData // ------------------------------------------------------------------------------------------------ // Purpose : Set the value for a data element of the method // Parameters: param -- WIPHY_* parameter code from wiPHY.h // pValue -- Ptr->variable in which the value is returned // ================================================================================================ wiStatus wiPHY_SetData(int param, ...) { va_list ap; void *ptr; int ival; wiUInt uval; wiReal rval; wiComplex cval; wiBoolean bval; if (Verbose) wiPrintf(" wiPHY_SetData(0x%04X,,...)\n",param); if (!ActiveMethod) return WI_ERROR_INVALID_METHOD; if (InvalidRange(param, 0x0001, 0xFFFF)) return WI_ERROR_PARAMETER1; va_start(ap, param); switch (param >> 12) { //-- Pointers/Arrays -------- case WITYPE_ADDR: ptr = va_arg(ap, void *); va_end(ap); break; //-- Integer ---------------- case WITYPE_INT: ival = va_arg(ap, int); va_end(ap); ptr = &ival; break; //-- Unsigned Integer ------- case WITYPE_UINT: uval = va_arg(ap, wiUInt); va_end(ap); ptr = &uval; break; //-- Real/Floating Point ---- case WITYPE_REAL: rval = va_arg(ap, wiReal); va_end(ap); ptr = &(rval); //-- Complex Value ---------- case WITYPE_COMPLEX: cval = va_arg(ap, wiComplex); va_end(ap); ptr = &cval; break; //-- Boolean ---------------- case WITYPE_BOOLEAN: bval = va_arg(ap, wiBoolean); va_end(ap); ptr = &bval; break; //-- Unsupported ------------ default: va_end(ap); return WI_ERROR_PARAMETER1; } XSTATUS(ActiveMethod->fn((WIPHY_SET_DATA | param), ptr)); return WI_SUCCESS; }