From e15a7e1267a6f733d734c5d3b59f3acc28bb4b29 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Mon, 25 Feb 2013 19:39:53 +0100 Subject: initial commit --- arduino/ace/.gitignore | 7 + arduino/ace/Makefile | 7 + arduino/ace/ace.c | 116 ++++ arduino/ace/ace.h | 27 + arduino/ace/arduino.mk | 379 ++++++++++++ arduino/ace/arq.c | 122 ++++ arduino/ace/arq.h | 52 ++ arduino/ace/framing.c | 88 +++ arduino/ace/framing.h | 47 ++ arduino/ace/test.ino | 44 ++ arduino/ace_cpp_old/Framer.cpp | 101 ++++ arduino/ace_cpp_old/Framer.h | 51 ++ arduino/ace_cpp_old/Makefile | 7 + arduino/ace_cpp_old/SafeSerial.cpp | 59 ++ arduino/ace_cpp_old/SafeSerial.h | 23 + arduino/ace_cpp_old/ace.ino | 13 + arduino/ace_cpp_old/arduino.mk | 379 ++++++++++++ arduino/ace_old/Makefile | 7 + arduino/ace_old/ace.ino | 117 ++++ arduino/ace_old/arduino.mk | 379 ++++++++++++ arduino/ace_old/debug.h | 9 + arduino/ace_old/link.c | 103 ++++ arduino/ace_old/link.h | 24 + arduino/ace_old/physical.c | 61 ++ arduino/ace_old/physical.h | 19 + arduino/ace_old/transport.c | 166 ++++++ arduino/ace_old/transport.h | 32 + scala/.gitignore | 18 + scala/build.sbt | 9 + scala/lib/jssc.jar | Bin 0 -> 120277 bytes .../scala/com/github/jodersky/ace/Arduino.scala | 28 + .../main/scala/com/github/jodersky/ace/Main.scala | 18 + .../scala/com/github/jodersky/ace/SafeSerial.scala | 35 ++ .../github/jodersky/ace/protocol/LinkLayer.scala | 72 +++ .../com/github/jodersky/ace/protocol/Message.scala | 3 + .../com/github/jodersky/ace/protocol/Packet.scala | 3 + .../jodersky/ace/protocol/PhysicalLayer.scala | 37 ++ .../jodersky/ace/protocol/ReactiveLayer.scala | 39 ++ .../jodersky/ace/protocol/SecureSerial.scala | 22 + .../jodersky/ace/protocol/TransportLayer.scala | 88 +++ specification/.gitignore | 1 + specification/latex/specification.aux | 18 + specification/latex/specification.log | 656 +++++++++++++++++++++ specification/latex/specification.pdf | Bin 0 -> 60846 bytes specification/latex/specification.tex | 103 ++++ specification/latex/specification.toc | 1 + 46 files changed, 3590 insertions(+) create mode 100644 arduino/ace/.gitignore create mode 100644 arduino/ace/Makefile create mode 100644 arduino/ace/ace.c create mode 100644 arduino/ace/ace.h create mode 100644 arduino/ace/arduino.mk create mode 100644 arduino/ace/arq.c create mode 100644 arduino/ace/arq.h create mode 100644 arduino/ace/framing.c create mode 100644 arduino/ace/framing.h create mode 100644 arduino/ace/test.ino create mode 100644 arduino/ace_cpp_old/Framer.cpp create mode 100644 arduino/ace_cpp_old/Framer.h create mode 100644 arduino/ace_cpp_old/Makefile create mode 100644 arduino/ace_cpp_old/SafeSerial.cpp create mode 100644 arduino/ace_cpp_old/SafeSerial.h create mode 100644 arduino/ace_cpp_old/ace.ino create mode 100644 arduino/ace_cpp_old/arduino.mk create mode 100644 arduino/ace_old/Makefile create mode 100644 arduino/ace_old/ace.ino create mode 100644 arduino/ace_old/arduino.mk create mode 100644 arduino/ace_old/debug.h create mode 100644 arduino/ace_old/link.c create mode 100644 arduino/ace_old/link.h create mode 100644 arduino/ace_old/physical.c create mode 100644 arduino/ace_old/physical.h create mode 100644 arduino/ace_old/transport.c create mode 100644 arduino/ace_old/transport.h create mode 100644 scala/.gitignore create mode 100644 scala/build.sbt create mode 100644 scala/lib/jssc.jar create mode 100644 scala/src/main/scala/com/github/jodersky/ace/Arduino.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/Main.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/SafeSerial.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/LinkLayer.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/Message.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/Packet.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/PhysicalLayer.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/ReactiveLayer.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/SecureSerial.scala create mode 100644 scala/src/main/scala/com/github/jodersky/ace/protocol/TransportLayer.scala create mode 100644 specification/.gitignore create mode 100644 specification/latex/specification.aux create mode 100644 specification/latex/specification.log create mode 100644 specification/latex/specification.pdf create mode 100644 specification/latex/specification.tex create mode 100644 specification/latex/specification.toc diff --git a/arduino/ace/.gitignore b/arduino/ace/.gitignore new file mode 100644 index 0000000..a9dd55f --- /dev/null +++ b/arduino/ace/.gitignore @@ -0,0 +1,7 @@ +.lib/ +.dep/ +*.o +*.hex +*.elf +*~ + diff --git a/arduino/ace/Makefile b/arduino/ace/Makefile new file mode 100644 index 0000000..3e0f36d --- /dev/null +++ b/arduino/ace/Makefile @@ -0,0 +1,7 @@ +#SOURCES := main.cc other.cc +#LIBRARIES := EEPROM + +ARDUINODIR=$(ARDUINO_HOME) +BOARD=mega2560 +#export LIBRARIES=LiquidCrystal +include arduino.mk diff --git a/arduino/ace/ace.c b/arduino/ace/ace.c new file mode 100644 index 0000000..ea05e1c --- /dev/null +++ b/arduino/ace/ace.c @@ -0,0 +1,116 @@ +#include "ace.h" + +#include + + +typedef struct { + uint8_t buffer[SERIAL_BUFFER_SIZE]; + volatile uint16_t head; + volatile uint16_t tail; +} ring_buffer; + +static ring_buffer tx_buffer0 = {{0}, 0, 0}; +static framer framer0; +static arq arq0; +static uint32_t max_ticks0; +static uint32_t ticks0; + +//initialize UART +static void init_s0(uint32_t baud) { + UCSR0A |= (1 << U2X0); //enable double speed transmission + uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2; + UBRR0H = baud_setting >> 8; + UBRR0L = baud_setting; + UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); // defaults to 8-bit, no parity, 1 stop bit + UCSR0B &= ~(1 << UDRIE0) | (1 << TXEN0) | (1 << RXCIE0); +} + +static void send_to_s0(uint8_t byte) { + uint16_t i = (tx_buffer0.head + 1) % SERIAL_BUFFER_SIZE; + // If the output buffer is full, there's nothing for it other than to + // wait for the interrupt handler to empty it a bit + if (i == tx_buffer0.tail) return; + //while (i == tx_buffer0.tail) {}; + tx_buffer0.buffer[tx_buffer0.head] = byte; + tx_buffer0.head = i; + //enable data register empty interrupt + UCSR0B |= (1 << UDRIE0); +} + +static void send_to_framer0(int16_t size, const uint8_t* const data) { + send_frame(&framer0, size, data); +} + +static void receive_from_framer0(int16_t size, uint8_t* data) { + receive_frame(&arq0, size, data); +} + +//called when byte is received +ISR(USART0_RX_vect) { + uint8_t c = UDR0; + receive_byte(&framer0, c); +} + +//called when data register is empty +ISR(USART0_UDRE_vect) { + if (tx_buffer0.head == tx_buffer0.tail) { + UCSR0B &= ~(1 << UDRIE0); //buffer empty, disable interruot + } else { + uint8_t c = tx_buffer0.buffer[tx_buffer0.tail]; + tx_buffer0.tail = (tx_buffer0.tail + 1) % SERIAL_BUFFER_SIZE; + UDR0 = c; //write next byte + } +} + +//initialize timer +static void init_t0(uint32_t ticks) { + cli(); + TCCR1A = 0; + TCCR1B = 0; + TCCR1B |= (1 << WGM12); // turn on CTC mode: + TCCR1B |= (1 << CS11); // set CS31 for 64 prescaler + // set compare match register to desired timer count: + OCR1A = F_CPU / 1000 / 64; // should be 250 for F_CPU=16Mhz and f = 1000Hz + sei(); + //the timer should now interrupt every ms + max_ticks0 = ticks; + ticks0 = 0; +} + +inline static void start_t0() { + TIMSK1 |= (1 << OCIE1A); +} + +inline static void stop_t0() { + TIMSK1 &= ~(1 << OCIE1A); +} + +ISR(TIMER1_COMPA_vect) { + ticks0 += 1; + if (ticks0 > max_ticks0) { + timeout(&arq0); + ticks0 = 0; + } +} + +void init_ace0(uint32_t baud, uint32_t extra_time) { + init_s0(baud); + init_framer(&framer0); + init_arq(&arq0); + + framer0.sender = send_to_s0; + arq0.sender = send_to_framer0; + + framer0.receiver = receive_from_framer0; + arq0.event_handler = ace_event0; + + uint32_t bits = (MAX_FRAME_SIZE + 3) * 8 * 2; + uint32_t tx_time = bits * 1000 / baud; // transmission time in milliseconds + init_t0(tx_time + extra_time); + arq0.start_timer = start_t0; + arq0.stop_timer = stop_t0; +} + +void ace_send0(uint8_t size, const uint8_t* const message) { + send_message(&arq0, size, message); +} diff --git a/arduino/ace/ace.h b/arduino/ace/ace.h new file mode 100644 index 0000000..75b178c --- /dev/null +++ b/arduino/ace/ace.h @@ -0,0 +1,27 @@ +#ifndef ACE_H +#define ACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "framing.h" +#include "arq.h" + +#define SERIAL_BUFFER_SIZE 64 + +void init_ace0(uint32_t baud, uint32_t extra_time); +void ace_send0(uint8_t size, const uint8_t* const message); +void ace_event0(message_event event, int16_t size, const uint8_t* const message); + +#define init_ace init_ace0 +#define ace_send ace_send0 +#define ace_event ace_event0 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ACE_H */ diff --git a/arduino/ace/arduino.mk b/arduino/ace/arduino.mk new file mode 100644 index 0000000..9fce9c7 --- /dev/null +++ b/arduino/ace/arduino.mk @@ -0,0 +1,379 @@ +#_______________________________________________________________________________ +# +# edam's Arduino makefile +#_______________________________________________________________________________ +# version 0.4 +# +# Copyright (C) 2011, 2012 Tim Marston . +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +#_______________________________________________________________________________ +# +# +# This is a general purpose makefile for use with Arduino hardware and +# software. It works with the arduino-1.0 software release. To download the +# latest version of this makefile, visit the following website, where you can +# also find more information and documentation on it's use. The following text +# can only really be considered a reference to it's use. +# +# http://ed.am/dev/make/arduino-mk +# +# This makefile can be used as a drop-in replacement for the Arduino IDE's +# build system. To use it, save arduino.mk somewhere (I keep mine at +# ~/src/arduino.mk) and create a symlink to it in your project directory named +# "Makefile". For example: +# +# $ ln -s ~/src/arduino.mk Makefile +# +# The Arduino software (version 1.0 or later) is required. If you are using +# Debian (or a derivative), type `apt-get install arduino`. Otherwise, you +# will have to download the Arduino software manually from http://arduino.cc/. +# It is suggested that you install it at ~/opt/arduino if you are unsure. +# +# If you downloaded the Arduino software manually and unpacked it somewhere +# other than ~/opt/arduino, you will need to set up ARDUINODIR to be the path +# where you unpacked it. (If unset, ARDUINODIR defaults to ~/opt/arduino and +# then /usr/share/arduino, in that order.) You might be best to set this in +# your ~/.profile by adding something like this: +# +# export ARDUINODIR=~/somewhere/arduino-1.0 +# +# You will also need to set BOARD to the type of Arduino you're building for. +# Type `make boards` for a list of acceptable values. You could set a default +# in your ~/.profile if you want, but it is suggested that you specify this at +# build time, especially if you work with different types of Arduino. For +# example: +# +# $ export BOARD=uno +# $ make +# +# You may also need to set SERIALDEV if it is not detected correctly. +# +# The presence of a .ino (or .pde) file causes the arduino.mk to automatically +# determine values for SOURCES, TARGET and LIBRARIES. Any .c, .cc and .cpp +# files in the project directory (or any "util" or "utility" subdirectories) +# are automatically included in the build and are scanned for Arduino libraries +# that have been #included. Note, there can only be one .ino (or .pde) file. +# +# Alternatively, if you want to manually specify build variables, create a +# Makefile that defines SOURCES and LIBRARIES and then includes arduino.mk. +# (There is no need to define TARGET). Here is an example Makefile: +# +# SOURCES := main.cc other.cc +# LIBRARIES := EEPROM +# include ~/src/arduino.mk +# +# Here is a complete list of configuration parameters: +# +# ARDUINODIR The path where the Arduino software is installed on your system. +# +# ARDUINOCONST The Arduino software version, as an integer, used to define the +# ARDUINO version constant. This defaults to 100 if undefined. +# +# AVRDUDECONF The avrdude.conf to use. If undefined, this defaults to a guess +# based on where the avrdude in use is. If empty, no avrdude.conf +# is passed to avrdude (to the system default is used). +# +# AVRTOOLSPATH A space-separated list of directories to search in order when +# looking for the avr build tools. This defaults to the system PATH +# followed by subdirectories in ARDUINODIR if undefined. +# +# BOARD Specify a target board type. Run `make boards` to see available +# board types. +# +# LIBRARIES A list of Arduino libraries to build and include. This is set +# automatically if a .ino (or .pde) is found. +# +# SERIALDEV The unix device name of the serial device that is the Arduino. +# If unspecified, an attempt is made to determine the name of a +# connected Arduino's serial device. +# +# SOURCES A list of all source files of whatever language. The language +# type is determined by the file extension. This is set +# automatically if a .ino (or .pde) is found. +# +# TARGET The name of the target file. This is set automatically if a +# .ino (or .pde) is found, but it is not necessary to set it +# otherwise. +# +# This makefile also defines the following goals for use on the command line +# when you run make: +# +# all This is the default if no goal is specified. It builds the +# target. +# +# target Builds the target. +# +# upload Uploads the last built target to an attached Arduino. +# +# clean Deletes files created during the build. +# +# boards Display a list of available board names, so that you can set the +# BOARD environment variable appropriately. +# +# monitor Start `screen` on the serial device. This is meant to be an +# equivalent to the Arduino serial monitor. +# +# size Displays size information about the bulit target. +# +# Builds the specified file, either an object file or the target, +# from those that that would be built for the project. +#_______________________________________________________________________________ +# + +# default arduino software directory, check software exists +ifndef ARDUINODIR +ARDUINODIR := $(firstword $(wildcard ~/opt/arduino /usr/share/arduino)) +endif +ifeq "$(wildcard $(ARDUINODIR)/hardware/arduino/boards.txt)" "" +$(error ARDUINODIR is not set correctly; arduino software not found) +endif + +# default arduino version +ARDUINOCONST ?= 100 + +# default path for avr tools +ifndef AVRTOOLSPATH +AVRTOOLSPATH := $(subst :, , $(PATH)) +AVRTOOLSPATH += $(ARDUINODIR)/hardware/tools +AVRTOOLSPATH += $(ARDUINODIR)/hardware/tools/avr/bin +endif + +# auto mode? +INOFILE := $(wildcard *.ino *.pde) +ifdef INOFILE +ifneq "$(words $(INOFILE))" "1" +$(error There is more than one .pde or .ino file in this directory!) +endif + +# automatically determine sources and targeet +TARGET := $(basename $(INOFILE)) +SOURCES := $(INOFILE) \ + $(wildcard *.c *.cc *.cpp) \ + $(wildcard $(addprefix util/, *.c *.cc *.cpp)) \ + $(wildcard $(addprefix utility/, *.c *.cc *.cpp)) + +# automatically determine included libraries +LIBRARIES := $(filter $(notdir $(wildcard $(ARDUINODIR)/libraries/*)), \ + $(shell sed -ne "s/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p" $(SOURCES))) + +endif + +# no serial device? make a poor attempt to detect an arduino +SERIALDEVGUESS := 0 +ifeq "$(SERIALDEV)" "" +SERIALDEV := $(firstword $(wildcard \ + /dev/ttyACM? /dev/ttyUSB? /dev/tty.usbserial* /dev/tty.usbmodem*)) +SERIALDEVGUESS := 1 +endif + +# software +findsoftware = $(firstword $(wildcard $(addsuffix /$(1), $(AVRTOOLSPATH)))) +CC := $(call findsoftware,avr-gcc) +CXX := $(call findsoftware,avr-g++) +LD := $(call findsoftware,avr-ld) +AR := $(call findsoftware,avr-ar) +OBJCOPY := $(call findsoftware,avr-objcopy) +AVRDUDE := $(call findsoftware,avrdude) +AVRSIZE := $(call findsoftware,avr-size) + +# files +TARGET := $(if $(TARGET),$(TARGET),a.out) +OBJECTS := $(addsuffix .o, $(basename $(SOURCES))) +DEPFILES := $(patsubst %, .dep/%.dep, $(SOURCES)) +ARDUINOCOREDIR := $(ARDUINODIR)/hardware/arduino/cores/arduino +ARDUINOLIB := .lib/arduino.a +ARDUINOLIBLIBSDIR := $(ARDUINODIR)/libraries +ARDUINOLIBLIBSPATH := $(foreach lib, $(LIBRARIES), \ + $(ARDUINODIR)/libraries/$(lib)/ $(ARDUINODIR)/libraries/$(lib)/utility/ ) +ARDUINOLIBOBJS := $(foreach dir, $(ARDUINOCOREDIR) $(ARDUINOLIBLIBSPATH), \ + $(patsubst %, .lib/%.o, $(wildcard $(addprefix $(dir)/, *.c *.cpp)))) +ifeq "$(AVRDUDECONF)" "" +ifeq "$(AVRDUDE)" "$(ARDUINODIR)/hardware/tools/avr/bin/avrdude" +AVRDUDECONF := $(ARDUINODIR)/hardware/tools/avr/etc/avrdude.conf +else +AVRDUDECONF := $(wildcard $(AVRDUDE).conf) +endif +endif + +# no board? +ifndef BOARD +ifneq "$(MAKECMDGOALS)" "boards" +ifneq "$(MAKECMDGOALS)" "clean" +$(error BOARD is unset. Type 'make boards' to see possible values) +endif +endif +endif + +# obtain board parameters from the arduino boards.txt file +BOARDS_FILE := $(ARDUINODIR)/hardware/arduino/boards.txt +BOARD_BUILD_MCU := \ + $(shell sed -ne "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_BUILD_FCPU := \ + $(shell sed -ne "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_BUILD_VARIANT := \ + $(shell sed -ne "s/$(BOARD).build.variant=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_UPLOAD_SPEED := \ + $(shell sed -ne "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_UPLOAD_PROTOCOL := \ + $(shell sed -ne "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_USB_VID := \ + $(shell sed -ne "s/$(BOARD).build.vid=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_USB_PID := \ + $(shell sed -ne "s/$(BOARD).build.pid=\(.*\)/\1/p" $(BOARDS_FILE)) + +# invalid board? +ifeq "$(BOARD_BUILD_MCU)" "" +ifneq "$(MAKECMDGOALS)" "boards" +ifneq "$(MAKECMDGOALS)" "clean" +$(error BOARD is invalid. Type 'make boards' to see possible values) +endif +endif +endif + +# flags +CPPFLAGS := -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections +CPPFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CPPFLAGS += -mmcu=$(BOARD_BUILD_MCU) +CPPFLAGS += -DF_CPU=$(BOARD_BUILD_FCPU) -DARDUINO=$(ARDUINOCONST) +CPPFLAGS += -DUSB_VID=$(BOARD_USB_VID) -DUSB_PID=$(BOARD_USB_PID) +CPPFLAGS += -I. -Iutil -Iutility -I $(ARDUINOCOREDIR) +CPPFLAGS += -I $(ARDUINODIR)/hardware/arduino/variants/$(BOARD_BUILD_VARIANT)/ +CPPFLAGS += $(addprefix -I $(ARDUINODIR)/libraries/, $(LIBRARIES)) +CPPFLAGS += $(patsubst %, -I $(ARDUINODIR)/libraries/%/utility, $(LIBRARIES)) +CPPDEPFLAGS = -MMD -MP -MF .dep/$<.dep +CPPINOFLAGS := -x c++ -include $(ARDUINOCOREDIR)/Arduino.h +AVRDUDEFLAGS := $(addprefix -C , $(AVRDUDECONF)) -DV +AVRDUDEFLAGS += -p $(BOARD_BUILD_MCU) -P $(SERIALDEV) +AVRDUDEFLAGS += -c $(BOARD_UPLOAD_PROTOCOL) -b $(BOARD_UPLOAD_SPEED) +LINKFLAGS := -Os -Wl,--gc-sections -mmcu=$(BOARD_BUILD_MCU) + +# figure out which arg to use with stty (for OS X, GNU and busybox stty) +STTYFARG := $(shell stty --help 2>&1 | \ + grep -q 'illegal option' && echo -f || echo -F) + +# include dependencies +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEPFILES) +endif + +# default rule +.DEFAULT_GOAL := all + +#_______________________________________________________________________________ +# RULES + +.PHONY: all target upload clean boards monitor size + +all: target + +target: $(TARGET).hex + +upload: target + @echo "\nUploading to board..." + @test -n "$(SERIALDEV)" || { \ + echo "error: SERIALDEV could not be determined automatically." >&2; \ + exit 1; } + @test 0 -eq $(SERIALDEVGUESS) || { \ + echo "*GUESSING* at serial device:" $(SERIALDEV); \ + echo; } + stty $(STTYFARG) $(SERIALDEV) hupcl + $(AVRDUDE) $(AVRDUDEFLAGS) -U flash:w:$(TARGET).hex:i + +clean: + rm -f $(OBJECTS) + rm -f $(TARGET).elf $(TARGET).hex $(ARDUINOLIB) *~ + rm -rf .lib .dep + +boards: + @echo Available values for BOARD: + @sed -nEe '/^#/d; /^[^.]+\.name=/p' $(BOARDS_FILE) | \ + sed -Ee 's/([^.]+)\.name=(.*)/\1 \2/' \ + -e 's/(.{12}) *(.*)/\1 \2/' + +monitor: + @test -n "$(SERIALDEV)" || { \ + echo "error: SERIALDEV could not be determined automatically." >&2; \ + exit 1; } + @test -n `which screen` || { \ + echo "error: can't find GNU screen, you might need to install it." >&2 \ + ecit 1; } + @test 0 -eq $(SERIALDEVGUESS) || { \ + echo "*GUESSING* at serial device:" $(SERIALDEV); \ + echo; } + screen $(SERIALDEV) + +size: $(TARGET).elf + echo && $(AVRSIZE) --format=avr --mcu=$(BOARD_BUILD_MCU) $(TARGET).elf + +# building the target + +$(TARGET).hex: $(TARGET).elf + $(OBJCOPY) -O ihex -R .eeprom $< $@ + +.INTERMEDIATE: $(TARGET).elf + +$(TARGET).elf: $(ARDUINOLIB) $(OBJECTS) + $(CC) $(LINKFLAGS) $(OBJECTS) $(ARDUINOLIB) -lm -o $@ + +%.o: %.c + mkdir -p .dep/$(dir $<) + $(COMPILE.c) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.cpp + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.cc + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.C + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.ino + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $(CPPINOFLAGS) $< + +%.o: %.pde + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ -x c++ -include $(ARDUINOCOREDIR)/Arduino.h $< + +# building the arduino library + +$(ARDUINOLIB): $(ARDUINOLIBOBJS) + $(AR) rcs $@ $? + +.lib/%.c.o: %.c + mkdir -p $(dir $@) + $(COMPILE.c) -o $@ $< + +.lib/%.cpp.o: %.cpp + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< + +.lib/%.cc.o: %.cc + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< + +.lib/%.C.o: %.C + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< diff --git a/arduino/ace/arq.c b/arduino/ace/arq.c new file mode 100644 index 0000000..9d4a08c --- /dev/null +++ b/arduino/ace/arq.c @@ -0,0 +1,122 @@ +#include "arq.h" + +#include +/* Expected frame data for ARQ + * + * +-----+-----+------+ + * | seq | cmd | data | + * +-----+-----+------+ + * + * seq: sequence number of frame (1 byte) + * cmd: command id of frame (1 byte), currently either ACK or DATA + * data: actual data of frame (arbitraty length, respecting frame limitations) + * + * Note: frame checking, headers and footers are not handled by arq, see 'framing' instead + * +*/ + +#define MAX_RESENDS 5 //number of resends before a timeout is generated +#define MAX_SEQ 255 //maximum sequence number of frames +#define DATA 0x05 +#define ACK 0x06 + +#define SEQ_INDEX 0 +#define CMD_INDEX 1 +#define MESSAGE_OFFSET 2 +#define MAX_MESSAGE_SIZE MAX_FRAME_SIZE - MESSAGE_OFFSET + + +typedef enum { + RECEIVED_FRAME, + TIMEOUT +} arq_event; + +static void send_ack(arq* a, uint8_t seq) { + uint8_t data[] = {seq, ACK}; + a->sender(2, data); +} + +static void process_event(arq* a, arq_event event, int16_t data_size, uint8_t* data) { + if (event == RECEIVED_FRAME) { + uint8_t seq = data[SEQ_INDEX]; + uint8_t cmd = data[CMD_INDEX]; + uint8_t* message = &(data[MESSAGE_OFFSET]); + int16_t message_size = data_size - MESSAGE_OFFSET; + + if (!a->awaiting_ack) { //ready to receive + if (cmd == DATA) { + if (a->last_received_seq != seq) { + a->last_received_seq = seq; + a->event_handler(RECEIVED, message_size, message); + } + send_ack(a, seq); + } + //ignore case in which an ack is received even though none is awaited + } else { //awaiting ack + a->awaiting_ack = false; + a->stop_timer(); + + if (cmd == ACK && seq == a->last_sent_buffer[SEQ_INDEX]) { + a->event_handler(SEND_SUCCESS, a->last_sent_size - MESSAGE_OFFSET, &(a->last_sent_buffer[MESSAGE_OFFSET])); + } else { + a->event_handler(BAD_ACK, a->last_sent_size - MESSAGE_OFFSET, &(a->last_sent_buffer[MESSAGE_OFFSET])); + } + } + + } else if (event == TIMEOUT) { + if (a->resends > MAX_RESENDS) { + a->awaiting_ack = false; + a->stop_timer(); + a->event_handler(NO_ACK, a->last_sent_size - MESSAGE_OFFSET, &(a->last_sent_buffer[MESSAGE_OFFSET])); + } else { + a->resends += 1; + a->sender(a->last_sent_size, a->last_sent_buffer); + a->awaiting_ack = true; + a->start_timer(); + } + } +} + +void receive_frame(arq* a, int16_t size, uint8_t* data) { + process_event(a, RECEIVED_FRAME, size, data); +} + +void timeout(arq* a) { + process_event(a, TIMEOUT, 0, NULL); +} + +void send_message(arq* a, int16_t size, const uint8_t * const message) { + if (a->awaiting_ack) { + a->event_handler(BUSY, size, message); + return; + } + + if (size > MAX_MESSAGE_SIZE) { + a->event_handler(SIZE_ERROR, size, message); + return; + } + + + a->last_sent_buffer[SEQ_INDEX] += 1; //increment seq + a->last_sent_buffer[CMD_INDEX] = DATA; + int i; + for (i = 0; i < size; ++i) { + a->last_sent_buffer[i + MESSAGE_OFFSET] = message[i]; + } + + a->last_sent_size = MESSAGE_OFFSET + size; + + a->sender(a->last_sent_size, a->last_sent_buffer); + a->awaiting_ack = true; + a->resends = 0; + a->start_timer(); +} + +void init_arq(arq* a) { + a->last_sent_size = 0; + a->last_received_seq = 0; + a->resends = 0; + a->awaiting_ack = false; +} + + diff --git a/arduino/ace/arq.h b/arduino/ace/arq.h new file mode 100644 index 0000000..592b0d4 --- /dev/null +++ b/arduino/ace/arq.h @@ -0,0 +1,52 @@ +#ifndef ARQ_H +#define ARQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "framing.h" + + +typedef enum { + RECEIVED = 0, + SEND_SUCCESS = 1, + NO_ACK = 3, + BAD_ACK = 4, + SIZE_ERROR = 5, + BUSY = 6 +} message_event; + +typedef void (*send_frame_function)(int16_t size, uint8_t* data); +typedef void (*message_event_function)(message_event e, int16_t size, const uint8_t* const message); +typedef void (*void_function)(); + +typedef struct { + uint8_t last_sent_buffer[MAX_FRAME_SIZE]; + int16_t last_sent_size; + uint8_t last_received_seq; + uint8_t resends; + bool awaiting_ack; + + send_frame_function sender; + message_event_function event_handler; + void_function start_timer; + void_function stop_timer; + +} arq; + +void init_arq(arq* a); +void receive_frame(arq* a, int16_t size, uint8_t* data); +void timeout(arq* a); +void send_message(arq* a, int16_t size, const uint8_t * const message); + + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ARQ_H */ diff --git a/arduino/ace/framing.c b/arduino/ace/framing.c new file mode 100644 index 0000000..4d9c5de --- /dev/null +++ b/arduino/ace/framing.c @@ -0,0 +1,88 @@ +#include "framing.h" + +static inline bool is_cmd(uint8_t byte) { + return (byte == FRAME_START || byte == FRAME_STOP || byte == FRAME_ESCAPE); +} + +static inline void reset(framer* f) { + f->position = -1; + f->checksum = 0x00; +} + +static inline void accept(framer* f, uint8_t byte) { + + //if a new byte would cause an overflow, restart frame + //note that this should not happen if both communicating parties have defined the same maximum frame length + if (f->position >= MAX_FRAME_SIZE) { + reset(f); + return; + } + + if (f->position != -1) { // i.e. a previous byte exists + f->buffer[f->position] = f->staged; + f->checksum = f->checksum ^ f->staged; + } + + f->position += 1; + f->staged = byte; +} + +void receive_byte(framer* f, uint8_t byte) { + + switch(f->state) { + case ESCAPING: + accept(f, byte); + f->state = RECEIVING; + break; + + case WAITING: + if (byte == FRAME_START) { + reset(f); + f->state = RECEIVING; + } + break; + + case RECEIVING: + switch(byte) { + case FRAME_ESCAPE: + f->state = ESCAPING; + break; + case FRAME_START: + reset(f); + break; + case FRAME_STOP: + f->state = WAITING; + if (f->staged == f->checksum) { //at this point, staged byte is the checksum sent in the frame (last byte of frame) + f->receiver(f->position, f->buffer); + } + break; + + default: + accept(f, byte); + break; + } + } +} + +void send_frame(framer* f, int16_t size, const uint8_t * const data_out) { + uint8_t checksum = 0x00; + uint8_t byte; + send_byte_function sender = f->sender; + + sender(FRAME_START); + int i; + for (i = 0; i < size; ++i) { + byte = data_out[i]; + if (is_cmd(byte)) sender(FRAME_ESCAPE); + sender(byte); + checksum = checksum ^ byte; + } + if (is_cmd(checksum)) sender(FRAME_ESCAPE); + sender(checksum); + sender(FRAME_STOP); +} + +void init_framer(framer* f) { + f->state = WAITING; + reset(f); +} diff --git a/arduino/ace/framing.h b/arduino/ace/framing.h new file mode 100644 index 0000000..daacba7 --- /dev/null +++ b/arduino/ace/framing.h @@ -0,0 +1,47 @@ +#ifndef FRAMING_H +#define FRAMING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define MAX_FRAME_SIZE 128 +#define FRAME_ESCAPE 0x02 +#define FRAME_START 0x03 +#define FRAME_STOP 0x10 + +typedef enum { + WAITING, + RECEIVING, + ESCAPING +} link_state; + +typedef void (*receive_frame_function)(int16_t size, uint8_t* data); +typedef void (*send_byte_function)(uint8_t byte); + + +typedef struct { + link_state state; // current state + uint8_t buffer[MAX_FRAME_SIZE]; // in data buffer + uint8_t staged; // previously read byte, will be put in buffer after next read + int16_t position; //current position of next byte to be read in buffer + uint8_t checksum; //current value of calculated checksum + + receive_frame_function receiver; + send_byte_function sender; + +} framer; + +void init_framer(framer* f); +void receive_byte(framer* f, uint8_t byte); +void send_frame(framer* f, int16_t size, const uint8_t * const data_out); + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* FRAMING_H */ diff --git a/arduino/ace/test.ino b/arduino/ace/test.ino new file mode 100644 index 0000000..e9df65f --- /dev/null +++ b/arduino/ace/test.ino @@ -0,0 +1,44 @@ +#include "Arduino.h" + +#include "LiquidCrystal.h" +#include "ace.h" + +LiquidCrystal lcd(8, 9, 4, 5, 6, 11); + +#define ERR_PIN 3 + +void ace_event(message_event e, int16_t size, const uint8_t* const message) { + + if (e == 0 || e == 1) { + digitalWrite(ERR_PIN, LOW); + lcd.clear(); + for(int i = 0; i < size; ++i) { + lcd.write(message[i]); + } + } + else { + digitalWrite(ERR_PIN, HIGH); + lcd.clear(); + lcd.print(e); + } +} + +void setup() { + init_ace(115200, 20); + lcd.begin(16,2); + lcd.clear(); + lcd.print("ready"); + pinMode(ERR_PIN, OUTPUT); +} + +uint8_t i = 0; +void loop() { + + lcd.clear(); + lcd.print("|"); + + + delay(1000); + ace_send0(1, &i); + delay(1000); +} diff --git a/arduino/ace_cpp_old/Framer.cpp b/arduino/ace_cpp_old/Framer.cpp new file mode 100644 index 0000000..03335af --- /dev/null +++ b/arduino/ace_cpp_old/Framer.cpp @@ -0,0 +1,101 @@ +#include "Framer.h" + +Framer::Framer(): + state(WAITING), + position(-1), + checksum(0) { +} + +void Framer::reset() { + position = -1; + checksum = 0x00; +} + +void Framer::accept(uint8_t byte) { + + //if a new byte would cause an overflow, restart frame + //note that this should not happen if both communicating parties have defined the same maximum frame length + if (position >= MAX_FRAME_SIZE) { + reset(); + return; + } + + if (position != -1) { // i.e. a previous byte exists + frameBuffer[position] = staged; + checksum = checksum ^ staged; + } + + position += 1; + staged = byte; + +} + +void Framer::put(uint8_t byte) { + + switch(state) { + case ESCAPING: + accept(byte); + state = RECEIVING; + break; + + case WAITING: + if (byte == START) { + reset(); + state = RECEIVING; + } + break; + + case RECEIVING: + switch(byte) { + case ESCAPE: + state = ESCAPING; + break; + case START: + reset(); + break; + case STOP: + state = WAITING; + if (staged == checksum) { //at this point, staged byte is the checksum sent in the frame (last byte of frame) + onFrame(position, frameBuffer); + } + break; + + default: + accept(byte); + break; + } + } +} + + + +void Framer::send(uint16_t length, const uint8_t * const data) { + uint8_t checksum = 0x00; + uint8_t byte; + + onSendByte(START); + for (int i = 0; i < length; ++i) { + byte = data[i]; + if (isCommandByte(byte)) + onSendByte(ESCAPE); + checksum = checksum ^ byte; + isCommandByte(byte); + } + if (isCommandByte(checksum)) { + onSendByte(ESCAPE); + } + onSendByte(checksum); + onSendByte(STOP); +}; + + + //~ cli(); + //~ TCCR1A = 0; // set entire TCCR1A register to 0 + //~ TCCR1B = 0; // same for TCCR1B + //~ // turn on CTC mode: + //~ TCCR1B |= (1 << WGM12); + //~ // set CS31 for 64 prescaler + //~ TCCR1B |= (1 << CS11); + //~ // set compare match register to desired timer count: + //~ OCR1A = F_CPU / 1000 / 64; // should be 250 for F_CPU=16Mhz and f = 1000Hz + //~ sei(); diff --git a/arduino/ace_cpp_old/Framer.h b/arduino/ace_cpp_old/Framer.h new file mode 100644 index 0000000..f06bebb --- /dev/null +++ b/arduino/ace_cpp_old/Framer.h @@ -0,0 +1,51 @@ +#ifndef FRAMER_H +#define FRAMER_H + +#include + +#define MAX_PACKET_SIZE 64 +#define MAX_FRAME_SIZE MAX_PACKET_SIZE + 3 + +class Framer { +private: + + enum LinkState { + WAITING, + RECEIVING, + ESCAPING + }; + + static const uint8_t ESCAPE = 0x02; + static const uint8_t START = 0x03; + static const uint8_t STOP = 0x10; + + LinkState state; //current state + uint8_t frameBuffer[MAX_FRAME_SIZE]; //data of current frame + uint8_t staged; //previous byte read, not defined when position == -1 + + int16_t position; //position of next byte to be read into frame buffer, can also be -1 if no byte has yet been staged + uint8_t checksum; + + + inline void reset(); //reset current frame + inline void accept(uint8_t byte); //reads a data byte (not a command byte) and takes an appropraiet action by modifying internal state + inline static bool isCommandByte(uint8_t byte) {return (byte == START || byte == STOP || byte == ESCAPE);} + + +protected: + + Framer(); + void put(uint8_t byte); + void send(uint16_t length, const uint8_t * const data); + + /* Called when a byte is to be sent. + * @param byte the byte to be sent */ + virtual void onSendByte(uint8_t byte) = 0; + + /* Called when a valid frame is received. */ + virtual void onFrame(uint16_t length, uint8_t *data) = 0; + +}; + + +#endif /* FRAMER_H */ diff --git a/arduino/ace_cpp_old/Makefile b/arduino/ace_cpp_old/Makefile new file mode 100644 index 0000000..5ed9f66 --- /dev/null +++ b/arduino/ace_cpp_old/Makefile @@ -0,0 +1,7 @@ +#SOURCES := main.cc other.cc +#LIBRARIES := EEPROM + +ARDUINODIR=$(ARDUINO_HOME) +BOARD=mega2560 +export LIBRARIES=LiquidCrystal +include arduino.mk diff --git a/arduino/ace_cpp_old/SafeSerial.cpp b/arduino/ace_cpp_old/SafeSerial.cpp new file mode 100644 index 0000000..bab930e --- /dev/null +++ b/arduino/ace_cpp_old/SafeSerial.cpp @@ -0,0 +1,59 @@ +#include "SafeSerial.h" + +#include + +typedef struct { + uint8_t buffer[SERIAL_BUFFER_SIZE]; + volatile uint16_t head; + volatile uint16_t tail; +} ring_buffer; + +static ring_buffer tx_buffer = {{0}, 0, 0}; + +SafeSerial::begin(uint32_t baud) { + //enable double speed transmission + *ucsrXa |= (1 << u2xX); + + uint16_t baudSetting = (F_CPU / 4 / baud - 1) / 2; + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + *ubrrXh = baudSetting >> 8; + *ubrrXl = baudSetting; + + // defaults to 8-bit, no parity, 1 stop bit + *ucsrXb |= (1 << *exenX) | (1 << *txenX) | (1 << *rxcieX); + *ucsrXb &= ~(1 << *udrieX) | (1 << *txenX) | (1 << *rxcieX); +} + + +//receive +ISR(USART0_RX_vect) { + uint8_t c = UDR0; + serial.put(c); +} + +//data register empty +ISR(USART0_UDRE_vect) { + if (tx_buffer.head == tx_buffer.tail) { + //buffer empty, disable interruot + UCSR0B &= ~(1 << UDRIE0); + } else { + uint8_t c = tx_buffer.buffer[tx_buffer.tail]; + tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + UDR0 = c; //write next byte + } +} + +void SafeSerial::send(uint8_t byte) { + uint16_t i = (tx_buffer.head + 1) % SERIAL_BUFFER_SIZE; + + // If the output buffer is full, there's nothing for it other than to + // wait for the interrupt handler to empty it a bit +if (i == tx_buffer.tail) return; + //while (i == tx_buffer.tail) {}; + + tx_buffer.buffer[tx_buffer.head] = byte; + tx_buffer.head = i; + + //enable data register empty interrupt + UCSR0B |= (1 << UDRIE0); +}; diff --git a/arduino/ace_cpp_old/SafeSerial.h b/arduino/ace_cpp_old/SafeSerial.h new file mode 100644 index 0000000..12dba3e --- /dev/null +++ b/arduino/ace_cpp_old/SafeSerial.h @@ -0,0 +1,23 @@ +#ifndef SAFESERIAL_H +#define SAFESERIAL_H + +#include +#include "Framer.h" + +//#define MAX_PACKET_SIZE 64 +//#define MAX_FRAME_SIZE MAX_PACKET_SIZE + 3 + +#define SERIAL_BUFFER_SIZE 64 + +class SafeSerial: public Framer { +private: + void sendByte(uint8_t byte); + + +protected: + /* virtual */ void onSendByte(uint8_t byte) {}; + /* virtual */ void onFrame(uint16_t length, uint8_t *data) {}; + +}; + +#endif /* SAFESERIAL_H */ diff --git a/arduino/ace_cpp_old/ace.ino b/arduino/ace_cpp_old/ace.ino new file mode 100644 index 0000000..2ca0347 --- /dev/null +++ b/arduino/ace_cpp_old/ace.ino @@ -0,0 +1,13 @@ +#include "Arduino.h" + +#include "SafeSerial.h" + +volatile SafeSerial s; + +void setup() { + +} + +void loop() { + s; +} diff --git a/arduino/ace_cpp_old/arduino.mk b/arduino/ace_cpp_old/arduino.mk new file mode 100644 index 0000000..9fce9c7 --- /dev/null +++ b/arduino/ace_cpp_old/arduino.mk @@ -0,0 +1,379 @@ +#_______________________________________________________________________________ +# +# edam's Arduino makefile +#_______________________________________________________________________________ +# version 0.4 +# +# Copyright (C) 2011, 2012 Tim Marston . +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +#_______________________________________________________________________________ +# +# +# This is a general purpose makefile for use with Arduino hardware and +# software. It works with the arduino-1.0 software release. To download the +# latest version of this makefile, visit the following website, where you can +# also find more information and documentation on it's use. The following text +# can only really be considered a reference to it's use. +# +# http://ed.am/dev/make/arduino-mk +# +# This makefile can be used as a drop-in replacement for the Arduino IDE's +# build system. To use it, save arduino.mk somewhere (I keep mine at +# ~/src/arduino.mk) and create a symlink to it in your project directory named +# "Makefile". For example: +# +# $ ln -s ~/src/arduino.mk Makefile +# +# The Arduino software (version 1.0 or later) is required. If you are using +# Debian (or a derivative), type `apt-get install arduino`. Otherwise, you +# will have to download the Arduino software manually from http://arduino.cc/. +# It is suggested that you install it at ~/opt/arduino if you are unsure. +# +# If you downloaded the Arduino software manually and unpacked it somewhere +# other than ~/opt/arduino, you will need to set up ARDUINODIR to be the path +# where you unpacked it. (If unset, ARDUINODIR defaults to ~/opt/arduino and +# then /usr/share/arduino, in that order.) You might be best to set this in +# your ~/.profile by adding something like this: +# +# export ARDUINODIR=~/somewhere/arduino-1.0 +# +# You will also need to set BOARD to the type of Arduino you're building for. +# Type `make boards` for a list of acceptable values. You could set a default +# in your ~/.profile if you want, but it is suggested that you specify this at +# build time, especially if you work with different types of Arduino. For +# example: +# +# $ export BOARD=uno +# $ make +# +# You may also need to set SERIALDEV if it is not detected correctly. +# +# The presence of a .ino (or .pde) file causes the arduino.mk to automatically +# determine values for SOURCES, TARGET and LIBRARIES. Any .c, .cc and .cpp +# files in the project directory (or any "util" or "utility" subdirectories) +# are automatically included in the build and are scanned for Arduino libraries +# that have been #included. Note, there can only be one .ino (or .pde) file. +# +# Alternatively, if you want to manually specify build variables, create a +# Makefile that defines SOURCES and LIBRARIES and then includes arduino.mk. +# (There is no need to define TARGET). Here is an example Makefile: +# +# SOURCES := main.cc other.cc +# LIBRARIES := EEPROM +# include ~/src/arduino.mk +# +# Here is a complete list of configuration parameters: +# +# ARDUINODIR The path where the Arduino software is installed on your system. +# +# ARDUINOCONST The Arduino software version, as an integer, used to define the +# ARDUINO version constant. This defaults to 100 if undefined. +# +# AVRDUDECONF The avrdude.conf to use. If undefined, this defaults to a guess +# based on where the avrdude in use is. If empty, no avrdude.conf +# is passed to avrdude (to the system default is used). +# +# AVRTOOLSPATH A space-separated list of directories to search in order when +# looking for the avr build tools. This defaults to the system PATH +# followed by subdirectories in ARDUINODIR if undefined. +# +# BOARD Specify a target board type. Run `make boards` to see available +# board types. +# +# LIBRARIES A list of Arduino libraries to build and include. This is set +# automatically if a .ino (or .pde) is found. +# +# SERIALDEV The unix device name of the serial device that is the Arduino. +# If unspecified, an attempt is made to determine the name of a +# connected Arduino's serial device. +# +# SOURCES A list of all source files of whatever language. The language +# type is determined by the file extension. This is set +# automatically if a .ino (or .pde) is found. +# +# TARGET The name of the target file. This is set automatically if a +# .ino (or .pde) is found, but it is not necessary to set it +# otherwise. +# +# This makefile also defines the following goals for use on the command line +# when you run make: +# +# all This is the default if no goal is specified. It builds the +# target. +# +# target Builds the target. +# +# upload Uploads the last built target to an attached Arduino. +# +# clean Deletes files created during the build. +# +# boards Display a list of available board names, so that you can set the +# BOARD environment variable appropriately. +# +# monitor Start `screen` on the serial device. This is meant to be an +# equivalent to the Arduino serial monitor. +# +# size Displays size information about the bulit target. +# +# Builds the specified file, either an object file or the target, +# from those that that would be built for the project. +#_______________________________________________________________________________ +# + +# default arduino software directory, check software exists +ifndef ARDUINODIR +ARDUINODIR := $(firstword $(wildcard ~/opt/arduino /usr/share/arduino)) +endif +ifeq "$(wildcard $(ARDUINODIR)/hardware/arduino/boards.txt)" "" +$(error ARDUINODIR is not set correctly; arduino software not found) +endif + +# default arduino version +ARDUINOCONST ?= 100 + +# default path for avr tools +ifndef AVRTOOLSPATH +AVRTOOLSPATH := $(subst :, , $(PATH)) +AVRTOOLSPATH += $(ARDUINODIR)/hardware/tools +AVRTOOLSPATH += $(ARDUINODIR)/hardware/tools/avr/bin +endif + +# auto mode? +INOFILE := $(wildcard *.ino *.pde) +ifdef INOFILE +ifneq "$(words $(INOFILE))" "1" +$(error There is more than one .pde or .ino file in this directory!) +endif + +# automatically determine sources and targeet +TARGET := $(basename $(INOFILE)) +SOURCES := $(INOFILE) \ + $(wildcard *.c *.cc *.cpp) \ + $(wildcard $(addprefix util/, *.c *.cc *.cpp)) \ + $(wildcard $(addprefix utility/, *.c *.cc *.cpp)) + +# automatically determine included libraries +LIBRARIES := $(filter $(notdir $(wildcard $(ARDUINODIR)/libraries/*)), \ + $(shell sed -ne "s/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p" $(SOURCES))) + +endif + +# no serial device? make a poor attempt to detect an arduino +SERIALDEVGUESS := 0 +ifeq "$(SERIALDEV)" "" +SERIALDEV := $(firstword $(wildcard \ + /dev/ttyACM? /dev/ttyUSB? /dev/tty.usbserial* /dev/tty.usbmodem*)) +SERIALDEVGUESS := 1 +endif + +# software +findsoftware = $(firstword $(wildcard $(addsuffix /$(1), $(AVRTOOLSPATH)))) +CC := $(call findsoftware,avr-gcc) +CXX := $(call findsoftware,avr-g++) +LD := $(call findsoftware,avr-ld) +AR := $(call findsoftware,avr-ar) +OBJCOPY := $(call findsoftware,avr-objcopy) +AVRDUDE := $(call findsoftware,avrdude) +AVRSIZE := $(call findsoftware,avr-size) + +# files +TARGET := $(if $(TARGET),$(TARGET),a.out) +OBJECTS := $(addsuffix .o, $(basename $(SOURCES))) +DEPFILES := $(patsubst %, .dep/%.dep, $(SOURCES)) +ARDUINOCOREDIR := $(ARDUINODIR)/hardware/arduino/cores/arduino +ARDUINOLIB := .lib/arduino.a +ARDUINOLIBLIBSDIR := $(ARDUINODIR)/libraries +ARDUINOLIBLIBSPATH := $(foreach lib, $(LIBRARIES), \ + $(ARDUINODIR)/libraries/$(lib)/ $(ARDUINODIR)/libraries/$(lib)/utility/ ) +ARDUINOLIBOBJS := $(foreach dir, $(ARDUINOCOREDIR) $(ARDUINOLIBLIBSPATH), \ + $(patsubst %, .lib/%.o, $(wildcard $(addprefix $(dir)/, *.c *.cpp)))) +ifeq "$(AVRDUDECONF)" "" +ifeq "$(AVRDUDE)" "$(ARDUINODIR)/hardware/tools/avr/bin/avrdude" +AVRDUDECONF := $(ARDUINODIR)/hardware/tools/avr/etc/avrdude.conf +else +AVRDUDECONF := $(wildcard $(AVRDUDE).conf) +endif +endif + +# no board? +ifndef BOARD +ifneq "$(MAKECMDGOALS)" "boards" +ifneq "$(MAKECMDGOALS)" "clean" +$(error BOARD is unset. Type 'make boards' to see possible values) +endif +endif +endif + +# obtain board parameters from the arduino boards.txt file +BOARDS_FILE := $(ARDUINODIR)/hardware/arduino/boards.txt +BOARD_BUILD_MCU := \ + $(shell sed -ne "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_BUILD_FCPU := \ + $(shell sed -ne "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_BUILD_VARIANT := \ + $(shell sed -ne "s/$(BOARD).build.variant=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_UPLOAD_SPEED := \ + $(shell sed -ne "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_UPLOAD_PROTOCOL := \ + $(shell sed -ne "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_USB_VID := \ + $(shell sed -ne "s/$(BOARD).build.vid=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_USB_PID := \ + $(shell sed -ne "s/$(BOARD).build.pid=\(.*\)/\1/p" $(BOARDS_FILE)) + +# invalid board? +ifeq "$(BOARD_BUILD_MCU)" "" +ifneq "$(MAKECMDGOALS)" "boards" +ifneq "$(MAKECMDGOALS)" "clean" +$(error BOARD is invalid. Type 'make boards' to see possible values) +endif +endif +endif + +# flags +CPPFLAGS := -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections +CPPFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CPPFLAGS += -mmcu=$(BOARD_BUILD_MCU) +CPPFLAGS += -DF_CPU=$(BOARD_BUILD_FCPU) -DARDUINO=$(ARDUINOCONST) +CPPFLAGS += -DUSB_VID=$(BOARD_USB_VID) -DUSB_PID=$(BOARD_USB_PID) +CPPFLAGS += -I. -Iutil -Iutility -I $(ARDUINOCOREDIR) +CPPFLAGS += -I $(ARDUINODIR)/hardware/arduino/variants/$(BOARD_BUILD_VARIANT)/ +CPPFLAGS += $(addprefix -I $(ARDUINODIR)/libraries/, $(LIBRARIES)) +CPPFLAGS += $(patsubst %, -I $(ARDUINODIR)/libraries/%/utility, $(LIBRARIES)) +CPPDEPFLAGS = -MMD -MP -MF .dep/$<.dep +CPPINOFLAGS := -x c++ -include $(ARDUINOCOREDIR)/Arduino.h +AVRDUDEFLAGS := $(addprefix -C , $(AVRDUDECONF)) -DV +AVRDUDEFLAGS += -p $(BOARD_BUILD_MCU) -P $(SERIALDEV) +AVRDUDEFLAGS += -c $(BOARD_UPLOAD_PROTOCOL) -b $(BOARD_UPLOAD_SPEED) +LINKFLAGS := -Os -Wl,--gc-sections -mmcu=$(BOARD_BUILD_MCU) + +# figure out which arg to use with stty (for OS X, GNU and busybox stty) +STTYFARG := $(shell stty --help 2>&1 | \ + grep -q 'illegal option' && echo -f || echo -F) + +# include dependencies +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEPFILES) +endif + +# default rule +.DEFAULT_GOAL := all + +#_______________________________________________________________________________ +# RULES + +.PHONY: all target upload clean boards monitor size + +all: target + +target: $(TARGET).hex + +upload: target + @echo "\nUploading to board..." + @test -n "$(SERIALDEV)" || { \ + echo "error: SERIALDEV could not be determined automatically." >&2; \ + exit 1; } + @test 0 -eq $(SERIALDEVGUESS) || { \ + echo "*GUESSING* at serial device:" $(SERIALDEV); \ + echo; } + stty $(STTYFARG) $(SERIALDEV) hupcl + $(AVRDUDE) $(AVRDUDEFLAGS) -U flash:w:$(TARGET).hex:i + +clean: + rm -f $(OBJECTS) + rm -f $(TARGET).elf $(TARGET).hex $(ARDUINOLIB) *~ + rm -rf .lib .dep + +boards: + @echo Available values for BOARD: + @sed -nEe '/^#/d; /^[^.]+\.name=/p' $(BOARDS_FILE) | \ + sed -Ee 's/([^.]+)\.name=(.*)/\1 \2/' \ + -e 's/(.{12}) *(.*)/\1 \2/' + +monitor: + @test -n "$(SERIALDEV)" || { \ + echo "error: SERIALDEV could not be determined automatically." >&2; \ + exit 1; } + @test -n `which screen` || { \ + echo "error: can't find GNU screen, you might need to install it." >&2 \ + ecit 1; } + @test 0 -eq $(SERIALDEVGUESS) || { \ + echo "*GUESSING* at serial device:" $(SERIALDEV); \ + echo; } + screen $(SERIALDEV) + +size: $(TARGET).elf + echo && $(AVRSIZE) --format=avr --mcu=$(BOARD_BUILD_MCU) $(TARGET).elf + +# building the target + +$(TARGET).hex: $(TARGET).elf + $(OBJCOPY) -O ihex -R .eeprom $< $@ + +.INTERMEDIATE: $(TARGET).elf + +$(TARGET).elf: $(ARDUINOLIB) $(OBJECTS) + $(CC) $(LINKFLAGS) $(OBJECTS) $(ARDUINOLIB) -lm -o $@ + +%.o: %.c + mkdir -p .dep/$(dir $<) + $(COMPILE.c) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.cpp + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.cc + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.C + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.ino + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $(CPPINOFLAGS) $< + +%.o: %.pde + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ -x c++ -include $(ARDUINOCOREDIR)/Arduino.h $< + +# building the arduino library + +$(ARDUINOLIB): $(ARDUINOLIBOBJS) + $(AR) rcs $@ $? + +.lib/%.c.o: %.c + mkdir -p $(dir $@) + $(COMPILE.c) -o $@ $< + +.lib/%.cpp.o: %.cpp + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< + +.lib/%.cc.o: %.cc + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< + +.lib/%.C.o: %.C + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< diff --git a/arduino/ace_old/Makefile b/arduino/ace_old/Makefile new file mode 100644 index 0000000..5ed9f66 --- /dev/null +++ b/arduino/ace_old/Makefile @@ -0,0 +1,7 @@ +#SOURCES := main.cc other.cc +#LIBRARIES := EEPROM + +ARDUINODIR=$(ARDUINO_HOME) +BOARD=mega2560 +export LIBRARIES=LiquidCrystal +include arduino.mk diff --git a/arduino/ace_old/ace.ino b/arduino/ace_old/ace.ino new file mode 100644 index 0000000..33984dc --- /dev/null +++ b/arduino/ace_old/ace.ino @@ -0,0 +1,117 @@ +#include "link.h" +#include "physical.h" +#include "transport.h" + + +// include the library code: +#include + +// initialize the library with the numbers of the interface pins +LiquidCrystal lcd(8, 9, 4, 5, 6, 11); + +int freeRam () { + extern int __heap_start, *__brkval; + int v; + return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); +} + +#define LED_PIN 13 +uint8_t msg_buffer[] = {97,98,99}; + message msg = {msg_buffer, 3}; + +void setup() { + pinMode(LED_PIN, OUTPUT); + lcd.begin(16, 2); + init_physical_layer(115200); + init_transport_layer(200); + +} + + +void step_circle() { + static volatile uint8_t position = 0; + static const char chars[] = {'|', '/', '-', '\\'}; + position = position + 1; + if (position >= 4) position = 0; + + lcd.setCursor(15, 0); + lcd.print(chars[position]); +} + + +void loop() { + + //lcd.print(freeRam()); + + int x = analogRead (0); + //lcd.setCursor(10,1); + if (x < 100) { + //lcd.print ("Right "); + } + else if (x < 200) { + //lcd.print ("Up "); + } + else if (x < 400){ + //lcd.print ("Down "); + } + else if (x < 600){ +// lcd.print ("Raw "); + to_physical_layer(97); + } + else if (x < 800){ + lcd.setCursor(0,0); + lcd.print ("SENDING..."); + to_transport_layer(&msg); + lcd.print ("DONE"); + } + else { + + } + + delay(100); + + //step_circle(); +} + +/*void from_physical_layer(uint8_t byte) { + if (byte == 'A') digitalWrite(LED_PIN, HIGH); + else digitalWrite(LED_PIN, LOW); +}*/ +/*void from_link_layer(packet* s) { + if (s->data[0] == 'A') digitalWrite(LED_PIN, HIGH); + else digitalWrite(LED_PIN, LOW); + +};*/ + + +static volatile uint32_t errs = 0; +void from_transport_layer(transport_code code, message* s) { + lcd.clear(); + lcd.setCursor(0,0); + if (code == RECEIVED) { + lcd.print("RECEIVED"); + lcd.setCursor(0,1); + for (int i = 0; i < s->length; ++i) lcd.write(s->data[i]); + } + + if (code == SEND_SUCCESS) { + lcd.print("SENT"); + for (int i = 0; i < s->length; ++i) lcd.write(s->data[i]); + } + + if (code >= SEND_ERROR) { + lcd.print("ERROR"); + lcd.setCursor(0,1); + switch(code) { + case NO_ACK: + lcd.print("NO ACK"); + break; + case BAD_ACK: + lcd.print("BAD ACK"); + break; + case BUSY: + lcd.print("BUSY"); + break; + } + } +} //implemented in transport diff --git a/arduino/ace_old/arduino.mk b/arduino/ace_old/arduino.mk new file mode 100644 index 0000000..9fce9c7 --- /dev/null +++ b/arduino/ace_old/arduino.mk @@ -0,0 +1,379 @@ +#_______________________________________________________________________________ +# +# edam's Arduino makefile +#_______________________________________________________________________________ +# version 0.4 +# +# Copyright (C) 2011, 2012 Tim Marston . +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +#_______________________________________________________________________________ +# +# +# This is a general purpose makefile for use with Arduino hardware and +# software. It works with the arduino-1.0 software release. To download the +# latest version of this makefile, visit the following website, where you can +# also find more information and documentation on it's use. The following text +# can only really be considered a reference to it's use. +# +# http://ed.am/dev/make/arduino-mk +# +# This makefile can be used as a drop-in replacement for the Arduino IDE's +# build system. To use it, save arduino.mk somewhere (I keep mine at +# ~/src/arduino.mk) and create a symlink to it in your project directory named +# "Makefile". For example: +# +# $ ln -s ~/src/arduino.mk Makefile +# +# The Arduino software (version 1.0 or later) is required. If you are using +# Debian (or a derivative), type `apt-get install arduino`. Otherwise, you +# will have to download the Arduino software manually from http://arduino.cc/. +# It is suggested that you install it at ~/opt/arduino if you are unsure. +# +# If you downloaded the Arduino software manually and unpacked it somewhere +# other than ~/opt/arduino, you will need to set up ARDUINODIR to be the path +# where you unpacked it. (If unset, ARDUINODIR defaults to ~/opt/arduino and +# then /usr/share/arduino, in that order.) You might be best to set this in +# your ~/.profile by adding something like this: +# +# export ARDUINODIR=~/somewhere/arduino-1.0 +# +# You will also need to set BOARD to the type of Arduino you're building for. +# Type `make boards` for a list of acceptable values. You could set a default +# in your ~/.profile if you want, but it is suggested that you specify this at +# build time, especially if you work with different types of Arduino. For +# example: +# +# $ export BOARD=uno +# $ make +# +# You may also need to set SERIALDEV if it is not detected correctly. +# +# The presence of a .ino (or .pde) file causes the arduino.mk to automatically +# determine values for SOURCES, TARGET and LIBRARIES. Any .c, .cc and .cpp +# files in the project directory (or any "util" or "utility" subdirectories) +# are automatically included in the build and are scanned for Arduino libraries +# that have been #included. Note, there can only be one .ino (or .pde) file. +# +# Alternatively, if you want to manually specify build variables, create a +# Makefile that defines SOURCES and LIBRARIES and then includes arduino.mk. +# (There is no need to define TARGET). Here is an example Makefile: +# +# SOURCES := main.cc other.cc +# LIBRARIES := EEPROM +# include ~/src/arduino.mk +# +# Here is a complete list of configuration parameters: +# +# ARDUINODIR The path where the Arduino software is installed on your system. +# +# ARDUINOCONST The Arduino software version, as an integer, used to define the +# ARDUINO version constant. This defaults to 100 if undefined. +# +# AVRDUDECONF The avrdude.conf to use. If undefined, this defaults to a guess +# based on where the avrdude in use is. If empty, no avrdude.conf +# is passed to avrdude (to the system default is used). +# +# AVRTOOLSPATH A space-separated list of directories to search in order when +# looking for the avr build tools. This defaults to the system PATH +# followed by subdirectories in ARDUINODIR if undefined. +# +# BOARD Specify a target board type. Run `make boards` to see available +# board types. +# +# LIBRARIES A list of Arduino libraries to build and include. This is set +# automatically if a .ino (or .pde) is found. +# +# SERIALDEV The unix device name of the serial device that is the Arduino. +# If unspecified, an attempt is made to determine the name of a +# connected Arduino's serial device. +# +# SOURCES A list of all source files of whatever language. The language +# type is determined by the file extension. This is set +# automatically if a .ino (or .pde) is found. +# +# TARGET The name of the target file. This is set automatically if a +# .ino (or .pde) is found, but it is not necessary to set it +# otherwise. +# +# This makefile also defines the following goals for use on the command line +# when you run make: +# +# all This is the default if no goal is specified. It builds the +# target. +# +# target Builds the target. +# +# upload Uploads the last built target to an attached Arduino. +# +# clean Deletes files created during the build. +# +# boards Display a list of available board names, so that you can set the +# BOARD environment variable appropriately. +# +# monitor Start `screen` on the serial device. This is meant to be an +# equivalent to the Arduino serial monitor. +# +# size Displays size information about the bulit target. +# +# Builds the specified file, either an object file or the target, +# from those that that would be built for the project. +#_______________________________________________________________________________ +# + +# default arduino software directory, check software exists +ifndef ARDUINODIR +ARDUINODIR := $(firstword $(wildcard ~/opt/arduino /usr/share/arduino)) +endif +ifeq "$(wildcard $(ARDUINODIR)/hardware/arduino/boards.txt)" "" +$(error ARDUINODIR is not set correctly; arduino software not found) +endif + +# default arduino version +ARDUINOCONST ?= 100 + +# default path for avr tools +ifndef AVRTOOLSPATH +AVRTOOLSPATH := $(subst :, , $(PATH)) +AVRTOOLSPATH += $(ARDUINODIR)/hardware/tools +AVRTOOLSPATH += $(ARDUINODIR)/hardware/tools/avr/bin +endif + +# auto mode? +INOFILE := $(wildcard *.ino *.pde) +ifdef INOFILE +ifneq "$(words $(INOFILE))" "1" +$(error There is more than one .pde or .ino file in this directory!) +endif + +# automatically determine sources and targeet +TARGET := $(basename $(INOFILE)) +SOURCES := $(INOFILE) \ + $(wildcard *.c *.cc *.cpp) \ + $(wildcard $(addprefix util/, *.c *.cc *.cpp)) \ + $(wildcard $(addprefix utility/, *.c *.cc *.cpp)) + +# automatically determine included libraries +LIBRARIES := $(filter $(notdir $(wildcard $(ARDUINODIR)/libraries/*)), \ + $(shell sed -ne "s/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p" $(SOURCES))) + +endif + +# no serial device? make a poor attempt to detect an arduino +SERIALDEVGUESS := 0 +ifeq "$(SERIALDEV)" "" +SERIALDEV := $(firstword $(wildcard \ + /dev/ttyACM? /dev/ttyUSB? /dev/tty.usbserial* /dev/tty.usbmodem*)) +SERIALDEVGUESS := 1 +endif + +# software +findsoftware = $(firstword $(wildcard $(addsuffix /$(1), $(AVRTOOLSPATH)))) +CC := $(call findsoftware,avr-gcc) +CXX := $(call findsoftware,avr-g++) +LD := $(call findsoftware,avr-ld) +AR := $(call findsoftware,avr-ar) +OBJCOPY := $(call findsoftware,avr-objcopy) +AVRDUDE := $(call findsoftware,avrdude) +AVRSIZE := $(call findsoftware,avr-size) + +# files +TARGET := $(if $(TARGET),$(TARGET),a.out) +OBJECTS := $(addsuffix .o, $(basename $(SOURCES))) +DEPFILES := $(patsubst %, .dep/%.dep, $(SOURCES)) +ARDUINOCOREDIR := $(ARDUINODIR)/hardware/arduino/cores/arduino +ARDUINOLIB := .lib/arduino.a +ARDUINOLIBLIBSDIR := $(ARDUINODIR)/libraries +ARDUINOLIBLIBSPATH := $(foreach lib, $(LIBRARIES), \ + $(ARDUINODIR)/libraries/$(lib)/ $(ARDUINODIR)/libraries/$(lib)/utility/ ) +ARDUINOLIBOBJS := $(foreach dir, $(ARDUINOCOREDIR) $(ARDUINOLIBLIBSPATH), \ + $(patsubst %, .lib/%.o, $(wildcard $(addprefix $(dir)/, *.c *.cpp)))) +ifeq "$(AVRDUDECONF)" "" +ifeq "$(AVRDUDE)" "$(ARDUINODIR)/hardware/tools/avr/bin/avrdude" +AVRDUDECONF := $(ARDUINODIR)/hardware/tools/avr/etc/avrdude.conf +else +AVRDUDECONF := $(wildcard $(AVRDUDE).conf) +endif +endif + +# no board? +ifndef BOARD +ifneq "$(MAKECMDGOALS)" "boards" +ifneq "$(MAKECMDGOALS)" "clean" +$(error BOARD is unset. Type 'make boards' to see possible values) +endif +endif +endif + +# obtain board parameters from the arduino boards.txt file +BOARDS_FILE := $(ARDUINODIR)/hardware/arduino/boards.txt +BOARD_BUILD_MCU := \ + $(shell sed -ne "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_BUILD_FCPU := \ + $(shell sed -ne "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_BUILD_VARIANT := \ + $(shell sed -ne "s/$(BOARD).build.variant=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_UPLOAD_SPEED := \ + $(shell sed -ne "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_UPLOAD_PROTOCOL := \ + $(shell sed -ne "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_USB_VID := \ + $(shell sed -ne "s/$(BOARD).build.vid=\(.*\)/\1/p" $(BOARDS_FILE)) +BOARD_USB_PID := \ + $(shell sed -ne "s/$(BOARD).build.pid=\(.*\)/\1/p" $(BOARDS_FILE)) + +# invalid board? +ifeq "$(BOARD_BUILD_MCU)" "" +ifneq "$(MAKECMDGOALS)" "boards" +ifneq "$(MAKECMDGOALS)" "clean" +$(error BOARD is invalid. Type 'make boards' to see possible values) +endif +endif +endif + +# flags +CPPFLAGS := -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections +CPPFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CPPFLAGS += -mmcu=$(BOARD_BUILD_MCU) +CPPFLAGS += -DF_CPU=$(BOARD_BUILD_FCPU) -DARDUINO=$(ARDUINOCONST) +CPPFLAGS += -DUSB_VID=$(BOARD_USB_VID) -DUSB_PID=$(BOARD_USB_PID) +CPPFLAGS += -I. -Iutil -Iutility -I $(ARDUINOCOREDIR) +CPPFLAGS += -I $(ARDUINODIR)/hardware/arduino/variants/$(BOARD_BUILD_VARIANT)/ +CPPFLAGS += $(addprefix -I $(ARDUINODIR)/libraries/, $(LIBRARIES)) +CPPFLAGS += $(patsubst %, -I $(ARDUINODIR)/libraries/%/utility, $(LIBRARIES)) +CPPDEPFLAGS = -MMD -MP -MF .dep/$<.dep +CPPINOFLAGS := -x c++ -include $(ARDUINOCOREDIR)/Arduino.h +AVRDUDEFLAGS := $(addprefix -C , $(AVRDUDECONF)) -DV +AVRDUDEFLAGS += -p $(BOARD_BUILD_MCU) -P $(SERIALDEV) +AVRDUDEFLAGS += -c $(BOARD_UPLOAD_PROTOCOL) -b $(BOARD_UPLOAD_SPEED) +LINKFLAGS := -Os -Wl,--gc-sections -mmcu=$(BOARD_BUILD_MCU) + +# figure out which arg to use with stty (for OS X, GNU and busybox stty) +STTYFARG := $(shell stty --help 2>&1 | \ + grep -q 'illegal option' && echo -f || echo -F) + +# include dependencies +ifneq "$(MAKECMDGOALS)" "clean" +-include $(DEPFILES) +endif + +# default rule +.DEFAULT_GOAL := all + +#_______________________________________________________________________________ +# RULES + +.PHONY: all target upload clean boards monitor size + +all: target + +target: $(TARGET).hex + +upload: target + @echo "\nUploading to board..." + @test -n "$(SERIALDEV)" || { \ + echo "error: SERIALDEV could not be determined automatically." >&2; \ + exit 1; } + @test 0 -eq $(SERIALDEVGUESS) || { \ + echo "*GUESSING* at serial device:" $(SERIALDEV); \ + echo; } + stty $(STTYFARG) $(SERIALDEV) hupcl + $(AVRDUDE) $(AVRDUDEFLAGS) -U flash:w:$(TARGET).hex:i + +clean: + rm -f $(OBJECTS) + rm -f $(TARGET).elf $(TARGET).hex $(ARDUINOLIB) *~ + rm -rf .lib .dep + +boards: + @echo Available values for BOARD: + @sed -nEe '/^#/d; /^[^.]+\.name=/p' $(BOARDS_FILE) | \ + sed -Ee 's/([^.]+)\.name=(.*)/\1 \2/' \ + -e 's/(.{12}) *(.*)/\1 \2/' + +monitor: + @test -n "$(SERIALDEV)" || { \ + echo "error: SERIALDEV could not be determined automatically." >&2; \ + exit 1; } + @test -n `which screen` || { \ + echo "error: can't find GNU screen, you might need to install it." >&2 \ + ecit 1; } + @test 0 -eq $(SERIALDEVGUESS) || { \ + echo "*GUESSING* at serial device:" $(SERIALDEV); \ + echo; } + screen $(SERIALDEV) + +size: $(TARGET).elf + echo && $(AVRSIZE) --format=avr --mcu=$(BOARD_BUILD_MCU) $(TARGET).elf + +# building the target + +$(TARGET).hex: $(TARGET).elf + $(OBJCOPY) -O ihex -R .eeprom $< $@ + +.INTERMEDIATE: $(TARGET).elf + +$(TARGET).elf: $(ARDUINOLIB) $(OBJECTS) + $(CC) $(LINKFLAGS) $(OBJECTS) $(ARDUINOLIB) -lm -o $@ + +%.o: %.c + mkdir -p .dep/$(dir $<) + $(COMPILE.c) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.cpp + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.cc + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.C + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $< + +%.o: %.ino + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ $(CPPINOFLAGS) $< + +%.o: %.pde + mkdir -p .dep/$(dir $<) + $(COMPILE.cpp) $(CPPDEPFLAGS) -o $@ -x c++ -include $(ARDUINOCOREDIR)/Arduino.h $< + +# building the arduino library + +$(ARDUINOLIB): $(ARDUINOLIBOBJS) + $(AR) rcs $@ $? + +.lib/%.c.o: %.c + mkdir -p $(dir $@) + $(COMPILE.c) -o $@ $< + +.lib/%.cpp.o: %.cpp + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< + +.lib/%.cc.o: %.cc + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< + +.lib/%.C.o: %.C + mkdir -p $(dir $@) + $(COMPILE.cpp) -o $@ $< diff --git a/arduino/ace_old/debug.h b/arduino/ace_old/debug.h new file mode 100644 index 0000000..d10d85b --- /dev/null +++ b/arduino/ace_old/debug.h @@ -0,0 +1,9 @@ +#ifndef MY_DEBUG_H +#define MY_DEBUG_H + +// include the library code: +#include +#include + + +#endif diff --git a/arduino/ace_old/link.c b/arduino/ace_old/link.c new file mode 100644 index 0000000..408e14e --- /dev/null +++ b/arduino/ace_old/link.c @@ -0,0 +1,103 @@ +#include "link.h" +#include "physical.h" + +#include +#include +#include + +typedef enum { + WAITING, + RECEIVING, + ESCAPING +} link_state; + +#define FRAME_ESCAPE 0x02 +#define FRAME_START 0x03 +#define FRAME_END 0x10 + + +void from_physical_layer(uint8_t byte) { + static link_state state = WAITING; + static uint16_t position = 0; //read position + static uint8_t packet_data_buffer[MAX_PACKET_SIZE]; + static packet received = {packet_data_buffer, 0}; + static uint8_t checksum = 0x00; + + static bool previous_exists = false; + static uint8_t previous_byte; + + #define start_receiving() \ + position = 0; \ + previous_exists = false; \ + checksum = 0x00 + + #define accept(byte) \ + if (position >= MAX_PACKET_SIZE) {start_receiving(); return;} \ + if (previous_exists) { \ + packet_data_buffer[position] = previous_byte; \ + position = position + 1; \ + checksum = checksum ^ previous_byte; \ + previous_byte = byte; \ + } else { \ + previous_byte = byte; \ + previous_exists = true; \ + } + + + switch(state) { + case ESCAPING: + accept(byte); + state = RECEIVING; + break; + + case WAITING: + if (byte == FRAME_START) { + start_receiving(); + state = RECEIVING; + } + break; + case RECEIVING: + switch(byte) { + case FRAME_ESCAPE: + state = ESCAPING; + break; + case FRAME_START: + start_receiving(); + break; + case FRAME_END: + state = WAITING; + uint8_t sent_checksum = previous_byte; + if (sent_checksum == checksum) { + received.length = position; + from_link_layer(&received); + } + + break; + default: + accept(byte); + break; + } + } + + #undef accept + #undef start_receiving +} + +void to_link_layer(packet* s) { + uint8_t checksum = 0x00; + uint8_t byte; + int i; + + to_physical_layer(FRAME_START); + for (i = 0; i < (s->length); ++i) { + byte = s->data[i]; + if (byte == FRAME_START || byte == FRAME_END || byte == FRAME_ESCAPE) + to_physical_layer(FRAME_ESCAPE); + checksum = checksum ^ byte; + to_physical_layer(byte); + } + if (checksum == FRAME_START || checksum == FRAME_END || checksum == FRAME_ESCAPE) + to_physical_layer(FRAME_ESCAPE); + to_physical_layer(checksum); + to_physical_layer(FRAME_END); +}; diff --git a/arduino/ace_old/link.h b/arduino/ace_old/link.h new file mode 100644 index 0000000..797145e --- /dev/null +++ b/arduino/ace_old/link.h @@ -0,0 +1,24 @@ +#ifndef LINK_H +#define LINK_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_PACKET_SIZE 256 + +typedef struct { + uint8_t* data; + uint16_t length; +} packet; + +void to_link_layer(packet* s); //implemented in link +void from_link_layer(packet* r); //should be implemented in transport + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* LINK_H */ diff --git a/arduino/ace_old/physical.c b/arduino/ace_old/physical.c new file mode 100644 index 0000000..17e15d7 --- /dev/null +++ b/arduino/ace_old/physical.c @@ -0,0 +1,61 @@ +#include "physical.h" +#include "link.h" + +#include + +typedef struct { + uint8_t buffer[SERIAL_BUFFER_SIZE]; + volatile uint16_t head; + volatile uint16_t tail; +} ring_buffer; + +static ring_buffer tx_buffer = {{0}, 0, 0}; + + +void init_physical_layer(uint32_t baud) { + //enable double speed transmission + UCSR0A |= (1 << U2X0); + + uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2; + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + UBRR0H = baud_setting >> 8; + UBRR0L = baud_setting; + + // defaults to 8-bit, no parity, 1 stop bit + UCSR0B |= (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); + UCSR0B &= ~(1 << UDRIE0) | (1 << TXEN0) | (1 << RXCIE0); +} + + +//receive +ISR(USART0_RX_vect) { + uint8_t c = UDR0; + from_physical_layer(c); +} + +//data register empty +ISR(USART0_UDRE_vect) { + if (tx_buffer.head == tx_buffer.tail) { + //buffer empty, disable interruot + UCSR0B &= ~(1 << UDRIE0); + } else { + uint8_t c = tx_buffer.buffer[tx_buffer.tail]; + tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; + UDR0 = c; //write next byte + } +} + +void to_physical_layer(uint8_t byte) { + uint16_t i = (tx_buffer.head + 1) % SERIAL_BUFFER_SIZE; + + // If the output buffer is full, there's nothing for it other than to + // wait for the interrupt handler to empty it a bit +if (i == tx_buffer.tail) return; + //while (i == tx_buffer.tail) {}; + + tx_buffer.buffer[tx_buffer.head] = byte; + tx_buffer.head = i; + + //enable data register empty interrupt + UCSR0B |= (1 << UDRIE0); +}; diff --git a/arduino/ace_old/physical.h b/arduino/ace_old/physical.h new file mode 100644 index 0000000..74272ff --- /dev/null +++ b/arduino/ace_old/physical.h @@ -0,0 +1,19 @@ +#ifndef PHYSICAL_H +#define PHYSICAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#define SERIAL_BUFFER_SIZE 64 + +void init_physical_layer(uint32_t baud); +void to_physical_layer(uint8_t s); //implemented in physical +void from_physical_layer(uint8_t r); //should be implemented in link + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* PHYSICAL_H */ diff --git a/arduino/ace_old/transport.c b/arduino/ace_old/transport.c new file mode 100644 index 0000000..986165e --- /dev/null +++ b/arduino/ace_old/transport.c @@ -0,0 +1,166 @@ +#include "transport.h" +#include "link.h" + +#include +#include +#include + +//ms +#define EXTRA_TIME 200 +#define MAX_RESENDS 5 +#define MAX_SEQ 255 + +#define next_seq(k) if (k < MAX_SEQ) k = k + 1; else k = 0 + +#define DATA 0x05 +#define ACK 0x06 + + +static void start_sending(message* msg, bool resend); +static void stop_sending(); + + +typedef enum { + RECEIVED_PACKET, + TIMEOUT +} event_kind; + +typedef struct { + event_kind kind; + packet* payload; +} event; + +static void disassemble_packet(packet* p, uint8_t* seq, uint8_t* command, uint8_t** msg, uint16_t* message_length) { + if (seq != NULL) *seq = p->data[0]; + if (command != NULL) *command = p->data[1]; + if (msg != NULL) *msg = &(p->data[2]); + if (message_length != NULL) *message_length = p->length - 2; +} + +static void assemble_packet(packet* p, uint8_t seq, uint8_t command, uint8_t* msg, uint16_t message_length) { + p->data[0] = seq; + p->data[1] = command; + int i; + for (i = 0; i < message_length; ++i) { + p->data[i+2] = msg[i]; + } + p->length = message_length + 2; +} + +static packet* ack(uint8_t seq) { + static uint8_t ack_buffer[] = {0, ACK}; + static packet ack_packet = {ack_buffer, 2}; + ack_buffer[0] = seq; + return &ack_packet; +} + +static volatile bool awaiting_ack = false; +static volatile uint8_t last_sent_seq = 0; +static volatile uint8_t resends = 0; +static volatile uint8_t last_sent_buffer[MAX_PACKET_SIZE]; +static volatile packet last_sent = {last_sent_buffer, 0}; + +static void process_event(event* e) { + static uint8_t last_received_seq = 0; + + switch(e->kind) { + case RECEIVED_PACKET: { + uint8_t seq; + uint8_t cmd; + static message msg; + disassemble_packet(e->payload, &seq, &cmd, &msg.data, &msg.length); + + if (!awaiting_ack) { + if (cmd == DATA) { + if (last_received_seq != seq) { + last_received_seq = seq; + from_transport_layer(RECEIVED, &msg); + } + to_link_layer(ack(seq)); + } + //ignore case in which an ack is received even though none is awaited + + } else { //waiting for an ack + stop_sending(); + disassemble_packet(&last_sent, NULL, NULL, &msg.data, &msg.length); + if (cmd == ACK && seq == last_sent_seq) { + from_transport_layer(SEND_SUCCESS, &msg); + } else { + from_transport_layer(BAD_ACK, &msg); + } + } + } break; + case TIMEOUT: + if (resends > MAX_RESENDS) { + message msg; + disassemble_packet(&last_sent, NULL, NULL, &msg.data, &msg.length); + stop_sending(); + from_transport_layer(NO_ACK, &msg); + } else { + start_sending(NULL, true); + } + break; + } +} + +static void start_sending(message* msg, bool resend) { + if (resend) { + resends = resends + 1; + } else { + next_seq(last_sent_seq); + assemble_packet(&last_sent, last_sent_seq, DATA, msg->data, msg->length); + resends = 0; + TIMSK1 |= (1 << OCIE1A); + } + + awaiting_ack = true; + to_link_layer(&last_sent); +} + +static void stop_sending() { + TIMSK1 &= ~(1 << OCIE1A); + awaiting_ack = false; +} + +static volatile uint32_t ticks; +static volatile uint32_t max_ticks; + +void init_transport_layer(uint32_t timeout_millis) { + cli(); + TCCR1A = 0; // set entire TCCR1A register to 0 + TCCR1B = 0; // same for TCCR1B + // turn on CTC mode: + TCCR1B |= (1 << WGM12); + // set CS31 for 64 prescaler + TCCR1B |= (1 << CS11); + // set compare match register to desired timer count: + OCR1A = F_CPU / 1000 / 64; // should be 250 for F_CPU=16Mhz and f = 1000Hz + sei(); + + //the timer should now interrupt every ms + max_ticks = timeout_millis; +} + +ISR(TIMER1_COMPA_vect) { + static event e = {TIMEOUT, NULL}; + + ticks = ticks + 1; + if (ticks > max_ticks) { + process_event(&e); + ticks = 0; + } +} + +void from_link_layer(packet* r) { + static event e = {RECEIVED_PACKET, NULL}; + e.payload = r; + process_event(&e); +} + +void to_transport_layer(message* s) { + if (!awaiting_ack) + start_sending(s, false); + else + from_transport_layer(BUSY, s); +} + diff --git a/arduino/ace_old/transport.h b/arduino/ace_old/transport.h new file mode 100644 index 0000000..233d19c --- /dev/null +++ b/arduino/ace_old/transport.h @@ -0,0 +1,32 @@ +#ifndef TRANSPORT_H +#define TRANSPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct { + uint8_t* data; + uint16_t length; +} message; + +typedef enum { + RECEIVED = 0, + SEND_SUCCESS = 1, + SEND_ERROR = 2, + NO_ACK = 3, + BAD_ACK = 4, + BUSY = 5 +} transport_code; + +void init_transport_layer(uint32_t timeout_millis); +void to_transport_layer(message* s); //implemented in transport +void from_transport_layer(transport_code code, message* r); //should be implemented in application + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* TRANSPORT_H */ diff --git a/scala/.gitignore b/scala/.gitignore new file mode 100644 index 0000000..94730a8 --- /dev/null +++ b/scala/.gitignore @@ -0,0 +1,18 @@ +*.class +*.log + +# sbt specific +dist/* +target/ +.target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.project +.classpath +.cache +.settings/ diff --git a/scala/build.sbt b/scala/build.sbt new file mode 100644 index 0000000..d61bc17 --- /dev/null +++ b/scala/build.sbt @@ -0,0 +1,9 @@ +name := "ace" + +organization := "com.github.jodersky" + +version := "1.0-SNAPSHOT" + +scalaVersion := "2.10.0" + +scalacOptions ++= Seq("-deprecation","-feature") diff --git a/scala/lib/jssc.jar b/scala/lib/jssc.jar new file mode 100644 index 0000000..b0d6a82 Binary files /dev/null and b/scala/lib/jssc.jar differ diff --git a/scala/src/main/scala/com/github/jodersky/ace/Arduino.scala b/scala/src/main/scala/com/github/jodersky/ace/Arduino.scala new file mode 100644 index 0000000..7077570 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/Arduino.scala @@ -0,0 +1,28 @@ +package com.github.jodersky.ace + +import scala.util.Try +import jssc.SerialPort +import jssc.SerialPortEventListener +import jssc.SerialPortEvent +import scala.util.Success +import com.github.jodersky.ace.protocol.SecureSerial +import scala.concurrent.Await +import scala.concurrent.duration._ + +object Arduino { + + private def open(port: String, rate: Int) = { + val serialPort = new SerialPort(port); + serialPort.openPort(); + serialPort.setParams(rate, + SerialPort.DATABITS_8, + SerialPort.STOPBITS_1, + SerialPort.PARITY_NONE); //Set params. Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0); + // serialPort.writeBytes("This is a test string".getBytes()); //Write data to port + //serialPort.closePort(); //Close serial port + serialPort + } + + def connect(port: String) = new SecureSerial(open(port, 115200)) + +} \ No newline at end of file diff --git a/scala/src/main/scala/com/github/jodersky/ace/Main.scala b/scala/src/main/scala/com/github/jodersky/ace/Main.scala new file mode 100644 index 0000000..17351e2 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/Main.scala @@ -0,0 +1,18 @@ +package com.github.jodersky.ace + +import scala.concurrent._ +import scala.concurrent.ExecutionContext.Implicits.global + +object Main { + + def main(args: Array[String]): Unit = { + val s = SafeSerial.open("/dev/ttyACM0", 115200).get + var cmd: String = "" + while (cmd != ":quit"){ + cmd = Console.readLine + s.send(cmd).onComplete(v => println("sent: " + v)) + } + s.close() + } + +} diff --git a/scala/src/main/scala/com/github/jodersky/ace/SafeSerial.scala b/scala/src/main/scala/com/github/jodersky/ace/SafeSerial.scala new file mode 100644 index 0000000..d75d6f5 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/SafeSerial.scala @@ -0,0 +1,35 @@ +package com.github.jodersky.ace + +import com.github.jodersky.ace.protocol._ +import jssc.SerialPort +import scala.concurrent.ExecutionContext.Implicits.global +import scala.util.Try + +class SafeSerial(port: SerialPort) { self => + val physical = new PhysicalLayer(port) + val link = new LinkLayer + val transport = new TransportLayer + + val application = new ReactiveLayer[Message, String] { + def receive(message: Message) = Console.println(message.data.map(_.toChar).mkString("")) + def write(s: String) = writeToLower(Message(s.map(_.toChar.toInt))).map(x => s) + } + + def send(s: String) = application.write(s) + def close() = Try(port.closePort()) + + physical connect link connect transport connect application + physical.begin() +} + +object SafeSerial { + def open(port: String, rate: Int) = Try { + val serialPort = new SerialPort(port); + serialPort.openPort() + serialPort.setParams(rate, + SerialPort.DATABITS_8, + SerialPort.STOPBITS_1, + SerialPort.PARITY_NONE) + serialPort + } map (port => new SafeSerial(port)) +} \ No newline at end of file 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 diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/Message.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/Message.scala new file mode 100644 index 0000000..32edfea --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/protocol/Message.scala @@ -0,0 +1,3 @@ +package com.github.jodersky.ace.protocol + +case class Message(data: Seq[Int]) \ No newline at end of file diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/Packet.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/Packet.scala new file mode 100644 index 0000000..583022f --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/protocol/Packet.scala @@ -0,0 +1,3 @@ +package com.github.jodersky.ace.protocol + +case class Packet(data: Seq[Int]) \ No newline at end of file diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/PhysicalLayer.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/PhysicalLayer.scala new file mode 100644 index 0000000..39c2d25 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/protocol/PhysicalLayer.scala @@ -0,0 +1,37 @@ +package com.github.jodersky.ace.protocol + +import scala.concurrent._ +import scala.concurrent.ExecutionContext.Implicits.global +import jssc.SerialPort +import java.io.IOException +import jssc.SerialPortEvent +import jssc.SerialPortEventListener + +class PhysicalLayer(serial: SerialPort) extends ReactiveLayer[Nothing, Array[Byte]] { + + def receive(nothing: Nothing) = throw new UnsupportedOperationException("A receive function cannot be called on the lowest layer.") + + private val listener = new SerialPortEventListener { + override def serialEvent(event: SerialPortEvent) = { + if (event.isRXCHAR()) { + val bytes = serial.readBytes + if (bytes != null) notifyHigher(bytes) + } + } + } + + + def write(data: Array[Byte]) = future { + serial.writeBytes(data) + } map { success => + if (success) data + else throw new IOException("Could not write to serial port.") + } + + def begin() = { + val mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR + serial.setEventsMask(mask) + serial.addEventListener(listener) + } + +} \ No newline at end of file diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/ReactiveLayer.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/ReactiveLayer.scala new file mode 100644 index 0000000..422ced3 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/protocol/ReactiveLayer.scala @@ -0,0 +1,39 @@ +package com.github.jodersky.ace.protocol + +import scala.concurrent.Future + +/** Represents a layer in a reactive protocol. + * + * @tparam L data type this layer receives from or writes to a lower layer + * @tparam T data type this layer sends to a higher layer or receives from a higher */ +trait ReactiveLayer[L, T] { + private var lowerLayer: Option[ReactiveLayer[_, L]] = None + private var higherLayer: Option[ReactiveLayer[T, _]] = None + + /** Notifies a higher layer that data is available. */ + protected def notifyHigher(data: T): Unit = higherLayer match { + case Some(higher) => higher.receive(data) + case None => throw new UnsupportedOperationException("Higher layer doesn't exist.") + } + + /** Writes data to a lower layer. */ + protected def writeToLower(l: L): Future[L] = lowerLayer match { + case Some(lower) => lower.write(l) + case None => Future.failed(new UnsupportedOperationException("Lower layer doesn't exist.")) + } + + /** Connects this layer with a higher layer, effectively linking calls + * `notifyHigher` to `higher.receive` and `higher.writeToLower` to `write`. */ + def connect[A](higher: ReactiveLayer[T, A]) = { + this.higherLayer = Some(higher) + higher.lowerLayer = Some(this) + higher + } + + /** Called from lower layer. */ + def receive(data: L): Unit + + /** Write data to this layer. + * @return a future value containing the data written, or an error */ + def write(data: T): Future[T] +} \ No newline at end of file diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/SecureSerial.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/SecureSerial.scala new file mode 100644 index 0000000..e229b82 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/protocol/SecureSerial.scala @@ -0,0 +1,22 @@ +package com.github.jodersky.ace.protocol + +import jssc.SerialPort +import scala.concurrent.ExecutionContext.Implicits.global +import scala.util.Try + +class SecureSerial(port: SerialPort) { self => + val physical = new PhysicalLayer(port) + val link = new LinkLayer + val transport = new TransportLayer + + val application = new ReactiveLayer[Message, String] { + def receive(message: Message) = Console.println(message.data.mkString("")) + def write(s: String) = writeToLower(Message(s.map(_.toInt))).map(x => s) + } + + def send(s: String) = application.write(s) + def close() = Try(port.closePort()) + + physical connect link connect transport connect application + physical.begin() +} \ No newline at end of file diff --git a/scala/src/main/scala/com/github/jodersky/ace/protocol/TransportLayer.scala b/scala/src/main/scala/com/github/jodersky/ace/protocol/TransportLayer.scala new file mode 100644 index 0000000..2055770 --- /dev/null +++ b/scala/src/main/scala/com/github/jodersky/ace/protocol/TransportLayer.scala @@ -0,0 +1,88 @@ +package com.github.jodersky.ace.protocol + +import scala.concurrent._ +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.duration._ +import java.io.IOException +import scala.collection.mutable.HashMap +import scala.collection.mutable.Queue +import com.github.jodersky.ace.protocol.{Packet => PPacket} +import scala.util.Success + +class TransportLayer extends ReactiveLayer[Packet, Message] { + + + private val openRequests = HashMap[Int, (Message, Promise[Message])]() + private val receivedSeqs = Queue[Int]() + + class Packet(val data: Seq[Int]) { + + def seq = data(0) + def cmd = data(1) + def message = Message(data.drop(2)) + + def underlying = PPacket(data) + } + + object Packet { + final val DATA = 0x05 + final val ACK = 0x06 + private var seq = 0; + private def nextSeq() = {seq += 1; if (seq > TransportLayer.MaxSeq) seq = 0; seq} + + def fromPacket(packet: PPacket) = new Packet(packet.data) + + def fromMessage(message: Message) = new Packet(Seq(nextSeq(), DATA) ++ message.data) + + def ack(seq: Int) = new Packet (Seq(seq, ACK)) + + } + + def receive(ppacket: PPacket) = { + val in = Packet.fromPacket(ppacket) + + in.cmd match { + case Packet.ACK => { + openRequests.get(in.seq).map{case (message, promise) => promise.complete(Success(message))} + } + + case Packet.DATA => { + writeToLower(Packet.ack(in.seq).underlying) + + if (!(receivedSeqs contains in.seq)) { + if (receivedSeqs.size > TransportLayer.MaxSeqBuffer) receivedSeqs.dequeue + receivedSeqs enqueue in.seq + notifyHigher(in.message) + } + } + + } + } + + def write(message: Message) = { + val promise = Promise[Message] + val packet = Packet.fromMessage(message) + val seq = packet.seq + + def send(n: Int): Future[Message] = + writeToLower(packet.underlying) map { packet => + Await.result(promise.future, TransportLayer.Timeout milliseconds) + } recoverWith { + case t: TimeoutException if (n < TransportLayer.MaxResends) => send(n + 1) + } + + if (openRequests.size >= TransportLayer.MaxSeqBuffer) Future.failed(new IOException("too many open requests")) + else { + openRequests += (seq -> (message, promise)) + send(0) andThen {case r => (openRequests -= seq)} + } + } + +} + +object TransportLayer { + final val Timeout = 100 + final val MaxResends = 5 + final val MaxSeq = 255 + final val MaxSeqBuffer = 10 +} \ No newline at end of file diff --git a/specification/.gitignore b/specification/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/specification/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/specification/latex/specification.aux b/specification/latex/specification.aux new file mode 100644 index 0000000..e6173fd --- /dev/null +++ b/specification/latex/specification.aux @@ -0,0 +1,18 @@ +\relax +\ifx\hyper@anchor\@undefined +\global \let \oldcontentsline\contentsline +\gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} +\global \let \oldnewlabel\newlabel +\gdef \newlabel#1#2{\newlabelxx{#1}#2} +\gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} +\AtEndDocument{\let \contentsline\oldcontentsline +\let \newlabel\oldnewlabel} +\else +\global \let \hyper@last\relax +\fi + +\select@language{english} +\@writefile{toc}{\select@language{english}} +\@writefile{lof}{\select@language{english}} +\@writefile{lot}{\select@language{english}} +\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces A frame in RSSP}}{2}{figure.1}} diff --git a/specification/latex/specification.log b/specification/latex/specification.log new file mode 100644 index 0000000..3747726 --- /dev/null +++ b/specification/latex/specification.log @@ -0,0 +1,656 @@ +This is pdfTeX, Version 3.1415926-1.40.10 (TeX Live 2009/Debian) (format=pdflatex 2012.4.28) 27 JAN 2013 17:18 +entering extended mode + %&-line parsing enabled. +**specification.tex +(./specification.tex +LaTeX2e <2009/09/24> +Babel and hyphenation patterns for english, usenglishmax, dumylang, noh +yphenation, loaded. +(/usr/share/texmf-texlive/tex/latex/base/article.cls +Document Class: article 2007/10/19 v1.4h Standard LaTeX document class +(/usr/share/texmf-texlive/tex/latex/base/size10.clo +File: size10.clo 2007/10/19 v1.4h Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +(/usr/share/texmf-texlive/tex/latex/base/inputenc.sty +Package: inputenc 2008/03/30 v1.1d Input encoding file +\inpenc@prehook=\toks14 +\inpenc@posthook=\toks15 + +(/usr/share/texmf-texlive/tex/latex/base/utf8.def +File: utf8.def 2008/04/05 v1.1m UTF-8 support for inputenc +Now handling font encoding OML ... +... no UTF-8 mapping file for font encoding OML +Now handling font encoding T1 ... +... processing UTF-8 mapping file for font encoding T1 + +(/usr/share/texmf-texlive/tex/latex/base/t1enc.dfu +File: t1enc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc + defining Unicode char U+00A1 (decimal 161) + defining Unicode char U+00A3 (decimal 163) + defining Unicode char U+00AB (decimal 171) + defining Unicode char U+00BB (decimal 187) + defining Unicode char U+00BF (decimal 191) + defining Unicode char U+00C0 (decimal 192) + defining Unicode char U+00C1 (decimal 193) + defining Unicode char U+00C2 (decimal 194) + defining Unicode char U+00C3 (decimal 195) + defining Unicode char U+00C4 (decimal 196) + defining Unicode char U+00C5 (decimal 197) + defining Unicode char U+00C6 (decimal 198) + defining Unicode char U+00C7 (decimal 199) + defining Unicode char U+00C8 (decimal 200) + defining Unicode char U+00C9 (decimal 201) + defining Unicode char U+00CA (decimal 202) + defining Unicode char U+00CB (decimal 203) + defining Unicode char U+00CC (decimal 204) + defining Unicode char U+00CD (decimal 205) + defining Unicode char U+00CE (decimal 206) + defining Unicode char U+00CF (decimal 207) + defining Unicode char U+00D0 (decimal 208) + defining Unicode char U+00D1 (decimal 209) + defining Unicode char U+00D2 (decimal 210) + defining Unicode char U+00D3 (decimal 211) + defining Unicode char U+00D4 (decimal 212) + defining Unicode char U+00D5 (decimal 213) + defining Unicode char U+00D6 (decimal 214) + defining Unicode char U+00D8 (decimal 216) + defining Unicode char U+00D9 (decimal 217) + defining Unicode char U+00DA (decimal 218) + defining Unicode char U+00DB (decimal 219) + defining Unicode char U+00DC (decimal 220) + defining Unicode char U+00DD (decimal 221) + defining Unicode char U+00DE (decimal 222) + defining Unicode char U+00DF (decimal 223) + defining Unicode char U+00E0 (decimal 224) + defining Unicode char U+00E1 (decimal 225) + defining Unicode char U+00E2 (decimal 226) + defining Unicode char U+00E3 (decimal 227) + defining Unicode char U+00E4 (decimal 228) + defining Unicode char U+00E5 (decimal 229) + defining Unicode char U+00E6 (decimal 230) + defining Unicode char U+00E7 (decimal 231) + defining Unicode char U+00E8 (decimal 232) + defining Unicode char U+00E9 (decimal 233) + defining Unicode char U+00EA (decimal 234) + defining Unicode char U+00EB (decimal 235) + defining Unicode char U+00EC (decimal 236) + defining Unicode char U+00ED (decimal 237) + defining Unicode char U+00EE (decimal 238) + defining Unicode char U+00EF (decimal 239) + defining Unicode char U+00F0 (decimal 240) + defining Unicode char U+00F1 (decimal 241) + defining Unicode char U+00F2 (decimal 242) + defining Unicode char U+00F3 (decimal 243) + defining Unicode char U+00F4 (decimal 244) + defining Unicode char U+00F5 (decimal 245) + defining Unicode char U+00F6 (decimal 246) + defining Unicode char U+00F8 (decimal 248) + defining Unicode char U+00F9 (decimal 249) + defining Unicode char U+00FA (decimal 250) + defining Unicode char U+00FB (decimal 251) + defining Unicode char U+00FC (decimal 252) + defining Unicode char U+00FD (decimal 253) + defining Unicode char U+00FE (decimal 254) + defining Unicode char U+00FF (decimal 255) + defining Unicode char U+0102 (decimal 258) + defining Unicode char U+0103 (decimal 259) + defining Unicode char U+0104 (decimal 260) + defining Unicode char U+0105 (decimal 261) + defining Unicode char U+0106 (decimal 262) + defining Unicode char U+0107 (decimal 263) + defining Unicode char U+010C (decimal 268) + defining Unicode char U+010D (decimal 269) + defining Unicode char U+010E (decimal 270) + defining Unicode char U+010F (decimal 271) + defining Unicode char U+0110 (decimal 272) + defining Unicode char U+0111 (decimal 273) + defining Unicode char U+0118 (decimal 280) + defining Unicode char U+0119 (decimal 281) + defining Unicode char U+011A (decimal 282) + defining Unicode char U+011B (decimal 283) + defining Unicode char U+011E (decimal 286) + defining Unicode char U+011F (decimal 287) + defining Unicode char U+0130 (decimal 304) + defining Unicode char U+0131 (decimal 305) + defining Unicode char U+0132 (decimal 306) + defining Unicode char U+0133 (decimal 307) + defining Unicode char U+0139 (decimal 313) + defining Unicode char U+013A (decimal 314) + defining Unicode char U+013D (decimal 317) + defining Unicode char U+013E (decimal 318) + defining Unicode char U+0141 (decimal 321) + defining Unicode char U+0142 (decimal 322) + defining Unicode char U+0143 (decimal 323) + defining Unicode char U+0144 (decimal 324) + defining Unicode char U+0147 (decimal 327) + defining Unicode char U+0148 (decimal 328) + defining Unicode char U+014A (decimal 330) + defining Unicode char U+014B (decimal 331) + defining Unicode char U+0150 (decimal 336) + defining Unicode char U+0151 (decimal 337) + defining Unicode char U+0152 (decimal 338) + defining Unicode char U+0153 (decimal 339) + defining Unicode char U+0154 (decimal 340) + defining Unicode char U+0155 (decimal 341) + defining Unicode char U+0158 (decimal 344) + defining Unicode char U+0159 (decimal 345) + defining Unicode char U+015A (decimal 346) + defining Unicode char U+015B (decimal 347) + defining Unicode char U+015E (decimal 350) + defining Unicode char U+015F (decimal 351) + defining Unicode char U+0160 (decimal 352) + defining Unicode char U+0161 (decimal 353) + defining Unicode char U+0162 (decimal 354) + defining Unicode char U+0163 (decimal 355) + defining Unicode char U+0164 (decimal 356) + defining Unicode char U+0165 (decimal 357) + defining Unicode char U+016E (decimal 366) + defining Unicode char U+016F (decimal 367) + defining Unicode char U+0170 (decimal 368) + defining Unicode char U+0171 (decimal 369) + defining Unicode char U+0178 (decimal 376) + defining Unicode char U+0179 (decimal 377) + defining Unicode char U+017A (decimal 378) + defining Unicode char U+017B (decimal 379) + defining Unicode char U+017C (decimal 380) + defining Unicode char U+017D (decimal 381) + defining Unicode char U+017E (decimal 382) + defining Unicode char U+200C (decimal 8204) + defining Unicode char U+2013 (decimal 8211) + defining Unicode char U+2014 (decimal 8212) + defining Unicode char U+2018 (decimal 8216) + defining Unicode char U+2019 (decimal 8217) + defining Unicode char U+201A (decimal 8218) + defining Unicode char U+201C (decimal 8220) + defining Unicode char U+201D (decimal 8221) + defining Unicode char U+201E (decimal 8222) + defining Unicode char U+2030 (decimal 8240) + defining Unicode char U+2031 (decimal 8241) + defining Unicode char U+2039 (decimal 8249) + defining Unicode char U+203A (decimal 8250) + defining Unicode char U+2423 (decimal 9251) +) +Now handling font encoding OT1 ... +... processing UTF-8 mapping file for font encoding OT1 + +(/usr/share/texmf-texlive/tex/latex/base/ot1enc.dfu +File: ot1enc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc + defining Unicode char U+00A1 (decimal 161) + defining Unicode char U+00A3 (decimal 163) + defining Unicode char U+00B8 (decimal 184) + defining Unicode char U+00BF (decimal 191) + defining Unicode char U+00C5 (decimal 197) + defining Unicode char U+00C6 (decimal 198) + defining Unicode char U+00D8 (decimal 216) + defining Unicode char U+00DF (decimal 223) + defining Unicode char U+00E6 (decimal 230) + defining Unicode char U+00EC (decimal 236) + defining Unicode char U+00ED (decimal 237) + defining Unicode char U+00EE (decimal 238) + defining Unicode char U+00EF (decimal 239) + defining Unicode char U+00F8 (decimal 248) + defining Unicode char U+0131 (decimal 305) + defining Unicode char U+0141 (decimal 321) + defining Unicode char U+0142 (decimal 322) + defining Unicode char U+0152 (decimal 338) + defining Unicode char U+0153 (decimal 339) + defining Unicode char U+2013 (decimal 8211) + defining Unicode char U+2014 (decimal 8212) + defining Unicode char U+2018 (decimal 8216) + defining Unicode char U+2019 (decimal 8217) + defining Unicode char U+201C (decimal 8220) + defining Unicode char U+201D (decimal 8221) +) +Now handling font encoding OMS ... +... processing UTF-8 mapping file for font encoding OMS + +(/usr/share/texmf-texlive/tex/latex/base/omsenc.dfu +File: omsenc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc + defining Unicode char U+00A7 (decimal 167) + defining Unicode char U+00B6 (decimal 182) + defining Unicode char U+00B7 (decimal 183) + defining Unicode char U+2020 (decimal 8224) + defining Unicode char U+2021 (decimal 8225) + defining Unicode char U+2022 (decimal 8226) +) +Now handling font encoding OMX ... +... no UTF-8 mapping file for font encoding OMX +Now handling font encoding U ... +... no UTF-8 mapping file for font encoding U + defining Unicode char U+00A9 (decimal 169) + defining Unicode char U+00AA (decimal 170) + defining Unicode char U+00AE (decimal 174) + defining Unicode char U+00BA (decimal 186) + defining Unicode char U+02C6 (decimal 710) + defining Unicode char U+02DC (decimal 732) + defining Unicode char U+200C (decimal 8204) + defining Unicode char U+2026 (decimal 8230) + defining Unicode char U+2122 (decimal 8482) + defining Unicode char U+2423 (decimal 9251) +)) +(/usr/share/texmf-texlive/tex/generic/babel/babel.sty +Package: babel 2008/07/06 v3.8l The Babel package + +(/usr/share/texmf-texlive/tex/generic/babel/english.ldf +Language: english 2005/03/30 v3.3o English support from the babel system + +(/usr/share/texmf-texlive/tex/generic/babel/babel.def +File: babel.def 2008/07/06 v3.8l Babel common definitions +\babel@savecnt=\count87 +\U@D=\dimen103 +) +\l@british = a dialect from \language\l@english +\l@UKenglish = a dialect from \language\l@english +\l@canadian = a dialect from \language\l@american +\l@australian = a dialect from \language\l@british +\l@newzealand = a dialect from \language\l@british +)) +(/usr/share/texmf-texlive/tex/latex/graphics/graphicx.sty +Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR) + +(/usr/share/texmf-texlive/tex/latex/graphics/keyval.sty +Package: keyval 1999/03/16 v1.13 key=value parser (DPC) +\KV@toks@=\toks16 +) +(/usr/share/texmf-texlive/tex/latex/graphics/graphics.sty +Package: graphics 2009/02/05 v1.0o Standard LaTeX Graphics (DPC,SPQR) + +(/usr/share/texmf-texlive/tex/latex/graphics/trig.sty +Package: trig 1999/03/16 v1.09 sin cos tan (DPC) +) +(/etc/texmf/tex/latex/config/graphics.cfg +File: graphics.cfg 2009/08/28 v1.8 graphics configuration of TeX Live +) +Package graphics Info: Driver file: pdftex.def on input line 91. + +(/usr/share/texmf-texlive/tex/latex/pdftex-def/pdftex.def +File: pdftex.def 2010/03/12 v0.04p Graphics/color for pdfTeX +\Gread@gobject=\count88 +)) +\Gin@req@height=\dimen104 +\Gin@req@width=\dimen105 +) +(/usr/share/texmf-texlive/tex/latex/subfigure/subfigure.sty +Package: subfigure 2002/03/15 v2.1.5 subfigure package +\subfigtopskip=\skip43 +\subfigcapskip=\skip44 +\subfigcaptopadj=\dimen106 +\subfigbottomskip=\skip45 +\subfigcapmargin=\dimen107 +\subfiglabelskip=\skip46 +\c@subfigure=\count89 +\c@lofdepth=\count90 +\c@subtable=\count91 +\c@lotdepth=\count92 + +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/share/texmf-texlive/tex/latex/subfigure/subfigure.cfg) +\subfig@top=\skip47 +\subfig@bottom=\skip48 +) +(/usr/share/texmf-texlive/tex/latex/rotating/rotating.sty +Package: rotating 2009/03/28 v2.16a rotated objects in LaTeX + +(/usr/share/texmf-texlive/tex/latex/base/ifthen.sty +Package: ifthen 2001/05/26 v1.1c Standard LaTeX ifthen package (DPC) +) +\c@r@tfl@t=\count93 +\rotFPtop=\skip49 +\rotFPbot=\skip50 +\rot@float@box=\box26 +\rot@mess@toks=\toks17 +) +(/usr/share/texmf-texlive/tex/latex/ctable/ctable.sty +Package: ctable 2009/09/17 v1.15 ctable package + +(/usr/share/texmf-texlive/tex/latex/graphics/color.sty +Package: color 2005/11/14 v1.0j Standard LaTeX Color (DPC) + +(/etc/texmf/tex/latex/config/color.cfg +File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive +) +Package color Info: Driver file: pdftex.def on input line 130. +) +(/usr/share/texmf-texlive/tex/latex/xkeyval/xkeyval.sty +Package: xkeyval 2008/08/13 v2.6a package option processing (HA) + +(/usr/share/texmf-texlive/tex/generic/xkeyval/xkeyval.tex +\XKV@toks=\toks18 +\XKV@tempa@toks=\toks19 +\XKV@depth=\count94 +File: xkeyval.tex 2008/08/13 v2.6a key=value parser (HA) +)) +(/usr/share/texmf-texlive/tex/latex/tools/array.sty +Package: array 2008/09/09 v2.4c Tabular extension package (FMi) +\col@sep=\dimen108 +\extrarowheight=\dimen109 +\NC@list=\toks20 +\extratabsurround=\skip51 +\backup@length=\skip52 +) +(/usr/share/texmf-texlive/tex/latex/tools/tabularx.sty +Package: tabularx 1999/01/07 v2.07 `tabularx' package (DPC) +\TX@col@width=\dimen110 +\TX@old@table=\dimen111 +\TX@old@col=\dimen112 +\TX@target=\dimen113 +\TX@delta=\dimen114 +\TX@cols=\count95 +\TX@ftn=\toks21 +) +(/usr/share/texmf-texlive/tex/latex/booktabs/booktabs.sty +Package: booktabs 2005/04/14 v1.61803 publication quality tables +\heavyrulewidth=\dimen115 +\lightrulewidth=\dimen116 +\cmidrulewidth=\dimen117 +\belowrulesep=\dimen118 +\belowbottomsep=\dimen119 +\aboverulesep=\dimen120 +\abovetopsep=\dimen121 +\cmidrulesep=\dimen122 +\cmidrulekern=\dimen123 +\defaultaddspace=\dimen124 +\@cmidla=\count96 +\@cmidlb=\count97 +\@aboverulesep=\dimen125 +\@belowrulesep=\dimen126 +\@thisruleclass=\count98 +\@lastruleclass=\count99 +\@thisrulewidth=\dimen127 +) +\@ctblframesep=\dimen128 +\@ctblframerule=\dimen129 +\@ctblwidth=\dimen130 +\@ctblcaptionskip=\dimen131 +\@ctblmaxwidth=\dimen132 +\@ctblmincapwidth=\dimen133 +\@ctblw=\dimen134 +\@ctblfloatwidth=\dimen135 +\@ctbloldsep=\dimen136 +\@ctbloldrule=\dimen137 +\ctbl@t=\box27 +) +(/usr/share/texmf-texlive/tex/latex/multirow/multirow.sty +\bigstrutjot=\dimen138 +) +(/usr/share/texmf-texlive/tex/latex/makecell/makecell.sty +Package: makecell 2009/08/03 V0.1e Managing of Tab Column Heads and Cells +\rotheadsize=\dimen139 +\c@nlinenum=\count100 +\TeXr@lab=\toks22 +) +(/usr/share/texmf-texlive/tex/latex/amsmath/amsmath.sty +Package: amsmath 2000/07/18 v2.13 AMS math features +\@mathmargin=\skip53 + +For additional information on amsmath, use the `?' option. +(/usr/share/texmf-texlive/tex/latex/amsmath/amstext.sty +Package: amstext 2000/06/29 v2.01 + +(/usr/share/texmf-texlive/tex/latex/amsmath/amsgen.sty +File: amsgen.sty 1999/11/30 v2.0 +\@emptytoks=\toks23 +\ex@=\dimen140 +)) +(/usr/share/texmf-texlive/tex/latex/amsmath/amsbsy.sty +Package: amsbsy 1999/11/29 v1.2d +\pmbraise@=\dimen141 +) +(/usr/share/texmf-texlive/tex/latex/amsmath/amsopn.sty +Package: amsopn 1999/12/14 v2.01 operator names +) +\inf@bad=\count101 +LaTeX Info: Redefining \frac on input line 211. +\uproot@=\count102 +\leftroot@=\count103 +LaTeX Info: Redefining \overline on input line 307. +\classnum@=\count104 +\DOTSCASE@=\count105 +LaTeX Info: Redefining \ldots on input line 379. +LaTeX Info: Redefining \dots on input line 382. +LaTeX Info: Redefining \cdots on input line 467. +\Mathstrutbox@=\box28 +\strutbox@=\box29 +\big@size=\dimen142 +LaTeX Font Info: Redeclaring font encoding OML on input line 567. +LaTeX Font Info: Redeclaring font encoding OMS on input line 568. +\macc@depth=\count106 +\c@MaxMatrixCols=\count107 +\dotsspace@=\muskip10 +\c@parentequation=\count108 +\dspbrk@lvl=\count109 +\tag@help=\toks24 +\row@=\count110 +\column@=\count111 +\maxfields@=\count112 +\andhelp@=\toks25 +\eqnshift@=\dimen143 +\alignsep@=\dimen144 +\tagshift@=\dimen145 +\tagwidth@=\dimen146 +\totwidth@=\dimen147 +\lineht@=\dimen148 +\@envbody=\toks26 +\multlinegap=\skip54 +\multlinetaggap=\skip55 +\mathdisplay@stack=\toks27 +LaTeX Info: Redefining \[ on input line 2666. +LaTeX Info: Redefining \] on input line 2667. +) +(/usr/share/texmf-texlive/tex/latex/amsfonts/amssymb.sty +Package: amssymb 2009/06/22 v3.00 + +(/usr/share/texmf-texlive/tex/latex/amsfonts/amsfonts.sty +Package: amsfonts 2009/06/22 v3.00 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 96. +)) +(/usr/share/texmf-texlive/tex/latex/hyperref/hyperref.sty +Package: hyperref 2009/10/09 v6.79a Hypertext links for LaTeX + +(/usr/share/texmf-texlive/tex/generic/oberdiek/ifpdf.sty +Package: ifpdf 2009/04/10 v2.0 Provides the ifpdf switch (HO) +Package ifpdf Info: pdfTeX in pdf mode detected. +) +(/usr/share/texmf-texlive/tex/generic/oberdiek/ifvtex.sty +Package: ifvtex 2008/11/04 v1.4 Switches for detecting VTeX and its modes (HO) +Package ifvtex Info: VTeX not detected. +) +(/usr/share/texmf-texlive/tex/generic/ifxetex/ifxetex.sty +Package: ifxetex 2009/01/23 v0.5 Provides ifxetex conditional +) +(/usr/share/texmf-texlive/tex/latex/oberdiek/hycolor.sty +Package: hycolor 2009/10/02 v1.5 Code for color options of hyperref/bookmark (H +O) + +(/usr/share/texmf-texlive/tex/latex/oberdiek/xcolor-patch.sty +Package: xcolor-patch 2009/10/02 xcolor patch +)) +\@linkdim=\dimen149 +\Hy@linkcounter=\count113 +\Hy@pagecounter=\count114 + +(/usr/share/texmf-texlive/tex/latex/hyperref/pd1enc.def +File: pd1enc.def 2009/10/09 v6.79a Hyperref: PDFDocEncoding definition (HO) +Now handling font encoding PD1 ... +... no UTF-8 mapping file for font encoding PD1 +) +(/usr/share/texmf-texlive/tex/generic/oberdiek/etexcmds.sty +Package: etexcmds 2007/12/12 v1.2 Prefix for e-TeX command names (HO) + +(/usr/share/texmf-texlive/tex/generic/oberdiek/infwarerr.sty +Package: infwarerr 2007/09/09 v1.2 Providing info/warning/message (HO) +) +Package etexcmds Info: Could not find \expanded. +(etexcmds) That can mean that you are not using pdfTeX 1.50 or +(etexcmds) that some package has redefined \expanded. +(etexcmds) In the latter case, load this package earlier. +) +(/usr/share/texmf-texlive/tex/latex/latexconfig/hyperref.cfg +File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive +) +(/usr/share/texmf-texlive/tex/latex/oberdiek/kvoptions.sty +Package: kvoptions 2009/08/13 v3.4 Keyval support for LaTeX options (HO) + +(/usr/share/texmf-texlive/tex/generic/oberdiek/kvsetkeys.sty +Package: kvsetkeys 2009/07/30 v1.5 Key value parser with default handler suppor +t (HO) +)) +Package hyperref Info: Option `colorlinks' set `true' on input line 2864. +Package hyperref Info: Option `bookmarks' set `false' on input line 2864. +Package hyperref Info: Hyper figures OFF on input line 2975. +Package hyperref Info: Link nesting OFF on input line 2980. +Package hyperref Info: Hyper index ON on input line 2983. +Package hyperref Info: Plain pages OFF on input line 2990. +Package hyperref Info: Backreferencing OFF on input line 2995. + +Implicit mode ON; LaTeX internals redefined +Package hyperref Info: Bookmarks OFF on input line 3197. +(/usr/share/texmf-texlive/tex/latex/ltxmisc/url.sty +\Urlmuskip=\muskip11 +Package: url 2006/04/12 ver 3.3 Verb mode for urls, etc. +) +LaTeX Info: Redefining \url on input line 3428. + +(/usr/share/texmf-texlive/tex/generic/oberdiek/bitset.sty +Package: bitset 2007/09/28 v1.0 Data type bit set (HO) + +(/usr/share/texmf-texlive/tex/generic/oberdiek/intcalc.sty +Package: intcalc 2007/09/27 v1.1 Expandable integer calculations (HO) +) +(/usr/share/texmf-texlive/tex/generic/oberdiek/bigintcalc.sty +Package: bigintcalc 2007/11/11 v1.1 Expandable big integer calculations (HO) + +(/usr/share/texmf-texlive/tex/generic/oberdiek/pdftexcmds.sty +Package: pdftexcmds 2009/09/23 v0.6 LuaTeX support for pdfTeX utility functions + (HO) + +(/usr/share/texmf-texlive/tex/generic/oberdiek/ifluatex.sty +Package: ifluatex 2009/04/17 v1.2 Provides the ifluatex switch (HO) +Package ifluatex Info: LuaTeX not detected. +) +(/usr/share/texmf-texlive/tex/generic/oberdiek/ltxcmds.sty +Package: ltxcmds 2009/08/05 v1.0 Some LaTeX kernel commands for general use (HO +) +) +Package pdftexcmds Info: LuaTeX not detected. +Package pdftexcmds Info: \pdf@primitive is available. +Package pdftexcmds Info: \pdf@ifprimitive is available. +))) +\Fld@menulength=\count115 +\Field@Width=\dimen150 +\Fld@charsize=\dimen151 +\Field@toks=\toks28 +Package hyperref Info: Hyper figures OFF on input line 4377. +Package hyperref Info: Link nesting OFF on input line 4382. +Package hyperref Info: Hyper index ON on input line 4385. +Package hyperref Info: backreferencing OFF on input line 4392. +Package hyperref Info: Link coloring ON on input line 4395. +Package hyperref Info: Link coloring with OCG OFF on input line 4402. +Package hyperref Info: PDF/A mode OFF on input line 4407. + +(/usr/share/texmf-texlive/tex/generic/oberdiek/atbegshi.sty +Package: atbegshi 2008/07/31 v1.9 At begin shipout hook (HO) +) +\Hy@abspage=\count116 +\c@Item=\count117 +) +*hyperref using default driver hpdftex* +(/usr/share/texmf-texlive/tex/latex/hyperref/hpdftex.def +File: hpdftex.def 2009/10/09 v6.79a Hyperref driver for pdfTeX +\Fld@listcount=\count118 +) (./specification.aux) +\openout1 = `specification.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 73. +LaTeX Font Info: ... okay on input line 73. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 73. +LaTeX Font Info: ... okay on input line 73. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 73. +LaTeX Font Info: ... okay on input line 73. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 73. +LaTeX Font Info: ... okay on input line 73. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 73. +LaTeX Font Info: ... okay on input line 73. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 73. +LaTeX Font Info: ... okay on input line 73. +LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 73. +LaTeX Font Info: ... okay on input line 73. +(/usr/share/texmf-texlive/tex/context/base/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count119 +\scratchdimen=\dimen152 +\scratchbox=\box30 +\nofMPsegments=\count120 +\nofMParguments=\count121 +\everyMPshowfont=\toks29 +\MPscratchCnt=\count122 +\MPscratchDim=\dimen153 +\MPnumerator=\count123 +\everyMPtoPDFconversion=\toks30 +) +Package hyperref Info: Link coloring ON on input line 73. + (/usr/share/texmf-texlive/tex/latex/hyperref/nameref.sty +Package: nameref 2007/05/29 v2.31 Cross-referencing by name of section + +(/usr/share/texmf-texlive/tex/latex/oberdiek/refcount.sty +Package: refcount 2008/08/11 v3.1 Data extraction from references (HO) +) +\c@section@level=\count124 +) +LaTeX Info: Redefining \ref on input line 73. +LaTeX Info: Redefining \pageref on input line 73. +\AtBeginShipoutBox=\box31 +LaTeX Font Info: Try loading font information for U+msa on input line 75. + +(/usr/share/texmf-texlive/tex/latex/amsfonts/umsa.fd +File: umsa.fd 2009/06/22 v3.00 AMS symbols A +) +LaTeX Font Info: Try loading font information for U+msb on input line 75. + +(/usr/share/texmf-texlive/tex/latex/amsfonts/umsb.fd +File: umsb.fd 2009/06/22 v3.00 AMS symbols B +) (./specification.toc) +\tf@toc=\write3 +\openout3 = `specification.toc'. + + +[1 + +{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2] (./specification.aux) +) +Here is how much of TeX's memory you used: + 6376 strings out of 495061 + 86385 string characters out of 1182621 + 158016 words of memory out of 3000000 + 9414 multiletter control sequences out of 15000+50000 + 11187 words of font info for 44 fonts, out of 3000000 for 9000 + 28 hyphenation exceptions out of 8191 + 38i,8n,34p,304b,311s stack positions out of 5000i,500n,10000p,200000b,50000s + +Output written on specification.pdf (2 pages, 60846 bytes). +PDF statistics: + 38 PDF objects out of 1000 (max. 8388607) + 5 named destinations out of 1000 (max. 500000) + 1 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/specification/latex/specification.pdf b/specification/latex/specification.pdf new file mode 100644 index 0000000..f0591a3 Binary files /dev/null and b/specification/latex/specification.pdf differ diff --git a/specification/latex/specification.tex b/specification/latex/specification.tex new file mode 100644 index 0000000..db261c7 --- /dev/null +++ b/specification/latex/specification.tex @@ -0,0 +1,103 @@ +% ** General Options *************************************************** + + \documentclass[10pt,a4paper]{article} + + % ** input encoding ** + \usepackage[utf8]{inputenc} % Linux / Windows + %\usepackage[applemac]{inputenc} % Mac + + % ** language ** + %\usepackage[french]{babel} % french + %\usepackage[french, english]{babel} % bilingual, french / english + \usepackage[english]{babel} % english + + % ** illustrations ** + \usepackage{graphicx} + \usepackage{subfigure} + + % ** tables ** + \usepackage{rotating} + \usepackage{ctable} + \usepackage{multirow} + \usepackage{makecell} + + % ** equations ** + \usepackage{amsmath,amssymb,amsfonts} + \newcommand{\be} {\begin{equation}} + \newcommand{\ee} {\end{equation}} + \newcommand{\ben} {\begin{equation*}} + \newcommand{\een} {\end{equation*}} + \newcommand{\st} {\ensuremath{\sigma}} + \newcommand{\dfm} {\ensuremath{\varepsilon}} + \newcommand{\delx} {\ensuremath{\Delta x}} + \newcommand{\dely} {\ensuremath{\Delta y}} + \newcommand{\delz} {\ensuremath{\Delta z}} + \renewcommand{\deg} {\ensuremath{^{\circ}}} + \providecommand{\abs}[1]{\ensuremath{\left|#1\right|}} + \providecommand{\re}[1]{\ensuremath{\frac{\Delta #1}{#1}}} + \providecommand{\norm}[1]{\ensuremath{\lVert#1\rVert}} + \renewcommand{\vec}[1]{\ensuremath{\boldsymbol{#1}}} + \providecommand{\unit}[1]{\ensuremath{\mathrm{#1}}} + \providecommand{\E}[1]{\ensuremath{\cdot 10^{#1}}} + \providecommand{\tp}[1]{\ensuremath{10^{#1}}} + \providecommand{\ddif}{\ensuremath{\mathrm{d}}} + + % ** links ** + \usepackage[colorlinks,bookmarks=false,linkcolor=blue,urlcolor=blue]{hyperref} + \newcommand{\mail}[1]{{\href{mailto:#1}{#1}}} + \newcommand{\ftplink}[1]{{\href{ftp://#1}{#1}}} + + + % ** comments ** + \newcommand{\comment}[1]{{}} % multi-line comment + + % ** layout ** + \setlength{\textheight}{235mm} + \setlength{\topmargin}{-1.2cm} + %\setlength{\footskip}{5mm} + \setlength{\textwidth}{15cm} + \setlength{\oddsidemargin}{0.56cm} + \setlength{\evensidemargin}{0.56cm} + +\newcommand{\iw}{7.3cm} + + +% ** Title, author ***************************************************** +\title{A Reactive Secure Serial Protocol} +\date{\today} +\author{Jakob Odersky\\{\small \mail{jodersky@gmail.com}}} + +\setcounter{tocdepth}{2} + +% ** Document ********************************************************** +\begin{document} + +\maketitle +\tableofcontents +\pagestyle{plain} +\newpage + +\begin{figure} +\begin{centering} + +\begin{tabular}{|c|c|c|c|}\hline +Header & Packet & Checksum & Trailer \\ \hline +0x02 & & & 0x03 +\end{tabular} + + + + +\end{centering} +\caption{A frame in RSSP} +\end{figure} + + + +% \newpage +% \appendix +% \input{appendix.tex} + +%\bibliographystyle{ieeetr} +%\bibliography{bibliography} +\end{document} diff --git a/specification/latex/specification.toc b/specification/latex/specification.toc new file mode 100644 index 0000000..556f38b --- /dev/null +++ b/specification/latex/specification.toc @@ -0,0 +1 @@ +\select@language {english} -- cgit v1.2.3