From e15a7e1267a6f733d734c5d3b59f3acc28bb4b29 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Mon, 25 Feb 2013 19:39:53 +0100 Subject: initial commit --- .../github/jodersky/ace/protocol/LinkLayer.scala | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala (limited to 'scala/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala') diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala new file mode 100644 index 0000000..5f8d228 --- /dev/null +++ b/scala/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 -- cgit v1.2.3