Asked by:
A little question in the 'auto_count' of 'cca.hpp'

Question
-
Hello all,
I have been working on a school task that may well use the 'cca.hpp' to make sequence synchronized, but I got confused on the code given by Sora, mainly the value of 'auto_count'.
First it was set to zero:
sync_state = no_energy; auto_count = 0;
After that,
if ( sync_state == no_energy ) { // auto-correlation senssing int iAutoCorr = GetAutoCorrelation ( pi>>2, corr_r, corr_i ); int iEnergy = GetEnergy ( pi>>2 ); // save sample in the accumulator sample_his << (pi>>2); sense_count += 4; if ( (iEnergy > (int)cca_pwr_threshold) && iAutoCorr >= (iEnergy - (iEnergy >> 3))) { auto_count++; // any case we are sensing high, we reset the sense counter sense_count = 0; // if remaining in plateau for 4*4=16 samples if (auto_count >= 4) { _dump_text ( "power detected!\n" );
I thought that there would be no way that 'auto_count>=4' can be true, because after the determination the ‘auto_count’ will be set to zero again:
else { auto_count = 0; }
the whole 'cca.hpp' shows below:
#pragma once #include <sora.h> #include <soratime.h> #include <dspcomm.h> #include "ieee80211facade.hpp" /*********************************************** TEnergyDetect ************************************************/ DEFINE_LOCAL_CONTEXT(TEnergyDetect, CF_11CCA, CF_Error); template<TFILTER_ARGS> class TEnergyDetect : public TFilter<TFILTER_PARAMS> { static const uint win_len = 8; // 8*4 samples, roughly 1us static const uint min_sensing_samples = 32; // 32*4 samples, 3 us static const uint max_sensing_samples = 100; // 100*4 samples, roughly 10us CTX_VAR_RO (uint, cca_pwr_threshold ); CTX_VAR_RW (uint, cca_pwr_reading ); CTX_VAR_RW (CF_11CCA::CCAState, cca_state ); CTX_VAR_RW (ulong, error_code ); uint average_energy_; uint window_[win_len]; uint idx_; uint count_; public: DEFINE_IPORT(COMPLEX16, 4); DEFINE_OPORT(COMPLEX16, 4); protected: FINL void __init () { average_energy_ = 0; memset ( window_, 0, sizeof(window_)); idx_ = 0; count_ = 0; } public: REFERENCE_LOCAL_CONTEXT(TEnergyDetect ); STD_TFILTER_CONSTRUCTOR(TEnergyDetect ) BIND_CONTEXT(CF_11CCA::cca_pwr_threshold, cca_pwr_threshold) BIND_CONTEXT(CF_11CCA::cca_pwr_reading, cca_pwr_reading) BIND_CONTEXT(CF_11CCA::cca_state, cca_state) BIND_CONTEXT(CF_Error::error_code, error_code) { __init (); } STD_TFILTER_RESET() { __init (); } STD_TFILTER_FLUSH() { } BOOL_FUNC_PROCESS (ipin) { while (ipin.check_read()) { const vcs& pi = cast_ref<vcs>(ipin.peek ()); // Computer the power average // Average over 32 samples vi power = hadd (shift_right (SquaredNorm (pi), 5)); uint ave_power = (uint) power[0]; average_energy_ = average_energy_ - window_[idx_] + ave_power; window_[idx_] = ave_power; idx_ ++; if ( idx_ >= win_len ) idx_ = 0; count_ ++; if ( count_ >= min_sensing_samples ) { if ( count_ >= max_sensing_samples ) { error_code = E_ERROR_CS_TIMEOUT; ipin.clear(); return 0; } if ( average_energy_ >= cca_pwr_threshold ) { cca_pwr_reading = average_energy_; cca_state = CF_11CCA::power_detected; RaiseEvent(OnPowerDetected)(); } } // Energy gating - only low power samples pass if ( cca_state != CF_11CCA::power_detected ) { vcs& po = cast_ref<vcs>(opin().append()); po = pi; Next()->Process(opin()); } ipin.pop(); } return true; } }; /***************************************************** TCCA11a - Carrier sensing using auto-correlation ******************************************************/ DEFINE_LOCAL_CONTEXT(TCCA11a, CF_11CCA, CF_CFOffset, CF_Error); template<TFILTER_ARGS> class TCCA11a : public TFilter<TFILTER_PARAMS> { private: typedef enum { no_energy, high_energy} CCA_STATE; static const uint ac_norm_shift = 5; static const uint NORM_SHIFT = 4; // carrier sensing slot timing static const uint max_sense_count = 84; // 80/20 = 4us private: // Context variables CTX_VAR_RO (uint, cca_pwr_threshold ); CTX_VAR_RW (uint, cca_pwr_reading ); CTX_VAR_RW (CF_11CCA::CCAState, cca_state ); CTX_VAR_RW (FP_RAD, CFO_est ); CTX_VAR_RW (ulong, error_code ); protected: // accumulators CMovingWindow<vcs, 4> sample_his; CAccumulator <int, 4> ac_re_his; CAccumulator <int, 4> ac_im_his; // norm0 of the auto correlation CAccumulator <int, 4> ac_norm_his; CAccumulator <int, 4> energy_his; CAccumulator <int, 4> energy_sqr_his; // counter for autocorrelation high energy samples uint auto_count; // counter for the number of samples sensed uint sense_count; // counter for the samples in high energy state uint high_count; // local sync state CCA_STATE sync_state; // variables for cross-correlation static_wrapper<A16 COMPLEX16 [16][16]> sts_corr_pattern; // the max value in cross-correlation int peak_corr; // the index in sample of the peak int peak_index; public: DEFINE_IPORT(COMPLEX16, 4); DEFINE_OPORT(COMPLEX16, 4); protected: FINL int GetAutoCorrelation ( vcs& input, int& corr_re, int& corr_im ) { vi re, im; // compute the auto correlation conj_mul ( re, im, input, sample_his.First() ); vi sum_r = hadd (re >> NORM_SHIFT ); vi sum_i = hadd (im >> NORM_SHIFT ); ac_re_his << sum_r[0]; ac_im_his << sum_i[0]; corr_re = ac_re_his.Register(); corr_im = ac_im_his.Register(); // NORM0 int sum = (abs(corr_re) + abs(corr_im)); ac_norm_his << sum; return ac_norm_his.Register(); } FINL int GetEnergy ( vcs& input ) { vi e = SquaredNorm (input); vi sum = hadd (e >> NORM_SHIFT ); energy_his << sum[0]; return energy_his.Register(); } FINL int GetCrossCorrelation ( vcs* sarray, int k, vcs* pattern ) { vi re[4], im[4]; vi sum_re, sum_im; conj_mul ( re[0], im[0], pattern[0], sarray[k] ); k = (k+1) & 0x3; conj_mul ( re[1], im[1], pattern[1], sarray[k] ); k = (k+1) & 0x3; conj_mul ( re[2], im[2], pattern[2], sarray[k] ); k = (k+1) & 0x3; conj_mul ( re[3], im[3], pattern[3], sarray[k] ); sum_re = hadd (re[0] + re[1] + re[2] + re[3]); sum_im = hadd (im[0] + im[1] + im[2] + im[3]); int corr = abs(sum_re[0]) + abs(sum_im[0]); return corr; } FINL bool establish_sync () { int sindex = sample_his.GetIndex (); vcs* sarray = (vcs*) sample_his; // clear the peak record peak_corr = 0; int sum_corr = 0; for (int i=0; i<16; i++) { vcs* pattern = (vcs*)sts_corr_pattern[i]; int corr = GetCrossCorrelation ( sarray, sindex, pattern ); if ( corr > peak_corr ) { peak_corr = corr; peak_index = i; } sum_corr += corr; } _dump_text ("establish sync: %d %d - sum %d\n", peak_corr, peak_index, sum_corr ); // a peak should be at least twice higher than noise correlation return ( peak_corr > (sum_corr >> 3)); } FINL bool check_sync () { int sindex = sample_his.GetIndex (); vcs* sarray = (vcs*) sample_his; vcs* pattern = (vcs*)sts_corr_pattern[peak_index]; int corr = GetCrossCorrelation ( sarray, sindex, pattern ); _dump_text ( "check peak -- %d\n", corr ); // check if it is a peak // a later peak should not be lower than the first peak by half if ( corr < (peak_corr >> 1)) { return false; } else { if ( corr > peak_corr ) { peak_corr = corr; } return true; } } protected: FINL void __init_corr_pattern () { // build up cross-correlation pattern A16 COMPLEX16 temp[64]; Generate80211aSTS<64> (temp); // cyclic shift for (int i=0; i<16; i++) { memcpy (sts_corr_pattern[i], &temp[i], sizeof(COMPLEX16)*16); } } FINL void __init () { sync_state = no_energy; auto_count = 0; sense_count = 0; high_count = 0; sample_his.Clear(); ac_re_his.Clear(); ac_im_his.Clear(); ac_norm_his.Clear(); energy_his.Clear(); energy_sqr_his.Clear (); peak_index = 0; peak_corr = 0; } public: REFERENCE_LOCAL_CONTEXT(TCCA11a ); STD_TFILTER_CONSTRUCTOR(TCCA11a ) BIND_CONTEXT(CF_11CCA::cca_pwr_threshold, cca_pwr_threshold) BIND_CONTEXT(CF_11CCA::cca_pwr_reading, cca_pwr_reading) BIND_CONTEXT(CF_11CCA::cca_state, cca_state) BIND_CONTEXT(CF_CFOffset::CFO_est, CFO_est) BIND_CONTEXT(CF_Error::error_code, error_code) { __init_corr_pattern(); __init (); } STD_TFILTER_RESET() { __init (); } STD_TFILTER_FLUSH() { } BOOL_FUNC_PROCESS (ipin) { while (ipin.check_read()) { const vcs& pi = cast_ref<const vcs>(ipin.peek ()); int corr_r, corr_i; if ( sync_state == no_energy ) { // auto-correlation senssing int iAutoCorr = GetAutoCorrelation ( pi>>2, corr_r, corr_i ); int iEnergy = GetEnergy ( pi>>2 ); // save sample in the accumulator sample_his << (pi>>2); sense_count += 4; if ( (iEnergy > (int)cca_pwr_threshold) && iAutoCorr >= (iEnergy - (iEnergy >> 3))) { auto_count++; // any case we are sensing high, we reset the sense counter sense_count = 0; // if remaining in plateau for 4*4=16 samples if (auto_count >= 4) { _dump_text ( "power detected!\n" ); // use cross-correlation to establish sync if ( establish_sync () ) { sync_state = high_energy; cca_pwr_reading = iEnergy; // adjust the peak_index high_count = 0; if ( peak_index > 3 ) { high_count = peak_index / 4; peak_index = peak_index & 0x03; } // coarse CFO estimation // Kun: disabled /* FP_RAD theta = uatan2 ( corr_i, corr_r ); CFO_est = (theta >> 4); printf ( "coarse freq offset (%lf) %lfKHz\n", fprad2rad(CFO_est), 20000 * fprad2rad(CFO_est) / 2 / 3.141593 ); */ } } } /* else if ( sense_count >= max_sense_count && auto_count == 0) { // CS timeout error_code = E_ERROR_CS_TIMEOUT; ipin.clear(); return true; } */ else { auto_count = 0; } } else if ( sync_state == high_energy ) { sample_his << (pi>>2); high_count ++; if ( high_count % 4 == 0 ) { if ( !check_sync ()) { // cross-correlation peak lost // if we already have enough peaks found, we mark // it as the end of STS if ( high_count > 8 ) { cca_state = CF_11CCA::power_detected; RaiseEvent(OnPowerDetected)(); _dump_text ( "CCA done!\n" ); } else { sync_state = no_energy; sense_count = 0; } } } } // Energy gating - only low power samples pass if ( sync_state == no_energy ) { vcs& po = cast_ref<vcs>(opin().append()); po = pi; Next()->Process(opin()); } ipin.pop(); } // now we have processed all data inqueue if ( sense_count >= max_sense_count && sync_state == no_energy ) { // CS time out error_code = E_ERROR_CS_TIMEOUT; } return true; } };
Thank you a lot for your time !
Tuesday, May 26, 2015 2:03 AM