aboutsummaryrefslogtreecommitdiff
path: root/scala/ace/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala
diff options
context:
space:
mode:
Diffstat (limited to 'scala/ace/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala')
-rw-r--r--scala/ace/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala72
1 files changed, 72 insertions, 0 deletions
diff --git a/scala/ace/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala b/scala/ace/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala
new file mode 100644
index 0000000..5f8d228
--- /dev/null
+++ b/scala/ace/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala
@@ -0,0 +1,72 @@
+package com.github.jodersky.ace.protocol
+
+import scala.collection.mutable.ArrayBuffer
+import scala.concurrent.Future
+import scala.concurrent.ExecutionContext.Implicits.global
+
+class LinkLayer extends ReactiveLayer[Array[Byte], Packet] {
+ import LinkLayer._
+
+ private var state: State = Waiting
+ private val buffer = new ArrayBuffer[Int]
+
+ def receive(data: Array[Byte]) = for (d <- data) receive(d)
+
+ def receive(data: Byte): Unit = {
+ val unsigned = data & 0xff
+
+ state match {
+ case Escaping => {
+ buffer += unsigned
+ state = Receiving
+ }
+ case Waiting => if (unsigned == Start) {
+ buffer.clear()
+ state = Receiving
+ }
+ case Receiving => unsigned match {
+ case Escape => state = Escaping
+ case Start => buffer.clear()
+ case End => {
+ state = Waiting
+ if (checksum(buffer.init.toArray) == buffer.last)
+ notifyHigher(Packet(buffer.init.toArray))
+ }
+ case datum => buffer += datum
+ }
+ }
+ }
+
+ def write(packet: Packet): Future[Packet] = {
+ val buffer = new ArrayBuffer[Int]
+ buffer += Start
+ packet.data foreach { unsigned =>
+ unsigned match {
+ case Start | End | Escape => {
+ buffer += Escape
+ buffer += unsigned
+ }
+ case _ => buffer += unsigned
+ }
+ }
+ buffer += checksum(packet.data)
+ buffer += End
+ writeToLower(buffer.map(_.toByte).toArray).map(_ => packet)
+ }
+}
+
+object LinkLayer {
+ sealed trait State
+ case object Waiting extends State
+ case object Receiving extends State
+ case object Escaping extends State
+
+ final val Escape = 0x02
+ final val Start = 0x03
+ final val End = 0x10
+
+ def checksum(unsignedData: Seq[Int]) = {
+ unsignedData.fold(0)(_ ^ _)
+ }
+
+} \ No newline at end of file