'Zutrittskontrolle

'Dupont Mike

'2009-2010

' ****************************************************
' *********** Konfigurationsteil *********************
'
' Schnelligkeit, Prozessortyp und Baud Rate
   $regfile = "m32def.dat"
   $crystal = 3686400
   $hwstack = 100
   $swstack = 100
   $framesize = 100
   $baud = 9600                                             'Baudrate der UART: 9600 Baud

' Leider kann man diese Konstanten bei BASCOM nicht in die
' Config LCD aufnehmen, daher muss der Displaytyp zweimal eingestellt werden.
   Const Lcdrows = 2
   Const Lcdcols = 16

' Dies sind die Werte, die für die Tasten oben, unten, links und rechts
' in die Variable
' "Keypressed" geschrieben werden. Weitere Angaben zur Tastaturabfrage sind ganz
' unten.
   Const Keyup = 1
   Const Keydown = 9
   Const Keyright = 6
   Const Keyleft = 4


' Für die Texte des Menüs wird Speicherplatz verwendet, daher muss hier die
' maximale Anzahl Menüeinträge angegeben werden.
   Const Mnumaxlines = 10

' Einstellungen zum LCD
   Config Portc = Output
   Config Portd.= Output
   Config Portd.= Output
   Config Lcdpin = Pin , Db4 = Portc., Db5 = Portc., Db6 = Portc., Db7 = Portc., E = Portc., Rs = Portc.2
   Config Lcd = 16 * 2
   Cursor Off Noblink

' Einstellungen zum I2C_Bus (TWI) und der Echtzeituhr
   Ddrd = &HFE
   Ddrb.= 1
   Config Sda = Portc.1                                     ' I2C Bus konfigurieren
   Config Scl = Portc.0
   Const Ds1307w = &HD0                                     ' Addresse der Ds1307 Uhr
   Const Ds1307r = &HD1
   Config Clock = User                                      '' Interne Time/Date Routinen für Bascom konfigurieren
   Config Date = Dmy , Separator = .

' *********** Konfiguration Ende *********************


' *********** Variablendeklarationen *****************
    'Diese Variable dient dazu  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   Dim Zahl As Byte

  'Diese Variable deint dazu sicher zu gehen,dass die Peron nur einmal begrüst
  'wird und dass Fehlfunktionen aus kompensieret werden.
   Dim Only_one As Byte

  'In dieser Textreihe wird zu Begrüsende Person gespeichert.Sie darf wegen
  'Platzmangel jedoch maximal nur 10 Zeichen beanspruchen.
   Dim Person As String * 10

  'In dieser Textreihe wird die Anrede gespeichert, d.h. Herr oder Frau, sollte
  'jedoch ein nicht identifizierbarer Transpondercode erfasst werden dient die
  'Textreihe zum Anzeigen eines Fehlers in Form von "ERROR".
   Dim Anrede As String * 5

  'In dieser Textreihe befindet sich nach einer Datenverpackung der Komplette
  'gelesene Transpondercode.
   Dim S As String * 11

  'In dieser Variablen wird ein Wert gespeichert der Angibt ob der gelesene
  'Tranpondercode identifiziert wurde oder ob es sich um einen Unbekannten Code
  'handelt.
   Dim Exist As Byte

   ' In dieser Variable wird gespeichert, welcher Menüeintrag bzw.
   ' welcher Programmteil aktuell aktiv ist. Dieser Wert muss einmal
   ' gesetzt werden und kann zur Laufzeit zum Wechsel der Funktion
   ' beliebig verändert werden.
      Dim Mnuselect As Integer

   ' In dieser Variablen wird die aktuelle Anzahl der Menüeinträge
   ' gespeichert, damit man nicht unten aus dem Menü "herausscrollen" kann
   ' Diese Variable muss manuell gesetzt werden!
      Dim Mnuselectscount As Integer

   ' In dieser Variablen wird der mnuselect-Eintrag gespeichert, der
   ' angesprungen wird, wenn die "BACK"-Taste innerhalb eines Menüs gedrückt
   ' wurde.
      Dim Mnuselectback As Integer

   ' In dieser Variable wird gespeichert, auf welchem Menüeintrag der
   ' Cursor gerade steht.
      Dim Mnuselectpointer As Integer

   ' In diesen Variablen werden die Menuestrukturen hin und hergeschoben.
   ' Wenn ein Menü erstellt werden soll, wird der Text des Menüs in das
   ' Array Mnutext(x) geschrieben.
      Dim Mnutext(mnumaxlines) As String * Lcdcols

   ' In diesen Variablen wird die Programmnummer des Teils gespeichert,
   ' der angesprungen werden soll, wenn der Menüeintrag bestätigt wird.
   ' Beispeil folgt weiter unten.
      Dim Mnuselects(mnumaxlines) As Integer



   ' Einfach nur Variablen, die zum Anzeigen des Menüs gebraucht werden.
   ' Außerhalb des Menüs stehen diese Variablen zur freien Verfügung, werden
   ' allerdings von einer Menü-Erzeugung dann überschrieben. Wenn allerdings
   ' "nur kurz" ein Zähler gebraucht wird, können diese verwendet werden.
      Dim I As Integer
      Dim N As Integer
      Dim M As Integer

   ' In dieser Variablen wird der alte Menüwert gespeichert, um
   ' abzufragen, wann das Menue verlassen werden muss.
      Dim Mnuselectold As Integer

   ' In dieser Variablen wird die gedrückte Taste gespeichert.
      Dim Keypressed As Integer

'******************* Ende der Variablendeklarationen **********************





'Displayzeit zum Initialisieren und Curser Optionen
   Waitms 300
   Cursor Noblink
   Cursor Off


' Vielleicht ist die Vorgehensweise jetzt noch nicht ganz klar, wird es
' aber sicherlich gleich werden. Da das Hauptmenü üblicherweise zuerst
' angezeigt werden soll, wird der Wert mnuselect auf 0 (oder den Wert
' der Hauptmenüs) gesetzt
   Mnuselect = 0

    'Zu beginn wird der Inhalt der Textreihe gelöscht somit können keine
  'Fehlfunktionen auftreten.
   S = ""

   'Hier wird die Subroutine angegeben die im Falle eines Urxc (Serial recive)
   'Interrupts angesprungen wird.
   On Urxc On_urxc

   'Der USART,Rx complete Interrupt wird Freigeschaltet
   Enable Urxc

   'Interrupts global einschalten.
   Enable Interrupts

' LCD Löschen
   Cls
' Nach diesen Einstellungen folgt nun der eigentliche Programmaufbau.
'
' Es soll nun folgendes Programm mit dieser Menüstruktur realisiert werden:
' In den Klammern steht der jeweilige Select-Case-Wert, der im Hauptprogramm
' benutzt wird
'
' Hauptmenü (0)
' |
' -- Settings (1)------- Backlight (11) --- ON (111)
' |                    |                  |
' |                    |                  - OFF (112)
' |                    - Delete Key (12)
' |
' |
' |
' -- Key + (2)----------- Key + (21)
' |                     |
' |                     - Reserve (22)---- Reserve1 (221)
' |                                      |
' |                                      - Reserve2 (222)
' |
' |
' -- Last IN (3)

   Do

      Only_one = 0
       Select Case Mnuselect
           Case 0:
               ' Hauptmenü

               ' Die Variable gibt an, welche Funktion eine Ebene
               ' darüber liegt, das ist natürlich beim Hauptmenü
               ' ebenfalls das Hauptmenü
                   Mnuselectback = 0
               ' Dies sind die Texte und die entsprechenden
               ' mnuselect-Variable, die dann in der
               ' select-Case ausgeführt werden.
                   Mnutext(1) = "Settings"
                   Mnuselects(1) = 1
                   Mnutext(2) = "Key +"
                   Mnuselects(2) = 2
                   Mnutext(3) = "Last IN"
                   Mnuselects(3) = 3
               ' Die Anzahl der Menüeinträge
                   Mnuselectscount = 3
               ' Aufruf des Menüs
                   Gosub Mnushow
           Case 1:
               ' Untermenü "Einstellungen"

               ' Die Variable gibt an, welche Funktion eine Ebene
               ' darüber liegt.
                   Mnuselectback = 0
               ' Dies sind die Texte und die entsprechenden
               ' mnuselect-Variable, die dann in der
               ' select-Case ausgeführt werden.
                   Mnutext(1) = "Backlight"
                   Mnuselects(1) = 11
                   Mnutext(2) = "Delete Key"
                   Mnuselects(2) = 12
               ' Die Anzahl der Menüeinträge
                   Mnuselectscount = 2
               ' Aufruf des Menüs
                   Gosub Mnushow
           Case 11:
                   Mnutext(1) = "ON"
                   Mnuselects(1) = 111
                   Mnutext(2) = "OFF"
                   Mnuselects(2) = 112
               ' Die Anzahl der Menüeinträge
                   Mnuselectscount = 2
               ' Aufruf des Menüs
                   Gosub Mnushow
           Case 12:
               ' Programmteil "Delete Key" und Rücksprung
                  Waitms 500
               ' Danach wird wieder ins Menü gesprungen
                  Mnuselect = 1
           Case 111:
               'Programmteil "ON" und Rücksprung
                  Portd.= 1
                  Mnuselect = 11

           Case 112:
               'Programmteil "OFF" und Rücksprung
                  Portd.= 0
                  Mnuselect = 11

           Case 2:
               ' Menü "Key +"
                   Mnuselectback = 0

                   Mnutext(1) = "Key +"
                   Mnuselects(1) = 21
                   Mnutext(2) = "Reserve"
                   Mnuselects(2) = 22

                   Mnuselectscount = 2

                   Gosub Mnushow

           Case 21:
               ' Programmteil "Key +"
                  Waitms 500
               ' Danach wird wieder ins Menü gesprungen
                  Mnuselect = 2
           Case 22:
               ' Menü "Reserve"
                   Mnuselectback = 2

                   Mnutext(1) = "Reserve1"
                   Mnuselects(1) = 221
                   Mnutext(2) = "Reserve2"
                   Mnuselects(2) = 222

                   Mnuselectscount = 2

                   Gosub Mnushow
           Case 221:
               ' Programmteil "Reserve1"
                  Waitms 500
                  Mnutext(1) = "Pussy"
               ' Danach wird wieder ins Menü gesprungen
                  Mnuselect = 22
           Case 222:
               ' Programmteil "Reserve2"
                  Waitms 500
               ' Danach wird wieder ins Menü gesprungen
                  Mnuselect = 22

           Case 3:
               ' Programmteil "Last IN"
                 For Zahl = 1 To 10
                 Portd.= 1
                 Waitms 200
                 Portd.= 0
                 Waitms 200
                 Next Zahl
               ' Danach wird wieder ins Menü gesprungen
                 Mnuselect = 0

           Case Else:
               ' Falls der Mnuselec mal querläuft, wird wieder ins
                  Waitms 500
               ' Hauptmenü gesprungen.
                  Mnuselect = 0

       End Select


   Loop


' hier startet nun die anzeigeroutine fuer das Display
   Mnushow:
       ' Wenn dieser Punkt angesprungen wird, verlangt das System eine Eingabe.
       ' Alle weiteren Aktionen, sofern nicht durch Interrupts erzeugt, werden
       ' nicht weiter verarbeitet.

       ' Das alte Mnuselect wird gesichert
       Mnuselectold = Mnuselect

       ' Der Zeiger wird auf den ersten Menüeintrag gestellt.
       Mnuselectpointer = 1

       ' So lange das Menue nicht geaendert wurde, wird dies immer fortgesetzt.
       While Mnuselectold = Mnuselect
           ' Zuerst einmal muss nun auf dem Display etwas angezeigt werden.

           ' Dies ist der Zaehler für die anzuzeigende Zeile
           M = 1
           Cls
           ' Displayzeilen minus 1
           N = Mnuselectpointer + Lcdrows
           Decr N

           ' Mehr als die verfuegbaren Menuepunkte können nicht angezeigt werden.
           If N > Mnuselectscount Then
               N = Mnuselectscount
           End If

           ' Anzeige der Zeilen
           For I = Mnuselectpointer To N
              Locate M , 1
              If I = Mnuselectpointer Then
                 Lcd ">"
              Else
                 Lcd " "
              End If
              Lcd Mnutext(i)
              Incr M
           Next

           ' Solange keine Tastatureingabe erfolgt, wird die Tastatur gepollt
           Do
               Gosub Tstq
           Loop Until Keypressed <> 16


           ' hier werden nun die Menuetasten ausgewertet.

           ' Aktion Taste nach oben
           If Keypressed = Keyup Then
               ' Nur wenn das Menü noch nicht oben ist.
               If Mnuselectpointer > 1 Then
                   Decr Mnuselectpointer
               End If
           End If

           ' Aktion Taste nach unten
           If Keypressed = Keydown Then
               ' Nur wenn das Menü noch nicht unten ist
               If Mnuselectpointer < Mnuselectscount Then
                   Incr Mnuselectpointer
               End If
           End If

           ' Aktion Taste vor
           If Keypressed = Keyright Then
               Mnuselect = Mnuselects(mnuselectpointer)
           End If

           ' Aktion Taste zurueck
           If Keypressed = Keyleft Then
               Mnuselect = Mnuselectback
           End If

      Wend
      Cls
   ' Es wird wieder ins Hauptprogramm zurueck gesprungen.
   Return


   Tstq:

    '* Taste "1" = Keycode 0
    '* Taste "2" = Keycode 1
    '* Taste "3" = Keycode 2
    '* Taste "4" = Keycode 4
    '* Taste "5" = Keycode 5
    '* Taste "6" = Keycode 6
    '* Taste "7" = Keycode 8
    '* Taste "8" = Keycode 9
    '* Taste "9" = Keycode 10
    '* Taste "*" = Keycode 12
    '* Taste "0" = Keycode 13
    '* Taste "#" = Keycode 14
    '* keine Taste = Keycode 16


Dim Asciichars As String * 16 , Taste As String * 1

Config Kbd = Porta , Debounce = 100 , Delay = 10

Asciichars = "123 456 789 *0# "

'****************************************


   Keypressed = Getkbd()

   If Keypressed <> 16 Then
      Print Keypressed
      Waitms 50

   End If


Return

'**************************************

'|--------------------Interrupt der seriellen Schnittstelle-------------------|'
On_urxc:
    'ASCII-Code einlesen

    Zahl = Inkey()
 If Zahl = 2 Then Else Return

    While Zahl <> 4                                         'While schleife so lange wie Zahl verschieden von 4 ist
         Zahl = Inkey()                                     '
         If Zahl <> 4 Then S = S + Chr(zahl)                'Nachkontrolle <> 4,wenn ja dann erhält S ein weiteres Zeichen
      Wend                                                  'Ende der While schleife (endet wenn Zahl = 4)
      Only_one = Only_one + 1
'Gosub Anzeige

'**************************************
 'Anzeige:

     If Only_one <> 1 Then Return
      Exist = 0

    If S = "R029980AD46" Then                               'Wenn die Zahlenreihe gleich "R029980AD46" ist, dann...
      Person = "Dupont    "
      Anrede = "Herr "
      Exist = 1
    End If

    If S = "R83D9A08DD5" Then                               'Wenn die Zahlenreihe gleich "R83D9A08DD5" ist, dann...
      Person = "Willems   "
      Anrede = "Frau "
      Exist = 1
    End If

    If S = "R0A88A02DDB" Then                               'Wenn Die Zahlenreihe gleich "R0A88A02DDB" ist, dann...
      Person = "Krause    "
      Anrede = "Herr "
      Exist = 1
    End If

    If Exist = 0 Then
      Person = " Unbekannt"
      Anrede = "ERROR"
    End If

      Cls                                                   'Lösche LCD Anzeige
         Locate 1 , 1                                       'Setze LCD Cursor auf Position 1,1
            Lcd "Willkommen"                                'Schreibe "Willkommen" auf die LCD Anzeige
         Locate 2 , 1                                       'Setze LCD Cursor auf Position 2,1
            Lcd Anrede ; Person                             'Schreibe "Herr" Name auf die Lcd-Anzeige

            Wait 4                                          'Warte 4 Sekunden

      Cls

      S = ""                                                'Inhalt der Textreihe (S) ist leer

      Return

' Ende des Programms. Kann unter Umständen auch weggelassen werden.
   End