#! /usr/bin/python3
#-*- coding: utf-8 -*-

#### ###########################################################################
####
####
####    Řídící program pro tlačítko Raspberry PI
####
####    PhDr. Mgr. Jeroným Klimeš, Ph.D. 2023-08-23
####
####    Rozšíření Raspberry či Arduina o tlačítko, bzučák či ledku, je to 
####    nejednodušší. Až mě překvapilo, co mě tento krátký program zabral času.
####    Tak snad Vám bude k užitku. 
####    Případné dotazy na jeronym.klimes@seznam.cz či www.klimes.us
####
####
#### ###########################################################################

def help_i_need_somebody():
    import textwrap
    print("\nNapoveda\n")
    print(textwrap.fill("Program rozlisuje - prosty stisk ci pusteni tlacitka, prenuti, dvojklik a dlouhy stisk, ktery resetuje prepnuti a dvojklik."))
    print(textwrap.fill("Jinymi slovy, kdyz si to na posledni chvili rozmyslite, tak drzite tlacitko, dokud neuslysite troji pipnuti, pak rychle pustite tlacitko, a tak nedojde k prepnuti ani dvojkliku."))
    print(textwrap.fill("V teto ukazce dvojklik prepina slysitelnost bzucaku. Dlouhystisk vypise tuto napovedu."))
    print(textwrap.fill("Pouzivam aktivni buzzer, bzucak, ktery je bez odporu mezi ground a nize uvedenym pinem (pin_buzzer). Stejne tak i tlacitko (reset tlacitko ze stareho PC) je bez odporu mezi ground a pinem (pin_button)."))
    print(textwrap.fill("Jsou to vzdy dva sousedni piny [9,11] a [20,22] a jim odpovidajici cisla GPIO_17 a GPIO_25)."))
    print("\n\n")
    #print("\nNápověda\n")
    #print(textwrap.fill("Používám aktivní buzzer, bzučák, který je bez odporu mezi ground a níže uvedeným pinem (pin_buzzer). Stejně tak i tlačítko (reset tlačítko ze starého PC) je bez odporu mezi ground a pinem (pin_button)."))
    #print(textwrap.fill("Jsou to vždy dva sousední piny [9,11] a [20,22] a jim odpovídající čísla GPIO_17 a GPIO_25)."))
    #print(textwrap.fill("Program rozlišuje - prostý stisk či puštění tlačítka, přenutí, dvojklik a dlouhý stisk, který resetuje přepnutí a dvojklik."))
    #print(textwrap.fill("Jinými slovy, když si to na poslední chvíli rozmyslíte, tak držíte tlačítko, dokud neuslyšíte trojí pípnutí, pak rychle pustíte tlačítko, a tak nedojde k přepnutí ani dvojkliku."))
    #print(textwrap.fill("V této ukázce dvojklik přepíná slysitelnost bzučáku."))
    #print("\n\n")
    
#### Uživatelské proměnné
debug=True
debug=False
pin_button = 25
pin_buzzer = 17
step       = 0.05 # sekundy je cyklus
limit_meziklik=3 # tři kroky, tedy priblizne 0,2 sekundy 
limit_dlouhostisk=20 # cca 5 sekund
mlceni=False

import time
import RPi.GPIO as GPIO
#Set warnings off (optional)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(pin_button,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(pin_buzzer,GPIO.OUT)

prepinac   = False
dvojklik   = False
last_state = False
prvoklik   = False
meziklik   = 0
dlouhostisk = 0

def pipac(pocet):
    global mlceni
    if (mlceni==False):
        for i in range(0,pocet):
            GPIO.output(pin_buzzer,GPIO.HIGH)
            time.sleep(0.1)
            GPIO.output(pin_buzzer,GPIO.LOW)
            time.sleep(0.1)

def tlacitko():
    print ("Tlacitko", 1-button_state)

def prepinatko(stav):
    if (stav):
        print ("        Prepinac 1")
    else:
        print ("        Prepinac 0")

def dvojklikatko(stav):
    global mlceni
    if (stav):
        print("             Dvojklik A - mlceti zlato")
        mlceni=True
    else:
        print("             Dvojklik B - pipati stribro")
        mlceni=False

def dlouhostiskatko():
    print("Dlouhý stisk - reset")
    help_i_need_somebody()

while True:
    button_state = GPIO.input(pin_button)
    if button_state!=last_state:
        if (debug): 
            print("Tlacitko", 1-button_state, "Meziklik",meziklik, "Prvoklik", prvoklik)    
        else:
            tlacitko()
    if button_state == 0: # tlacitko stlacene
        if (last_state!=button_state): # doslo ke zmene
            if (prvoklik==True and meziklik<=limit_meziklik): # tak je to dvojklik
                pipac(2)
                if dvojklik==True:
                    dvojklik=False
                    dvojklikatko(False)
                else:
                    dvojklik=True
                    dvojklikatko(True)
                prvoklik=False
                dlouhostisk=0
            elif (meziklik>limit_meziklik): # pri stisku nulujeme citace
                prvoklik=True # Toto je prvoklik, ubehla doba pro dvojklik
                meziklik=0
        else: # nacitani dlouhostisku a vyhodnoceni.
            dlouhostisk=dlouhostisk+1
            if dlouhostisk>limit_dlouhostisk:
                pipac(3)
                meziklik=0
                dlouhostisk=0
                prvoklik=False
                dlouhostiskatko()
    else: # tlacitko je pustene
        if (prvoklik==True and meziklik>limit_meziklik): # vyprsel cas dvojklik, takze je to obycejny staceni/prepnuti
            pipac(1)
            if prepinac==False: 
                prepinac=True
                prvoklik=False 
                prepinatko(True)
                dlouhostisk=0
            elif prepinac==True:
                prepinac=False
                prvoklik=False 
                prepinatko(False)
                dlouhostisk=0
        meziklik=meziklik+1 # pocitame prubehy
    last_state=button_state
    time.sleep(step)