Chip_Case_Generator/Z_case_Generator_V2.0/ZChipConfig.py

367 lines
15 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
import os
from reg_define import *
class ZChipConfig(object):
CHANNEL_OFFSET = 0x00600000
SCALE_FACTOR = 2 ** 31
def __init__(self, mk_instance, channel_id=0, **kwargs):
self.mk = mk_instance
self.channel_id = channel_id
self.FolderName = kwargs.get('FolderName')
self.config_file = kwargs.get('config_file')
self._setup_environment()
self._init_logger()
def _setup_environment(self):
if self.FolderName:
os.makedirs(self.FolderName, exist_ok=True)
if self.config_file and os.path.exists(self.config_file):
os.remove(self.config_file)
def _init_logger(self):
import logging
self.logger = logging.getLogger(f"ChipConfig.ch{self.channel_id}")
if not self.logger.handlers:
handler = logging.StreamHandler()
formatter = logging.Formatter(
'%(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
self.logger.addHandler(handler)
self.logger.setLevel(logging.INFO)
def get_channel_addr(self, base_addr):
if isinstance(base_addr, str):
if base_addr.startswith('0x'):
base_addr = int(base_addr, 16)
else:
base_addr = int(base_addr)
if not hasattr(self, '_channel_offset'):
self._channel_offset = self.CHANNEL_OFFSET * self.channel_id
return hex(base_addr + self._channel_offset)
def _configure_tc_mode(self):
"""配置TC模式 - 分组配置系数"""
# self.logger.info(
# "Configuring TC mode with group-wise coefficient setup")
# 写入TC_BYPASS
self.write_register(
self.get_register_addr('BYPASS'),
self.REGISTER_VALUES['BYPASS_TC']
)
# 计算TC系数
coefficients = self._calculate_tc_coefficients()
# 分组配置TC系数并设置配置完成标志
self._configure_tc_coefficients_by_groups(coefficients)
# self.logger.info("TC mode configuration completed")
def _configure_tc_coefficients_by_groups(self, coefficients):
"""分组配置TC系数每组配置完成后设置对应的配置完成标志"""
# 定义7个系数组每组包含一个系数的4个寄存器(alpha_re, alpha_im, beta_re, beta_im)
tc_register_groups = self._build_tc_register_groups(coefficients)
for group_idx, group_registers in enumerate(tc_register_groups):
# 配置当前组的所有寄存器
# self.logger.info(f"配置系数组 {group_idx}")
self.write_registers_batch(group_registers)
# 设置当前组的配置完成标志
self._set_coef_config_done_for_group(group_idx)
# self.logger.info(f"系数组 {group_idx} 配置完成")
def set_tc_coefficient_set(self, coeff_set_name):
"""设置要使用的TC系数组"""
if coeff_set_name not in self.TC_COEFFICIENT_SETS:
available = list(self.TC_COEFFICIENT_SETS.keys())
raise ValueError(f"未知的系数组: {coeff_set_name}. 可用的系数组: {available}")
self.tc_coeff_set = coeff_set_name
# self.logger.info(
# f"切换到TC系数组: {coeff_set_name} - {self.TC_COEFFICIENT_SETS[coeff_set_name]['description']}")
def _calculate_tc_coefficients(self, **kwargs):
tc_coef_set = kwargs.pop('tc_coef_set')
coef_set = TC_COEFFICIENT_SETS[tc_coef_set]
amp_real = coef_set['amp_real']
amp_imag = coef_set['amp_imag']
time_real = coef_set['time_real']
time_imag = coef_set['time_imag']
sampling_rate = 3e9
coef1, coef2 = [], []
for ar, ai, tr, ti in zip(amp_real, amp_imag, time_real, time_imag):
amp_coef = ar + 1j * ai
time_coef = tr + 1j * ti
coef1.append(amp_coef * np.exp(1e9 / (sampling_rate) / 2 / (1 - amp_coef) * time_coef) /
(1 - amp_coef))
coef2.append(np.exp(1e9 / (sampling_rate) / (1 - amp_coef) * time_coef))
# print('coef1_real = ')
# for c in coef1:
# print(c.real)
# # print(hex(int(c.real*(2**31-1)) & 0xFFFFFFFF))
# print('coef1_imag = ')
# for c in coef1:
# # print(hex(int(c.imag*(2**31-1)) & 0xFFFFFFFF))
# print(c.imag)
# print('coef2_real = ')
# for c in coef2:
# # print(hex(int(c.real*(2**31-1)) & 0xFFFFFFFF))
# print(c.real)
# print('coef2_imag = ')
# for c in coef2:
# # print(hex(int(c.imag*(2**31-1)) & 0xFFFFFFFF))
# print(c.imag)
return {
'alpha_re': [int(c.real * self.SCALE_FACTOR) for c in coef1],
'alpha_im': [int(c.imag * self.SCALE_FACTOR) for c in coef1],
'beta_re': [int(c.real * self.SCALE_FACTOR) for c in coef2],
'beta_im': [int(c.imag * self.SCALE_FACTOR) for c in coef2]
}
def _build_tc_register_groups(self, coefficients):
"""构建分组的TC寄存器配置"""
tc_register_groups = []
# 获取所有寄存器地址
alpha_re_addrs = self.get_register_addr('TC_ALPHA_RE')
alpha_im_addrs = self.get_register_addr('TC_ALPHA_IM')
beta_re_addrs = self.get_register_addr('TC_BETA_RE')
beta_im_addrs = self.get_register_addr('TC_BETA_IM')
# 按组分配寄存器假设有8个系数但只使用前7组
num_groups = len(coefficients['alpha_re'])
for i in range(num_groups):
group_registers = [
(alpha_re_addrs[i], coefficients['alpha_re'][i]),
(alpha_im_addrs[i], coefficients['alpha_im'][i]),
(beta_re_addrs[i], coefficients['beta_re'][i]),
(beta_im_addrs[i], coefficients['beta_im'][i])
]
tc_register_groups.append(group_registers)
return tc_register_groups
def _set_coef_config_done_for_group(self, group_idx):
"""为指定组设置配置完成标志"""
if not (0 <= group_idx <= 7): # 8组索引0-7
self.logger.warning(f"无效的组索引: {group_idx}")
return
# 计算当前组的配置完成标志值2^group_idx
config_done_value = 1 << group_idx
config_done_hex = f'0x{config_done_value:02x}'
# 读取当前配置完成寄存器的值,进行或运算以保留其他组的标志
try:
# 如果需要保留其他组的标志,这里需要先读取当前值
# current_value = self._read_register(self.get_register_addr('COEF_CONFIG_DONE'))
# new_value = current_value | config_done_value
# 简化版本:直接写入当前组的标志
self.write_register(
self.get_register_addr('COEF_CONFIG_DONE'),
config_done_hex
)
# self.logger.info(f"系数组 {group_idx} 配置完成标志已设置: {config_done_hex}")
except Exception as e:
self.logger.error(f"设置系数组 {group_idx} 配置完成标志失败: {e}")
raise
def write_registers_batch(self, register_values):
"""
批量写入寄存器
参数:
register_values: [(address, value), ...] 或 {address: value, ...}
"""
if isinstance(register_values, dict):
register_values = register_values.items()
for address, value in register_values:
try:
self.mk.rw_once('w', address, value, self.config_file)
except Exception as e:
self.logger.error(f"Failed to write register {address}: {e}")
raise
def write_register(self, address, value):
"""写入单个寄存器"""
try:
self.mk.rw_once('w', address, value, self.config_file)
except Exception as e:
self.logger.error(f"Failed to write register {address}: {e}")
raise
def _freq2hex(self, freq):
fs = 750
fcw = int(freq / fs / 4 * 2 ** 32)
return int(fcw)
def _deg2hex(self, deg):
return int(deg / 360 * (2 ** 16 - 1))
# def _system_reg_config(self, **kwargs):
# 中断屏蔽寄存器
# mk_instance.rw_once('w', '0x14', '0x10000000', config.config_file)
def _general_reg_config(self, **kwargs):
ctrl_registers = []
# 自定义寄存器配置支持(元组/字典/列表三种格式)
if 'custom_registers' in kwargs:
custom_registers = kwargs.pop('custom_registers')
first_item = custom_registers[0]
# 元组格式:[(addr, val), ...] 批量写入
if isinstance(first_item, tuple):
self.write_registers_batch(custom_registers)
# 字典格式:[{"addr": addr, "values": val}, ...] 单条写入
elif isinstance(first_item, dict):
for item in custom_registers:
addr = item['addr']
values = item['values']
self.write_register(addr, values)
# 列表格式:[[addr, val], ...] 单条写入
elif isinstance(first_item, list):
for item in custom_registers:
addr = item[0]
values = item[1]
self.write_register(addr, values)
# 芯片工作模式配置
if 'chip_mode' in kwargs:
# TODO: 部分模式可以合并双频点与单音NCO
chip_mode = kwargs.pop('chip_mode')
if chip_mode == 'RAMP':
self._ramp_config(**kwargs)
elif chip_mode == 'AWG':
self._awg_config(**kwargs)
def _ramp_config(self, **kwargs):
self.write_register(addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['MODDOTR'], 8) # 切换到RAMP输出
ramp_ctrl = kwargs.pop('ramp_ctrl')
if ramp_ctrl == 'MCU': # RAMP连到 mcu_regfile
self.write_register(addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['SPI_RAMPENR'], 1 << 30)
# 之后来用汇编操作RAMP四个参数寄存器
elif ramp_ctrl == 'SPI': # RAMP连到 ctrl_regfile
ramp_spi_registers = []
fixed_enable = kwargs.pop('fixed_enable')
if fixed_enable: # 打开固定值使能位,把值填进去就好
fixed_value = kwargs.pop('fixed_value')
ramp_spi_registers += [1 << 15 | fixed_value << 16]
self.write_register(addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['SPI_RAMPFIXR'], # 常数寄存器
ramp_spi_registers)
else:
ramp_spi_registers += [0 << 15] # 不是固定值模式常数寄存器给0就好
height = kwargs.pop('height', 0)
length = kwargs.pop('step_time', 0)
ramp_spi_registers += [height << 16]
ramp_spi_registers += [length]
self.write_register(addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['SPI_RAMPFIXR'],
ramp_spi_registers)
# 必须最后配使能
self.write_register(addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['SPI_RAMPENR'], 1 << 31 | 0 << 30)
def _awg_config(self, **kwargs):
#数据选择寄存器300108配置开始
# 模式与寄存器数值的映射字典 (Bit 2 和 Bit[1:0])
mode_map = {
'nco': 6,
'nco_fm': 7,
'env': 4,
'mod': 5
}
# 1. 在内存中先计算 mode 对应的基础寄存器值
mode = kwargs.pop('mode', None)
moddotr_val = mode_map.get(mode, 0) # 如果 mode 不在字典里,默认基础值为 0
# 2. DSP拖尾矫正开关配置
tail_en = kwargs.pop('tail_en', False)
if tail_en:
coefficients = self._calculate_tc_coefficients(**kwargs)
# 拼接系数列表
tc_coef_registers = (
coefficients['alpha_re'] +
coefficients['alpha_im'] +
coefficients['beta_re'] +
coefficients['beta_im']
)
self.write_register(addr_base['TCCO0_BASE'] + reg_define['tc_reg']['TCPARR0'], tc_coef_registers)
tccdr_addr = addr_base['TCCO0_BASE'] + reg_define['tc_reg']['TCCDR']
for i in range(8):
self.write_register(tccdr_addr, 1 << i)
# 如果开启了 tail_en在内存里直接给第 4 位 (Bit 3) 置 1
moddotr_val &= ~4 #把[2]变0
# 3. 所有逻辑判断完毕后,只触发一次物理写操作!
moddotr_addr = addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['MODDOTR']
self.write_register(moddotr_addr, moddotr_val)
#调制使能寄存器300104配置开始
amp_mod_enable = kwargs.pop('amp_mod_enable', False)
freq_mod_enable = kwargs.pop('freq_mod_enable', False)
bias_enable = kwargs.pop('bias_enable', False)
# 低电平使能逻辑True(开启) -> 0False(关闭) -> 1
mod_enable = (
(int(not bias_enable) << 0) # Bit 0: Bias (低电平有效)
| (int(not freq_mod_enable) << 1) # Bit 1: Freq (加括号,先取非再左移 1 位)
| (int(not amp_mod_enable) << 2) # Bit 2: Amp (加括号,先取非再左移 2 位)
)
self.write_register(addr_base['CTRL0_BASE'] + reg_define['ctrl_reg']['MODENR'], mod_enable)
#mcu_regfile配置开始
mcu_registers = []
fcw_list = kwargs.pop('fcw', 0)
mcu_reg_clr = kwargs.pop('mcu_reg_clr', 0)
pcw_list = kwargs.pop('pcw', 0)
fcw = int(fcw_list[0] / fs / 4 * 2 ** 32)
for fcw in fcw_list:
mcu_registers.append(int(fcw / fs / 4 * 2 ** 32))
if mcu_reg_clr:
mcu_registers += [1 << 31]
else:
mcu_registers += [0 << 31]
for pcw in pcw_list:
mcu_registers.append(int(pcw / 360 * (2 ** 16 - 1)) << 16)
rz_pha = kwargs.pop('rz_pha', 0)
mcu_registers.append(int(rz_pha / 360 * (2 ** 16 - 1)))
#幅度
ff_amp_list = kwargs.pop('ff_amp', 0)
fm_amp_list = kwargs.pop('fm_amp', 0)
for ff, fm in zip(ff_amp_list, fm_amp_list):
mcu_registers.append(((ff & 0xFFFF) << 16) | (fm & 0xFFFF))
#偏置
bias_list = kwargs.pop('bias', 0)
for bias in bias_list:
mcu_registers.append(bias << 16)
self.write_register(addr_base['DTCM0_BASE'] + reg_define['mcu_reg']['CWFR0'], mcu_registers)
#FMER
fm_en = kwargs.pop('fm_en', False)
if fm_en:
self.write_register(addr_base['DTCM0_BASE'] + reg_define['mcu_reg']['FMER'], 1 << 31)
elif not fm_en:
self.write_register(addr_base['DTCM0_BASE'] + reg_define['mcu_reg']['FMER'], 0 << 31)
#mcu_regfile配置到此完成
return None
def config_chip_reg(mk_instance, **kwargs):
config = ZChipConfig(mk_instance, **kwargs)
config._general_reg_config(**kwargs)