;
;    Mecrisp - A native code Forth implementation for MSP430 microcontrollers
;    Copyright (C) 2011  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/>.
;

; Main file for Mecrisp for MSP430F1612 with special Launchpad hardware initialisations and without analog.

; Contains settings for memory usage, switches for desired features and
; special chip or hardware specific initialisations.
; If you want to port Mecrisp to another member of the MSP430 family, start here.

;------------------------------------------------------------------------------
; Base Definitions
;------------------------------------------------------------------------------
 cpu msp430
 include "mspregister.asm"
 include "datastack.asm"

;------------------------------------------------------------------------------
; How many Flash for kernel ?
;------------------------------------------------------------------------------

  ; How many space should be allocated for kernel ? 
  ; Has to be on a 512-Byte-Boundary ! (Flash page organisation :-)

  ; 0E000h:  8   kb
  ; 0DE00h:  8.5 kb
  ; 0DC00h:  9   kb
  ; 0DA00h:  9.5 kb
  ; 0D800h: 10   kb
  ; 0D600h: 10,5 kb
  ; 0D400h: 11   kb
  ; 0D200h: 11.5 kb
  ; 0D000h: 12   kb

  org 0DC00h ;  9 kb Flash for Kernel

kernelstartadresse equ $

 padding on ; Strings sometimes need an extra padding zero so that instructions are aligned.

;------------------------------------------------------------------------------
; Declare your chip here and have a look at interrupts.asm
;------------------------------------------------------------------------------
msp430f1612 equ 1 ; (Porting: Change this !)

;------------------------------------------------------------------------------
; Which options do you desire ?
;------------------------------------------------------------------------------

doppeltzahleneinbinden equ 1         ; Double-Numbers ?

fixkommarechnungeneinbinden equ 1    ; Fixpoint-Numbers (depends on Double-Numbers) ?

leaveeinbinden          equ 1        ; Wish for Leave ?

spezialstrings          equ 1        ; Wish for s" move compare skipstring ?

unicodebeachten equ 1                ; Wish for Unicode support ?
caseinsensitive equ 1                ; Case insensitive ?

caseeinbinden equ 1                  ; CASE-Structure ?

;------------------------------------------------------------------------------
; Options for Hardware access without special dependencies
;------------------------------------------------------------------------------

;analogeinbinden equ 1                ; Small and comfortable Routines for ADC10 ?

;------------------------------------------------------------------------------
; Compilation into Flash and its settings
;------------------------------------------------------------------------------

flashdictionaryeinbinden equ 1       ; Use and compile into flash memory ?
                                     ; This includes some small helpers and flips link direction.

;flashkompilationsstart equ 1        ; Start with compiling into flash ?

ramverwaltungeinbinden equ 1         ; Do you want to define variables in Flash ?

initialisiereflashvariablen equ 1    ; Do you want variable initialisation on Reset ?

Anfangswortname equ "init"           ; How to name your turnkey ?

;------------------------------------------------------------------------------
; Options for Hardware access that depends on initialised variables
;------------------------------------------------------------------------------

;taktlauschereinbinden equ 1         ; Wish for Ledcomm ?

;terminalhooks equ 1                 ; Vectorized terminal ?

interrupthookseinbinden equ 1        ; On the fly changeable interrupt hooks ?

;------------------------------------------------------------------------------
; Configuration of memory map
;------------------------------------------------------------------------------

rampointer set 01100h ; Beginning of Ram (Porting: Change this !)

ramallot macro Name, Menge         ; To define labels for uninitialised variables and buffers for core usage
Name equ rampointer
rampointer set rampointer + Menge
         endm

  ramallot Base, 2                 ; Variable for Base
  ramallot State, 2                ; Variable for State
  ramallot Datenstacksicherung, 2  ; Copy of stackpointer for simple syntax checking.
  ramallot Dictionarypointer, 2    ; Variable with dictionarypointer
  ramallot FadenEnde, 2            ; Current entry point into dictionary for FIND
  ramallot konstantenfaltungszeiger, 2 ; A Pointer for determine how many folding constants are currently on data stack

  ifdef leaveeinbinden
    ramallot leavepointer, 2       ; Pointer to generate leave exit points in loops
  endif

  ifdef flashdictionaryeinbinden
    ramallot ZweitDictionaryPointer, 2 ; Second dictionarypointer
    ramallot ZweitFadenEnde, 2         ; Second entry into dictionary
    ramallot FlashFlags, 2             ; Variable to collect flags for new definitions in Flash
    ifdef ramverwaltungeinbinden
      ramallot VariablenPointer, 2     ; Pointer for Ram allocation for Flash variables
    endif
  endif

  ifdef taktlauschereinbinden ; Variables for Ledcomm, Refer to documentation for English description of Ledcomm.
    ; Word-Variablen
    ramallot Lichtmuster_low, 2 ; Der aktuellere Teil der Lichtmustermessungen
    ramallot Datenregister, 2   ; Die hineinkommenden Daten werden hier hineinrotiert
    ramallot Sendedaten, 2      ; Datenbits zum Herausrotieren und Abstrahlen

    ; Byte-Variablen
    ramallot Verbindungsdauer, 1 ; Enthält einen Wert, der angibt, wie lange die Verbindung schon besteht.
                                 ; Erst nach dem in Synchron_Dauer. ungestörtem Durchlauf wird mit dem Senden begonnen,
                                 ; weil auch ein plötzlicher Umgebungslichtwechsel die Probesequenz erfüllen könnte.
    ramallot Strahlzaehler, 1    ; Zähler, der die noch auszugebenden Pulse merkt
    ramallot Lauschzaehler, 1    ; Zähler, der weiß, wie oft noch zu Lauschen ist, bevor es hell werden muss
    ramallot Taktlauscherzustand, 1 ; Ein Bitmuster des Zustandes, Bit 0: 0=Dunkel, 1=Hell
  endif ; Taktlauschereinbinden

  ; Length of number output buffer, has to be uneven
Zahlenpufferlaenge equ 35 ; 16 Bits, 1 Sign, 1 Space + 1 Spare = 19 Bytes + 1 Length-Byte
  ramallot Zahlenpuffer, Zahlenpufferlaenge + 1  ; You need at least 35 bytes for fixpoint number usage.

  ; Put data stack in a location with uncritical buffers around so that overflows and underflows wont't crash immediately.
datenstacklaenge equ 64 ; Size of datastack, has to be even
  ramallot datenstackende, datenstacklaenge
datenstackanfang equ datenstackende + datenstacklaenge

  ramallot Eingabepuffergesamtlaenge, 1
MaximaleEingabe equ 120 ; Size of input buffer, has to be even.
  ramallot Eingabepuffer, MaximaleEingabe + 1

returnstacklaenge equ 64 ; Size of returnstack, has to be even
  ramallot returnstackende, returnstacklaenge
returnstackanfang equ returnstackende + returnstacklaenge

nRamDictionaryAnfang equ rampointer
nRamDictionaryEnde   equ 02500h ; End of 5 kb Ram (Porting: Change this !)

  ifdef flashdictionaryeinbinden
nFlashDictionaryAnfang equ 02500h  ; Begin of 55 kb Flash memory in chip for user dictionary (Porting: Change this !)
nFlashDictionaryEnde   equ kernelstartadresse ; End of user dictionary + 1.
nBacklinkgrenze equ nFlashDictionaryAnfang    ; Address border to compare with to find out if definition is in Ram or in Flash
  endif

;------------------------------------------------------------------------------
; Messages. There macros are defined early for printing messages and they don't like ( and ) in strings.

write macro Text
  call #dotgaensefuesschen
  .byte STRLEN(Text), Text
  align 2
  endm

writeln macro Text
  call #dotgaensefuesschen
  .byte STRLEN(Text)+1, Text, 10
  align 2
  endm

;------------------------------------------------------------------------------
; Hardware dependent parts of terminal
 include "usart0terminal.asm" ; (Porting: Change this !)

;------------------------------------------------------------------------------
Reset:      ; Main entry point.
;------------------------------------------------------------------------------

  ; Grundsätzliche Initialisierung
  mov   #WDTPW+WDTHOLD, &WDTCTL   ; Watchdog off
  mov   #returnstackanfang, SP    ; Init Returnstackpointer
  mov   #datenstackanfang,  r4    ; Init Datastackpointer

  ; Early hardware initialisations:

  ; Block I2C-Lines
  clr.b &P3OUT
  mov.b #2+4, &P3DIR ; Pull SDA and SCL low to block communication between TUSB3410 and EEprom

  ; Pull Reset for TUSB low
  clr.b &P4OUT
  mov.b #64, &P4DIR

  ; Start 12 MHz crystal on XT2
  bic.b   #XT2OFF, &BCSCTL1        ; XT2on

  ; Select USART0 TXD/RXD
  bis.b   #030h, &P3SEL


  ifdef flashdictionaryeinbinden     ; I have to find initial values for Dictionary Pointers:
    include "catchflashpointers.asm" ; This updates Fadenende, DictionaryPointer, VariablenPointer.
  else                               ; For Ram alone it is easy:
    mov #nRamDictionaryAnfang, &Dictionarypointer
    mov #CoreFadenende, &Fadenende
  endif

  ; Now it is time to initialize hardware. (Porting: Change this !)

  ; Select 12 MHz crystal on XT2 as main clock
  ; bic.b   #XT2OFF, &BCSCTL1        ; XT2on - already activated
- bic.b   #OFIFG, &IFG1            ; Clear OSC fault flag
  mov.w   #0FFh, r15               ; R15 = Delay
- dec.w   r15                      ; Additional delay to ensure start
  jnz     -
  bit.b   #OFIFG, &IFG1            ; OSC fault flag set?
  jnz     --                       ; OSC Fault, clear flag again
  bis.b   #SELM_2+SELS, &BCSCTL2   ; MCLK = SMCLK = XT2


  ; SMCLK output for TUSB3410 on P5.5
  mov.b #32, &P5DIR
  mov.b #32, &P5SEL
  
  ; Release Reset-line for TUSB3410
  clr.b &P4DIR

  ;------------------------------------------------------------------------------
  ; Init serial communication
            bis.b   #UTXE0+URXE0, &ME1       ; Enable USART0 TXD/RXD
            bis.b   #CHAR, &U0CTL            ; 8-bit characters
            mov.b   #SSEL1, &U0TCTL          ; UCLK = SMCLK
            mov.b   #0E2h, &U0BR0            ; 9600 @ 12Mhz
            mov.b   #004h, &U0BR1            ;
            clr.b   &U0MCTL                  ; No modulation
            bic.b   #SWRST, &U0CTL           ; **Initalize USART state machine**
  ;------------------------------------------------------------------------------

  ; 12 MHz ! Take care: If you change clock, you have to change Flash clock divider, too !
  ; Current divider 29+1 --> 400kHz @ 8 MHz. Has to be in range 257 kHz - 476 kHz.

  ifdef flashdictionaryeinbinden
    clr.b &IE1 ; Clear interrupt flags of oscillator fault, NMR and flash violation.
    mov.w #FWKEY, &FCTL1            ; Lock flash against writing
    mov.w #FWKEY|FSSEL_1|29, &FCTL2 ; MCLK/30 for Flash Timing Generator
  endif

  ; Initialisation is complete. Prepare to enter Forth:

  ; This message is never shown because USB-serial bridge needs more time to initialise.
  ; writeln "Mecrisp 1.1 for F1612 by Matthias Koch"

  ifdef flashdictionaryeinbinden
  ifdef Anfangswortname

      ; Initialisations similar to the ones in quit for turnkey applications:
      mov #10, &Base ; Decimal number base.
      clr &state     ; Just executing
      clr &konstantenfaltungszeiger ; No constants for folding available

    pushda #Anfangswortnamensstring
    call #wortsuche
    tst 2(r4) ; Found turnkey definition ?
    jz +
    ; Found:
      drop       ; Drop Flags
      call @r4+  ; Execute
      br #quit_inneneinsprung ; Special entry into quit so preserve everything the turnkey left.

Anfangswortnamensstring: .byte STRLEN(Anfangswortname), Anfangswortname
  align 2

+  ; Not found ? Don't tidy up. Quit clears stacks for us.
  endif ; Anfangswortname
  endif

  br #quit

;------------------------------------------------------------------------------
  include "forth-core.asm"  ; Include everything of Mecrisp
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
null_handler: ; Catches unused interrupts
;------------------------------------------------------------------------------
  reti

;------------------------------------------------------------------------------
;           Interrupt vectors of F1612
;------------------------------------------------------------------------------


  ifdef interrupthookseinbinden

 org 0FFE0h ; Interrupt table with hooks

  .word   irq_vektor_dac       ; 01: 0FFE0  DAC, DMA
  .word   irq_vektor_port2     ; 02: 0FFE2  Port 2
  .word   irq_vektor_tx1       ; 03: 0FFE4  USART1 TX
  .word   irq_vektor_rx1       ; 04: 0FFE6  USART1 RX
  .word   irq_vektor_port1     ; 05: 0FFE8  Port 1
  .word   irq_vektor_timera1   ; 06: 0FFEA  Timer A1
  .word   irq_vektor_timera0   ; 07: 0FFEC  Timer A0
  .word   irq_vektor_adc       ; 08: 0FFEE  ADC12
  .word   irq_vektor_tx0       ; 09: 0FFF0  USART0 TX
  .word   irq_vektor_rx0       ; 10: 0FFF2  USART0 RX
  .word   irq_vektor_watchdog  ; 11: 0FFF4  Watchdog
  .word   irq_vektor_comp      ; 12: 0FFF6  Comparantor
  .word   irq_vektor_timerb1   ; 13: 0FFF8  Timer B1
  .word   irq_vektor_timerb0   ; 14: 0FFFA  Timer B0
  .word   null_handler         ; 15: 0FFFC  NMI. Unused.
  .word   Reset                ; 16: 0FFFE  Main entry point

  else

 org 0FFE0h ; Empty interrupt table

  .word   null_handler  ; 0FFE0
  .word   null_handler  ; 0FFE2
  .word   null_handler  ; 0FFE4
  .word   null_handler  ; 0FFE6
  .word   null_handler  ; 0FFE8
  .word   null_handler  ; 0FFEA
  .word   null_handler  ; 0FFEC
  .word   null_handler  ; 0FFEE
  .word   null_handler  ; 0FFF0
  .word   null_handler  ; 0FFF2
  .word   null_handler  ; 0FFF4
  .word   null_handler  ; 0FFF6
  .word   null_handler  ; 0FFF8
  .word   null_handler  ; 0FFFA
  .word   null_handler  ; 0FFFC
  .word   Reset         ; 0FFFE  Main entry point

  endif

end
