@@ -12,52 +12,99 @@ class RfCmd(Enum):
1212
1313
1414class RfBase (BaseIo ):
15+ """
16+ Base driver class for RF IOs (DDS-based signal generation).
17+
18+ Wraps a direct digital synthesizer (DDS) core and provides control over
19+ frequency, phase, and amplitude. The ``update`` flag on each method controls
20+ whether the new value is applied immediately (``True``) or staged for a later
21+ atomic update (``False``), which allows frequency, phase, and amplitude to be
22+ changed simultaneously.
23+ """
1524 def __init__ (self , addr , clk_freq ):
1625 super ().__init__ (addr , clk_freq )
1726
18- def frequency (self , val : int , update : bool = True ):
27+ def frequency (self , val : float , update : bool = True ):
28+ """
29+ Set the output frequency.
30+
31+ The valid range is ``[-clk_freq/2, clk_freq/2]`` (i.e. ±62.5 MHz for a 125 MHz clock).
32+
33+ :param val: Frequency in Hz.
34+ :param update: If ``True``, apply the new value immediately. Set to ``False`` to stage
35+ the change and apply it atomically together with other staged parameters.
36+ """
1937 FREQ_MIN = - self ._clk_freq / 2
2038 FREQ_MAX = self ._clk_freq / 2
2139 if (val < FREQ_MIN ) or (val > FREQ_MAX ):
2240 raise Exception (f"Frequency value { val } is out of range [{ FREQ_MIN } , { FREQ_MAX } ]." )
23- cmd = RfCmd .FREQ .value
24- if update :
41+ cmd = RfCmd .FREQ .value
42+ if update :
2543 cmd |= RfCmd .UPDATE .value
26- data = int (val / self ._clk_freq * ((1 << 32 ) - 1 ))
44+ data = int (val / self ._clk_freq * ((1 << 32 ) - 1 ))
2745 self ._add_instruction (cmd = cmd , data = data )
2846
29- def phase (self , val : int , update : bool = True ):
30- cmd = RfCmd .PHASE .value
31- if update :
47+ def phase (self , val : float , update : bool = True ):
48+ """
49+ Set the output phase.
50+
51+ The value is taken modulo 360°, so any value outside ``[0°, 360°)`` wraps around.
52+
53+ :param val: Phase in degrees.
54+ :param update: If ``True``, apply the new value immediately. Set to ``False`` to stage
55+ the change and apply it atomically together with other staged parameters.
56+ """
57+ cmd = RfCmd .PHASE .value
58+ if update :
3259 cmd |= RfCmd .UPDATE .value
33- data = int ((val % 360 ) / 360 * ((1 << 32 ) - 1 ))
34- self ._add_instruction (cmd = cmd , data = data )
35-
36- def amplitude (self , val : int , update : bool = True ):
60+ data = int ((val % 360 ) / 360 * ((1 << 32 ) - 1 ))
61+ self ._add_instruction (cmd = cmd , data = data )
62+
63+ def amplitude (self , val : float , update : bool = True ):
64+ """
65+ Set the output amplitude.
66+
67+ The valid range is ``[-1, 1]``, where ``±1`` corresponds to full-scale output.
68+
69+ :param val: Amplitude as a normalized value in ``[-1, 1]``.
70+ :param update: If ``True``, apply the new value immediately. Set to ``False`` to stage
71+ the change and apply it atomically together with other staged parameters.
72+ """
3773 AMPL_MIN = - 1
3874 AMPL_MAX = 1
3975 if (val < AMPL_MIN ) or (val > AMPL_MAX ):
4076 raise Exception (f"Amplitude value { val } is out of range [{ AMPL_MIN } , { AMPL_MAX } ]." )
41-
4277 cmd = RfCmd .AMPL .value
43- if update :
78+ if update :
4479 cmd |= RfCmd .UPDATE .value
45- data = int (val * ((1 << 15 ) - 1 ))
80+ data = int (val * ((1 << 15 ) - 1 ))
4681 self ._add_instruction (cmd = cmd , data = data )
4782
4883 def phase_reset (self , update : bool = True ):
49- data = 1
50- cmd = RfCmd .PHASE_RST .value
51- if update :
84+ """
85+ Reset the DDS phase accumulator to zero.
86+
87+ :param update: If ``True``, apply immediately. Set to ``False`` to stage the reset
88+ and apply it atomically together with other staged parameters.
89+ """
90+ cmd = RfCmd .PHASE_RST .value
91+ if update :
5292 cmd |= RfCmd .UPDATE .value
53- self ._add_instruction (cmd = cmd , data = data )
93+ self ._add_instruction (cmd = cmd , data = 1 )
5494
5595
5696class RfOut (RfBase ):
97+ """
98+ Driver class for RF output channels.
99+ """
57100 def __init__ (self , addr , clk_freq ):
58101 super ().__init__ (addr , clk_freq )
59-
102+
103+
60104class RfIn (RfBase ):
105+ """
106+ Driver class for RF input channels (TODO: missing FPGA backend).
107+ """
61108 def __init__ (self , addr , clk_freq ):
62109 super ().__init__ (addr , clk_freq )
63110
0 commit comments