/* 
 * 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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 4
0
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);

}
Exemplo n.º 5
0
/*
 *  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
}
Exemplo n.º 6
0
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;

}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
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;
		}
	}
}
Exemplo n.º 10
0
/*
 *  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);
}