Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Ham Radio Sub-space Communications
#2
Here is a complete, self-contained Python script using numpy and matplotlib

This script builds a frequency-domain G-OFDM matrix (G) using a Root-Raised Cosine (RRC) pulse-shaping profile. It matrices a raw IQ payload across adjacent subcarriers to control out-of-band spectral leakage while spreading signal energy across the subcarrier grid.

Code:
import numpy as np import matplotlib.pyplot as plt def generate_g_matrix(num_subcarriers, roll_off=0.35, span=3):     """     Generates a Generalized OFDM (G-OFDM) frequency-domain pulse-shaping     precoding matrix G.         Parameters:         num_subcarriers (int): Number of subcarriers (N)         roll_off (float): Roll-off factor alpha (0.0 to 1.0)         span (int): Subcarrier overlap span for pulse shaping             Returns:         numpy.ndarray: N x N complex transformation matrix G     """     N = num_subcarriers     G = np.zeros((N, N), dtype=complex)         # Generate Root-Raised Cosine (RRC) window profile across subcarriers     for i in range(N):         for j in range(N):             # Calculate distance/offset between subcarriers             diff = np.abs(i - j)                         # Wrap around for cyclic subcarrier continuity             if diff > N / 2:                 diff = N - diff                             if diff == 0:                 G[i, j] = 1.0             elif diff <= span:                 # Apply frequency-domain RRC roll-off factor                 weight = 0.5 * (1 + np.cos(np.pi * diff / (span + 1))) ** roll_off                 # Apply phase distribution shift across matrix elements                 phase_shift = np.exp(-1j * np.pi * (i - j) / N)                 G[i, j] = weight * phase_shift                     # Normalize matrix energy to maintain constant TX power     G = G / np.linalg.norm(G, ord=2)     return G def process_g_ofdm_payload(iq_symbols, G_matrix, cp_len=16):     """     Processes an IQ payload vector through G-OFDM precoding and IFFT.         Parameters:         iq_symbols (ndarray): Vector of complex IQ payload symbols         G_matrix (ndarray): Precoding matrix G         cp_len (int): Cyclic Prefix length in samples             Returns:         ndarray: Time-domain G-OFDM transmit waveform     """     N = G_matrix.shape[0]         # 1. Apply Frequency-Domain G-Matrix Precoding     # x_freq = G * d (Spreads payload energy across subcarrier matrix)     precoded_subcarriers = np.dot(G_matrix, iq_symbols)         # 2. IFFT transform to discrete time-domain waveform     time_domain_signal = np.fft.ifft(precoded_subcarriers, n=N)         # 3. Add Cyclic Prefix (CP) for multipath resilience     cyclic_prefix = time_domain_signal[-cp_len:]     g_ofdm_frame = np.concatenate([cyclic_prefix, time_domain_signal])         return g_ofdm_frame, precoded_subcarriers # ===================================================================== # BENCH TEST RUNNER # ===================================================================== if __name__ == "__main__":     # System Parameters     N_SUBCARRIERS = 64  # Number of subcarriers     CP_LENGTH = 16      # Cyclic prefix samples         # 1. Generate random QPSK IQ payload (d)     np.random.seed(42)  # Fixed seed for repeatable test     raw_bits = np.random.randint(0, 2, N_SUBCARRIERS * 2)     i_bits = 2 * raw_bits[0::2] - 1     q_bits = 2 * raw_bits[1::2] - 1     iq_payload = (i_bits + 1j * q_bits) / np.sqrt(2) # QPSK normalized         # 2. Construct the G-OFDM Matrix (G)     G = generate_g_matrix(N_SUBCARRIERS, roll_off=0.35, span=2)         # 3. Process signal through standard OFDM vs G-OFDM pipelines     # Standard OFDM (G = Identity Matrix)     standard_ofdm_signal, _ = process_g_ofdm_payload(iq_payload, np.eye(N_SUBCARRIERS), CP_LENGTH)     # G-OFDM Matrix Pipeline     g_ofdm_signal, precoded_iq = process_g_ofdm_payload(iq_payload, G, CP_LENGTH)         # 4. Compute Power Spectral Densities (PSD) for comparison     fft_size = 1024     psd_standard = np.abs(np.fft.fftshift(np.fft.fft(standard_ofdm_signal, n=fft_size))) ** 2     psd_g_ofdm = np.abs(np.fft.fftshift(np.fft.fft(g_ofdm_signal, n=fft_size))) ** 2         # Convert to dB     psd_standard_db = 10 * np.log10(psd_standard / np.max(psd_standard))     psd_g_ofdm_db = 10 * np.log10(psd_g_ofdm / np.max(psd_g_ofdm))         freq_axis = np.linspace(-0.5, 0.5, fft_size)         # 5. Output Verification     print(f"=== G-OFDM Matrix Verification ===")     print(f"Matrix Dimension: {G.shape[0]}x{G.shape[1]}")     print(f"Input IQ Payload Shape: {iq_payload.shape}")     print(f"Precoded Subcarrier Payload Shape: {precoded_iq.shape}")     print(f"Final Time-Domain Frame Length (with CP): {len(g_ofdm_signal)} samples")         # Plot Spectral Comparison     plt.figure(figsize=(10, 5))     plt.plot(freq_axis, psd_standard_db, label="Standard OFDM (Rectangular)", alpha=0.6, color="red")     plt.plot(freq_axis, psd_g_ofdm_db, label="G-OFDM (G Matrix Shaped)", linewidth=2, color="blue")     plt.title("Spectral Comparison: Standard OFDM vs. G-OFDM Precoding")     plt.xlabel("Normalized Frequency (f / Fs)")     plt.ylabel("Power Spectral Density (dB)")     plt.grid(True, linestyle="--", alpha=0.6)     plt.ylim(-60, 5)     plt.legend()     plt.tight_layout()     plt.show()


Key Elements of the Script

Matrix Precoding (G): Rather than passing the raw IQ array d straight into the IFFT, it gets transformed via matrix multiplication with G

Controlled Subcarrier Overlap: The generate G matrix function uses a Root-Raised Cosine roll-off curve to distribute portions of each symbol's energy into neighboring subcarriers.

Out-of-Band (OOB) Suppression: If you run the code and look at the Matplotlib PSD output, you will see the side lobes drop off much faster on the G-OFDM trace than on a standard rectangular-windowed OFDM signal, preventing spectral bleed.
Reply


Messages In This Thread
Ham Radio Sub-space Communications - by admin - 07-21-2026, 11:56 AM
RE: Ham Radio Sub-space Communications - by admin - 07-21-2026, 12:54 PM
RE: Ham Radio Sub-space Communications - by admin - 07-21-2026, 12:59 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)