#!/usr/bin/python
# -*- encoding: utf-8 -*-

# posledni uprava kodu:
# 4.brezna 2013 
#    drobna uprava kodu v podprogramu zadavani cisla pres klavesnici "zadanicisla()"
#    (pri zadani tecky, pomlcky, nebo prazdneho retezce je vystupem znak "0")  

import time
import smbus
import os

bus = smbus.SMBus(1)   # novejsi varianta RasPi (512MB)
#bus = smbus.SMBus(0)  # starsi varianta RasPi (256MB)

addr = 0x20 # adresa expanderu MCP23017 (podle nastavenych adresovacich vyvodu)





def main():

# ******** priklady pouziti podprogramu *********

  init()             # zakladni nastaveni systemu - smery portu na expanderu, reset a nastaveni displeje


#=================================================
  # tisk textu na urcenou pozici
  pozice(0,4)            # nastaveni pozice pro tisk (radka,sloupec); cislovano od 0,0 - LH roh
  slovo("AHOJ")          # vytisknuti slova na prvni radku
  pozice(1,2)            # nastaveni pozice pro tisk
  slovo("123456")        # vytisknuti slova na druhou radku

  time.sleep(3)

  # kdyz se neurci pozice, pokracuje se automaticky za predchozim textem
  slovo("789")

  
#=================================================
  time.sleep(3)    # pauza 
  disclear()       # a smazani celeho displeje. Aktualni pozice se nastavi na levy horni roh


#=================================================
  # tisk specialnich znaku podle kodovacich tabulek v datasheetu (zalezi na typu ROM - JAP/EU)
  # datasheet je tady:  http://www.crystalfontz.com/controllers/ST7066U.pdf
  slovo("neASCII znaky:")
  pozice (1,0)    # zacatek spodni radky
  neascii(0xE0)   # znak mala alfa (JAP) / beta (EU)
  neascii(0xF4)   # znak velka omega (JAP) / mala omega (EU)
  neascii(0xC5)   # znak "krizek s ocaskem" (JAP) / sipka nahoru (EU)
  neascii(0xB2)   # znak "solarni panel" (JAP) / stupen (EU)
  
#=================================================
  time.sleep(3)
  disclear()


#=================================================
  # tisk cele radky od pozice 0 do konce (doplni pripadne mezerami)
  celaradka("text na horni r." , 0) # prvni parametr je text, druhy je cislo radky (pocitano od 0)
  time.sleep(3)
  celaradka("kratsi text", 0)       # zbytek puvodni radky se automaticky premaze mezerami

#=================================================
  time.sleep(3)
  disclear()


#=================================================
  # rozblikani kurzoru na zadane pozici
  celaradka("simulace vstupu",0)
  pozice(1,0)
  slovo("vstup:")   # nejdriv napsat nejaky napis
  blikkurzor(1,7)   # a za nim rozblikat kurzor 

  time.sleep(3)

  # simulace zadavani textu
  # kdyz je kurzor nastaveny na blikani, zobrazuje se automaticky za poslednim zadanym znakem
  pozice(1,7)
  znak("X")         # zobrazeni 1 znaku (stejne jako funkce slovo, ale o trochu rychlejsi)
  time.sleep(2)
  znak("Y")  
  time.sleep(2)
  znak("Z")  
  
  zruskurzor()      # zruseni blikani kurzoru


#=================================================
  time.sleep(3)
  disclear()

#=================================================
  # uzivatelsky definovana grafika pro 8 znaku (mozno vyuzit pro zobrazeni ceskych znaku)
  celaradka("graficke znaky:",0) # bezny napis na horni radku

  # definice tretiho znaku (c s hackem)
  grafika(3, 0x0A, 0x04, 0x0f , 0x10 , 0x10 , 0x10, 0x0f , 0x00)
  pozice (1,5)
  neascii (3)  # vytisknout 4x za sebe na spodni radku treti definovany znak
  neascii (3)
  neascii (3)
  neascii (3)

  time.sleep(3)

  # pri zmene definice grafickeho znaku se automaticky meni VSECHNY prave zobrazene znaky se stejnym kodem !!
  # zmena grafiky ze znaku "c s hackem" na "kolecko s teckou"
  grafika(3, 0x00, 0x0e, 0x11 , 0x15 , 0x11 , 0x0e, 0x00 , 0x00)
  
  time.sleep(3)

  # timto zpusobem je mozne graficky znak animovat
  # (priklad: pohyb prerusovane svisle cary zprava do leva v sesti krocich). Sirka znaku je 5 bodu
  for i in range(6):  # (posun bude o 0 az 4 body). V poslednim kroku se znak vymaze (cara se vysune mimo zobrazovanou oblast)
    posun = (1 << i)
    grafika(3, posun, posun, 0 , posun , posun , 0, posun , posun)
    time.sleep(0.5)
   
#=================================================
  # ovladani nevyuziteho 7. bitu na expanderu (vyuziti napriklad pro zvlastni signalizacni LEDku)
  celaradka("ovladani 7. bitu",0)

  setbit7(1)      # nastaveni na logickou 1 (rozsviceni LEDky)
  time.sleep(3)
  setbit7(0)      # nastaveni na logickou 0 (zhasnuti LEDky)
  time.sleep(3)
  disclear()

#=================================================
  # cteni stavu na 7. bitu expanderu (vyuziti napriklad pro dalsi tlacitko)
  celaradka("stav bitu 7:",0)  
  celaradka("cteci cyklus:",1)  

  for cyk in range (20):
    stav = getbit7()   # precteni stavu
    pozice(0,13)
    znak(str(stav))    # zobrazeni cisla na displeji
    pozice(1,14)
    slovo(str(cyk))           
    time.sleep(0.5)

#=================================================
  time.sleep(1)
  disclear()

#=================================================
  # zablikani podsvetem
  slovo("test podsvetu")
  podsvet(0)
  time.sleep(1)
  podsvet(1)
  time.sleep(1)
  podsvet(0)
  time.sleep(1)
  podsvet(1)
  disclear()         # smazani celeho displeje


#=================================================
  # listovani v seznamu polozek pomoci klaves "A", "B" a "D"
  slovo("mesic:")

  # (seznam polozek je definovany nize - primo v podprogramu)
  vybrano = listovani(0,7,6) # poloha seznamu na displeji (radek, sloupec) a index prvni zobrazene polozky

  disclear()
  celaradka("Vybrany mesic:",0)
  celaradka("index polozky: " + str(vybrano[0]),1)
  time.sleep(3)
  celaradka("text: " + vybrano[1],1)

#=================================================
  time.sleep(5)
  disclear()


#=================================================
  # jednoducha kalkulacka (A + B) s vyuzitim maticove klavesnice na expanderu na portu B
  #    (zvladne i zaporna a desetinna cisla)
  celaradka("test klavesnice",0)
  celaradka("zadej A:",1)
  cislo1 = zadanicisla(1,8,5)     # podprogram pro zadavani cisel na displej (radka,sloupec,maximalni delka vstupu)
  celaradka("zadej B:",1)
  cislo2 = zadanicisla(1,8,5)     

  cislofloat1 = float(cislo1)     # vystupem funkce je textovy retezec, ktery je treba prevest na float
  cislofloat2 = float(cislo2)
  soucet =  cislofloat1 + cislofloat2     # a pak se s tim da pracovat jako s normalnim cislem
  celaradka ("soucet = " + str(soucet),1) # soucet se zase musi pred zobrazenim prevest na text (funkce str()) 

#=================================================
  time.sleep(5)
  disclear()
 

#=================================================
  # zobrazeni a prolezani tri-urovnoveho menu pomoci klaves "A", "B" a "D" (klavesa "C" ukonci menu)
  # definice vsech polozek menu je primo v podprogramu
  multimenu()


#=================================================
  podsvet(0)   # posledni zhasne ... :-)


#=================================================
# ***************  konec demonstracniho programu ************  




# ++++++++  dale nasleduji vsechny podprogramy +++++++++++++++


def setbit7(bit7):   # nastaveni nevyuziteho bitu 7 na portu A na "1" nebo "0" 
  bus.write_byte_data(addr,0x00,0x00) # cely port A na OUT
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  if (bit7 == 1):
    novy = (porta | 0x80) # nevyuzity bit (GPA7) nastavit na 1
  else:
    novy = (porta & 0x7F) # nevyuzity bit (GPA7) nastavit na 0 
  bus.write_byte_data(addr,0x12,novy) 


def getbit7():  # cteni nevyuziteho bitu 7 na portu A
  bus.write_byte_data(addr,0x00,0x80) # bit 7 na portu A na vstup
  bus.write_byte_data(addr,0x0C,0x80) # pripojit Pull-Up na bitu 7 na portu A 
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  bit7 = ((porta & 0x80)>>7)
  return bit7



def podsvet(pods):   # 1... rozsvitit; 0...zhasnout
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A

  if (pods == 1):
    novy = (porta | 0x40) # podsvetovy bit (GPA6) nastavit na 1
  else:
    novy = (porta & 0xBF) # podsvetovy bit (GPA6) nastavit na 0 
  bus.write_byte_data(addr,0x12,novy) 
  

def regsel(rs): # 0...prikazy; 1...data
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  if (rs == 1):
    novy = (porta | 0x20) # pin prepinace rezimu (GPA5) nastavit na 1 (data) 
  else:
    novy = (porta & 0xDF) # pin prepinace rezimu (GPA5) nastavit na 0 (prikazy)
  bus.write_byte_data(addr,0x12,novy) 


def strobe():   # zapis nastavenych dat do displeje kratkym nulovym pulsem
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  novy = (porta & 0xEF)                # strobe bit (GPA4) nastavit na 0
  bus.write_byte_data(addr,0x12,novy)
  time.sleep(0.0001) 
  bus.write_byte_data(addr,0x12,porta) # vratit strobe bit (GPA4) do 1
  time.sleep(0.0001) 

      
def pulbajt(pb):   # odeslani pulbajtu do displeje (pb je v rozsahu 0 az 15)
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  signaly = (porta & 0xf0)
  bus.write_byte_data(addr,0x12, pb + signaly) 
  strobe()


def bajt(b):   # odeslani bajtu rozlozeneho na 2 pulky do displeje
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  signaly = (porta & 0xf0)
  hornipulbajt= ((b & 0xf0)>>4)
  dolnipulbajt= (b & 0x0f)
  bus.write_byte_data(addr,0x12,hornipulbajt + signaly) 
  strobe()
  bus.write_byte_data(addr,0x12,dolnipulbajt + signaly) 
  strobe()


def neascii(kod):  #tisk specialnich znaku s ASCII kodem vetsim nez 127
  regsel(1)
  bajt(kod)  

      
def znak(char):  # zobrazeni jednoho ASCII znaku na aktualni pozici 
  regsel(1)
  porta = bus.read_byte_data(addr,0x12) # precist aktualni stav na portu A
  signaly = (porta & 0xf0)
  hornipulbajt= ((ord(char) & 0xf0)>>4)
  dolnipulbajt= (ord(char) & 0x0f)
  bus.write_byte_data(addr,0x12,hornipulbajt + signaly) 
  strobe()
  bus.write_byte_data(addr,0x12,dolnipulbajt + signaly) 
  strobe()
  

def slovo(text):   # zobrazeni textu na aktualni pozici 
                   #(POZOR, aby text neobsahoval znaky s ASCII kodem vyssim nez 127)
  for i in range(len(text)):
    znak(text[i:i+1])
    

def celaradka(text,radka):  # doplneni textu mezerami na 16 znaku a zobrazeni na radce
  pozice(radka,0)
  while len(text)<16:       # celkova sirka displeje (v pripade pouziti sirsich displeju je treba zmenit)
    text = text+" "
  slovo(text)


def pozice(rad,slo): # pocitano od pozice 0,0 = levy horni roh
  if rad == 0:       #horni radka
    adresa = 0x80 + slo
  if rad == 1:       #druha radka
    adresa = 0xC0 + slo

#  pro ctyrradkovy displej by melo fungovat toto, ale nemam to vyzkousene
#  if rad == 2: #treti radka
#    adresa = 0x94 + slo
#  if rad == 3: #dolni radka
#    adresa = 0xD4 + slo

  regsel(0)
  bajt(adresa)

def blikkurzor(rad,slo): # rozblikat kurzor na pozici [rad,slo] 
  if rad == 0:
    adresa = 0x80 + slo
  if rad == 1:
    adresa = 0xC0 + slo

#  pro ctyrradkovy displej by melo fungovat toto, ale nemam to vyzkousene
#  if rad == 2: #treti radka
#    adresa = 0x94 + slo
#  if rad == 3: #dolni radka
#    adresa = 0xD4 + slo

  regsel(0)
  bajt(adresa)
  bajt(0x0F)


def zruskurzor():  # vypnuti blikaciho kurzoru
  regsel(0)
  bajt(0x0C)


def disclear():    # smazani celeho displeje a nastaveni pozice na 0,0
  regsel(0)
  bajt(0x01)
  time.sleep(0.003)
  bajt(0x02)
  time.sleep(0.003)


# moznost nadefinovat si az 8 vlastnich znaku
def grafika(index,b0,b1,b2,b3,b4,b5,b6,b7): #index znaku 0 az 7, nasledovany osmi bajty grafiky 
  regsel(0)
  bajt(0x40+(index*8)) 
  regsel(1) 
                   # priklad definice pro "y s carkou" (nejvyssi 3 bity se nevyuzivaji)
  bajt(b0)         # 0x02   --- ---X-
  bajt(b1)         # 0x04   --- --X--
  bajt(b2)         # 0x11   --- X---X
  bajt(b3)         # 0x11   --- X---X  
  bajt(b4)         # 0x0F   --- -XXXX  
  bajt(b5)         # 0x01   --- ----X  
  bajt(b6)         # 0x0E   --- -XXX-  
  bajt(b7)         # 0x00   --- -----


def init():
  
  # nastaveni expanderu - smery portu (IN/OUT)
  bus.write_byte_data(addr,0x00,0x00) # cely port A na OUT
  bus.write_byte_data(addr,0x01,0x0F) # bity 0 az 3 portu B na IN, 4 az 7 na OUT (maticova klavesnice)
  bus.write_byte_data(addr,0x0D,0x0F) # na vstupni piny B portu pripnout vnitrni Pull-Up odpory

  bus.write_byte_data(addr,0x12,0x10) # pin strobe zacina v "1"

  podsvet(1)

  # reset displeje - sekvence kodu podle datasheetu (nastaveni "ctyrdratoveho" datoveho vstupu)
  regsel(0)

  pulbajt(3)
  pulbajt(3)

  pulbajt(3)
  pulbajt(2)

  pulbajt(2)
  pulbajt(8)

  pulbajt(0)
  pulbajt(12)

  pulbajt(0)
  pulbajt(6)

  pulbajt(0)
  pulbajt(1)



# podprogram pro listovani v seznamu pomoci klaves "A", "B". (vyber klavesou "D")
def listovani(radka,sloupec,startpolozka):  # poloha prvniho znaku na displeji a prvni zobrazena polozka ze seznamu

  # definice polozek (pro jednoduchost zobrazeni jsou vsechny polozky stejne dlouhe)
  # pri ruznych delkach polozek by se muselo zajistit mazani casti displeje pred zobrazenim kratsich polozek
  # jinak by se treba pri prechodu z polozky "cervenec" na "srpen" zobrazil "srpennec"
  seznam={}
  seznam[0]  = "leden   "
  seznam[1]  = "unor    "
  seznam[2]  = "brezen  "
  seznam[3]  = "duben   "
  seznam[4]  = "kveten  " 
  seznam[5]  = "cerven  "
  seznam[6]  = "cervenec"
  seznam[7]  = "srpen   "
  seznam[8]  = "zari    "
  seznam[9]  = "rijen   "
  seznam[10] = "listopad"
  seznam[11] = "prosinec"

  maxpolozka = len(seznam) -1     # index posledni polozky (11) = pocet polozek v seznamu -1

  aktualnipolozka = startpolozka  # zobrazeni startovaci polozky na urcenych souradnicich
  pozice(radka,sloupec)
  slovo (seznam[aktualnipolozka])

  predchozitlacitko = ""
  stisknuto = ""
  while (stisknuto != "D"):        # klavesa "D" je vyber polozky (ENTER)
    stisknuto = klavesa(predchozitlacitko)
    predchozitlacitko = stisknuto  # pomocna promenna pro zabraneni automatickemu opakovani klaves pri dlouhem stisknuti
    if (len(stisknuto)>1):         # pri stisku vice klaves soucasne vzit jen prvni znak
      stisknuto=stisknuto[1:2]


    if (stisknuto == "A"):         # predchozi polozka
      aktualnipolozka = aktualnipolozka - 1
      if (aktualnipolozka < 0): aktualnipolozka = 0  # ochrana na podteceni indexu pod 0

    if (stisknuto == "B" ):        # nasledujici polozka
      aktualnipolozka = aktualnipolozka + 1
      if (aktualnipolozka > maxpolozka): aktualnipolozka = maxpolozka  # ochrana preteceni pres maximalni index

    pozice(radka,sloupec)          # tisk vybrane polozky na displej
    slovo (seznam[aktualnipolozka])

  # navratove hodnoty jsou: vybrany index a odpovidajici retezec ze seznamu 
  return aktualnipolozka , seznam[aktualnipolozka]   




#podprogram pro zadavani cisla pres klavesnici a displej
def zadanicisla(radka,sloupec,maxdelka):  # poloha na displeji , maximalni delka zadavaneho retezce
  blikkurzor(radka,sloupec)
  retezec=""

  predchozitlacitko = ""
  stisknuto = ""
  while (stisknuto != "D"):        # klavesa "D" je [Enter]
    stisknuto = klavesa(predchozitlacitko)
    predchozitlacitko = stisknuto  # pomocna promenna pro zabraneni automatickemu opakovani klaves pri dlouhem stisknuti

    if (len(stisknuto)>1):         # pri stisku vice klaves soucasne vzit jen prvni znak
      stisknuto=stisknuto[1:2]


    if (stisknuto == "C" and len(retezec) > 0):     # klavesa "C" ma vyznam jako [BackSpace]
      retezec=retezec[0:len(retezec)-1] + " "       # nejdriv nahrazeni posledniho znaku mezerou
      pozice(radka,sloupec)
      slovo(retezec)                                # a zobrazeni na displeji (tim se posledni znak smaze)
      retezec=retezec[0:len(retezec)-1]             # zruseni te mezery v promenne
      pozice(radka, sloupec + len(retezec))         # a rozblikani kurzoru za poslednim znakem


    if (stisknuto == "-"):                  # prepinani znamenka "-" pred cislem:
      if (retezec[0:1] == "-"):             # kdyz je na zacatku "-" tak ho zrusit
        retezec = retezec[1:] + " "         # stejna cast jako u mazani posledniho znaku klavesou "C"
        pozice(radka,sloupec)
        slovo(retezec)
        retezec=retezec[0:len(retezec)-1]
        pozice(radka, sloupec + len(retezec))
      else:                                 # kdyz na zacatku "-" neni
        if (len(retezec) < maxdelka):       # a kdyz se pred cislo to "-" vejde,
          retezec = "-" + retezec           # tak doplneni znamenka "-" pred cislo


    if (stisknuto == "."):                 # zadavani desetinne tecky:
      if (not "." in retezec):             # kdyz cislo jeste neobsahuje des. tecku,
        if (len(retezec) < maxdelka - 1):  # a kdyz se tam jeste vejde,
          retezec = retezec + "."          # tak ji vloz do retezce (neda se zapsat na uplne posledni pozici)
                                           #  pri maximalni delce napr 5 znaku nejde zadat "6842." nebo "-851."

    # omezeni vkladani pouze na cisla "0" az "9"
    if ((ord(stisknuto) > 47 and ord(stisknuto) < 58) and len(retezec) < maxdelka): 
      retezec = retezec + stisknuto

      
    pozice(radka,sloupec)           # po kazde zmene promenne aktualizovat cast displeje s cislem
    slovo(retezec)                  # kurzor se automaticky zobrazuje ZA poslednim vytisknutym cislem
    if (len(retezec) == maxdelka):  # ale pri dosazeni maximalni delky retezce blika kurzor POD poslednim znakem
      blikkurzor(radka , sloupec + maxdelka - 1)

  zruskurzor()

  if(retezec == "" or retezec == "-" or retezec == "."):  # kdyz se nezada zadne cislo, tak je vystupem 0
    retezec = "0"

  return retezec 



def klavesa(predchozitlacitko):    # cekani na stisk 1 klavesy
  tlacitko = klavesnice()
  while (tlacitko == predchozitlacitko or tlacitko == ""): # zabraneni opakovani jednoho tlacitka pri dlouhem stisku
    tlacitko = klavesnice()
    if (tlacitko==""):             # druhy stisk stejneho tlacitka je mozny az po uvolneni
      predchozitlacitko="uvolneno"
    time.sleep(0.1)
  return tlacitko  




def klavesnice():   # cteni a vyhodnoceni okamziteho stavu vsech 16 klaves

  # klavesnice je pripojena tak, ze ma radkove vyvody na expanderu na pinech GPB4 az GPB7
  # radky (vystupy z expanderu) jsou na GPB4 az GPB7
  # sloupce (vstupy do expanderu) jsou na GPB0 az GPB3

  # definice rozlozeni klaves pro klavesnici KB1604
  #    (klavesa "*" nahrazuje znak "-", klavesa "#" ma vyznam desetinne tecky)
  radka = ['123A' , '456B' , '789C' , '-0.D'] 

  indexradky = 0
  stisknuto = ""
  for r in [0xE0 , 0xD0 , 0xB0 ,  0x70]:       # postupne se nastavi "0" na kazde ze ctyr radek 
    bus.write_byte_data(addr,0x13,r)
    time.sleep(0.01)                           # pauza setina sekundy na kazdou radku
    kodsloupce = bus.read_byte_data(addr,0x13) # precteni stavu portu (celeho, vcetne stavu radek)
    jendolnibity = (kodsloupce  & 0x0F)        # zajimave jsou pouze dolni 4 bity (vstupni)

    for s in range(0,4):                       # prochazeni 4 vstupnich bitu a hledani stavu "0"
      if (jendolnibity & 2**s) == False:       # prevod nulovych bitu na tlacitkovy znak
        stisknuto = stisknuto + radka[indexradky][s] 
          
    indexradky = indexradky + 1


  return stisknuto                             # vysledkem je retezec, ktery obsahuje seznam stisknutych klaves 



def zobrazmultimenu (uro , par1 , par2 , par3):
  # format horni radky na displeji se meni podle urovne menu
  # v nejvyssi urovni se zobrazuje napis MENU
  if (uro == 1): horr = "MENU            "

  # v prostredni urovni je to napis MENU a nazev nejvyssi polozky (napr: MENU-Upravy)
  if (uro == 2): horr = "MENU - " + menu[par1,0,0] 

  # v nejnizsi urovni se napis MENU zkrati na M a vedle jsou nazvy nadrazenych polozek (napr: M-Napoveda-Obsah)
  if (uro == 3): horr = "M-" + menu[par1,0,0] + "-" + menu[par1,par2,0] 

  if (par[uro] < 1):  # pri listovani v submenu je mozne se proklikat pred prvni polozku a pres ni se dostat o uroven vyse
    dolr = "  .."     # v tom pripade se v dolni radce zobrazi dve tecky
  else:
    dolr = menu[par1 , par2 , par3] # jinak se v dolni radce zobrazuje aktualni polozka v prislusnem menu / submenu

  celaradka(horr,0)  # zobrazeni menu na displeji (horni radka)
  celaradka(dolr,1)  # zobrazeni menu na displeji (dolni radka)


menu={}
akce={}
maxuroven={}
par={}

def multimenu():  # viceurovnove menu ma displeji a jeho prochazeni pomoci klavesnice

  # definice polozek pro viceurovnove menu
  global  menu
  global  akce
  global  maxuroven
  global  par

  maxuroven[0,0,0] = 4      # pocet polozek v nejvyssi urovni (Soubor, Upravy, Nastaveni, Napoveda)

  menu[1,0,0] = "Soubor"    # nazev prvni polozky v nejvyssi urovni menu
  akce[1,0,0] = "0"         # 0=nevyvolava spusteni zadneho programu
  maxuroven[1,0,0] = 3      # pocet polozek v submenu teto polozky (Otevrit, Ulozit, Novy)

  menu[1,1,0] = "Otevrit"   # nazev prvni polozky submenu v menu "Soubor"
  akce[1,1,0] = "sudo python /home/pi/runmenu otevrit"  #  prikaz pro spusteni polozky "Otevrit"
  maxuroven[1,1,0] = 0      # polozka "Otevrit" uz nema dalsi submenu

  menu[1,2,0] = "Ulozit"    # nazev druhe polozky submenu v menu "Soubor"
  akce[1,2,0] = "sudo python /home/pi/runmenu ulozit"   #  prikaz pro spusteni polozky "Ulozit"
  maxuroven[1,2,0] = 0      # polozka "Ulozit" uz nema dalsi submenu

  menu[1,3,0] = "Novy"      # nazev treti polozky submenu v menu "Soubor"
  akce[1,3,0] = "sudo python /home/pi/runmenu novy"     #  prikaz pro spusteni polozky "Novy"
  maxuroven[1,2,0] = 0      # polozka "Novy" uz nema dalsi submenu



  menu[2,0,0] = "Upravy"    # nazev druhe polozky v nejvyssi urovni menu
  akce[2,0,0] = "0"         # vyber polozky nevyvola spusteni zadneho programu
  maxuroven[2,0,0] = 3      # pocet polozek v submenu tet polozky (Kopirovat, Vlozit, Vlozit jinak..)

  menu[2,1,0] = "Kopirovat" # nazev prvni polozky submenu v menu "Upravy"
  akce[2,1,0] = "sudo python /home/pi/runmenu kopirovat" # prikaz pro spusteni polozky "Kopirovat"
  maxuroven[2,1,0] = 0      # polozka "Kopirovat" uz nema dalsi submenu
  
  menu[2,2,0] = "Vlozit"    # nazev druhe polozky submenu v menu "Upravy"
  akce[2,2,0] = "sudo python /home/pi/runmenu vlozit" # prikaz pro spusteni polozky "Vlozit"
  maxuroven[2,2,0] = 0      # polozka "Vlozit" uz nema dalsi submenu

  menu[2,3,0] = "Vlozit jinak" # nazev treti polozky submenu v menu "Upravy"
  akce[2,3,0] = "0"         # vybrani polozky "Vlozit jinak" nezpusobi spusteni dalsiho programu
  maxuroven[2,3,0] = 2      # polozka "Vlozit jinak" ma dalsi 2 polozky v submenu ("jako text", "jako obrazek") 

  menu[2,3,1] = "Jako text" # nazev prvni polozky submenu v polozce "Vlozit jinak"
  akce[2,3,1] = "sudo python /home/pi/runmenu vlozittxt"  # spusteni programu "Vlozit jinak" -> "jako text"
  maxuroven[2,3,1] = 0      # polozka "jako text" uz nema dalsi submenu 

  menu[2,3,2] = "Jako obrazek" # nazev druhe polozky submenu v polozce "Vlozit jinak"
  akce[2,3,2] = "sudo python /home/pi/runmenu vlozitobr"  # spusteni programu "vlozit jinak" -> "jako obrazek"
  maxuroven[2,3,2] = 0      # polozka "jako text" uz nema dalsi submenu 

  menu[3,0,0] = "Nastaveni" # nazev treti polozky v nejvyssi urovni menu
  akce[3,0,0] = "sudo python /home/pi/runmenu nastaveni" # spusteni programu po vybrani hlavni polozky "Nastaveni"
  maxuroven[3,0,0] = 0      # polozka "Nastaveni" uz pod sebou nema dalsi polozky

  menu[4,0,0] = "Napoveda"  # nazev ctvrte polozky v nejvyssi urovni menu
  akce[4,0,0] = "0"         # vybrani polozky "Napoveda" nespousti dalsi program
  maxuroven[4,0,0] = 2      # menu "Napoveda" ma pod sebou dve polozky ("Obsah", "O aplikaci")

  menu[4,1,0] = "Obsah"     # nazev prvni polozky v menu "Napoveda"
  akce[4,1,0] = "0"         # vybrani polozky "Obsah" nespousti dalsi program
  maxuroven[4,1,0] = 4      # obsah napovedy ma 4 odstavce (subpolozky)

  menu[4,1,1] = "Odstavec 1" # nazev prvniho odstavce v Obsahu napovedy
  akce[4,1,1] = "sudo python /home/pi/runmenu odstavec1" # spusteni programu na zobrazeni prvniho odstavce
  maxuroven[4,1,1] = 0      # polozka "Odstavec1" uz nema dalsi submenu 

  menu[4,1,2] = "Odstavec 2" # nazev druheho odstavce v Obsahu napovedy
  akce[4,1,2] = "sudo python /home/pi/runmenu odstavec2" # spusteni programu na zobrazeni druheho odstavce
  maxuroven[4,1,2] = 0      # polozka "Odstavec2" uz nema dalsi submenu 

  menu[4,1,3] = "Odstavec 3" # nazev tretiho odstavce v Obsahu napovedy
  akce[4,1,3] = "sudo python /home/pi/runmenu odstavec3" # spusteni programu na zobrazeni tretiho odstavce
  maxuroven[4,1,3] = 0      # polozka "Odstavec3" uz nema dalsi submenu 

  menu[4,1,4] = "Odstavec 4" # nazev ctvrteho odstavce v Obsahu napovedy
  akce[4,1,4] = "sudo python /home/pi/runmenu odstavec4" # spusteni programu na zobrazeni ctvrteho odstavce
  maxuroven[4,1,4] = 0      # polozka "Odstavec4" uz nema dalsi submenu 

  menu[4,2,0] = "O aplikaci" # nazev druhe polozky v menu "Napoveda"
  akce[4,2,0] = "sudo python /home/pi/runmenu oaplikaci" # spusteni programu po vybrani polozky "O aplikaci"
  maxuroven[4,2,0] = 0      # polozka "O aplikaci" uz nema dalsi submenu 






  par[1]=0      # listovani v nejvyssi urovni menu (Soubor->Upravy->Nastaveni->Napoveda)
  par[2]=0      # listovani v prostredni urovni menu (napriklad: Kopirovat->Vlozit->Vlozit jinak)
  par[3]=0      # listovani v nejnizsi urovni menu (napriklad: Odstavec1->Odstavec2->Odstavec3->Odstavec4)

  pocetpolozek = maxuroven[par[1],par[2],par[3]] # pocet polozek v nejvyssi urovni menu (maxuroven[0,0,0])

  uroven = 1    # zacina se v nejvyssi urovni ...
  par[1] = 1    # ...polozkou "Soubor"   (menu[1,0,0])

  zobrazmultimenu(uroven,par[1],par[2],par[3])

  predchozitlacitko = ""
  stisknuto = ""
  while (stisknuto != "C"):       # klavesa "C" je pro ukonceni MENU
    stisknuto = klavesa(predchozitlacitko)
    predchozitlacitko = stisknuto  # pomocna promenna pro zabraneni automatickemu opakovani klaves pri dlouhem stisknuti
    if (len(stisknuto)>1):         # pri stisku vice klaves soucasne vzit jen prvni znak
      stisknuto=stisknuto[1:2]


    if (stisknuto == "A"):         # predchozi polozka
      par[uroven] = par[uroven] - 1  
      if (par[uroven] == 0 and uroven == 1): # v nejvyssi urovni uz se neda "podlistovat" pod prvni polozku 
        par[uroven] = 1  
    
      if (par[uroven] < 0): # v ostatnich urovnich se da podlistovat az na nultou polozku, ktera znamena moznost vylezt o uroven vyse
        par[uroven] = 0
      zobrazmultimenu(uroven,par[1],par[2],par[3])
         
    if (stisknuto == "B"):           # nasledujici polozka
      par[uroven] = par[uroven] + 1   
      if (par[uroven] > pocetpolozek): # ochrana prekroceni maximamalniho poctu polozek v menu
         par[uroven] = pocetpolozek
      zobrazmultimenu(uroven,par[1],par[2],par[3])

    if (stisknuto == "D"):           # vyber polozky
      if (par[uroven] > 0 ):         # vnoreni do "hlubsi" urovne menu
        if (akce[par[1],par[2],par[3]] == "0"): # kdyz je "akce" pro prislusnou polozku "0", tak se jen vnori hloubeji
          uroven = uroven + 1
          par[uroven] = 0
          pocetpolozek = maxuroven[par[1],par[2],par[3]]
          par[uroven] = 1
        else:                        # kdyz je akce nejaky prikaz, bude vykonan v SHELLu
          prikaz = akce[par[1],par[2],par[3]]
          os.system (prikaz)
        zobrazmultimenu(uroven,par[1],par[2],par[3])

      else:                   # kdyz se stiskne "D" v nulté polozce menu, vyleze se o uroven vyse
        if (uroven == 1 and par[uroven] == 0): # v nejvyssi urovni uz nelze skoct vyse
          print "vyse uz to nejde"
        else:
          uroven = uroven - 1
          par[uroven] = 0
          pocetpolozek = maxuroven[par[1],par[2],par[3]]
          par[uroven] = 1
        zobrazmultimenu(uroven,par[1],par[2],par[3])








if __name__ == '__main__':
  main()
