Files
openairinterface5g/openair1/PHY/NR_TRANSPORT/nr_antenna_state.h
T
2026-09-19 23:28:08 +09:00

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 */