Subversion Repositories pentevo

Rev

Rev 1271 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #!/usr/bin/env python
  2.  
  3. import sys
  4. from sympy import *
  5. import math
  6. import matplotlib.pyplot as plt
  7. import numpy as np
  8.  
  9. #e24 = [1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1];
  10. #e6  = [1.0,                1.5,                2.2,                3.3,                4.7,                6.8               ];
  11.  
  12.  
  13. def select_pvalues_list(values='e24'):
  14. # returns [1.0, ..., 9.1] list (for e24)
  15.  
  16.     if values=='e24':
  17.         r = [1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1]
  18.     elif values=='e12':
  19.         r = [1.0,      1.2,      1.5,      1.8,      2.2,      2.7,      3.3,      3.9,      4.7,      5.6,      6.8,      8.2     ]
  20.     elif values=='e6':
  21.         r = [1.0,                1.5,                2.2,                3.3,                4.7,                6.8               ]
  22.     else:
  23.         sys.stderr.write('wrong argument given!\n')
  24.         raise NameError('stop here')
  25.         sys.exit(1)
  26.  
  27.     r = [r[-1]*0.1] + r + [r[0]*10.0]
  28.  
  29.     return r
  30.  
  31. def select_two_nearest(val,val_exp,pvalues_name='e24'):
  32.  
  33.     def my_lt(v1,v2):
  34.         return (v1<v2) and (not math.isclose(v1,v2,rel_tol=1e-3))
  35.  
  36.     def my_gt(v1,v2):
  37.         return (v1>v2) and (not math.isclose(v1,v2,rel_tol=1e-3))
  38.  
  39.  
  40.     pvalues = select_pvalues_list(pvalues_name)
  41.  
  42.     # select range
  43.     if my_lt(val, min(pvalues[1:-1])):
  44.         while my_lt(val, min(pvalues[1:-1])):
  45.             if my_lt(val, max(pvalues[1:-1])*0.1):
  46.                 val     = val     * 10.0;
  47.                 val_exp = val_exp *  0.1;
  48.             else:
  49.                 break;
  50.  
  51.     elif my_gt(val, max(pvalues[1:-1])):
  52.         while my_gt(val, max(pvalues[1:-1])):
  53.             if my_gt(val, min(pvalues[1:-1])*10.0):
  54.                 val     = val     *  0.1;
  55.                 val_exp = val_exp * 10.0;
  56.             else:
  57.                 break;
  58.  
  59.  
  60.     # select nearest values
  61.     for i in range(len(pvalues)-1):
  62.         vdn = pvalues[i];
  63.         vup = pvalues[i+1];
  64.         if vdn<=val and val<=vup:
  65.             break;
  66.  
  67.     vdn_exp = val_exp
  68.     vup_exp = val_exp
  69.  
  70.     if vdn<pvalues[1]:
  71.         vdn *= 10.0
  72.         vdn_exp *= 0.1
  73.  
  74.     if vup>pvalues[-2]:
  75.         vup *= 0.1
  76.         vup_exp *= 10.0
  77.  
  78.     return [ (vdn,vdn_exp), (vup,vup_exp) ];
  79.  
  80. def select_one_nearest(val,pvalues_name='e24'):
  81.  
  82.     lval = select_two_nearest(val,1.0,pvalues_name)
  83.  
  84.     (vdn,vdn_exp) = lval[0]
  85.     (vup,vup_exp) = lval[1]
  86.  
  87.     vdn *= vdn_exp
  88.     vup *= vup_exp
  89.  
  90.     if math.fabs( (vdn-val)/val ) <= math.fabs( (vup-val)/val ):
  91.         return vdn
  92.     else:
  93.         return vup
  94.  
  95. def get_neighbour_value(val,dir='up',pvalues_name='e24'):
  96.    
  97.     pvalues = select_pvalues_list(pvalues_name)
  98.     exp = 1.0
  99.  
  100.     found_v = None
  101.     found_idx = None
  102.     for idx,v in enumerate(pvalues[1:-1]):
  103.         if math.isclose(val,v,rel_tol=1e-3):
  104.             found_v = v
  105.             found_idx = idx
  106.  
  107.             #print(' found {} {}'.format(found_v,found_idx))
  108.             break
  109.    
  110.     if found_v is None:
  111.         raise NameError('found_v is None!')
  112.         sys.exit(1)
  113.  
  114.     if dir=='up':
  115.         if math.isclose(found_v,pvalues[-2],rel_tol=1e-3):
  116.             next_v = pvalues[1]
  117.             exp = 10.0
  118.         else:
  119.             tmp = pvalues[1:-1]
  120.             #print('  tmp {}'.format(tmp))
  121.             next_v = tmp[found_idx+1]
  122.        
  123.     elif dir=='down':
  124.         if math.isclose(found_v,pvalues[1],rel_tol=1e-3):
  125.             next_v = pvalues[-2]
  126.             exp = 0.1
  127.         else:
  128.             tmp = pvalues[1:-1]
  129.             next_v = tmp[found_idx-1]
  130.  
  131.     else:
  132.         raise NameError('dir is neither "up" nor "down"!')
  133.         sys.exit(1)
  134.  
  135.     return (next_v,exp)
  136.  
  137.  
  138. def r_fix(r,r_e24,pvalues_name='e24'):
  139.         # select parallel or series additional resistor for r to be closest to r_e24
  140.         if r>=r_e24: # series
  141.                 r_exact = r-r_e24
  142.                 (rlo_,rhi_)=select_two_nearest(r_exact,1,pvalues_name)
  143.                 rlo = rlo_[0] * rlo_[1]
  144.                 rhi = rhi_[0] * rhi_[1]
  145.                 if abs(r_exact-rlo)<abs(r_exact-rhi):
  146.                         return (r_e24+rlo,rlo,'series')
  147.                 else:
  148.                         return (r_e24+rhi,rhi,'series')
  149.  
  150.         else: # parallel (r<r_e24)
  151.                 r_exact = 1.0/(1.0/r - 1.0/r_e24)
  152.                 (rlo_,rhi_)=select_two_nearest(r_exact,1,pvalues_name)
  153.                 rlo = rlo_[0] * rlo_[1]
  154.                 rhi = rhi_[0] * rhi_[1]
  155.                 r_rlo = 1.0/(1.0/r_e24+1.0/rlo)
  156.                 r_rhi = 1.0/(1.0/r_e24+1.0/rhi)
  157.                 if abs(r_rlo-r)<abs(r_rhi-r):
  158.                         return (r_rlo,rlo,'parallel')
  159.                 else:
  160.                         return (r_rhi,rhi,'parallel')
  161.  
  162.  
  163.  
  164.  
  165. def calc_dac():
  166.  
  167.     r3,r2,r1,r0,rpd = symbols('r3 r2 r1 r0 rpd', real=True, positive=True)
  168.  
  169.     eq1 = Eq( 1/(1/r3 + 1/r2 + 1/r1 + 1/r0 + 1/rpd), 75.0 )  # output impedance
  170.     eq2 = Eq( r3 / (1/(1/r2+1/r1+1/r0+1/rpd)), (5-0.8)/0.8 ) # bit[3]=1, bits[2:0]=0,   level (unloaded) = 0.8v
  171.     eq3 = Eq( r2 / (1/(1/r3+1/r1+1/r0+1/rpd)), (5-0.4)/0.4 ) # bit[2]=1, bits[3,1:0]=0, level (unloaded) = 0.4v
  172.     eq4 = Eq( r1 / (1/(1/r3+1/r2+1/r0+1/rpd)), (5-0.2)/0.2 ) # bit[1]=1, bits[3:2,0]=0, level (unloaded) = 0.2v
  173.     eq5 = Eq( r0 / (1/(1/r3+1/r2+1/r1+1/rpd)), (5-0.1)/0.1 ) # bit[0]=1, bits[3:0]=0,   level (unloaded) = 0.1v (all on: 1.5v)
  174.  
  175.     # solve the set
  176.     u_solve = solve( [eq1, eq2, eq3, eq4, eq5], [r3,r2,r1,r0,rpd], dict=True )
  177.  
  178.     if len(u_solve)!=1:
  179.         sys.stderr.write("Many or no solutions: {} !\n".format(u_solve))
  180.         exit(1)
  181.    
  182.     print(u_solve)
  183.  
  184.     # ideal result should be:
  185.     #
  186.     # r3 = 468.75
  187.     # r2 = 937.5
  188.     # r1 = 1875
  189.     # r0 = 3750
  190.     # rpd = 107+1/7
  191.  
  192. def calc_dac_out(r0=3750,r1=1875,r2=937.5,r3=468.75,rpd=(107+1/7),rload=75,val=15):
  193.  
  194.     assert type(val) is int
  195.     assert 0<=val and val<=15
  196.  
  197.     if val==0:
  198.         return 0.0
  199.  
  200.     sup = 0
  201.     sdn = 1/rpd + 1/rload
  202.  
  203.     if val & 1:
  204.         sup += 1/(r0+5)
  205.     else:
  206.         sdn += 1/(r0-5)
  207.  
  208.     if val & 2:
  209.         sup += 1/(r1+5)
  210.     else:              
  211.         sdn += 1/(r1-5)
  212.  
  213.     if val & 4:
  214.         sup += 1/(r2+5)
  215.     else:              
  216.         sdn += 1/(r2-5)
  217.  
  218.     if val & 8:
  219.         sup += 1/(r3+5)
  220.     else:              
  221.         sdn += 1/(r3-5)
  222.  
  223.     return 5.0/(sdn*(1/sup+1/sdn))
  224.  
  225.  
  226.  
  227. def draw_dac(r0=3750,r1=1875,r2=937.5,r3=468.75,rpd=(107+1/7),label='unknown'):
  228.  
  229.     plt.figure(1)
  230.     n = range(0,16)
  231.  
  232.     v_ideal = [calc_dac_out(val=i) for i in n]
  233.     v_e24   = [calc_dac_out(r0,r1,r2,r3,rpd,val=i) for i in n]
  234.  
  235.     plt.plot(n,v_ideal,linewidth=2,label='ideal')
  236.     plt.plot(n,v_e24,linewidth=2,label=label)
  237.     plt.legend(title='video DAC')
  238.     plt.xlim(0,15)
  239.     plt.xticks(np.linspace(0,15,num=16))
  240.     plt.xlabel('DAC value')
  241.     plt.ylim(0,0.8)
  242.     plt.yticks(np.linspace(0,0.8,num=17))
  243.     plt.ylabel('Volts')
  244.     plt.grid(True)
  245.     plt.show()
  246.  
  247.  
  248. def main():
  249.  
  250.     #calc_dac()
  251.     #draw_dac()
  252.  
  253.     ric = 20
  254.     r3 = 468.75 - ric
  255.     r2 = 937.5 - ric
  256.     r1 = 1875 - ric
  257.     r0 = 3750 -ric
  258.     rpd = 107+1/7
  259.  
  260.     r0_1 = select_one_nearest(r0,pvalues_name='e24')
  261.     r1_1 = select_one_nearest(r1,'e24')
  262.     r2_1 = select_one_nearest(r2,'e24')
  263.     r3_1 = select_one_nearest(r3,'e24')
  264.     rpd_1 = select_one_nearest(rpd,'e24')
  265.  
  266.     print(r0_1,r1_1,r2_1,r3_1,rpd_1)
  267.  
  268.     r0_2 = r_fix(r0,r0_1,pvalues_name='e24')
  269.     r1_2 = r_fix(r1,r1_1,pvalues_name='e24')
  270.     r2_2 = r_fix(r2,r2_1,pvalues_name='e24')
  271.     r3_2 = r_fix(r3,r3_1,pvalues_name='e24')
  272.     rpd_2 = r_fix(rpd,rpd_1,pvalues_name='e24')
  273.  
  274.     print(r0_2,r1_2,r2_2,r3_2,rpd_2)
  275.  
  276.  
  277.     rr0 = r0_1 + ric + r0_2[1]
  278.     rr1 = r1_1 + ric + r1_2[1]
  279.     rr2 = r2_1 + ric
  280.     rr3 = r3_1 + ric + r3_2[1]
  281.     rrpd = 1/(1/rpd_1 + 1/rpd_2[1])
  282.  
  283.     print(rr0,rr1,rr2,rr3,rrpd)
  284.  
  285.     draw_dac(r0=rr0,r1=rr1,r2=rr2,r3=rr3,rpd=rrpd,label='2xE24')
  286.  
  287.  
  288.  
  289. if __name__=="__main__":
  290.     main()
  291.  
  292.  
  293.  
  294.