summaryrefslogtreecommitdiff
path: root/ebus-racket/ebus/layer2.rkt
blob: 3309c1659189b6b51347be37a81942860de1d17e (plain)
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
#lang racket/base
(require racket/bool
         (planet bzlib/parseq:1:3))

(define logger (make-logger 'ebus-layer2 (current-logger)))
;; Ebus SYN
(define ebus-const-syn #xaa)
;; Ebus Escape-Sequence Start
(define ebus-const-escape #xa9)
;; Ebus ACK
(define ebus-const-ackok #x00)
;; Ebus Broadcast Address
(define ebus-const-broadcastaddr 254)

(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-message logger 'debug (format "drop ~s x SYN (~s)" syn ebus-const-syn) #t)))
  (cond ((not (false? paket))
	 paket)
	((eof-object? (peek-byte input-port))
	 eof)
	(else
	 ;; skip one byte
	 (let ([byte (read-byte input-port)])
	   (log-message logger 'debug (format "drop ~s 0x~x" byte byte) #t))
	 (read-ebus input-port))))

(provide 
 ;; Read Layer Ebus-Paket `ebus-paket`
 (prefix-out layer2- read-ebus)
 (prefix-out layer2- (struct-out ebus-paket))
 (prefix-out layer2- (struct-out ebus-body-broadcast))
 (prefix-out layer2- (struct-out ebus-body-mastermaster))
 (prefix-out layer2- (struct-out ebus-body-masterslave))
 (prefix-out layer2- logger))