286 lines
9.5 KiB
C
286 lines
9.5 KiB
C
#ifndef NR_ANTENNA_STATE_H
|
|
#define NR_ANTENNA_STATE_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <pthread.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/// Maximum number of physical antennas supported
|
|
#define NR_MAX_ANTENNAS 8
|
|
|
|
/// O-RAN compliant antenna state for TX/RX arrays
|
|
/// Mirrors o-ran-uplane-conf.yang: tx-array-antenna-mask-config
|
|
typedef struct {
|
|
/// Antenna bitmask per O-RAN WG4 spec: bit N = 1 means antenna N is active
|
|
/// Corresponds to o-ran-uplane-conf:antenna-bitmask
|
|
uint8_t tx_antenna_bitmask;
|
|
uint8_t rx_antenna_bitmask;
|
|
|
|
/// Target mask used for new scheduling while an unsafe TX downshift drains.
|
|
uint8_t requested_tx_antenna_bitmask;
|
|
/// True when requested_tx_antenna_bitmask removes physical TX chains that
|
|
/// cannot be muted until incompatible in-flight DL HARQ processes complete.
|
|
bool tx_mask_update_pending;
|
|
|
|
/// Total number of configured antennas
|
|
uint8_t num_tx_antennas;
|
|
uint8_t num_rx_antennas;
|
|
|
|
/// Thread safety for runtime updates
|
|
pthread_mutex_t lock;
|
|
|
|
/// Energy saving statistics (for research/monitoring)
|
|
struct {
|
|
uint64_t tx_mute_events; ///< Number of TX mute operations
|
|
uint64_t rx_mute_events; ///< Number of RX mute operations
|
|
uint64_t total_muted_slots; ///< Total slots with at least one antenna muted
|
|
uint64_t energy_saved_estimate; ///< Estimated energy saved (arbitrary units)
|
|
uint64_t last_update_timestamp; ///< Last update time (for O1 notifications)
|
|
} stats;
|
|
|
|
/// O-RAN compliance: array name for NETCONF identification
|
|
char tx_array_name[64];
|
|
char rx_array_name[64];
|
|
|
|
/// Recovery mode: after unmuting, allow CSI to update before using full capacity
|
|
struct {
|
|
bool in_recovery; ///< Currently in recovery mode
|
|
uint64_t recovery_start_ts; ///< Timestamp when recovery started (us)
|
|
uint32_t recovery_duration_ms; ///< Recovery duration in milliseconds (default 500ms)
|
|
} recovery;
|
|
|
|
/// Configuration flags
|
|
struct {
|
|
bool protect_antenna0; ///< Never mute antenna 0 (needed for SSB)
|
|
} config;
|
|
|
|
} nr_antenna_state_t;
|
|
|
|
/**
|
|
* @brief Initialize antenna state with all antennas active
|
|
* @param state Pointer to antenna state structure
|
|
* @param num_tx Number of TX antennas
|
|
* @param num_rx Number of RX antennas
|
|
* @param tx_array_name O-RAN array name for TX (e.g., "tx-array-0")
|
|
* @param rx_array_name O-RAN array name for RX (e.g., "rx-array-0")
|
|
*/
|
|
void nr_init_antenna_state(nr_antenna_state_t *state,
|
|
uint8_t num_tx,
|
|
uint8_t num_rx,
|
|
const char *tx_array_name,
|
|
const char *rx_array_name);
|
|
|
|
/**
|
|
* @brief Free antenna state resources
|
|
* @param state Pointer to antenna state structure
|
|
*/
|
|
void nr_free_antenna_state(nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Set TX antenna bitmask (O-RAN O1 interface equivalent)
|
|
*
|
|
* This function implements the O-RAN WG4 MPLANE-TRX-CONTROL feature.
|
|
* Corresponds to NETCONF edit-config on tx-array-antenna-mask-config.
|
|
*
|
|
* @param state Pointer to antenna state structure
|
|
* @param bitmask Antenna bitmask (bit N = 1 means antenna N active)
|
|
* @return Previous bitmask value
|
|
*/
|
|
uint8_t nr_set_tx_antenna_bitmask(nr_antenna_state_t *state, uint8_t bitmask);
|
|
|
|
/**
|
|
* @brief Request a TX mask, staging physical downshifts until MAC HARQ is safe
|
|
*
|
|
* New scheduling immediately observes the requested mask. Pure upshifts are
|
|
* applied physically at once; a request that removes active TX chains remains
|
|
* pending until the MAC scheduler explicitly commits it.
|
|
*
|
|
* @param state Pointer to antenna state structure
|
|
* @param bitmask Requested antenna bitmask
|
|
* @return Previous requested bitmask
|
|
*/
|
|
uint8_t nr_request_tx_antenna_bitmask(nr_antenna_state_t *state, uint8_t bitmask);
|
|
|
|
/**
|
|
* @brief Read the requested TX mask
|
|
* @return Requested bitmask, or 0xFF when state is NULL
|
|
*/
|
|
uint8_t nr_get_requested_tx_antenna_bitmask(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Atomically snapshot a pending TX-mask request
|
|
* @param state Pointer to antenna state structure
|
|
* @param bitmask Output requested mask when pending
|
|
* @return true when a physical mask update is pending
|
|
*/
|
|
bool nr_get_pending_tx_antenna_bitmask(const nr_antenna_state_t *state, uint8_t *bitmask);
|
|
|
|
/**
|
|
* @brief Commit a previously checked pending TX mask
|
|
*
|
|
* The compare against expected_bitmask prevents a concurrent control request
|
|
* from being applied using a stale HARQ-safety decision.
|
|
*
|
|
* @param state Pointer to antenna state structure
|
|
* @param expected_bitmask Mask for which the scheduler completed its check
|
|
* @return true when that exact pending request was committed
|
|
*/
|
|
bool nr_apply_requested_tx_antenna_bitmask(nr_antenna_state_t *state, uint8_t expected_bitmask);
|
|
|
|
/**
|
|
* @brief Set RX antenna bitmask (O-RAN O1 interface equivalent)
|
|
* @param state Pointer to antenna state structure
|
|
* @param bitmask Antenna bitmask (bit N = 1 means antenna N active)
|
|
* @return Previous bitmask value
|
|
*/
|
|
uint8_t nr_set_rx_antenna_bitmask(nr_antenna_state_t *state, uint8_t bitmask);
|
|
|
|
/**
|
|
* @brief Get current TX antenna bitmask
|
|
* @param state Pointer to antenna state structure
|
|
* @return Current TX antenna bitmask
|
|
*/
|
|
uint8_t nr_get_tx_antenna_bitmask(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Get current RX antenna bitmask
|
|
* @param state Pointer to antenna state structure
|
|
* @return Current RX antenna bitmask
|
|
*/
|
|
uint8_t nr_get_rx_antenna_bitmask(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Check if a specific TX antenna is active
|
|
* @param state Pointer to antenna state structure
|
|
* @param ant_id Antenna index (0-based)
|
|
* @return true if antenna is active, false if muted
|
|
*/
|
|
bool nr_is_tx_antenna_active(const nr_antenna_state_t *state, uint8_t ant_id);
|
|
|
|
/**
|
|
* @brief Check if a specific RX antenna is active
|
|
* @param state Pointer to antenna state structure
|
|
* @param ant_id Antenna index (0-based)
|
|
* @return true if antenna is active, false if muted
|
|
*/
|
|
bool nr_is_rx_antenna_active(const nr_antenna_state_t *state, uint8_t ant_id);
|
|
|
|
/**
|
|
* @brief Get count of currently active TX antennas
|
|
* @param state Pointer to antenna state structure
|
|
* @return Number of active TX antennas
|
|
*/
|
|
int nr_get_active_tx_antenna_count(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Get count of currently active RX antennas
|
|
* @param state Pointer to antenna state structure
|
|
* @return Number of active RX antennas
|
|
*/
|
|
int nr_get_active_rx_antenna_count(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Mute a specific TX antenna
|
|
* @param state Pointer to antenna state structure
|
|
* @param ant_id Antenna index to mute (0-based)
|
|
*/
|
|
void nr_mute_tx_antenna(nr_antenna_state_t *state, uint8_t ant_id);
|
|
|
|
/**
|
|
* @brief Unmute a specific TX antenna
|
|
* @param state Pointer to antenna state structure
|
|
* @param ant_id Antenna index to unmute (0-based)
|
|
*/
|
|
void nr_unmute_tx_antenna(nr_antenna_state_t *state, uint8_t ant_id);
|
|
|
|
/**
|
|
* @brief Mute a specific RX antenna
|
|
* @param state Pointer to antenna state structure
|
|
* @param ant_id Antenna index to mute (0-based)
|
|
*/
|
|
void nr_mute_rx_antenna(nr_antenna_state_t *state, uint8_t ant_id);
|
|
|
|
/**
|
|
* @brief Unmute a specific RX antenna
|
|
* @param state Pointer to antenna state structure
|
|
* @param ant_id Antenna index to unmute (0-based)
|
|
*/
|
|
void nr_unmute_rx_antenna(nr_antenna_state_t *state, uint8_t ant_id);
|
|
|
|
/**
|
|
* @brief Get effective number of MIMO layers based on active antennas
|
|
*
|
|
* For MIMO, the number of layers is limited by the requested antenna mask.
|
|
* During a staged downshift this stops new high-rank HARQ traffic before the
|
|
* physical antenna mask changes.
|
|
*
|
|
* @param state Pointer to antenna state structure
|
|
* @param requested_layers Originally requested number of layers
|
|
* @return Effective number of layers that can be used
|
|
*/
|
|
int nr_get_effective_mimo_layers(const nr_antenna_state_t *state, int requested_layers);
|
|
|
|
/**
|
|
* @brief Log antenna state for debugging
|
|
* @param state Pointer to antenna state structure
|
|
*/
|
|
void nr_log_antenna_state(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Get energy saving statistics
|
|
* @param state Pointer to antenna state structure
|
|
* @param tx_mute_events Output: number of TX mute events
|
|
* @param rx_mute_events Output: number of RX mute events
|
|
* @param total_muted_slots Output: total slots with muting
|
|
*/
|
|
void nr_get_antenna_stats(const nr_antenna_state_t *state,
|
|
uint64_t *tx_mute_events,
|
|
uint64_t *rx_mute_events,
|
|
uint64_t *total_muted_slots);
|
|
|
|
/**
|
|
* @brief Reset energy saving statistics
|
|
* @param state Pointer to antenna state structure
|
|
*/
|
|
void nr_reset_antenna_stats(nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Unmute all TX antennas and enter recovery mode
|
|
* @param state Pointer to antenna state structure
|
|
*
|
|
* This initiates a recovery period during which the scheduler
|
|
* uses conservative settings to allow UE CSI reports to update.
|
|
*/
|
|
void nr_unmute_all_tx_antennas(nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Unmute all RX antennas
|
|
* @param state Pointer to antenna state structure
|
|
*/
|
|
void nr_unmute_all_rx_antennas(nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Check if system is in recovery mode after unmuting
|
|
* @param state Pointer to antenna state structure
|
|
* @return true if in recovery mode
|
|
*/
|
|
bool nr_is_in_recovery_mode(const nr_antenna_state_t *state);
|
|
|
|
/**
|
|
* @brief Set antenna 0 protection (SSB antenna)
|
|
* @param state Pointer to antenna state structure
|
|
* @param protect true to prevent muting antenna 0
|
|
*/
|
|
void nr_set_antenna0_protection(nr_antenna_state_t *state, bool protect);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* NR_ANTENNA_STATE_H */
|
|
|