summaryrefslogtreecommitdiff
path: root/ebus-racket/ebus/layer2.rkt
diff options
context:
space:
mode:
Diffstat (limited to 'ebus-racket/ebus/layer2.rkt')
-rw-r--r--ebus-racket/ebus/layer2.rkt98
1 files changed, 98 insertions, 0 deletions
diff --git a/ebus-racket/ebus/layer2.rkt b/ebus-racket/ebus/layer2.rkt
new file mode 100644
index 0000000..f9bc31a
--- /dev/null
+++ b/ebus-racket/ebus/layer2.rkt
@@ -0,0 +1,98 @@
+#lang racket/base
+(require (only-in racket/bool false?)
+ "../3rdparty/bzlib/parseq/main.ss")
+
+(define-logger ebus2)
+
+(define ebus-const-syn #xaa) ;; SYN
+(define ebus-const-escape #xa9) ;; Escape-Sequence Start
+(define ebus-const-ackok #x00) ;; ACK
+(define ebus-const-broadcastaddr #xfe) ;; Broadcast Address
+
+(struct ebus-body-broadcast (crc) #:transparent)
+
+(struct ebus-body-mastermaster (crc) #:transparent)
+
+(struct ebus-body-masterslave
+ (crc payloadSlaveLength payloadSlave crcSlave)
+ #:transparent)
+
+(struct ebus-paket
+ (source destination primaryCommand secondaryCommand payloadLength payload body)
+ #:transparent)
+
+;; single, maybe escaped, payload data byte
+(define ebus-payload
+ (choice (seq escape-seq <- ebus-const-escape
+ escape-code <- (byte-in (list 0 1))
+ (return (cond
+ ((= escape-code 0) ebus-const-escape)
+ ((= escape-code 1) bytes ebus-const-syn))))
+ any-byte
+ ))
+
+(define parse-ebus-broadcast
+ (token (seq crc <- any-byte
+ syn <- ebus-const-syn
+ (return (ebus-body-broadcast crc)))))
+
+(define parse-ebus-mastermaster
+ (token (seq crc <- any-byte
+ ack <- ebus-const-ackok ;; ACK des Empfängers
+ syn <- ebus-const-syn ;; SYN des Senders
+ (return (ebus-body-mastermaster crc)))))
+
+(define parse-ebus-masterslave
+ (token (seq crc <- any-byte
+ ack <- ebus-const-ackok ;; ACK des Empfängers
+ payloadSlaveLength <- any-byte
+ payloadSlave <- (repeat ebus-payload payloadSlaveLength payloadSlaveLength)
+ crcSlave <- any-byte
+ ackSlave <- ebus-const-ackok ;; ACK des Senders
+ synSlave <- ebus-const-syn ;; SYN des Senders
+ (return (ebus-body-masterslave crc payloadSlaveLength payloadSlave crcSlave)))))
+
+(define parse-ebus-paket
+ (token (seq source <- any-byte
+ destination <- any-byte
+ primaryCommand <- any-byte
+ secondaryCommand <- any-byte
+ payloadLength <- any-byte
+ payload <- (repeat ebus-payload payloadLength payloadLength)
+ body <- (cond ((= destination ebus-const-broadcastaddr) parse-ebus-broadcast)
+ (else (choice parse-ebus-mastermaster
+ parse-ebus-masterslave)))
+ (return (ebus-paket source
+ destination
+ primaryCommand
+ secondaryCommand
+ payloadLength
+ payload
+ body)))))
+
+(define ebus-sync (tokens syncs <- (seq (repeat (string->bytes/latin-1 "\xaa")))
+ (return (length syncs))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (read-ebus input-port)
+ (define syn ((make-reader ebus-sync #:sof? #f #:eof? #f) input-port))
+ (define paket ((make-reader parse-ebus-paket #:sof? #f #:eof? #f) input-port))
+ (cond ((not (false? syn)) (log-ebus2-debug "dropped ~a x SYN (~a)" syn ebus-const-syn)))
+ (cond ((not (false? paket)) paket)
+ ((eof-object? (peek-byte input-port)) eof)
+ (else
+ ;; skip one byte
+ (let ([byte (read-byte input-port)])
+ (log-ebus2-debug "drop ~s 0x~x" byte byte))
+ (read-ebus input-port))))
+
+(provide
+ ;; Read Layer Ebus-Paket `ebus-paket`
+ read-ebus
+ ;; Expose datastructures
+ (struct-out ebus-paket)
+ (struct-out ebus-body-broadcast)
+ (struct-out ebus-body-mastermaster)
+ (struct-out ebus-body-masterslave))