import wiringpi as wp
from time import sleep

i2c_addr = 0x21
base_addr = 81
pins = range(base_addr, base_addr + 16)
pins = [22, 27, 17, 19, 13, 6, 5, 20, 21, 26, 1, 12, 16, 4]

""" has to be inverted
pins_segment_select = [81, 82, 83]"""
pins_segment_select = [83, 82, 81]
pins_segment_select = [22, 27, 17]

""" has to be inverted
pins_digit_select = [84, 85, 86, 87] """
#pins_digit_select = [87, 86, 85, 84]
pins_digit_select = [19, 13, 6, 5]

#pins_display_select = [89, 90, 91, 92, 93]
pins_display_select = [1, 20, 12, 16, 4]
pin_run = 95
pin_run = 21
pin_lt = 88
pin_lt = 26

high = False
low = not high

"""
def init():
  wp.mcp23017Setup(base_addr, i2c_addr)
  for pin in pins:
    wp.pinMode(pin, 1)
init()
"""
def init():
  wp.wiringPiSetupGpio()
  for pin in pins:
    wp.pinMode(pin, 1)
init()

def init_ones():
  for pin in pins:
    wp.digitalWrite(pin, 1)
def init_zeros():
  for pin in pins:
    wp.digitalWrite(pin, 0)
def init_high():
  for pin in pins:
    wp.digitalWrite(pin, high)
def init_low():
  for pin in pins:
    wp.digitalWrite(pin, low)
def dec2bin_high(dec, digits):
  bin_str = format(dec, '#0' + str(digits + 2) + 'b')[2:]
  return map(lambda x: high if x == '1' else low, bin_str)
def dec2bin_low(dec, digits):
  bin_str = format(dec, '#0' + str(digits + 2) + 'b')[2:]
  return map(lambda x: low if x == '1' else high, bin_str)
def toggle_run():
  if wp.digitalRead(pin_run) == 0:
    #print("enable RUN")
    wp.digitalWrite(pin_run, 1)
  else:
    #print("disable RUN")
    wp.digitalWrite(pin_run, 0)
def toggle_lt():
  if wp.digitalRead(pin_lt) == 0:
    #print("enable LT")
    wp.digitalWrite(pin_lt, 1)
  else:
    #print("disable LT")
    wp.digitalWrite(pin_lt, 0)
def check_decimal_for_validity(decimal, lower, upper):
  if type(decimal) is not type(1):
    print("input not a decimal")
    return False
  if decimal < lower or decimal > upper:
    print("decimal out of range")
    return False
  return True

def select_segment(decimal):
  #if not check_decimal_for_validity(decimal, 0, 7):
  #  print("input error, no segment selected")
  #  return
  values = dec2bin_high(decimal, 3)
  pss = pins_segment_select
  wp.digitalWrite(pss[0], values[0])
  wp.digitalWrite(pss[1], values[1])
  wp.digitalWrite(pss[2], values[2])

def select_digit(decimal):
  #if not check_decimal_for_validity(decimal, 0, 9):
  #  print("input error, no digit selected")
  #  return
  values = dec2bin_low(decimal, 4)
  pds = pins_digit_select
  wp.digitalWrite(pds[0], values[0])
  wp.digitalWrite(pds[1], values[1])
  wp.digitalWrite(pds[2], values[2])
  wp.digitalWrite(pds[3], values[3])

def select_display(decimal):
  #if not check_decimal_for_validity(decimal, 1, 5):
  #  print("input error, no display selected")
  #  return
  wp.digitalWrite(pins_display_select[int(decimal) - 1], high)
  
def unselect_display(decimal):
  #if not check_decimal_for_validity(decimal, 1, 5):
  #  print("input error, no display unselected")
  #  return
  wp.digitalWrite(pins_display_select[int(decimal) - 1], low)
  
def unselect_all_displays():
  for pin in pins_display_select:
    wp.digitalWrite(pin, low)
    
def select_all_displays():
  for pin in pins_display_select:
    wp.digitalWrite(pin, high)
    
def toggle_display(decimal):
  select_display(decimal)
  unselect_display(decimal)

def read_pins():
  for pin in pins:
    print(str(pin) + ' --> ' + str(wp.digitalRead(pin)))

def digit2display(disp, dig):
  select_display(disp)
  select_digit(dig)
  unselect_all_displays()

def num2seg(num, seg):
  select_segment(seg)
  select_digit(num)
  toggle_display(3)

def fancy(number,disp):
  num_arr = map(int, list(str(number)))
  num_arr = num_arr + [0] * max(0, (8 - len(num_arr)))
  if len(num_arr) > 8:
    num_arr = num_arr[:8]
  print(num_arr)
  num_arr = num_arr[-1::-1]

  for j in range(5000):  
    for i in range(8):
      select_segment(i)
      select_digit(num_arr[i])
      toggle_display(disp)
      sleep(0.001)
      
def al(number,s):
    num_arr = map(int, list(str(number)))[-1::-1]
    for i in range(5000):
        for segment in range(8):
            for disp in range(2,6):
                select_segment(segment)
                select_digit(num_arr[segment])
                num_arr = num_arr[-1::-1]
                toggle_display(disp)
                sleep(s)

def ini():
    init()
    init_low()
    toggle_run()

                
                
