diff options
author | Ekaitz Zarraga <ekaitz@elenq.tech> | 2024-12-29 21:01:25 +0100 |
---|---|---|
committer | Ekaitz Zarraga <ekaitz@elenq.tech> | 2024-12-29 21:03:23 +0100 |
commit | 9d10e4b0376b29e80f52418953171df579989611 (patch) | |
tree | 3af72547bdaa4b77b364d168f7227d908d062896 /simulation.scm | |
parent | 4c5bba5b443f205fa73792317cff48c46cd8b15c (diff) |
simulation: WIP Virtual Channels:
A virtual channel is a combination of a frequency and a data rate. These
really act as the real channels in LoRa because there no interference
between them, even if they are considered the same channel in terms of
frequency, the data-rate (spreading factor) prevents interference.
Diffstat (limited to 'simulation.scm')
-rw-r--r-- | simulation.scm | 152 |
1 files changed, 108 insertions, 44 deletions
diff --git a/simulation.scm b/simulation.scm index 6af1357..a2d8283 100644 --- a/simulation.scm +++ b/simulation.scm @@ -67,17 +67,69 @@ (define (seconds->time-unit s) (* internal-time-units-per-second s)) +;; Virtual channel is a combination of radio frequency and data-rate/sf +;; Radio communication that happens in the same radio channel (same freq) but +;; with different spreading factor does not trigger an interference +(define-record-type <vchannel> + (make-vchannel freq dr) + vchannel? + (freq vchannel-freq) ; kHz + (dr vchannel-dr)) + +;; Window channel and DR parameters: +;; These are default values. `RXParamSetupReq` MAC command can be used to +;; change them +(define RX2-vchannel-EU863-870 (make-vchannel 869525 0)) +(define RX2-vchannel-US902-928 (make-vchannel 923300 8)) +(define RX1DROffset 0) + +(define (upstream-vchannel->RX1-vchannel-EU863-870 vchan RX1DROffset) + (define (upstream-dr->downstream-dr dr) + (match dr + ((? (lambda (x) (< x 8))) + (if (> RX1DROffset dr) 0 (- dr RX1DROffset))) + ((or 8 10) + (if (= RX1DROffset 0) 1 0)) + ((or 9 11) + (match RX1DROffset (0 2) (1 1) (_ 0))))) + (make-vchannel (vchannel-freq vchan) + (upstream-dr->downstream-dr (vchannel-dr vchan)))) + +(define (upstream-vchannel->RX1-vchannel-US903-928 vchan RX1DROffset) + (define (upstream-dr->downstream-dr dr) + (match dr + ((or 0 5) (if (= 3 RX1DROffset) 8 (- 10 RX1DROffset))) + ((or 1 2 3) (- (+ 10 dr) RX1DROffset)) + (6 (- 11 RX1DROffset)) + (4 (if (= 0 RX1DROffset) 13 (- 13 RX1DROffset))))) + (make-vchannel (vchannel-freq vchan) + (upstream-dr->downstream-dr (vchannel-dr vchan)))) + +(define (product f l1 l2) + (concatenate (map (lambda (x) (map (lambda (y) (f x y)) l2)) l1))) + +;; Minimum set of vchannels for EU +(define initial-vchannels-EU863-870 + (product make-vchannel (list 868100 868300 868500) (iota 6))) + +;; All the defined vchannels for the US +(define vchannels-US903-928-uplink + (append (product make-vchannel (iota 64 902300 200) (iota 4)) + (map make-vchannel (iota 8 903000 1600) (iota 8 4 0)))) +(define vchannels-US903-928-downlink + (product make-vchannel (iota 8 923300 600) (iota (- 13 7) 8))) + ;; For End-Device <--> Radio <--> Gateway ;; type can be: ;; '[up/down]link-start ;; '[up/down]link-end ;; 'interference (define-record-type <radio-event> - (make-radio-event type id channel-n frame) + (make-radio-event type id vchannel frame) radio-event? (type radio-event-type) (id radio-event-id) ;; Match the start-interference-end events - (channel-n radio-event-channel-n) + (vchannel radio-event-vchannel) (frame radio-event-frame)) ;; For Gateway <--> Network Server @@ -111,13 +163,13 @@ (define (rand-time) (random 2.)) -(define (make-class-a id initial-channel upstream-chn downstream-chn) +(define (make-class-a id initial-vchannel upstream-chn downstream-chn) (define window (make-channel)) ;; Activates/deactivates the message sink to avoid blocking on messages we ;; don't need (define internal-com (make-channel)) ;; Make all atomic - (define channel initial-channel) + (define vchannel initial-vchannel) ;; TODO: Unhardcode me (define time-on-air 0.01) @@ -134,15 +186,15 @@ '() (if confirmed? 'confirmed-data 'unconfirmed-data)))) (put-message upstream-chn - (make-radio-event 'uplink-start event-id channel frame)) + (make-radio-event 'uplink-start event-id vchannel frame)) (sleep time-on-air) (put-message upstream-chn - (make-radio-event 'uplink-end event-id channel frame)))) + (make-radio-event 'uplink-end event-id vchannel frame)))) - (define (receive-window channel time) - (define (listening-to? chn) - (= channel chn)) + (define (receive-window vchannel time) + (define (listening-to? vchn) + (equal? vchannel vchn)) (define (detect-preamble) (let wait-for-downlink-start () @@ -200,10 +252,10 @@ (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)) + (receive-window vchannel RX1)) (if (< (get-internal-real-time) RX2-start) (begin (wait-until RX2-start) - (receive-window channel RX2)) + (receive-window vchannel RX2)) #f)))) (when downlink (process-downlink! downlink))))) @@ -232,13 +284,14 @@ (spawn-fiber (lambda () ;; TODO: choose channel properly - (let ((event-id (new-id))) + (let ((event-id (new-id)) + (vchannel (make-vchannel 50000000 0))) ;; TODO: hehe invented! (ll "Gateway ~a sending downlink ~a" id frame) (put-message radio - (make-radio-event 'downlink-start event-id 1 frame)) + (make-radio-event 'downlink-start event-id vchannel frame)) (sleep time-on-air) (put-message radio - (make-radio-event 'downlink-end event-id 1 frame)))))) + (make-radio-event 'downlink-end event-id vchannel frame)))))) (define (send-to-network-server x) (ll "Gateway ~a forwarding ~a" id x) @@ -251,10 +304,10 @@ (match ev (($ <network-event> id frame) (send-to-device frame)) - (($ <radio-event> 'uplink-start event-id channel-n frame) #f) - (($ <radio-event> 'interference event-id channel-n frame) + (($ <radio-event> 'uplink-start event-id vchannel frame) #f) + (($ <radio-event> 'interference event-id vchannel frame) (set! pending-interferences (cons ev pending-interferences))) - (($ <radio-event> 'uplink-end event-id channel-n frame) + (($ <radio-event> 'uplink-end event-id vchannel frame) (let-values (((mine not-mine) (partition (lambda (x) (eq? (radio-event-id x) (radio-event-id ev))) @@ -268,17 +321,17 @@ "Fiber for radio resource allocation/control." ;; We can access it only from one fiber! Careful! - (define lorawan-channels (make-hash-table)) + (define lorawan-vchannels (make-hash-table)) (define (interferences ev chn) - (let ((res (hash-table-ref/default lorawan-channels chn '()))) + (let ((res (hash-table-ref/default lorawan-vchannels chn '()))) (if (equal? res (list ev)) '() res))) - (define (use-lorawan-channel! chn start-event) - (hash-table-update!/default lorawan-channels chn + (define (use-vchannel! chn start-event) + (hash-table-update!/default lorawan-vchannels chn (lambda (event-list) (cons start-event event-list)) '())) - (define (release-lorawan-channel! chn end-event) - (hash-table-update! lorawan-channels chn + (define (release-vchannel! chn end-event) + (hash-table-update! lorawan-vchannels chn (lambda (event-list) (remove! (lambda (x) (eq? (radio-event-id x) (radio-event-id end-event))) @@ -286,20 +339,21 @@ (define (radio-event->interference ev) "Make a new radio-event of type 'interference from another radio-event" (match ev - (($ <radio-event> type id channel-n frame) - (make-radio-event 'interference id channel-n frame)))) + (($ <radio-event> type id vchannel frame) + (make-radio-event 'interference id vchannel frame)))) (lambda () (forever (let ((ev (get-message in))) (match ev - (($ <radio-event> 'uplink-start event-id channel-n frame) - (ll "Device ~a started uplink-frame #~a on channel ~a" + (($ <radio-event> 'uplink-start event-id vchannel frame) + (ll "Device ~a started uplink-frame #~a on freq ~a DR ~a" (frame-DeviceAddr frame) (frame-FCnt frame) - channel-n) - (use-lorawan-channel! channel-n ev) - (let ((ints (interferences ev channel-n))) + (vchannel-freq vchannel) + (vchannel-dr vchannel)) + (use-vchannel! vchannel ev) + (let ((ints (interferences ev vchannel))) (hash-table-walk gateways (lambda (k gateway) (spawn-fiber @@ -312,15 +366,16 @@ (radio-event->interference ev))) ints))))))) - (($ <radio-event> 'downlink-start event-id channel-n frame) - (ll "Device ~a started downlink-frame #~a on channel ~a" + (($ <radio-event> 'downlink-start event-id vchannel frame) + (ll "Device ~a started downlink-frame #~a on freq ~a DR ~a" (frame-DeviceAddr frame) (frame-FCnt frame) - channel-n) - (use-lorawan-channel! channel-n ev) + (vchannel-freq vchannel) + (vchannel-dr vchannel)) + (use-vchannel! vchannel ev) (let ((chan (device-channel (hash-table-ref end-devices (frame-DeviceAddr frame)))) - (ints (interferences ev channel-n))) + (ints (interferences ev vchannel))) (put-message chan ev) (for-each (lambda (ev) @@ -328,24 +383,26 @@ (put-message chan (radio-event->interference ev))) ints))) - (($ <radio-event> 'uplink-end event-id channel-n frame) - (ll "Device ~a ended uplink-frame #~a on channel ~a" + (($ <radio-event> 'uplink-end event-id vchannel frame) + (ll "Device ~a ended uplink-frame #~a on freq ~a DR ~a" (frame-DeviceAddr frame) (frame-FCnt frame) - channel-n) - (release-lorawan-channel! channel-n ev) + (vchannel-freq vchannel) + (vchannel-dr vchannel)) + (release-vchannel! vchannel ev) (hash-table-walk gateways (lambda (k gateway) (spawn-fiber (lambda () (put-message (device-channel gateway) ev)))))) - (($ <radio-event> 'downlink-end event-id channel-n frame) - (ll "Device ~a ended downlink-frame #~a on channel ~a" + (($ <radio-event> 'downlink-end event-id vchannel frame) + (ll "Device ~a ended downlink-frame #~a on freq ~a DR ~a" (frame-DeviceAddr frame) (frame-FCnt frame) - channel-n) - (release-lorawan-channel! channel-n ev) + (vchannel-freq vchannel) + (vchannel-dr vchannel)) + (release-vchannel! vchannel ev) (put-message (device-channel (hash-table-ref end-devices (frame-DeviceAddr frame))) @@ -389,7 +446,14 @@ (let ((chn (make-channel))) (hash-table-set! end-devices id - (make-device chn (make-class-a id (modulo id 3) radio-chn chn))))) + (make-device chn + (make-class-a + id + ;; TODO: generalize for the US too? + (list-ref initial-vchannels-EU863-870 + (modulo id (length initial-vchannels-EU863-870))) + radio-chn + chn))))) (iota end-device-count gateway-count)) (for-each |