import math
def calc_possible_dpi(interline_gaps, dpi_ph, fire_decimation, ph_type, verbose):
  possible_dpi = []  # dpi
  for dpi_img in range(1,3000): # dpi
    dpi_possible   = True
    for interlinegap in interlinegaps:
      mult_int    = int(interlinegap*(dpi_img/dpi_ph))
      mult_double = interlinegap*(dpi_img/dpi_ph)
      if (mult_double - mult_int) > 0:
        dpi_possible = False
    if dpi_possible:
      possible_dpi.append(dpi_img)

  mod_2 = []
  divide_possible = []
  decimation_value = []
  decimation_possible = []
  for dpi_img in possible_dpi:
    # check if value is mod 2
    if math.fmod((dpi_img/dpi_ph),(9.765625e-4)) == 0:
      mod_2.append(True)
      
    else:
      mod_2.append(False)
      
    # check if interlinegaps can be divided by the value
    divide_possible_temp = True
    for interlinegap in interlinegaps:
      if not math.fmod(interlinegap*(dpi_img/dpi_ph),1) == 0:
        divide_possible_temp = False
    divide_possible.append(divide_possible_temp)

    # Calc Decimation value
    decimation_value.append((float(fire_decimation) * float(dpi_ph)/float(dpi_img)) - 1)
    decimation_possible_temp = False
    if decimation_value[-1] == int(decimation_value[-1]):
      decimation_possible_temp = True
    decimation_possible.append(decimation_possible_temp)
      
  # Calc number of possible Resolutions
  nbr_of_resolutions = 0
  for i in range(len(possible_dpi)):
    if mod_2[i] and decimation_possible[i] and divide_possible[i]:
      nbr_of_resolutions = nbr_of_resolutions + 1
    
    
  # Print results
  print("{} Possible Resolutions of {} with {} Subpixels".format(nbr_of_resolutions, ph_type, fire_decimation))
  if verbose:
    print("         |                |     For Jetmapping                       |      For Interpolator               ")
    print("dpi_img  | dpi_img/dpi_ph | Possible Division | Possible Calculation | Decimation Register Value | Possible")
    print("         |                | for FPGA          | for PH               |                           |         ")
    print("---------+----------------+-------------------+----------------------+---------------------------+---------")
    for i in range(len(possible_dpi)):
      dpi_img = possible_dpi[i]
      if mod_2[i] and divide_possible[i] and decimation_possible[i]:
        print("--> {:4} | {:14} | {}              | {}                 | {:7.4}                   | {}  <--".format(dpi_img,dpi_img/dpi_ph,mod_2[i], divide_possible[i], decimation_value[i], decimation_possible[i]))
      elif mod_2[i]:
        print("    {:4} | {:14} | {}              | {}                 | {:7.4}                   | {}".format(dpi_img,dpi_img/dpi_ph,mod_2[i], divide_possible[i], decimation_value[i], decimation_possible[i]))
      else:
        print("    {:4} | {:14} | {}             | {}                 | {:7.4}                   | {}".format(dpi_img,dpi_img/dpi_ph,mod_2[i], divide_possible[i], decimation_value[i], decimation_possible[i]))  

"""
Explanation: Calculation Variable Prinhead Resolution
WpWiki Page
Possible Resolutions
$if(pixel_{offset} * \frac{dpi_{img}}{dpi_{ph}} = integer)$
Possible in FPGA if $integer = multiple_of(2)$
Other Restrictions are (not considerated in the calculation)

ErgoSoft Rip can only create images with a DPI of max $2400dpi$
The Speed of the machine is limited. with $360dpi$ default speed if $840\frac{mm}{s}$. At $180dpi$ default speed should be $1680\frac{mm}{s}$, but in the Siemens PLC only 3 digits are used to set the print speed. Higher speeds are also not tested on the Digiround.
End of explanation
"""


interlinegaps = [12,28,40] # px
fire_decimation = 36 # nbr of subpixels
dpi_ph = 360.0             # dpi
calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Konica Minolta KM1024i", verbose=True)

#for fire_decimation in range(50):
#  calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Konica Minolta KM1024i", verbose=False)

"""
Explanation: KM1024i
End of explanation
"""


interlinegaps   = [20]  # px
fire_decimation = 32    # nbr of subpixels
dpi_ph          = 360.0 # dpi
calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Konica Minolta KM1024", verbose=True)

"""
Explanation: KM1024
End of explanation
"""


interlinegaps   = [13,279,292] # px
fire_decimation = 32           # nbr of subpixels
dpi_ph          = 600.0        # dpi
calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Ricoh GEN5", verbose=True)

"""
Explanation: Ricoh Gen5
End of explanation
"""


interlinegaps = [0,18,60,72,78,90,106,124,130,142,148,160,164,176,182,194,202,214,220,232,236,248,254,266,272,290,306,318,324,336,378,396] # px
fire_decimation = 32    # nbr of subpixels
dpi_ph          = 600.0 # dpi
calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Kyocera KJ4B 30kHz", verbose=True)

"""
Explanation: Kyocera KJ4B 30kHz
End of explanation
"""


interlinegaps = [0,20,70,80,90,100,150,160,170,180,220,230,240,250,260,300,310,320,330,380,390,400,410,460,480] # px
fire_decimation = 32    # nbr of subpixels
dpi_ph          = 600.0 # dpi
calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Kyocera KJ4B 40kHz", verbose=True)

"""
Explanation: Kyocera KJ4B 40kHz
End of explanation
"""


interlinegaps = [0,80,90,170,180,260,270,350,360,440,450,530,540,620,630,710,810,890,900,980,990,1070,1080,1160,1170,1250,1260,1340,1350,1430,1440,1520] # px
fire_decimation = 36     # nbr of subpixels
dpi_ph          = 1200.0 # dpi
calc_possible_dpi(interlinegaps, dpi_ph, fire_decimation, "Kyocera KJ412S", verbose=True)

"""
Explanation: Kyocera KJ4B_1200_64k
End of explanation
"""


import math
def calc_floatparts(val):
  # get integer part
  int_val = int(val)
  # get 1/16 val
  temp_val = val-int_val
  if( (temp_val%0.125) == 0.0625 ):
    sixteenth_val = 1
    temp_val = temp_val - (temp_val%0.125)
  else:
    sixteenth_val = 0
  # get 1/8 val
  if( (temp_val%0.25) == 0.125 ):
    eigth_val = 1
    temp_val = temp_val - (temp_val%0.25)
  else:
    eigth_val = 0
  # get 1/4 val
  if( (temp_val%0.5) == 0.25 ):
    quater_val = 1
    temp_val = temp_val - (temp_val%0.5)
  else:
    quater_val = 0
  # get 1/2 val
  if( (temp_val%1) == 0.5 ):
    half_val = 1
    temp_val = temp_val - (temp_val%1)
  else:
    half_val = 0
  # Check if we got all
  if temp_val == 0:
    print("Calulation correct")
  else:
    print("Calulation wrong")

  # Concat for getting hex value
  hex_val = int_val*16 + half_val*8+ quater_val*4 + eigth_val*2 + sixteenth_val
    
  print("value       = {}".format(val))
  print("hex value   = 0x{:08X}".format(hex_val))
  print("integerpart = {}".format(int_val))
  print("1/2 part    = {}".format(half_val))
  print("1/4 part    = {}".format(quater_val))
  print("1/8 part    = {}".format(eigth_val))
  print("1/16 part   = {}".format(sixteenth_val))
  print("")

calc_floatparts(1.0)
calc_floatparts(3.0 + 0.5 + 0.25 + 0.125 + 0.0625 + 0.03125)
calc_floatparts(8.0 + 0.5 + 0.25 + 0.125 + 0.0625)
calc_floatparts(63.0 + 0.5 + 0.25 + 0.125 + 0.0625) # max value

"""
Explanation: Register Calculation image_to_printhead_resolution
image_to_printhead_resolution content
[31:4] = integer part
[3]    = 1/2 part
[2]    = 1/4 part
[1]    = 1/8 part
[0]    = 1/16 part
End of explanation
"""


# vhdl function ported to python
def unsigned_num_bits(num):
  _nbits = 1
  _n = num
  while(_n > 1):
    _nbits = _nbits + 1
    _n     = _n / 2
  return _nbits

def calcPosXVal(maxVal_x, maxMult, xpos_BitNb):
  for i in range(int(round(maxMult))):
    val = maxVal_x * i
    
    print("MaxVal: {:4}  Multiplication: {:2} Result: {:5} NumberofBits(needed/available): ({:2}/{:2})".format(maxVal_x, i, val, unsigned_num_bits(val), xpos_BitNb))

"""
Explanation: Pixel Pos Values
End of explanation
"""


calcPosXVal(12, 63.9375, 8)

"""
Explanation: KM1024i
End of explanation
"""


calcPosXVal(480, 63.9375, 12)

"""
Explanation: KY KJ4B 40KHz
End of explanation
"""


calcPosXVal(292, 63.9375, 10)

"""
Explanation: Ricoh GEN5
End of explanation
"""


