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