\ ------------------------------------------------------------------------------ \
\ 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? ;