summaryrefslogtreecommitdiff
path: root/simulation.scm
diff options
context:
space:
mode:
authorEkaitz Zarraga <ekaitz@elenq.tech>2024-12-29 16:30:28 +0100
committerEkaitz Zarraga <ekaitz@elenq.tech>2024-12-29 16:30:28 +0100
commit9fdc216f3b4223bbce338a6c806d54288da26c40 (patch)
tree08f9c198aedcca2a18ef1cae9c444f0865529edc /simulation.scm
parent7cb6de7a9dbb09144aa210674da5cc8d157522c2 (diff)
simulation: Enable RX1 and RX2
Diffstat (limited to 'simulation.scm')
-rw-r--r--simulation.scm109
1 files changed, 67 insertions, 42 deletions
diff --git a/simulation.scm b/simulation.scm
index 314c15d..061c703 100644
--- a/simulation.scm
+++ b/simulation.scm
@@ -12,9 +12,9 @@
#:use-module (fibers timers))
(define RX1 1) ; s (has to be between 1-15s)
-(define RX2 (1+ RX1)) ; s
-(define RECEIVE_DELAY1 1) ; s
-(define RECEIVE_DELAY2 (1+ RECEIVE_DELAY1)) ; s
+(define RX2 (+ 2 RX1)) ; s
+(define RECEIVE_DELAY1 3) ; s
+(define RECEIVE_DELAY2 (+ 2 RECEIVE_DELAY1)) ; s
(define RETRANSMISSION_DELAY 2) ; s
;; From RP002 (Regional Parameters):
;; MAC commands exist in the LoRaWAN® specification to change the value of
@@ -62,6 +62,11 @@
(put-message *id-channel-in* #t)
(get-message *id-channel-out*))
+
+;; For timer operations
+(define (seconds->time-unit s)
+ (* internal-time-units-per-second s))
+
;; For End-Device <--> Radio <--> Gateway
;; type can be:
;; '[up/down]link-start
@@ -113,8 +118,6 @@
(define internal-com (make-channel))
;; Make all atomic
(define channel initial-channel)
- (define (listening-to? chn)
- (= channel chn))
;; TODO: Unhardcode me
(define time-on-air 0.01)
@@ -147,7 +150,56 @@
(sleep time-on-air)
(put-message upstream-chn (make-radio-event 'uplink-end event-id channel frame))))
+
+ (define (receive-window channel time)
+ (define (listening-to? chn)
+ (= channel chn))
+
+ (define (detect-preamble)
+ (let wait-for-downlink-start ()
+ (let ((msg (perform-operation
+ (choice-operation
+ (wrap-operation (sleep-operation time)
+ (lambda _ 'time-is-out))
+ (get-operation downstream-chn)))))
+ (match msg
+ ;; We got the preamble in time
+ (($ <radio-event> 'downlink-start message-id (= listening-to? chn) frame)
+ (ll "Device ~a got preamble" id)
+ message-id)
+ ;; No preamble in time
+ ('time-is-out #f)
+ ;; Current message is not a preamble, continue
+ (_ (wait-for-downlink-start))))))
+
+ (define (demodulate message-id)
+ (let wait-for-downlink-end ((interference? #f))
+ (let ((part-of-same-message? (lambda (i) (= message-id i)))
+ (msg (get-message downstream-chn)))
+ (match msg
+ (($ <radio-event> 'interference
+ (= part-of-same-message? id)
+ (= listening-to? chn)
+ frame)
+ (wait-for-downlink-end #t)) ;; Got interference
+ (($ <radio-event> 'downlink-end
+ (= part-of-same-message? id)
+ (= listening-to? chn)
+ frame)
+ (and (not interference?) frame))
+ (_ (wait-for-downlink-end interference?))))))
+
+ (put-message internal-com 'wait)
+ (let* ((preamble-id (detect-preamble))
+ (result (and preamble-id (demodulate preamble-id))))
+ (put-message internal-com 'continue)
+ result))
+
(define (device-operation)
+ (define (wait-until t)
+ (perform-operation
+ (timer-operation t)))
+
(define current-frame 0)
(forever
;; TODO check to-confirm
@@ -156,43 +208,16 @@
(send-uplink-frame current-frame id #t)
(set! current-frame (1+ current-frame)) ;; TODO: improve
- (sleep RECEIVE_DELAY1) ;; TODO: make sure this is ok
- (put-message internal-com 'wait)
- (let ((until (+ (get-internal-real-time)
- (* RX1 internal-time-units-per-second))))
- ;; TODO: listen to the first, and then hook to its radio-event-id
- (let wait-for-downlink-start ()
- (let ((msg (perform-operation
- (choice-operation
- (wrap-operation (timer-operation until)
- (lambda _ 'time-is-out))
- (get-operation downstream-chn)))))
- (ll "~a" msg)
- (match msg
- ;; We got the preamble in time
- (($ <radio-event> 'downlink-start message-id (= listening-to? chn) frame)
- (ll "Device ~a got preamble" id)
- (let wait-for-downlink-end ((interference? #f))
- (let ((part-of-same-message? (lambda (i) (= message-id i)))
- (msg (get-message downstream-chn)))
- (match msg
- (($ <radio-event> 'interference
- (= part-of-same-message? id)
- (= listening-to? chn)
- frame)
- (wait-for-downlink-end #t)) ;; Got interference
- (($ <radio-event> 'downlink-end
- (= part-of-same-message? id)
- (= listening-to? chn)
- frame)
- (unless interference?
- (process-downlink! frame))) ;; TODO try RX2
- (_ (wait-for-downlink-end interference?))))))
- ;; No preamble in time
- ('time-is-out #f)
- ;; Current message is not a preamble, continue
- (_ (wait-for-downlink-start))))))
- (put-message internal-com 'continue)))
+ (let* ((now (get-internal-real-time))
+ (RX1-start (+ now (seconds->time-unit RECEIVE_DELAY1)))
+ (RX2-start (+ now (seconds->time-unit RECEIVE_DELAY2)))
+ (downlink (or (begin (wait-until RX1-start)
+ (receive-window channel RX1))
+ (if (< (get-internal-real-time) RX2-start)
+ (begin (wait-until RX2-start)
+ (receive-window channel RX2))
+ #f))))
+ (when downlink (process-downlink! downlink)))))
(define (downstream-sink)
(forever