ad9102 prestored saw done

This commit is contained in:
Ayzen
2026-02-03 18:57:30 +03:00
parent 809f19bea4
commit fd1095c50a
9 changed files with 230 additions and 23 deletions

View File

@ -10,6 +10,13 @@ GET_DATA_TOTAL_LENGTH = 30 # Total number of bytes when getting DATA
SEND_PARAMS_TOTAL_LENGTH = 30 # Total number of bytes when sending parameters
TASK_ENABLE_COMMAND_LENGTH = 32 # Total number of bytes when sending TASK_ENABLE command
AD9833_CMD_TOTAL_LENGTH = 10 # Total bytes when sending AD9102 saw command
AD9833_CMD_HEADER = "8888"
AD9102_SAW_STEP_DEFAULT = 1
AD9102_PAT_PERIOD_DEFAULT = 0xFFFF
AD9102_PAT_PERIOD_BASE_DEFAULT = 0x02
AD9102_DAC_CLK_HZ = None # set to actual DAC clock if you want freq->SAW_STEP conversion
class TaskType(IntEnum):
Manual = 0x00
ChangeCurrentLD1 = 0x01
@ -148,6 +155,17 @@ def send_STATE(prt):
pass
def send_AD9833(prt, bytestring):
''' Start/stop AD9833 output with triangle (ramp) mode (0x8888 + ...).
Expected device answer: STATE.
'''
if len(bytestring) != AD9833_CMD_TOTAL_LENGTH:
print("Error. Wrong parameter string for AD9833 command.")
return None
prt.write(bytestring)
print("Sent: AD9833 ramp command.")
# ---- Getting data
@ -262,6 +280,76 @@ def create_TaskEnableCommand(sending_param):
return bytearray.fromhex(data)
def calc_saw_step_for_freq(freq_hz: float, dac_clk_hz: float, triangle: bool):
if freq_hz <= 0 or dac_clk_hz is None or dac_clk_hz <= 0:
return AD9102_SAW_STEP_DEFAULT
n = 2 if triangle else 1
step = int(round(dac_clk_hz / (freq_hz * n * 16384.0)))
if step < 1:
step = 1
if step > 63:
step = 63
return step
def calc_pat_period_for_duty(saw_step: int, duty: float, pat_period_base: int, triangle: bool):
if duty is None or duty <= 0 or duty > 1.0:
return AD9102_PAT_PERIOD_DEFAULT
n = 2 if triangle else 1
base_cycles = 16 if pat_period_base == 0 else pat_period_base
ramp_cycles = n * 16384 * max(1, min(63, saw_step))
pat_period = int(round(ramp_cycles / (duty * base_cycles)))
if pat_period < 1:
pat_period = 1
if pat_period > 0xFFFF:
pat_period = 0xFFFF
return pat_period
def create_AD9833_ramp_command(saw_step: int = None,
pat_period: int = None,
pat_period_base: int = None,
enable: bool = True,
triangle: bool = True):
if saw_step is None:
saw_step = AD9102_SAW_STEP_DEFAULT
if pat_period is None:
pat_period = AD9102_PAT_PERIOD_DEFAULT
if pat_period_base is None:
pat_period_base = AD9102_PAT_PERIOD_BASE_DEFAULT
if saw_step < 1:
saw_step = 1
if saw_step > 63:
saw_step = 63
if pat_period < 0:
pat_period = 0
if pat_period > 0xFFFF:
pat_period = 0xFFFF
if pat_period_base < 0:
pat_period_base = 0
if pat_period_base > 0x0F:
pat_period_base = 0x0F
flags = 0
if enable:
flags |= 0x0001
if triangle:
flags |= 0x0002
param0 = ((pat_period_base & 0x0F) << 8) | (saw_step & 0xFF)
crc_word = flags ^ param0 ^ pat_period
data = flipfour(AD9833_CMD_HEADER) # Word 0 (header)
data += flipfour(int_to_hex(flags))
data += flipfour(int_to_hex(param0))
data += flipfour(int_to_hex(pat_period))
data += flipfour(int_to_hex(crc_word))
return bytearray.fromhex(data)
def encode_Input(params):
if params is None:
@ -295,24 +383,38 @@ def encode_Input(params):
def decode_STATE(state):
st = flipfour(state)
if st == '0000':
if st is None or len(st) != 4:
return "Error: invalid STATE length."
hi = int(st[0:2], 16)
lo = int(st[2:4], 16)
errors = []
if lo & 0x01:
errors.append("SD Card reading/writing error (SD_ERR)")
if lo & 0x02:
errors.append("Command error (UART_ERR)")
if lo & 0x04:
errors.append("Wrong parameter value error (UART_DECODE_ERR)")
if lo & 0x08:
errors.append("Laser 1: TEC driver overheat (TEC1_ERR)")
if lo & 0x10:
errors.append("Laser 2: TEC driver overheat (TEC2_ERR)")
if lo & 0x20:
errors.append("Resetting system error (DEFAULT_ERR)")
if lo & 0x40:
errors.append("File deletion error (REMOVE_ERR)")
if lo & 0x80:
errors.append("AD9102 status check failed (AD9102_ERR)")
if not errors:
status = "All ok."
elif st == '0001':
status = "SD Card reading/writing error (SD_ERR)."
elif st == '0002':
status = "Command error (UART_ERR)."
elif st == '0004':
status = "Wrong parameter value error (UART_DECODE_ERR)."
elif st == '0008':
status = "Laser 1: TEC driver overheat (TEC1_ERR)."
elif st == '0010':
status = "Laser 2: TEC driver overheat (TEC2_ERR)."
elif st == '0020':
status = "Resetting system error (DEFAULT_ERR)."
elif st == '0040':
status = "File deletion error (REMOVE_ERR)."
else:
status = "Unknown or reserved error."
status = "; ".join(errors)
if hi != 0:
status += f" | AD9102_PAT_STATUS=0x{hi:02X}"
return status
@ -342,6 +444,3 @@ def decode_DATA(dh):
return data