



def calculate_ftw_freq(ftw):
    fs = 1e9  
    freq = (fs*ftw)/2**48
    return freq

def parse_header (header) :
    # bit 0 - Terminate bit #
    # bit 1 - number of words for Attenuator #
    # bit 2 - number of words for DAC #
    # bits [4:3] - number of words for Pot #
    # bits [7:6] - number of words for ShReg #
    # bits [11:9] - number of words for MAX#
    # bits [15:12] - number of words for LMX #
    # bits [17:16] - number of words for GPIO #
    # bits [21:19] - number of words for DDS #
    #bit [23] - mode; 0 - SingleSpi, 1 - QuadSpi #
    terminate_bit = header & 0x01
    num_words_attenuator = (header >> 1) & 0x01
    num_words_dac = (header >> 2) & 0x01
    num_words_pot = (header >> 3) & 0x03
    num_words_shreg = (header >> 6) & 0x03
    num_words_max = (header >> 9) & 0x07
    num_words_lmx = (header >> 12) & 0x0F
    num_words_gpio = (header >> 16) & 0x03
    num_words_dds = (header >> 19) & 0x07
    mode = (header >> 23) & 0x01
    return {
        "terminate_bit": terminate_bit,
        "num_words_attenuator": num_words_attenuator,
        "num_words_dac": num_words_dac,
        "num_words_pot": num_words_pot,
        "num_words_shreg": num_words_shreg,
        "num_words_max": num_words_max,
        "num_words_lmx": num_words_lmx,
        "num_words_gpio": num_words_gpio,
        "num_words_dds": num_words_dds,
        "mode": "SingleSpi" if mode == 0 else "QuadSpi"
    }


def main():
    # Enter the width of the QSpi. Possible values are 8, 16, 24, 32
    width = int(input("Enter the width of the QSpi: "))
    if width not in [8, 16, 24, 32]:
        print("Invalid width. Please enter 8, 16, 24, or 32.")
        return
    # Ask if you need to parse a header
    parse_header_input = input("Do you want to parse a header? (y/n): ").lower() == 'y'
    if parse_header_input:
        # 
        # Enter the mosi0Reg value in hex.
        mosi0_header_input = input("Enter the Mosi0Reg value for header (hex): ")
        try:
            mosi0_header = int(mosi0_header_input, 16)
            if mosi0_header < 0 or mosi0_header > 255:
                print("Invalid Mosi0Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
        # Enter the mosi1Reg value in hex.
        mosi1_header_input = input("Enter the Mosi1Reg value for header (hex): ")
        try:
            mosi1_header = int(mosi1_header_input, 16)
            if mosi1_header < 0 or mosi1_header > 255:
                print("Invalid Mosi1Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
        # Enter the mosi2Reg value in hex.
        mosi2_header_input = input("Enter the Mosi2Reg value for header (hex): ")
        try:
            mosi2_header = int(mosi2_header_input, 16)
            if mosi2_header < 0 or mosi2_header > 255:
                print("Invalid Mosi2Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
        # Enter the mosi3Reg value in hex.
        mosi3_header_input = input("Enter the Mosi3Reg value for header (hex): ")
        try:
            mosi3_header = int(mosi3_header_input, 16)
            if mosi3_header < 0 or mosi3_header > 255:
                print("Invalid Mosi3Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
        # Combine the Mosi registers into a single header value.
        if width == 32:
            header_input = (mosi0_header | (mosi1_header << 8) | 
                            (mosi2_header << 16) | (mosi3_header << 24))
        elif width == 24:
            header_input = (mosi0_header | (mosi1_header << 6) | 
                            (mosi2_header << 12) | (mosi3_header << 18))
        elif width == 16:
            header_input = (mosi0_header | (mosi1_header << 4) | 
                            (mosi2_header << 8) | (mosi3_header << 12))
        elif width == 8:
            header_input = (mosi0_header | (mosi1_header << 2) | 
                            (mosi2_header << 4) | (mosi3_header << 6))

        
        # Parse the header
        parsed_header = parse_header(header_input)
        
        # Print the parsed values
        print("\n--- Parsed Header ---")
        for key, value in parsed_header.items():
            print(f"{key}: {value}")
        print("\n--- End of Header Parsing ---")
    
    # Do you want to contnue 
    continue_input = input("Do you want to continue (y/n): ").lower() == 'y'
    if not continue_input:
        print("Exiting the program.")
        return
    # Ask if this is a DDS device
    is_dds = input("Is this a DDS device? (y/n): ").lower() == 'y'
    
    dds_word_count = 0
    dds_values = []
    
    # If DDS, we need to collect 4 words
    total_words = 4 if is_dds else 1
    
    # Collect data for all required words
    all_qmosi_values = []
    
    for word in range(total_words):
        if is_dds and word > 0:
            print(f"\n--- Entering data for DDS word {word+1}/4 ---")
            
        # Enter the Mosi0Reg value in hex.
        mosi0_input = input("Enter the Mosi0Reg value (hex): ")
        try:
            mosi0_reg = int(mosi0_input, 16)
            if mosi0_reg < 0 or mosi0_reg > 255:
                print("Invalid Mosi0Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
            
        # Enter the Mosi1Reg value in hex.
        mosi1_input = input("Enter the Mosi1Reg value (hex): ")
        try:
            mosi1_reg = int(mosi1_input, 16)
            if mosi1_reg < 0 or mosi1_reg > 255:
                print("Invalid Mosi1Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
            
        # Enter the Mosi2Reg value in hex.
        mosi2_input = input("Enter the Mosi2Reg value (hex): ")
        try:
            mosi2_reg = int(mosi2_input, 16)
            if mosi2_reg < 0 or mosi2_reg > 255:
                print("Invalid Mosi2Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
            
        # Enter the Mosi3Reg value in hex.
        mosi3_input = input("Enter the Mosi3Reg value (hex): ")
        try:
            mosi3_reg = int(mosi3_input, 16)
            if mosi3_reg < 0 or mosi3_reg > 255:
                print("Invalid Mosi3Reg value. Please enter a value between 0x00 and 0xFF.")
                return
        except ValueError:
            print("Invalid hex value. Please enter a valid hexadecimal number.")
            return
            
        # Merge the Mosi registers into a single value.
        if width == 32:
            qmosi_value = mosi0_reg | (mosi1_reg << 8) | (mosi2_reg << 16) | (mosi3_reg << 24)
        elif width == 24:
            qmosi_value = mosi0_reg | (mosi1_reg << 6) | (mosi2_reg << 12) | (mosi3_reg << 18)
        elif width == 16:
            qmosi_value = mosi0_reg | (mosi1_reg << 4) | (mosi2_reg << 8) | (mosi3_reg << 12)
        elif width == 8:
            qmosi_value = mosi0_reg | (mosi1_reg << 2) | (mosi2_reg << 4) | (mosi3_reg << 6)
        
        all_qmosi_values.append(qmosi_value)
        
        if not is_dds or word == total_words - 1:
            print("\n--- Result ---")
            
            # Print individual values
            for i, value in enumerate(all_qmosi_values):
                if is_dds:
                    print(f"DDS Word {i+1}: {value:#0{width//4 + 2}x}")
                else:
                    print(f"QSpi Mosi value: {value:#0{width//4 + 2}x}")
            
            if is_dds and width == 24:
                dds_combined = 0
                for i, value in enumerate(all_qmosi_values):
                    dds_combined |= (value << (24 * (3-i)))  
                
                print(f"\nDDS 96-bit combined value: {dds_combined:#0{96//4 + 2}x}")
                #bin #
                print(f"DDS 96-bit combined value (binary): {dds_combined:096b}")
                

                # Calculate the DDS frequency if needed. Take the lower 48 bits.
                ftw = dds_combined & 0xFFFFFFFFFFFF
                freq = calculate_ftw_freq(ftw)
                print(f"DDS Frequency: {freq:.2f} Hz")

if __name__ == "__main__":
    main()