#
#    Mecrisp-Quintus - A native code Forth implementation for RISC-V
#    Copyright (C) 2018  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/>.
#

.include "../common/terminalhooks.s"

# -----------------------------------------------------------------------------
# Labels for a few hardware ports
# -----------------------------------------------------------------------------

.equ RCGCPIO,    0x400FE608
.equ RCGCUART,   0x400FE618

.equ GPIO_PORTA_AHB_AFSEL_R,  0x40058420
.equ GPIO_PORTA_AHB_DEN_R,    0x4005851C
.equ GPIO_PORTA_AHB_PCTL_R,   0x4005852C

.equ Terminal_UART_Base, 0x4000C000

.equ UARTDR,     Terminal_UART_Base + 0x000
.equ UARTFR,     Terminal_UART_Base + 0x018
.equ UARTIBRD,   Terminal_UART_Base + 0x024
.equ UARTFBRD,   Terminal_UART_Base + 0x028
.equ UARTLCRH,   Terminal_UART_Base + 0x02C
.equ UARTCTL,    Terminal_UART_Base + 0x030
.equ UARTCC,     Terminal_UART_Base + 0xFC8

# Werte für den UARTFR-Register

.equ RXFE, 0x10 # Receive  FIFO empty
.equ TXFF, 0x20 # Transmit FIFO full

# -----------------------------------------------------------------------------
uart_init:
# -----------------------------------------------------------------------------

  li x5, 0x7FFF       # Alle GPIO-Ports aktivieren
  li x6, RCGCPIO
  sw x5, 0(x6)

  li x5, 1            # UART0 aktivieren
  li x6, RCGCUART
  sw x5, 0(x6)

  li x5, 0x11         # In diesem Chip ist die serielle Schnittstelle nicht standardmäßig als Sonderfunktion aktiviert
  li x6, GPIO_PORTA_AHB_PCTL_R
  sw x5, 0(x6)

  li x5, 3            # PA0 und PA1 auf UART-Sonderfunktion schalten
  li x6, GPIO_PORTA_AHB_AFSEL_R
  sw x5, 0(x6)

  li x5, 3            # PA0 und PA1 als digitale Leitungen aktivieren
  li x6, GPIO_PORTA_AHB_DEN_R
  sw x5, 0(x6)

  # Set_Terminal_UART_Baudrate

   # UART-Einstellungen vornehmen

  li x5, 0         # UART stop
  li x6, UARTCTL
  sw x5, 0(x6)

  # Baud rate generation:
  # 16000000 / (16 * 115200 ) = 1000000 / 115200 = 8.6805
  # 0.6805... * 64 = 43.5   ~ 44
  # use 8 and 44

  li x5, 8
  li x6, UARTIBRD
  sw x5, 0(x6)

  li x5, 44
  li x6, UARTFBRD
  sw x5, 0(x6)

  li x5, 0x60|0x10  # 8N1, enable FIFOs !
  li x6, UARTLCRH
  sw x5, 0(x6)

  li x5, 5          # Choose PIOSC as source
  li x6, UARTCC
  sw x5, 0(x6)

  li x5, 0
  li x6, UARTFR
  sw x5, 0(x6)

  li x5, 0x301      # UART start
  li x6, UARTCTL
  sw x5, 0(x6)

  ret

# -----------------------------------------------------------------------------
  Definition Flag_visible, "serial-emit"
serial_emit: # ( c -- ) Emit one character
# -----------------------------------------------------------------------------
  push x1

1:call serial_qemit
  popda x5
  beq x5, zero, 1b

  li x6, UARTDR
  sw x3, 0(x6)
  drop

  pop x1
  ret
   
# -----------------------------------------------------------------------------
  Definition Flag_visible, "serial-key"
serial_key: # ( -- c ) Receive one character
# -----------------------------------------------------------------------------
  push x1

1:call serial_qkey
  popda x5
  beq x5, zero, 1b

  li x6, UARTDR
  pushdatos
  lw x3, 0(x6)
  andi x3, x3, 0xFF

  pop x1
  ret

# -----------------------------------------------------------------------------
  Definition Flag_visible, "serial-emit?"
serial_qemit:  # ( -- ? ) Ready to send a character ?
# -----------------------------------------------------------------------------
  push x1
  call pause

  pushdaconst 0
  li x6, UARTFR
  lw x5, 0(x6)
  andi x5, x5, TXFF

  bne x5, zero, 1f
    xori x3, x3, -1
1:

  pop x1
  ret

# -----------------------------------------------------------------------------
  Definition Flag_visible, "serial-key?"
serial_qkey:  # ( -- ? ) Is there a key press ?
# -----------------------------------------------------------------------------
  push x1
  call pause

  pushdaconst 0
  li x6, UARTFR
  lw x5, 0(x6)
  andi x5, x5, RXFE

  bne x5, zero, 1f
    xori x3, x3, -1
1:

  pop x1
  ret

# -----------------------------------------------------------------------------
  Definition Flag_visible, "reset"
# ----------------------------------------------------------------------------- 
  j Reset

#    
#  # -----------------------------------------------------------------------------  
#  simpleecho: # Most simple UART echo possible
#  # -----------------------------------------------------------------------------
#    li x10, uart_data
#    lw x11, 0(x10)
#    li x12, -1
#    beq x11, x12, echo
#      
#    li x10, uart_data
#    sw x11, 0(x10)
#  j simpleecho
#  
#  # -----------------------------------------------------------------------------
#  echo: # Echo with data stack usage and LED blinking
#  # -----------------------------------------------------------------------------
#    call key
#    
#      li x10, leds
#      sw x3, 0(x10)
#      
#    call emit
#    j echo
#    
#  # -----------------------------------------------------------------------------
#  blinky: # Blink the LEDs with a counter    
#  # -----------------------------------------------------------------------------
#    li x10, leds
#    addi x11, x11, 1
#    sw x11, 0(x10)
#    j blinky
#    
