From e78ba71ac41ec3a2863bc3c729b56d3c10ce3993 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Tue, 5 May 2015 17:20:54 +0200
Subject: [PATCH] Add common avr stuff

---
 common/avr/Makefile.common |  88 ++++++++++++++++++
 common/avr/README          |  83 +++++++++++++++++
 common/avr/serialio.h      | 181 +++++++++++++++++++++++++++++++++++++
 3 files changed, 352 insertions(+)
 create mode 100644 common/avr/Makefile.common
 create mode 100644 common/avr/README
 create mode 100644 common/avr/serialio.h

diff --git a/common/avr/Makefile.common b/common/avr/Makefile.common
new file mode 100644
index 0000000..8cdb9da
--- /dev/null
+++ b/common/avr/Makefile.common
@@ -0,0 +1,88 @@
+#
+# Define the following in your makefile and then include this file
+#   TARGETS=<list of targets to be built>
+#
+#   <TARGET>.ARCH=<architecture for target (avr)>
+#   <TARGET>.CHIP=<chip used for target>
+#   <TARGET>.FUSE=<fuse settings for target>
+#   <TARGET>.C=<.c files for target>
+#   <TARGET>.H=<.h file for target>
+
+# Factory defaults for various chips
+# factory_mega16.FUSE=--wr_fuse_l=0xe1 --wr_fuse_h=0x99 --wr_fuse_e=0xff
+
+ifeq ($(TARGET),)
+
+all:	$(TARGETS:%=%.LINK)
+
+
+%.LINK:
+	@mkdir -p compiled/$*
+	make --no-print-directory TARGET=$* $*.LINK
+
+%.VERIFY: 
+	@mkdir -p compiled/$*
+	make --no-print-directory TARGET=$* $*.VERIFY
+
+%.LOAD: 
+	@mkdir -p compiled/$*
+	make --no-print-directory TARGET=$* $*.LOAD 
+
+%.FUSE:
+	make --no-print-directory TARGET=$* $*.FUSE
+
+
+
+else
+
+avr-CC=avr-gcc
+avr-CCFLAGS=-mmcu=$(CHIP) -g -Wall -Werror -O3 -I. -I../lib
+avr-OBJCOPY=avr-objcopy
+
+ARCH=$($(TARGET).ARCH)
+CHIP=$($(TARGET).CHIP)
+
+CC=$($(ARCH)-CC)
+CCFLAGS=$($(ARCH)-CCFLAGS) $($(TARGET).CCFLAGS)
+OBJCOPY=$($(ARCH)-OBJCOPY)
+
+SOURCES=$($(1).C:%=%.c) $($(1).H:%=%.h)
+OBJECTS=$($(1).C:%=compiled/$(1)/%.o) 
+
+
+%.LINK: compiled/$(TARGET)/%.exe
+	echo $@
+
+%.LOAD_uisp: compiled/$(TARGET)/%.sr
+	uisp \
+		-dprog=stk200 \
+		--erase \
+		--upload if=compiled/$(TARGET)/$*.sr
+
+%.VERIFY: compiled/$(TARGET)/%.sr
+	avrdude -P usb -c avrisp2 -p $(CHIP) \
+	        -U flash:v:compiled/$(TARGET)/$*.sr:s
+
+%.LOAD: compiled/$(TARGET)/%.sr
+	avrdude -P usb -c avrisp2 -p $(CHIP) \
+	        -U flash:w:compiled/$(TARGET)/$*.sr:s
+
+%.FUSE:
+	uisp \
+		-dprog=stk200 \
+		$($(TARGET).FUSE)
+
+compiled/$(TARGET)/%.o: $(call SOURCES,$(TARGET))
+	$(CC) $(CCFLAGS) -o $@ -c $*.c
+
+compiled/$(TARGET)/%.exe: $(call OBJECTS,$(TARGET))
+	$(CC) $(CCFLAGS) -o $@ $(call OBJECTS,$*)
+
+compiled/$(TARGET)/%.sr: compiled/$(TARGET)/%.exe
+	$(OBJCOPY) -O srec $< $@
+
+.PRECIOUS: compiled/$(TARGET)/%.o \
+	   compiled/$(TARGET)/%.exe \
+	   compiled/$(TARGET)/%.sr
+
+endif
\ No newline at end of file
diff --git a/common/avr/README b/common/avr/README
new file mode 100644
index 0000000..e89ca75
--- /dev/null
+++ b/common/avr/README
@@ -0,0 +1,83 @@
+Digital in/out and poll commands are sent as one byte:
+
+   +-+-+-+-+-+-+-+-+
+   |0|0 0|  chan   | Bit clear
+   +-+-+-+-+-+-+-+-+
+
+   +-+-+-+-+-+-+-+-+
+   |0|0 1|  chan   | Bit set
+   +-+-+-+-+-+-+-+-+
+
+   +-+-+-+-+-+-+-+-+
+   |0|1 0|  chan   | Bit get
+   +-+-+-+-+-+-+-+-+
+
+   +-+-+-+-+-+-+-+-+
+   |0|1 1|  chan   | Channel get
+   +-+-+-+-+-+-+-+-+
+
+
+Channels are sent as 2 to 6 bytes, depending on resolution:
+
+   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+2  |1| bit8...bit2 |  |0|bit|  chan   |
+   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+
+   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+3  |1|bit15...bit9 |  |1| bit8...bit2 |  |0|bit|  chan   |
+   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+
+   ...
+
+   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+ 
+6  |1|bit31...bit30|  |1|bit29...bit23| ... |0|bit|  chan   |
+   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+ 
+
+
+
+Channel 31 is special, as it serves as the configuration channel. When
+reading from it multiple responses are sent with the following layout
+
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ |           command specific data           |cmd|kind |conf chan|
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+
+  kind: 000 == end of configuration
+        001 == digital in
+        010 == digital out
+	011 == analog in
+	100 == analog out
+	101 == counter in
+
+cmd == 0 (Resolution)
+
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ |                               | # of bits |0 0|kind |conf chan|
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+
+  # of bits (1..32) 
+
+cmd == 1 (Minimum value)
+
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ |              minimum              |S| unit|0 1|kind |conf chan|
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ 
+  S (sign): 0 == +
+            1 == -
+  unit: 000 == V
+        001 == mV
+        010 == uV
+
+cmd == 2 (Maximum value)
+
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ |              maximum              |S| unit|1 0|kind |conf chan|
+ +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ 
+  S (sign): 0 == +
+            1 == -
+  unit: 000 == V
+        001 == mV
+        010 == uV
+
diff --git a/common/avr/serialio.h b/common/avr/serialio.h
new file mode 100644
index 0000000..0710dea
--- /dev/null
+++ b/common/avr/serialio.h
@@ -0,0 +1,181 @@
+/*
+ * Digital in/out and poll commands are sent as one byte:
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|0 0|  chan   | Bit clear
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|0 1|  chan   | Bit set
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|1 0|  chan   | Bit get
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *   +-+-+-+-+-+-+-+-+
+ *   |0|1 1|  chan   | Channel get
+ *   +-+-+-+-+-+-+-+-+
+ *
+ *
+ * Channels are sent as 2 to 6 bytes, depending on resolution:
+ *
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ * 2 |1| bit8...bit2 |  |0|bit|  chan   |
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ *
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ * 3 |1|bit15...bit9 |  |1| bit8...bit2 |  |0|bit|  chan   |
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+ 
+ *
+ *   ...
+ *
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+ 
+ * 6 |1|bit31...bit30|  |1|bit29...bit23| ... |0|bit|  chan   |
+ *   +-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+ 
+ *
+ *
+ *
+ * Channel 31 is special, as it serves as the configuration channel. When
+ * reading from it multiple responses are sent with the following layout
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |           command specific data           |cmd|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ *
+ *  kind: 000 == end of configuration
+ *        001 == digital in
+ *        010 == digital out
+ *        011 == analog in
+ *        100 == analog out
+ *        101 == counter in
+ *
+ *cmd == 0 (Resolution)
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |                               | # of bits |0 0|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ *
+ *  # of bits (1..32) 
+ *
+ *cmd == 1 (Minimum value)
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |              minimum              |S| unit|0 1|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * 
+ *  S (sign): 0 == +
+ *            1 == -
+ *  unit: 000 == V
+ *        001 == mV
+ *        010 == uV
+ *        100 == A
+ *
+ *cmd == 2 (Maximum value)
+ *
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * |              maximum              |S| unit|1 0|kind |conf chan|
+ * +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+
+ * 
+ *  S (sign): 0 == +
+ *            1 == -
+ *  unit: 000 == V
+ *        001 == mV
+ *        010 == uV
+ *        100 == A
+ */
+
+static volatile unsigned long serialio_value;
+static volatile unsigned char serialio_channel, serialio_length;
+
+static void serialio_putchar(unsigned char ch) 
+{
+  
+  while ((in(UCSRA) & 0x20) == 0) {};
+  out(UDR, ch);
+}
+
+static void serialio_putbit(unsigned char channel, unsigned char value) 
+{
+  if (value) {
+    serialio_putchar(0x20 | (channel & 0x1f));
+  } else {
+    serialio_putchar(0x00 | (channel & 0x1f));
+  }
+}
+
+static void serialio_putchannel(unsigned char channel, unsigned long value) 
+{
+  if (value >= (1L<<30)) { serialio_putchar(0x80 | ((value >> 30) & 0x03)); }
+  if (value >= (1L<<23)) { serialio_putchar(0x80 | ((value >> 23) & 0x7f)); }
+  if (value >= (1L<<16)) { serialio_putchar(0x80 | ((value >> 16) & 0x7f)); }
+  if (value >= (1L<< 9)) { serialio_putchar(0x80 | ((value >> 9) & 0x7f)); }
+  serialio_putchar(0x80 | ((value >> 2) & 0x7f));
+  serialio_putchar(((value << 5) & 0x60) | (channel & 0x1f));
+}
+
+
+#define CONF_DIG_IN(channel) (0x20 | (channel)&0x1f)
+#define CONF_DIG_OUT(channel) (0x40 | (channel)&0x1f)
+
+#define CONF_END() serialio_putchannel(31, 0)
+#define CONF_DIGITAL_IN(chan, config) \
+  serialio_putchannel(31, (0x20|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_DIGITAL_OUT(chan, config) \
+  serialio_putchannel(31, (0x40|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_ANALOG_IN(chan, config) \
+  serialio_putchannel(31, (0x60|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_ANALOG_OUT(chan, config) \
+  serialio_putchannel(31, (0x80|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_ENCODER_IN(chan, config) \
+  serialio_putchannel(31, (0xa0|(chan&0x1f)|(config&0xffffff00)))
+#define CONF_RESOLUTION(bits) (((bits)<<10)|0x000)
+#define CONF_MIN(value) ((value)|0x100)
+#define CONF_MAX(value) ((value)|0x200)
+#define CONF_NEGATIVE_VOLT(volt) (((long)(volt)<<14)|0x2000)
+#define CONF_POSITIVE_VOLT(volt) ((long)(volt)<<14)
+#define CONF_NEGATIVE_MILLIVOLT(millivolt) (((long)(millivolt)<<14)|0x2400)
+#define CONF_POSITIVE_MILLIVOLT(millivolt) ((long)(millivolt)<<14|0x400)
+#define CONF_POSITIVE_AMPERE(ampere) (((long)(ampere)<<14)|0x1000)
+
+static void serialio_init() 
+{
+  serialio_value = 0;
+  serialio_channel = 255;
+  serialio_length = 0;
+}
+
+typedef enum { 
+  serialio_error, serialio_more, serialio_clearbit, serialio_setbit, 
+  serialio_setchannel, serialio_pollbit, serialio_pollchannel 
+} serialio_rxc_status;
+
+
+static serialio_rxc_status serialio_RXC(unsigned char ch) {
+  unsigned char result = serialio_error;
+
+  if (serialio_length == 0) { serialio_value = 0; }
+  serialio_length++;
+  if ((ch & 0x80) == 0x80) {
+    // Collect yet another byte for later processing
+    serialio_value = (serialio_value << 7) | (ch & 0x7f);
+    result = serialio_more;
+  } else {
+    serialio_value = (serialio_value << 2) | ((ch & 0x60) >> 5);
+    serialio_channel = ch & 0x1f;
+    if (serialio_length == 1) {
+      switch (serialio_value & 0x03) {
+	// Digital output buffer (ULN2803A) is inverting
+	case 0: { result = serialio_clearbit; } break;
+	case 1: { result = serialio_setbit; } break;
+	case 2: { result = serialio_pollbit; } break;
+	case 3: { result = serialio_pollchannel; } break;
+      }
+    } else {
+      result = serialio_setchannel;
+    }
+    serialio_length = 0;
+  }
+  return result;
+}
+
-- 
GitLab