#ifndef bsu_aclf_aclf_h #define bsu_aclf_aclf_h /* Cesar project {{{ * * Copyright (C) 2010 Spidcom * * <<>> * * }}} */ /** * \file bsu/aclf/aclf.h * \brief AC Line Frequency. * \ingroup bsu * * All functions needed to track the frequency variation of the AC Line. */ #include "hal/phy/phy.h" #include "hal/timer/timer.h" #include "mac/common/config.h" #include "mac/common/timings.h" #include "common/defs/homeplugAV.h" #include "lib/stats.h" #include "lib/rnd.h" #if MODULE_INCLUDED(bsu_aclf) # include "config/aclf/bp/cable.h" #endif /** Number of beacon period start date handled. * The value is computed to allow the CCo to compute the four next BTOs. */ #define BSU_ACLF_BPSD_NB (HPAV_BEACON_BTO_NB + 2) /** Frequency possibility. */ enum bsu_aclf_frequency_t { BSU_ACLF_FREQ_UNKNOWN, BSU_ACLF_FREQ_50HZ, BSU_ACLF_FREQ_60HZ, BSU_ACLF_FREQ_CABLE, BSU_ACLF_FREQ_NB }; typedef enum bsu_aclf_frequency_t bsu_aclf_frequency_t; /** Conversion of the frequency to ticks. */ enum bsu_aclf_bp_t { BSU_ACLF_BP_50HZ_TCK = 1000000, BSU_ACLF_BP_55HZ_TCK = 909090, BSU_ACLF_BP_60HZ_TCK = 833333, #if MODULE_INCLUDED(bsu_aclf) BSU_ACLF_BP_CABLE_TCK = CONFIG_ACLF_BP_CABLE_TCK, #else BSU_ACLF_BP_CABLE_TCK = BSU_ACLF_BP_50HZ_TCK, #endif }; typedef enum bsu_aclf_bp_t bsu_aclf_bp_t; /** The minimum value for the beacon period in ticks for 50Hz PowerLine. */ #define BSU_ACLF_50HZ_CLK_MIN_TCK \ (BSU_ACLF_BP_50HZ_TCK - BITS_ONES (HPAV_BEACON_BTO_VALID_BITS)) /** The maximum value for the beacon period in ticks for 50Hz PowerLine. */ #define BSU_ACLF_50HZ_CLK_MAX_TCK \ (BSU_ACLF_BP_50HZ_TCK + BITS_ONES (HPAV_BEACON_BTO_VALID_BITS)) /** The minimum value for the beacon period in ticks for 60Hz PowerLine. */ #define BSU_ACLF_60HZ_CLK_MIN_TCK \ (BSU_ACLF_BP_60HZ_TCK - BITS_ONES (HPAV_BEACON_BTO_VALID_BITS)) /** The maximum value for the beacon period in ticks for 60Hz PowerLine. */ #define BSU_ACLF_60HZ_CLK_MAX_TCK \ (BSU_ACLF_BP_60HZ_TCK + BITS_ONES (HPAV_BEACON_BTO_VALID_BITS)) /** ACLF PowerLine synchronisation information. */ struct bsu_aclf_pwl_sync_t { /** Last power line cross date. */ u32 cross_date; /** Last power line cross date estimated. */ u32 cross_est_date; /** Filtered Error in ticks. */ int w_err_tck; /** Cross interval between two wake ups in ticks. */ uint cross_interval_tck; /** Trig PWL crossing present. */ bool trig_present; /** Inform the BSU the PLL is initialised. */ bool init; }; /** ACLF context structure. */ struct bsu_aclf_t { /** Phy context. */ phy_t *phy; /** Mac configuration, */ mac_config_t *mac_config; /** * Inform on the frequency of the PWL. Only two values are possible * the 50 and 60 Hz. */ const bsu_aclf_frequency_t frequency; /** * Beacon period static value. This value never change it corresponds * to the theoretical value of the beacon period. (1 000 000 ticks * for the 50 Hz and 833 333 ticks for the 60Hz) */ const bsu_aclf_bp_t beacon_period_theo_tck; /** * Table of the beacon period start in date. The first value of the array * is the beacon period start date of the current beacon period, the next * value is the next one and so on. */ u32 bpsd [BSU_ACLF_BPSD_NB]; /** * Current beacon period value of the ACLF. Use to estimate the beacon * period. */ uint beacon_period_tck; /** * The next four beacon period offset values. Those values can be set to * invalid HPAV_BEACON_BTO_INVALID. */ s16 bto[HPAV_BEACON_BTO_NB]; /** * Power Line information synchronisation. */ struct bsu_aclf_pwl_sync_t pwl_sync; /** Delay the beacon period start date from the Power Line cross. */ uint bpsd_delay_ms; /** Random context. */ lib_rnd_t rnd; }; typedef struct bsu_aclf_t bsu_aclf_t; BEGIN_DECLS /** * Initialise the module. * \param phy the phy context. * \param mac_config the mac config structure. * \return the module context pointer. */ bsu_aclf_t* bsu_aclf_init (phy_t *phy, mac_config_t *mac_config); /** * Uninitialise the module. * \param ctx the module context. */ void bsu_aclf_uninit (bsu_aclf_t *ctx); /** * Compute the frequency of the power line using the PRATIC register. * \param ctx the module context. * * It shall read the PRATIC register twice with a gap of BSU_ACLF_ZC_50. This * function shall update the data in the object. * * \warn If the medium is a coaxial cable, the 50Hz will be chosen. */ void bsu_aclf_acl_frequency_detection (bsu_aclf_t *ctx); /** * Compute the beacon period start date from the data contained in the * beacon. * \param ctx the module context. * \param bts_date the beacon time stamp in phy_date. * \param bto the four BTO present in the beacon. * \param bpsto the beacon period start time offset. */ void bsu_aclf_compute_beacon_period_start_date (bsu_aclf_t *ctx, const u32 bts_date, const s16 bto[HPAV_BEACON_BTO_NB], const u32 bpsto); /** * Get the beacon period start time. * \param ctx the module context. * \param bpsd the array to store the beacon period start time values. * \param nb the number of entries desired in the array. * * nb must be at most equal to BSU_ACLF_BPSD_NB. */ void bsu_aclf_beacon_period_start_date (bsu_aclf_t *ctx, u32 *bpsd, uint nb); /** * Get the BTOs computed. * \param ctx the module context. * \param btos the array to store the BTO's values. * \param nb the number of entries desired in the array. * * NB must be at most equal to HPAV_BEACON_BTO_NB. */ void bsu_aclf_bto (bsu_aclf_t *ctx, s16 btos[], uint nb); /** * Return the next beacon period start date. * \param ctx the module context. */ u32 bsu_aclf_beacon_period_start_date_next (bsu_aclf_t *ctx); /** * Get the current beacon period duration. * \param ctx the module context. * \return the beacon period duration. */ u32 bsu_aclf_beacon_period_tck (bsu_aclf_t *ctx); /** * Get the current beacon period duration in ATU. * \param ctx the module context. * \return the beacon period duration. * * Rounded up i.e. 3906.25 == 3907 */ u32 bsu_aclf_beacon_period_atu (bsu_aclf_t *ctx); /** * Shift the date to correspond to the current date. * \param ctx the module context. */ void bsu_aclf_shift_beacon_period_start_date (bsu_aclf_t *ctx); /** * Compute the beacon period start date from the AC Line. * \param ctx the module context. */ void bsu_aclf_ac_compute_beacon_period_start_date (bsu_aclf_t *ctx); /** * Suppress the next BPSD because the it will start before the first beacon * period ends. * \param ctx the module context. */ void bsu_aclf_bpsd_avoid_overlap (bsu_aclf_t *ctx); /** * Clear all data in BSU ACLF. * \param ctx the module context. */ void bsu_aclf_clear (bsu_aclf_t *ctx); /** * Track the PowerLine cross date. * \param ctx the module context. */ void bsu_aclf_track_powerline (bsu_aclf_t *ctx); /** * Clear the synchronisation with a previous CCo. * \param ctx the module context. * * This will un-synchronise the next beacon periods start date from the * previous synchronisation based on the slots beacon values. */ void bsu_aclf_clear_sync (bsu_aclf_t *ctx); /** * Get the date at the one the beacon should be considered as invalid. * \param ctx the module context. * \return the expiration date. */ u32 bsu_aclf_beacon_expiration_date (bsu_aclf_t *ctx); END_DECLS #endif /* bsu_aclf_aclf_h */