#!/bin/python

import numpy as np
import eseries as es

def calc_fsw_from_r_fset(r_fset):
    fsw = 67600 / (r_fset / 1e3 + 6.4)
    fsw = fsw * 1e3
    return fsw

def calc_r_fset_from_fsw(fsw):
    fsw = fsw / 1e3
    r = 67600 / (fsw) - 6.4
    r = r * 1e3
    return r

def calc_r_iset_from_i(i):
    i = i * 1e3
    r = 2000 * 1.2 / i
    r = r * 1e3
    return r
def calc_i_from_r_iset(r):
    r = r * 1e-3
    i = 2000 * 1.2 / r
    i = i * 1e-3
    return i

def calc_vout(r1, r2, k):
    r1 = r1 / 1000
    r2 = r2 / 1000
    v = (1.2 / r2 + k * 0.0387) * r1 + 1.2
    return v

switching_freq = 1.1e6
output_voltage_nom = 24 + 0.9
inductor_value = 22e-6
input_voltage = 12
output_current_per_lane = 60e-3
desired_e_series = es.E12
r1 = 560e3
r2 = 100e3

# Calculate the parameters
print('Calculating for the given parameters:')
print(f'{switching_freq = }')
print(f'{output_voltage_nom = } and {input_voltage = }')
print(f'{inductor_value =}')
print(f'{desired_e_series = }')
print('')

rfset = calc_r_fset_from_fsw(switching_freq)
print(f'{rfset = }')

# Find the nearest value in the e series
rfset = es.find_nearest(desired_e_series, rfset)
f_sw = calc_fsw_from_r_fset(rfset)

print(f'The nearest value from the E series is: {rfset = }')
freq_error = (f_sw - switching_freq) / switching_freq * 100
print(f'Resulting switching frequency is {f_sw} (Error: {freq_error:.1f} %)')

print(f"Desired output current per lane is {output_current_per_lane} A")
r_iset = calc_r_iset_from_i(output_current_per_lane)
print(f'Resulting in {r_iset = }')
r_iset = es.find_nearest(desired_e_series, r_iset)
output_current_per_lane = calc_i_from_r_iset(r_iset)
print(f'Nearest e series value {r_iset = } resulting in an LED current of {output_current_per_lane} A')

d = (output_voltage_nom - input_voltage) / output_voltage_nom
d_inv = 1-d
print(f"Expected duty cycle: {d}")
i_ripple = (output_voltage_nom- input_voltage) / (2 * inductor_value * f_sw) * (input_voltage / output_voltage_nom)
print(f'Ripple current: {i_ripple} A')
i_sat_min = output_current_per_lane * 4 / d_inv + i_ripple
print(f'Minimum saturation current of inductor: {i_sat_min:.3f} A')

print(f'Voltage divider {r1 = } | {r2 = }')
print(f'Output voltage initial: {calc_vout(r1, r2, 0.88)} V')
print(f'Output voltage maximum: {calc_vout(r1, r2, 1)} V')
print(f'Output voltage minimum: {calc_vout(r1, r2, 0)} V')

ovp = output_voltage_nom + (r1/r2 + 1)*(2.3 - 1.2)

print(f'Over voltage protection: {ovp} V')

ratio = r1/r2
print(f'Resistance ratio is {ratio}')
if f_sw <= 1150e3:
    ratio_range = (5, 10)
else:
    ratio_range = (10, 20)

if ratio < ratio_range[0] or ratio > ratio_range[1]:
    print('Ratio is outside recommended limits!')
else:
    print('Resistance ratio is inside recommended limits')

# Loop stability
cfb = 1 / (2 * np.pi * 20e3 * r1 )
print(f'Loop stability capacitor value: {cfb} F')
