Commit e78ba71a authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Add common avr stuff

parent 8dffe83f
#
# 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
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
/*
* 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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment