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

;; 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-master-or-slave (token (choice parse-ebus-mastermaster parse-ebus-masterslave)))

(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 parse-ebus-master-or-slave))
                                     (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)
  (let ([syn   ((make-reader ebus-sync #:sof? #f #:eof? #f)  input-port)]
        [paket   ((make-reader parse-ebus-paket #:sof? #f #:eof? #f) input-port)])
    (cond ((not (false? syn))
           (display (format "drop ~s x SYN (~s) ~n" syn ebus-const-syn))))
    (cond ((not (false? paket))
           paket)
          ((eof-object? (peek-byte input-port))
           eof)
          (else
	   (let ([byte (read-byte input-port)])
	     (display (format "drop ~s 0x~x ~n" byte byte)))
	   ;; skip one byte
           (read-byte input-port)
           (read-ebus input-port)))))

(provide (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 layre2- (struct-out ebus-body-masterslave)))