/* * Initialize the Valid Rate Index from valid entries in Rate Table */ static A_UINT8 rcSibInitValidRates(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc, A_UINT32 capflag, PHY_STATE_CTRL *pPhyStateCtrl) { A_UINT8 i, hi = 0; A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; A_UINT8 valid; for (i = 0; i < pRateTable->rateCount; i++) { if (singleStream) { valid = pRateTable->info[i].validSingleStream; } else { valid = pRateTable->info[i].valid; } if (valid == TRUE) { A_UINT32 phy = pRateTable->info[i].phy; if (!rcIsValidPhyRate(phy, capflag, FALSE)) continue; pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = i; pPhyStateCtrl->validPhyRateCount[phy] += 1; rcSetValidTxMask(pRc, i, TRUE); hi = A_MAX(hi, i); } } return hi; }
LOCAL htc_handle_t _HTC_Init(HTC_SETUP_COMPLETE_CB SetupComplete, HTC_CONFIG *pConfig) { HIF_CALLBACK hifCBConfig; HTC_CONTEXT *pHTC; pHTC = (HTC_CONTEXT *)adf_os_mem_alloc(sizeof(HTC_CONTEXT)); adf_os_mem_zero(pHTC, sizeof(HTC_CONTEXT)); pHTC->OSHandle = pConfig->OSHandle; pHTC->PoolHandle = pConfig->PoolHandle; pHTC->hifHandle = pConfig->HIFHandle; hifCBConfig.send_buf_done = A_INDIR(htc._HTC_SendDoneHandler); hifCBConfig.recv_buf = A_INDIR(htc._HTC_MsgRecvHandler); hifCBConfig.context = pHTC; /* initialize hardware layer */ HIF_register_callback(pConfig->HIFHandle, &hifCBConfig); /* see if the host wants us to override the number of ctrl buffers */ pHTC->NumBuffersForCreditRpts = 0; if (0 == pHTC->NumBuffersForCreditRpts) { /* nothing to override, simply set default */ pHTC->NumBuffersForCreditRpts = HTC_DEFAULT_NUM_CTRL_BUFFERS; } pHTC->MaxEpPendingCreditRpts = 0; if (0 == pHTC->MaxEpPendingCreditRpts) { pHTC->MaxEpPendingCreditRpts = HTC_DEFAULT_MAX_EP_PENDING_CREDIT_REPORTS; } /* calculate the total allocation size based on the number of credit report buffers */ pHTC->CtrlBufferAllocSize = MIN_CREDIT_BUFFER_ALLOC_SIZE * pHTC->NumBuffersForCreditRpts; /* we need at least enough buffer space for 1 ctrl message */ pHTC->CtrlBufferAllocSize = A_MAX(pHTC->CtrlBufferAllocSize,MAX_HTC_SETUP_MSG_SIZE); /* save the size of each buffer/credit we will receive */ pHTC->RecvBufferSize = pConfig->CreditSize; //RecvBufferSize; pHTC->TotalCredits = pConfig->CreditNumber; pHTC->TotalCreditsAssigned = 0; /* setup the pseudo service that handles HTC control messages */ pHTC->HTCControlService.ProcessRecvMsg = A_INDIR(htc._HTC_ControlSvcProcessMsg); pHTC->HTCControlService.ProcessSendBufferComplete = A_INDIR(htc._HTC_ControlSvcProcessSendComplete); pHTC->HTCControlService.TrailerSpcCheckLimit = HTC_CTRL_BUFFER_CHECK_SIZE; pHTC->HTCControlService.MaxSvcMsgSize = MAX_HTC_SETUP_MSG_SIZE; pHTC->HTCControlService.ServiceCtx = pHTC; /* automatically register this pseudo service to endpoint 1 */ pHTC->Endpoints[ENDPOINT0].pService = &pHTC->HTCControlService; HIF_get_default_pipe(pHTC->hifHandle, &pHTC->Endpoints[ENDPOINT0].UpLinkPipeID, &pHTC->Endpoints[ENDPOINT0].DownLinkPipeID); /* Initialize control pipe so we could receive the HTC control packets */ // @TODO: msg size! HIF_config_pipe(pHTC->hifHandle, pHTC->Endpoints[ENDPOINT0].UpLinkPipeID, 1); /* set the first free endpoint */ pHTC->CurrentEpIndex = ENDPOINT1; pHTC->SetupCompleteCb = SetupComplete; /* setup buffers for just the setup phase, we only need 1 buffer to handle * setup */ HTC_AssembleBuffers(pHTC, 4, MAX_HTC_SETUP_MSG_SIZE); /* start hardware layer so that we can queue buffers */ HIF_start(pHTC->hifHandle); return pHTC; }
/* * Initialize the Valid Rate Index from Rate Set */ static A_UINT8 rcSibSetValidRates(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc, struct ieee80211_rateset *pRateSet, A_UINT32 capflag, struct ath_node_target *an, PHY_STATE_CTRL *pPhyStateCtrl) { A_UINT8 i, j, hi = 0; A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; A_UINT32 valid; struct atheros_node *pSib = ATH_NODE_ATHEROS(an); /* Use intersection of working rates and valid rates */ for (i = 0; i < pRateSet->rs_nrates; i++) { for (j = 0; j < pRateTable->rateCount; j++) { A_UINT32 phy = pRateTable->info[j].phy; #ifdef MAGPIE_MERLIN if (pSib->stbc) { valid = pRateTable->info[j].validSTBC; } else if (singleStream) { #else if (singleStream) { #endif valid = pRateTable->info[j].validSingleStream; } else { valid = pRateTable->info[j].valid; } /* * We allow a rate only if its valid and the capflag matches one of * the validity (TRUE/TRUE_20/TRUE_40) flags */ if (((pRateSet->rs_rates[i] & 0x7F) == (pRateTable->info[j].dot11Rate & 0x7F)) && ((valid & WLAN_RC_CAP_MODE(capflag)) == WLAN_RC_CAP_MODE(capflag)) && !WLAN_RC_PHY_HT(phy)) { if (!rcIsValidPhyRate(phy, capflag, FALSE)) continue; pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = j; pPhyStateCtrl->validPhyRateCount[phy] += 1; rcSetValidTxMask(pRc, j, TRUE); hi = A_MAX(hi, j); } } } return hi; } static A_UINT8 rcSibSetValidHtRates(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc, A_UINT8 *pMcsSet, A_UINT32 capflag, struct ath_node_target *an, PHY_STATE_CTRL *pPhyStateCtrl) { A_UINT8 i, j, hi = 0; A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; A_UINT8 valid; struct atheros_node *pSib = ATH_NODE_ATHEROS(an); /* Use intersection of working rates and valid rates */ for (i = 0; i < ((struct ieee80211_rateset *)pMcsSet)->rs_nrates; i++) { for (j = 0; j < pRateTable->rateCount; j++) { A_UINT32 phy = pRateTable->info[j].phy; #ifdef MAGPIE_MERLIN if (pSib->stbc) { valid = pRateTable->info[j].validSTBC; } else if (singleStream) { #else if (singleStream) { #endif valid = pRateTable->info[j].validSingleStream; } else { valid = pRateTable->info[j].valid; } if (((((struct ieee80211_rateset *)pMcsSet)->rs_rates[i] & 0x7F) != (pRateTable->info[j].dot11Rate & 0x7F)) || !WLAN_RC_PHY_HT(phy) || !WLAN_RC_PHY_HT_VALID(valid, capflag) || ((pRateTable->info[j].dot11Rate == 15) && (valid & TRUE_20) && (capflag & WLAN_RC_WEP_TKIP_FLAG)) ) { continue; } if (!rcIsValidPhyRate(phy, capflag, FALSE)) continue; pPhyStateCtrl->validPhyRateIndex[phy][pPhyStateCtrl->validPhyRateCount[phy]] = j; pPhyStateCtrl->validPhyRateCount[phy] += 1; rcSetValidTxMask(pRc, j, TRUE); hi = A_MAX(hi, j); } } return hi; } /* * Update the SIB's rate control information * * This should be called when the supported rates change * (e.g. SME operation, wireless mode change) * * It will determine which rates are valid for use. */ static void rcSibUpdate_ht(struct ath_softc_tgt *sc, struct ath_node_target *an, A_UINT32 capflag, A_BOOL keepState, struct ieee80211_rate *pRateSet) { RATE_TABLE_11N *pRateTable = 0; struct atheros_node *pSib = ATH_NODE_ATHEROS(an); struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc; A_UINT8 *phtMcs = (A_UINT8*)&pRateSet->htrates; TX_RATE_CTRL *pRc = (TX_RATE_CTRL *)(pSib); PHY_STATE_CTRL mPhyCtrlState; A_UINT8 i, j, k, hi = 0, htHi = 0; pRateTable = (RATE_TABLE_11N*)asc->hwRateTable[sc->sc_curmode]; /* Initial rate table size. Will change depending on the working rate set */ pRc->rateTableSize = MAX_TX_RATE_TBL; /* Initialize thresholds according to the global rate table */ for (i = 0 ; (i < pRc->rateTableSize) && (!keepState); i++) { pRc->state[i].per = 0; } /* Determine the valid rates */ rcInitValidTxMask(pRc); for (i = 0; i < WLAN_RC_PHY_MAX; i++) { for (j = 0; j < MAX_TX_RATE_PHY; j++) { mPhyCtrlState.validPhyRateIndex[i][j] = 0; } mPhyCtrlState.validPhyRateCount[i] = 0; } pRc->rcPhyMode = (capflag & WLAN_RC_40_FLAG); if (pRateSet == NULL || !pRateSet->rates.rs_nrates) { /* No working rate, just initialize valid rates */ hi = rcSibInitValidRates(pRateTable, pRc, capflag, &mPhyCtrlState); } else { /* Use intersection of working rates and valid rates */ hi = rcSibSetValidRates(pRateTable, pRc, &(pRateSet->rates), capflag, an, &mPhyCtrlState); if (capflag & WLAN_RC_HT_FLAG) { htHi = rcSibSetValidHtRates(pRateTable, pRc, phtMcs, capflag, an, &mPhyCtrlState); } hi = A_MAX(hi, htHi); } pRc->rateTableSize = hi + 1; pRc->rateMaxPhy = 0; ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL); for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { for (j = 0; j < mPhyCtrlState.validPhyRateCount[i]; j++) { pRc->validRateIndex[k++] = mPhyCtrlState.validPhyRateIndex[i][j]; } if (!rcIsValidPhyRate(i, pRateTable->initialRateMax, TRUE) || !mPhyCtrlState.validPhyRateCount[i]) continue; pRc->rateMaxPhy = mPhyCtrlState.validPhyRateIndex[i][j-1]; } ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL); ASSERT(k <= MAX_TX_RATE_TBL); pRc->rateMaxPhy = pRc->validRateIndex[k-4]; pRc->maxValidRate = k; rcSortValidRates(pRateTable, pRc); }
void aodtv72_cdoshearcalc( float xlat,float xlon,float tempval,int atype,float *valb,float *valc) /* Determine eye size or shear distance for a given scene. Inputs : xlat - center latitude of analysis grid xlon - center longitude of analysis grid tempval - temperature threshold value to be used atype - analysis type (1-cdo size,2-eye size,3-shear distance) Outputs : valb - eye/cdo radius or shear distance valc - eye/cdo symmetry value or 0 */ { int ixx,iyy,np,b,numvalid; float xdist,xangle,smalldist,vc,maxdist; float *zlat,*zlon; float a1,a2,a3,a4,v1,v2,v3; /* allocate memory */ b=sizeof(float); zlat=(float *)calloc((size_t)bufsiz,b); zlon=(float *)calloc((size_t)bufsiz,b); np=0; /* CDO size determination - RETURNS RADIUS */ if(atype==1) { /* a1=999.9;a2=999.9;a3=999.9;a4=999.9; */ a1=300.0;a2=300.0;a3=300.0;a4=300.0; for(ixx=0;ixx<areadata_v72->numx;ixx++) { for(iyy=0;iyy<areadata_v72->numy;iyy++) { if(areadata_v72->temp[iyy][ixx]>tempval) { zlat[np]=areadata_v72->lat[iyy][ixx]; zlon[np]=areadata_v72->lon[iyy][ixx]; np++; } } } /* printf("np=%d numx*numy=%d\n",np,areadata_v72->numx*areadata_v72->numy); */ maxdist=0.0; if(np<(areadata_v72->numx*areadata_v72->numy)) { for(ixx=0;ixx<np;ixx++) { aodtv72_distance(xlat,xlon,zlat[ixx],zlon[ixx],1,&xdist,&xangle); if(xdist>maxdist) maxdist=xdist; /* determine size of CDO */ if(xdist>keyerM_v72){ if((A_ABS(xangle-45.0)<=15.0)&&(xdist<a1)) a1=xdist; if((A_ABS(xangle-135.0)<=15.0)&&(xdist<a2)) a2=xdist; if((A_ABS(xangle-225.0)<=15.0)&&(xdist<a3)) a3=xdist; if((A_ABS(xangle-315.0)<=15.0)&&(xdist<a4)) a4=xdist; } } /* printf("a1=%f a2=%f a3=%f a4=%f\n",a1,a2,a3,a4); */ numvalid=4; v3=keyerM_v72+kres_v72; if(a1<v3) numvalid--; if(a2<v3) numvalid--; if(a3<v3) numvalid--; if(a4<v3) numvalid--; } else { a1=0.0; a2=0.0; a3=0.0; a4=0.0; } if(numvalid<3) { *valb=0.0; *valc=0.0; } else { a1=A_MIN(a1,maxdist); a2=A_MIN(a2,maxdist); a3=A_MIN(a3,maxdist); a4=A_MIN(a4,maxdist); *valb=(a1+a2+a3+a4)/4.0; /* *valc=A_ABS(((a1+a3)/2.0)-((a2+a4)/2.0))/2.0; */ v1=a1+a3; v2=a2+a4; vc=v1/v2; vc=A_MAX(vc,1.0/vc); *valc=vc; } /* printf("\nnp=%5.5d a1=%5.1f a2=%5.1f a3=%5.1f a4=%5.1f ",np,a1,a2,a3,a4); */ } /* shear distance determination */ if(atype==3) { a1=999.9;a2=999.9;a3=999.9;a4=999.9; for(ixx=0;ixx<areadata_v72->numx;ixx++) { for(iyy=0;iyy<areadata_v72->numy;iyy++) { if(areadata_v72->temp[iyy][ixx]<=tempval) { zlat[np]=areadata_v72->lat[iyy][ixx]; zlon[np]=areadata_v72->lon[iyy][ixx]; np++; } } } smalldist=999.9; for(ixx=0;ixx<np;ixx++) { aodtv72_distance(xlat,xlon,zlat[ixx],zlon[ixx],1,&xdist,&xangle); if(xdist<smalldist) smalldist=xdist; } *valb=smalldist; *valc=0.0; } /* free memory */ free(zlon); free(zlat); }
/* * Update the SIB's rate control information * * This should be called when the supported rates change * (e.g. SME operation, wireless mode change) * * It will determine which rates are valid for use. */ void rcSibUpdate(struct atheros_softc *asc, struct atheros_node *pSib, int keepState, struct ieee80211_rateset *pRateSet, enum ieee80211_phymode curmode) { #define N(a) (sizeof(a)/sizeof(a[0])) const RATE_TABLE *pRateTable; struct TxRateCtrl_s *pRc = &pSib->txRateCtrl; A_UINT8 i, j, hi = 0, count; A_INT8 k; int rateCount, numInfo; HAL_BOOL bFoundDot11Rate_11, bFoundDot11Rate_22; pRateTable = asc->hwRateTable[curmode]; /* Initial rate table size. Will change depending on the working rate set */ pRc->rateTableSize = MAX_TX_RATE_TBL; numInfo = N(pRateTable->info); /* Initialize thresholds according to the global rate table */ for (i = 0 ; (i < pRc->rateTableSize) && (!keepState) && (i < pRateTable->rateCount); i++) { if (i < numInfo) { pRc->state[i].rssiThres = pRateTable->info[i].rssiAckValidMin; } pRc->state[i].per = 0; #if ATH_SUPPORT_VOWEXT /* for RCA */ pRc->state[i].maxAggrSize = MAX_AGGR_LIMIT; #endif } /* Determine the valid rates */ rcInitValidTxMask(pRc); rateCount = pRateTable->rateCount; #ifdef notyet if (wlanIs5211Channel14(pSib)) { rateCount = 2; } #endif count = 0; if (!pRateSet->rs_nrates) { /* No working rate, use valid rates */ for (i = 0; i < rateCount; i++) { /* * If the rate is: * 1. not valid, or * 2. this is an uapsd node but the rate is not an uapsd rate * skip it. */ if (pRateTable->info[i].valid != TRUE) { continue; } #ifdef ATH_SUPPORT_UAPSD_RATE_CONTROL if ((pSib->uapsd) && (pRateTable->info[i].validUAPSD != TRUE)) { continue; } #endif /* ATH_SUPPORT_UAPSD_RATE_CONTROL */ pRc->validRateIndex[count] = i; /* * Copy the static rate series for the correspondig rate * from static rate table to TxRateCtrl_s. */ OS_MEMCPY(pRc->validRateSeries[count], &(pRateTable->info[i].normalSched), MAX_SCHED_TBL); count ++; rcSetValidTxMask(pRc, i, TRUE); hi = A_MAX(hi, i); pSib->rixMap[i] = 0; } pRc->maxValidRate = count; pRc->maxValidTurboRate = pRateTable->numTurboRates; } else { A_UINT8 turboCount; A_UINT64 mask; bFoundDot11Rate_11 = FALSE; bFoundDot11Rate_22 = FALSE; for(k = 0; k < pRateSet->rs_nrates; k++) { // Look for 5.5 mbps if((pRateSet->rs_rates[k] & 0x7F) == 11) { bFoundDot11Rate_11 = TRUE; } // Look for 11 mbps if((pRateSet->rs_rates[k] & 0x7F) == 22) { bFoundDot11Rate_22 = TRUE; } } /* * Use intersection of working rates and valid rates. * if working rates has 6 OFDM and does not have 5.5 and 11 CCKM, use 6. * if working rates has 9 OFDM and does not has 11 CCKM, use 9. */ turboCount = 0; for (i = 0; i < pRateSet->rs_nrates; i++) { for (j = 0; j < rateCount; j++) { if ((pRateSet->rs_rates[i] & 0x7F) == (pRateTable->info[j].dot11Rate & 0x7F)) { #ifdef ATH_SUPPORT_UAPSD_RATE_CONTROL /* * If this is an uapsd node but the rate is not an uapsd rate * skip it. */ if ((pSib->uapsd) && (pRateTable->info[j].validUAPSD != TRUE)) { continue; } #endif /* ATH_SUPPORT_UAPSD_RATE_CONTROL */ if(pRateTable->info[j].valid == TRUE) { rcSetValidTxMask(pRc, j, TRUE); hi = A_MAX(hi, j); pSib->rixMap[j] = i; } else { //To keep rate monotonicity if(pRateTable->info[j].phy == WLAN_PHY_OFDM && ((((pRateSet->rs_rates[i] & 0x7F) == 12) && (!bFoundDot11Rate_11) && (!bFoundDot11Rate_22)) || (((pRateSet->rs_rates[i] & 0x7F) == 18) && !bFoundDot11Rate_22))) { rcSetValidTxMask(pRc, j, TRUE); hi = A_MAX(hi, j); pSib->rixMap[j] = i; } } } } } /* Get actually valid rate index, previous we get it from rate table, * now get rate table which include all working rate, so we need make * sure our valid rate table align with working rate */ mask = pRc->validTxRateMask; for (i = 0; i < pRc->rateTableSize; i ++) { if (mask & ((A_UINT64)1 << i)) { pRc->validRateIndex[count] = i; /* * Copy the static rate series for the correspondig rate * from static rate table to TxRateCtrl_s. */ OS_MEMCPY(pRc->validRateSeries[count], &(pRateTable->info[i].normalSched), MAX_SCHED_TBL); count ++; if (pRateTable->info[i].phy == WLAN_PHY_TURBO) { turboCount ++; } } } pRc->maxValidRate = count; pRc->maxValidTurboRate = turboCount; } /* * Modify the static rate series in TxRateCtrl_s with respect to intersection * rate table. */ for(i = 0 ; i < pRc->maxValidRate; i ++) { k = i; for (j = 5; j < MAX_SCHED_TBL; j ++) { if(j % 8 == 0) { k = i; j = j + 4; continue; } for (; k >= 0; k --) { if(pRc->validRateSeries[i][j] == pRateTable->info[k].rateCode) { break; } } if (k == -1) { pRc->validRateSeries[i][j] = pRc->validRateSeries[i][j-1]; } } } pRc->rateTableSize = hi + 1; pRc->rateMax = A_MIN(hi, pRateTable->initialRateMax); ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL); #undef N }
void aodtv72_classify(void) /* Classify scene type based on FFT analysis and histogram temperatures using empirically defined threshold values. Inputs : global structure odtcurrent_v72 containing current image analysis Outputs : scenetype in structure odtcurrent_v72 is modified SCENE TYPES : EYE REGION CLOUD REGION 0 - clear 0 - uniform 1 - pinhole 1 - embedded center 2 - large 2 - irregular cdo 3 - none 3 - curved band 4 - shear */ { int iok,ixx,iyy,cloudfft,cloudcat,eyefft,eyecat,cwtcat,diffcat; int cbring,cbringval,diffcloudcat; int sceneeye,scenecloud,spiral,spiralmax; int lastcscene,lastescene,cbringvalmax; float xlat,xlon,tempval,lasttno,lasttno12; float eyetemp,cloudtemp,cloudcwt,eyestdv,cloudsyma; float essizeDG=0.0,esdiffDG=0.0; float lat1,lon1,lat2,lon2; float eyecdosize,diffcloudt,cdosize,cdosizex,rmw; float cbringlatmax,cbringlonmax; double curtime,curtimem12,xtime,lastvalidtime; struct odtdata *odthistory; logical cbfound,cbscene,cbgray,shear,irrcdo,landcheck; float cdodiam[6] = { 0.0,85.0,140.0,195.0,250.0,999.0 }; float xpart,ddvor; int cdocat; char cdate[13],*hfilex; FILE *fp; logical embdd=FALSE,checkembc=FALSE; float Ea,Eb,Ec,Ed,Ee,eyeval,Ca,Cb,Cc,Cd,Ce,cloudval; float diffeyecloudt,eyecloudcatdiff,eyecwtcatdiff,cloudcatdiff; float eyepart,cloudpart,cwtpart,diffcat2,lastvalidtno,lastr9,maxtno; float cdomax[7]= { 0.0,0.4,0.4,0.5,0.5,0.6,0.6 }; int diffeyecloudcat; logical foundeye,foundm12; eyetemp=odtcurrent_v72->IR.eyet; eyefft=odtcurrent_v72->IR.eyefft; eyestdv=odtcurrent_v72->IR.eyestdv; cloudtemp=odtcurrent_v72->IR.cloudt; cloudcwt=odtcurrent_v72->IR.cwcloudt; cloudfft=odtcurrent_v72->IR.cloudfft; cloudsyma=odtcurrent_v72->IR.cloudsymave; xlat=odtcurrent_v72->IR.latitude; xlon=odtcurrent_v72->IR.longitude; for(ixx=0;ixx<10;ixx++) { /* compute cloud category */ if((cloudtemp<=ebd_v72[ixx])&&(cloudtemp>ebd_v72[ixx+1])) { cloudcat=ixx; xpart=(cloudtemp-ebd_v72[cloudcat])/(ebd_v72[cloudcat+1]-ebd_v72[cloudcat]); if(cloudcat==0) xpart=0.0; cloudpart=cloudcat+xpart; } /* compute eye category */ if((eyetemp<=ebd_v72[ixx])&&(eyetemp>ebd_v72[ixx+1])) { eyecat=ixx; xpart=(eyetemp-ebd_v72[eyecat])/(ebd_v72[eyecat+1]-ebd_v72[eyecat]); if(eyecat==0) xpart=0.0; eyepart=eyecat+xpart; } /* compute C-W eye category */ if((cloudcwt<=ebd_v72[ixx])&&(cloudcwt>ebd_v72[ixx+1])) { cwtcat=ixx; xpart=(cloudcwt-ebd_v72[cwtcat])/(ebd_v72[cwtcat+1]-ebd_v72[cwtcat]); if(cwtcat==0) xpart=0.0; cwtpart=cwtcat+xpart; } } /* printf("EYE = temp=%f cat=%d part=%f \n",eyetemp,eyecat,eyepart); */ /* printf("CLD = temp=%f cat=%d part=%f \n",cloudtemp,cloudcat,cloudpart); */ /* printf("CWT = temp=%f cat=%d part=%f \n",cloudcwt,cwtcat,cwtpart); */ diffcat=A_MAX(0,A_MAX(cloudcat,cwtcat)-eyecat); diffcloudt=cloudtemp-cloudcwt; diffeyecloudt=eyetemp-cloudtemp; eyecwtcatdiff=cwtpart-eyepart; eyecloudcatdiff=cloudpart-eyepart; cloudcatdiff=cloudpart-cwtpart; diffcloudcat=cloudcat-cwtcat; diffeyecloudcat=cloudcat-eyecat; diffcat2=eyetemp-(A_MIN(cloudtemp,cloudcwt)); curtime=aodtv72_calctime(odtcurrent_v72->IR.date,odtcurrent_v72->IR.time); curtimem12=curtime-0.5; /* determine last Final T# value for curved band/other scene check */ foundeye=FALSE; maxtno=0.0; lastr9=0; lasttno=maxtno; lastvalidtno=lasttno; if((odthistoryfirst_v72==0)||(strlen(hfile_v72)==0)) { foundm12=TRUE; lastescene=3; lastr9=1; if((cwtpart<3.5)&&(osstr_v72<3.5)) { lastcscene=3; lasttno12=osstr_v72; } else { lastcscene=0; lasttno12=A_MAX(osstr_v72,4.0); } } else { odthistory=odthistoryfirst_v72; foundm12=FALSE; lastcscene=3; while(odthistory!=0) { xtime=aodtv72_calctime(odthistory->IR.date,odthistory->IR.time); landcheck=TRUE; if(((oland_v72)&&(odthistory->IR.land==1))||(odthistory->IR.Traw<1.0)) landcheck=FALSE; if((xtime<curtime)&&(landcheck)) { lastvalidtime=xtime; if((xtime>=curtimem12)&&(!foundm12)) { lasttno12=odthistory->IR.Tfinal; foundm12=TRUE; } lasttno=odthistory->IR.Tfinal; lastcscene=odthistory->IR.cloudscene; lastescene=odthistory->IR.eyescene; if(lastescene<=2) foundeye=TRUE; if((lastcscene==4)&&(lastescene==3)) foundeye=FALSE; lastvalidtno=lasttno; lastr9=odthistory->IR.rule9; if(lasttno>maxtno) maxtno=lasttno; } else { if(!landcheck) { /* if over land for more than 12 hours, turn off foundeye */ if((xtime-lastvalidtime)>0.5) { foundeye=FALSE; lasttno=lastvalidtno-(1.0*(xtime-lastvalidtime)); /* printf("lastvalidtno=%f deltatime=%f lasttno=%f\n",lastvalidtno,xtime-lastvalidtime,lasttno); */ } } } odthistory=odthistory->nextrec; } /* check for large break in history file */ if(!foundm12) lasttno12=lasttno; } /* printf("foundm12=%d\n",foundm12); */ /* printf("lasttno12=%f\n",lasttno12); */ /* NEW SCENE IDENTIFICATION SCHEME */ /* NEW EYE SCENE THRESHOLD DETERMINATION */ Ec=0.0; Ee=0.0; Ea=1.0-((eyefft-2)*0.1); Eb=-(eyepart*0.5); if(eyestdv>10.0) Ec=0.50; /* Ed=eyecloudcatdiff*0.75; */ Ed=(eyecloudcatdiff*0.25)+(eyecwtcatdiff*0.50); /* new */ /* printf("Ed=%f\n",Ed); */ /* printf("maxtno=%f Ee=%f\n",maxtno,Ee); */ if((foundm12)&&(lastescene<3)&&(maxtno>5.0)) Ee=Ee+0.25; /* printf("Ee=%f\n",Ee); */ /* if(lasttno12<3.5) Ee=Ee-1.0; */ if(lasttno12<=4.5) Ee=A_MAX(-1.0,lasttno12-4.5); /* new */ /* printf("lasttno12=%f Ee=%f\n",lasttno12,Ee); */ if((lastr9>0)&&(lasttno<4.0)) Ee=Ee-0.5; /* new */ /* printf("Ee=%f\n",Ee); */ eyeval=Ea+Eb+Ec+Ed+Ee; sceneeye=3; /* NO EYE */ if(eyeval>=0.50) sceneeye=0; /* EYE */ /* if(eyeval>=0.00) sceneeye=5; / OBSCURED EYE / if(eyeval>=1.50) sceneeye=4; / RAGGED EYE / if(eyeval>=3.50) sceneeye=0; / CLEAR EYE / */ /* printf("eyeval= %f sceneeye=%d \n",eyeval,sceneeye); */ eyecdosize=0.0; if(rmwsizeman_v72>0) { /* printf("RMW SIZE=%d\n",rmwsizeman_v72); */ odtcurrent_v72->IR.rmw=(float)rmwsizeman_v72; eyecdosize=(float)rmwsizeman_v72-1.0; /* manually input eye size */ } else { iok=aodtv72_rmw(&rmw,&eyecdosize); odtcurrent_v72->IR.rmw=rmw; } /* LARGE EYE CHECKS */ if((sceneeye==0)&&(eyecdosize>=45.0)) sceneeye=2; /* large eye */ /* NEW CLOUD SCENE THRESHOLD DETERMINATION */ shear=FALSE; irrcdo=FALSE; cbscene=TRUE; cbgray=TRUE; Cc=0.0; Cd=0.5; /* changed to 0.5 */ Ce=0.0; Ca=cwtpart*0.25; Cb=cloudpart*0.25; if(cloudfft<=2) Cc=A_MIN(1.50,cwtpart*0.25); if(lastcscene>=3) Cd=-0.50; /* printf("cwtpart=%f lasttno12=%f\n",cwtpart,lasttno12); */ if(cwtpart>2.0) { /* new */ if(lasttno12>=2.5) { if(sceneeye==0) Ce=A_MIN(1.00,lasttno12-2.5); if(lasttno12>=3.5) Ce=Ce+1.00; } if((foundm12)&&(foundeye)) Ce=Ce+1.25; } cloudval=Ca+Cb+Cc+Cd+Ce; if(cloudval<0.0) shear=TRUE; /* SHEAR */ if(cloudval>=0.00) cbscene=TRUE; /* CURVED BAND (gray) */ if(cloudval>=1.00) { cbscene=TRUE; /* CURVED BAND (gray) */ /* check for irregular CDO */ if((diffcat2<0.0)&&(cloudsyma>40.0)) { irrcdo=TRUE; /* IRREGULAR CDO */ } } if((cloudval>=2.00)&&(cloudval<3.00)) { cbscene=TRUE; /* CURVED BAND (gray) */ /* check for irregular CDO */ /* if((diffcloudcat<0)&&(diffcloudt>8.0)&&(cloudsyma>30.0)) { */ if((diffcat2<0.0)&&(cloudsyma>30.0)) { irrcdo=TRUE; /* IRREGULAR CDO */ } if(cwtcat>=3) { /* if xcwt>3.0 try black/white CB check */ if((diffcloudcat>0)&&(diffcloudt<-8.0)) cbgray=FALSE; /* CURVED BAND (black/white) */ /* check for large/ragged eye */ if((sceneeye==0)||((eyepart>1.00)&&(diffeyecloudcat>=2.00))) cbscene=FALSE; /* EYE */ /* check for CDO */ if((cloudcatdiff<=0.0)&&(eyecwtcatdiff<1.00)) cbscene=FALSE; /* CDO */ } } if(cloudval>=3.00) { cbscene=FALSE; /* CDO */ /* check for irregular CDO */ if((diffcloudcat<0)&&(diffcloudt>8.0)&&(cloudsyma>30.0)) { irrcdo=TRUE; /* IRREGULAR CDO */ cbscene=TRUE; } } /* EMBEDDED CENTER CHECK */ if((cloudtemp<cloudcwt)&&(cloudcwt<eyetemp)) checkembc=TRUE; if((!cbscene)&&(checkembc)) { tempval=ebd_v72[cwtcat+1]+273.16; aodtv72_logspiral(xlat,xlon,tempval,1,&spiral,&lat1,&lon1); if((spiral>=8)&&(spiral<20)) embdd=TRUE; /* printf(" EMBDD : cwtcat=%d spiral=%d \n",cwtcat,spiral); */ } /* printf("cloudval= %f shear=%d cbscene=%d cbgray=%d irrcdo=%d \n",cloudval,shear,cbscene,cbgray,irrcdo); */ (void)aodtv72_julian2cmonth(odtcurrent_v72->IR.date,cdate); /* printf("%9s %6d %4.1f %4.1f %2d %2d %5.1f %5.1f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %2d %2d %4.1f %4.1f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %6.2f %7.2f %3.1f \n",cdate,odtcurrent_v72->IR.time, cloudpart,cwtpart,cloudfft,diffcloudcat,diffcloudt,cloudsyma,Ca,Cb,0.0,Cc,Cd,Ce,cloudval, eyefft,diffeyecloudcat,eyepart,eyestdv,Ea,Eb,Ec,Ed,Ee,eyeval,xlat,xlon,lasttno); */ /* CLASSIFY CLOUD REGION */ cbring=0; cbringval=0; cbringvalmax=0; cbringlatmax=xlat; cbringlonmax=xlon; L100: if(cbscene) { if(shear) { sceneeye=3; /* NO EYE */ scenecloud=4; /* SHEAR */ tempval=ebd_v72[3]+273.16; aodtv72_cdoshearcalc(xlat,xlon,tempval,3,&essizeDG,&esdiffDG); eyecdosize=A_MAX(4.0,essizeDG); } else if(irrcdo) { sceneeye=3; /* NO EYE */ scenecloud=2; /* IRREGULAR CDO */ } else { cbfound=FALSE; L200: if(cbgray) { /* perform Curved Band analysis */ ixx=4; /* start with LIGHT GRAY */ while((ixx>=2)&&(!cbfound)) { tempval=ebd_v72[ixx]+273.16; aodtv72_logspiral(xlat,xlon,tempval,1,&spiral,&lat1,&lon1); /* printf("BD level=%d spiral=%d\n",ixx,spiral); */ if((spiral>=8)||(ixx==2)) { /* 10 = .375% -- 10 ==> 9 arcs of 15 degrees */ if(spiral>25) { if(ixx==4) { cbgray=FALSE; goto L200; } else { ixx=0; } } else { if((ixx==2)&&(spiral<7)) { /* 7 = .25% -- 10 ==> 6 arcs of 15 degrees */ /* probably shear */ cbfound=FALSE; shear=TRUE; goto L100; } else { cbfound=TRUE; } } } else { ixx--; } } } else { /* try BLACK and WHITE rings */ cbscene=FALSE; ixx=6; while((ixx>4)&&(!cbfound)) { tempval=ebd_v72[ixx]+273.16; aodtv72_logspiral(xlat,xlon,tempval,1,&spiral,&lat1,&lon1); if((spiral>=9)&&(spiral<=25)) { cbfound=TRUE; } else { ixx--; } } } if(cbfound) { /* found curved band scenes */ cbring=ixx; cbringval=spiral; sceneeye=3; /* NO EYE */ scenecloud=3; /* CURVED BAND */ /* search for maximum curved band analysis location within 1-degree box */ tempval=ebd_v72[cbring]+273.16; if(osearch_v72) { aodtv72_logspiral(xlat,xlon,tempval,2,&spiralmax,&lat2,&lon2); cbringvalmax=spiralmax; cbringlatmax=lat2; cbringlonmax=lon2; } } else { /* did not find curved band scenes, mark as non-eye/eye scene */ scenecloud=0; cbscene=FALSE; embdd=FALSE; /* redundant declaration */ goto L100; } } } else { scenecloud=0; /* UNIFORM */ if(embdd) scenecloud=1; /* EMBEDDED CENTER */ /* PINHOLE EYE TEST */ /* printf("sceneeye=%d diffeyecloudcat=%d eyefft=%d cwtpart=%f scenecloud=%d cloudfft=%d lasttno12=%f\n", sceneeye,diffeyecloudcat,eyefft,cwtpart,scenecloud,cloudfft,lasttno12); */ if((rmwsizeman_v72>0)&&(rmwsizeman_v72<5.0)) sceneeye=1; if((eyeval>-0.25)&&(eyeval<1.50)&&(diffeyecloudcat>=2)&&(eyefft<=2)&& (cwtpart>6.0)&&(scenecloud<=1)&&(cloudfft<=4)&&(lasttno12>=3.5)) { sceneeye=1; /* PINHOLE EYE CHECK */ } } if((scenecloud<=2)&&(sceneeye==3)) { /* for CDO TESTS */ for(ixx=2;ixx<=6;ixx++) { /* DG,MG,LG,B,W */ tempval=ebd_v72[ixx]+273.16; /* printf("xlat=%f xlon=%f tempval=%f\n",xlat,xlon,tempval); */ aodtv72_cdoshearcalc(xlat,xlon,tempval,1,&cdosize,&cdosizex); /* printf("CDO : ixx=%d cdosize=%f cdosize/111=%f \n",ixx,cdosize,cdosize/111.0); */ if(ixx==2) eyecdosize=cdosize; } } odtcurrent_v72->IR.eyescene=sceneeye; odtcurrent_v72->IR.cloudscene=scenecloud; odtcurrent_v72->IR.eyesceneold=-1; odtcurrent_v72->IR.cloudsceneold=-1; odtcurrent_v72->IR.eyecdosize=eyecdosize; odtcurrent_v72->IR.ringcb=cbring; odtcurrent_v72->IR.ringcbval=cbringval; odtcurrent_v72->IR.ringcbvalmax=cbringvalmax; odtcurrent_v72->IR.ringcblatmax=cbringlatmax; odtcurrent_v72->IR.ringcblonmax=cbringlonmax; }
int aodtv72_calcscene(void) /* Perform Fast Fourier Transform (FFT) analysis and determine scene type via empirically defined threshold values. Inputs : global structure odtcurrent_v72 containing current intensity values Outputs : various elements within structure odtcurrent_v72 Return : -41 : error with FFT routine -51 : cloud temperature value <-100C or >+40C 0 : o.k. */ { int nbin=64,iok,a,b,bptr; int ixx,iyy,izz,iscene,idxcnt,maxsecd2,sxscnt; int *sectorcnt,cnteye; float bd[534],cbd[534],tbd[534]; float radb,rade,radeye,teye,dx2,eyecnt,rngcnt; float xangle,xdist,xtemp,slice; float *sectordiffa,*sectormin; float **sector,*eyearr,*sxs,sectang1,sectang2; float *avex,*stdvx,*skewx,*xs,*i2; float Aaveext,Astdvext,Askewext,Aavesym,Astdvsym,Askewsym; float Eaveeye,Estdveye,Eskeweye; float alsdist,alsradb,alsrade,alssum,alst,alscnt; struct ringdata *tcirc; float eyetemp; float eyecdosize,rmw; int eyecat; char cdate[13],*hfilex; FILE *fp; /* initialize temperature histogram bin values */ for(iyy=0;iyy<nbin;iyy++) { bd[iyy]=26.0-(float)iyy*2.0; } /* set up arrays for FFT ananlysis. iscene=0 will perform FFT for cloud top region while iscene=1 will perform FFT for eye region */ for(iscene=0;iscene<=1;iscene++) { for(iyy=0;iyy<nbin;iyy++) { cbd[iyy]=0.0; tbd[iyy]=0.0; } /* define start and end radii values */ if(iscene==0) { /* CLOUD TOP */ radb=(float)kstart_v72; rade=(float)kend_v72; } else { /* EYE REGION */ radb=0.0; rade=(float)kstart_v72; } /* load arrays for FFT analysis */ tcirc=tcircfirst_v72; while(tcirc!=0) { if((tcirc->dist>=radb)&&(tcirc->dist<=rade)) { teye=(tcirc->temp - 273.16); for(ixx=0;ixx<(nbin-1);ixx++) { if((teye<=bd[ixx])&&(teye>=bd[ixx+1])) { cbd[ixx]=cbd[ixx]+1.0; tbd[ixx]=tbd[ixx]+teye; } } } tcirc=tcirc->nextrec; } /* perform FFT analysis */ iok=aodtv72_fft(cbd,&dx2,&idxcnt); if(iok<0) return -41; /* assign variables based upon region being analyzed */ if(iscene==0) { rngcnt=idxcnt; /* CLOUD TOP */ } else { eyecnt=idxcnt; /* EYE REGION */ } } /* compute various cloud and eye region parameters for classification scheme */ /* allocate memory for arrays */ a=sizeof(int); sectorcnt=(int *)calloc((size_t)maxsec,a); b=sizeof(float); bptr=sizeof(float*); sectormin=(float *)calloc((size_t)maxsec,b); sector=(float **)calloc((size_t)maxsec,bptr); for(ixx=0;ixx<maxsec;ixx++) { sector[ixx]=(float *)calloc((size_t)maxsecA,b); } eyearr=(float *)calloc((size_t)maxsecA,b); for(ixx=0;ixx<maxsec;ixx++) { sectorcnt[ixx]=0; sectormin[ixx]=999.0; for(iyy=0;iyy<maxsecA;iyy++) { sector[ixx][iyy]=-999.99; } } /* load array for analysis */ radb=(float)kstart_v72; rade=(float)kend_v72; radeye=(float)kstart_v72; tcirc=tcircfirst_v72; slice=360.0/(float)maxsec; cnteye=0; while(tcirc!=0) { xangle=tcirc->angle; xdist=tcirc->dist; xtemp=tcirc->temp-273.16; if(xangle==360.0) xangle=0.0; ixx=0; if((xdist>=radb)&&(xdist<=rade)) { while(ixx<maxsec) { sectang1=A_MAX(0.0,(float)ixx*slice); sectang2=A_MIN(360.0,(float)(ixx+1)*slice); if((xangle>=sectang1)&&(xangle<sectang2)) { sector[ixx][sectorcnt[ixx]]=xtemp; sectorcnt[ixx]++; ixx=maxsec; } else { ixx++; } } } if((xdist>=0)&&(xdist<=radeye)) { eyearr[cnteye]=xtemp; cnteye++; } /* the following will count all values w/in the different BD curve ranges for the whole cloud region so we can examine the structure of the cloud region later */ tcirc=tcirc->nextrec; } /* position annulus at CW max temp distance and determine mean temp w/in +/- 40km from this distance. If dist is less than 68km from center, annulus will start at 28km */ alscnt=0; alssum=0.0; alsdist=(float)odtcurrent_v72->IR.cwring; alsradb=A_MAX(28.0,alsdist-40.0); alsrade=A_MAX(108.0,alsdist+40.0); tcirc=tcircfirst_v72; while(tcirc!=0) { xdist=tcirc->dist; xtemp=tcirc->temp-273.16; if((xdist>=alsradb)&&(xdist<=alsrade)) { alssum=alssum+xtemp; alscnt++; } tcirc=tcirc->nextrec; } alst=alssum/(float)alscnt; odtcurrent_v72->IR.cloudt=alst; if((odtcurrent_v72->IR.cloudt<-100.0)||(odtcurrent_v72->IR.cloudt>40.0)) return -51; /* determine "minimum" temperature for each sector. This is not the actual lowest temperature, but instead is the temperature value of the coldest 90% of the values within the sector. This will, hopefully, eliminate some outliers */ /* allocate memory */ xs=(float *)calloc((size_t)maxsecA,b); i2=(float *)calloc((size_t)maxsecA,b); sxs=(float *)calloc((size_t)maxsecA,b); for(ixx=0;ixx<maxsec;ixx++) { sxscnt=sectorcnt[ixx]; for(iyy=0;iyy<sxscnt;iyy++) { sxs[iyy]=sector[ixx][iyy]; } aodtv72_xxsort(sxs,xs,i2,sxscnt); izz=sxscnt-(sxscnt*.1); sectormin[ixx]=xs[izz]; } /* free memory */ free(sxs); free(i2); free(xs); /* determine averages, standard deviations and skews for each sector */ /* allocate memory */ avex=(float *)calloc((size_t)maxsec,b); stdvx=(float *)calloc((size_t)maxsec,b); skewx=(float *)calloc((size_t)maxsec,b); sectordiffa=(float *)calloc((size_t)maxsec,b); for (ixx=0;ixx<maxsec;ixx++) { aodtv72_calcskew(sector[ixx],sectorcnt[ixx],&avex[ixx],&stdvx[ixx],&skewx[ixx]); } aodtv72_calcskew(avex,maxsec,&Aaveext,&Astdvext,&Askewext); odtcurrent_v72->IR.cloudt2=Aaveext; /* these are used to examine symmetry of convection */ maxsecd2=maxsec/2; for (ixx=0;ixx<maxsecd2;ixx++) { sectordiffa[ixx]=A_ABS(avex[ixx]-avex[maxsecd2+ixx]); } aodtv72_calcskew(sectordiffa,maxsecd2,&Aavesym,&Astdvsym,&Askewsym); /* these are used to examine properties of the eye region */ aodtv72_calcskew(eyearr,cnteye,&Eaveeye,&Estdveye,&Eskeweye); odtcurrent_v72->IR.eyestdv=Estdveye; odtcurrent_v72->IR.cloudsymave=Aavesym; odtcurrent_v72->IR.eyefft=(int)eyecnt; odtcurrent_v72->IR.cloudfft=(int)rngcnt; /* free memory */ free(sectordiffa); free(skewx); free(stdvx); free(avex); for(ixx=0;ixx<maxsec;ixx++) { free(sector[ixx]); } free(sector); free(eyearr); free(sectormin); free(sectorcnt); /* assign scenetype value in structure odtcurrent_v72 */ aodtv72_classify(); return 0; }
int aodtv72_rmw(float *rmw,float *eyesize) /* Determine radius of maximum wind based upon Jim Kossin's regression based scheme Inputs : ix0 - element location of center point iy0 - line location of center point Outputs : rmw - radius of maximum wind distance eyesize - eye size radius (km) -1 = error/eyewall not found 0 = radius found */ { int ixmin,ixmax,iymin,iymax; int ixc,iyc,i,ix,iy,idx1,idy1,idx2,idy2; float dx1,dx2,dy1,dy2,dav,xlat,xlon,xclat,xclon,xangle; float tcrit=228.0,warm=223.0;; /* calculate cursorx/cursory from numx/numy... values should be 0.5*numx/y */ ixc=areadata_v72->numx/2; iyc=areadata_v72->numy/2; ixmax=A_MIN(areadata_v72->numx,ixc+320); ixmin=A_MAX(0,ixc-320); iymax=A_MIN(areadata_v72->numy,iyc+240); iymin=A_MAX(0,iyc-240); if(odtcurrent_v72->IR.cloudt>=warm) { tcrit=(odtcurrent_v72->IR.eyet+(2.0*odtcurrent_v72->IR.cloudt))/3.0; } *rmw=-99.9; *eyesize=-99.9; /* iterate five times */ for(i=0;i<5;i++) { ix=ixc; while(areadata_v72->temp[iyc][ix]>tcrit) { ix=ix-1; if(ix==ixmin) { return -1; } } idx1=ix; ix=ixc; while(areadata_v72->temp[iyc][ix]>tcrit) { ix=ix+1; if(ix==ixmax) { return -1; } } idx2=ix; iy=iyc; while(areadata_v72->temp[iy][ixc]>tcrit) { iy=iy-1; if(iy==iymin) { return -1; } } idy1=iy; iy=iyc; while(areadata_v72->temp[iy][ixc]>tcrit) { iy=iy+1; if(iy==iymax) { return -1; } } idy2=iy; ixc=(int)((((float)(idx1+idx2))/2.0)); iyc=(int)((((float)(idy1+idy2))/2.0)); } xclat=areadata_v72->lat[iyc][ixc]; xclon=areadata_v72->lon[iyc][ixc]; xlat=areadata_v72->lat[iyc][idx1]; xlon=areadata_v72->lon[iyc][idx1]; aodtv72_distance(xlat,xlon,xclat,xclon,1,&dx1,&xangle); xlat=areadata_v72->lat[iyc][idx2]; xlon=areadata_v72->lon[iyc][idx2]; aodtv72_distance(xlat,xlon,xclat,xclon,1,&dx2,&xangle); xlat=areadata_v72->lat[idy1][ixc]; xlon=areadata_v72->lon[idy1][ixc]; aodtv72_distance(xlat,xlon,xclat,xclon,1,&dy1,&xangle); xlat=areadata_v72->lat[idy2][ixc]; xlon=areadata_v72->lon[idy2][ixc]; aodtv72_distance(xlat,xlon,xclat,xclon,1,&dy2,&xangle); dav=(dx1+dx2+dy1+dy2)/4.0; if(dav>0.0) { *rmw=2.8068+(0.8361*dav); /* Howard's coeffs */ *eyesize=dav; } return 0; }
/* * Context: softIRQ (tasklet) */ void ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb, const struct ath_buf *bf, int tx, u_int64_t mactime, struct ath_softc *sc) { struct ieee80211vap *vap, *next; struct ath_desc *ds = bf->bf_desc; int noise = 0, antenna = 0, ieeerate = 0; u_int32_t rssi = 0; u_int8_t pkttype = 0; unsigned int mon_hdrspace = A_MAX(sizeof(struct ath_tx_radiotap_header), (A_MAX(sizeof(struct wlan_ng_prism2_header), ATHDESC_HEADER_SIZE))); if ((skb_headroom(skb) < mon_hdrspace) && pskb_expand_head(skb, mon_hdrspace, 0, GFP_ATOMIC)) { printk("No headroom for monitor header - %s:%d %s\n", __FILE__, __LINE__, __func__); return; } if (tx) { rssi = bf->bf_dsstatus.ds_txstat.ts_rssi; antenna = bf->bf_dsstatus.ds_txstat.ts_antenna; ieeerate = sc->sc_hwmap[bf->bf_dsstatus.ds_txstat.ts_rate].ieeerate; } else { rssi = bf->bf_dsstatus.ds_rxstat.rs_rssi; antenna = bf->bf_dsstatus.ds_rxstat.rs_antenna; ieeerate = sc->sc_hwmap[bf->bf_dsstatus.ds_rxstat.rs_rate].ieeerate; } noise = bf->bf_channoise; /* XXX locking */ for (vap = TAILQ_FIRST(&ic->ic_vaps); vap != NULL; vap = next) { struct sk_buff *skb1; struct net_device *dev = vap->iv_dev; struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; u_int8_t dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; next = TAILQ_NEXT(vap, iv_next); /* If we have rx'd an error frame... */ if (!tx && bf->bf_dsstatus.ds_rxstat.rs_status != 0) { /* Discard PHY errors if necessary */ if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_PHY) { if (vap->iv_monitor_phy_errors == 0) continue; } /* Discard CRC errors if necessary */ if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_CRC) { if (vap->iv_monitor_crc_errors == 0) continue; } /* Accept PHY, CRC and decrypt errors. Discard the rest. */ if (bf->bf_dsstatus.ds_rxstat.rs_status &~ (HAL_RXERR_DECRYPT | HAL_RXERR_MIC | HAL_RXERR_PHY | HAL_RXERR_CRC)) continue; /* We can't use addr1 to determine direction at this point */ pkttype = PACKET_HOST; } else { /* * The frame passed its CRC, so we can rely * on the contents of the frame to set pkttype. */ if (tx) pkttype = PACKET_OUTGOING; else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { if (IEEE80211_ADDR_EQ(wh->i_addr1, dev->broadcast)) pkttype = PACKET_BROADCAST; else pkttype = PACKET_MULTICAST; } else pkttype = PACKET_HOST; } if (vap->iv_opmode != IEEE80211_M_MONITOR || vap->iv_state != IEEE80211_S_RUN) continue; if (vap->iv_monitor_nods_only && dir != IEEE80211_FC1_DIR_NODS) { /* don't rx fromds, tods, or dstods packets */ continue; } skb1 = skb_copy(skb, GFP_ATOMIC); if (skb1 == NULL) { /* XXX stat+msg */ continue; } ieee80211_skb_copy_noderef(skb, skb1); if (vap->iv_monitor_txf_len && tx) { /* truncate transmit feedback packets */ skb_trim(skb1, vap->iv_monitor_txf_len); skb_reset_network_header(skb1); } switch (vap->iv_dev->type) { case ARPHRD_IEEE80211: break; case ARPHRD_IEEE80211_PRISM: { struct wlan_ng_prism2_header *ph; if (skb_headroom(skb1) < sizeof(struct wlan_ng_prism2_header)) { ieee80211_dev_kfree_skb(&skb1); break; } ph = (struct wlan_ng_prism2_header *) skb_push(skb1, sizeof(struct wlan_ng_prism2_header)); memset(ph, 0, sizeof(struct wlan_ng_prism2_header)); ph->msgcode = DIDmsg_lnxind_wlansniffrm; ph->msglen = sizeof(struct wlan_ng_prism2_header); strncpy(ph->devname, dev->name, sizeof(ph->devname)); ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ph->hosttime.status = 0; ph->hosttime.len = 4; ph->hosttime.data = jiffies; /* Pass up tsf clock in mactime */ /* NB: the prism mactime field is 32bit, so we lose TSF precision here */ ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ph->mactime.status = 0; ph->mactime.len = 4; ph->mactime.data = mactime; ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ph->istx.status = 0; ph->istx.len = 4; ph->istx.data = tx ? P80211ENUM_truth_true : P80211ENUM_truth_false; ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ph->frmlen.status = 0; ph->frmlen.len = 4; ph->frmlen.data = skb->len; ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ph->channel.status = 0; ph->channel.len = 4; ph->channel.data = ieee80211_mhz2ieee(ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags); ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ph->rssi.status = 0; ph->rssi.len = 4; ph->rssi.data = rssi; ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ph->noise.status = 0; ph->noise.len = 4; ph->noise.data = noise; ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ph->signal.status = 0; ph->signal.len = 4; ph->signal.data = rssi + noise; ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ph->rate.status = 0; ph->rate.len = 4; ph->rate.data = ieeerate; break; } case ARPHRD_IEEE80211_RADIOTAP: { if (tx) { struct ath_tx_radiotap_header *th; if (skb_headroom(skb1) < sizeof(struct ath_tx_radiotap_header)) { printk("%s:%d %s\n", __FILE__, __LINE__, __func__); ieee80211_dev_kfree_skb(&skb1); break; } th = (struct ath_tx_radiotap_header *) skb_push(skb1, sizeof(struct ath_tx_radiotap_header)); memset(th, 0, sizeof(struct ath_tx_radiotap_header)); th->wt_ihdr.it_version = 0; th->wt_ihdr.it_len = cpu_to_le16(sizeof(struct ath_tx_radiotap_header)); th->wt_ihdr.it_present = cpu_to_le32(ATH_TX_RADIOTAP_PRESENT); /* radiotap's TSF field is the full 64 bits, so we don't lose * any TSF precision when using radiotap */ th->wt_tsft = cpu_to_le64(mactime); th->wt_flags = 0; th->wt_rate = ieeerate; th->wt_antenna = antenna; th->wt_pad = 0; if (bf->bf_dsstatus.ds_txstat.ts_status & HAL_TXERR_XRETRY) th->wt_txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); th->wt_dataretries = bf->bf_dsstatus.ds_txstat.ts_shortretry + bf->bf_dsstatus.ds_txstat.ts_longretry; } else { struct ath_rx_radiotap_header *th; if (skb_headroom(skb1) < sizeof(struct ath_rx_radiotap_header)) { printk("%s:%d %s\n", __FILE__, __LINE__, __func__); ieee80211_dev_kfree_skb(&skb1); break; } th = (struct ath_rx_radiotap_header *) skb_push(skb1, sizeof(struct ath_rx_radiotap_header)); memset(th, 0, sizeof(struct ath_rx_radiotap_header)); th->wr_ihdr.it_version = 0; th->wr_ihdr.it_len = cpu_to_le16(sizeof(struct ath_rx_radiotap_header)); th->wr_ihdr.it_present = cpu_to_le32(ATH_RX_RADIOTAP_PRESENT); if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) th->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; if (bf->bf_dsstatus.ds_rxstat.rs_status & HAL_RXERR_CRC) th->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; if (skb->len >= IEEE80211_CRC_LEN) th->wr_flags |= IEEE80211_RADIOTAP_F_FCS; th->wr_rate = ieeerate; th->wr_chan_freq = cpu_to_le16(ic->ic_curchan->ic_freq); /* Define the channel flags for radiotap */ switch (sc->sc_curmode) { case IEEE80211_MODE_11A: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_A); break; case IEEE80211_MODE_TURBO_A: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_TA); break; case IEEE80211_MODE_11B: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_B); break; case IEEE80211_MODE_11G: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_G); break; case IEEE80211_MODE_TURBO_G: th->wr_chan_flags = cpu_to_le16(IEEE80211_CHAN_TG); break; default: th->wr_chan_flags = 0; /* unknown */ break; } th->wr_dbm_antnoise = (int8_t) noise; th->wr_dbm_antsignal = th->wr_dbm_antnoise + rssi; th->wr_antenna = antenna; th->wr_antsignal = rssi; th->wr_tsft = cpu_to_le64(mactime); } break; } case ARPHRD_IEEE80211_ATHDESC: { if (skb_headroom(skb1) < ATHDESC_HEADER_SIZE) { printk("%s:%d %s\n", __FILE__, __LINE__, __func__); ieee80211_dev_kfree_skb(&skb1); break; } memcpy(skb_push(skb1, ATHDESC_HEADER_SIZE), ds, ATHDESC_HEADER_SIZE); break; } default: break; } if (skb1 != NULL) { if (!tx && (skb1->len >= IEEE80211_CRC_LEN) && (vap->iv_dev->type != ARPHRD_IEEE80211_RADIOTAP)) { /* Remove FCS from end of RX frames when * delivering to non-Radiotap VAPs. */ skb_trim(skb1, skb1->len - IEEE80211_CRC_LEN); } skb1->dev = dev; /* NB: deliver to wlanX */ skb_reset_mac_header(skb1); skb1->ip_summed = CHECKSUM_NONE; skb1->pkt_type = pkttype; skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ if (netif_rx(skb1) == NET_RX_DROP) { /* If netif_rx dropped the packet because * device was too busy, reclaim the ref. in * the skb. */ if (SKB_CB(skb1)->ni != NULL) ieee80211_unref_node(&SKB_CB(skb1)->ni); vap->iv_devstats.rx_dropped++; } vap->iv_devstats.rx_packets++; vap->iv_devstats.rx_bytes += skb1->len; } } }
/* * Update the SIB's rate control information * * This should be called when the supported rates change * (e.g. SME operation, wireless mode change) * * It will determine which rates are valid for use. */ void rcSibUpdate(struct ath_softc *sc, struct ath_node *an, A_BOOL keepState) { struct atheros_node *pSib = ATH_NODE_ATHEROS(an); struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc; const RATE_TABLE *pRateTable = asc->hwRateTable[sc->sc_curmode]; struct ieee80211_rateset *pRateSet = &an->an_node.ni_rates; struct TxRateCtrl_s *pRc = &pSib->txRateCtrl; A_UINT8 i, j, hi = 0,count; int rateCount; /* Initial rate table size. Will change depending on the working rate set */ pRc->rateTableSize = MAX_TX_RATE_TBL; /* Initialize thresholds according to the global rate table */ for (i = 0 ; (i < pRc->rateTableSize) && (!keepState); i++) { pRc->state[i].rssiThres = pRateTable->info[i].rssiAckValidMin; pRc->state[i].per = 0; } /* Determine the valid rates */ rcInitValidTxMask(pRc); rateCount = pRateTable->rateCount; #ifdef notyet if (wlanIs5211Channel14(pSib)) { rateCount = 2; } #endif count = 0; if (!pRateSet->rs_nrates) { /* No working rate, use valid rates */ for (i = 0; i < rateCount; i++) { if (pRateTable->info[i].valid == TRUE) { pRc->validRateIndex[count] = i; count ++; rcSetValidTxMask(pRc, i, TRUE); hi = A_MAX(hi, i); pSib->rixMap[i] = 0; } } pRc->maxValidRate = count; pRc->maxValidTurboRate = pRateTable->numTurboRates; } else { A_UINT8 turboCount; A_UINT32 mask; /* Use intersection of working rates and valid rates */ turboCount = 0; for (i = 0; i < pRateSet->rs_nrates; i++) { for (j = 0; j < rateCount; j++) { if (((pRateSet->rs_rates[i] & 0x7F) == (pRateTable->info[j].dot11Rate & 0x7F)) && (pRateTable->info[j].valid == TRUE)) { rcSetValidTxMask(pRc, j, TRUE); hi = A_MAX(hi, j); pSib->rixMap[j] = i; } } } /* Get actually valid rate index, previous we get it from rate table, * now get rate table which include all working rate, so we need make * sure our valid rate table align with working rate */ mask = pRc->validTxRateMask; for (i = 0; i < pRc->rateTableSize; i ++) { if (mask & (1 << i)) { pRc->validRateIndex[count] = i; count ++; if (pRateTable->info[i].phy == WLAN_PHY_TURBO) { turboCount ++; } } } pRc->maxValidRate = count; pRc->maxValidTurboRate = turboCount; } pRc->rateTableSize = hi + 1; pRc->rateMax = A_MIN(hi, pRateTable->initialRateMax); ASSERT(pRc->rateTableSize <= MAX_TX_RATE_TBL); }