;12.10.2024 reaktion12
;..................................
; PIC: 18F13K22//Assembler:MPASM V5.43//IDE: MPLABX v5.20
;
;Port A:    port a komplett ausgang:    a2 signal-LED an 
;Port B:    komplett eingang:
;           b4 taste bereit, b5 taste stopp, b6 100 hz-frequenz, b7 nc
;Port C:    alle 7 auf ausgang/daten: 
;     c0: out data a      c1: out data b    c2: out data c      c3: out data d
;     c4: latch hunderter c5: latch zehner  c6: latch einer     c7: nc
;tasten an b4 u b5 haben bei t-druck "1"
;-----------------------------------------------------------------------------
#include <p18F13K22.inc>

    ;Config settings
    CONFIG IESO = OFF, PLLEN = OFF, FOSC = IRC, FCMEN = OFF, PCLKEN = OFF
    CONFIG BOREN = OFF, BORV = 19, PWRTEN = OFF, WDTEN = OFF
    CONFIG MCLRE = ON, HFOFST = OFF, DEBUG = OFF, STVREN = ON
    CONFIG XINST = OFF, BBSIZ = OFF, LVP = OFF

    errorlevel -302        ;surpress the 'not in bank0' warning

GPR_VAR         UDATA
zuf             RES     1  ;zeitzhler 100 hz-flanken
zuftemp         RES     1  ;wert, der in schleife runter gezhlt wird
acht            RES     1  ;zhlt 8 durchlufe fr mittelwertbildung	    
temp            RES     1  ;universal-zwischenspeicher
;-----
hundert         RES     1
zehner          RES     1
einer           RES     1
loby            RES     1  ;low-byte fr miwert
hiby            RES     1  ;high-byte fr miwert
;.....................................................................
     Org    0x0000         ;kein reset vector
     bra    START

MAIN_PROG   CODE

START:                       ;Setup main init
     movlw      b'00000010'  ;set cpu clock speed of 31KHz
     movwf      OSCCON       ;
     clrf       OSCTUNE      ;
          
     clrf       LATA         ;port a auf ausgang
     clrf       TRISA
     clrf       LATB         ;
     movlw      b'11110000'  ;port b4-b7 alle eingang
     movwf      TRISB
     clrf       ANSELH       ;eingnge auf digital
     clrf       LATC         ;
     clrf       TRISC        ;
     movlw      b'11110000'  ;cd4511 auf keine datenausgabe setzen
     movwf      LATC
;-----------------------------------------------------------------------------
MainLoop:                ;beginn hauptprogramm
    nop
    movlw  d'8'          ;8 durchlufe fr mittelwert-bildung
    movwf  acht          ;
    clrf   loby          ;vorsorglich lschen
    clrf   hiby
;------------------------
zufall:                  ;zufallszahl zu erzeugen,dessen zhler starten
    bcf    LATA,2        ;signal-led lschen
    nop
zuf1:                    ;100 hz-flanken zhlen
    btfsc  PORTB,6       ;liegt "0" an?
    bra    zuf1          ;noch kein zero, warten
zuf2:
    btfss  PORTB,6       ;springen, wenn "1"
    bra    zuf2          ;warten auf "1"
    incf   zuf           ;zhlt immer durch, berlauf egal
zuf3:
    nop
    btfss  PORTB,4       ;bereit-taste gedrckt? zufallszahl erzeugt, springen
    bra    zuf1          ;nicht gedrckt, weiter zufallszahlen generieren
;------------------------------------------------------------------------    
stopp:                   ;erste verzgerung anfertigen: erst 1,00 sec vorher
zger:                   ;
    movlw  h'64'         ;dez 1,00 sec
    movwf  temp          ;temp als wert in schleife
zg2:                    ;100 hz-flanken zhlen
    btfsc  PORTB,6       ;liegt "0" an?
    bra    zg2          ;noch kein zero, warten
zg3:
    btfss  PORTB,6       ;springen, wenn "1"
    bra    zg3          ;warten auf "1"

    decfsz temp,1        ;springen, wenn "0"
    bra    zg2          ;1,00 sec nicht erreicht, weiter in schleife
                         ;fertig mit 1 sec vorzeit
;-------------------------------------------
malzuf:                  ;jetzt zufallszahl mal 2 als weitere verzgerung,
    nop                  ;danach led an und die messung starten
    movlw  d'2'          ;zuf mal 2
    movwf  temp
ma0:                     ;zuf fr zweiten lauf neu laden
    movff  zuf,zuftemp
ma1:                     ;100 hz-flanken zhlen
    btfsc  PORTB,6       ;liegt "0" an?
    bra    ma1           ;noch kein zero, warten
ma2:
    btfss  PORTB,6       ;springen, wenn "1"
    bra    ma2           ;warten auf "1"

    decfsz zuftemp,1     ;springen, wenn "0"
    bra    ma1           ;zuf noch nicht runter gezhlt
    decfsz temp,1        ;rundenzhler decrementieren
    bra    ma0           ;schleife noch nicht rum
    nop                  ;schleife mit zuf mal zwei rum
;---------------------------------------------------------------------------
reaktion:                ;jetzt signal-led an und reaktionszeit messen
    movlw  h'ff'         ;messzeit max. 2,55 sec
    movwf  zuftemp       ;zuftemp auch als hier als wert in schleife
    bsf    LATA,2        ;LED fr Start Messzeit an
    nop
rea1:                    ;100 hz-flanken zhlen
    btfsc  PORTB,6       ;liegt "0" an?
    bra    rea1          ;noch kein zero, warten
rea2:
    btfss  PORTB,6       ;springen, wenn "1"
    bra    rea2          ;warten auf "1"

    dcfsnz zuftemp,1     ;springen, wenn noch nicht "0"
    bra    ablauf        ;2,55 sec berschritten, abbruch
    btfss  PORTB,5       ;stopp-taste a2 gedrckt ?
    bra    rea1          ;noch nicht gedrckt, weiter messen
;-----------------
rea3:                    ;stopp-taste gedrckt, zeit ermitteln
    movf   zuftemp,0     ;zuftemp in wreg
    sublw  h'ff'         ;substract wreg von literal dez 255, ergebnis in w
    movwf  zuftemp       ;ergebnis in zuftemp, nun anzeigen
    bra    zeigen        ;stopp-taste gedrckt, zuftemp hlt zeit, die anzeigen
;------------------------    
ablauf:                  ;max. reaktionszeit von 2,55sec berschritten
    nop
    movlw  h'ff'         ;dies in anzeige laden und anzeigen
    movwf  zuftemp
;------------------------------------------------------------------------
zeigen:                  ;eingang: anzeigewert in zuftemp
    nop
    call   addier        ;erst noch addieren fr miwert, dann zeigen
    call   indezimal     ;umwandlung dual in dezimal
    call   segment7      ;zahlenausgabe ber cd4511-er auf 7-seg.-leds
    nop
zeig1:                   ;8 umlufe rum ?    
    decfsz acht,1        ;springen, wenn 8 rum sind
    bra    zufall        ;nicht rum, nchste runde, zufallzahl bernehmen
    call   mittel        ;8 lufe rum, jetzt mittelwert ausrechnen
    call   pause         ;erst fr ein paar sec das aktuelle ergebnis zeigen,
    movff  loby,zuftemp  ;daten aus mittelwertbildung in variable fr 7seg
    call   indezimal     ;danach erst den miwert
    call   segment7
    bra    MainLoop      ;nun ganz von vorne beginnen
;---------------------------------------------------------------------------
addier:                  ;eingang: daten in zuftemp
    movf   zuftemp,0     ;zuftemp in wreg
    addwf  loby,1        ;inhalt von wreg zu loby addieren
    btfss  STATUS,0      ;wenn bertrag in status,c , dann springen
    return               ;kein bertrag in hiby ntig
    movlw  d'1'          ;bertrag in hiby ntig
    addwf  hiby,1        ;trag fertig
    return               ;ausgang: datensumme in loby und hiby
;-------------------------------------------------------------------------
mittel:                  ;eingang: daten in loby und hiby
    movlw  d'3'          ;rundenzhler frs dividieren auf 3 setzen
    movwf  temp
mit2:
    btfsc  hiby,0        ;springen, wenn bit0 von hiby "0" ist
    bra    mit3          ;bit0 ist "1"
    bcf    STATUS,0      ;carry-bit in STATUS lschen
    bra    mit4
mit3:
    bsf    STATUS,0
mit4:
    rrcf   loby,1        ;low-byte rechts shiften und carry-bit mitnehmen in 7
    rrncf  hiby          ;high-byte fr nchstes manver vorbereiten
    decfsz temp          ;schon dreimal geschoben?
    bra    mit2          ;noch nicht dreimal, weiter schieben
    return               ;dreimal geschoben, division durch 8 ist fertig
                         ;ausgang: reaktion in loby
;------------------------------------------------------------------------------
pause:                   ;2,55 sec pause fr anzeige aktuelles ergebnis
    movlw  h'ff'         ;
    movwf  temp          ;variable als wert in schleife
    ;bsf    LATA,2       ;spter evtl. LED fr hinweis auf aktuellen wert
pau1:                    ;100 hz-flanken zhlen
    btfsc  PORTB,6       ;liegt "0" an?
    bra    pau1          ;noch kein zero, warten
pau2:
    btfss  PORTB,6       ;springen, wenn "1"
    bra    pau2          ;warten auf "1"
    decfsz temp,1        ;springen, wenn "0"
    bra    pau1          ;noch nicht fertig, weiter flanken zhlen
    return
;-----------------------------------------------------------------------------    
indezimal:                   ;umwandlung von zahlen fr dezimal-ausgabe
                             ;eingnge: mewert in zuftemp = nur 8-bit !!!
    nop
    clrf    hundert,1        ;eingang: zuftemp hlt werte von 0 bis 255
    clrf    zehner,1
    clrf    einer
hun:
    movff   zuftemp,temp     ;zehner-rest umspeichern in temp
    movlw   d'100'           ;wieviel hunderter stecken in zuftemp ?
    subwf   zuftemp,1,1      ;minus hundert, der rest in zuftemp
    bnc     zehn             ;negativ:kein hunderter mehr, zum zehner-zhlen
    incf    hundert          ;positiv: sind noch hunderter
    bra     hun              ;weiter hunderter zhlen
;-----------
zehn:
    movff   temp,zuftemp     ;eingang: wert in temp
z1: movff   zuftemp,temp     ;einer-rest umspeichern in temp
    movlw   d'10'            ;wieviel zehner stecken in zuftemp ?
    subwf   zuftemp,1,1      ;minus zehn, der rest in zuftemp
    bnc     ein              ;negativ:kein zehner mehr, zum einer-zhlen
    incf    zehner           ;positiv: sind noch zehner
    bra     z1               ;weiter zehner zhlen  
;-----------
ein:                         ;eingang: einer in temp
    movff   temp,einer       ;ist ja schon fertig jetzt !!!!
    return                   ;ausgang: hunert,zehner,einer
;-----------------------------------------------------------------------------
segment7:                    ;die cd74hc4511 bernehmen daten bei neg flanke
                             ;pc0 daten einer bis pb2 daten hunderter
                             ;pin 3,4 von 74hc4511 sind fest auf "1" gelegt
                             ;also immer anzeige
    movlw   b'11110000'
    movwf   temp
    movwf   LATC
;---  
    movf    einer,0,1        ;Daten von einer in w
    iorwf   temp,0,1         ;incl-or w mit temp, ergebnis in w
    movwf   LATC
    bcf     LATC,6           ;bernahme u abspeichern der einer im 4511
    nop
    bsf     LATC,6
;---     
    movf    zehner,0,1       ;Daten von zehner in w
    iorwf   temp,0,1         ;incl-or w mit temp, ergebnis in w
    movwf   LATC
    bcf     LATC,5           ;bernahme zehner
    nop
    bsf     LATC,5
;---
    movf    hundert,0,1      ;Daten von hundert in w
    iorwf   temp,0,1         ;incl-or w mit temp, ergebnis in w
    movwf   LATC
    bcf     LATC,4           ;bernahme der hunderter im 4511
    nop
    bsf     LATC,4
segaus:
    return
    
    end
;-----------------------------------------------------------------------------
