\ ------------------------------------------------------------------------------ \
\ sys.fs
\ purpose: set up essential system utilities first
\ Not preprocessed.

compiletoram
 \  reset    Can't reset here as it takes too long
   init.calltrace		\ Prevent "Unhandled Interrupt ..." and list the problem instead.
   48mhz				\ Increase MCU clock to 48 MHz	  
   48000 init.systick	\ Set the Systick to 1ms increments


\ ------------------------------------------------------------------------------ \
\ gpio.fs
\ purpose: gpio configs
\ PA1 is ANALOG INPUT for LMT-01 PULSES
\ PC1 is OUTPUT HIGH to power LMT-01 or FLOATING/LOW to disable LMT-01

: gpio-init ( -- )
\ Enable GPIOA and GPIOC
RCC_AHBENR_IOPAEN enable! \ enable GPIOA
RCC_AHBENR_IOPCEN enable! \ enable GPIOC

\ PA1 is COMP1 & 2 INPUT. I/Os used as comparators inputs must be configured in analog mode.
GPIOA_MODER_MODER1 ANALOG bfs! \ porta-1 is analog mode

\ PA5 is TIM2_CH1_ETR external clock via AF2
 GPIOA_MODER_MODER5 AF bfs!
 GPIOA_AFRL_AFRL5 AF2 bfs!

\ PA6 COMP1 OUT for LMT01 pulses
GPIOA_MODER_MODER6 AF bfs!
GPIOA_AFRL_AFRL6 AF7 bfs!

\ PA7 is INPUT for TIM14_CH1 via AF4
GPIOA_MODER_MODER7 AF bfs!
GPIOA_AFRL_AFRL7 AF4 bfs!

\ Power to LMT-01 via PC1
GPIOC_MODER_MODER1 OUTPUT bfs! \ PC1 to output (%01) PUSH PULL
GPIOC_BSRR_BR1 1 bfs! \ PC1 set, BSRR is atomic so no bis! is needed

;


\ ------------------------------------------------------------------------------ \
\ leds.fs

: greenon  ( -- ) GPIOC_BSRR_BS9 enable! ;    \ green led on
: greenoff ( -- ) GPIOC_BSRR_BR9 disable! ;   \ green led off
: blueon  ( -- )  GPIOC_BSRR_BS8 enable! ;    \ blue led on
: blueoff ( -- )  GPIOC_BSRR_BR8 disable! ;   \ blue led off

: pulse-blink	\ flash per received lmt01 pulse



;
\ ------------------------------------------------------------------------------ \
\ comparator.fs
\ purpose: detect high and low logic levels from the LMT-01
\ Design:
\
\ COMP1 INP (+) detects PULSE LOW. It uses 1/2 of VREFINT = 0.6095V on INM (-) and outputs to Timer 2 input capture 4
\ COMP2 detects PULSE HIGH and is is in WINDOW mode. It uses 1/2 of VREFINT = 0.6095V on INM (-) and outputs to
\ Timer3 input capture 1
\ 
\ GPIOA-1 is ANALOG INPUT for LMT-01 PULSES
\ GPIOC-1 is OUTPUT HIGH to power LMT-01 or FLOATING to disable LMT-01
\ Comp ref input =  1/2 Vrefint = 0.6095
\ notes:
\ The comparator outputs can be redirected to an I/O or to timer inputs for triggering:

: comp-init ( -- )
\ Enable COMPARATOR CLOCK, this is done in tandem with SYSCFGEN
RCC_APB2ENR_SYSCFGEN enable! 

\ Configure Comp 1
COMP_CSR_COMP1MODE %01 bfs!      \ COMP1 INPUT MODE: %00 High speed / full power 10: Low speed / low-powerc
COMP_CSR_COMP1INSEL %001 bfs!    \ COMP1 INPUT SELECT: %001 1/2 of VREFINT = 0.6095V
COMP_CSR_COMP1OUTSEL %100 bfs!   \ COMP1 OUTPUT SELECT: %100: Timer 2 input capture 4
COMP_CSR_COMP1HYST %10 bfs!      \ COMP1 HYSTERESIS: %10 Medium hysteresis

\ Configure Comp2 to drive Disco LED when LMT-01 pulses for user visual feedback
\ Connect a LED (with resistor) to PA12 and ground. AF will select PA12
COMP_CSR_COMP2MODE %11 bfs!      \ COMP2 INPUT MODE: %00 High speed / full power 11: Very-low speed / ultra-low power
COMP_CSR_COMP2INSEL %001 bfs!    \ COMP2 INPUT SELECT: %001 1/2 of VREFINT = 0.6095V
COMP_CSR_COMP2OUTSEL %110 bfs!   \ COMP2 OUTPUT SELECT: %110: Timer 3 input capture 1
COMP_CSR_COMP2HYST %10 bfs!      \ COMP2 HYSTERESIS: %10 Medium hysteresis
COMP_CSR_WNDWEN enable!          \ Window mode: connects the non-inverting input of COMP2 to COMP1's n-i input
;

: enable-comparators ( -- )
   COMP_CSR_COMP1EN enable! \ Comparator 1 enable
   COMP_CSR_COMP2EN enable! \ Select COMP2
;

: disable-comparators ( -- )
   COMP_CSR_COMP1EN disable! \ disable COMP1
   COMP_CSR_COMP2EN disable! \ Disable COMP2
;

\ ------------------------------------------------------------------------------ \
\ pulse.fs
\ purpose: count pulses from the LMT-01 temperature sensor using TIM2
\ Comp1 output --> PA6, LMT01 pulses
\ Comp2 output --> PA12, plus (not implimented yet) timeout for final LMT01 pulse
\ PA5 is TIM2_CH1_ETR external clock via AF2

: counters-init ( -- )
\ Timer 2 enable CLOCKS
 RCC_APB1ENR_TIM2EN enable!

\ Timer 2 config for pulse counting
TIM2_SMCR_SMS %111 bfs!   \ %111: External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter. 
TIM2_SMCR_TS  %111 bfs!   \ %111: External Trigger input (ETRF)
TIM2_SMCR_ETF %0001 bfs!  \ %0011: fSAMPLING = fCK_INT, N = 8

TIM2_CR1_CEN enable!      \ enable timer2
;


\ ---------------------------------------------------------------------------\
\ Program Name: f0-disco-lmt01-gema.fs
\ Date: Tue 18 Jun 2021 16:51:24 AEST
\ Copyright 2021 by t.j.porter, GPL Licensed 
\ For Mecrisp-Stellaris by Matthias Koch. \ https://sourceforge.net/projects/mecrisp/
\ Chip: STM32F051
\ Board: STM32F0 Discovery Board
\ All register names are CMSIS-SVD compliant
\ Short Program Description: Demo of SVD2FORTH V6 with gema using a LMT-01 thermometer
\ See doc/README.html for full description
\ User LD3: Green user LED connected to PC-9
\ User LD4: Blue user LED connected to PC-8
\ PA1 is ANALOG INPUT for LMT-01 PULSES
\ PC1 is OUTPUT HIGH to power LMT-01 or INPUT to disable LMT-01

: init ( -- )   \ init (turnkey) word guarantees run first at bootup (to initialise peripherals)
gpio-init
comp-init
counters-init
;

: lmt01.on ( -- ) 
   GPIOC_BSRR_BS1 enable!      \ PC1 set HIGH, this powers the LMT-01, pulses start in 50 mS
;

: lmt01.off ( -- ) 
  GPIOC_BSRR_BR1 disable!
;

: clear-lmt01-counter ( -- )
  0 TIM2_CNT ! 
;

: lmt01.count? ( -- x )
  TIM2_CNT @ 
;

: lmt01.error?
   lmt01.count? 1 > if ( all ok )
   else ." error LMT-01 device connection fault, check cables ... " cr quit then 
;

: generate-lmt01-count ( -- ) \ LMT-01 Count is hardwired to TIM2 externally
   clear-lmt01-counter
   lmt01.on
   1 ms.delay		       \ Avoid counting lmt01 startup spike (5uS long)
   enable-comparators	   \ Receive lmt01 pulses into TIM2
   99 ms.delay		       \ Everything is done in 100mS (min delay for zero pulses = 45mS)
   disable-comparators
   lmt01.off
 ;

: degrees.c? ( -- C )      \ convert lmt01.count to degC, Temp (C) = ((count/4096) *256) -50
   0 swap		           \ convert numbers to s31.32 and calculate
   0 4096  f/ 
   0 256  f*
   0 50  d-
;

: degrees.f? ( -- F * 10 )   \ Formula = (C × 9/5) + 32 
  degrees.c? 		         \ get LMT-01 count
  0 9 f*                     \ convert numbers to s31.32 and calculate
  0 5  f/
  0 32  d+
; 

: temperature?  ( sensor # -- error | temperature C )
   generate-lmt01-count	      \ Get temperature
   lmt01.error?               \ Abort if LMT-01 isn't sending pulses
   lmt01.count?	dup 
   degrees.c? 1 f.n  ." C  "  \ Print temp in C
   degrees.f? 1 f.n  ." F "   \ Using C value, calculate F and print
;

: sensor-test ( -- )	      \ display total counts from sensor over 100ms, ie a full sensor cycle
   init
   clear-lmt01-counter
   enable-comparators	      
   lmt01.on
   100 ms.delay
   lmt01.count? . cr
   disable-comparators
   lmt01.off
   clear-lmt01-counter
;


: t ( -- ) init temperature? ;





