\
\    Mecrisp-Across - A Forth cross compiler for small MSP430 microcontrollers
\    Copyright (C) 2016  Matthias Koch
\
\    This program is free software: you can redistribute it and/or modify
\    it under the terms of the GNU General Public License as published by
\    the Free Software Foundation, either version 3 of the License, or
\    (at your option) any later version.
\
\    This program is distributed in the hope that it will be useful,
\    but WITHOUT ANY WARRANTY; without even the implied warranty of
\    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
\    GNU General Public License for more details.
\
\    You should have received a copy of the GNU General Public License
\    along with this program.  If not, see <http://www.gnu.org/licenses/>.
\


\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\  8. Teil: Schließlich jenes, was kompiliert werden soll :-)
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

new \ Das Dictionary des Crosscompilers zurücksetzen

\ <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
    TARGET
\ <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

: us 0 ?do i i + drop i i + drop loop inline ; \ Für 8 MHz bemessen
: ms 0 ?do 998 us loop ;

: Sendedatenholen ( -- Daten true | false ) key? dup if key tuck emit then ;
: Datenempfangen  ( Daten -- ) emit ;
: Verbindungsanfang ( -- )  1 p1out cbis! [char] < emit ; \ Verbindungsanzeige nach Bedarf anpassen
: Verbindungsende   ( -- )  1 p1out cbic! [char] > emit ;


1 constant Anode
2 constant Kathode

: Strahle ( -- )
  Anode   P2OUT cbis!
  Kathode P2OUT cbic!
  Anode Kathode or P2DIR cbis!
;

: Lauschen-Vorbereitung ( -- )
  Anode   P2OUT cbic!            \ Sperrschichtkapazität
  Kathode P2OUT cbis!            \ durch Verpolung laden
  Anode Kathode or P2DIR cbis!
  begin Kathode P2IN cbit@ until \ Warten, bis die Kathode geladen ist
  Kathode P2DIR cbic!
;

: Lauschen-Nachbearbeitung ( -- Flag )
  Kathode P2IN cbit@ not        \ Ist die Kathode entladen, ist es hell
;


18 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 ? )

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

: 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

  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
  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 ( -- )

  8MHz uart-init

  $5A14 $120 ! \ Watchdog-Interrupt mit ACLK/32768 = 1 s
  1 ie1 c!      \ Watchdog-Interrupt aktivieren

  Anode Kathode or p2dir c! \ Ausgänge für die Ledcomm-LED und die Verbindungsanzeige
  65  p1dir c!
  64  p1out c!

  Taktlauscher-init

  $10  $0162 !
  1953 $0172 !
  $210 $0160 !

  eint
;

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

: blinky ( -- ) -1 zustand xor! ;

\ <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
    HOST
\ <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

\ Vektortabelle füllen und Einsprungpunkte definieren

$FFF2 vector taktlauscher  \ Timer A0
$FFF4 vector blinky        \ Watchdog
$FFFE vector ledcomm       \ Reset

\ Zeit für die Crosscompilation !

crosscompile

\ -----------------------------------------------------------------------------

\ Was hat der Compiler daraus gemacht ?

\ t-listing
t-listing-file ledcomm.list

\ Was ist entstanden ? Einen tiefen Einblick für den Menschen ermöglichen.

disimage
disimage-file ledcomm.asm

\ Und die fertige Intel-Hex-Datei für den Chip ausgeben.

hexdump
hexdump-file ledcomm.hex

