import machine import time I2C_ADDR = 0x60 I2C_SDA_PIN = 8 I2C_SCL_PIN = 9 # --- Si5351 Register Map --- REG_ENABLE_CTRL = 3 REG_CLK0_CTRL = 16 REG_PLL_A_PARAMS = 26 REG_MS0_PARAMS = 42 REG_NVM_BURN = 161 REG_PLL_RESET = 177 REG_CRYSTAL_LOAD = 183 def calc_fractional_regs(a, b, c): """Calculates the 8 bytes of register data for Si5351 PLLs and MultiSynths.""" # Use floor division (//) for exact integer math, avoiding float inaccuracies p1 = 128 * a + ((128 * b) // c) - 512 p2 = 128 * b - c * ((128 * b) // c) p3 = c # Return as a bytearray so it can be sent in a single I2C block write return bytes([ (p3 >> 8) & 0xFF, p3 & 0xFF, ((p1 >> 16) & 0x03) | (((p2 >> 16) & 0x03) << 4), (p1 >> 8) & 0xFF, p1 & 0xFF, (((p3 >> 16) & 0x0F) << 4) | ((p2 >> 16) & 0x0F), (p2 >> 8) & 0xFF, p2 & 0xFF ]) def setup(i2c): def write_reg(reg, val): i2c.writeto_mem(I2C_ADDR, reg, bytes([val])) # 1. Disable all outputs and power down clocks safely write_reg(REG_ENABLE_CTRL, 0xFF) for reg in range(16, 24): write_reg(reg, 0x80) # 2. Set Crystal Load Capacitance to 10pF # 0xD2 sets 10pF (11b) while preserving the required reserved bits (010010b) write_reg(REG_CRYSTAL_LOAD, 0xD2) # 3. Configure PLLA (Multiplier: a=24, b=24, c=25) plla_regs = calc_fractional_regs(24, 24, 25) i2c.writeto_mem(I2C_ADDR, REG_PLL_A_PARAMS, plla_regs) # 4. Configure MultiSynth0 (Divider: a=40, b=0, c=1) ms0_regs = calc_fractional_regs(40, 0, 1) i2c.writeto_mem(I2C_ADDR, REG_MS0_PARAMS, ms0_regs) # 5. Power up CLK0, set integer mode, route to PLLA write_reg(REG_CLK0_CTRL, 0x4F) # 6. Reset PLLA to apply frequency parameters write_reg(REG_PLL_RESET, 0x20) # 7. Re-enable CLK0 Output write_reg(REG_ENABLE_CTRL, 0xFE) print("Success: Si5351 configured for 15.6 MHz on CLK0.") def burn(i2c): def write_reg(reg, val): i2c.writeto_mem(I2C_ADDR, reg, bytes([val])) print("Initiating NVM Burn sequence...") write_reg(REG_NVM_BURN, 0xC0) time.sleep(1) # Wait for NVM burn to complete print("NVM Burn complete. Settings are now permanent.") if __name__ == "__main__": i2c = machine.I2C(0, scl=machine.Pin(I2C_SCL_PIN), sda=machine.Pin(I2C_SDA_PIN), freq=400000) setup(i2c) # Ensure VDD is stable at 3.3V before executing the burn process burn(i2c)