This repository has been archived by the owner on Jun 5, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
timed.fs
117 lines (96 loc) · 3.1 KB
/
timed.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
\ timed.fs
\ Multiple callback timers using one single background task
\ Needs multi.fs
\ Temporary - for easier debugging
<<<board>>>
compiletoflash
include /Users/thomas/go/src/github.com/jeelabs/embello/explore/1608-forth/flib/mecrisp/multi.fs
\ End Temporary
compiletoflash
\ --------------------------------------------------
\ Configuration
\ --------------------------------------------------
8 constant max-timed \ maximum number of timers (using 4 cells each)
\ --------------------------------------------------
\ Internal Helpers
\ --------------------------------------------------
\ 4 cells per timer ( interval, last-run, callback, repeat )
max-timed 4 * cells buffer: timed-data
\ Calculate internal adresses
: tmd-inte-addr ( timed# - addr ) timed-data swap 4 * cells + ;
: tmd-last-addr ( timed# - addr ) timed-data swap 4 * 1+ cells + ;
: tmd-call-addr ( timed# - addr ) timed-data swap 4 * 2+ cells + ;
: tmd-repe-addr ( timed# - addr ) timed-data swap 4 * 3 + cells + ;
\ Used by call-once/call-periodic
: call-internal ( callback when/interval repeat timed# )
>r r@ tmd-repe-addr !
r@ tmd-inte-addr !
r@ tmd-call-addr !
millis r> tmd-last-addr !
;
\ Execute timer callback and clear if no repetition is required
: timed-exec ( timed# )
>r r@ tmd-call-addr @ execute
millis r@ tmd-last-addr !
r@ tmd-repe-addr @ NOT IF
\ clear callback if no repetition needed
false r@ tmd-call-addr !
THEN
r> drop
;
\ Check if a timer needs to be executed (checks if enabled and enough time passed)
: needs-run? ( timed# )
dup tmd-call-addr @ IF
millis over tmd-last-addr @ - ( timed# time_since_last_run )
over tmd-inte-addr @ > ( timed# true_if_time_to_run )
ELSE
false
THEN nip ;
\ Check and execute all the timers
: timed-run ( -- #exec )
0 \ return number of executed tasks
max-timed 0 DO
i needs-run? IF
i timed-exec 1+
THEN
LOOP ;
\ Go to sleep if we're the only task running
: sleep-if-alone ( -- )
eint? IF \ Only enter sleep mode if interrupts have been enabled
dint up-alone? IF sleep THEN eint
THEN ;
\ Task which handles the timers in background
task: timedtask
: timed& ( -- )
timedtask activate
begin
timed-run NOT IF sleep-if-alone THEN
pause
again
;
\ --------------------------------------------------
\ External API
\ --------------------------------------------------
\ Clear timer data structure
: clear-timed ( -- ) timed-data max-timed 4 * cells 0 fill ;
\ Register a callback or cancel a timer
: call-after ( callback when timed# ) false swap call-internal ;
: call-every ( callback interval timed# ) true swap call-internal ;
: call-never ( timed# ) tmd-call-addr 0 swap ! ;
\ Show all timers
: timed. ( -- ) CR
max-timed 0 do
." Timer #" i .
." Interval: " i tmd-inte-addr @ .
." Last-Run: " i tmd-last-addr @ .
." Callback: " i tmd-call-addr @ .
." Repeat: " i tmd-repe-addr @ .
CR loop ;
\ Initializes timed-data and starts multitasking
: timed-init ( -- )
clear-timed
timed& multitask
;
\ for testing only
: ping ( -- ) CR ." PING" CR ;
compiletoram