summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxengineering <me@xengineering.eu>2024-05-30 20:00:44 +0200
committerxengineering <me@xengineering.eu>2024-05-30 20:06:23 +0200
commit922d2a0cbd1406c0b437c0a062a8c04129d7dda4 (patch)
tree933e13ed1bfa7d1c01e9e600db226f1da0c524e4
parent85dc84ab0e8f5bf2fc02ad8881c7a7247bdb492b (diff)
downloadiot-core-922d2a0cbd1406c0b437c0a062a8c04129d7dda4.tar
iot-core-922d2a0cbd1406c0b437c0a062a8c04129d7dda4.tar.zst
iot-core-922d2a0cbd1406c0b437c0a062a8c04129d7dda4.zip
software: communication: Implement unslip()
This implements to decode the Serial Line Internet Protocol (SLIP). It splits the continuous byte stream into frames. Based on these frames the rest of the data link layer and upper layers can be implemented.
-rw-r--r--software/communication/data_link.go63
-rw-r--r--software/communication/data_link_test.go33
-rw-r--r--software/communication/interface.go10
3 files changed, 103 insertions, 3 deletions
diff --git a/software/communication/data_link.go b/software/communication/data_link.go
new file mode 100644
index 0000000..d6e752d
--- /dev/null
+++ b/software/communication/data_link.go
@@ -0,0 +1,63 @@
+package communication
+
+const (
+ SLIP_END = 0xC0
+ SLIP_ESC = 0xDB
+ SLIP_ESC_END = 0xDC
+ SLIP_ESC_ESC = 0xDD
+ SLIP_MAX_PAYLOAD = 1500
+)
+
+type dataLink struct {
+ rx chan []byte
+}
+
+func newDataLink() dataLink {
+ dl := dataLink{}
+
+ dl.rx = make(chan []byte)
+
+ return dl
+}
+
+func (dl *dataLink) start(source chan byte) {
+ go dl.receive(source)
+}
+
+func (dl *dataLink) receive(source chan byte) {
+ for {
+ frame := unslip(source)
+ dl.rx <- frame
+ }
+}
+
+func unslip(source chan byte) []byte {
+ escaped := false
+ buffer := make([]byte, 0)
+
+ for {
+ octet := <-source
+ if escaped {
+ switch octet {
+ case SLIP_ESC_END:
+ buffer = append(buffer, SLIP_END)
+ case SLIP_ESC_ESC:
+ buffer = append(buffer, SLIP_ESC)
+ }
+ } else {
+ switch octet {
+ case SLIP_END:
+ break
+ case SLIP_ESC:
+ escaped = true
+ continue
+ default:
+ buffer = append(buffer, octet)
+ continue
+ }
+ break
+ }
+ }
+
+ return buffer
+}
diff --git a/software/communication/data_link_test.go b/software/communication/data_link_test.go
new file mode 100644
index 0000000..91b941d
--- /dev/null
+++ b/software/communication/data_link_test.go
@@ -0,0 +1,33 @@
+package communication
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestUnslip(t *testing.T) {
+ input := []byte{
+ 0xFF, 0x12, SLIP_END,
+ }
+
+ bytes := make(chan byte)
+ frames := make(chan []byte)
+
+ go func() {
+ for _, v := range input {
+ bytes <- v
+ }
+ }()
+
+ go func() {
+ for {
+ frames <- unslip(bytes)
+ }
+ }()
+
+ frame := <-frames
+ expected := []byte{0xFF, 0x12}
+ if !reflect.DeepEqual(frame, expected) {
+ t.Fatalf("Frame '%v' does not match expected '%v'\n", frame, expected)
+ }
+}
diff --git a/software/communication/interface.go b/software/communication/interface.go
index d124a48..df089f2 100644
--- a/software/communication/interface.go
+++ b/software/communication/interface.go
@@ -1,11 +1,12 @@
package communication
import (
- "fmt"
+ "log"
)
type SerialInterface struct {
phy physical
+ dl dataLink
}
func NewSerialInterface() (SerialInterface, error) {
@@ -17,16 +18,19 @@ func NewSerialInterface() (SerialInterface, error) {
return iface, err
}
+ iface.dl = newDataLink()
+
return iface, nil
}
func (i *SerialInterface) Start() {
i.phy.start()
+ i.dl.start(i.phy.rx)
}
func (i *SerialInterface) Cat() {
for {
- data := <-i.phy.rx
- fmt.Printf("%s", string(data))
+ data := <-i.dl.rx
+ log.Printf("RX: '%v'\n", data)
}
}