 # -- coding: utf-8 --
from dbg_uart2 import DbgUart
import struct
from cmsis_svd.parser import SVDParser
from enum import Enum
import sys

analyzer_db = {}

class Peripheral:
    def __init__(self, name):
        self.name = name

class Register:
    pass


class LogLevel(Enum):
    INFO = 1
    WARN = 2
    ERROR = 3

class Analyzer:
    def __init__(self, device, periph_name, port="COM1", baudrate=1000000):
        self.device = device
        self.periph_name = periph_name
        self.port = port
        self.baudrate = baudrate

    def run(self):
        pass

    def get_instance_num(self, periph_name):
        inst_num = -1
        schema = self._get_schama(periph_name)
        if not schema:
            return inst_num
    
        if len(schema._group_name) < len(periph_name):
            inst_num = int(periph_name[len(schema._group_name):])

        return inst_num
    
    
    def _get_schama(self, periph_name):
        schema = None
        for peripheral in self.device.peripherals:
            periph_name = periph_name.upper()
            if peripheral.name == periph_name:
                schema = peripheral
                break

        return schema


    # 按外设名称读取寄存器值
    def read_peripheral(self, periph_name):
        schema = None
        data = None
        for peripheral in self.device.peripherals:
            periph_name = periph_name.upper()
            if peripheral.name == periph_name:
                schema = peripheral
                break
        if schema:
            data = self.read_peripheral_data(schema)

        return data


    # 读取外设寄存器数值
    def read_peripheral_data(self, schema):
        global args
        reader = DbgUart(self.port, self.baudrate)
        if not reader.enter_dbg_mode():
            print("打开调试模式失败")
            sys.exit("请检查串口编号与波特率是否正确")
            return None

        data = reader.read(schema.base_address, (schema.registers[-1].address_offset + 4) // 4)
        if not data:
            return None

        periph = Peripheral(schema.name)
        cnt = 0
        for r in schema.registers:
            reg = Register()
            setattr(periph, r.name, reg)
            reg_data, = struct.unpack('<L', data[r.address_offset:(r.address_offset+4)])
            reg.value = reg_data
            for f in reversed(r.fields):
                setattr(reg, f.name, (reg_data >> f.bit_offset) & ((1 << f.bit_width) - 1))

            cnt += 4

        return periph


    def print_reg(self, periph):
        if not periph:
            return
        
        print(f"模块: {periph.name}")
        # 打印所有寄存器的值
        for reg, fields in periph.__dict__.items():
            print(f"{reg}:")
            if type(fields) is not Register:
                continue
            for field, value in fields.__dict__.items():
                print(f"\t{field}:0x{value:X}")

    def log(self, level, msg, suggestion=""):
        print(f"[{level.name}] {msg}")
        if (level==LogLevel.ERROR or level==LogLevel.WARN):
            print(f"[Suggestion]: {suggestion}")


def register_analyzer(name, analyzer):
    analyzer_db[name] = analyzer
