# -- coding: utf-8 --
from analyzer import Analyzer
from analyzer import register_analyzer
from analyzer import LogLevel


class I2SAnalyzer(Analyzer):
    def run(self):
        super().run()
        self.log(LogLevel.INFO, f"{self.periph_name}分析启动")
        inst_num = self.get_instance_num(self.periph_name)
        inst_error = 0
        
        #前置检查开始，如果出错就需要中止分析，以防读寄存器卡死或出现非法值
        HPSYS_RCC = self.read_peripheral("hpsys_rcc")
        HPSYS_CFG = self.read_peripheral("hpsys_cfg")
        #self.print_reg(HPSYS_CFG)
        
        #以下是根据实例编号需要区分的内容
        #检查时钟与复位
        if (inst_num==1):
            if (HPSYS_RCC.ENR1.I2S1!=1):
                self.log(LogLevel.ERROR, f"{self.periph_name}模块时钟未开启",\
                         "需将HPSYS_RCC的ESR1_I2S1置1以开启模块时钟")
                inst_error = 1
            if (HPSYS_RCC.RSTR1.I2S1!=0):
                self.log(LogLevel.ERROR, f"{self.periph_name}模块被复位",\
                         "需将HPSYS_RCC的RSTR1_I2S1置0以释放模块复位")
                inst_error = 1
            bck_pin_list  = [5,29]
            lrck_pin_list = [6,30]
            sdi_pin_list  = [4,28]
            sdo_pin_list  = [3,25]
            mclk_pin_list = [2,24]

        #前置检查结束，如果出错就中止分析
        if (inst_error==1):
            self.log(LogLevel.ERROR, f"{self.periph_name}上述初始配置发现错误，分析无法继续进行",\
                     "请将上述错误修正后重新启动分析")
            return
        #self.log(LogLevel.INFO, "初始配置分析完成，未发现错误，启动功能分析")

        #以下是各实例共同的内容
        #PINMUX检查
        HPSYS_PINMUX = self.read_peripheral("hpsys_pinmux")
        #BCK IO检查
        bck_pin = 0x3f
        for i in bck_pin_list:
            if (HPSYS_PINMUX.__dict__[f"PAD_PA{i:02d}"].FSEL == 3):
                bck_pin = i
                break
        if (bck_pin == 0x3f): #没有分配IO
            self.log(LogLevel.ERROR, f"未找到BCK分配的IO",\
                     f"可分配IO为PA{bck_pin_list}")
            inst_error = 1
        else:
            self.log(LogLevel.INFO, f"BCK分配到PA{bck_pin:02d}")
            if ((HPSYS_PINMUX.__dict__[f"PAD_PA{bck_pin:02d}"].PE == 1)):
                self.log(LogLevel.WARN, f"BCK PA{bck_pin:02d}内部上下拉开启，可能产生漏电",\
                         f"可将HPSYS_PINMUX->PAD_PA{bck_pin:02d}.PE设为0以关闭内部上下拉电阻")
        #LRCK IO检查
        lrck_pin = 0x3f
        for i in lrck_pin_list:
            if (HPSYS_PINMUX.__dict__[f"PAD_PA{i:02d}"].FSEL == 3):
                lrck_pin = i
                break
        if (lrck_pin == 0x3f): #没有分配IO
            self.log(LogLevel.ERROR, f"未找到LRCK分配的IO",\
                     f"可分配IO为PA{lrck_pin_list}")
            inst_error = 1
        else:
            self.log(LogLevel.INFO, f"LRCK分配到PA{lrck_pin:02d}")
            if ((HPSYS_PINMUX.__dict__[f"PAD_PA{lrck_pin:02d}"].PE == 1)):
                self.log(LogLevel.WARN, f"LRCK PA{lrck_pin:02d}内部上下拉开启，可能产生漏电",\
                         f"可将HPSYS_PINMUX->PAD_PA{lrck_pin:02d}.PE设为0以关闭内部上下拉电阻")
        #SDO IO检查
        sdo_pin = 0x3f
        for i in sdo_pin_list:
            if (HPSYS_PINMUX.__dict__[f"PAD_PA{i:02d}"].FSEL == 3):
                sdo_pin = i
                break
        if (sdo_pin == 0x3f): #没有分配IO
            self.log(LogLevel.WARN, f"未找到SDO分配的IO",\
                     f"可分配IO为PA{sdo_pin_list}")
        else:
            self.log(LogLevel.INFO, f"SDO分配到PA{sdo_pin:02d}")
            if ((HPSYS_PINMUX.__dict__[f"PAD_PA{sdo_pin:02d}"].PE == 1)):
                self.log(LogLevel.WARN, f"SDO PA{sdo_pin:02d}内部上下拉开启，可能产生漏电",\
                         f"可将HPSYS_PINMUX->PAD_PA{sdo_pin:02d}.PE设为0以关闭内部上下拉电阻")
        #SDI IO检查
        sdi_pin = 0x3f
        for i in sdi_pin_list:
            if (HPSYS_PINMUX.__dict__[f"PAD_PA{i:02d}"].FSEL == 3):
                sdi_pin = i
                break
        if (sdi_pin == 0x3f): #没有分配IO
            self.log(LogLevel.WARN, f"未找到SDI分配的IO",\
                     f"可分配IO为PA{sdi_pin_list}")
        else:
            self.log(LogLevel.INFO, f"SDI分配到PA{sdi_pin:02d}")
            if (HPSYS_PINMUX.__dict__[f"PAD_PA{sdi_pin:02d}"].IE != 1):
                self.log(LogLevel.ERROR, f"SDI PA{sdi_pin:02d}输入未使能",\
                         f"将HPSYS_PINMUX->PAD_PA{sdi_pin:02d}.IE设为1")
            if ((HPSYS_PINMUX.__dict__[f"PAD_PA{sdi_pin:02d}"].PE == 1)):
                self.log(LogLevel.WARN, f"SDI PA{sdi_pin:02d}内部上下拉开启，可能产生漏电",\
                         f"可将HPSYS_PINMUX->PAD_PA{sdi_pin:02d}.PE设为0以关闭内部上下拉电阻")
        #MCLK IO检查
        mclk_pin = 0x3f
        for i in mclk_pin_list:
            if (HPSYS_PINMUX.__dict__[f"PAD_PA{i:02d}"].FSEL == 3):
                mclk_pin = i
                break
        if (mclk_pin == 0x3f): #没有分配IO
            self.log(LogLevel.WARN, f"未找到MCLK分配的IO",\
                     f"可分配IO为PA{mclk_pin_list}")
        else:
            self.log(LogLevel.INFO, f"MCLK分配到PA{mclk_pin:02d}")
            if ((HPSYS_PINMUX.__dict__[f"PAD_PA{mclk_pin:02d}"].PE == 1)):
                self.log(LogLevel.WARN, f"MCLK PA{mclk_pin:02d}内部上下拉开启，可能产生漏电",\
                         f"可将HPSYS_PINMUX->PAD_PA{mclk_pin:02d}.PE设为0以关闭内部上下拉电阻")
        
        #读取I2S寄存器
        I2S = self.read_peripheral(self.periph_name)
        
        #检查I2S速率
##        i2c_mode = I2C.CR.MODE;
##        if (i2c_mode == 0):
##            self.log(LogLevel.INFO, "I2C为标准模式(standard-mode)")
##            if (I2C.LCR.SLV > (2*I2C.WCR.CNT + 6)):
##                i2c_freq = 48000/(2*I2C.LCR.SLV + 7 + I2C.CR.DNF);
##            else:
##                i2c_freq = 48000/(I2C.LCR.SLV + 2*I2C.WCR.CNT + 6 + 7 + I2C.CR.DNF);
##        elif (i2c_mode == 1):
##            self.log(LogLevel.INFO, "I2C为快速或快速增强模式(fast-mode/fast-mode plus)")
##            if (I2C.LCR.FLV > (2*I2C.WCR.CNT + 6)):
##                i2c_freq = 48000/(2*I2C.LCR.FLV + 7 + I2C.CR.DNF);
##            else:
##                i2c_freq = 48000/(I2C.LCR.FLV + 2*I2C.WCR.CNT + 6 + 7 + I2C.CR.DNF);
##        else:
##            self.log(LogLevel.WARN, "I2C为高速模式，需使用专用格式访问",\
##                     "请确认是否需要3.4M高速模式(HS-mode)")
##            i2c_freq = 48000/(I2C.LCR.HLVH + I2C.LCR.HLVL + 7 + 2*I2C.CR.DNF);
##        self.log(LogLevel.INFO, f"接口频率约{i2c_freq:.0f}kHz")
##        if (i2c_freq >= 1000):
##            self.log(LogLevel.INFO, "外部上拉电阻推荐1K欧")
##        elif (i2c_freq >= 400):
##            self.log(LogLevel.INFO, "外部上拉电阻推荐4.7K欧")

        #检查I2S模块状态
        #TODO

            
        #输出分析结果
        if (inst_error==1):
            self.log(LogLevel.ERROR, f"{self.periph_name}配置发现错误",\
                     "请检查配置")
        else:
            self.log(LogLevel.INFO, f"{self.periph_name}分析结束，未发现错误")
        
register_analyzer("I2S", I2SAnalyzer)

