
\ Ledcomm-Gecko
\   Connect LED with Anode (over optional 100 Ohms resistor) to PD1 and with Cathode directly to PD0.

compiletoflash

\ EXP Header:
\ Top row Bottom row
\   3V3   GND
\    5V   PD7
\   PD6   PC6
\   PD5   PB1
\   PD4   PB1
\   PD3   PC5
\   PD2   PC4
\   PD1   PC3
\   PD0   PC0
\  VMCU   GND

$40006000 $24 0 * + constant PA_Base
$40006000 $24 1 * + constant PB_Base
$40006000 $24 2 * + constant PC_Base
$40006000 $24 3 * + constant PD_Base
$40006000 $24 4 * + constant PE_Base
$40006000 $24 5 * + constant PF_Base

PD_Base $00 +  constant  PD_CTRL         \ RW  Port Control Register
PD_Base $04 +  constant  PD_MODEL        \ RW  Port Pin Mode Low Register
PD_Base $08 +  constant  PD_MODEH        \ RW  Port Pin Mode High Register
PD_Base $0C +  constant  PD_DOUT         \ RW  Port Data Out Register
PD_Base $10 +  constant  PD_DOUTSET      \ W1  Port Data Out Set Register
PD_Base $14 +  constant  PD_DOUTCLR      \ W1  Port Data Out Clear Register
PD_Base $18 +  constant  PD_DOUTTGL      \ W1  Port Data Out Toggle Register
PD_Base $1C +  constant  PD_DIN          \ R   Port Data In Register

PE_Base $00 +  constant  PE_CTRL         \ RW  Port Control Register
PE_Base $04 +  constant  PE_MODEL        \ RW  Port Pin Mode Low Register
PE_Base $08 +  constant  PE_MODEH        \ RW  Port Pin Mode High Register
PE_Base $0C +  constant  PE_DOUT         \ RW  Port Data Out Register
PE_Base $10 +  constant  PE_DOUTSET      \ W1  Port Data Out Set Register
PE_Base $14 +  constant  PE_DOUTCLR      \ W1  Port Data Out Clear Register
PE_Base $18 +  constant  PE_DOUTTGL      \ W1  Port Data Out Toggle Register
PE_Base $1C +  constant  PE_DIN          \ R   Port Data In Register

decimal

: Sendedatenholen ( -- Daten true | false ) key? if key dup emit true else false then ;
: Datenempfangen  ( Daten -- ) emit ;
: Verbindungsanfang ( -- ) ."  (Up) "      %0100 pe_doutset ! ; \ Verbindungsanzeige nach Bedarf anpassen
: Verbindungsende   ( -- ) ."  (Down) " cr %0100 pe_doutclr ! ;

: Strahle ( -- )
    $44 pd_model !
    %10 pd_dout  !
;

: Lauschen-Vorbereitung ( -- )
    $44 pd_model !
    %01 pd_dout  !

  \ Warten, bis die Kathode geladen ist - das geht im ARM nicht durch Einlesen des Pins
  10 0 do loop

    $41 pd_model !
    %00 pd_dout  !
;

: Lauschen-Nachbearbeitung ( -- Flag )
  %01 pd_din bit@ not \ Ist die Kathode entladen, ist es hell
;


34 constant Synchrondauer

8 variable Strahlzaehler
0 variable Verbindungsdauer
0 variable Lauschzaehler
0 variable Lichtmuster
0 variable Sendedaten
0 variable Datenregister

true variable Zustand ( Hell oder Dunkel ? )
 244 variable Basiszeit ( in Mikrosekunden )

: msb? ( x -- x Flag ) dup 0< ;

: HolePuls ( -- )
  8 Strahlzaehler ! \ Null-Puls, wird auch im Ruhezustand gesendet.

  \ Verbindungsdauer prüfen, beginne erst zu Senden, wenn die Verbindung auch sicher besteht.
  \ Belasse es im Falle einer gerade laufenden Synchronisation dabei, Ruhezustandspulse abzugeben.

  Verbindungsdauer @ Synchrondauer <> if exit then

  Sendedaten @ ?dup if  \ An bestehender Übertragung weiterarbeiten
                      msb? if 4 Strahlzaehler ! then \ Eins-Puls erforderlich ?
                      shl 
                      dup 0= if 12 Strahlzaehler ! then \ Wurde gerade die Merk-Eins herausrotiert ? Übertragungspuls !
                      Sendedaten !
                    else  \ Neue Daten holen und vorbereiten                     
                      Sendedatenholen
                      if 
                        ?dup if  ( Daten-zum-Senden )
                               4 Strahlzaehler ! \ Bei neuen Daten ungleich Null wird die führende Eins gesendet
                               
                               msb? if \ Ist das MSB schon die führende Eins ?
                                      shl 1 or \ Eine Merk-Eins reinrotieren, die nicht übertragen wird
                                    else
                                      shl 1 or \ Eine Merk-Eins reinrotieren, die nicht übertragen wird
                                      begin
                                        msb?   \ So lange schieben, bis die führende Eins herauspurzelt
                                        swap shl swap
                                      until
                                    then
                                                              
                               Sendedaten ! \ Fertig geschobene Datenbits zum weiteren Senden bereitlegen
                             else 12 Strahlzaehler ! \ Für eine Null genügt ein Übertragungspuls
                             then
                      then
                    then
;

: Bitmustererkennung ( -- )
  Verbindungsdauer @ Synchrondauer <>
  if \ Verbindung besteht erst nach 18 mal Zublinkern stabil.
    1 Verbindungsdauer +!
    Verbindungsdauer @ Synchrondauer = if Verbindungsanfang then    
  then

  Lichtmuster @
      %1111111111100 and    \ Übertragungspuls wird mit 11 bis 14 Basiszeiten erkannt
  dup %1111111111100 = if drop Datenregister @ Datenempfangen 
                             0 Datenregister ! \ Datenregister muss gelöscht werden,
                       else                    \  da die Daten aus mit variabler Länge übertragen werden

          %111111100 and    \ Null-Puls wird mit 7-10 Basiszeiten erkannt
          %111111100 = if   Datenregister @ shl      Datenregister ! 
                       else Datenregister @ shl 1 or Datenregister ! 
                       then \ Eins-Puls wird mit 3-6 Basiszeiten erkannt.
                       
                       then
; 

: Taktlauscher-init ( -- )
  0 Sendedaten !     \ Keine Daten zum Herausrotieren und Abstrahlen ! Wichtig !
  Verbindungsdauer @ Synchrondauer = if Verbindungsende then
  0 Verbindungsdauer !

  Zustand @ if
    \ Für einen hellen Taktlauscher
    HolePuls
    Strahle
  else
    \ Für einen dunkelen Taktlauscher  
    0 Strahlzaehler !
    1 Lauschzaehler !
    Lauschen-Vorbereitung
  then
;

: Taktlauscher ( -- )
  Strahlzaehler @ ?dup 
  if \ Strahlzähler ist nicht Null
    -1 Strahlzaehler +! 
    1- if 
         Strahle
       else \ Gerade Null geworden
         32 Lauschzaehler !
         0 Lichtmuster !
         Lauschen-Vorbereitung
       then
  else
    Lauschen-Nachbearbeitung
    1 and Lichtmuster @ shl or
    dup Lichtmuster ! ( Neues-Lichtmuster )
    %11111 and
    %11100 = if 
               Bitmustererkennung 
               HolePuls
               Strahle
             else
               -1 Lauschzaehler +!
               Lauschzaehler @ if Lauschen-Vorbereitung 
                               else Taktlauscher-init then
             then
  then
;

: ledcomm ( -- )

  $4400 pe_model bis! \ Set PE3 and PE4 as Push-Pull-Outputs for on-board LEDs
  %1100 pe_doutclr !  \ Both LEDs off.

    $44 pd_model !    \ Set PD0 and PD1 as Push-Pull-Outputs for Ledcomm
      0 pd_dout  !    \ Ledcomm-LED off

  Taktlauscher-init

  ['] Taktlauscher irq-systick !  \ (8 / 32768) s = 244 us
  Basiszeit @ 14 * $E000E014 !    \ 244 us * 14 MHz = 3416 Takte
  7 $E000E010 !                   \ Enable the systick interrupt.

  eint begin again
;

: bright ( -- ) true zustand ! ;
: dark   ( -- ) false zustand ! ;

compiletoram
