import numpy as np
from rtlsdr import RtlSdr
from scipy.signal import hilbert
import sounddevice as sd  # Optional: for audio playback/monitoring

# -------------------------------
# SDR Parameters
# -------------------------------
CENTER_FREQ = 100e6       # Target carrier (Hz)
SAMPLE_RATE = 2e6         # Hz
GAIN = 'auto'
BUFFER_SIZE = 1024*8      # Samples per read

# -------------------------------
# HDGL Lattice Parameters
# -------------------------------
NUM_CORES = 2
NUM_STRANDS = 4
SLOTS_PER_STRAND = 4
SIDE_AMPLITUDE = 0.05

PHI = 1.6180339887

def init_lattice():
    cores = []
    for _ in range(NUM_CORES):
        lattice = np.random.uniform(0.5, 1.0, (NUM_STRANDS, SLOTS_PER_STRAND))
        phases = np.random.uniform(0, 2*np.pi, (NUM_STRANDS, SLOTS_PER_STRAND))
        cores.append({'lattice': lattice, 'phases': phases})
    return cores

nodes = [init_lattice() for _ in range(1)]  # single node for demo

# -------------------------------
# HDGL Sideband Function
# -------------------------------
def lattice_sideband(node_cores, t):
    sideband = np.zeros_like(t, dtype=np.float32)
    for core in node_cores:
        for s in range(NUM_STRANDS):
            for slot in range(SLOTS_PER_STRAND):
                phase_offset = core['phases'][s, slot] + 0.2 * core['lattice'][s, slot]
                sideband += np.sin(2*np.pi*50*t + phase_offset)  # small freq offset for demo
    sideband /= (NUM_CORES * NUM_STRANDS * SLOTS_PER_STRAND)
    return SIDE_AMPLITUDE * sideband

# -------------------------------
# SDR Streaming Loop
# -------------------------------
sdr = RtlSdr()
sdr.sample_rate = SAMPLE_RATE
sdr.center_freq = CENTER_FREQ
sdr.gain = GAIN

try:
    while True:
        iq_samples = sdr.read_samples(BUFFER_SIZE)
        t = np.arange(len(iq_samples)) / SAMPLE_RATE

        # Generate sideband from HDGL lattice
        sideband = lattice_sideband(nodes, t)

        # Combine with carrier (IQ samples) in-place
        # Convert to float if complex
        carrier_real = np.real(iq_samples)
        composite_signal = carrier_real + sideband

        # Optional: monitor as audio
        sd.play(composite_signal, samplerate=int(SAMPLE_RATE))
except KeyboardInterrupt:
    print("Streaming stopped by user")
finally:
    sdr.close()
