diff --git a/Makefile b/Makefile deleted file mode 100644 index 66571b377d2edf30c19b0635609cbaef70d00d07..0000000000000000000000000000000000000000 --- a/Makefile +++ /dev/null @@ -1,81 +0,0 @@ -PROJECT=bioloid_exp -######################################################## -# afegir tots els fitxers que s'han de compilar aquà -######################################################## -SOURCES=src/main.c src/dyn_slave_se.c src/dyn_slave_diff.c src/mem.c src/dyn_common.c src/ports.c src/adc.c src/i2c.c src/compass.c - -timer1_use=uart_usb#possible values are dac or uart_usb -timer3_use=uart_ttl#possible values are pwm or uart_ttl - -defines= - -ifeq ($(timer1_use),dac) - SOURCES+=src/dac.c - defines+=-D_DAC -else - SOURCES+=src/uart_usb.c - defines+=-D_UART_USB -endif - -ifeq ($(timer3_use),pwm) - SOURCES+=src/pwm.c - defines+=-D_PWM -else - SOURCES+=src/uart_ttl.c - defines+=-D_UART_TTL -endif - -OBJS=$(SOURCES:.c=.o) -SRC_DIR=./src/ -INCLUDE_DIR=./include/ -BUILD_DIR=./build/ -BIN_DIR=./bin/ -CC=avr-gcc -OBJCOPY=avr-objcopy -MMCU=atmega128 - -CFLAGS=-mmcu=$(MMCU) -Wall -Os $(defines) -DF_CPU=16000000UL -gdwarf-2 -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wstrict-prototypes - -LDFLAGS=-mmcu=$(MMCU) -Wl,-Map=$(PROJECT).map -DF_CPU=16000000UL -#LDFLAGS=-mmcu=$(MMCU) -Wl,-Map=$(PROJECT).map,--section-start,.eeprom=810000 -DF_CPU=16000000UL - -HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature -HEX_EEPROM_FLAGS = -j .eeprom --change-section-lma .eeprom=0 - -.PHONY: all - -all: $(PROJECT).hex $(PROJECT)_eeprom.hex - -$(PROJECT).hex: $(PROJECT).elf - $(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@ -$(PROJECT)_eeprom.hex: $(PROJECT).elf - $(OBJCOPY) -O ihex $(HEX_EEPROM_FLAGS) $< $@ -$(PROJECT).elf: $(OBJS) - $(CC) $(LDFLAGS) $(OBJS) $(LIB_DIRS) $(LIBS) -o $(PROJECT).elf -%.o:%.c - $(CC) -c $(CFLAGS) -I$(INCLUDE_DIR) -o $@ $< - -download: $(MAIN_OUT_HEX) - avrdude -c avr109 -P /dev/ttyUSB0 -b 19200 -p m128 -U flash:w:$(PROJECT).hex - avrdude -c avr109 -P /dev/ttyUSB0 -b 19200 -p m128 -U eeprom:w:$(PROJECT)_eeprom.hex - -bootloader: bootloader_hex - -$(MAKE) -C remote-controlled-socket/uc/avrprog_boot_v0_85/ program - -bootloader_hex: - @if [ ! -d "./remote-controlled-socket" ] ; then \ - echo "AVR bootloader not found"; \ - hg clone https://bitbucket.org/befi/remote-controlled-socket; \ - patch remote-controlled-socket/uc/avrprog_boot_v0_85/main.c < patches/main.c.patch; \ - patch remote-controlled-socket/uc/avrprog_boot_v0_85/makefile < patches/makefile.patch; \ - patch remote-controlled-socket/uc/avrprog_boot_v0_85/chipdef.h < patches/chipdef.h.patch; \ - cp patches/uart_usb.c remote-controlled-socket/uc/avrprog_boot_v0_85/; \ - fi - $(MAKE) -C remote-controlled-socket/uc/avrprog_boot_v0_85/ - -clean: - -rm $(PROJECT).* - -rm $(PROJECT)_eeprom.* - -rm $(OBJS) - -rm src/*.lst - -rm -rf remote-controlled-socket diff --git a/README b/README new file mode 100755 index 0000000000000000000000000000000000000000..fb24089f480a340b207fd7e239a643c3ccaf6260 --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +Biloid expansion board + by Sergi Hernandez Juan + +http://apollo.upc.es/humanoide/trac/wiki/BioloidPremiumSensorExtensionBoard + +The Humanoid Lab <humanoide@iri.upc.edu> diff --git a/a2d.c b/a2d.c new file mode 100755 index 0000000000000000000000000000000000000000..610228877a69765499fee257f8c22d6e308793d3 --- /dev/null +++ b/a2d.c @@ -0,0 +1,188 @@ +/*! \file a2d.c \brief Analog-to-Digital converter function library. */ +//***************************************************************************** +// +// File Name : 'a2d.c' +// Title : Analog-to-digital converter functions +// Author : Pascal Stang - Copyright (C) 2002 +// Created : 2002-04-08 +// Revised : 2002-09-30 +// Version : 1.1 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "global.h" +#include "a2d.h" + +// global variables + +// number of channels to convert +#define NUM_CH 8 + +// number of samples to average +#define NUM_SAMPLES 16 + +// current channel +volatile unsigned char current_ch; +// list of channels to convert +const unsigned char list_ch[NUM_CH]={0,1,2,3,4,5,6,7}; +// channel data +volatile short int adc_data[NUM_CH]; +// averaged channel data +volatile short int ch1_data[NUM_SAMPLES]; +volatile short int ch2_data[NUM_SAMPLES]; +volatile short int ch3_data[NUM_SAMPLES]; +volatile short int ch4_data[NUM_SAMPLES]; +volatile short int ch5_data[NUM_SAMPLES]; +volatile short int ch6_data[NUM_SAMPLES]; +volatile short int ch7_data[NUM_SAMPLES]; +volatile short int ch8_data[NUM_SAMPLES]; +volatile unsigned char current_sample; + +// functions + +// initialize a2d converter +void a2dInit(void) +{ + // configure the analog inputs + DDRF = 0x00; + PORTF = 0x00; + + sbi(ADCSR, ADEN); // enable ADC (turn on ADC power) + cbi(ADCSR, ADFR); // default to single sample convert mode + a2dSetPrescaler(ADC_PRESCALE); // set default prescaler + a2dSetReference(ADC_REFERENCE); // set default reference + cbi(ADMUX, ADLAR); // set to right-adjusted result + + // set the initial channel to convert + current_ch=0; + current_sample=0; + a2dSetChannel(list_ch[current_ch]); + + // start conversion + a2dStartConvert(); + + sbi(ADCSR, ADIE); // enable ADC interrupts +} + +// turn off a2d converter +void a2dOff(void) +{ + cbi(ADCSR, ADIE); // disable ADC interrupts + cbi(ADCSR, ADEN); // disable ADC (turn off ADC power) +} + +// configure A2D converter clock division (prescaling) +void a2dSetPrescaler(unsigned char prescale) +{ + outb(ADCSR, ((inb(ADCSR) & ~ADC_PRESCALE_MASK) | prescale)); +} + +// configure A2D converter voltage reference +void a2dSetReference(unsigned char ref) +{ + outb(ADMUX, ((inb(ADMUX) & ~ADC_REFERENCE_MASK) | (ref<<6))); +} + +// sets the a2d input channel +void a2dSetChannel(unsigned char ch) +{ + outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel +} + +// start a conversion on the current a2d input channel +void a2dStartConvert(void) +{ + sbi(ADCSR, ADIF); // clear hardware "conversion complete" flag + sbi(ADCSR, ADSC); // start conversion +} + +// return TRUE if conversion is complete +u08 a2dIsComplete(void) +{ + return bit_is_set(ADCSR, ADSC); +} + +//! Interrupt handler for ADC complete interrupt. +SIGNAL(ADC_vect) +{ + short int data; + + // save data + data=(inb(ADCL) | (inb(ADCH)<<8)); + adc_data[current_ch]=data; + switch(current_ch) + { + case 0: ch1_data[current_sample]=data; + break; + case 1: ch2_data[current_sample]=data; + break; + case 2: ch3_data[current_sample]=data; + break; + case 3: ch4_data[current_sample]=data; + break; + case 4: ch5_data[current_sample]=data; + break; + case 5: ch6_data[current_sample]=data; + break; + case 6: ch7_data[current_sample]=data; + break; + case 7: ch8_data[current_sample]=data; + break; + } + // prepare for next channel + if(current_ch==(NUM_CH-1)) + current_sample=(current_sample+1)%NUM_SAMPLES; + current_ch=(current_ch+1)%NUM_CH; + a2dSetChannel(list_ch[current_ch]); + a2dStartConvert(); +} + +unsigned short int adc_get_channel(unsigned char ch_id) +{ + if(ch_id>=0 && ch_id<=7) + return adc_data[ch_id]; + else + return 0xFFFF; +} + +unsigned short int adc_get_averaged_channel(unsigned char ch_id) +{ + short int *data_pointer; + short int average=0; + unsigned char i; + + switch(ch_id) + { + case 0: data_pointer=ch1_data; + break; + case 1: data_pointer=ch2_data; + break; + case 2: data_pointer=ch3_data; + break; + case 3: data_pointer=ch4_data; + break; + case 4: data_pointer=ch5_data; + break; + case 5: data_pointer=ch6_data; + break; + case 6: data_pointer=ch7_data; + break; + case 7: data_pointer=ch8_data; + break; + default: return 0xFFFF; + break; + } + for(i=0;i<NUM_SAMPLES;i++) + average=average+data_pointer[i]; + average=average/NUM_SAMPLES; + + return average; +} diff --git a/a2d.h b/a2d.h new file mode 100755 index 0000000000000000000000000000000000000000..076a6545b542e6b52c2de1f2055f2d1817572c64 --- /dev/null +++ b/a2d.h @@ -0,0 +1,147 @@ +/*! \file a2d.h \brief Analog-to-Digital converter function library. */ +//***************************************************************************** +// +// File Name : 'a2d.h' +// Title : Analog-to-digital converter functions +// Author : Pascal Stang - Copyright (C) 2002 +// Created : 4/08/2002 +// Revised : 4/30/2002 +// Version : 1.1 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +/// \ingroup driver_avr +/// \defgroup a2d A/D Converter Function Library (a2d.c) +/// \code #include "a2d.h" \endcode +/// \par Overview +/// This library provides an easy interface to the analog-to-digital +/// converter available on many AVR processors. Updated to support +/// the ATmega128. +// +//**************************************************************************** +//@{ + +#ifndef A2D_H +#define A2D_H + +// defines + +// A2D clock prescaler select +// *selects how much the CPU clock frequency is divided +// to create the A2D clock frequency +// *lower division ratios make conversion go faster +// *higher division ratios make conversions more accurate +#define ADC_PRESCALE_DIV2 0x00 ///< 0x01,0x00 -> CPU clk/2 +#define ADC_PRESCALE_DIV4 0x02 ///< 0x02 -> CPU clk/4 +#define ADC_PRESCALE_DIV8 0x03 ///< 0x03 -> CPU clk/8 +#define ADC_PRESCALE_DIV16 0x04 ///< 0x04 -> CPU clk/16 +#define ADC_PRESCALE_DIV32 0x05 ///< 0x05 -> CPU clk/32 +#define ADC_PRESCALE_DIV64 0x06 ///< 0x06 -> CPU clk/64 +#define ADC_PRESCALE_DIV128 0x07 ///< 0x07 -> CPU clk/128 +// default value +#define ADC_PRESCALE ADC_PRESCALE_DIV64 +// do not change the mask value +#define ADC_PRESCALE_MASK 0x07 + +// A2D voltage reference select +// *this determines what is used as the +// full-scale voltage point for A2D conversions +#define ADC_REFERENCE_AREF 0x00 ///< 0x00 -> AREF pin, internal VREF turned off +#define ADC_REFERENCE_AVCC 0x01 ///< 0x01 -> AVCC pin, internal VREF turned off +#define ADC_REFERENCE_RSVD 0x02 ///< 0x02 -> Reserved +#define ADC_REFERENCE_256V 0x03 ///< 0x03 -> Internal 2.56V VREF +// default value +#define ADC_REFERENCE ADC_REFERENCE_AVCC +// do not change the mask value +#define ADC_REFERENCE_MASK 0xC0 + +// bit mask for A2D channel multiplexer +#define ADC_MUX_MASK 0x1F + +// channel defines (for reference and use in code) +// these channels supported by all AVRs with A2D +#define ADC_CH_ADC0 0x00 +#define ADC_CH_ADC1 0x01 +#define ADC_CH_ADC2 0x02 +#define ADC_CH_ADC3 0x03 +#define ADC_CH_ADC4 0x04 +#define ADC_CH_ADC5 0x05 +#define ADC_CH_ADC6 0x06 +#define ADC_CH_ADC7 0x07 +#define ADC_CH_122V 0x1E ///< 1.22V voltage reference +#define ADC_CH_AGND 0x1F ///< AGND +// these channels supported only in ATmega128 +// differential with gain +#define ADC_CH_0_0_DIFF10X 0x08 +#define ADC_CH_1_0_DIFF10X 0x09 +#define ADC_CH_0_0_DIFF200X 0x0A +#define ADC_CH_1_0_DIFF200X 0x0B +#define ADC_CH_2_2_DIFF10X 0x0C +#define ADC_CH_3_2_DIFF10X 0x0D +#define ADC_CH_2_2_DIFF200X 0x0E +#define ADC_CH_3_2_DIFF200X 0x0F +// differential +#define ADC_CH_0_1_DIFF1X 0x10 +#define ADC_CH_1_1_DIFF1X 0x11 +#define ADC_CH_2_1_DIFF1X 0x12 +#define ADC_CH_3_1_DIFF1X 0x13 +#define ADC_CH_4_1_DIFF1X 0x14 +#define ADC_CH_5_1_DIFF1X 0x15 +#define ADC_CH_6_1_DIFF1X 0x16 +#define ADC_CH_7_1_DIFF1X 0x17 + +#define ADC_CH_0_2_DIFF1X 0x18 +#define ADC_CH_1_2_DIFF1X 0x19 +#define ADC_CH_2_2_DIFF1X 0x1A +#define ADC_CH_3_2_DIFF1X 0x1B +#define ADC_CH_4_2_DIFF1X 0x1C +#define ADC_CH_5_2_DIFF1X 0x1D + +// compatibility for new Mega processors +// ADCSR hack apparently no longer necessary in new AVR-GCC +#ifdef ADCSRA +#ifndef ADCSR + #define ADCSR ADCSRA +#endif +#endif +#ifdef ADATE + #define ADFR ADATE +#endif + +// function prototypes + +//! Initializes the A/D converter. +/// Turns ADC on and prepares it for use. +void a2dInit(void); + +//! Turn off A/D converter +void a2dOff(void); + +//! Sets the division ratio of the A/D converter clock. +/// This function is automatically called from a2dInit() +/// with a default value. +void a2dSetPrescaler(unsigned char prescale); + +//! Configures which voltage reference the A/D converter uses. +/// This function is automatically called from a2dInit() +/// with a default value. +void a2dSetReference(unsigned char ref); + +//! sets the a2d input channel +void a2dSetChannel(unsigned char ch); + +//! start a conversion on the current a2d input channel +void a2dStartConvert(void); + +//! return TRUE if conversion is complete +u08 a2dIsComplete(void); + +unsigned short int adc_get_channel(unsigned char ch_id); + +unsigned short int adc_get_averaged_channel(unsigned char ch_id); + +#endif +//@} diff --git a/avrlibdefs.h b/avrlibdefs.h new file mode 100755 index 0000000000000000000000000000000000000000..a8dea50342b2dd159ebb5035ae658f9b79816c97 --- /dev/null +++ b/avrlibdefs.h @@ -0,0 +1,83 @@ +/*! \file avrlibdefs.h \brief AVRlib global defines and macros. */ +//***************************************************************************** +// +// File Name : 'avrlibdefs.h' +// Title : AVRlib global defines and macros include file +// Author : Pascal Stang +// Created : 7/12/2001 +// Revised : 9/30/2002 +// Version : 1.1 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// Description : This include file is designed to contain items useful to all +// code files and projects, regardless of specific implementation. +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + + +#ifndef AVRLIBDEFS_H +#define AVRLIBDEFS_H + +// Code compatibility to new AVR-libc +// outb(), inb(), inw(), outw(), BV(), sbi(), cbi(), sei(), cli() +#ifndef outb + #define outb(addr, data) addr = (data) +#endif +#ifndef inb + #define inb(addr) (addr) +#endif +#ifndef outw + #define outw(addr, data) addr = (data) +#endif +#ifndef inw + #define inw(addr) (addr) +#endif +#ifndef BV + #define BV(bit) (1<<(bit)) +#endif +#ifndef cbi + #define cbi(reg,bit) reg &= ~(BV(bit)) +#endif +#ifndef sbi + #define sbi(reg,bit) reg |= (BV(bit)) +#endif +#ifndef cli + #define cli() __asm__ __volatile__ ("cli" ::) +#endif +#ifndef sei + #define sei() __asm__ __volatile__ ("sei" ::) +#endif + +// support for individual port pin naming in the mega128 +// see port128.h for details +#ifdef __AVR_ATmega128__ +// not currently necessary due to inclusion +// of these defines in newest AVR-GCC +// do a quick test to see if include is needed +#ifndef PD0 + #include "port128.h" +#endif +#endif + +// use this for packed structures +// (this is seldom necessary on an 8-bit architecture like AVR, +// but can assist in code portability to AVR) +#define GNUC_PACKED __attribute__((packed)) + +// port address helpers +#define DDR(x) ((x)-1) // address of data direction register of port x +#define PIN(x) ((x)-2) // address of input register of port x + +// MIN/MAX/ABS macros +#define MIN(a,b) ((a<b)?(a):(b)) +#define MAX(a,b) ((a>b)?(a):(b)) +#define ABS(x) ((x>0)?(x):(-x)) + +// constants +#define PI 3.14159265359 + +#endif diff --git a/avrlibtypes.h b/avrlibtypes.h new file mode 100755 index 0000000000000000000000000000000000000000..4d44ac56223bd8fb421a64ef3cab79779c376b7d --- /dev/null +++ b/avrlibtypes.h @@ -0,0 +1,84 @@ +/*! \file avrlibtypes.h \brief AVRlib global types and typedefines. */ +//***************************************************************************** +// +// File Name : 'avrlibtypes.h' +// Title : AVRlib global types and typedefines include file +// Author : Pascal Stang +// Created : 7/12/2001 +// Revised : 9/30/2002 +// Version : 1.0 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// Description : Type-defines required and used by AVRlib. Most types are also +// generally useful. +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + + +#ifndef AVRLIBTYPES_H +#define AVRLIBTYPES_H + +#ifndef WIN32 + // true/false defines + #define FALSE 0 + #define TRUE -1 +#endif + +// datatype definitions macros +typedef unsigned char u08; +typedef signed char s08; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned long u32; +typedef signed long s32; +typedef unsigned long long u64; +typedef signed long long s64; + +/* use inttypes.h instead +// C99 standard integer type definitions +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned long uint32_t; +typedef signed long int32_t; +typedef unsigned long uint64_t; +typedef signed long int64_t; +*/ +// maximum value that can be held +// by unsigned data types (8,16,32bits) +#define MAX_U08 255 +#define MAX_U16 65535 +#define MAX_U32 4294967295 + +// maximum values that can be held +// by signed data types (8,16,32bits) +#define MIN_S08 -128 +#define MAX_S08 127 +#define MIN_S16 -32768 +#define MAX_S16 32767 +#define MIN_S32 -2147483648 +#define MAX_S32 2147483647 + +#ifndef WIN32 + // more type redefinitions + typedef unsigned char BOOL; + typedef unsigned char BYTE; + typedef unsigned int WORD; + typedef unsigned long DWORD; + + typedef unsigned char UCHAR; + typedef unsigned int UINT; + typedef unsigned short USHORT; + typedef unsigned long ULONG; + + typedef char CHAR; + typedef int INT; + typedef long LONG; +#endif + +#endif diff --git a/buffer.c b/buffer.c new file mode 100755 index 0000000000000000000000000000000000000000..304221f39baa32bd9dd2fb4e00167a3e8a27ca6d --- /dev/null +++ b/buffer.c @@ -0,0 +1,163 @@ +/*! \file buffer.c \brief Multipurpose byte buffer structure and methods. */ +//***************************************************************************** +// +// File Name : 'buffer.c' +// Title : Multipurpose byte buffer structure and methods +// Author : Pascal Stang - Copyright (C) 2001-2002 +// Created : 9/23/2001 +// Revised : 9/23/2001 +// Version : 1.0 +// Target MCU : any +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#include "buffer.h" +#include "global.h" +#include "avr/io.h" + +#ifndef CRITICAL_SECTION_START +#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli() +#define CRITICAL_SECTION_END SREG = _sreg +#endif + +// global variables + +// initialization + +void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size) +{ + // begin critical section + CRITICAL_SECTION_START; + // set start pointer of the buffer + buffer->dataptr = start; + buffer->size = size; + // initialize index and length + buffer->dataindex = 0; + buffer->datalength = 0; + // end critical section + CRITICAL_SECTION_END; +} + +// access routines +unsigned char bufferGetFromFront(cBuffer* buffer) +{ + unsigned char data = 0; + // begin critical section + CRITICAL_SECTION_START; + // check to see if there's data in the buffer + if(buffer->datalength) + { + // get the first character from buffer + data = buffer->dataptr[buffer->dataindex]; + // move index down and decrement length + buffer->dataindex++; + if(buffer->dataindex >= buffer->size) + { + buffer->dataindex -= buffer->size; + } + buffer->datalength--; + } + // end critical section + CRITICAL_SECTION_END; + // return + return data; +} + +void bufferDumpFromFront(cBuffer* buffer, unsigned short numbytes) +{ + // begin critical section + CRITICAL_SECTION_START; + // dump numbytes from the front of the buffer + // are we dumping less than the entire buffer? + if(numbytes < buffer->datalength) + { + // move index down by numbytes and decrement length by numbytes + buffer->dataindex += numbytes; + if(buffer->dataindex >= buffer->size) + { + buffer->dataindex -= buffer->size; + } + buffer->datalength -= numbytes; + } + else + { + // flush the whole buffer + buffer->datalength = 0; + } + // end critical section + CRITICAL_SECTION_END; +} + +unsigned char bufferGetAtIndex(cBuffer* buffer, unsigned short index) +{ + // begin critical section + CRITICAL_SECTION_START; + // return character at index in buffer + unsigned char data = buffer->dataptr[(buffer->dataindex+index)%(buffer->size)]; + // end critical section + CRITICAL_SECTION_END; + return data; +} + +unsigned char bufferAddToEnd(cBuffer* buffer, unsigned char data) +{ + // begin critical section + CRITICAL_SECTION_START; + // make sure the buffer has room + if(buffer->datalength < buffer->size) + { + // save data byte at end of buffer + buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = data; + // increment the length + buffer->datalength++; + // end critical section + CRITICAL_SECTION_END; + // return success + return -1; + } + // end critical section + CRITICAL_SECTION_END; + // return failure + return 0; +} + +unsigned short bufferIsNotFull(cBuffer* buffer) +{ + // begin critical section + CRITICAL_SECTION_START; + // check to see if the buffer has room + // return true if there is room + unsigned short bytesleft = (buffer->size - buffer->datalength); + // end critical section + CRITICAL_SECTION_END; + return bytesleft; +} + +unsigned short bufferIsEmpty(cBuffer *buffer) +{ + // begin critical section + CRITICAL_SECTION_START; + // check to see if the buffer has room + // return true if there is room + unsigned short bytes = buffer->datalength; + // end critical section + CRITICAL_SECTION_END; + if(bytes==0) return TRUE; + else return FALSE; + +} + +void bufferFlush(cBuffer* buffer) +{ + // begin critical section + CRITICAL_SECTION_START; + // flush contents of the buffer + buffer->datalength = 0; + // end critical section + CRITICAL_SECTION_END; +} + diff --git a/buffer.h b/buffer.h new file mode 100755 index 0000000000000000000000000000000000000000..40b35d1fa9ea256d1cd7c8eef855d39264948908 --- /dev/null +++ b/buffer.h @@ -0,0 +1,76 @@ +/*! \file buffer.h \brief Multipurpose byte buffer structure and methods. */ +//***************************************************************************** +// +// File Name : 'buffer.h' +// Title : Multipurpose byte buffer structure and methods +// Author : Pascal Stang - Copyright (C) 2001-2002 +// Created : 9/23/2001 +// Revised : 11/16/2002 +// Version : 1.1 +// Target MCU : any +// Editor Tabs : 4 +// +/// \ingroup general +/// \defgroup buffer Circular Byte-Buffer Structure and Function Library (buffer.c) +/// \code #include "buffer.h" \endcode +/// \par Overview +/// This byte-buffer structure provides an easy and efficient way to store +/// and process a stream of bytes. You can create as many buffers as you +/// like (within memory limits), and then use this common set of functions to +/// access each buffer. The buffers are designed for FIFO operation (first +/// in, first out). This means that the first byte you put in the buffer +/// will be the first one you get when you read out the buffer. Supported +/// functions include buffer initialize, get byte from front of buffer, add +/// byte to end of buffer, check if buffer is full, and flush buffer. The +/// buffer uses a circular design so no copying of data is ever necessary. +/// This buffer is not dynamically allocated, it has a user-defined fixed +/// maximum size. This buffer is used in many places in the avrlib code. +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** +//@{ + +#ifndef BUFFER_H +#define BUFFER_H + +// structure/typdefs + +//! cBuffer structure +typedef struct struct_cBuffer +{ + unsigned char *dataptr; ///< the physical memory address where the buffer is stored + unsigned short size; ///< the allocated size of the buffer + unsigned short datalength; ///< the length of the data currently in the buffer + unsigned short dataindex; ///< the index into the buffer where the data starts +} cBuffer; + +// function prototypes + +//! initialize a buffer to start at a given address and have given size +void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size); + +//! get the first byte from the front of the buffer +unsigned char bufferGetFromFront(cBuffer* buffer); + +//! dump (discard) the first numbytes from the front of the buffer +void bufferDumpFromFront(cBuffer* buffer, unsigned short numbytes); + +//! get a byte at the specified index in the buffer (kind of like array access) +// ** note: this does not remove the byte that was read from the buffer +unsigned char bufferGetAtIndex(cBuffer* buffer, unsigned short index); + +//! add a byte to the end of the buffer +unsigned char bufferAddToEnd(cBuffer* buffer, unsigned char data); + +//! check if the buffer is full/not full (returns zero value if full) +unsigned short bufferIsNotFull(cBuffer* buffer); + +//! flush (clear) the contents of the buffer +void bufferFlush(cBuffer* buffer); + +unsigned short bufferIsEmpty(cBuffer *buffer); + +#endif +//@} diff --git a/compass.c b/compass.c new file mode 100755 index 0000000000000000000000000000000000000000..973d8d50e5430c69e358ae9e1db19c49ef1793f1 --- /dev/null +++ b/compass.c @@ -0,0 +1,136 @@ +#include "compass.h" +#include "avr/io.h" +#include "i2c.h" + +volatile unsigned short int compass_heading; +volatile unsigned short int compass_heading_averaged; +volatile unsigned char waiting_data; + +void CompassInit(void) +{ + unsigned char cmd=COMPASS_HEADING; + + calibrate=FALSE; + calibrating=FALSE; + compass_heading=0; + compass_heading_averaged=0; + // the I2C peripheral must be initialized before calling this function + i2cMasterSend(COMPASS_ADDR, 1, &cmd); + waiting_data=FALSE; +} + +void compass_avrg(unsigned short int heading) +{ + static unsigned long int new_average,first_value; + static unsigned char num_data=0; + unsigned long int diff=0; + + if(num_data==0) + { + num_data=num_data+1; + first_value=(long int)heading; + } + else + { + diff=heading+3600-first_value; + if(diff<1800) + diff=diff+3600; + else if(diff>5400) + diff=diff-3600; + new_average=new_average+diff; + num_data=num_data+1; + if(num_data==17) + { + new_average=new_average/16; + new_average=new_average+first_value; + compass_heading_averaged=(unsigned short int)new_average; + if(compass_heading_averaged>3600) + compass_heading_averaged=compass_heading_averaged-3600; + new_average=0; + num_data=0; + } + } +} + +void compass_periodic_call(void) +{ + unsigned char cmd,heading[2]; + static int count=0; + + if(i2cGetState()==I2C_IDLE) + { + if(waiting_data) + { + if(calibrate) + { + calibrating=TRUE; + calibrate=FALSE; + count=100; + } + else if(calibrating) + { + if(count>0) + count--; + else + { + cmd=COMPASS_START_CAL; + i2cMasterSend(COMPASS_ADDR, 1, &cmd); + waiting_data=FALSE; + } + } + else + { + if(count>0) + count--; + else + { + i2c_get_data(2,heading); + compass_heading=heading[1]+(heading[0]<<8); + compass_avrg(compass_heading); + cmd=COMPASS_HEADING; + i2cMasterSend(COMPASS_ADDR, 1, &cmd); + waiting_data=FALSE; + count = 10; + } + } + } + else + { + if(calibrating) + { + count++; + if(count==30000) + { + cmd=COMPASS_STOP_CAL; + i2cMasterSend(COMPASS_ADDR, 1, &cmd); + waiting_data=TRUE; + calibrate=FALSE; + calibrating=FALSE; + count = 100; + } + } + else + { + if(count>0) + count--; + else + { + i2cMasterReceive(COMPASS_ADDR,2); + waiting_data=TRUE; + } + } + } + } +} + +unsigned short int compass_get_heading(void) +{ + return compass_heading; +} + +unsigned short int compass_get_averaged_heading(void) +{ + return compass_heading_averaged; +} + + diff --git a/compass.h b/compass.h new file mode 100755 index 0000000000000000000000000000000000000000..85a28567e1bfd526a379aecfe20e3281232adf65 --- /dev/null +++ b/compass.h @@ -0,0 +1,20 @@ +#ifndef _COMPASS_H +#define _COMPASS_H + +// compass address +#define COMPASS_ADDR 0x42 + +// compass commands +#define COMPASS_HEADING 0x41 +#define COMPASS_START_CAL 0x43 +#define COMPASS_STOP_CAL 0x45 + +volatile unsigned char calibrate; +volatile unsigned char calibrating; + +void CompassInit(void); +void compass_periodic_call(void); +unsigned short int compass_get_heading(void); +unsigned short int compass_get_averaged_heading(void); + +#endif diff --git a/default/Makefile b/default/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..ab0cc842eb22e5812dcbdacf311d52985d25e208 --- /dev/null +++ b/default/Makefile @@ -0,0 +1,101 @@ +############################################################################### +# Makefile for the project expansion_board +############################################################################### + +## General Flags +PROJECT = expansion_board +MCU = atmega128 +TARGET = expansion_board.elf +CC = avr-gcc + +CPP = avr-g++ + +## Options common to compile, link and assembly rules +COMMON = -mmcu=$(MCU) + +## Compile options common for all C compilation units. +CFLAGS = $(COMMON) +CFLAGS += -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d + +## Assembly specific flags +ASMFLAGS = $(COMMON) +ASMFLAGS += $(CFLAGS) +ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2 + +## Linker flags +LDFLAGS = $(COMMON) +LDFLAGS += -Wl,-Map=expansion_board.map + + +## Intel Hex file production flags +HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature + +HEX_EEPROM_FLAGS = -j .eeprom +HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" +HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings + + +## Objects that must be built in order to link +OBJECTS = expansion_board.o dynamixel.o timer128.o compass.o i2c.o a2d.o buffer.o uartsw.o ports.o + +## Objects explicitly added by the user +LINKONLYOBJECTS = + +## Build +all: $(TARGET) expansion_board.hex expansion_board.eep expansion_board.lss size + +## Compile +expansion_board.o: ../expansion_board.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +dynamixel.o: ../dynamixel.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +timer128.o: ../timer128.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +compass.o: ../compass.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +i2c.o: ../i2c.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +a2d.o: ../a2d.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +buffer.o: ../buffer.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +uartsw.o: ../uartsw.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +ports.o: ../ports.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +##Link +$(TARGET): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET) + +%.hex: $(TARGET) + avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@ + +%.eep: $(TARGET) + -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0 + +%.lss: $(TARGET) + avr-objdump -h -S $< > $@ + +size: ${TARGET} + @echo + @avr-size -C --mcu=${MCU} ${TARGET} + +## Clean target +.PHONY: clean +clean: + -rm -rf $(OBJECTS) expansion_board.elf dep/* expansion_board.hex expansion_board.eep expansion_board.lss expansion_board.map + + +## Other dependencies +-include $(shell mkdir dep 2>NUL) $(wildcard dep/*) + diff --git a/default/NUL b/default/NUL new file mode 100644 index 0000000000000000000000000000000000000000..1b1fbad9c42db259c5c68748ac9f62539bd0abff --- /dev/null +++ b/default/NUL @@ -0,0 +1 @@ +mkdir: cannot create directory ‘dep’: File exists diff --git a/default/expansion_board.aps b/default/expansion_board.aps new file mode 100755 index 0000000000000000000000000000000000000000..b5a5f596c0bae8eb041c2e04ab900f020634e5ef --- /dev/null +++ b/default/expansion_board.aps @@ -0,0 +1 @@ +<AVRStudio><MANAGEMENT><ProjectName>expansion_board</ProjectName><Created>21-Jan-2011 15:23:22</Created><LastEdit>18-Jul-2011 12:33:48</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>21-Jan-2011 15:23:22</Created><Version>4</Version><Build>4, 18, 0, 685</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>default\expansion_board.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>\\VBOXSVR\shared\Software\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET></CURRENT_TARGET><CURRENT_PART></CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM></COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>expansion_board.c</SOURCEFILE><SOURCEFILE>dynamixel.c</SOURCEFILE><SOURCEFILE>timer128.c</SOURCEFILE><SOURCEFILE>compass.c</SOURCEFILE><SOURCEFILE>i2c.c</SOURCEFILE><SOURCEFILE>a2d.c</SOURCEFILE><SOURCEFILE>buffer.c</SOURCEFILE><SOURCEFILE>uartsw.c</SOURCEFILE><SOURCEFILE>ports.c</SOURCEFILE><HEADERFILE>utils.h</HEADERFILE><HEADERFILE>dynamixel.h</HEADERFILE><HEADERFILE>global.h</HEADERFILE><HEADERFILE>timer128.h</HEADERFILE><HEADERFILE>avrlibtypes.h</HEADERFILE><HEADERFILE>avrlibdefs.h</HEADERFILE><HEADERFILE>port128.h</HEADERFILE><HEADERFILE>compass.h</HEADERFILE><HEADERFILE>i2c.h</HEADERFILE><HEADERFILE>i2cconf.h</HEADERFILE><HEADERFILE>memory_map.h</HEADERFILE><HEADERFILE>a2d.h</HEADERFILE><HEADERFILE>buffer.h</HEADERFILE><HEADERFILE>uartsw.h</HEADERFILE><HEADERFILE>uartswconf.h</HEADERFILE><HEADERFILE>ports.h</HEADERFILE><OTHERFILE>default\expansion_board.lss</OTHERFILE><OTHERFILE>default\expansion_board.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>atmega128</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>expansion_board.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS><OPTION><FILE>buffer.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>dynamixel.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>expansion_board.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>timer128.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>uart2.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20100110\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20100110\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><ProjectFiles><Files><Name>\\VBOXSVR\shared\Software\utils.h</Name><Name>\\VBOXSVR\shared\Software\dynamixel.h</Name><Name>\\VBOXSVR\shared\Software\global.h</Name><Name>\\VBOXSVR\shared\Software\timer128.h</Name><Name>\\VBOXSVR\shared\Software\avrlibtypes.h</Name><Name>\\VBOXSVR\shared\Software\avrlibdefs.h</Name><Name>\\VBOXSVR\shared\Software\port128.h</Name><Name>\\VBOXSVR\shared\Software\compass.h</Name><Name>\\VBOXSVR\shared\Software\i2c.h</Name><Name>\\VBOXSVR\shared\Software\i2cconf.h</Name><Name>\\VBOXSVR\shared\Software\memory_map.h</Name><Name>\\VBOXSVR\shared\Software\a2d.h</Name><Name>\\VBOXSVR\shared\Software\buffer.h</Name><Name>\\VBOXSVR\shared\Software\uartsw.h</Name><Name>\\VBOXSVR\shared\Software\uartswconf.h</Name><Name>\\VBOXSVR\shared\Software\ports.h</Name><Name>\\VBOXSVR\shared\Software\expansion_board.c</Name><Name>\\VBOXSVR\shared\Software\dynamixel.c</Name><Name>\\VBOXSVR\shared\Software\timer128.c</Name><Name>\\VBOXSVR\shared\Software\compass.c</Name><Name>\\VBOXSVR\shared\Software\i2c.c</Name><Name>\\VBOXSVR\shared\Software\a2d.c</Name><Name>\\VBOXSVR\shared\Software\buffer.c</Name><Name>\\VBOXSVR\shared\Software\uartsw.c</Name><Name>\\VBOXSVR\shared\Software\ports.c</Name></Files></ProjectFiles><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files><File00000><FileId>00000</FileId><FileName>expansion_board.c</FileName><Status>1</Status></File00000><File00001><FileId>00001</FileId><FileName>uartsw.h</FileName><Status>1</Status></File00001><File00002><FileId>00002</FileId><FileName>uartsw.c</FileName><Status>1</Status></File00002><File00003><FileId>00003</FileId><FileName>uartswconf.h</FileName><Status>1</Status></File00003><File00004><FileId>00004</FileId><FileName>buffer.h</FileName><Status>1</Status></File00004><File00005><FileId>00005</FileId><FileName>compass.c</FileName><Status>1</Status></File00005><File00006><FileId>00006</FileId><FileName>dynamixel.c</FileName><Status>1</Status></File00006><File00007><FileId>00007</FileId><FileName>dynamixel.h</FileName><Status>1</Status></File00007><File00008><FileId>00008</FileId><FileName>ports.h</FileName><Status>1</Status></File00008><File00009><FileId>00009</FileId><FileName>ports.c</FileName><Status>1</Status></File00009><File00010><FileId>00010</FileId><FileName>port128.h</FileName><Status>1</Status></File00010><File00011><FileId>00011</FileId><FileName>i2c.c</FileName><Status>1</Status></File00011><File00012><FileId>00012</FileId><FileName>compass.h</FileName><Status>1</Status></File00012><File00013><FileId>00013</FileId><FileName>buffer.c</FileName><Status>1</Status></File00013><File00014><FileId>00014</FileId><FileName>a2d.c</FileName><Status>1</Status></File00014></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio> diff --git a/default/expansion_board.aws b/default/expansion_board.aws new file mode 100755 index 0000000000000000000000000000000000000000..351856dd9e369b31b6960a6674e81ec68689e037 --- /dev/null +++ b/default/expansion_board.aws @@ -0,0 +1 @@ +<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name=""/><Files><File00000 Name="\\Vboxsvr\shared\Software\expansion_board.c" Position="201 89 894 404" LineCol="146 14" State="Maximized"/><File00001 Name="\\Vboxsvr\shared\Software\uartsw.h" Position="223 116 908 401" LineCol="0 0" State="Maximized"/><File00002 Name="\\Vboxsvr\shared\Software\uartsw.c" Position="245 138 930 423" LineCol="49 0" State="Maximized"/><File00003 Name="\\Vboxsvr\shared\Software\uartswconf.h" Position="267 160 952 445" LineCol="40 0" State="Maximized"/><File00004 Name="\\Vboxsvr\shared\Software\buffer.h" Position="289 182 974 467" LineCol="0 0" State="Maximized"/><File00005 Name="\\Vboxsvr\shared\Software\compass.c" Position="311 204 996 489" LineCol="19 0" State="Maximized"/><File00006 Name="\\Vboxsvr\shared\Software\dynamixel.c" Position="333 226 1018 511" LineCol="226 0" State="Maximized"/><File00007 Name="\\Vboxsvr\shared\Software\dynamixel.h" Position="201 94 886 379" LineCol="26 0" State="Maximized"/><File00008 Name="\\Vboxsvr\shared\Software\ports.h" Position="223 116 908 401" LineCol="21 0" State="Maximized"/><File00009 Name="\\Vboxsvr\shared\Software\ports.c" Position="245 138 930 423" LineCol="22 0" State="Maximized"/><File00010 Name="\\Vboxsvr\shared\Software\port128.h" Position="267 160 952 445" LineCol="0 0" State="Maximized"/><File00011 Name="\\Vboxsvr\shared\Software\i2c.c" Position="289 182 974 467" LineCol="0 0" State="Maximized"/><File00012 Name="\\Vboxsvr\shared\Software\compass.h" Position="311 204 996 489" LineCol="12 35" State="Maximized"/><File00013 Name="\\Vboxsvr\shared\Software\buffer.c" Position="333 226 1018 511" LineCol="0 0" State="Maximized"/><File00014 Name="\\Vboxsvr\shared\Software\a2d.c" Position="201 94 886 379" LineCol="0 0" State="Maximized"/><File00015 Name="\\Vboxsvr\shared\Software\memory_map.h" Position="197 71 1026 519" LineCol="0 0" State="Maximized"/></Files></AVRWorkspace> diff --git a/default/expansion_board.c b/default/expansion_board.c new file mode 100755 index 0000000000000000000000000000000000000000..482b8152e8b03e4447af2fd05c45227985728795 --- /dev/null +++ b/default/expansion_board.c @@ -0,0 +1,352 @@ +#include "memory_map.h" +#include "dynamixel.h" +#include "timer128.h" +#include "compass.h" +#include "uartsw.h" +#include "avr/io.h" +#include "ports.h" +#include "a2d.h" +#include "i2c.h" + +void periodic_calls(void) +{ + static short int count=0; + + sei(); + outb(TCNT0,0x7F); + compass_periodic_call(); + count++; + if(count==1000) + { + if(PINE&0x04) + cbi(PORTE,2); + else + sbi(PORTE,2); + count=0; + } +} + +int main(void) +{ + unsigned char data[128],id,length,instruction,answer[2],status; + // selected address + unsigned char rs485_address; + // adc conversion result + unsigned short int adc_value; + // heading value + unsigned short int compass_heading; + // serial port variables + unsigned char data_available; + unsigned char serial_data; + // gpio identifier + unsigned char gpio_id; + // pwm identifier + unsigned char pwm_id; + // pwm value + unsigned short int pwm_value; + + // initialize the IO ports + init_ports(); + + // initialize the RS485 interface + init_RS485(); + get_RS485_address(&rs485_address); + + // initialize the analog to digital converter + a2dInit(); + + // initialize the i2c peripheral + i2cInit(); + + // initialize the compass + CompassInit(); + + // initialize timer to execute periodic functions + timer0Init(); + // set the period to 1ms + timer0SetPrescaler(TIMER_CLK_DIV1024); + outb(TCNT0,0x7F); + timerAttach(TIMER0OVERFLOW_INT, periodic_calls); + + // initialize the timer 3 to generate RC PWM + timer3Init(); + timer3SetPrescaler(TIMER_CLK_DIV8); + timer3PWMInitICR(40000);// set a 50 Hz freq + + // initialize the timer 1 to generate analog signals + timer1Init(); + timer1SetPrescaler(TIMER_CLK_DIV1); + timer1PWMInitICR(16000);// set a a kHz freq + + // initialize the software serial port +// uartswInit(); + + sei();// turn on interrupts (if not already on) + + while(1) + { + status=RxRS485Packet(RS485_single_ended,&id,&instruction,&length,data); + if(status==CHECK_ERROR) + TxRS485Packet(RS485_single_ended,rs485_address,CHECKSUM_ERROR,0,NULL); + else if(status==CORRECT) + { + if(id==rs485_address) + { + switch(instruction) + { + case INST_PING: TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + break; + case INST_READ: if(data[0]>=0x00 && data[0]<=0x07) + { + if(length==2) + { + adc_value=adc_get_channel(data[0]); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,(unsigned char *)&adc_value); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + if(data[0]>=0x08 && data[0]<=0x0F) + { + if(length==2) + { + adc_value=adc_get_averaged_channel(data[0]-8); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,(unsigned char *)&adc_value); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x10) + { + if(length==2) + { + compass_heading=compass_get_heading(); + answer[0]=compass_heading&0xFF; + answer[1]=(compass_heading>>8)&0xFF; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x11) + { + if(length==2) + { + compass_heading=compass_get_averaged_heading(); + answer[0]=compass_heading&0xFF; + answer[1]=(compass_heading>>8)&0xFF; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x12) + { + if(length==2) + { + if(!calibrate && !calibrating) + answer[0]=0x00; + else + answer[0]=0x01; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,1,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + + } + else if(data[0]==0x21) + { + if(length==2) + { + data_available=uartswReceiveByte(&serial_data); + answer[0]=data_available; + answer[1]=serial_data; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]>=0x30 && data[0]<=0x55) + { + if(length==2) + { + gpio_id=(data[0]-0x30)>>1; + if((data[0]%2)==0x00)// configuration register + answer[0]=get_port_config(gpio_id); + else// data register + { + answer[0]=read_port(gpio_id); + + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,1,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x61 || data[0]==0x63 || data[0]==0x65 || data[0]==0x67) + { + if(length==2) + { + pwm_id=(data[0]-0x61)>>1; + answer[0]=0x00; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,1,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + break; + case INST_WRITE: if(data[0]==0x12) + { + if(length==2) + { + if(!calibrate) + calibrate=TRUE; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x20) + { + if(length==2) + { + uartswSendByte(data[1]); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]>=0x30 && data[0]<=0x55) + { + if(length==2) + { + gpio_id=(data[0]-0x30)>>1; + if((data[0]%2)==0x00)// configuration register + { + config_port(gpio_id,data[1]); + answer[0]=DDRA; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else// value register + { + if(data[1]==0x00) + clear_port(gpio_id); + else + set_port(gpio_id); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x60 || data[0]==0x62 || data[0]==0x64 || data[0]==0x66) + { + if(length==3) + { + pwm_id=(data[0]-0x60)>>1; + pwm_value=data[1]+data[2]*256; + if(pwm_value>40000) + pwm_value=40000; + switch(pwm_id) + { + case 0: timer3PWMASet(pwm_value); + break; + case 1: timer3PWMBSet(pwm_value); + break; + case 2: timer3PWMCSet(pwm_value); + break; + case 3: timer1PWMCSet(pwm_value); + break; + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x61 || data[0]==0x63 || data[0]==0x65 || data[0]==0x67) + { + if(length==2) + { + pwm_id=(data[0]-0x61)>>1; + switch(pwm_id) + { + case 0: if(data[1]==0x00) + timer3PWMAOff(); + else + timer3PWMAOn(); + break; + case 1: if(data[1]==0x00) + timer3PWMBOff(); + else + timer3PWMBOn(); + break; + case 2: if(data[1]==0x00) + timer3PWMCOff(); + else + timer3PWMCOn(); + break; + case 3: if(data[1]==0x00) + timer1PWMCOff(); + else + timer1PWMCOn(); + break; + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x70 || data[0]==0x72) + { + if(length==3) + { + pwm_id=(data[0]-0x70)>>1; + pwm_value=data[1]+data[2]*256; + if(pwm_value>16000) + pwm_value=16000; + if(pwm_id==0) + timer1PWMASet(pwm_value); + else + timer1PWMBSet(pwm_value); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x71 || data[0]==0x73) + { + if(length==2) + { + pwm_id=(data[0]-0x71)>>1; + if(pwm_id==0) + { + if(data[1]==0x00) + timer1PWMAOff(); + else + timer1PWMAOn(); + } + else + { + if(data[1]==0x00) + timer1PWMBOff(); + else + timer1PWMBOn(); + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + case INST_SYNC_WRITE: // do nothing to avoid desynchronization with the controller + break; + default: //TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + break; + } + } + } + } +} diff --git a/dynamixel.c b/dynamixel.c new file mode 100755 index 0000000000000000000000000000000000000000..bd8b85f71b1f05438b2174b07d21e2a1ba4409a7 --- /dev/null +++ b/dynamixel.c @@ -0,0 +1,245 @@ +#include <avr/interrupt.h> +#include "dynamixel.h" +#include "timer128.h" +#include "buffer.h" +#include <avr/io.h> + +// receive buffers +volatile unsigned char rs485_se_data[RX_BUFFER_SIZE]; +volatile unsigned char rs485_se_read_ptr; +volatile unsigned char rs485_se_write_ptr; +volatile unsigned char rs485_se_num; +volatile unsigned char rs485_diff_data[RX_BUFFER_SIZE]; +volatile unsigned char rs485_diff_read_ptr; +volatile unsigned char rs485_diff_write_ptr; +volatile unsigned char rs485_diff_num; + +unsigned char RS485_is_tx_ready(unsigned char nUart) +{ + if(nUart) + return (UCSR1A & (1<<UDRE)); + else + return (UCSR0A & (1<<UDRE)); +} + +unsigned char RS485_is_rx_ready(unsigned char nUart) +{ + unsigned char status; + cli(); + if(nUart) + { + if(rs485_se_num==0) status=FALSE; + else status=TRUE; + } + else + { + if(rs485_diff_num==0) status=FALSE; + else status=TRUE; + } + sei(); + + return status; +} + +void RS485_set_tx_done(unsigned char nUart) +{ + if(nUart) + sbi(UCSR1A,6); + else + sbi(UCSR0A,6); +} + +unsigned char RS485_is_tx_done(unsigned char nUart) +{ + if(nUart) + return bit_is_set(UCSR1A,6); + else + return bit_is_set(UCSR0A,6); +} + +void RS485_send(unsigned char nUart,unsigned char data) +{ + RS485_set_tx_done(nUart); + while(!RS485_is_tx_ready(nUart)); + if(nUart) + UDR1=data; + else + UDR0=data; +} + +void RS485_receive(unsigned char nUart,unsigned char *data) +{ + while(!RS485_is_rx_ready(nUart)); + cli(); + if(nUart) + { + (*data) = rs485_se_data[rs485_se_read_ptr]; + rs485_se_read_ptr=(rs485_se_read_ptr+1)%RX_BUFFER_SIZE; + rs485_se_num--; + } + else + { + (*data) = rs485_diff_data[rs485_diff_read_ptr]; + rs485_diff_read_ptr=(rs485_diff_read_ptr+1)%RX_BUFFER_SIZE; + rs485_diff_num--; + } + sei(); +} + +void init_RS485(void) +{ + // configure the IO ports + DDRD=DDRD|0xC8;// RX_en, TX_en, TX are outputs + DDRD=DDRD&0xFB;// RX is an input + + // configure the address selection bits + DDRG=DDRG&0xE7;// they are inputs + + // configure the ports to receive data + SET_RS485_RXD; + + // initialize the rs485 ports + UCSR0A = 0;// Single (not double) the USART transmission speed + UBRR0H = 0; + UBRR0L = 0;// BAUD = 1000000bps at U2X=0, Fosc=16MHz => UBRR=0 + outb(UCSR0B, BV(RXCIE)|BV(RXEN)|BV(TXEN)); + UCSR0C = 0x86; // 8 bit data, no parity (and URSEL must be 1) + + UCSR1A = 0;// Single (not double) the USART transmission speed + UBRR1H = 0; + UBRR1L = 0;// BAUD = 1000000bps at U2X=0, Fosc=16MHz => UBRR=0 + outb(UCSR1B, BV(RXCIE)|BV(RXEN)|BV(TXEN)); + UCSR1C = 0x86; // 8 bit data, no parity (and URSEL must be 1) + + // initialize receive buffer for both interfaces + rs485_se_read_ptr=0; + rs485_se_write_ptr=0; + rs485_se_num=0; + + rs485_diff_read_ptr=0; + rs485_diff_write_ptr=0; + rs485_diff_num=0; +} + +void get_RS485_address(unsigned char *address) +{ + unsigned char sel; + + sel=(PING&0x18); + switch(sel) + { + case 0x00: (*address)=0x45; + break; + case 0x10: (*address)=0x80; + break; + case 0x08: (*address)=0xC0; + break; + case 0x18: (*address)=0xFD; + break; + default: (*address)=0x45; + break; + } +} + +void TxRS485Packet(unsigned char nUart,unsigned char id, unsigned char instruction, unsigned char param_len, unsigned char *params) +{ + unsigned char checksum=0,i=0; + + SET_RS485_TXD; + RS485_send(nUart,0xFF); + RS485_send(nUart,0xFF); + RS485_send(nUart,id); + checksum+=id; + RS485_send(nUart,param_len+2); + checksum+=param_len+2; + RS485_send(nUart,instruction); + checksum+=instruction; + for(i=0;i<param_len;i++) + { + RS485_send(nUart,params[i]); + checksum+=params[i]; + } + RS485_send(nUart,~checksum); + while(!RS485_is_tx_done(nUart));// wait util the data is sent + SET_RS485_RXD; +} + +unsigned char RxRS485Packet(unsigned char nUart,unsigned char *id,unsigned char *instruction, unsigned char *param_len, unsigned char *params) +{ + static unsigned char checksum=0,read_params=0; + static dyn_states state=dyn_header1; + unsigned char byte; + + if(RS485_is_rx_ready(nUart)) + { + switch(state) + { + case dyn_header1: RS485_receive(nUart,&byte); + if(byte==0xFF) state=dyn_header2; + else state=dyn_header1; + break; + case dyn_header2: RS485_receive(nUart,&byte); + if(byte==0xFF) + { + state=dyn_id; + checksum=0; + } + else state=dyn_header1; + break; + case dyn_id: RS485_receive(nUart,id); + checksum+=(*id); + state=dyn_length; + break; + case dyn_length: RS485_receive(nUart,param_len); + checksum+=(*param_len); + (*param_len)=(*param_len)-2; + state=dyn_inst; + break; + case dyn_inst: RS485_receive(nUart,instruction); + checksum+=(*instruction); + if((*param_len)==0) state=dyn_checksum; + else state=dyn_params; + read_params=0; + break; + case dyn_params: RS485_receive(nUart,¶ms[read_params]); + checksum+=params[read_params]; + read_params++; + if(read_params==(*param_len)) + state=dyn_checksum; + else + state=dyn_params; + break; + case dyn_checksum: RS485_receive(nUart,&byte); + checksum+=byte; + state=dyn_header1; + //if(checksum==0xFF) + return CORRECT; + //else + //{ + // return CHECK_ERROR; + //} + break; + } + } + + return INCOMPLETE; + +} + +UART_INTERRUPT_HANDLER(UART0_RX_vect) +{ + // service UART0 receive interrupt + rs485_diff_data[rs485_diff_write_ptr]=inb(UDR0); + rs485_diff_write_ptr=(rs485_diff_write_ptr+1)%RX_BUFFER_SIZE; + rs485_diff_num++; +} + +UART_INTERRUPT_HANDLER(UART1_RX_vect) +{ + // service UART1 receive interrupt + rs485_se_data[rs485_se_write_ptr]=inb(UDR1); + rs485_se_write_ptr=(rs485_se_write_ptr+1)%RX_BUFFER_SIZE; + rs485_se_num=rs485_se_num+1; +} + + diff --git a/dynamixel.h b/dynamixel.h new file mode 100755 index 0000000000000000000000000000000000000000..c1503e4db1903c634b55ce4e06ed3f75a52494e3 --- /dev/null +++ b/dynamixel.h @@ -0,0 +1,66 @@ +#ifndef _DYNAMIXEL_H +#define _DYNAMIXEL_H + +#include "global.h" +#include "utils.h" + +//! Type of interrupt handler to use for uart interrupts. +/// Value may be SIGNAL or INTERRUPT. +/// \warning Do not change unless you know what you're doing. +#ifndef UART_INTERRUPT_HANDLER +#define UART_INTERRUPT_HANDLER SIGNAL +#endif + +// receive buffers length +#define RX_BUFFER_SIZE 128 + +// Instruction identifiers +#define INST_PING 0x01 +#define INST_READ 0x02 +#define INST_WRITE 0x03 +#define INST_REG_WRITE 0x04 +#define INST_ACTION 0x05 +#define INST_RESET 0x06 +#define INST_DIGITAL_RESET 0x07 +#define INST_SYSTEM_READ 0x0C +#define INST_SYSTEM_WRITE 0x0D +#define INST_SYNC_WRITE 0x83 +#define INST_SYNC_REG_WRITE 0x84 + +// bus errors +#define INSTRUCTION_ERROR 0x40 +#define OVERLOAD_ERROR 0x20 +#define CHECKSUM_ERROR 0x10 +#define RANGE_ERROR 0x08 +#define OVERHEATING_ERROR 0x04 +#define ANGLE_LIMIT_ERROR 0x02 +#define VOLTAGE_ERROR 0x01 +#define NO_ERROR 0x00 + +#define RS485_single_ended 1 +#define RS485_differential 0 + +// instructions to configure the data direction on the RS485 interface +#define SET_RS485_TXD PORTD &= ~_BV(PD7),PORTD |= _BV(PD6) +#define SET_RS485_RXD PORTD &= ~_BV(PD6),PORTD |= _BV(PD7) + +// broadcasting address +#define BROADCASTING_ID 0xFE + +// possible packet status +#define CORRECT 0 +#define INCOMPLETE 1 +#define CHECK_ERROR 2 + +typedef enum {dyn_header1,dyn_header2,dyn_id,dyn_length,dyn_inst,dyn_params,dyn_checksum} dyn_states; + +// function to initialize the RS485 interface +void init_RS485(void); +// function to set the rs485 device address +void get_RS485_address(unsigned char *address); +// function to send a packet through the RS485 interface +void TxRS485Packet(unsigned char nUart,unsigned char id, unsigned char instruction, unsigned char param_len, unsigned char *params); +// function to receive a packet through the RS485 interface using interrupts +unsigned char RxRS485Packet(unsigned char nUart,unsigned char *id, unsigned char *instruction, unsigned char *param_len, unsigned char *params); + +#endif diff --git a/expansion_board.aps b/expansion_board.aps new file mode 100755 index 0000000000000000000000000000000000000000..b5a5f596c0bae8eb041c2e04ab900f020634e5ef --- /dev/null +++ b/expansion_board.aps @@ -0,0 +1 @@ +<AVRStudio><MANAGEMENT><ProjectName>expansion_board</ProjectName><Created>21-Jan-2011 15:23:22</Created><LastEdit>18-Jul-2011 12:33:48</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>21-Jan-2011 15:23:22</Created><Version>4</Version><Build>4, 18, 0, 685</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>default\expansion_board.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>\\VBOXSVR\shared\Software\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET></CURRENT_TARGET><CURRENT_PART></CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM></COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>expansion_board.c</SOURCEFILE><SOURCEFILE>dynamixel.c</SOURCEFILE><SOURCEFILE>timer128.c</SOURCEFILE><SOURCEFILE>compass.c</SOURCEFILE><SOURCEFILE>i2c.c</SOURCEFILE><SOURCEFILE>a2d.c</SOURCEFILE><SOURCEFILE>buffer.c</SOURCEFILE><SOURCEFILE>uartsw.c</SOURCEFILE><SOURCEFILE>ports.c</SOURCEFILE><HEADERFILE>utils.h</HEADERFILE><HEADERFILE>dynamixel.h</HEADERFILE><HEADERFILE>global.h</HEADERFILE><HEADERFILE>timer128.h</HEADERFILE><HEADERFILE>avrlibtypes.h</HEADERFILE><HEADERFILE>avrlibdefs.h</HEADERFILE><HEADERFILE>port128.h</HEADERFILE><HEADERFILE>compass.h</HEADERFILE><HEADERFILE>i2c.h</HEADERFILE><HEADERFILE>i2cconf.h</HEADERFILE><HEADERFILE>memory_map.h</HEADERFILE><HEADERFILE>a2d.h</HEADERFILE><HEADERFILE>buffer.h</HEADERFILE><HEADERFILE>uartsw.h</HEADERFILE><HEADERFILE>uartswconf.h</HEADERFILE><HEADERFILE>ports.h</HEADERFILE><OTHERFILE>default\expansion_board.lss</OTHERFILE><OTHERFILE>default\expansion_board.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>atmega128</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>expansion_board.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS><OPTION><FILE>buffer.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>dynamixel.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>expansion_board.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>timer128.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>uart2.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20100110\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20100110\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><ProjectFiles><Files><Name>\\VBOXSVR\shared\Software\utils.h</Name><Name>\\VBOXSVR\shared\Software\dynamixel.h</Name><Name>\\VBOXSVR\shared\Software\global.h</Name><Name>\\VBOXSVR\shared\Software\timer128.h</Name><Name>\\VBOXSVR\shared\Software\avrlibtypes.h</Name><Name>\\VBOXSVR\shared\Software\avrlibdefs.h</Name><Name>\\VBOXSVR\shared\Software\port128.h</Name><Name>\\VBOXSVR\shared\Software\compass.h</Name><Name>\\VBOXSVR\shared\Software\i2c.h</Name><Name>\\VBOXSVR\shared\Software\i2cconf.h</Name><Name>\\VBOXSVR\shared\Software\memory_map.h</Name><Name>\\VBOXSVR\shared\Software\a2d.h</Name><Name>\\VBOXSVR\shared\Software\buffer.h</Name><Name>\\VBOXSVR\shared\Software\uartsw.h</Name><Name>\\VBOXSVR\shared\Software\uartswconf.h</Name><Name>\\VBOXSVR\shared\Software\ports.h</Name><Name>\\VBOXSVR\shared\Software\expansion_board.c</Name><Name>\\VBOXSVR\shared\Software\dynamixel.c</Name><Name>\\VBOXSVR\shared\Software\timer128.c</Name><Name>\\VBOXSVR\shared\Software\compass.c</Name><Name>\\VBOXSVR\shared\Software\i2c.c</Name><Name>\\VBOXSVR\shared\Software\a2d.c</Name><Name>\\VBOXSVR\shared\Software\buffer.c</Name><Name>\\VBOXSVR\shared\Software\uartsw.c</Name><Name>\\VBOXSVR\shared\Software\ports.c</Name></Files></ProjectFiles><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files><File00000><FileId>00000</FileId><FileName>expansion_board.c</FileName><Status>1</Status></File00000><File00001><FileId>00001</FileId><FileName>uartsw.h</FileName><Status>1</Status></File00001><File00002><FileId>00002</FileId><FileName>uartsw.c</FileName><Status>1</Status></File00002><File00003><FileId>00003</FileId><FileName>uartswconf.h</FileName><Status>1</Status></File00003><File00004><FileId>00004</FileId><FileName>buffer.h</FileName><Status>1</Status></File00004><File00005><FileId>00005</FileId><FileName>compass.c</FileName><Status>1</Status></File00005><File00006><FileId>00006</FileId><FileName>dynamixel.c</FileName><Status>1</Status></File00006><File00007><FileId>00007</FileId><FileName>dynamixel.h</FileName><Status>1</Status></File00007><File00008><FileId>00008</FileId><FileName>ports.h</FileName><Status>1</Status></File00008><File00009><FileId>00009</FileId><FileName>ports.c</FileName><Status>1</Status></File00009><File00010><FileId>00010</FileId><FileName>port128.h</FileName><Status>1</Status></File00010><File00011><FileId>00011</FileId><FileName>i2c.c</FileName><Status>1</Status></File00011><File00012><FileId>00012</FileId><FileName>compass.h</FileName><Status>1</Status></File00012><File00013><FileId>00013</FileId><FileName>buffer.c</FileName><Status>1</Status></File00013><File00014><FileId>00014</FileId><FileName>a2d.c</FileName><Status>1</Status></File00014></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio> diff --git a/expansion_board.aws b/expansion_board.aws new file mode 100755 index 0000000000000000000000000000000000000000..351856dd9e369b31b6960a6674e81ec68689e037 --- /dev/null +++ b/expansion_board.aws @@ -0,0 +1 @@ +<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name=""/><Files><File00000 Name="\\Vboxsvr\shared\Software\expansion_board.c" Position="201 89 894 404" LineCol="146 14" State="Maximized"/><File00001 Name="\\Vboxsvr\shared\Software\uartsw.h" Position="223 116 908 401" LineCol="0 0" State="Maximized"/><File00002 Name="\\Vboxsvr\shared\Software\uartsw.c" Position="245 138 930 423" LineCol="49 0" State="Maximized"/><File00003 Name="\\Vboxsvr\shared\Software\uartswconf.h" Position="267 160 952 445" LineCol="40 0" State="Maximized"/><File00004 Name="\\Vboxsvr\shared\Software\buffer.h" Position="289 182 974 467" LineCol="0 0" State="Maximized"/><File00005 Name="\\Vboxsvr\shared\Software\compass.c" Position="311 204 996 489" LineCol="19 0" State="Maximized"/><File00006 Name="\\Vboxsvr\shared\Software\dynamixel.c" Position="333 226 1018 511" LineCol="226 0" State="Maximized"/><File00007 Name="\\Vboxsvr\shared\Software\dynamixel.h" Position="201 94 886 379" LineCol="26 0" State="Maximized"/><File00008 Name="\\Vboxsvr\shared\Software\ports.h" Position="223 116 908 401" LineCol="21 0" State="Maximized"/><File00009 Name="\\Vboxsvr\shared\Software\ports.c" Position="245 138 930 423" LineCol="22 0" State="Maximized"/><File00010 Name="\\Vboxsvr\shared\Software\port128.h" Position="267 160 952 445" LineCol="0 0" State="Maximized"/><File00011 Name="\\Vboxsvr\shared\Software\i2c.c" Position="289 182 974 467" LineCol="0 0" State="Maximized"/><File00012 Name="\\Vboxsvr\shared\Software\compass.h" Position="311 204 996 489" LineCol="12 35" State="Maximized"/><File00013 Name="\\Vboxsvr\shared\Software\buffer.c" Position="333 226 1018 511" LineCol="0 0" State="Maximized"/><File00014 Name="\\Vboxsvr\shared\Software\a2d.c" Position="201 94 886 379" LineCol="0 0" State="Maximized"/><File00015 Name="\\Vboxsvr\shared\Software\memory_map.h" Position="197 71 1026 519" LineCol="0 0" State="Maximized"/></Files></AVRWorkspace> diff --git a/expansion_board.c b/expansion_board.c new file mode 100755 index 0000000000000000000000000000000000000000..482b8152e8b03e4447af2fd05c45227985728795 --- /dev/null +++ b/expansion_board.c @@ -0,0 +1,352 @@ +#include "memory_map.h" +#include "dynamixel.h" +#include "timer128.h" +#include "compass.h" +#include "uartsw.h" +#include "avr/io.h" +#include "ports.h" +#include "a2d.h" +#include "i2c.h" + +void periodic_calls(void) +{ + static short int count=0; + + sei(); + outb(TCNT0,0x7F); + compass_periodic_call(); + count++; + if(count==1000) + { + if(PINE&0x04) + cbi(PORTE,2); + else + sbi(PORTE,2); + count=0; + } +} + +int main(void) +{ + unsigned char data[128],id,length,instruction,answer[2],status; + // selected address + unsigned char rs485_address; + // adc conversion result + unsigned short int adc_value; + // heading value + unsigned short int compass_heading; + // serial port variables + unsigned char data_available; + unsigned char serial_data; + // gpio identifier + unsigned char gpio_id; + // pwm identifier + unsigned char pwm_id; + // pwm value + unsigned short int pwm_value; + + // initialize the IO ports + init_ports(); + + // initialize the RS485 interface + init_RS485(); + get_RS485_address(&rs485_address); + + // initialize the analog to digital converter + a2dInit(); + + // initialize the i2c peripheral + i2cInit(); + + // initialize the compass + CompassInit(); + + // initialize timer to execute periodic functions + timer0Init(); + // set the period to 1ms + timer0SetPrescaler(TIMER_CLK_DIV1024); + outb(TCNT0,0x7F); + timerAttach(TIMER0OVERFLOW_INT, periodic_calls); + + // initialize the timer 3 to generate RC PWM + timer3Init(); + timer3SetPrescaler(TIMER_CLK_DIV8); + timer3PWMInitICR(40000);// set a 50 Hz freq + + // initialize the timer 1 to generate analog signals + timer1Init(); + timer1SetPrescaler(TIMER_CLK_DIV1); + timer1PWMInitICR(16000);// set a a kHz freq + + // initialize the software serial port +// uartswInit(); + + sei();// turn on interrupts (if not already on) + + while(1) + { + status=RxRS485Packet(RS485_single_ended,&id,&instruction,&length,data); + if(status==CHECK_ERROR) + TxRS485Packet(RS485_single_ended,rs485_address,CHECKSUM_ERROR,0,NULL); + else if(status==CORRECT) + { + if(id==rs485_address) + { + switch(instruction) + { + case INST_PING: TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + break; + case INST_READ: if(data[0]>=0x00 && data[0]<=0x07) + { + if(length==2) + { + adc_value=adc_get_channel(data[0]); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,(unsigned char *)&adc_value); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + if(data[0]>=0x08 && data[0]<=0x0F) + { + if(length==2) + { + adc_value=adc_get_averaged_channel(data[0]-8); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,(unsigned char *)&adc_value); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x10) + { + if(length==2) + { + compass_heading=compass_get_heading(); + answer[0]=compass_heading&0xFF; + answer[1]=(compass_heading>>8)&0xFF; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x11) + { + if(length==2) + { + compass_heading=compass_get_averaged_heading(); + answer[0]=compass_heading&0xFF; + answer[1]=(compass_heading>>8)&0xFF; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x12) + { + if(length==2) + { + if(!calibrate && !calibrating) + answer[0]=0x00; + else + answer[0]=0x01; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,1,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + + } + else if(data[0]==0x21) + { + if(length==2) + { + data_available=uartswReceiveByte(&serial_data); + answer[0]=data_available; + answer[1]=serial_data; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,2,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]>=0x30 && data[0]<=0x55) + { + if(length==2) + { + gpio_id=(data[0]-0x30)>>1; + if((data[0]%2)==0x00)// configuration register + answer[0]=get_port_config(gpio_id); + else// data register + { + answer[0]=read_port(gpio_id); + + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,1,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x61 || data[0]==0x63 || data[0]==0x65 || data[0]==0x67) + { + if(length==2) + { + pwm_id=(data[0]-0x61)>>1; + answer[0]=0x00; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,1,answer); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + break; + case INST_WRITE: if(data[0]==0x12) + { + if(length==2) + { + if(!calibrate) + calibrate=TRUE; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x20) + { + if(length==2) + { + uartswSendByte(data[1]); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]>=0x30 && data[0]<=0x55) + { + if(length==2) + { + gpio_id=(data[0]-0x30)>>1; + if((data[0]%2)==0x00)// configuration register + { + config_port(gpio_id,data[1]); + answer[0]=DDRA; + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else// value register + { + if(data[1]==0x00) + clear_port(gpio_id); + else + set_port(gpio_id); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x60 || data[0]==0x62 || data[0]==0x64 || data[0]==0x66) + { + if(length==3) + { + pwm_id=(data[0]-0x60)>>1; + pwm_value=data[1]+data[2]*256; + if(pwm_value>40000) + pwm_value=40000; + switch(pwm_id) + { + case 0: timer3PWMASet(pwm_value); + break; + case 1: timer3PWMBSet(pwm_value); + break; + case 2: timer3PWMCSet(pwm_value); + break; + case 3: timer1PWMCSet(pwm_value); + break; + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x61 || data[0]==0x63 || data[0]==0x65 || data[0]==0x67) + { + if(length==2) + { + pwm_id=(data[0]-0x61)>>1; + switch(pwm_id) + { + case 0: if(data[1]==0x00) + timer3PWMAOff(); + else + timer3PWMAOn(); + break; + case 1: if(data[1]==0x00) + timer3PWMBOff(); + else + timer3PWMBOn(); + break; + case 2: if(data[1]==0x00) + timer3PWMCOff(); + else + timer3PWMCOn(); + break; + case 3: if(data[1]==0x00) + timer1PWMCOff(); + else + timer1PWMCOn(); + break; + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x70 || data[0]==0x72) + { + if(length==3) + { + pwm_id=(data[0]-0x70)>>1; + pwm_value=data[1]+data[2]*256; + if(pwm_value>16000) + pwm_value=16000; + if(pwm_id==0) + timer1PWMASet(pwm_value); + else + timer1PWMBSet(pwm_value); + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else if(data[0]==0x71 || data[0]==0x73) + { + if(length==2) + { + pwm_id=(data[0]-0x71)>>1; + if(pwm_id==0) + { + if(data[1]==0x00) + timer1PWMAOff(); + else + timer1PWMAOn(); + } + else + { + if(data[1]==0x00) + timer1PWMBOff(); + else + timer1PWMBOn(); + } + TxRS485Packet(RS485_single_ended,rs485_address,NO_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + } + else + TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + case INST_SYNC_WRITE: // do nothing to avoid desynchronization with the controller + break; + default: //TxRS485Packet(RS485_single_ended,rs485_address,INSTRUCTION_ERROR,0,NULL); + break; + } + } + } + } +} diff --git a/global.h b/global.h new file mode 100755 index 0000000000000000000000000000000000000000..075dfe6423d6854ca7ff608197ec53ef7a8ac667 --- /dev/null +++ b/global.h @@ -0,0 +1,40 @@ +/*! \file global.h \brief AVRlib project global include. */ +//***************************************************************************** +// +// File Name : 'global.h' +// Title : AVRlib project global include +// Author : Pascal Stang - Copyright (C) 2001-2002 +// Created : 7/12/2001 +// Revised : 9/30/2002 +// Version : 1.1 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// Description : This include file is designed to contain items useful to all +// code files and projects. +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef GLOBAL_H +#define GLOBAL_H + +// global AVRLIB defines +#include "avrlibdefs.h" +// global AVRLIB types definitions +#include "avrlibtypes.h" + +// project/system dependent defines + +// CPU clock speed +#define F_CPU 16000000 // 16MHz processor +//#define F_CPU 14745000 // 14.745MHz processor +//#define F_CPU 8000000 // 8MHz processor +//#define F_CPU 7372800 // 7.37MHz processor +//#define F_CPU 4000000 // 4MHz processor +//#define F_CPU 3686400 // 3.69MHz processor +#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond + +#endif diff --git a/i2c.c b/i2c.c new file mode 100755 index 0000000000000000000000000000000000000000..1ca4b20f95e0eabe5e0b0db0f3fad27a0178d6b7 --- /dev/null +++ b/i2c.c @@ -0,0 +1,606 @@ +/*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */ +//***************************************************************************** +// +// File Name : 'i2c.c' +// Title : I2C interface using AVR Two-Wire Interface (TWI) hardware +// Author : Pascal Stang - Copyright (C) 2002-2003 +// Created : 2002.06.25 +// Revised : 2003.03.02 +// Version : 0.9 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "i2c.h" + +// Standard I2C bit rates are: +// 100KHz for slow speed +// 400KHz for high speed + +//#define I2C_DEBUG + +// I2C state and address variables +static volatile eI2cStateType I2cState; +static u08 I2cDeviceAddrRW; +// send/transmit buffer (outgoing data) +static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; +static u08 I2cSendDataIndex; +static u08 I2cSendDataLength; +// receive buffer (incoming data) +static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; +static u08 I2cReceiveDataIndex; +static u08 I2cReceiveDataLength; + +// function pointer to i2c receive routine +//! I2cSlaveReceive is called when this processor +// is addressed as a slave for writing +static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData); +//! I2cSlaveTransmit is called when this processor +// is addressed as a slave for reading +static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData); + +// functions +void i2cInit(void) +{ + // set pull-up resistors on I2C bus pins + // TODO: should #ifdef these +// sbi(PORTC, 5); // i2c SCL on ATmega163,323,16,32,etc +// sbi(PORTC, 4); // i2c SDA on ATmega163,323,16,32,etc +// sbi(PORTD, 0); // i2c SCL on ATmega128,64 +// sbi(PORTD, 1); // i2c SDA on ATmega128,64 + + // clear SlaveReceive and SlaveTransmit handler to null + i2cSlaveReceive = 0; + i2cSlaveTransmit = 0; + // set i2c bit rate to 100KHz + i2cSetBitrate(100); + // enable TWI (two-wire interface) + sbi(TWCR, TWEN); + // set state + I2cState = I2C_IDLE; + // enable TWI interrupt and slave address ACK + sbi(TWCR, TWIE); + sbi(TWCR, TWEA); + //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); +} + +void i2cSetBitrate(u16 bitrateKHz) +{ + u08 bitrate_div; + // set i2c bitrate + // SCL freq = F_CPU/(16+2*TWBR)) + #ifdef TWPS0 + // for processors with additional bitrate division (mega128) + // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) + // set TWPS to zero + cbi(TWSR, TWPS0); + cbi(TWSR, TWPS1); + #endif + // calculate bitrate division + bitrate_div = ((F_CPU/1000l)/bitrateKHz); + if(bitrate_div >= 16) + bitrate_div = (bitrate_div-16)/2; + outb(TWBR, bitrate_div); +} + +void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn) +{ + // set local device address (used in slave mode only) + outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) ); +} + +void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData)) +{ + i2cSlaveReceive = i2cSlaveRx_func; +} + +void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData)) +{ + i2cSlaveTransmit = i2cSlaveTx_func; +} + +inline void i2cSendStart(void) +{ + // send start condition + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); +} + +inline void i2cSendStop(void) +{ + // transmit stop condition + // leave with TWEA on for slave receiving + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO)); +} + +inline void i2cWaitForComplete(void) +{ + // wait for i2c interface to complete operation + while( !(inb(TWCR) & BV(TWINT)) ); +} + +inline void i2cSendByte(u08 data) +{ + // save data to the TWDR + outb(TWDR, data); + // begin send + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); +} + +inline void i2cReceiveByte(u08 ackFlag) +{ + // begin receive over i2c + if( ackFlag ) + { + // ackFlag = TRUE: ACK the recevied data + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); + } + else + { + // ackFlag = FALSE: NACK the recevied data + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); + } +} + +inline u08 i2cGetReceivedByte(void) +{ + // retieve received data byte from i2c TWDR + return( inb(TWDR) ); +} + +inline u08 i2cGetStatus(void) +{ + // retieve current i2c status from i2c TWSR + return( inb(TWSR) ); +} + +void i2cMasterSend(u08 deviceAddr, u08 length, u08* data) +{ + u08 i; + // wait for interface to be ready + while(I2cState); + // set state + I2cState = I2C_MASTER_TX; + // save data + I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation + for(i=0; i<length; i++) + I2cSendData[i] = *data++; + I2cSendDataIndex = 0; + I2cSendDataLength = length; + // send start condition + i2cSendStart(); +} + +void i2cMasterReceive(u08 deviceAddr, u08 length)//, u08* data) +{ +// u08 i; + // wait for interface to be ready + while(I2cState); + // set state + I2cState = I2C_MASTER_RX; + // save data + I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation + I2cReceiveDataIndex = 0; + I2cReceiveDataLength = length; + // send start condition + i2cSendStart(); + // wait for data +// while(I2cState); + // return data +// for(i=0; i<length; i++) +// *data++ = I2cReceiveData[i]; +} + +u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data) +{ + u08 retval = I2C_OK; + + // disable TWI interrupt + cbi(TWCR, TWIE); + + // send start condition + i2cSendStart(); + i2cWaitForComplete(); + + // send device address with write + i2cSendByte( deviceAddr & 0xFE ); + i2cWaitForComplete(); + + // check if device is present and live + if( inb(TWSR) == TW_MT_SLA_ACK) + { + // send data + while(length) + { + i2cSendByte( *data++ ); + i2cWaitForComplete(); + length--; + } + } + else + { + // device did not ACK it's address, + // data will not be transferred + // return error + retval = I2C_ERROR_NODEV; + } + + // transmit stop condition + // leave with TWEA on for slave receiving + i2cSendStop(); + while( !(inb(TWCR) & BV(TWSTO)) ); + + // enable TWI interrupt + sbi(TWCR, TWIE); + + return retval; +} + +u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data) +{ + u08 retval = I2C_OK; + + // disable TWI interrupt + cbi(TWCR, TWIE); + + // send start condition + i2cSendStart(); + i2cWaitForComplete(); + + // send device address with read + i2cSendByte( deviceAddr | 0x01 ); + i2cWaitForComplete(); + + // check if device is present and live + if( inb(TWSR) == TW_MR_SLA_ACK) + { + // accept receive data and ack it + while(length > 1) + { + i2cReceiveByte(TRUE); + i2cWaitForComplete(); + *data++ = i2cGetReceivedByte(); + // decrement length + length--; + } + + // accept receive data and nack it (last-byte signal) + i2cReceiveByte(FALSE); + i2cWaitForComplete(); + *data++ = i2cGetReceivedByte(); + } + else + { + // device did not ACK it's address, + // data will not be transferred + // return error + retval = I2C_ERROR_NODEV; + } + + // transmit stop condition + // leave with TWEA on for slave receiving + i2cSendStop(); + + // enable TWI interrupt + sbi(TWCR, TWIE); + + return retval; +} +/* +void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata) +{ + // disable TWI interrupt + cbi(TWCR, TWIE); + + // send start condition + i2cSendStart(); + i2cWaitForComplete(); + + // if there's data to be sent, do it + if(sendlength) + { + // send device address with write + i2cSendByte( deviceAddr & 0xFE ); + i2cWaitForComplete(); + + // send data + while(sendlength) + { + i2cSendByte( *senddata++ ); + i2cWaitForComplete(); + sendlength--; + } + } + + // if there's data to be received, do it + if(receivelength) + { + // send repeated start condition + i2cSendStart(); + i2cWaitForComplete(); + + // send device address with read + i2cSendByte( deviceAddr | 0x01 ); + i2cWaitForComplete(); + + // accept receive data and ack it + while(receivelength > 1) + { + i2cReceiveByte(TRUE); + i2cWaitForComplete(); + *receivedata++ = i2cGetReceivedByte(); + // decrement length + receivelength--; + } + + // accept receive data and nack it (last-byte signal) + i2cReceiveByte(TRUE); + i2cWaitForComplete(); + *receivedata++ = i2cGetReceivedByte(); + } + + // transmit stop condition + // leave with TWEA on for slave receiving + i2cSendStop(); + while( !(inb(TWCR) & BV(TWSTO)) ); + + // enable TWI interrupt + sbi(TWCR, TWIE); +} +*/ + +//! I2C (TWI) interrupt service routine +SIGNAL(TWI_vect) +{ + // read status bits + u08 status = inb(TWSR) & TWSR_STATUS_MASK; + + switch(status) + { + // Master General + case TW_START: // 0x08: Sent start condition + case TW_REP_START: // 0x10: Sent repeated start condition + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: M->START\r\n"); + rprintfInit(uart1SendByte); + #endif + // send device address + i2cSendByte(I2cDeviceAddrRW); + break; + + // Master Transmitter & Receiver status codes + case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged + case TW_MT_DATA_ACK: // 0x28: Data acknowledged + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: MT->SLA_ACK or DATA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + if(I2cSendDataIndex < I2cSendDataLength) + { + // send data + i2cSendByte( I2cSendData[I2cSendDataIndex++] ); + } + else + { + // transmit stop condition, enable SLA ACK + i2cSendStop(); + // set state + I2cState = I2C_IDLE; + } + break; + case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: MR->DATA_NACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // store final received data byte + I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); + // continue to transmit STOP condition + case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged + case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged + case TW_MT_DATA_NACK: // 0x30: Data not acknowledged + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: MTR->SLA_NACK or MT->DATA_NACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // transmit stop condition, enable SLA ACK + i2cSendStop(); + // set state + I2cState = I2C_IDLE; + break; + case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost + //case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: MT->ARB_LOST\r\n"); + rprintfInit(uart1SendByte); + #endif + // release bus + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); + // set state + I2cState = I2C_IDLE; + // release bus and transmit start when bus is free + //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); + break; + case TW_MR_DATA_ACK: // 0x50: Data acknowledged + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: MR->DATA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // store received data byte + I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); + // fall-through to see if more bytes will be received + case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: MR->SLA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + if(I2cReceiveDataIndex < (I2cReceiveDataLength-1)) + // data byte will be received, reply with ACK (more bytes in transfer) + i2cReceiveByte(TRUE); + else + // data byte will be received, reply with NACK (final byte in transfer) + i2cReceiveByte(FALSE); + break; + + // Slave Receiver status codes + case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned + case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned + case TW_SR_GCALL_ACK: // 0x70: GCA+W has been received, ACK has been returned + case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: GCA+W has been received, ACK has been returned + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: SR->SLA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // we are being addressed as slave for writing (data will be received from master) + // set state + I2cState = I2C_SLAVE_RX; + // prepare buffer + I2cReceiveDataIndex = 0; + // receive data byte and return ACK + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); + break; + case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned + case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: SR->DATA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // get previously received data byte + I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR); + // check receive buffer status + if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE) + { + // receive data byte and return ACK + i2cReceiveByte(TRUE); + //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); + } + else + { + // receive data byte and return NACK + i2cReceiveByte(FALSE); + //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); + } + break; + case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned + case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: SR->DATA_NACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // receive data byte and return NACK + i2cReceiveByte(FALSE); + //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); + break; + case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: SR->SR_STOP\r\n"); + rprintfInit(uart1SendByte); + #endif + // switch to SR mode with SLA ACK + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); + // i2c receive is complete, call i2cSlaveReceive + if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData); + // set state + I2cState = I2C_IDLE; + break; + + // Slave Transmitter + case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned + case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: GCA+R has been received, ACK has been returned + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: ST->SLA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // we are being addressed as slave for reading (data must be transmitted back to master) + // set state + I2cState = I2C_SLAVE_TX; + // request data from application + if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData); + // reset data index + I2cSendDataIndex = 0; + // fall-through to transmit first data byte + case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: ST->DATA_ACK\r\n"); + rprintfInit(uart1SendByte); + #endif + // transmit data byte + outb(TWDR, I2cSendData[I2cSendDataIndex++]); + if(I2cSendDataIndex < I2cSendDataLength) + // expect ACK to data byte + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); + else + // expect NACK to data byte + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); + break; + case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received + case TW_ST_LAST_DATA: // 0xC8: + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: ST->DATA_NACK or LAST_DATA\r\n"); + rprintfInit(uart1SendByte); + #endif + // all done + // switch to open slave + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); + // set state + I2cState = I2C_IDLE; + break; + + // Misc + case TW_NO_INFO: // 0xF8: No relevant state information + // do nothing + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: NO_INFO\r\n"); + rprintfInit(uart1SendByte); + #endif + break; + case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition + #ifdef I2C_DEBUG + rprintfInit(uart1AddToTxBuffer); + rprintf("I2C: BUS_ERROR\r\n"); + rprintfInit(uart1SendByte); + #endif + // reset internal hardware and release bus + outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA)); + // set state + I2cState = I2C_IDLE; + break; + } +} + +eI2cStateType i2cGetState(void) +{ + return I2cState; +} + +void i2c_get_data(unsigned char length, unsigned char *data) +{ + unsigned char i; + + for(i=0;i<length;i++) + { + data[i]=I2cReceiveData[i]; + } +} + diff --git a/i2c.h b/i2c.h new file mode 100755 index 0000000000000000000000000000000000000000..21b68e3140e6bd8baec6378242161e66f26be2d1 --- /dev/null +++ b/i2c.h @@ -0,0 +1,178 @@ +/*! \file i2c.h \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */ +//***************************************************************************** +// +// File Name : 'i2c.h' +// Title : I2C interface using AVR Two-Wire Interface (TWI) hardware +// Author : Pascal Stang - Copyright (C) 2002-2003 +// Created : 2002.06.25 +// Revised : 2003.03.03 +// Version : 0.9 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +/// \ingroup driver_avr +/// \defgroup i2c I2C Serial Interface Function Library (i2c.c) +/// \code #include "i2c.h" \endcode +/// \par Overview +/// This library provides the high-level functions needed to use the I2C +/// serial interface supported by the hardware of several AVR processors. +/// The library is functional but has not been exhaustively tested yet and is +/// still expanding. Thanks to the standardization of the I2C protocol and +/// register access, the send and receive commands are everything you need to +/// talk to thousands of different I2C devices including: EEPROMS, Flash memory, +/// MP3 players, A/D and D/A converters, electronic potentiometers, etc. +/// +/// \par About I2C +/// I2C (pronounced "eye-squared-see") is a two-wire bidirectional +/// network designed for easy transfer of information between a wide variety +/// of intelligent devices. Many of the Atmel AVR series processors have +/// hardware support for transmitting and receiving using an I2C-type bus. +/// In addition to the AVRs, there are thousands of other parts made by +/// manufacturers like Philips, Maxim, National, TI, etc that use I2C as +/// their primary means of communication and control. Common device types +/// are A/D & D/A converters, temp sensors, intelligent battery monitors, +/// MP3 decoder chips, EEPROM chips, multiplexing switches, etc. +/// +/// I2C uses only two wires (SDA and SCL) to communicate bidirectionally +/// between devices. I2C is a multidrop network, meaning that you can have +/// several devices on a single bus. Because I2C uses a 7-bit number to +/// identify which device it wants to talk to, you cannot have more than +/// 127 devices on a single bus. +/// +/// I2C ordinarily requires two 4.7K pull-up resistors to power (one each on +/// SDA and SCL), but for small numbers of devices (maybe 1-4), it is enough +/// to activate the internal pull-up resistors in the AVR processor. To do +/// this, set the port pins, which correspond to the I2C pins SDA/SCL, high. +/// For example, on the mega163, sbi(PORTC, 0); sbi(PORTC, 1);. +/// +/// For complete information about I2C, see the Philips Semiconductor +/// website. They created I2C and have the largest family of devices that +/// work with I2C. +/// +/// \Note: Many manufacturers market I2C bus devices under a different or generic +/// bus name like "Two-Wire Interface". This is because Philips still holds +/// "I2C" as a trademark. For example, SMBus and SMBus devices are hardware +/// compatible and closely related to I2C. They can be directly connected +/// to an I2C bus along with other I2C devices are are generally accessed in +/// the same way as I2C devices. SMBus is often found on modern motherboards +/// for temp sensing and other low-level control tasks. +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef I2C_H +#define I2C_H + +#include "global.h" + +// include project-specific configuration +#include "i2cconf.h" + +// TWSR values (not bits) +// (taken from avr-libc twi.h - thank you Marek Michalkiewicz) +// Master +#define TW_START 0x08 +#define TW_REP_START 0x10 +// Master Transmitter +#define TW_MT_SLA_ACK 0x18 +#define TW_MT_SLA_NACK 0x20 +#define TW_MT_DATA_ACK 0x28 +#define TW_MT_DATA_NACK 0x30 +#define TW_MT_ARB_LOST 0x38 +// Master Receiver +#define TW_MR_ARB_LOST 0x38 +#define TW_MR_SLA_ACK 0x40 +#define TW_MR_SLA_NACK 0x48 +#define TW_MR_DATA_ACK 0x50 +#define TW_MR_DATA_NACK 0x58 +// Slave Transmitter +#define TW_ST_SLA_ACK 0xA8 +#define TW_ST_ARB_LOST_SLA_ACK 0xB0 +#define TW_ST_DATA_ACK 0xB8 +#define TW_ST_DATA_NACK 0xC0 +#define TW_ST_LAST_DATA 0xC8 +// Slave Receiver +#define TW_SR_SLA_ACK 0x60 +#define TW_SR_ARB_LOST_SLA_ACK 0x68 +#define TW_SR_GCALL_ACK 0x70 +#define TW_SR_ARB_LOST_GCALL_ACK 0x78 +#define TW_SR_DATA_ACK 0x80 +#define TW_SR_DATA_NACK 0x88 +#define TW_SR_GCALL_DATA_ACK 0x90 +#define TW_SR_GCALL_DATA_NACK 0x98 +#define TW_SR_STOP 0xA0 +// Misc +#define TW_NO_INFO 0xF8 +#define TW_BUS_ERROR 0x00 + +// defines and constants +#define TWCR_CMD_MASK 0x0F +#define TWSR_STATUS_MASK 0xF8 + +// return values +#define I2C_OK 0x00 +#define I2C_ERROR_NODEV 0x01 + +// types +typedef enum +{ + I2C_IDLE = 0, I2C_BUSY = 1, + I2C_MASTER_TX = 2, I2C_MASTER_RX = 3, + I2C_SLAVE_TX = 4, I2C_SLAVE_RX = 5 +} eI2cStateType; + +// functions + +//! Initialize I2C (TWI) interface +void i2cInit(void); + +//! Set the I2C transaction bitrate (in KHz) +void i2cSetBitrate(u16 bitrateKHz); + +// I2C setup and configurations commands +//! Set the local (AVR processor's) I2C device address +void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn); + +//! Set the user function which handles receiving (incoming) data as a slave +void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData)); +//! Set the user function which handles transmitting (outgoing) data as a slave +void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData)); + +// Low-level I2C transaction commands +//! Send an I2C start condition in Master mode +void i2cSendStart(void); +//! Send an I2C stop condition in Master mode +void i2cSendStop(void); +//! Wait for current I2C operation to complete +void i2cWaitForComplete(void); +//! Send an (address|R/W) combination or a data byte over I2C +void i2cSendByte(u08 data); +//! Receive a data byte over I2C +// ackFlag = TRUE if recevied data should be ACK'ed +// ackFlag = FALSE if recevied data should be NACK'ed +void i2cReceiveByte(u08 ackFlag); +//! Pick up the data that was received with i2cReceiveByte() +u08 i2cGetReceivedByte(void); +//! Get current I2c bus status from TWSR +u08 i2cGetStatus(void); + +// high-level I2C transaction commands + +//! send I2C data to a device on the bus +void i2cMasterSend(u08 deviceAddr, u08 length, u08 *data); +//! receive I2C data from a device on the bus +void i2cMasterReceive(u08 deviceAddr, u08 length);//, u08* data); + +//! send I2C data to a device on the bus (non-interrupt based) +u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data); +//! receive I2C data from a device on the bus (non-interrupt based) +u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data); + +//! Get the current high-level state of the I2C interface +eI2cStateType i2cGetState(void); + +void i2c_get_data(unsigned char length, unsigned char *data); + +#endif diff --git a/i2cconf.h b/i2cconf.h new file mode 100755 index 0000000000000000000000000000000000000000..81521675be5df58f2cd4db2520c3ae661bee5040 --- /dev/null +++ b/i2cconf.h @@ -0,0 +1,28 @@ +/*! \file i2cconf.h \brief I2C (TWI) interface configuration. */ +//***************************************************************************** +// +// File Name : 'i2cconf.h' +// Title : I2C (TWI) interface configuration +// Author : Pascal Stang - Copyright (C) 2002-2003 +// Created : 2002.06.25 +// Revised : 2003.03.02 +// Version : 0.7 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef I2CCONF_H +#define I2CCONF_H + +// define I2C data buffer sizes +// These buffers are used in interrupt-driven Master sending and receiving, +// and in slave sending and receiving. They must be large enough to store +// the largest I2C packet you expect to send and receive, respectively. +#define I2C_SEND_DATA_BUFFER_SIZE 0x20 +#define I2C_RECEIVE_DATA_BUFFER_SIZE 0x20 + +#endif diff --git a/include/adc.h b/include/adc.h deleted file mode 100644 index c79e8cb1219993819b5b4488feccf52858900f63..0000000000000000000000000000000000000000 --- a/include/adc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _ADC_H -#define _ADC_H - -#include <avr/io.h> -#include <avr/interrupt.h> - -void adc_init(void); -void adc_start(void); -void adc_stop(void); -void adc_set_num_samples(uint8_t num); -void adc_set_sample_period(uint8_t time_ms); -void adc_loop(void); - -#endif diff --git a/include/compass.h b/include/compass.h deleted file mode 100644 index 8a739de1abdb505c3def20e798cbe0da0bcb778e..0000000000000000000000000000000000000000 --- a/include/compass.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _COMPASS_H -#define _COMPASS_H - -#include <avr/io.h> -#include <avr/interrupt.h> - -// compass address -#define COMPASS_ADDR 0x42 - -// compass commands -#define COMPASS_HEADING 0x41 -#define COMPASS_START_CAL 0x43 -#define COMPASS_STOP_CAL 0x45 - -void compass_init(void); -void compass_start(void); -void compass_stop(void); -void compass_start_calibration(void); -void compass_stop_calibration(void); -void compass_set_num_samples(uint8_t num); -void compass_loop(void); - -#endif diff --git a/include/dac.h b/include/dac.h deleted file mode 100644 index 45b7f3b897eb7ae5c68c80ea925f7b7fb6c8afeb..0000000000000000000000000000000000000000 --- a/include/dac.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _DAC_H -#define _DAC_H - -#include <avr/io.h> -#include <avr/interrupt.h> - -typedef enum {dac0=0,dac1=1} dac_ch_t; - -void dac_init(void); -void dac_start(void); -void dac_stop(void); -void dac_enable_channel(dac_ch_t ch); -void dac_disable_channel(dac_ch_t ch); -void dac_set_voltage(dac_ch_t ch,uint16_t voltage); - -#endif diff --git a/include/dyn_common.h b/include/dyn_common.h deleted file mode 100644 index 72a1d88b6af832cdedef82e3592c680ebc0288f6..0000000000000000000000000000000000000000 --- a/include/dyn_common.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _DYN_COMMON_H -#define _DYN_COMMON_H - -#include <avr/io.h> -#include <avr/interrupt.h> - -// Instruction identifiers -#define INST_PING 0x01 -#define INST_READ 0x02 -#define INST_WRITE 0x03 -#define INST_REG_WRITE 0x04 -#define INST_ACTION 0x05 -#define INST_RESET 0x06 -#define INST_SYNC_READ 0x82 -#define INST_SYNC_WRITE 0x83 -#define INST_BULK_READ 0x92 -#define INST_BULK_WRITE 0x93 - -// bus errors -#define INSTRUCTION_ERROR 0x40 -#define OVERLOAD_ERROR 0x20 -#define CHECKSUM_ERROR 0x10 -#define RANGE_ERROR 0x08 -#define OVERHEATING_ERROR 0x04 -#define ANGLE_LIMIT_ERROR 0x02 -#define VOLTAGE_ERROR 0x01 -#define NO_ERROR 0x00 - -uint8_t do_write(uint8_t address,uint8_t length,uint8_t *data); -uint8_t do_read(uint8_t address,uint8_t length,uint8_t **data); - -#endif diff --git a/include/dyn_slave_diff.h b/include/dyn_slave_diff.h deleted file mode 100644 index c3978a5ba0815b197def619daf743c51f98d7b16..0000000000000000000000000000000000000000 --- a/include/dyn_slave_diff.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DYN_SLAVE_DIFF_H -#define DYN_SLAVE_DIFF_H - -#include <avr/interrupt.h> -#include <avr/io.h> -#include "dyn_common.h" - -void dyn_slave_diff_init(uint8_t baudrate,uint8_t id); -void dyn_slave_diff_set_baudrate(uint8_t baudrate); -void dyn_slave_diff_set_id(uint8_t id); -void dyn_slave_diff_loop(void); -void dyn_slave_diff_set_error(uint8_t error); -void dyn_slave_diff_clear_error(void); - -#endif diff --git a/include/dyn_slave_se.h b/include/dyn_slave_se.h deleted file mode 100644 index 3c29692e5708f7eb6934a74ccd409d6cef146158..0000000000000000000000000000000000000000 --- a/include/dyn_slave_se.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DYN_SLAVE_SE_H -#define DYN_SLAVE_SE_H - -#include <avr/interrupt.h> -#include <avr/io.h> -#include "dyn_common.h" - -void dyn_slave_se_init(uint8_t baudrate,uint8_t id); -void dyn_slave_se_set_baudrate(uint8_t baudrate); -void dyn_slave_se_set_id(uint8_t id); -void dyn_slave_se_loop(void); -void dyn_slave_se_set_error(uint8_t error); -void dyn_slave_se_clear_error(void); - -#endif diff --git a/include/i2c.h b/include/i2c.h deleted file mode 100644 index 923ceb8efd72f4a1dd63512abf21e081d8a4a75f..0000000000000000000000000000000000000000 --- a/include/i2c.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef I2C_H -#define I2C_H - -// TWSR values (not bits) -// (taken from avr-libc twi.h - thank you Marek Michalkiewicz) -// Master -#define TW_START 0x08 -#define TW_REP_START 0x10 -// Master Transmitter -#define TW_MT_SLA_ACK 0x18 -#define TW_MT_SLA_NACK 0x20 -#define TW_MT_DATA_ACK 0x28 -#define TW_MT_DATA_NACK 0x30 -#define TW_MT_ARB_LOST 0x38 -// Master Receiver -#define TW_MR_ARB_LOST 0x38 -#define TW_MR_SLA_ACK 0x40 -#define TW_MR_SLA_NACK 0x48 -#define TW_MR_DATA_ACK 0x50 -#define TW_MR_DATA_NACK 0x58 -// Misc -#define TW_NO_INFO 0xF8 -#define TW_BUS_ERROR 0x00 - -// defines and constants -#define TWCR_CMD_MASK 0x0F -#define TWSR_STATUS_MASK 0xF8 - -// return values -#define I2C_OK 0x00 -#define I2C_ERROR_NODEV 0x01 - -// types -typedef enum {I2C_IDLE=0,I2C_BUSY=1,I2C_MASTER_TX=2,I2C_MASTER_RX=3} i2c_states_t; - -/* public functions */ -void i2c_init(uint16_t bitrate_khz); -void i2c_set_bitrate(uint16_t bitrate_khz); -void i2c_master_send(uint8_t deviceAddr, uint8_t length, uint8_t *data); -void i2c_master_receive(uint8_t deviceAddr, uint8_t length); -void i2c_get_data(unsigned char length, unsigned char *data); -i2c_states_t i2c_get_state(void); - -#endif diff --git a/include/mem.h b/include/mem.h deleted file mode 100644 index 54b80f57597cd23ac26771d68bf74139cbc6cfb6..0000000000000000000000000000000000000000 --- a/include/mem.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _MEM_H -#define _MEM_H - -#include <avr/io.h> -#include "memory_map.h" - -extern uint8_t ram_data[RAM_SIZE]; - -void ram_init(void); -uint8_t ram_read(uint8_t address, uint8_t length, uint8_t **data); -uint8_t ram_write(uint8_t address, uint8_t length, uint8_t *data); - -#endif diff --git a/include/memory_map.h b/include/memory_map.h deleted file mode 100644 index 015a029fc125120dfa4b51a8fcda2df29750402f..0000000000000000000000000000000000000000 --- a/include/memory_map.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef _MEMORY_MAP_H -#define _MEMORY_MAP_H - -// Register Id EEPROM - declared in dynamixel -#define Model_Number_L 0X00 //0 - 0X0C R - Lowest byte of model number -#define Model_Number_H 0X01 //1 - 0X00 R - Highest byte of model number -#define Version_Firmware 0X02 //2 - 0X00 R - Information on the version of firmware -#define ID 0X03 //3 - 0X03 R/W - ID of Dynamixel -#define Baud_Rate 0X04 //4 - 0X01 R/W - Baud Rate of Dynamixel -#define Return_Delay_Time 0X05 //5 - 0XFA R/W - Return Delay Time (value*2us) currently not implemented -#define Status_Return_Level 0X10 //16 - 0x10 R/W - Level os reply information -// EEPROM end at 0x1F -// RAM starts at 0x20 -#define ADC_CONTROL 0x20 //32 - 0x20 R/W ADC control bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // running stop start -#define ADC_NUM_SAMPLES 0x21 //33 - 0x21 R/W Number of sample to average -#define ADC_SAMPLE_PERIOD 0x22 //33 - 0x22 R/W ADC sample period in ms -#define GPIO0_config 0x30 //48 - 0x30 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO0_data 0x31 //49 - 0x31 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO1_config 0x32 //50 - 0x32 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO1_data 0x33 //51 - 0x33 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO2_config 0x34 //52 - 0x34 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO2_data 0x35 //53 - 0x35 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO3_config 0x36 //54 - 0x36 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO3_data 0x37 //55 - 0x37 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO4_config 0x38 //56 - 0x38 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO4_data 0x39 //57 - 0x39 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO5_config 0x3A //58 - 0x3A R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO5_data 0x3B //59 - 0x3B R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO6_config 0x3C //60 - 0x3C R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO6_data 0x3D //61 - 0x3D R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO7_config 0x3E //62 - 0x3E R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO7_data 0x3F //63 - 0x3F R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO8_config 0x40 //64 - 0x40 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO8_data 0x41 //65 - 0x41 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO9_config 0x41 //66 - 0x42 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO9_data 0x43 //67 - 0x43 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO10_config 0x44 //68 - 0x44 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO10_data 0x45 //69 - 0x45 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO11_config 0x46 //70 - 0x46 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO11_data 0x47 //71 - 0x47 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO12_config 0x48 //72 - 0x48 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO12_data 0x49 //73 - 0x49 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO13_config 0x4A //74 - 0x4A R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO13_data 0x4B //75 - 0x4B R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO14_config 0x4C //76 - 0x4C R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO14_data 0x4D //77 - 0x4D R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO15_config 0x4E //78 - 0x4E R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO15_data 0x4F //79 - 0x4F R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO16_config 0x50 //80 - 0x50 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO16_data 0x51 //81 - 0x51 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO17_config 0x52 //82 - 0x52 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO17_data 0x53 //83 - 0x53 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define GPIO18_config 0x54 //84 - 0x54 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // mode (0 -> input, 1 -> output) -#define GPIO18_data 0x55 //85 - 0x55 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current input value (input mode) - // output value (output mode) -#define LED 0x56 //86 - 0x56 R/W Auxiliary LED bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current value -#define SWITCHES 0x57 //87 - 0x57 R Auxiliary Switches bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // current switches value -#define ADC_CHANNEL0_L 0x58 -#define ADC_CHANNEL0_H 0x59 -#define ADC_CHANNEL1_L 0x5A -#define ADC_CHANNEL1_H 0x5B -#define ADC_CHANNEL2_L 0x5C -#define ADC_CHANNEL2_H 0x5D -#define ADC_CHANNEL3_L 0x5E -#define ADC_CHANNEL3_H 0x5F -#define ADC_CHANNEL4_L 0x60 -#define ADC_CHANNEL4_H 0x61 -#define ADC_CHANNEL5_L 0x62 -#define ADC_CHANNEL5_H 0x63 -#define ADC_CHANNEL6_L 0x64 -#define ADC_CHANNEL6_H 0x65 -#define ADC_CHANNEL7_L 0x66 -#define ADC_CHANNEL7_H 0x67 -#define ADC_AVG_CHANNEL0_L 0x68 -#define ADC_AVG_CHANNEL0_H 0x69 -#define ADC_AVG_CHANNEL1_L 0x6A -#define ADC_AVG_CHANNEL1_H 0x6B -#define ADC_AVG_CHANNEL2_L 0x6C -#define ADC_AVG_CHANNEL2_H 0x6D -#define ADC_AVG_CHANNEL3_L 0x6E -#define ADC_AVG_CHANNEL3_H 0x6F -#define ADC_AVG_CHANNEL4_L 0x70 -#define ADC_AVG_CHANNEL4_H 0x71 -#define ADC_AVG_CHANNEL5_L 0x72 -#define ADC_AVG_CHANNEL5_H 0x73 -#define ADC_AVG_CHANNEL6_L 0x74 -#define ADC_AVG_CHANNEL6_H 0x75 -#define ADC_AVG_CHANNEL7_L 0x76 -#define ADC_AVG_CHANNEL7_H 0x77 -#define PWM_CONTROL 0x78 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // ch3_enabled ch2_enabled ch1_enabled ch0_enabled running stop start -#define PWM_ENABLE 0x79 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // dis_ch3 dis_ch2 dis_ch1 dis_ch0 en_ch3 en_ch2 en_ch1 en_ch0 -#define PWM_FREQ_L 0x7A -#define PWM_FREQ_H 0x7B -#define PWM_CH0_DUTY 0x7C -#define PWM_CH1_DUTY 0x7D -#define PWM_CH2_DUTY 0x7E -#define PWM_CH3_DUTY 0x7F -#define DAC_CONTROL 0x80 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // ch1_enabled ch0_enabled running stop start -#define DAC_ENABLE 0x81 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 -#define DAC_CH0_VOLTAGE_L 0x82 // dis_ch1 dis_ch0 en_ch1 en_ch0 -#define DAC_CH0_VOLTAGE_H 0x83 -#define DAC_CH1_VOLTAGE_L 0x84 -#define DAC_CH1_VOLTAGE_H 0x85 -#define COMPASS_CONTROL 0x86 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // calibrating running stop cal start cal stop start -#define COMPASS_HEADING_VAL_L 0x87 -#define COMPASS_HEADING_VAL_H 0x88 -#define COMPASS_AVG_HEADING_VAL_L 0x89 -#define COMPASS_AVG_HEADING_VAL_H 0x8A -#define COMPASS_NUM_SAMPLES 0x8B -#define UART_TTL_CONTROL 0x8C // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // data_available sending running send stop start -#define UART_TTL_TX_DATA 0x8D -#define UART_TTL_RX_DATA 0x8E -#define UART_TTL_BAUDRATE_L 0x8F -#define UART_TTL_BAUDRATE_H 0x90 -#define UART_USB_CONTROL 0x91 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // data_available sending running send stop start -#define UART_USB_TX_DATA 0x92 -#define UART_USB_RX_DATA 0x93 -#define UART_USB_BAUDRATE_L 0x94 -#define UART_USB_BAUDRATE_H 0x95 - -#define RAM_SIZE 150 - -#endif diff --git a/include/ports.h b/include/ports.h deleted file mode 100644 index ed792f76d99de785917880a769df7b4531cacd24..0000000000000000000000000000000000000000 --- a/include/ports.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _PORTS_H -#define _PORTS_H - -#define NUM_GPIO 19 - -#define INPUT 0x00 -#define OUTPUT 0x01 - -typedef struct -{ - volatile uint8_t *dir_reg; - volatile uint8_t *write_reg; - volatile uint8_t *read_reg; - uint8_t bit; -}TGPIO; - -void init_ports(void); -void config_port(uint8_t port_id,uint8_t dir); -uint8_t get_port_config(uint8_t port_id); -void set_port(uint8_t port_id); -void clear_port(uint8_t port_id); -uint8_t read_port(uint8_t port_id); -void set_led(void); -void clear_led(void); -void toggle_led(void); -uint8_t get_selector_value(void); - -#endif diff --git a/include/pwm.h b/include/pwm.h deleted file mode 100644 index f63ca7bdfbf3d02fb13793c7221b14f869ae5db7..0000000000000000000000000000000000000000 --- a/include/pwm.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _PWM_H -#define _PWM_H - -#include <avr/io.h> -#include <avr/interrupt.h> - -typedef enum {pwm0=0,pwm1=1,pwm2=2,pwm3=3} pwm_id_t; - -void pwm_init(void); -void pwm_start(void); -void pwm_stop(void); -void pwm_enable_ch(pwm_id_t id); -void pwm_disable_ch(pwm_id_t id); -void pwm_set_frequency(uint16_t freq_hz); -void pwm_set_duty_cycle(pwm_id_t id,uint8_t duty); - -#endif diff --git a/include/uart_ttl.h b/include/uart_ttl.h deleted file mode 100644 index cd9d6131985a79641fcc6ea6a627a596da5c83c0..0000000000000000000000000000000000000000 --- a/include/uart_ttl.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef UART_TTL_H -#define UART_TTL_H - -/* public functions */ -void uart_ttl_init(void); -void uart_ttl_start(void); -void uart_ttl_stop(void); -void uart_ttl_set_baudrate(uint32_t baudrate); -void uart_ttl_send_byte(uint8_t data); -uint8_t uart_ttl_is_sending(void); -uint8_t uart_ttl_receive_byte(uint8_t* data); -uint8_t uart_ttl_is_data_available(void); - -#endif diff --git a/include/uart_usb.h b/include/uart_usb.h deleted file mode 100644 index 069b63f085cb707d36864ffe17fd6006f15166d3..0000000000000000000000000000000000000000 --- a/include/uart_usb.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef UART_USB_H -#define UART_USB_H - -/* public functions */ -void uart_usb_init(void); -void uart_usb_start(void); -void uart_usb_stop(void); -void uart_usb_set_baudrate(uint32_t baudrate); -void uart_usb_send_byte(uint8_t data); -uint8_t uart_usb_is_sending(void); -uint8_t uart_usb_receive_byte(uint8_t* data); -uint8_t uart_usb_is_data_available(void); - -#endif diff --git a/legacy/expansion_board.hex b/legacy/expansion_board.hex new file mode 100755 index 0000000000000000000000000000000000000000..dfb655c8d9945a4079a171cb11b2703ca2961a63 --- /dev/null +++ b/legacy/expansion_board.hex @@ -0,0 +1,614 @@ +:100000000C9454000C9473000C9473000C947300C3 +:100010000C9473000C9473000C9473000C94730094 +:100020000C9473000C94A2090C9406080C947109AA +:100030000C94DE080C940F090C94D5070C94AD08B1 +:100040000C9472070C9473000C946B040C94730062 +:100050000C9473000C94B20E0C9473000C94730007 +:100060000C9440090C94660A0C94D3090C94040A6D +:100070000C94350A0C947C080C9496040C94730030 +:100080000C9473000C942D0D0C947300000001006F +:1000900008004000000100040000010008002000EA +:1000A000400080000001000411241FBECFEFD0E10A +:1000B000DEBFCDBF11E0A0E0B1E0EAEBF5E200E089 +:1000C0000BBF02C007900D92AE38B107D9F714E00C +:1000D000AEE8B1E001C01D92A736B107E1F70E947A +:1000E00075000C94DB120C9400002F923F924F92FB +:1000F0005F926F927F928F929F92AF92BF92CF92B8 +:10010000DF92EF92FF920F931F93DF93CF93CDB7C0 +:10011000DEB7C958D0400FB6F894DEBF0FBECDBFD2 +:100120000E949B110E941E03CE0104960E94490367 +:100130000E94720E0E94040C0E942E0B0E94C304A7 +:1001400085E00E9425058FE782BF80E064E872E0C9 +:100150000E9470050E94FF0482E00E94340580E442 +:100160009CE90E94F1060E94DC0481E00E942A05BD +:1001700080E89EE30E946406789413E0412E512C9F +:100180004C0E5D1EB2E02B2E312C2C0E3D1EA6E037 +:10019000AA2EB12CAC0EBD1EF5E06F2E712C6C0E8C +:1001A0007D1EE8E08E2E912C8C0E9D1E81E0BE01FE +:1001B0006F5F7F4FA20191018E01065F1F4F0E946A +:1001C000A903823021F481E06C8140E197C188234A +:1001D00069F739816C81361749F78B81823041F09C +:1001E000833009F494C0813009F781E0632F82C124 +:1001F0009A859830B0F48A81823059F4892F0E9410 +:10020000540F9987888781E06C8140E022E0840167 +:1002100006C081E0632F40E420E000E010E00E948F +:100220005F039A85292F2850283078F48A818230FC +:1002300009F06AC0822F0E94640F9987888781E045 +:100240006C8140E022E084015CC1903139F48A8104 +:10025000823009F059C00E94220B08C0913169F424 +:100260008A81823009F050C00E94280B8E839F83C0 +:1002700081E06C8140E022E045C0923171F48A81D6 +:10028000823009F041C080913502882321F48091A9 +:100290003402882391F181E023C0913251F48A81A4 +:1002A000823091F5C3010E9406118E838D818F8368 +:1002B000DFCF892F80538632A8F48A81823021F5DE +:1002C000892F90E0C0979C0135952795C09680FDB9 +:1002D00004C0822F0E94E11103C0822F0E943812B5 +:1002E0008E830CC0913631F0933621F0953611F0A3 +:1002F000973651F48A81823039F41E8281E06C8114 +:1003000040E021E08501FDC081E06C81F6C02A85D6 +:10031000223161F48A81823091F5809135028823FF +:1003200019F43FEF3093350281E0E4C0203239F414 +:100330008A81823021F58B850E946910D9C0822F75 +:1003400080538632F8F48A818230C9F430E0C901E2 +:10035000C09795958795982F20FD06C06B850E94C4 +:10036000AB118AB38E83C4C08B85882321F4892F77 +:100370000E941C12BDC0892F0E940112B9C081E0E9 +:10038000632FBBC0203631F0223621F0243611F025 +:10039000263661F58A81833009F0AEC0FC84EE24F4 +:1003A0008B85A701480F511DCA015CE9813495076F +:1003B00010F080E49CE930E02056304035952795D8 +:1003C000213059F0213030F0223051F0233009F043 +:1003D0008FC009C00E9463078BC00E94680788C055 +:1003E0000E946D0785C00E94C40682C0213631F08C +:1003F000233621F0253611F02736B9F58A8182306F +:1004000009F07AC030E021563040359527952130EB +:1004100089F0213030F02230B1F0233009F068C08B +:100420001BC08B85882319F40E94480761C00E9475 +:100430002D075EC08B85882319F40E94510758C090 +:100440000E94360755C08B85882319F40E945A07ED +:100450004FC00E943F074CC08B85882319F40E942F +:10046000B70646C00E94A20643C0203711F02237CB +:1004700001F58A81833009F03FC0DC84CC248B8570 +:10048000A601480F511D8EE34138580710F040E88F +:100490005EE3822F90E08057904095958795882362 +:1004A00021F4CA010E94BE0623C0CA010E94C106EF +:1004B0001FC0213711F02337F9F48A818230E1F42B +:1004C000822F90E081579040959587959B85882352 +:1004D00041F4992319F40E94A9060AC00E949406C7 +:1004E00007C0992319F40E94B00602C00E949B061F +:1004F00081E06C8140E002C081E040E420E000E067 +:1005000010E00E945F0352CE78948FE782BF0E9472 +:100510004E0B80918E0190918F01019690938F01E7 +:1005200080938E01885E934049F40A9B02C01A981A +:1005300001C01A9A10928F0110928E01089588239B +:1005400021F080919B00807208958BB18072089594 +:10055000F894882319F080913A0302C08091360202 +:10056000882311F08FEF01C080E0789408958823EC +:1005700031F080919B00806480939B0008955E9A87 +:100580000895882321F080919B00807408958BB199 +:1005900080740895982F882331F080919B008064A7 +:1005A00080939B0001C05E9A992319F080919B0073 +:1005B00001C08BB18072C1F3992319F060939C0044 +:1005C00008956CB908951F93CF93DF93182FEB0113 +:1005D000812F0E94A8028823D9F3F8941123A9F04F +:1005E000E0913903F0E0E754FD4F808188838091EA +:1005F000390390E001968F77907080933903809152 +:100600003A03815080933A0314C0E091B802F0E0BD +:10061000E95CFD4F808188838091B80290E001966B +:100620008F7790708093B8028091360281508093CA +:1006300036027894DF91CF911F91089581B3886C31 +:1006400081BB8A98E4E6F0E08081877E808396987B +:10065000979A1BB81092900019B898E99AB986E851 +:100660008093950010929B00109298001092990030 +:1006700090939A0080939D001092390310923B034F +:1006800010923A031092B8021092B70210923602FA +:100690000895FC01809163008871883049F08930A9 +:1006A00058F0803119F0883139F404C080E805C071 +:1006B00080EC03C08DEF01C085E480830895CF9264 +:1006C000DF92EF92FF920F931F93CF93DF93D82E79 +:1006D000F62EE42EC22E9798969A6FEF0E94CA02C9 +:1006E0008D2D6FEF0E94CA028D2D6F2D0E94CA02C0 +:1006F0006C2D6E5F8D2D0E94CA028D2D6E2D0E9475 +:10070000CA0282E0F80EFE0CFC0CE80110E007C003 +:100710008D2D68810E94CA028991F80E1F5F1C15F9 +:10072000B8F3F0948D2D6F2D0E94CA02DD2019F0D0 +:1007300080919B0001C08BB18074C1F39698979A09 +:10074000DF91CF911F910F91FF90EF90DF90CF90AD +:1007500008956F927F928F929F92AF92BF92DF9295 +:10076000EF92FF920F931F93DF93CF930F92CDB72A +:10077000DEB7D82E3B014A0159010E94A802882306 +:1007800009F499C0E090900183E0E81609F440C0B4 +:100790008E1530F0E1E0EE16E1F0EE1560F10CC0E0 +:1007A000F5E0EF1609F45AC0EF1608F440C086E0F1 +:1007B000E81609F080C06FC08D2DBE016F5F7F4FBE +:1007C0000E94E30289818F3F99F481E08093900138 +:1007D00073C08D2DBE016F5F7F4F0E94E302898140 +:1007E0008F3F31F482E0809390011092920163C0B8 +:1007F0001092900160C08D2DB3010E94E3028091A0 +:100800009201F3019081890F8093920183E03DC0B2 +:100810008D2DB5010E94E302F50180819091920136 +:10082000980F909392018250808384E02EC08D2D8A +:10083000B4010E94E30280919201F4019081890F3A +:1008400080939201F5018081882311F486E001C034 +:1008500085E080939001109291012DC0F09091015C +:100860000F0D111D8D2DB8010E94E30280919201A0 +:10087000F8019081890F80939201F394F092910195 +:10088000F5018081F81621F486E08093900113C071 +:10089000E092900110C08D2DBE016F5F7F4F0E94CE +:1008A000E302809192019981890F809392011092C5 +:1008B000900180E001C081E00F90CF91DF911F9106 +:1008C0000F91FF90EF90DF90BF90AF909F908F902F +:1008D0007F906F9008951F920F920FB60F920BB6F4 +:1008E0000F9211248F939F93EF93FF938091B70200 +:1008F0009CB1E7E3F2E0E80FF11D90838091B7022D +:1009000090E001968F7790708093B70280913602C5 +:100910008F5F80933602FF91EF919F918F910F909F +:100920000BBE0F900FBE0F901F9018951F920F9245 +:100930000FB60F920BB60F9211248F939F93EF93E4 +:10094000FF9380913B0390919C00E9EBF2E0E80F6C +:10095000F11D908380913B0390E001968F7790701A +:1009600080933B0380913A038F5F80933A03FF911A +:10097000EF919F918F910F900BBE0F900FBE0F9034 +:100980001F901895089583B7887F836083BF12BE38 +:1009900087B7816087BF10923C0310923D0310928D +:1009A0003E0310923F0310924C0310924D0310929D +:1009B0004E0310924F0308958EB5887F83608EBDDD +:1009C0001DBC1CBC87B7846087BF089585B5887F30 +:1009D000826085BD14BC87B7806487BF10924803CE +:1009E0001092490310924A0310924B031092400355 +:1009F0001092410310924203109243030895EAE8D3 +:100A0000F0E08081887F836080831092890010925B +:100A10008800EDE7F0E0808184608083089580E0C5 +:100A200090E0FC01EE0FFF1FED56FE4F1182108289 +:100A300001968E309105A9F70E94C3040E94DC0440 +:100A40000E94E6040E94FF04089593B7987F982BB4 +:100A500093BF08959EB5987F982B9EBD089595B538 +:100A6000987F982B95BD0895EAE8F0E09081987FF3 +:100A7000982B9083089583B7E82FF0E0E770F0702B +:100A8000EE0FFF1FE457FF4F25913491C9010895E0 +:100A90008EB5E82FF0E0E770F070EE0FFF1FE4571F +:100AA000FF4F25913491C901089585B5E82FF0E0F5 +:100AB000E770F070EE0FFF1FE457FF4F2591349160 +:100AC000C901089580918A00E82FF0E0E770F07086 +:100AD000EE0FFF1FE457FF4F25913491C901089590 +:100AE0008E3040F4E82FF0E0EE0FFF1FED56FE4F82 +:100AF0007183608308958E3040F4E82FF0E0EE0FAC +:100B0000FF1FED56FE4F118210820895EF92FF9263 +:100B10000F931F93CF93DF93EC0114B5109244030E +:100B200010924503109246031092470385B5E82FB3 +:100B3000F0E0E770F070EE0FFF1FE457FF4F2591D4 +:100B4000349140E050E060E074E284EF90E00E9475 +:100B5000C012B901CA01693B2DE8720726E082077D +:100B600020E09207A0F437E2C131D30780F49E0160 +:100B700040E050E00E94581228EE33E040E050E0A0 +:100B80000E949E12C901DA01BC01CD0121C028EEEC +:100B900033E040E050E00E949E12CA01B9019E017C +:100BA00040E050E00E94581213C08091440390919D +:100BB0004503A0914603B091470385B7837E85BF67 +:100BC00085B7806285BF889585B78F7D85BF08C052 +:100BD0009B01AC01210F311D411D511D79018A017D +:100BE00020914403309145034091460350914703BF +:100BF00084B590E0A0E0B0E0542F432F322F22279D +:100C0000822B932BA42BB52B8E159F05A007B10724 +:100C100060F2DF91CF911F910F91FF90EF900895B7 +:100C200010923C0310923D0310923E0310923F033A +:100C300010924C0310924D0310924E0310924F03EA +:100C4000089520913C0330913D0340913E03509123 +:100C50003F03B901CA010895109248031092490355 +:100C600010924A0310924B031092400310924103DA +:100C7000109242031092430308952091480330914B +:100C8000490340914A0350914B03B901CA010895A9 +:100C9000893031F48FB582608FBD8FB58E7F0AC0E9 +:100CA0008A3019F48FB5826002C08FB58D7F8FBDF9 +:100CB0008FB581608FBD1BBC1ABC19BC18BC1092CB +:100CC00079001092780008952FB52E7F2FBD2FB593 +:100CD00022602FBD2EB528602EBD2EB520612EBD01 +:100CE00097BD86BD1BBC1ABC19BC18BC10927900FC +:100CF0001092780008958FB58D7F8FBD8FB58E7F50 +:100D00008FBD8FB58F778FBD8FB58F7B8FBD8FB523 +:100D10008F7D8FBD8FB58F7E8FBD8FB5877F8FBD48 +:100D20008FB58B7F8FBD08958FB580688FBD8FB5D0 +:100D30008F7B8FBD08958FB580628FBD8FB58F7EFD +:100D40008FBD08958FB588608FBD8FB58B7F8FBDA8 +:100D500008958FB58F778FBD8FB58F7B8FBD089529 +:100D60008FB58F7D8FBD8FB58F7E8FBD08958FB569 +:100D7000877F8FBD8FB58B7F8FBD08959BBD8ABD4B +:100D8000089599BD88BD0895909379008093780067 +:100D90000895893049F480918B00826080938B00A4 +:100DA00080918B008E7F0EC08A3021F480918B0061 +:100DB000826003C080918B008D7F80938B00809137 +:100DC0008B00816080938B001092870010928600C8 +:100DD000109285001092840010928300109282007D +:100DE0000895EBE8F0E020812E7F208320812260AF +:100DF0002083EAE8F0E020812860208320812061C0 +:100E0000208390938100809380001092870010923D +:100E10008600109285001092840010928300109238 +:100E200082000895EBE8F0E080818D7F80838081EF +:100E30008E7F808380818F77808380818F7B80838A +:100E400080818F7D808380818F7E80838081877F7A +:100E5000808380818B7F80830895EBE8F0E0808140 +:100E60008068808380818F7B80830895EBE8F0E049 +:100E700080818062808380818F7E80830895EBE80B +:100E8000F0E080818860808380818B7F80830895FB +:100E9000EBE8F0E080818F77808380818F7B808397 +:100EA0000895EBE8F0E080818F7D808380818F7EE4 +:100EB00080830895EBE8F0E08081877F80838081E4 +:100EC0008B7F808308959093870080938600089598 +:100ED000909385008093840008959093830080937D +:100EE000820008951F920F920FB60F920BB60F92C9 +:100EF00011242F933F934F935F936F937F938F931F +:100F00009F93AF93BF93EF93FF9380913C03909196 +:100F10003D03A0913E03B0913F030196A11DB11D79 +:100F200080933C0390933D03A0933E03B0933F0313 +:100F300080913C0390913D03A0913E03B0913F030B +:100F40000097A105B10599F480914C0390914D0350 +:100F5000A0914E03B0914F030196A11DB11D809346 +:100F60004C0390934D03A0934E03B0934F03809195 +:100F7000930190919401892B29F0E0919301F091D4 +:100F800094010995FF91EF91BF91AF919F918F913E +:100F90007F916F915F914F913F912F910F900BBE79 +:100FA0000F900FBE0F901F9018951F920F920FB6C3 +:100FB0000F920BB60F9211242F933F934F935F9391 +:100FC0006F937F938F939F93AF93BF93EF93FF9311 +:100FD0008091970190919801892B29F0E0919701D8 +:100FE000F09198010995FF91EF91BF91AF919F9179 +:100FF0008F917F916F915F914F913F912F910F90C2 +:101000000BBE0F900FBE0F901F9018951F920F925E +:101010000FB60F920BB60F9211242F933F934F935D +:101020005F936F937F938F939F93AF93BF93EF9350 +:10103000FF938091480390914903A0914A03B09196 +:101040004B030196A11DB11D809348039093490362 +:10105000A0934A03B0934B038091480390914903B6 +:10106000A0914A03B0914B030097A105B10599F4F3 +:101070008091400390914103A0914203B0914303BA +:101080000196A11DB11D8093400390934103A0934D +:101090004203B09343038091440390914503A09190 +:1010A0004603B09147030196A11DB11D80934403EF +:1010B00090934503A0934603B09347038091A10109 +:1010C0009091A201892B29F0E091A101F091A20158 +:1010D0000995FF91EF91BF91AF919F918F917F9172 +:1010E0006F915F914F913F912F910F900BBE0F9099 +:1010F0000FBE0F901F9018951F920F920FB60F9270 +:101100000BB60F9211242F933F934F935F936F93DE +:101110007F938F939F93AF93BF93EF93FF938091B0 +:10112000A5019091A601892B29F0E091A501F091EC +:10113000A6010995FF91EF91BF91AF919F918F917A +:101140007F916F915F914F913F912F910F900BBEC7 +:101150000F900FBE0F901F9018951F920F920FB611 +:101160000F920BB60F9211242F933F934F935F93DF +:101170006F937F938F939F93AF93BF93EF93FF935F +:101180008091950190919601892B29F0E09195012C +:10119000F09196010995FF91EF91BF91AF919F91C9 +:1011A0008F917F916F915F914F913F912F910F9010 +:1011B0000BBE0F900FBE0F901F9018951F920F92AD +:1011C0000FB60F920BB60F9211242F933F934F93AC +:1011D0005F936F937F938F939F93AF93BF93EF939F +:1011E000FF938091990190919A01892B29F0E091C8 +:1011F0009901F0919A010995FF91EF91BF91AF91FB +:101200009F918F917F916F915F914F913F912F911E +:101210000F900BBE0F900FBE0F901F9018951F924E +:101220000F920FB60F920BB60F9211242F933F938C +:101230004F935F936F937F938F939F93AF93BF93DE +:10124000EF93FF9380919B0190919C01892B29F052 +:10125000E0919B01F0919C010995FF91EF91BF9165 +:10126000AF919F918F917F916F915F914F913F913E +:101270002F910F900BBE0F900FBE0F901F901895DF +:101280001F920F920FB60F920BB60F9211242F934D +:101290003F934F935F936F937F938F939F93AF93FE +:1012A000BF93EF93FF9380919D0190919E01892BB5 +:1012B00029F0E0919D01F0919E010995FF91EF9138 +:1012C000BF91AF919F918F917F916F915F914F915E +:1012D0003F912F910F900BBE0F900FBE0F901F905C +:1012E00018951F920F920FB60F920BB60F92112402 +:1012F0002F933F934F935F936F937F938F939F931E +:10130000AF93BF93EF93FF9380919F019091A001C2 +:10131000892B29F0E0919F01F091A0010995FF919F +:10132000EF91BF91AF919F918F917F916F915F915D +:101330004F913F912F910F900BBE0F900FBE0F90CA +:101340001F9018951F920F920FB60F920BB60F9227 +:1013500011242F933F934F935F936F937F938F93BA +:101360009F93AF93BF93EF93FF938091A3019091CD +:10137000A401892B29F0E091A301F091A401099522 +:10138000FF91EF91BF91AF919F918F917F916F915D +:101390005F914F913F912F910F900BBE0F900FBE19 +:1013A0000F901F9018951F920F920FB60F920BB6C9 +:1013B0000F9211242F933F934F935F936F937F93DB +:1013C0008F939F93AF93BF93EF93FF938091A70168 +:1013D0009091A801892B29F0E091A701F091A80133 +:1013E0000995FF91EF91BF91AF919F918F917F915F +:1013F0006F915F914F913F912F910F900BBE0F9086 +:101400000FBE0F901F9018951F920F920FB60F925C +:101410000BB60F9211242F933F934F935F936F93CB +:101420007F938F939F93AF93BF93EF93FF9380919D +:10143000A9019091AA01892B29F0E091A901F091CD +:10144000AA010995FF91EF91BF91AF919F918F9163 +:101450007F916F915F914F913F912F910F900BBEB4 +:101460000F900FBE0F901F9018951F920F920FB6FE +:101470000F920BB60F9211242F933F934F935F93CC +:101480006F937F938F939F93AF93BF93EF93FF934C +:101490008091AB019091AC01892B29F0E091AB01D7 +:1014A000F091AC010995FF91EF91BF91AF919F91A0 +:1014B0008F917F916F915F914F913F912F910F90FD +:1014C0000BBE0F900FBE0F901F9018951F920F929A +:1014D0000FB60F920BB60F9211242F933F934F9399 +:1014E0005F936F937F938F939F93AF93BF93EF938C +:1014F000FF938091AD019091AE01892B29F0E0918D +:10150000AD01F091AE010995FF91EF91BF91AF91BF +:101510009F918F917F916F915F914F913F912F910B +:101520000F900BBE0F900FBE0F901F901895EF926B +:10153000FF920F931F939C016091B101662379F490 +:1015400081E08093B101C901A0E0B0E08093B201D5 +:101550009093B301A093B401B093B5016EC0E09035 +:10156000B201F090B3010091B4011091B501205F78 +:10157000314FC901A0E0B0E08E199F09A00BB10B5B +:10158000883027E0920720E0A20720E0B20728F485 +:10159000805F914FAF4FBF4F0CC0893125E192075B +:1015A00020E0A20720E0B20720F080519E40A0403A +:1015B000B0402091B6013091B7014091B8015091EF +:1015C000B901280F391F4A1F5B1F2093B6013093C2 +:1015D000B7014093B8015093B901862F8F5F809374 +:1015E000B101813151F584E056954795379527959E +:1015F0008A95D1F72E0D3F1D401F511F3093510387 +:1016000020935003809150039091510381519E404B +:1016100050F0809150039091510380519E409093DF +:101620005103809350031092B6011092B7011092AB +:10163000B8011092B9011092B1011F910F91FF9062 +:10164000EF9008952091520330915303C9010895FA +:101650002091500330915103C9010895DF93CF9336 +:101660000F92CDB7DEB781E48983109235021092D4 +:1016700034021092530310925203109251031092AD +:10168000500382E461E0AE014F5F5F4F0E94600C47 +:10169000109254030F90CF91DF910895DF93CF9371 +:1016A00000D00F92CDB7DEB70E945E0E882309F0FE +:1016B00087C080915403882309F449C08091350282 +:1016C000882331F08FEF809334021092350260C08E +:1016D000809134022091AF013091B001882381F0D4 +:1016E000121613060CF45EC083E4898382E461E081 +:1016F000AE014F5F5F4F0E94600C1092540360C0B8 +:10170000121613060CF44EC082E0BE016E5F7F4FCE +:101710000E94610E9A8180E02B81820F911D90932F +:1017200053038093520380915203909153030E947C +:10173000970A81E4898382E461E0AE014F5F5F4FE5 +:101740000E94600C109254038AE090E023C08091C4 +:1017500034022091AF013091B001882301F1C90119 +:1017600001969093B0018093AF018053954741F566 +:1017700085E4898382E461E0AE014F5F5F4F0E94A0 +:10178000600C8FEF80935403109235021092340254 +:1017900084E690E09093B0018093AF0111C01216DF +:1017A00013063CF4215030403093B0012093AF0138 +:1017B00007C082E462E00E94800C8FEF80935403A4 +:1017C0000F900F900F90CF91DF91089520917100AD +:1017D0002E7F20937100209171002D7F2093710046 +:1017E0009C0140E050E060E87EE380E090E00E94F1 +:1017F000C012203130F0822F90E040979595879568 +:10180000282F209370000895109201021092000278 +:10181000109203021092020284E690E00E94E60B0E +:10182000E4E7F0E08081846080831092BA018081D7 +:1018300081608083808180648083089590E061115D +:1018400091E08E7F982B90937200089590930102FF +:1018500080930002089590930302809302020895FA +:10186000E4E7F0E080818F70806A80830895E4E788 +:10187000F0E080818F70806D808308958091740086 +:1018800087FFFCCF089580937300E4E7F0E0808148 +:101890008F70806880830895882329F08091740078 +:1018A0008F70806C04C0809174008F70806880930A +:1018B00074000895809173000895809171000895D7 +:1018C000982F8091BA018823E1F782E08093BA01D2 +:1018D0009E7F9093BB01ACEBB1E0FA0102C0819115 +:1018E0008D938E2F841B8617D0F31092DC016093AA +:1018F000DD01809174008F70806A80937400089578 +:10190000982F8091BA018823E1F783E08093BA0190 +:1019100091609093BB011092FE016093FF01809152 +:1019200074008F70806A809374000895982FFA0174 +:10193000809174008E7F80937400809174008F700A +:10194000806A809374008091740087FFFCCF9E7F33 +:1019500090937300809174008F70806880937400FE +:101960008091740087FFFCCF80917100883189F0ED +:1019700091E012C0808180937300809174008F7019 +:101980008068809374008091740087FFFCCF31964B +:101990006150662379F790E0809174008F70806DBC +:1019A000809374008091740084FFFCCF8091740058 +:1019B000816080937400892F08951F93CF93DF93E4 +:1019C000982F162FEA01809174008E7F8093740007 +:1019D000809174008F70806A80937400809174008D +:1019E00087FFFCCF916090937300809174008F709B +:1019F0008068809374008091740087FFFCCF809191 +:101A00007100803469F091E018C08FEF0E944C0C97 +:101A10008091740087FFFCCF8091730089931150EF +:101A2000123098F780E00E944C0C8091740087FF80 +:101A3000FCCF80917300888390E0809174008F7058 +:101A4000806D809374008091740081608093740035 +:101A5000892FDF91CF911F9108951F920F920FB69A +:101A60000F920BB60F9211242F933F934F935F93D6 +:101A70006F937F938F939F93AF93BF93EF93FF9356 +:101A800080917100887F803609F49FC0813670F59F +:101A9000883209F45FC0893298F4803109F457C064 +:101AA000813138F4882309F4EEC0883009F0F3C09E +:101AB0004EC0883109F44EC0803209F0ECC0E3C05A +:101AC000803409F477C0813438F4803309F4DBC002 +:101AD000883309F0E0C05DC0803509F45FC0883507 +:101AE00009F44AC0883409F0D6C0CDC0883909F459 +:101AF00082C08939B0F4883709F467C0893738F46F +:101B0000883609F462C0803709F0C5C05EC08838E5 +:101B100009F471C0803909F45EC0803809F0BBC097 +:101B20005AC0803B09F47DC0813B38F4803A09F407 +:101B300066C0883A09F0AFC074C0803C09F49EC00A +:101B4000883C09F49BC0883B09F0A5C07BC080910C +:101B5000BB010FC09091DC018091DD01981708F066 +:101B600092C0E92FF0E0E454FE4F80819F5F909394 +:101B7000DC01809373007BC08091FE019091730023 +:101B8000E82FF0E0E252FE4F90838F5F8093FE01DA +:101B90007AC0809174008F70806879C08091FE0156 +:101BA00090917300E82FF0E0E252FE4F90838F5F38 +:101BB0008093FE012091FE0130E08091FF0190E0D2 +:101BC000019728173907BCF414C085E08093BA0147 +:101BD0001092FE0147C08091FE0190917300E82FA2 +:101BE000F0E0E252FE4F90838F5F8093FE018032DF +:101BF00010F48FEF01C080E00E944C0C4CC080912B +:101C000074008F70806C80937400E0910002F091FA +:101C100001023097F1F18091FE016EED71E00995BE +:101C200038C084E08093BA01E0910202F09103028F +:101C3000309731F080E26CEB71E009958093DD0123 +:101C40001092DC019091DC01E92FF0E0E454FE4FAA +:101C50008081809373009F5F9093DC018091DD0110 +:101C6000981728F4809174008F70806C04C0809164 +:101C700074008F708068809374000DC08091740030 +:101C80008F70806C04C0809174008F70806D809321 +:101C900074001092BA01FF91EF91BF91AF919F91A3 +:101CA0008F917F916F915F914F913F912F910F9005 +:101CB0000BBE0F900FBE0F901F9018958091BA0128 +:101CC0000895982F20E030E00AC0FB01E20FF31FD7 +:101CD000D901A252BE4F8C9180832F5F3F4F2917AD +:101CE000A0F308951092610010926200379A35981F +:101CF00086B1887F866086B987B18F73806487B923 +:101D00003D9810920504109266048091050497B1E5 +:101D1000E0E0F1E0E80FF11D80818F71907E892B6A +:101D200087B9349A369A339A089533983798089534 +:101D300096B1987F982B96B9089597B18295880FA0 +:101D4000880F807C9F73982B97B9089597B18F71F6 +:101D5000907E892B87B90895349A369A089586B172 +:101D6000807408951F920F920FB60F920BB60F92C8 +:101D700011242F933F938F939F93EF93FF9334B14D +:101D800025B1922F80E0232F30E0282B392BE091D2 +:101D90000504F0E0EE0FFF1FEB50FC4F3183208372 +:101DA00080910504833049F1843028F48130A9F012 +:101DB0008230D8F40AC0853081F1853030F1863028 +:101DC000A1F1873009F042C038C0E0916604F0E02C +:101DD000EE0FFF1FEA5BFB4F37C0E0916604F0E0B7 +:101DE000EE0FFF1FEB56FC4F2FC0E0916604F0E0B2 +:101DF000EE0FFF1FEB54FC4F27C0E0916604F0E0AC +:101E0000EE0FFF1FEB5AFC4F1FC0E0916604F0E09D +:101E1000EE0FFF1FEB58FC4F17C0E0916604F0E097 +:101E2000EE0FFF1FEB52FC4F0FC0E0916604F0E095 +:101E3000EE0FFF1FEA5FFB4F07C0E0916604F0E082 +:101E4000EE0FFF1FEA5DFB4F318320838091050475 +:101E5000873041F48091660490E001968F70907015 +:101E6000809366048091050490E0019687709070DD +:101E700080930504E091050497B1F0E0E050FF4F36 +:101E800080818F71907E892B87B9349A369AFF9121 +:101E9000EF919F918F913F912F910F900BBE0F90DB +:101EA0000FBE0F901F901895883018F0EFEFFFEFDE +:101EB00009C0E82FF0E0EE0FFF1FEB50FC4F019040 +:101EC000F081E02DCF0108958330D9F0843028F4DB +:101ED000813071F0823090F40EC08530C1F08530D1 +:101EE00098F08630B9F08730C1F02FEF3FEF2DC06A +:101EF00045E953E014C046E454E011C045EB53E01B +:101F00000EC045E553E00BC045E753E008C045ED82 +:101F100053E005C046E054E002C046E254E060E011 +:101F200070E020E030E0FA01E20FF31F8081918140 +:101F3000680F791F2E5F3F4F20323105A1F7CB018B +:101F400060E170E00E948B129B01C9010895FC01C1 +:101F50008FB7F8947183608353834283178216820C +:101F6000158214828FBF0895DC014FB7F894149640 +:101F70008D919C911597892B11F4E0E025C0169660 +:101F80008D919C911797ED91FC911197E80FF91F96 +:101F9000E081019617969C938E93169712962D9139 +:101FA0003C9113978217930730F0821B930B17967F +:101FB0009C938E93169714968D919C9115970197EB +:101FC00015969C938E9314974FBF8E2F0895FC0106 +:101FD0004FB7F8948481958168177907B0F48681AA +:101FE0009781860F971F978386832281338182177B +:101FF000930720F0821B930B9783868384819581BE +:10200000861B970B9583848302C0158214824FBF71 +:102010000895FC01CB012FB7F8942FBF268137819B +:1020200062817381820F931F0E9477120190F08169 +:10203000E02DE80FF91F808108951F93CF93DF9360 +:10204000EC01162F4FB7F8942C813D816A817B817A +:102050002617370798F48E819F81820F931F0E9465 +:102060007712E881F981E80FF91F10838C819D8137 +:1020700001969D838C834FBF8FEF02C04FBF80E0DE +:10208000DF91CF911F910895FC018FB7F8948FBF16 +:102090002281338184819581281B390BC9010895E0 +:1020A000FC018FB7F8948FBF84819581892B19F03B +:1020B00020E030E002C02FEF3FEFC9010895FC019E +:1020C0008FB7F894158214828FBF08958CE092E048 +:1020D0000895982F809104028823E1F78FEF809371 +:1020E00004029093050289E08093060295982CB52E +:1020F0003DB58091070290910802820F931F9BBD0E +:102100008ABD87B7806187BF0895809106028823C2 +:1021100011F180910602823068F08091050280FF03 +:1021200002C0959A01C0959880910502869580938A +:10213000050201C0959A8AB59BB52091070230919E +:102140000802280F391F3BBD2ABD8091060281502D +:102150008093060208951092040208958091090266 +:10216000882319F587B78F7D87BF4CB55DB5209162 +:102170000702309108028091070290910802240F13 +:10218000351F96958795280F391F39BD28BD86B70D +:10219000886086BF87B7886087BF8FEF809309020A +:1021A00010920B0210920A02089580910A028695FD +:1021B00080930A02849B05C080910A028068809304 +:1021C0000A0280910B028F5F80930B0228B539B50C +:1021D0008091070290910802820F931F99BD88BDDC +:1021E00080910B02883088F060910A028CE092E0C6 +:1021F0000E941D1087B7877F87BF86B7806286BF22 +:1022000087B7806287BF109209020895CF93DF934A +:10221000EC0180910E0290910F02892B69F0809160 +:10222000100290911102892B39F08CE092E00E940B +:10223000B40F88838FEF01C080E0DF91CF910895C4 +:10224000EF92FF920F931F937B018C0181E00E941C +:102250002A05C801B70196958795779567956050CF +:102260007C4D8B409F4FA80197010E949E12309396 +:102270000802209307021F910F91FF90EF9008959D +:1022800087B78F7E87BF87B7877F87BF87B78F7DE9 +:1022900087BF83E00E947B0584E00E947B0586E087 +:1022A0000E947B0508958CE092E064E172E040E2D8 +:1022B00050E00E94A70F0895EF92FF920F931F9393 +:1022C0006CE0E62E62E0F62EC70164E172E040E2C7 +:1022D00050E00E94A70F8D9A8C98949860E875E260 +:1022E00080E090E00E9420111092040287B78F7E58 +:1022F00087BF83E065E870E10E94700510920902D3 +:1023000087B7877F87BF0EEA10E184E0B8010E949B +:10231000700586E0B8010E9470058EB58F7B8EBD7A +:1023200087B7806287BFC7010E945F101F910F911E +:10233000FF90EF900895129A1A9A139A149A159A88 +:10234000BF9ABD9ABE9A1ABA14BAE4E6F0E0808148 +:10235000887F80830895833198F590E06130C1F4DF +:10236000FC0133E0EE0FFF1F3A95E1F7E81BF90B94 +:10237000E85FFE4FA081B18181E090E0068002C05D +:10238000880F991F0A94E2F72C91282B2C9308951B +:10239000FC0123E0EE0FFF1F2A95E1F7E81BF90B84 +:1023A000E85FFE4FA081B18181E090E0068002C02D +:1023B000880F991F0A94E2F780952C9128232C937B +:1023C0000895833110F0E0E01AC090E0FC0143E092 +:1023D000EE0FFF1F4A95E1F7E81BF90BE85FFE4F90 +:1023E00081E090E0068002C0880F991F0A94E2F70E +:1023F0000190F081E02DE081E82309F0E1E08E2FEB +:1024000008958331C0F490E0FC0153E0EE0FFF1F0C +:102410005A95E1F7E81BF90BE85FFE4FA281B38103 +:1024200081E090E0068002C0880F991F0A94E2F7CD +:102430002C91282B2C9308958331C8F490E0FC0153 +:1024400063E0EE0FFF1F6A95E1F7E81BF90BE85F09 +:10245000FE4FA281B38181E090E0068002C0880F28 +:10246000991F0A94E2F780952C9128232C930895C4 +:10247000833110F0E0E01AC090E0FC0173E0EE0F51 +:10248000FF1F7A95E1F7E81BF90BE85FFE4F81E04B +:1024900090E0068002C0880F991F0A94E2F704803A +:1024A000F581E02DE081E82309F0E1E08E2F089529 +:1024B000629FD001739FF001829FE00DF11D649F28 +:1024C000E00DF11D929FF00D839FF00D749FF00DB4 +:1024D000659FF00D9927729FB00DE11DF91F639F55 +:1024E000B00DE11DF91FBD01CF0111240895AA1BF4 +:1024F000BB1B51E107C0AA1FBB1FA617B70710F0EF +:10250000A61BB70B881F991F5A95A9F78095909520 +:10251000BC01CD01089597FB092E07260AD077FD4F +:1025200004D0E5DF06D000201AF4709561957F4F46 +:102530000895F6F7909581959F4F0895A1E21A2E80 +:10254000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1F57 +:10255000A217B307E407F50720F0A21BB30BE40BA7 +:10256000F50B661F771F881F991F1A9469F76095EE +:102570007095809590959B01AC01BD01CF010895A8 +:1025800097FB092E05260ED057FD04D0D7DF0AD0C1 +:10259000001C38F450954095309521953F4F4F4F92 +:1025A0005F4F0895F6F790958095709561957F4FF0 +:0A25B0008F4F9F4F0895F894FFCF5E +:1025BA0000010203040506073A003B003900003A0D +:1025CA00003B003900013A003B003900023A003B67 +:1025DA00003900033A003B003900043A003B003955 +:1025EA0000053A003B003900063A003B0039000773 +:1025FA0064006500630002340035003300073400CC +:10260A003500330006340035003300053400350048 +:10261A00330004340035003300033400350033003E +:10262A000234003500330001340035003300006401 +:0E263A0000650063000164006500630000009D +:00000001FF diff --git a/memory_map.h b/memory_map.h new file mode 100755 index 0000000000000000000000000000000000000000..c8165758d15bdf4b2cc68c3872fccd0e75a270d9 --- /dev/null +++ b/memory_map.h @@ -0,0 +1,86 @@ +#ifndef _MEMORY_MAP +#define _MEMORY_MAP + +// Expansio board memory map + +// register access function +// 0x00 R ADC0 +// 0x01 R ADC1 +// 0x02 R ADC2 +// 0x03 R ADC3 +// 0x04 R ADC4 +// 0x05 R ADC5 +// 0x06 R ADC6 +// 0x07 R ADC7 +// 0x08 R ADC0 averaged (16 samples) +// 0x09 R ADC1 averaged (16 samples) +// 0x0A R ADC2 averaged (16 samples) +// 0x0B R ADC3 averaged (16 samples) +// 0x0C R ADC4 averaged (16 samples) +// 0x0D R ADC5 averaged (16 samples) +// 0x0E R ADC6 averaged (16 samples) +// 0x0F R ADC7 averaged (16 samples) + + +// 0x10 R compass raw +// 0x11 R compass averaged + +// 0x20 W send a byte through the serial port (FTDI) +// 0x21 R receive a byte through the serial port (FTDI) + +// 0x30 R/W GPIO 0 configuration +// 0x31 R/W GPIO 0 data +// 0x32 R/W GPIO 1 configuration +// 0x33 R/W GPIO 1 data +// 0x34 R/W GPIO 2 configuration +// 0x35 R/W GPIO 2 data +// 0x36 R/W GPIO 3 configuration +// 0x37 R/W GPIO 3 data +// 0x38 R/W GPIO 4 configuration +// 0x39 R/W GPIO 4 data +// 0x3A R/W GPIO 5 configuration +// 0x3B R/W GPIO 5 data +// 0x3C R/W GPIO 6 configuration +// 0x3D R/W GPIO 6 data +// 0x3E R/W GPIO 7 configuration +// 0x3F R/W GPIO 7 data +// 0x40 R/W GPIO 8 configuration +// 0x41 R/W GPIO 8 data +// 0x41 R/W GPIO 9 configuration +// 0x43 R/W GPIO 9 data +// 0x44 R/W GPIO 10 configuration +// 0x45 R/W GPIO 10 data +// 0x46 R/W GPIO 11 configuration +// 0x47 R/W GPIO 11 data +// 0x48 R/W GPIO 12 configuration +// 0x49 R/W GPIO 12 data +// 0x4A R/W GPIO 13 configuration +// 0x4B R/W GPIO 13 data +// 0x4C R/W GPIO 14 configuration +// 0x4D R/W GPIO 14 data +// 0x4E R/W GPIO 15 configuration +// 0x4F R/W GPIO 15 data +// 0x50 R/W GPIO 16 configuration +// 0x51 R/W GPIO 16 data +// 0x52 R/W GPIO 17 configuration +// 0x53 R/W GPIO 17 data +// 0x54 R/W GPIO 18 configuration +// 0x55 R/W GPIO 18 data + +// 0x60 W PWM 1 duty cycle +// 0x61 W PWM 1 on/off +// 0x62 W PWM 2 duty cycle +// 0x63 W PWM 2 on/off +// 0x64 W PWM 3 duty cycle +// 0x65 W PWM 3 on/off +// 0x66 W PWM 4 duty cycle +// 0x67 W PWM 4 on/off + +// 0x70 W D/A 1 value +// 0x71 W D/A 1 on/off +// 0x72 W D/A 2 value +// 0x73 W D/A 2 on/off + + + +#endif diff --git a/patches/chipdef.h.patch b/patches/chipdef.h.patch deleted file mode 100644 index e6a380eedb8051da64d04648906c21e24e83845b..0000000000000000000000000000000000000000 --- a/patches/chipdef.h.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -r 407d6aac41dc uc/avrprog_boot_v0_85/chipdef.h ---- a/uc/avrprog_boot_v0_85/chipdef.h Sun Apr 01 13:47:42 2012 +0200 -+++ b/uc/avrprog_boot_v0_85/chipdef.h Tue Nov 10 10:52:39 2015 +0100 -@@ -12,11 +12,13 @@ - - #if defined (SPMCSR) - #define SPM_REG SPMCSR --#elif defined (SPMCR) -+#else -+#if defined (SPMCR) - #define SPM_REG SPMCR - #else - #error "AVR processor does not provide bootloader support!" - #endif -+#endif - - #define APP_END (FLASHEND - (BOOTSIZE * 2)) - diff --git a/patches/main.c.patch b/patches/main.c.patch deleted file mode 100644 index fc1803e6a56fd0622357451d64531b2122a95989..0000000000000000000000000000000000000000 --- a/patches/main.c.patch +++ /dev/null @@ -1,169 +0,0 @@ -diff -r 407d6aac41dc uc/avrprog_boot_v0_85/main.c ---- a/uc/avrprog_boot_v0_85/main.c Sun Apr 01 13:47:42 2012 +0200 -+++ b/uc/avrprog_boot_v0_85/main.c Tue Nov 10 10:52:26 2015 +0100 -@@ -51,8 +51,8 @@ - #endif - - /* UART Baudrate */ -- #define BAUDRATE 19200 - // #define BAUDRATE 19200 -+#define BAUDRATE 19200 - //#define BAUDRATE 115200 - - /* use "Double Speed Operation" */ -@@ -167,6 +167,7 @@ - #include <avr/interrupt.h> - #include <util/delay.h> - -+#include "uart_usb.h" - #include "chipdef.h" - - uint8_t gBuffer[SPM_PAGESIZE]; -@@ -180,14 +181,20 @@ - - static void sendchar(uint8_t data) - { -- while (!(UART_STATUS & (1<<UART_TXREADY))); -- UART_DATA = data; -+// while (!(UART_STATUS & (1<<UART_TXREADY))); -+// UART_DATA = data; -+ uart_usb_send_byte(data); - } - - static uint8_t recvchar(void) - { -- while (!(UART_STATUS & (1<<UART_RXREADY))); -- return UART_DATA; -+ uint8_t data; -+ -+// while (!(UART_STATUS & (1<<UART_RXREADY))); -+// return UART_DATA; -+ while(!uart_usb_is_data_available()); -+ uart_usb_receive_byte(&data); -+ return data; - } - - static inline void eraseFlash(void) -@@ -205,7 +212,7 @@ - static inline void recvBuffer(pagebuf_t size) - { - pagebuf_t cnt; -- uint8_t *tmp = gBuffer; -+ uint8_t *tmp = gBuffer; - - for (cnt = 0; cnt < sizeof(gBuffer); cnt++) { - *tmp++ = (cnt < size) ? recvchar() : 0xFF; -@@ -331,11 +338,27 @@ - - static void (*jump_to_app)(void) = 0x0000; - -+static void enter_app(void) -+{ -+ cli(); -+ MCUCR = (1<<IVCE); //Enable change of interrupt vectors -+ MCUCR = (0<<IVSEL); //Move interrupts to start flash section -+ sei(); -+ jump_to_app(); -+} -+ - int main(void) - { - uint16_t address = 0; - uint8_t device = 0, val; - -+ MCUCR = (1<<IVCE); //Enable change of interrupt vectors -+ MCUCR = (1<<IVSEL); //Move interrupts to boot flash section -+ -+ uart_usb_init(); -+ uart_usb_set_baudrate(19200); -+ uart_usb_start(); -+ - #ifdef DISABLE_WDT_AT_STARTUP - #ifdef WDT_OFF_SPECIAL - #warning "using target specific watchdog_off" -@@ -346,24 +369,25 @@ - wdt_disable(); - #endif - #endif -+ sei();// enable interrupts for the software serial port. - - #ifdef START_POWERSAVE - uint8_t OK = 1; - #endif - -- BLDDR &= ~(1<<BLPNUM); // set as Input -- BLPORT |= (1<<BLPNUM); // Enable pullup -+// BLDDR &= ~(1<<BLPNUM); // set as Input -+// BLPORT |= (1<<BLPNUM); // Enable pullup - - // Set baud rate -- UART_BAUD_HIGH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF; -- UART_BAUD_LOW = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); -+// UART_BAUD_HIGH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF; -+// UART_BAUD_LOW = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); - - #ifdef UART_DOUBLESPEED -- UART_STATUS = ( 1<<UART_DOUBLE ); -+// UART_STATUS = ( 1<<UART_DOUBLE ); - #endif - -- UART_CTRL = UART_CTRL_DATA; -- UART_CTRL2 = UART_CTRL2_DATA; -+// UART_CTRL = UART_CTRL_DATA; -+// UART_CTRL2 = UART_CTRL2_DATA; - - #if defined(START_POWERSAVE) - /* -@@ -376,10 +400,11 @@ - if ((BLPIN & (1<<BLPNUM))) { - // jump to main app if pin is not grounded - BLPORT &= ~(1<<BLPNUM); // set to default --#ifdef UART_DOUBLESPEED -- UART_STATUS &= ~( 1<<UART_DOUBLE ); --#endif -- jump_to_app(); // Jump to application sector -+//#ifdef UART_DOUBLESPEED -+// UART_STATUS &= ~( 1<<UART_DOUBLE ); -+//#endif -+// jump_to_app(); // Jump to application sector -+ enter_app(); - - } else { - val = recvchar(); -@@ -405,10 +430,11 @@ - if ((BLPIN & (1<<BLPNUM))) { - // jump to main app if pin is not grounded - BLPORT &= ~(1<<BLPNUM); // set to default --#ifdef UART_DOUBLESPEED -- UART_STATUS &= ~( 1<<UART_DOUBLE ); --#endif -- jump_to_app(); // Jump to application sector -+//#ifdef UART_DOUBLESPEED -+// UART_STATUS &= ~( 1<<UART_DOUBLE ); -+//#endif -+// jump_to_app(); // Jump to application sector -+ enter_app(); - } - - #elif defined(START_WAIT) -@@ -416,13 +442,17 @@ - uint16_t cnt = 0; - - while (1) { -- if (UART_STATUS & (1<<UART_RXREADY)) -- if (UART_DATA == START_WAIT_UARTCHAR) -+// if (UART_STATUS & (1<<UART_RXREADY)) -+// if (UART_DATA == START_WAIT_UARTCHAR) -+// break; -+ if(uart_usb_is_data_available()) -+ if(recvchar()==START_WAIT_UARTCHAR) - break; - - if (cnt++ >= WAIT_VALUE) { - BLPORT &= ~(1<<BLPNUM); // set to default -- jump_to_app(); // Jump to application sector -+// jump_to_app(); // Jump to application sector -+ enter_app(); - } - - _delay_ms(10); diff --git a/patches/makefile.patch b/patches/makefile.patch deleted file mode 100644 index 960cf152cf67881e5cfad39e374059f919b6fd8b..0000000000000000000000000000000000000000 --- a/patches/makefile.patch +++ /dev/null @@ -1,77 +0,0 @@ -diff -r 407d6aac41dc uc/avrprog_boot_v0_85/makefile ---- a/uc/avrprog_boot_v0_85/makefile Sun Apr 01 13:47:42 2012 +0200 -+++ b/uc/avrprog_boot_v0_85/makefile Tue Nov 10 10:52:17 2015 +0100 -@@ -37,7 +37,7 @@ - # user defined values - - # MCU name --MCU = atmega8 -+# MCU = atmega8 - ## MCU = atmega16 - ## MCU = atmega162 - ## MCU = atmega169 -@@ -46,7 +46,7 @@ - ## MCU = atmega64 - ## MCU = atmega644 - ## MCU = atmega644p --## MCU = atmega128 -+MCU = atmega128 - ## MCU = at90can128 - - ################## BOOTLOADER ###################### -@@ -59,15 +59,16 @@ - #/* Select Boot Size in Words (select one, comment out the others) */ - ## NO! BOOTSIZE=128 - ## NO! BOOTSIZE=256 --BOOTSIZE=512 --##BOOTSIZE=1024 -+## BOOTSIZE=512 -+## BOOTSIZE=1024 - ## BOOTSIZE=2048 -+BOOTSIZE=4096 - - # /* Select if bootloader should include the inverrupt-vectors - # when selecting 'no' here, the bootloader must not use - # any interrupts and the modified linker-scripts are used. */ --##BOOTINTVEC=yes --BOOTINTVEC=no -+BOOTINTVEC=yes -+## BOOTINTVEC=no - - ## - ifeq ($(MCU), atmega8) -@@ -266,7 +267,7 @@ - - - # List C source files here. (C dependencies are automatically generated.) --SRC = $(TARGET).c -+SRC = $(TARGET).c uart_usb.c - - - # List Assembler source files here. -@@ -292,7 +293,7 @@ - - # List any extra directories to look for include files here. - # Each directory must be seperated by a space. --EXTRAINCDIRS = -+EXTRAINCDIRS = ../../../include - - - # Compiler flag to set the C Standard level. -@@ -303,7 +304,7 @@ - CSTANDARD = -std=gnu99 - - # Place -D or -U options here --CDEFS = -DBOOTSIZE=$(BOOTSIZE) -+CDEFS = -DBOOTSIZE=$(BOOTSIZE) -DF_CPU=16000000 - - # Place -I options here - CINCS = -@@ -405,7 +406,7 @@ - AVRDUDE_PORT = usb # programmer connected to serial device - #AVRDUDE_PORT = /dev/ttyS0 # programmer connected to serial device - --AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex -U lfuse:w:0xe4:m -U hfuse:w:0xda:m -+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex -U lfuse:w:0xff:m -U hfuse:w:0xd8:m - #AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep - diff --git a/patches/uart_usb.c b/patches/uart_usb.c deleted file mode 100644 index 1c007d5c2f07e635beae8a044171e812343ee6c0..0000000000000000000000000000000000000000 --- a/patches/uart_usb.c +++ /dev/null @@ -1,241 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include "uart_usb.h" - -#define UART_USB_DEFAULT_BAUDRATE 9600 - -#define UART_USB_RX_BUFFER_SIZE 0x20 - -#define UART_USB_TX_PORT PORTD -#define UART_USB_TX_DDR DDRD -#define UART_USB_TX_PIN PD5 - -#define UART_USB_RX_PORT PORTD -#define UART_USB_RX_DDR DDRD -#define UART_USB_RX_PORTIN PIND -#define UART_USB_RX_PIN PD4 - -// uartsw transmit status and data variables -volatile uint8_t uart_usb_tx_busy; -volatile uint8_t uart_usb_tx_data; -volatile uint8_t uart_usb_tx_bit_num; - -// baud rate common to transmit and receive -volatile uint16_t uart_usb_baudrate_div; - -// uartsw receive status and data variables -volatile uint8_t uart_usb_rx_busy; -volatile uint8_t uart_usb_rx_data; -volatile uint8_t uart_usb_rx_bit_num; - -/* rx buffer */ -unsigned char uart_usb_rx_data_buffer[UART_USB_RX_BUFFER_SIZE]; -unsigned char uart_usb_rx_read_ptr; -unsigned char uart_usb_rx_write_ptr; -unsigned char uart_usb_rx_num_data; - -/* private functions */ - -/* interrupt handlers */ -ISR(TIMER1_CAPT_vect)//RX -{ - uint16_t capture; - // clear ICP interrupt flag - TIFR|=(1<<ICF1); - - if(!uart_usb_rx_busy) - { - // disable input capture interrutps - TIMSK&=~(1<<TICIE1); - capture=TCNT1+uart_usb_baudrate_div + uart_usb_baudrate_div/2; - // schedule data bit sampling 1.5 bit periods from now - OCR1BH=(capture>>8)&0xFF; - OCR1BL=capture&0xFF; - // clear OC1B interrupt flag - TIFR|=(1<<OCF1B); - // enable OC1B interrupt - TIMSK|=(1<<OCIE1B); - // set start bit flag - uart_usb_rx_busy = 0x01; - // reset bit counter - uart_usb_rx_bit_num = 0; - // reset data - uart_usb_rx_data = 0; - } -} - -ISR(TIMER1_COMPB_vect)//RX -{ - uint16_t capture; - - // clear OC1B interrupt flag - TIFR|=(1<<OCF1B); - // shift data byte to make room for new bit - uart_usb_rx_data = uart_usb_rx_data>>1; - - if(UART_USB_RX_PORTIN&(1<<UART_USB_RX_PIN)) - uart_usb_rx_data |= 0x80; - - // increment bit counter - uart_usb_rx_bit_num++; - // schedule next bit sample - capture=OCR1B+uart_usb_baudrate_div; - OCR1BH=(capture>>8)&0xFF; - OCR1BL=capture&0xFF; - - // check if we have a full byte - if(uart_usb_rx_bit_num >= 8) - { - // save data in receive buffer - uart_usb_rx_data_buffer[uart_usb_rx_write_ptr]=uart_usb_rx_data; - uart_usb_rx_write_ptr=(uart_usb_rx_write_ptr+1)%UART_USB_RX_BUFFER_SIZE; - uart_usb_rx_num_data++; - // disable OC1B interrupt - TIMSK&=~(1<<OCIE1B); - // enable ICP interrupt - TIMSK|=(1<<TICIE1); - // clear start bit flag - uart_usb_rx_busy = 0x00; - } -} - -ISR(TIMER1_COMPA_vect)//TX -{ - uint16_t capture; - - // clear OC1B interrupt flag - TIFR|=(1<<OCF1A); - if(uart_usb_tx_bit_num) - { - if(uart_usb_tx_bit_num>1) - { - // transmit data bits (inverted, LSB first) - if((uart_usb_tx_data&0x01)) - UART_USB_TX_PORT|=(1<<UART_USB_TX_PIN); - else - UART_USB_TX_PORT&=~(1<<UART_USB_TX_PIN); - // shift bits down - uart_usb_tx_data = uart_usb_tx_data>>1; - } - else - UART_USB_TX_PORT|=(1<<UART_USB_TX_PIN); - // schedule the next bit - capture=OCR1A+uart_usb_baudrate_div; - OCR1AH=(capture>>8)&0xFF; - OCR1AL=capture&0xFF; - // count down - uart_usb_tx_bit_num--; - } - else - { - // enable OC1A interrupt - TIMSK&=~(1<<OCIE1A); - uart_usb_tx_busy = 0x00; - } -} - -/* public functions */ -void uart_usb_init(void) -{ - // configure GPIO ports - UART_USB_TX_DDR|=(1<<UART_USB_TX_PIN);// output - UART_USB_RX_DDR&=~(1<<UART_USB_RX_PIN);//input - // set input to 0 - UART_USB_RX_PORT&=~(1<<UART_USB_RX_PIN); - // initialize baud rate - uart_usb_set_baudrate(UART_USB_DEFAULT_BAUDRATE); - - // setup the transmitter - uart_usb_tx_busy = 0x00; - TIMSK&=~(1<<OCIE1A); - - // setup the receiver - uart_usb_rx_busy = 0x00; - TIMSK&=~(1<<OCIE1B); - // trigger on falling edge - TCCR1B&=~(1<<ICES1); - // enable ICP interrupt - TIMSK|=(1<<TICIE1); - - /* initlaize buffer variables */ - uart_usb_rx_read_ptr=0; - uart_usb_rx_write_ptr=0; - uart_usb_rx_num_data=0; -} - -void uart_usb_start(void) -{ - TIMSK&=~(1<<OCIE1A); - TIMSK&=~(1<<OCIE1B); - // clear ICP interrupt flag - TIFR|=(1<<ICF1); - TIMSK|=(1<<TICIE1); -} - -void uart_usb_stop(void) -{ - // disable interrupts - TIMSK&=~(1<<OCIE1A); - TIMSK&=~(1<<OCIE1B); - TIMSK&=~(1<<TICIE1); -} - -void uart_usb_set_baudrate(uint32_t baudrate) -{ - TCCR1B&=0xF8; - TCCR1B|=0x01; - // calculate division factor for requested baud rate, and set it - uart_usb_baudrate_div = (uint16_t)((F_CPU+(baudrate/2L))/(baudrate*1L)); -} - -void uart_usb_send_byte(uint8_t data) -{ - uint16_t capture; - - // wait until uart is ready - while(uart_usb_tx_busy); - // set busy flag - uart_usb_tx_busy = 0x01; - // save data - uart_usb_tx_data = data; - // set number of bits (+1 for stop bit) - uart_usb_tx_bit_num = 9; - - UART_USB_TX_PORT&=~(1<<UART_USB_TX_PIN); - - capture=TCNT1+uart_usb_baudrate_div; - OCR1AH=(capture>>8)&0xFF; - OCR1AL=capture&0xFF; - // clear interrupts - TIFR|=(1<<OCF1A); - // enable OC1A interrupt - TIMSK|=(1<<OCIE1A); -} - -uint8_t uart_usb_is_sending(void) -{ - return uart_usb_tx_busy; -} - -uint8_t uart_usb_receive_byte(uint8_t* data) -{ - // make sure we have a receive buffer - if(uart_usb_rx_num_data>0) - { - *data=uart_usb_rx_data_buffer[uart_usb_rx_read_ptr]; - uart_usb_rx_read_ptr=(uart_usb_rx_read_ptr+1)%UART_USB_RX_BUFFER_SIZE; - uart_usb_rx_num_data--; - // make sure we have data - return 0x01; - } - else - return 0x00; -} - -uint8_t uart_usb_is_data_available(void) -{ - if(uart_usb_rx_num_data>0) - return 0x01; - else - return 0x00; -} diff --git a/port128.h b/port128.h new file mode 100755 index 0000000000000000000000000000000000000000..41617aa15019546fc766fd5fe68ca96205edaa19 --- /dev/null +++ b/port128.h @@ -0,0 +1,98 @@ +/*! \file port128.h \brief Additional include for Mega128 to define individual port pins. */ +//***************************************************************************** +// +// File Name : 'port128.h' +// Title : Additional include for Mega128 to define individual port pins +// Author : Pascal Stang +// Created : 11/18/2002 +// Revised : 11/18/2002 +// Version : 1.1 +// Target MCU : Atmel AVR series +// Editor Tabs : 4 +// +// Description : This include file contains additional port and pin defines +// to help make code transparently compatible with the mega128. As in +// the other AVR processors, using defines like PD2 to denote PORTD, pin2 +// is not absolutely necessary but enhances readability. The mega128 io.h +// no longer defines individual pins of ports (like PD2 or PA5, for +// example). Instead, port pins are defines universally for all ports as +// PORT0 through PORT7. However, this renaming causes a code-portability +// issue from non-mega128 AVRs to the mega128. Including this file will +// replace the missing defines. +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef PORT128_H +#define PORT128_H + +// Mega128 individual port defines +// (using these is technically unnecessary but improves code compatibility to +// the mega128 from other AVR processors where these values were still defined +// in the io.h for that processor) + +// PORTA +#define PA0 PORT0 +#define PA1 PORT1 +#define PA2 PORT2 +#define PA3 PORT3 +#define PA4 PORT4 +#define PA5 PORT5 +#define PA6 PORT6 +#define PA7 PORT7 +// PORTB +#define PB0 PORT0 +#define PB1 PORT1 +#define PB2 PORT2 +#define PB3 PORT3 +#define PB4 PORT4 +#define PB5 PORT5 +#define PB6 PORT6 +#define PB7 PORT7 +// PORTC +#define PC0 PORT0 +#define PC1 PORT1 +#define PC2 PORT2 +#define PC3 PORT3 +#define PC4 PORT4 +#define PC5 PORT5 +#define PC6 PORT6 +#define PC7 PORT7 +// PORTD +#define PD0 PORT0 +#define PD1 PORT1 +#define PD2 PORT2 +#define PD3 PORT3 +#define PD4 PORT4 +#define PD5 PORT5 +#define PD6 PORT6 +#define PD7 PORT7 +// PORTE +#define PE0 PORT0 +#define PE1 PORT1 +#define PE2 PORT2 +#define PE3 PORT3 +#define PE4 PORT4 +#define PE5 PORT5 +#define PE6 PORT6 +#define PE7 PORT7 +// PORTF +#define PF0 PORT0 +#define PF1 PORT1 +#define PF2 PORT2 +#define PF3 PORT3 +#define PF4 PORT4 +#define PF5 PORT5 +#define PF6 PORT6 +#define PF7 PORT7 +// PORTG +#define PG0 PORT0 +#define PG1 PORT1 +#define PG2 PORT2 +#define PG3 PORT3 +#define PG4 PORT4 +#define PG5 PORT5 + +#endif diff --git a/ports.c b/ports.c new file mode 100755 index 0000000000000000000000000000000000000000..bbaa59403c5efc978f792902cb4758c7b6fe1d44 --- /dev/null +++ b/ports.c @@ -0,0 +1,105 @@ +#include <avr/io.h> +#include "ports.h" +#include "global.h" + +TGPIO gpio_bits[NUM_GPIO]={{&DDRA,&PORTA,&PINA,0}, + {&DDRA,&PORTA,&PINA,1}, + {&DDRA,&PORTA,&PINA,2}, + {&DDRA,&PORTA,&PINA,3}, + {&DDRA,&PORTA,&PINA,4}, + {&DDRA,&PORTA,&PINA,5}, + {&DDRA,&PORTA,&PINA,6}, + {&DDRA,&PORTA,&PINA,7}, + {&DDRG,&PORTG,&PING,2}, + {&DDRC,&PORTC,&PINC,7}, + {&DDRC,&PORTC,&PINC,6}, + {&DDRC,&PORTC,&PINC,5}, + {&DDRC,&PORTC,&PINC,4}, + {&DDRC,&PORTC,&PINC,3}, + {&DDRC,&PORTC,&PINC,2}, + {&DDRC,&PORTC,&PINC,1}, + {&DDRC,&PORTC,&PINC,0}, + {&DDRG,&PORTG,&PING,1}, + {&DDRG,&PORTG,&PING,0}}; + +void init_ports(void) +{ + //auxiliar LED + sbi(DDRE,2); + sbi(PORTE,2); + + // configure as outputs the pwm pins + sbi(DDRE,3); + sbi(DDRE,4); + sbi(DDRE,5); + sbi(DDRB,7); + + // configure as outputs the DA pins + sbi(DDRB,5); + sbi(DDRB,6); + + // general purpose input/output + // all inputs by default + DDRA=0x00; + DDRC=0x00; + DDRG=DDRG&0xF8; + +} + +void config_port(unsigned char port_id,unsigned char dir) +{ + if(port_id>=0 && port_id<NUM_GPIO) + { + if(dir==OUTPUT)// configure as an output + sbi(*(gpio_bits[port_id].dir_reg),gpio_bits[port_id].bit); + else// configure as an input + cbi(*(gpio_bits[port_id].dir_reg),gpio_bits[port_id].bit); + } +} + +unsigned char get_port_config(unsigned char port_id) +{ + unsigned char dir; + + if(port_id>=0 && port_id<NUM_GPIO) + { + dir=(*(gpio_bits[port_id].dir_reg)&(0x01<<gpio_bits[port_id].bit)); + if(dir==0x00) + return INPUT; + else + return OUTPUT; + } + else + return INPUT; +} + +void set_port(unsigned char port_id) +{ + if(port_id>=0 && port_id<NUM_GPIO) + { + sbi(*(gpio_bits[port_id].write_reg),gpio_bits[port_id].bit); + } +} + +void clear_port(unsigned char port_id) +{ + if(port_id>=0 && port_id<NUM_GPIO) + { + cbi(*(gpio_bits[port_id].write_reg),gpio_bits[port_id].bit); + } +} + +unsigned char read_port(unsigned char port_id) +{ + unsigned char value; + if(port_id>=0 && port_id<NUM_GPIO) + { + value=((*(gpio_bits[port_id].read_reg))&(0x01<<gpio_bits[port_id].bit)); + if(value==0x00) + return 0x00; + else + return 0x01; + } + else + return 0x00; +} diff --git a/ports.h b/ports.h new file mode 100755 index 0000000000000000000000000000000000000000..45cdfb9f9a7509cd8166796511222898aa37974f --- /dev/null +++ b/ports.h @@ -0,0 +1,24 @@ +#ifndef _PORTS_H +#define _PORTS_H + +#define NUM_GPIO 19 + +#define INPUT 0x00 +#define OUTPUT 0x01 + +typedef struct +{ + unsigned char *dir_reg; + unsigned char *write_reg; + unsigned char *read_reg; + unsigned char bit; +}TGPIO; + +void init_ports(void); +void config_port(unsigned char port_id,unsigned char dir); +unsigned char get_port_config(unsigned char port_id); +void set_port(unsigned char port_id); +void clear_port(unsigned char port_id); +unsigned char read_port(unsigned char port_id); + +#endif diff --git a/src/adc.c b/src/adc.c deleted file mode 100644 index 6615ac5510792c607f209df78f2f5b7e034b3c54..0000000000000000000000000000000000000000 --- a/src/adc.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "adc.h" -#include "mem.h" -#include "ports.h" - -// number of channels to convert -#define NUM_CH 8 -// number of samples to average -#define ADC_MAX_NUM_SAMPLES 16 - -// private variables -volatile uint8_t adc_sample_period_ms; -// current channel -volatile uint8_t adc_current_ch; -// channel data -volatile int16_t adc_data[NUM_CH]; -// averaged channel data -volatile int16_t adc_ch_data[NUM_CH][ADC_MAX_NUM_SAMPLES]; -volatile uint8_t adc_current_sample; -volatile uint8_t adc_num_samples; -volatile uint8_t adc_running; -volatile uint8_t adc_prescaler_mask; - -/* private functions */ -void adc_set_channel(uint8_t ch_id) -{ - ADMUX&=0xF8; - ADMUX|= (ch_id&0x07); -} - -void adc_start_conv(void) -{ - ADCSRA|=(1<<ADSC); -} - -uint8_t adc_is_conversion_done(void) -{ - if(ADCSRA&(1<<ADIF)) - return 0x01; - else - return 0x00; -} - -uint8_t adc_is_period_done(void) -{ - if(TIFR&(1<<OCF2)) - return 0x01; - else - return 0x00; -} - -/* public functions */ -void adc_init(void) -{ - // configure the analog inputs - DDRF = 0x00; - PORTF = 0x00; - - ADMUX = (1<<REFS0);// use AVCC as reference, Right justified, channel 0 - ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // free running mode disabled, interrupts enabled, prescaler to 128 - - // clear any pending interrupt - ADCSRA|=(1<<ADIF); - - // set the initial channel to convert - adc_current_ch=0; - adc_current_sample=0; - adc_running=0; - adc_num_samples=ADC_MAX_NUM_SAMPLES; - ram_data[ADC_NUM_SAMPLES]=ADC_MAX_NUM_SAMPLES; - adc_sample_period_ms=0x01; - ram_data[ADC_SAMPLE_PERIOD]=0x01; - adc_set_sample_period(adc_sample_period_ms); - - // configure the timer 2 to perform periodic conversions (1 ms period) - TCCR2=(1<<WGM21);// CTC mode, no output, prescaler to 0 (no clock source) - TCNT2=0x00;// start from 0 - TIMSK=0x00;// interrupts not enabled -} - -void adc_start(void) -{ - // enable the ADC - ADCSRA|=(1<<ADEN); - // enable the timer 2 interrupts - TCNT2=0x00;// start from 0 - TIMSK=0x00;// interrupts not enabled - // clear interrupts - TIFR|=(1<<OCF2); - TIFR|=(1<<TOV2); - // configure the timer prescaler and count value - adc_running=0x01; - adc_set_sample_period(adc_sample_period_ms); - ram_data[ADC_CONTROL]|=0x04; -} - -void adc_stop(void) -{ - TCCR2&=0xF8;// set prescaler to 0 (no clock source) - // disable the ADC - ADCSRA&=~(1<<ADEN); - adc_running=0x00; - ram_data[ADC_CONTROL]&=0xFB; -} - -void adc_set_num_samples(uint8_t num) -{ - if(num>ADC_MAX_NUM_SAMPLES) - adc_num_samples=ADC_MAX_NUM_SAMPLES; - else - { - if(num<=0) - adc_num_samples=1; - else - adc_num_samples=num; - } - if(adc_current_sample>num) - adc_current_sample=0; - ram_data[ADC_NUM_SAMPLES]=num; -} - -void adc_set_sample_period(uint8_t time_ms) -{ - uint16_t prescaler_values[5]={1,8,64,256,1024}; - uint16_t compare_value; - uint8_t i; - - for(i=0;i<5;i++) - { - compare_value=(((F_CPU/1000)*time_ms)/(prescaler_values[i]*NUM_CH))-1; - if(compare_value<256) - { - OCR2=(uint8_t)compare_value; - if(adc_running) - { - TCCR2&=0xF8; - TCCR2|=(i+1); - } - else - adc_prescaler_mask=i+1; - break; - } - } - ram_data[ADC_SAMPLE_PERIOD]=time_ms; -} - -void adc_loop(void) -{ - uint8_t i; - uint16_t data; - - if(adc_is_period_done()) - { - TIFR|=(1<<OCF2);// clear interrupt flag - TIFR|=(1<<TOV2); - TCNT2=0x00;// start from 0 - // start a new conversion - adc_set_channel(adc_current_ch); - adc_start_conv(); - } - else - { - if(adc_is_conversion_done()) - { - ADCSRA|=(1<<ADIF);// clear interrupt flag - data=(ADCL | (ADCH<<8)); - ram_data[ADC_CHANNEL0_L+adc_current_ch*2]=data%256; - ram_data[ADC_CHANNEL0_H+adc_current_ch*2]=data/256; - adc_ch_data[adc_current_ch][adc_current_sample]=data; - // compute the average for the current channel - data=0; - for(i=0;i<adc_num_samples;i++) - data+=adc_ch_data[adc_current_ch][i]; - data=data/adc_num_samples; - ram_data[ADC_AVG_CHANNEL0_L+adc_current_ch*2]=data%256; - ram_data[ADC_AVG_CHANNEL0_H+adc_current_ch*2]=data/256; - if(adc_current_ch==NUM_CH-1)// last channel - adc_current_sample=(adc_current_sample+1)%adc_num_samples; - adc_current_ch=(adc_current_ch+1)%NUM_CH; - } - } -} diff --git a/src/compass.c b/src/compass.c deleted file mode 100644 index ffb186fe6c394c8b85893bbbdd60a75f98ed2f93..0000000000000000000000000000000000000000 --- a/src/compass.c +++ /dev/null @@ -1,252 +0,0 @@ -#include "compass.h" -#include "i2c.h" -#include "mem.h" -#include "ports.h" - -#define COMPASS_MAX_NUM_SAMPLES 16 - -typedef enum {idle,get_data,get_data_delay,read_data,start_cal,calibrating,calibration_delay,stop_cal} compass_states_t; - -/* private variables */ -volatile uint8_t compass_current_sample; -volatile uint8_t compass_num_samples; - -volatile uint8_t compass_start_cal; -volatile uint8_t compass_stop_cal; -volatile uint8_t compass_stop_op; -volatile uint8_t compass_start_op; -volatile compass_states_t compass_state; -// time control variables -volatile uint8_t compass_delay_done; - -/* private functions */ -void compass_avrg(uint16_t heading) -{ - static unsigned long int new_average,first_value; - unsigned long int diff=0; - - if(compass_current_sample==0) - { - compass_current_sample++; - first_value=(long int)heading; - } - else - { - diff=heading+3600-first_value; - if(diff<1800) - diff=diff+3600; - else if(diff>5400) - diff=diff-3600; - new_average=new_average+diff; - compass_current_sample++; - if(compass_current_sample==compass_num_samples) - { - new_average=new_average/(compass_num_samples-1); - new_average=new_average+first_value; - if(new_average>3600) - new_average-=3600; - ram_data[COMPASS_AVG_HEADING_VAL_L]=new_average%256; - ram_data[COMPASS_AVG_HEADING_VAL_H]=new_average/256; - new_average=0; - compass_current_sample=0; - } - } -} - -void compass_start_time_delay(uint8_t delay_ms) -{ - TCNT0=0x00;// reset counter - OCR0=delay_ms*16;// set count value - TCCR0&=0xF8; - TCCR0|=0x07;// enable clock - compass_delay_done=0x00; -} - -uint8_t compass_is_delay_done(void) -{ - return compass_delay_done; -} - -/* interrupt handlers */ -ISR(TIMER0_COMP_vect) -{ - compass_delay_done=0x01; - // disable clock - TCCR0&=0xF8; -} - -/* public functions */ -void compass_init(void) -{ - /* initialize private variables */ - compass_start_cal=0; - compass_stop_cal=0; - compass_stop_op=0; - compass_start_op=0; - compass_delay_done=0x00; - compass_state=idle; - compass_current_sample=0; - compass_num_samples=COMPASS_MAX_NUM_SAMPLES; - ram_data[COMPASS_NUM_SAMPLES]=COMPASS_MAX_NUM_SAMPLES; - - /* use timer 0 to control the operation delay */ - TCCR0=(1<<WGM01);//campare mode, output disable, prescaler 0 - ASSR=0x00;// disable assynchronous operation - TIMSK=(1<<OCIE0);// enable interrupts - OCR0=0xFF; - TCNT0=0x00; - - /* initialize i2c peripheral */ - i2c_init(100); -} - -void compass_start(void) -{ - compass_stop_op=0; - compass_start_op=1; - ram_data[COMPASS_CONTROL]|=0x40; -} - -void compass_stop(void) -{ - compass_stop_op=1; - compass_start_op=0; -} - -void compass_start_calibration(void) -{ - compass_start_cal=1; - compass_stop_cal=0; -} - -void compass_stop_calibration(void) -{ - compass_start_cal=0; - compass_stop_cal=1; -} - -void compass_set_num_samples(uint8_t num) -{ - if(num>COMPASS_MAX_NUM_SAMPLES) - compass_num_samples=COMPASS_MAX_NUM_SAMPLES; - else if(num<=2) - compass_num_samples=2; - else - compass_num_samples=num; - ram_data[COMPASS_NUM_SAMPLES]=compass_num_samples; -} - -void compass_loop(void) -{ - uint8_t cmd,heading[2]; - unsigned short int compass_heading; - static compass_states_t prev_state=idle; - - switch(compass_state) - { - case idle: if(compass_start_op==1) - { - compass_state=get_data; - compass_start_op=0; - } - else - { - if(compass_start_cal==1) - { - compass_start_cal=0; - compass_state=start_cal; - prev_state=idle; - } - else - compass_state=idle; - } - break; - case get_data: if(i2c_get_state()==I2C_IDLE) - { - cmd=COMPASS_HEADING; - i2c_master_send(COMPASS_ADDR,1,&cmd); - compass_start_time_delay(10); - compass_state=get_data_delay; - } - else - compass_state=get_data; - break; - case get_data_delay: if(compass_is_delay_done()==1) - { - if(i2c_get_state()==I2C_IDLE) - { - i2c_master_receive(COMPASS_ADDR,2); - compass_state=read_data; - } - else - compass_state=get_data_delay; - } - else - compass_state=get_data_delay; - break; - case read_data: if(i2c_get_state()==I2C_IDLE) - { - i2c_get_data(2,heading); - compass_heading=heading[1]+(heading[0]<<8); - ram_data[COMPASS_HEADING_VAL_L]=heading[1]; - ram_data[COMPASS_HEADING_VAL_H]=heading[0]; - compass_avrg(compass_heading); - if(compass_stop_op==1) - { - compass_stop_op=0; - compass_state=idle; - ram_data[COMPASS_CONTROL]&=0xBF; - } - else - { - if(compass_start_cal==1) - { - compass_start_cal=0; - compass_state=start_cal; - prev_state=get_data; - } - else - compass_state=get_data; - } - } - else - compass_state=read_data; - break; - case start_cal: if(i2c_get_state()==I2C_IDLE) - { - cmd=COMPASS_START_CAL; - i2c_master_send(COMPASS_ADDR,1,&cmd); - ram_data[COMPASS_CONTROL]|=0x80; - compass_state=calibrating; - } - else - compass_state=start_cal; - break; - case calibrating: if(compass_stop_cal==1) - { - compass_state=stop_cal; - compass_stop_cal=0; - } - else - compass_state=calibrating; - break; - case stop_cal: if(i2c_get_state()==I2C_IDLE) - { - cmd=COMPASS_STOP_CAL; - i2c_master_send(COMPASS_ADDR,1,&cmd); - compass_start_time_delay(20); - compass_state=calibration_delay; - } - else - compass_state=stop_cal; - break; - case calibration_delay: if(compass_is_delay_done()==1) - { - compass_state=prev_state; - ram_data[COMPASS_CONTROL]&=0x7F; - } - else - compass_state=calibration_delay; - break; - } -} diff --git a/src/dac.c b/src/dac.c deleted file mode 100644 index 77d9f1086f0ff1543d06fb0b728bdf1105a5ff64..0000000000000000000000000000000000000000 --- a/src/dac.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "dac.h" -#include "mem.h" - -#define DAC_TOP_VALUE ((uint32_t)1600) -#define DAC_PRESCALE_MASK 1 -#define DAC_MAX_VOLTAGE ((uint32_t)40960) //5V in 3|13 fixed point format - -/* private variables */ -uint8_t dac_running; - -/* public functions */ -void dac_init(void) -{ - // configure as outputs the DA pins - DDRB|=0x60; - - /* initialize internal variables */ - dac_running=0; - OCR1AH=0x00; - OCR1AL=0x00; - OCR1BH=0x00; - OCR1BL=0x00; - /* set the top value */ - ICR1H=(DAC_TOP_VALUE>>8)&0xFF; - ICR1L=(DAC_TOP_VALUE)&0xFF; - - /* configure the timer 3 */ - TCNT1H=0x00; - TCNT1L=0x00; - /* set the timer mode */ - TCCR1A=(1<<WGM11);// all three channels in fast PWM mode, output disabled - TCCR1B=(1<<WGM13)|(1<<WGM12);// no clock source, fast PWM mode -} - -void dac_start(void) -{ - TCNT1H=0x00; - TCNT1L=0x00; - /* set the prescaler value */ - TCCR1B&=0xF8; - TCCR1B|=DAC_PRESCALE_MASK; - dac_running=0x01; - ram_data[DAC_CONTROL]|=0x10; -} - -void dac_stop(void) -{ - /* set the prescaler to 0 (no clock source) */ - TCCR1B&=0xF8; - dac_running=0x00; - ram_data[DAC_CONTROL]&=0xEF; -} - -void dac_enable_channel(dac_ch_t ch) -{ - switch(ch) - { - case dac0: TCCR1A|=(1<<COMA1); - ram_data[DAC_CONTROL]|=0x40; - break; - case dac1: TCCR1A|=(1<<COMB1); - ram_data[DAC_CONTROL]|=0x80; - break; - } -} - -void dac_disable_channel(dac_ch_t ch) -{ - switch(ch) - { - case dac0: TCCR1A&=~(1<<COMA1); - ram_data[DAC_CONTROL]&=0xBF; - break; - case dac1: TCCR1A&=~(1<<COMB1); - ram_data[DAC_CONTROL]|=0x7F; - break; - } -} - -void dac_set_voltage(dac_ch_t ch,uint16_t voltage) -{ - uint32_t compare_value; - - if(voltage>DAC_MAX_VOLTAGE) - voltage=DAC_MAX_VOLTAGE; - compare_value=(voltage*DAC_TOP_VALUE)/DAC_MAX_VOLTAGE; - - switch(ch) - { - case dac0: OCR1AH=(compare_value>>8)&0xFF; - OCR1AL=(compare_value)&0xFF; - ram_data[DAC_CH0_VOLTAGE_L]=voltage%256; - ram_data[DAC_CH0_VOLTAGE_H]=voltage/256; - break; - case dac1: OCR1BH=(compare_value>>8)&0xFF; - OCR1BL=(compare_value)&0xFF; - ram_data[DAC_CH1_VOLTAGE_L]=voltage%256; - ram_data[DAC_CH1_VOLTAGE_H]=voltage/256; - break; - } -} - diff --git a/src/dyn_common.c b/src/dyn_common.c deleted file mode 100644 index 076333f70240c7356d68680dc9e8ade13a4776a7..0000000000000000000000000000000000000000 --- a/src/dyn_common.c +++ /dev/null @@ -1,226 +0,0 @@ -#include "dyn_common.h" -#include "dyn_slave_se.h" -#include "mem.h" -#include "ports.h" -#include "adc.h" -#ifdef _PWM -#include "pwm.h" -#endif -#ifdef _DAC -#include "dac.h" -#endif -#include "compass.h" -#ifdef _UART_TTL -#include "uart_ttl.h" -#endif -#ifdef _UART_USB -#include "uart_usb.h" -#endif - -uint8_t do_write(uint8_t address,uint8_t length,uint8_t *data) -{ - uint8_t i,num=0; - uint8_t low_byte=0x00; - - for(i=address;i<address+length;i++) - { - /* dynamixel interface */ - if(i==ID) - dyn_slave_se_set_id(data[num]); - else if(i==Baud_Rate) - dyn_slave_se_set_baudrate(data[num]); - /* gpio interface */ - else if(i>=GPIO0_config && i<=GPIO18_data) - { - if((i%2)==0)// config register - config_port((i-GPIO0_config)>>1,data[num]); - else// data register - { - if(data[num]==0x00) - clear_port((i-GPIO0_data)>>1); - else - set_port((i-GPIO0_data)>>1); - } - } - else if(i==LED) - { - if(data[num]==0x00) - clear_led(); - else - set_led(); - } - /* ADC interface */ - else if(i==ADC_CONTROL) - { - if(data[num]&0x01) - adc_start(); - else if(data[num]&0x02) - adc_stop(); - } - else if(i==ADC_NUM_SAMPLES) - adc_set_num_samples(data[num]); - else if(i==ADC_SAMPLE_PERIOD) - adc_set_sample_period(data[num]); - #ifdef _PWM - /* PWM interface */ - else if(i==PWM_CONTROL) - { - if(data[num]&0x01) - pwm_start(); - else if(data[num]&0x02) - pwm_stop(); - } - else if(i==PWM_ENABLE) - { - if(data[num]&0x01) - pwm_enable_ch(pwm0); - else if(data[num]&0x10) - pwm_disable_ch(pwm0); - if(data[num]&0x02) - pwm_enable_ch(pwm1); - else if(data[num]&0x20) - pwm_disable_ch(pwm1); - if(data[num]&0x04) - pwm_enable_ch(pwm2); - else if(data[num]&0x40) - pwm_disable_ch(pwm2); - if(data[num]&0x08) - pwm_enable_ch(pwm3); - else if(data[num]&0x80) - pwm_disable_ch(pwm3); - } - else if(i==PWM_FREQ_L) - low_byte=data[num]; - else if(i==PWM_FREQ_H) - pwm_set_frequency(low_byte+data[num]*256); - else if(i>=PWM_CH0_DUTY && i<=PWM_CH3_DUTY) - pwm_set_duty_cycle((pwm_id_t)(i-PWM_CH0_DUTY),data[num]); - #endif - #ifdef _DAC - /* dac interface */ - else if(i==DAC_CONTROL) - { - if(data[num]&0x01) - dac_start(); - else if(data[num]&0x02) - dac_stop(); - } - else if(i==DAC_ENABLE) - { - if(data[num]&0x01) - dac_enable_channel(dac0); - else if(data[num]&0x04) - dac_disable_channel(dac0); - if(data[num]&0x02) - dac_enable_channel(dac1); - else if(data[num]&0x08) - dac_disable_channel(dac1); - } - else if(i==DAC_CH0_VOLTAGE_L) - low_byte=data[num]; - else if(i==DAC_CH0_VOLTAGE_H) - dac_set_voltage(dac0,low_byte+data[num]*256); - else if(i==DAC_CH1_VOLTAGE_L) - low_byte=data[num]; - else if(i==DAC_CH1_VOLTAGE_H) - dac_set_voltage(dac1,low_byte+data[num]*256); - #endif - /* compass interface */ - else if(i==COMPASS_CONTROL) - { - if(data[num]&0x01) - compass_start(); - else if(data[num]&0x02) - compass_stop(); - else if(data[num]&0x04) - compass_start_calibration(); - else if(data[num]&0x08) - compass_stop_calibration(); - } - else if(i==COMPASS_NUM_SAMPLES) - compass_set_num_samples(data[num]); - #ifdef _UART_TTL - /* uart TTL interface */ - else if(i==UART_TTL_CONTROL) - { - if(data[num]&0x01) - uart_ttl_start(); - else if(data[num]&0x02) - uart_ttl_stop(); - } - else if(i==UART_TTL_TX_DATA) - uart_ttl_send_byte(data[num]); - else if(i==UART_TTL_BAUDRATE_L) - low_byte=data[num]; - else if(i==UART_TTL_BAUDRATE_H) - uart_ttl_set_baudrate(low_byte+data[num]*256); - #endif - #ifdef _UART_USB - /* uart TTL interface */ - else if(i==UART_USB_CONTROL) - { - if(data[num]&0x01) - uart_usb_start(); - else if(data[num]&0x02) - uart_usb_stop(); - } - else if(i==UART_USB_TX_DATA) - uart_usb_send_byte(data[num]); - else if(i==UART_USB_BAUDRATE_L) - low_byte=data[num]; - else if(i==UART_USB_BAUDRATE_H) - uart_usb_set_baudrate(low_byte+data[num]*256); - #endif - num++; - } - - return 0x01; -} - -uint8_t do_read(uint8_t address,uint8_t length,uint8_t **data) -{ - uint8_t i=0; - - /* perform operations before reading the ram */ - for(i=address;i<address+length;i++) - { - if(i>=GPIO0_config && i<=GPIO18_data) - { - if((i%2)!=0) // data register - read_port((i-GPIO0_config)>>1); - } - else if(i==SWITCHES) - get_selector_value(); - #ifdef _UART_TTL - else if(i==UART_TTL_CONTROL) - { - if(uart_ttl_is_data_available()) - ram_data[UART_TTL_CONTROL]|=0x80; - else - ram_data[UART_TTL_CONTROL]&=0x7F; - if(uart_ttl_is_sending()) - ram_data[UART_TTL_CONTROL]|=0x40; - else - ram_data[UART_TTL_CONTROL]&=0xBF; - } - else if(i==UART_TTL_RX_DATA) - uart_ttl_receive_byte(&ram_data[UART_TTL_RX_DATA]); - #endif - #ifdef _UART_USB - else if(i==UART_USB_CONTROL) - { - if(uart_usb_is_data_available()) - ram_data[UART_USB_CONTROL]|=0x80; - else - ram_data[UART_USB_CONTROL]&=0x7F; - if(uart_usb_is_sending()) - ram_data[UART_USB_CONTROL]|=0x40; - else - ram_data[UART_USB_CONTROL]&=0xBF; - } - else if(i==UART_USB_RX_DATA) - uart_usb_receive_byte(&ram_data[UART_USB_RX_DATA]); - #endif - } - return ram_read(address,length,data); -} diff --git a/src/dyn_slave_diff.c b/src/dyn_slave_diff.c deleted file mode 100644 index 6b7206aca40822b574b48be1c5e3414cedb8c40e..0000000000000000000000000000000000000000 --- a/src/dyn_slave_diff.c +++ /dev/null @@ -1,427 +0,0 @@ -#include <avr/interrupt.h> -#include <avr/io.h> -#include "dyn_slave_diff.h" -#include "mem.h" - -/* private variables */ -uint8_t dyn_slave_diff_id; -uint8_t dyn_slave_diff_data[128]; -uint8_t dyn_slave_diff_num_rx_bytes; -uint8_t dyn_slave_diff_num_tx_bytes; -uint8_t dyn_slave_diff_packet_ready; -uint8_t dyn_slave_diff_send_done; -uint8_t dyn_slave_diff_error; -uint8_t dyn_slave_diff_tmp_data[RAM_SIZE]; -uint8_t dyn_slave_diff_tmp_address; -uint8_t dyn_slave_diff_tmp_length; -uint8_t dyn_slave_diff_reg_pending; -uint8_t dyn_slave_diff_sync_read_pending; -uint8_t dyn_slave_diff_sync_read_previous; -uint8_t dyn_slave_diff_bulk_read_pending; -uint8_t dyn_slave_diff_bulk_read_previous; - -inline void dyn_slave_diff_set_rx(void) -{ - PORTB &= 0xEF; -} - -inline void dyn_slave_diff_set_tx(void) -{ - PORTB |= 0x10; -} - -/* interrupt handlers */ -ISR(USART0_TX_vect) -{ - if(dyn_slave_diff_num_tx_bytes==dyn_slave_diff_data[3]+4) - { - dyn_slave_diff_set_rx(); - dyn_slave_diff_send_done=1; - } - else - { - UDR0=dyn_slave_diff_data[dyn_slave_diff_num_tx_bytes]; - dyn_slave_diff_num_tx_bytes++; - } -} - -ISR(USART0_RX_vect) -{ - static uint8_t length; - - cli();// disable any other interrupt - dyn_slave_diff_data[dyn_slave_diff_num_rx_bytes]=UDR0; - switch(dyn_slave_diff_num_rx_bytes) - { - case 0: if(dyn_slave_diff_data[dyn_slave_diff_num_rx_bytes]==0xFF) - dyn_slave_diff_num_rx_bytes++; - break; - case 1: if(dyn_slave_diff_data[dyn_slave_diff_num_rx_bytes]==0xFF) - dyn_slave_diff_num_rx_bytes++; - else - dyn_slave_diff_num_rx_bytes--; - break; - case 2: dyn_slave_diff_num_rx_bytes++; - break; - case 3: length=dyn_slave_diff_data[dyn_slave_diff_num_rx_bytes]+3; - dyn_slave_diff_num_rx_bytes++; - break; - default: if(dyn_slave_diff_num_rx_bytes==length) - { - dyn_slave_diff_num_rx_bytes=0; - dyn_slave_diff_packet_ready=1; - } - else - dyn_slave_diff_num_rx_bytes++; - break; - } - sei();// enable all interrutps -} - -/* private functions */ -uint8_t dyn_slave_diff_is_packet_ready(void) -{ - if(dyn_slave_diff_packet_ready==0x01) - { - dyn_slave_diff_packet_ready=0x00; - return 0x01; - } - else - return 0x00; -} - -uint8_t dyn_slave_diff_check_id(void) -{ - if(dyn_slave_diff_id==dyn_slave_diff_data[2] || dyn_slave_diff_data[2]==0xFE) - return 0x01; - else - { - dyn_slave_diff_num_rx_bytes=0; - return 0x00; - } -} - -uint8_t dyn_slave_diff_check_checksum(void) -{ - uint8_t i,cs=0x00; - - for(i=2;i<dyn_slave_diff_data[3]+4;i++) - cs+=dyn_slave_diff_data[i]; - if(cs==0xFF) - return 0x01; - else - return 0x00; -} - -inline uint8_t dyn_slave_diff_get_instruction(void) -{ - return dyn_slave_diff_data[4]; -} - -inline uint8_t dyn_slave_diff_get_received_id(void) -{ - return dyn_slave_diff_data[2]; -} - -// read operation -inline uint8_t dyn_slave_diff_get_address(void) -{ - return dyn_slave_diff_data[5]; -} - -inline uint8_t dyn_slave_diff_get_read_length(void) -{ - return dyn_slave_diff_data[6]; -} - -// write operation -inline uint8_t dyn_slave_diff_get_write_length(void) -{ - return dyn_slave_diff_data[3]-3; -} - -inline uint8_t *dyn_slave_diff_get_write_data(void) -{ - return &dyn_slave_diff_data[6]; -} - -// sync read operation -uint8_t dyn_slave_diff_sync_read_id_present(void) -{ - uint8_t i,num; - - num=dyn_slave_diff_data[3]-4; - for(i=0;i<num;i++) - { - if(dyn_slave_diff_data[7+i]==dyn_slave_diff_id) - { - if(i==0) - return 0x00; - else - return dyn_slave_diff_data[6+i]; - } - } - return 0xFF; -} - -// sync write operation -uint8_t dyn_slave_diff_sync_write_id_present(uint8_t **data) -{ - uint8_t i,num; - - num=(dyn_slave_diff_data[3]-4)/(dyn_slave_diff_data[6]+1); - for(i=0;i<num;i++) - { - if(dyn_slave_diff_data[7+i*(dyn_slave_diff_data[6]+1)]==dyn_slave_diff_id) - { - (*data)=&dyn_slave_diff_data[7+i*(dyn_slave_diff_data[6]+1)+1]; - return 0x01; - } - } - return 0x00; -} - -// bulk read operation -uint8_t dyn_slave_diff_bulk_read_id_present(uint8_t *address,uint8_t *length) -{ - uint8_t i,num; - - num=(dyn_slave_diff_data[3]-2)/3; - for(i=0;i<num;i++) - { - if(dyn_slave_diff_data[5+i*3]==dyn_slave_diff_id) - { - (*address)=dyn_slave_diff_data[6+i*3]; - (*length)=dyn_slave_diff_data[7+i*3]; - if(i==0) - return 0x00; - else - return dyn_slave_diff_data[5+(i-1)*3]; - } - } - return 0xFF; -} - -// bulk write operation -uint8_t dyn_slave_diff_bulk_write_id_present(uint8_t *address,uint8_t *length,uint8_t **data) -{ - uint8_t i,num; - - num=dyn_slave_diff_data[3]+4; - for(i=5;i<num;) - { - if(dyn_slave_diff_data[i]==dyn_slave_diff_id) - { - (*address)=dyn_slave_diff_data[i+1]; - (*length)=dyn_slave_diff_data[i+2]; - (*data)=&dyn_slave_diff_data[i+3]; - return 0x01; - } - else - i+=dyn_slave_diff_data[i+2]+3; - } - return 0x00; -} - -void dyn_slave_diff_send_status(uint8_t error,uint8_t length, uint8_t *data) -{ - uint8_t i,cs=0; - - if(dyn_slave_diff_data[2]!=0xFE) - { - if(dyn_slave_diff_data[4]==INST_PING || ((dyn_slave_diff_data[4]==INST_READ || - dyn_slave_diff_data[4]==INST_SYNC_READ || dyn_slave_diff_data[4]==INST_BULK_READ) && - ram_data[Status_Return_Level]!=0x00) || ram_data[Status_Return_Level]==0x02) - dyn_slave_diff_data[0]=0xFF; - dyn_slave_diff_data[1]=0xFF; - dyn_slave_diff_data[2]=dyn_slave_diff_id; - cs+=dyn_slave_diff_id; - dyn_slave_diff_data[3]=length+2; - cs+=length+2; - dyn_slave_diff_data[4]=error; - cs+=error; - for(i=0;i<length;i++) - { - dyn_slave_diff_data[5+i]=data[i]; - cs+=data[i]; - } - dyn_slave_diff_data[5+i]=~cs; - // set in tex mode - dyn_slave_diff_set_tx(); - // start transmission - dyn_slave_diff_num_tx_bytes=1; - UDR0=dyn_slave_diff_data[0]; - } -} - -inline uint8_t dyn_slave_diff_is_send_done(void) -{ - return dyn_slave_diff_send_done; -} - -/* public functions */ -void dyn_slave_diff_init(uint8_t baudrate,uint8_t id) -{ - DDRE=DDRE|0x01;// TX (0) are outputs 0x01=00000001 - DDRE=DDRE&0xFD;// RX(1) is an input 0xFE=11111101 - - DDRB=DDRB|0x10;// DIR (4) are outputs 0x10=00010000 - // configure the ports to receive data - dyn_slave_diff_set_rx(); - - // initialize the rs485 ports - UCSR0A = (1<<U2X);// double USART transmission speed - dyn_slave_diff_set_baudrate(baudrate); - UCSR0A|=0x40;// clear any pending interrupt - UCSR0B = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE); - UCSR0C = (1<<UCSZ1)|(1<< UCSZ0); // 8 bit data, no parity, 1 stop bit - - dyn_slave_diff_set_id(id); - // initialize private variables - dyn_slave_diff_num_tx_bytes=0; - dyn_slave_diff_num_rx_bytes=0; - dyn_slave_diff_packet_ready=0; - dyn_slave_diff_send_done=0; - dyn_slave_diff_error=NO_ERROR; - dyn_slave_diff_tmp_address=0x00; - dyn_slave_diff_tmp_length=0x00; - dyn_slave_diff_reg_pending=0x00; - dyn_slave_diff_sync_read_pending=0x00; - dyn_slave_diff_bulk_read_pending=0x00; -} - -void dyn_slave_diff_set_baudrate(uint8_t baudrate) -{ - UBRR0H = 0; - UBRR0L = baudrate; -} - -void dyn_slave_diff_set_id(uint8_t id) -{ - dyn_slave_diff_id=id; -} - -void dyn_slave_diff_loop(void) -{ - static uint8_t *data,i; - - if(dyn_slave_diff_is_packet_ready()) - { - if(dyn_slave_diff_check_id()) - { - if(dyn_slave_diff_check_checksum()) - { - switch(dyn_slave_diff_get_instruction()) - { - case INST_PING: dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,0x00,0x00000000); - break; - case INST_READ: if(do_read(dyn_slave_diff_get_address(),dyn_slave_diff_get_read_length(),&data)) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,dyn_slave_diff_get_read_length(),data); - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - case INST_WRITE: if(do_write(dyn_slave_diff_get_address(),dyn_slave_diff_get_write_length(),dyn_slave_diff_get_write_data())) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,0x00,0x00000000); - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - case INST_REG_WRITE: dyn_slave_diff_tmp_address=dyn_slave_diff_get_address(); - dyn_slave_diff_tmp_length=dyn_slave_diff_get_write_length(); - data=dyn_slave_diff_get_write_data(); - for(i=0;i<dyn_slave_diff_tmp_length;i++) - dyn_slave_diff_tmp_data[i]=data[i]; - dyn_slave_diff_reg_pending=0x01; - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,0x00,0x00000000); - break; - case INST_ACTION: if(dyn_slave_diff_reg_pending) - { - if(do_write(dyn_slave_diff_tmp_address,dyn_slave_diff_tmp_length,dyn_slave_diff_tmp_data)) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,0x00,0x00000000); - } - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - case INST_RESET: - break; - case INST_SYNC_READ: dyn_slave_diff_sync_read_previous=dyn_slave_diff_sync_read_id_present(); - if(dyn_slave_diff_sync_read_previous!=0xFF) - { - if(dyn_slave_diff_sync_read_previous==0x00)// first device on the list - { - if(do_read(dyn_slave_diff_get_address(),dyn_slave_diff_get_read_length(),&data)) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,dyn_slave_diff_get_read_length(),data); - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - else// sync read pending - { - dyn_slave_diff_tmp_address=dyn_slave_diff_get_address(); - dyn_slave_diff_tmp_length=dyn_slave_diff_get_read_length(); - dyn_slave_diff_sync_read_pending=0x01; - } - } - break; - case INST_SYNC_WRITE: if(dyn_slave_diff_sync_write_id_present(&data)) - do_write(dyn_slave_diff_get_address(),dyn_slave_diff_get_read_length(),data); - break; - case INST_BULK_READ: dyn_slave_diff_bulk_read_previous=dyn_slave_diff_bulk_read_id_present(&dyn_slave_diff_tmp_address,&dyn_slave_diff_tmp_length); - if(dyn_slave_diff_bulk_read_previous!=0xFF) - { - if(dyn_slave_diff_bulk_read_previous==0x00)// first device on the list - { - if(do_read(dyn_slave_diff_tmp_address,dyn_slave_diff_tmp_length,&data)) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,dyn_slave_diff_tmp_length,data); - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - else// sync read pending - dyn_slave_diff_bulk_read_pending=0x01; - } - break; - case INST_BULK_WRITE: if(dyn_slave_diff_bulk_write_id_present(&dyn_slave_diff_tmp_address,&dyn_slave_diff_tmp_length,&data)) - do_write(dyn_slave_diff_tmp_address,dyn_slave_diff_tmp_length,data); - break; - default: dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - } - } - else - dyn_slave_diff_send_status(dyn_slave_diff_error|CHECKSUM_ERROR,0x00,0x00000000); - } - else - { - if(dyn_slave_diff_sync_read_pending) - { - if(dyn_slave_diff_get_received_id()==dyn_slave_diff_sync_read_previous) - { - dyn_slave_diff_sync_read_pending=0x00; - if(do_read(dyn_slave_diff_tmp_address,dyn_slave_diff_tmp_length,&data)) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,dyn_slave_diff_tmp_length,data); - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - } - if(dyn_slave_diff_bulk_read_pending) - { - if(dyn_slave_diff_get_received_id()==dyn_slave_diff_bulk_read_previous) - { - dyn_slave_diff_bulk_read_pending=0x00; - if(do_read(dyn_slave_diff_tmp_address,dyn_slave_diff_tmp_length,&data)) - dyn_slave_diff_send_status(dyn_slave_diff_error|NO_ERROR,dyn_slave_diff_tmp_length,data); - else - dyn_slave_diff_send_status(dyn_slave_diff_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - } - } - } -} - -void dyn_slave_diff_set_error(uint8_t error) -{ - dyn_slave_diff_error|=error; -} - -void dyn_slave_diff_clear_error(void) -{ - dyn_slave_diff_error=NO_ERROR; -} diff --git a/src/dyn_slave_se.c b/src/dyn_slave_se.c deleted file mode 100644 index 14432c099ea244cf8986d0d4ede7f3e036b0a406..0000000000000000000000000000000000000000 --- a/src/dyn_slave_se.c +++ /dev/null @@ -1,431 +0,0 @@ -#include <avr/interrupt.h> -#include <avr/io.h> -#include "dyn_slave_se.h" -#include "mem.h" - -/* private variables */ -uint8_t dyn_slave_se_id; -uint8_t dyn_slave_se_data[128]; -uint8_t dyn_slave_se_num_rx_bytes; -uint8_t dyn_slave_se_num_tx_bytes; -uint8_t dyn_slave_se_packet_ready; -uint8_t dyn_slave_se_send_done; -uint8_t dyn_slave_se_error; -uint8_t dyn_slave_se_tmp_data[RAM_SIZE]; -uint8_t dyn_slave_se_tmp_address; -uint8_t dyn_slave_se_tmp_length; -uint8_t dyn_slave_se_reg_pending; -uint8_t dyn_slave_se_sync_read_pending; -uint8_t dyn_slave_se_sync_read_previous; -uint8_t dyn_slave_se_bulk_read_pending; -uint8_t dyn_slave_se_bulk_read_previous; - -inline void dyn_slave_se_set_rx(void) -{ - PORTD &= 0xBF; - PORTD |= 0x80; -} - -inline void dyn_slave_se_set_tx(void) -{ - PORTD &= 0x7F; - PORTD |= 0x40; -} - -/* interrupt handlers */ -ISR(USART1_TX_vect) -{ - if(dyn_slave_se_num_tx_bytes==dyn_slave_se_data[3]+4) - { - dyn_slave_se_set_rx(); - dyn_slave_se_send_done=1; - } - else - { - UDR1=dyn_slave_se_data[dyn_slave_se_num_tx_bytes]; - dyn_slave_se_num_tx_bytes++; - } -} - -ISR(USART1_RX_vect) -{ - static uint8_t length; - - cli();// disable any other interrupt - dyn_slave_se_data[dyn_slave_se_num_rx_bytes]=UDR1; - switch(dyn_slave_se_num_rx_bytes) - { - case 0: if(dyn_slave_se_data[dyn_slave_se_num_rx_bytes]==0xFF) - dyn_slave_se_num_rx_bytes++; - break; - case 1: if(dyn_slave_se_data[dyn_slave_se_num_rx_bytes]==0xFF) - dyn_slave_se_num_rx_bytes++; - else - dyn_slave_se_num_rx_bytes--; - break; - case 2: dyn_slave_se_num_rx_bytes++; - break; - case 3: length=dyn_slave_se_data[dyn_slave_se_num_rx_bytes]+3; - dyn_slave_se_num_rx_bytes++; - break; - default: if(dyn_slave_se_num_rx_bytes==length) - { - dyn_slave_se_num_rx_bytes=0; - dyn_slave_se_packet_ready=1; - } - else - dyn_slave_se_num_rx_bytes++; - break; - } - sei();// enable all interrutps -} - -/* private functions */ -uint8_t dyn_slave_se_is_packet_ready(void) -{ - if(dyn_slave_se_packet_ready==0x01) - { - dyn_slave_se_packet_ready=0x00; - return 0x01; - } - else - return 0x00; -} - -uint8_t dyn_slave_se_check_id(void) -{ - if(dyn_slave_se_id==dyn_slave_se_data[2] || dyn_slave_se_data[2]==0xFE) - return 0x01; - else - { - dyn_slave_se_num_rx_bytes=0; - return 0x00; - } -} - -uint8_t dyn_slave_se_check_checksum(void) -{ - uint8_t i,cs=0x00; - - for(i=2;i<dyn_slave_se_data[3]+4;i++) - cs+=dyn_slave_se_data[i]; - if(cs==0xFF) - return 0x01; - else - return 0x00; -} - -inline uint8_t dyn_slave_se_get_instruction(void) -{ - return dyn_slave_se_data[4]; -} - -inline uint8_t dyn_slave_se_get_received_id(void) -{ - return dyn_slave_se_data[2]; -} - -// read operation -inline uint8_t dyn_slave_se_get_address(void) -{ - return dyn_slave_se_data[5]; -} - -inline uint8_t dyn_slave_se_get_read_length(void) -{ - return dyn_slave_se_data[6]; -} - -// write operation -inline uint8_t dyn_slave_se_get_write_length(void) -{ - return dyn_slave_se_data[3]-3; -} - -inline uint8_t *dyn_slave_se_get_write_data(void) -{ - return &dyn_slave_se_data[6]; -} - -// sync read operation -uint8_t dyn_slave_se_sync_read_id_present(void) -{ - uint8_t i,num; - - num=dyn_slave_se_data[3]-4; - for(i=0;i<num;i++) - { - if(dyn_slave_se_data[7+i]==dyn_slave_se_id) - { - if(i==0) - return 0x00; - else - return dyn_slave_se_data[6+i]; - } - } - return 0xFF; -} - -// sync write operation -uint8_t dyn_slave_se_sync_write_id_present(uint8_t **data) -{ - uint8_t i,num; - - num=(dyn_slave_se_data[3]-4)/(dyn_slave_se_data[6]+1); - for(i=0;i<num;i++) - { - if(dyn_slave_se_data[7+i*(dyn_slave_se_data[6]+1)]==dyn_slave_se_id) - { - (*data)=&dyn_slave_se_data[7+i*(dyn_slave_se_data[6]+1)+1]; - return 0x01; - } - } - return 0x00; -} - -// bulk read operation -uint8_t dyn_slave_se_bulk_read_id_present(uint8_t *address,uint8_t *length) -{ - uint8_t i,num; - - num=(dyn_slave_se_data[3]-2)/3; - for(i=0;i<num;i++) - { - if(dyn_slave_se_data[5+i*3]==dyn_slave_se_id) - { - (*address)=dyn_slave_se_data[6+i*3]; - (*length)=dyn_slave_se_data[7+i*3]; - if(i==0) - return 0x00; - else - return dyn_slave_se_data[5+(i-1)*3]; - } - } - return 0xFF; -} - -// bulk write operation -uint8_t dyn_slave_se_bulk_write_id_present(uint8_t *address,uint8_t *length,uint8_t **data) -{ - uint8_t i,num; - - num=dyn_slave_se_data[3]+4; - for(i=5;i<num;) - { - if(dyn_slave_se_data[i]==dyn_slave_se_id) - { - (*address)=dyn_slave_se_data[i+1]; - (*length)=dyn_slave_se_data[i+2]; - (*data)=&dyn_slave_se_data[i+3]; - return 0x01; - } - else - i+=dyn_slave_se_data[i+2]+3; - } - return 0x00; -} - -void dyn_slave_se_send_status(uint8_t error,uint8_t length, uint8_t *data) -{ - uint8_t i,cs=0; - - if(dyn_slave_se_data[2]!=0xFE) - { - if(dyn_slave_se_data[4]==INST_PING || ((dyn_slave_se_data[4]==INST_READ || - dyn_slave_se_data[4]==INST_SYNC_READ || dyn_slave_se_data[4]==INST_BULK_READ) && - ram_data[Status_Return_Level]!=0x00) || ram_data[Status_Return_Level]==0x02) - dyn_slave_se_data[0]=0xFF; - dyn_slave_se_data[1]=0xFF; - dyn_slave_se_data[2]=dyn_slave_se_id; - cs+=dyn_slave_se_id; - dyn_slave_se_data[3]=length+2; - cs+=length+2; - dyn_slave_se_data[4]=error; - cs+=error; - for(i=0;i<length;i++) - { - dyn_slave_se_data[5+i]=data[i]; - cs+=data[i]; - } - dyn_slave_se_data[5+i]=~cs; - // set in tex mode - dyn_slave_se_set_tx(); - // start transmission - dyn_slave_se_num_tx_bytes=1; - UDR1=dyn_slave_se_data[0]; - } -} - -inline uint8_t dyn_slave_se_is_send_done(void) -{ - return dyn_slave_se_send_done; -} - -/* public functions */ -void dyn_slave_se_init(uint8_t baudrate,uint8_t id) -{ - // DDRD - Port D Data Direction Register - DDRD=DDRD|0xC8;// RX_en (7), TX_en (6), TX (3) are outputs 0xC2=11000010 - DDRD=DDRD&0xFB;// RX(2) is an input 0xFE=11111110 - - // configure the ports to receive data - dyn_slave_se_set_rx(); - - // initialize the rs485 ports - UCSR1A = (1<<U2X);// double USART transmission speed - dyn_slave_se_set_baudrate(baudrate); - UCSR1A|=0x40;// clear any pending interrupt - UCSR1B = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE); - UCSR1C = (1<<UCSZ1)|(1<< UCSZ0); // 8 bit data, no parity, 1 stop bit - - dyn_slave_se_set_id(id); - // initialize private variables - dyn_slave_se_num_tx_bytes=0; - dyn_slave_se_num_rx_bytes=0; - dyn_slave_se_packet_ready=0; - dyn_slave_se_send_done=0; - dyn_slave_se_error=NO_ERROR; - dyn_slave_se_tmp_address=0x00; - dyn_slave_se_tmp_length=0x00; - dyn_slave_se_reg_pending=0x00; - dyn_slave_se_sync_read_pending=0x00; - dyn_slave_se_bulk_read_pending=0x00; -} - -void dyn_slave_se_set_baudrate(uint8_t baudrate) -{ - UBRR1H = 0; - UBRR1L = baudrate; - ram_data[Baud_Rate]=baudrate; -} - -void dyn_slave_se_set_id(uint8_t id) -{ - dyn_slave_se_id=id; - ram_data[ID]=id; -} - -void dyn_slave_se_loop(void) -{ - static uint8_t *data,i; - - if(dyn_slave_se_is_packet_ready()) - { - if(dyn_slave_se_check_id()) - { - if(dyn_slave_se_check_checksum()) - { - switch(dyn_slave_se_get_instruction()) - { - case INST_PING: dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,0x00,0x00000000); - break; - case INST_READ: if(do_read(dyn_slave_se_get_address(),dyn_slave_se_get_read_length(),&data)) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,dyn_slave_se_get_read_length(),data); - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - case INST_WRITE: if(do_write(dyn_slave_se_get_address(),dyn_slave_se_get_write_length(),dyn_slave_se_get_write_data())) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,0x00,0x00000000); - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - case INST_REG_WRITE: dyn_slave_se_tmp_address=dyn_slave_se_get_address(); - dyn_slave_se_tmp_length=dyn_slave_se_get_write_length(); - data=dyn_slave_se_get_write_data(); - for(i=0;i<dyn_slave_se_tmp_length;i++) - dyn_slave_se_tmp_data[i]=data[i]; - dyn_slave_se_reg_pending=0x01; - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,0x00,0x00000000); - break; - case INST_ACTION: if(dyn_slave_se_reg_pending) - { - if(do_write(dyn_slave_se_tmp_address,dyn_slave_se_tmp_length,dyn_slave_se_tmp_data)) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,0x00,0x00000000); - } - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - case INST_RESET: - break; - case INST_SYNC_READ: dyn_slave_se_sync_read_previous=dyn_slave_se_sync_read_id_present(); - if(dyn_slave_se_sync_read_previous!=0xFF) - { - if(dyn_slave_se_sync_read_previous==0x00)// first device on the list - { - if(do_read(dyn_slave_se_get_address(),dyn_slave_se_get_read_length(),&data)) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,dyn_slave_se_get_read_length(),data); - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - else// sync read pending - { - dyn_slave_se_tmp_address=dyn_slave_se_get_address(); - dyn_slave_se_tmp_length=dyn_slave_se_get_read_length(); - dyn_slave_se_sync_read_pending=0x01; - } - } - break; - case INST_SYNC_WRITE: if(dyn_slave_se_sync_write_id_present(&data)) - do_write(dyn_slave_se_get_address(),dyn_slave_se_get_read_length(),data); - break; - case INST_BULK_READ: dyn_slave_se_bulk_read_previous=dyn_slave_se_bulk_read_id_present(&dyn_slave_se_tmp_address,&dyn_slave_se_tmp_length); - if(dyn_slave_se_bulk_read_previous!=0xFF) - { - if(dyn_slave_se_bulk_read_previous==0x00)// first device on the list - { - if(do_read(dyn_slave_se_tmp_address,dyn_slave_se_tmp_length,&data)) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,dyn_slave_se_tmp_length,data); - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - else// sync read pending - dyn_slave_se_bulk_read_pending=0x01; - } - break; - case INST_BULK_WRITE: if(dyn_slave_se_bulk_write_id_present(&dyn_slave_se_tmp_address,&dyn_slave_se_tmp_length,&data)) - do_write(dyn_slave_se_tmp_address,dyn_slave_se_tmp_length,data); - break; - default: dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - break; - } - } - else - dyn_slave_se_send_status(dyn_slave_se_error|CHECKSUM_ERROR,0x00,0x00000000); - } - else - { - if(dyn_slave_se_sync_read_pending) - { - if(dyn_slave_se_get_received_id()==dyn_slave_se_sync_read_previous) - { - dyn_slave_se_sync_read_pending=0x00; - if(do_read(dyn_slave_se_tmp_address,dyn_slave_se_tmp_length,&data)) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,dyn_slave_se_tmp_length,data); - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - } - if(dyn_slave_se_bulk_read_pending) - { - if(dyn_slave_se_get_received_id()==dyn_slave_se_bulk_read_previous) - { - dyn_slave_se_bulk_read_pending=0x00; - if(do_read(dyn_slave_se_tmp_address,dyn_slave_se_tmp_length,&data)) - dyn_slave_se_send_status(dyn_slave_se_error|NO_ERROR,dyn_slave_se_tmp_length,data); - else - dyn_slave_se_send_status(dyn_slave_se_error|INSTRUCTION_ERROR,0x00,0x00000000); - } - } - } - } -} - -void dyn_slave_se_set_error(uint8_t error) -{ - dyn_slave_se_error|=error; -} - -void dyn_slave_se_clear_error(void) -{ - dyn_slave_se_error=NO_ERROR; -} diff --git a/src/i2c.c b/src/i2c.c deleted file mode 100644 index 1b44ba02bc4e4398fb130e73722ff4ac98413098..0000000000000000000000000000000000000000 --- a/src/i2c.c +++ /dev/null @@ -1,217 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include "i2c.h" - -#define I2C_RX_BUFFER_LEN 32 -#define I2C_TX_BUFFER_LEN 32 - -/* private variables */ -static volatile i2c_states_t i2c_state; -static uint8_t i2c_device_address; -// send/transmit buffer (outgoing data) -static uint8_t i2c_tx_data[I2C_RX_BUFFER_LEN]; -static uint8_t i2c_tx_data_ptr; -static uint8_t i2c_tx_length; -// receive buffer (incoming data) -static uint8_t i2c_rx_data[I2C_TX_BUFFER_LEN]; -static uint8_t i2c_rx_data_ptr; -static uint8_t i2c_rx_length; - -/* private functions */ -inline void i2c_send_start(void) -{ - // send start condition - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT)|(1<<TWSTA); -} - -inline void i2c_send_stop(void) -{ - // transmit stop condition - // leave with TWEA on for slave receiving - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO); -} - -inline void i2c_wait_for_complete(void) -{ - // wait for i2c interface to complete operation - while((TWCR&(1<<TWINT))==0x00); -} - -inline void i2c_send_byte(uint8_t data) -{ - // save data to the TWDR - TWDR=data; - // begin send - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT); -} - -inline void i2c_receive_byte(uint8_t ackFlag) -{ - // begin receive over i2c - if( ackFlag ) - { - // ackFlag = TRUE: ACK the recevied data - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT)|(1<<TWEA); - } - else - { - // ackFlag = FALSE: NACK the recevied data - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT); - } -} - -inline uint8_t i2c_get_byte(void) -{ - // retieve received data byte from i2c TWDR - return TWDR; -} - -i2c_states_t i2c_get_state(void) -{ - // retieve current i2c status from i2c TWSR - return i2c_state; -} - -/* interrupt handlers */ -ISR(TWI_vect) -{ - // read status bits - uint8_t status = TWSR&TWSR_STATUS_MASK; - - switch(status) - { - // Master General - case TW_START://0x08: Sent start condition - case TW_REP_START:// 0x10: Sent repeated start condition - // send device address - i2c_send_byte(i2c_device_address); - break; - // Master Transmitter & Receiver status codes - case TW_MT_SLA_ACK:// 0x18: Slave address acknowledged - case TW_MT_DATA_ACK:// 0x28: Data acknowledged - if(i2c_tx_data_ptr < i2c_tx_length) - { - // send data - i2c_send_byte( i2c_tx_data[i2c_tx_data_ptr++] ); - } - else - { - // transmit stop condition, enable SLA ACK - i2c_send_stop(); - // set state - i2c_state = I2C_IDLE; - } - break; - case TW_MR_DATA_NACK:// 0x58: Data received, NACK reply issued - // store final received data byte - i2c_rx_data[i2c_rx_data_ptr++] = TWDR; - // continue to transmit STOP condition - case TW_MR_SLA_NACK:// 0x48: Slave address not acknowledged - case TW_MT_SLA_NACK:// 0x20: Slave address not acknowledged - case TW_MT_DATA_NACK:// 0x30: Data not acknowledged - // transmit stop condition, enable SLA ACK - i2c_send_stop(); - // set state - i2c_state = I2C_IDLE; - break; - case TW_MT_ARB_LOST:// 0x38: Bus arbitration lost - // release bus - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT); - // set state - i2c_state = I2C_IDLE; - break; - case TW_MR_DATA_ACK:// 0x50: Data acknowledged - // store received data byte - i2c_rx_data[i2c_rx_data_ptr++] = TWDR; - // fall-through to see if more bytes will be received - case TW_MR_SLA_ACK:// 0x40: Slave address acknowledged - if(i2c_rx_data_ptr < (i2c_rx_length-1)) - // data byte will be received, reply with ACK (more bytes in transfer) - i2c_receive_byte(0x01); - else - // data byte will be received, reply with NACK (final byte in transfer) - i2c_receive_byte(0x00); - break; - // Misc - case TW_NO_INFO:// 0xF8: No relevant state information - // do nothing - break; - case TW_BUS_ERROR:// 0x00: Bus error due to illegal start or stop condition - // reset internal hardware and release bus - TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT)|(1<<TWSTO)|(1<<TWEA); - // set state - i2c_state = I2C_IDLE; - break; - } -} - -/* public functions */ -void i2c_init(uint16_t bitrate_khz) -{ - /* configure the io ports */ - //DDRD|=0x03; - // set i2c bit rate to 100KHz - i2c_set_bitrate(bitrate_khz); - - /* initialize the internal variables */ - i2c_tx_data_ptr=0; - i2c_tx_length=0; - i2c_rx_data_ptr=0; - i2c_rx_length=0; - i2c_state=I2C_IDLE; - - TWCR=(1<<TWEN)|(1<<TWIE)|(1<<TWEA); -} - -void i2c_set_bitrate(uint16_t bitrate_khz) -{ - uint8_t bitrate_div; - - TWSR&=~((1<<TWPS0)|(1<<TWPS1)); - // calculate bitrate division - bitrate_div = ((F_CPU/1000l)/bitrate_khz); - if(bitrate_div >= 16) - bitrate_div = (bitrate_div-16)/2; - TWBR=bitrate_div; -} - -void i2c_master_send(uint8_t deviceAddr, uint8_t length, uint8_t* data) -{ - uint8_t i; - // wait for interface to be ready - while(i2c_state); - // set state - i2c_state = I2C_MASTER_TX; - // save data - i2c_device_address = (deviceAddr & 0xFE); // RW cleared: write operation - for(i=0; i<length; i++) - i2c_tx_data[i] = *data++; - i2c_tx_data_ptr = 0; - i2c_tx_length = length; - // send start condition - i2c_send_start(); -} - -void i2c_master_receive(uint8_t deviceAddr, uint8_t length)//, uint8_t* data) -{ - // uint8_t i; - // wait for interface to be ready - while(i2c_state); - // set state - i2c_state = I2C_MASTER_RX; - // save data - i2c_device_address = (deviceAddr|0x01); // RW set: read operation - i2c_rx_data_ptr = 0; - i2c_rx_length = length; - // send start condition - i2c_send_start(); -} - -void i2c_get_data(unsigned char length, unsigned char *data) -{ - unsigned char i; - - for(i=0;i<length;i++) - data[i]=i2c_rx_data[i]; -} - diff --git a/src/main.c b/src/main.c deleted file mode 100755 index 3acf8c99280f93a12a5f3d1a33c731823839ad08..0000000000000000000000000000000000000000 --- a/src/main.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <avr/io.h> -#include <util/delay.h> -#include <avr/interrupt.h> -#include "dyn_slave_se.h" -#include "dyn_slave_diff.h" -#include "mem.h" -#include "ports.h" -#include "adc.h" -#ifdef _PWM -#include "pwm.h" -#endif -#ifdef _DAC -#include "dac.h" -#endif -#include "compass.h" -#ifdef _UART_TTL -#include "uart_ttl.h" -#endif -#ifdef _UART_USB -#include "uart_usb.h" -#endif - -int16_t main(void) -{ - ram_init(); - dyn_slave_se_init(ram_data[Baud_Rate],ram_data[ID]); - dyn_slave_diff_init(ram_data[Baud_Rate],ram_data[ID]); - init_ports(); - adc_init(); - #ifdef _PWM - pwm_init(); - #endif - #ifdef _DAC - dac_init(); - #endif - compass_init(); - #ifdef _UART_TTL - uart_ttl_init(); - #endif - #ifdef _UART_USB - uart_usb_init(); - #endif - sei(); - - while (1) - { - adc_loop(); - compass_loop(); - dyn_slave_se_loop(); - dyn_slave_diff_loop(); - } -} diff --git a/src/mem.c b/src/mem.c deleted file mode 100644 index b6e29bc31f4bf82798a53ee63e23535c0a974c96..0000000000000000000000000000000000000000 --- a/src/mem.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "mem.h" -#include <avr/eeprom.h> - -// dynamixel RAM variables -uint8_t ram_data[RAM_SIZE]; - -// Dynamixel EEPROM variables -uint8_t EEMEM eeprom_data[17]={0x1C,0x00,0x00,0xC0,0x01,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}; - -void ram_init(void) -{ - uint8_t i; - - for(i=0;i<=Return_Delay_Time;i++) - ram_data[i]=eeprom_read_byte(&eeprom_data[i]); - for(;i<RAM_SIZE;i++) - ram_data[i]=0x00; -} - -uint8_t ram_read(uint8_t address, uint8_t length, uint8_t **data) -{ - if((address+length)>RAM_SIZE) - return 0x00; - else - { - (*data)=&ram_data[address]; - return 0x01; - } -} - -uint8_t ram_write(uint8_t address, uint8_t length, uint8_t *data) -{ - uint8_t i,num=0; - - if((address+length)>RAM_SIZE) - return 0x00; - else - { - for(i=address;i<address+length;i++) - { - if(i<=Return_Delay_Time) - eeprom_write_byte(&eeprom_data[i],data[num]); - ram_data[i]=data[num]; - num++; - } - return 0x01; - } -} diff --git a/src/ports.c b/src/ports.c deleted file mode 100644 index ad16eccc572feb85f80663c392b80a47869e3cc1..0000000000000000000000000000000000000000 --- a/src/ports.c +++ /dev/null @@ -1,136 +0,0 @@ -#include <avr/io.h> -#include "ports.h" -#include "mem.h" - -TGPIO gpio_bits[NUM_GPIO]={{&DDRA,&PORTA,&PINA,0}, - {&DDRA,&PORTA,&PINA,1}, - {&DDRA,&PORTA,&PINA,2}, - {&DDRA,&PORTA,&PINA,3}, - {&DDRA,&PORTA,&PINA,4}, - {&DDRA,&PORTA,&PINA,5}, - {&DDRA,&PORTA,&PINA,6}, - {&DDRA,&PORTA,&PINA,7}, - {&DDRG,&PORTG,&PING,2}, - {&DDRC,&PORTC,&PINC,7}, - {&DDRC,&PORTC,&PINC,6}, - {&DDRC,&PORTC,&PINC,5}, - {&DDRC,&PORTC,&PINC,4}, - {&DDRC,&PORTC,&PINC,3}, - {&DDRC,&PORTC,&PINC,2}, - {&DDRC,&PORTC,&PINC,1}, - {&DDRC,&PORTC,&PINC,0}, - {&DDRG,&PORTG,&PING,1}, - {&DDRG,&PORTG,&PING,0}}; - -void init_ports(void) -{ - //auxiliar LED - DDRE|=0x04; - clear_led(); - - // general purpose input/output - // all inputs by default - DDRA=0x00; - DDRC=0x00; - DDRG&=0xF8; - - // input selector - DDRG&=0xE7; -} - -void config_port(uint8_t port_id,uint8_t dir) -{ - if(port_id>=0 && port_id<NUM_GPIO) - { - if(dir==OUTPUT)// configure as an output - { - *(gpio_bits[port_id].dir_reg)|=0x01<<gpio_bits[port_id].bit; - ram_data[GPIO0_config+port_id*2]=0x01; - } - else// configure as an input - { - *(gpio_bits[port_id].dir_reg)&=~(0x01<<gpio_bits[port_id].bit); - ram_data[GPIO0_config+port_id*2]=0x00; - } - } -} - -uint8_t get_port_config(uint8_t port_id) -{ - uint8_t dir; - - if(port_id>=0 && port_id<NUM_GPIO) - { - dir=(*(gpio_bits[port_id].dir_reg)&(0x01<<gpio_bits[port_id].bit)); - if(dir==0x00) - return INPUT; - else - return OUTPUT; - } - else - return INPUT; -} - -void set_port(uint8_t port_id) -{ - if(port_id>=0 && port_id<NUM_GPIO) - { - *(gpio_bits[port_id].write_reg)|=0x01<<gpio_bits[port_id].bit; - ram_data[GPIO0_data+port_id*2]=0x01; - } -} - -void clear_port(uint8_t port_id) -{ - if(port_id>=0 && port_id<NUM_GPIO) - { - *(gpio_bits[port_id].write_reg)&=~(0x01<<gpio_bits[port_id].bit); - ram_data[GPIO0_data+port_id*2]=0x00; - } -} - -uint8_t read_port(uint8_t port_id) -{ - uint8_t value; - if(port_id>=0 && port_id<NUM_GPIO) - { - value=((*(gpio_bits[port_id].read_reg))&(0x01<<gpio_bits[port_id].bit)); - if(value==0x00) - { - ram_data[GPIO0_data+port_id]=0x00; - return 0x00; - } - else - { - ram_data[GPIO0_data+port_id]=0x01; - return 0x01; - } - } - else - return 0x00; -} - -void set_led(void) -{ - PORTE&=0xFB; - ram_data[LED]=0x01; -} - -void clear_led(void) -{ - PORTE|=0x04; - ram_data[LED]=0x00; -} - -void toggle_led(void) -{ - PORTE^=0x04; - ram_data[LED]^=0x01; -} - -uint8_t get_selector_value(void) -{ - ram_data[SWITCHES]=(PING&0x18)>>3; - return ((PING&0x18)>>3); -} - diff --git a/src/pwm.c b/src/pwm.c deleted file mode 100644 index 3d882ca6acfafee9adabf68616d36f7f8a295bc3..0000000000000000000000000000000000000000 --- a/src/pwm.c +++ /dev/null @@ -1,162 +0,0 @@ -#include "pwm.h" -#include "mem.h" -#include "ports.h" - -#define DEFAULT_PWM_FREQ 50// Hz -#define DEFAULT_PWM_DUTY 50// % - -#define PWM_MAX_CHANNELS 4 - -/* private variables */ -uint32_t pwm_top_value; -uint8_t pwm_prescaler_mask; -uint8_t pwm_running; -uint8_t pwm_duty_cycle[PWM_MAX_CHANNELS]; - -/* public functions */ -void pwm_init(void) -{ - /* configure the IO pins */ - DDRE|=0x38; - DDRB|=0x80; - - /* initialize internal variables */ - pwm_top_value=40000; - ram_data[PWM_FREQ_L]=50; - ram_data[PWM_FREQ_H]=0; - pwm_prescaler_mask=2; - pwm_running=0x00; - - pwm_set_duty_cycle(pwm0,DEFAULT_PWM_DUTY); - pwm_set_duty_cycle(pwm1,DEFAULT_PWM_DUTY); - pwm_set_duty_cycle(pwm2,DEFAULT_PWM_DUTY); - pwm_set_duty_cycle(pwm3,DEFAULT_PWM_DUTY); - - /* configure the timer 3 */ - TCNT3H=0x00; - TCNT3L=0x00; - /* set the timer mode */ - TCCR3A=(1<<WGM31);// all three channels in fast PWM mode, output disabled - TCCR3B=(1<<WGM33)|(1<<WGM32);// no clock source, fast PWM mode - // no interrupts enabled -} - -void pwm_start(void) -{ - TCNT3H=0x00; - TCNT3L=0x00; - // set the prescaler value to the correct value - /* set the prescaler value */ - TCCR3B&=0xF8; - TCCR3B|=pwm_prescaler_mask; - /* set the top value */ - ICR3H=(pwm_top_value>>8)&0xFF; - ICR3L=(pwm_top_value)&0xFF; - pwm_running=0x01; - ram_data[PWM_CONTROL]|=0x04; -} - -void pwm_stop(void) -{ - /* set the prescaler to 0 (no clock source) */ - TCCR3B&=0xF8; - pwm_running=0x00; - ram_data[PWM_CONTROL]&=0xFB; -} - -void pwm_enable_ch(pwm_id_t id) -{ - switch(id) - { - case pwm0: TCCR3A|=(1<<COMA1); - ram_data[PWM_CONTROL]|=0x10; - break; - case pwm1: TCCR3A|=(1<<COMB1); - ram_data[PWM_CONTROL]|=0x20; - break; - case pwm2: TCCR3A|=(1<<COMC1); - ram_data[PWM_CONTROL]|=0x40; - break; - case pwm3: break; - } -} - -void pwm_disable_ch(pwm_id_t id) -{ - switch(id) - { - case pwm0: TCCR3A&=~(1<<COMA1); - ram_data[PWM_CONTROL]&=0xEF; - break; - case pwm1: TCCR3A&=~(1<<COMB1); - ram_data[PWM_CONTROL]&=0xDF; - break; - case pwm2: TCCR3A&=~(1<<COMC1); - ram_data[PWM_CONTROL]&=0xBF; - break; - case pwm3: break; - } -} - -void pwm_set_frequency(uint16_t freq_hz) -{ - uint32_t prescaler_values[5]={1,8,64,256,1024}; - uint32_t den; - uint8_t i; - - for(i=0;i<5;i++) - { - den=freq_hz*prescaler_values[i]; - pwm_top_value=(((uint32_t)16000000)/den)-1; - if(pwm_top_value<65536) - { - /* adjust the duty cyle */ - pwm_set_duty_cycle(pwm0,pwm_duty_cycle[0]); - pwm_set_duty_cycle(pwm1,pwm_duty_cycle[1]); - pwm_set_duty_cycle(pwm2,pwm_duty_cycle[2]); - pwm_set_duty_cycle(pwm3,pwm_duty_cycle[3]); - if(pwm_running) - { - /* set the prescaler value */ - TCCR3B&=0xF8; - TCCR3B|=(i+1); - /* set the top value */ - ICR3H=(pwm_top_value>>8)&0xFF; - ICR3L=(pwm_top_value)&0xFF; - } - else - pwm_prescaler_mask=(i+1); - ram_data[PWM_FREQ_L]=freq_hz%256; - ram_data[PWM_FREQ_H]=freq_hz/256; - break; - } - } -} - -void pwm_set_duty_cycle(pwm_id_t id,uint8_t duty) -{ - uint16_t compare_value; - - compare_value=(pwm_top_value/100)*duty; - - switch(id) - { - case pwm0: OCR3AH=(compare_value>>8)&0xFF; - OCR3AL=(compare_value&0xFF); - pwm_duty_cycle[0]=duty; - ram_data[PWM_CH0_DUTY]=duty; - break; - case pwm1: OCR3BH=(compare_value>>8)&0xFF; - OCR3BL=(compare_value&0xFF); - pwm_duty_cycle[1]=duty; - ram_data[PWM_CH1_DUTY]=duty; - break; - case pwm2: OCR3CH=(compare_value>>8)&0xFF; - OCR3CL=(compare_value&0xFF); - pwm_duty_cycle[2]=duty; - ram_data[PWM_CH2_DUTY]=duty; - break; - case pwm3: break; - } -} - diff --git a/src/uart_ttl.c b/src/uart_ttl.c deleted file mode 100644 index ef05e726cb4955a885a31bfb6a41f78547e9a7f2..0000000000000000000000000000000000000000 --- a/src/uart_ttl.c +++ /dev/null @@ -1,246 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include "uart_ttl.h" -#include "mem.h" - -#define UART_TTL_DEFAULT_BAUDRATE 9600 - -#define UART_TTL_RX_BUFFER_SIZE 0x20 - -#define UART_TTL_TX_PORT PORTE -#define UART_TTL_TX_DDR DDRE -#define UART_TTL_TX_PIN PE6 - -#define UART_TLL_RX_PORT PORTE -#define UART_TTL_RX_DDR DDRE -#define UART_TLL_RX_PORTIN PINE -#define UART_TTL_RX_PIN PE7 - -// uartsw transmit status and data variables -volatile uint8_t uart_ttl_tx_busy; -volatile uint8_t uart_ttl_tx_data; -volatile uint8_t uart_ttl_tx_bit_num; - -// baud rate common to transmit and receive -volatile uint16_t uart_ttl_baudrate_div; - -// uartsw receive status and data variables -volatile uint8_t uart_ttl_rx_busy; -volatile uint8_t uart_ttl_rx_data; -volatile uint8_t uart_ttl_rx_bit_num; - -/* rx buffer */ -unsigned char uart_ttl_rx_data_buffer[UART_TTL_RX_BUFFER_SIZE]; -unsigned char uart_ttl_rx_read_ptr; -unsigned char uart_ttl_rx_write_ptr; -unsigned char uart_ttl_rx_num_data; - -/* private functions */ - -/* interrupt handlers */ -ISR(TIMER3_CAPT_vect)//RX -{ - uint16_t capture; - // clear ICP interrupt flag - ETIFR|=(1<<ICF3); - - if(!uart_ttl_rx_busy) - { - // disable input capture interrutps - ETIMSK&=~(1<<TICIE3); - capture=TCNT3+uart_ttl_baudrate_div + uart_ttl_baudrate_div/2; - // schedule data bit sampling 1.5 bit periods from now - OCR3BH=(capture>>8)&0xFF; - OCR3BL=capture&0xFF; - // clear OC1B interrupt flag - ETIFR|=(1<<OCF3B); - // enable OC1B interrupt - ETIMSK|=(1<<OCIE3B); - // set start bit flag - uart_ttl_rx_busy = 0x01; - // reset bit counter - uart_ttl_rx_bit_num = 0; - // reset data - uart_ttl_rx_data = 0; - } -} - -ISR(TIMER3_COMPB_vect)//RX -{ - uint16_t capture; - - // clear OC1B interrupt flag - ETIFR|=(1<<OCF3B); - // shift data byte to make room for new bit - uart_ttl_rx_data = uart_ttl_rx_data>>1; - - if(UART_TLL_RX_PORTIN&(1<<UART_TTL_RX_PIN)) - uart_ttl_rx_data |= 0x80; - - // increment bit counter - uart_ttl_rx_bit_num++; - // schedule next bit sample - capture=OCR3B+uart_ttl_baudrate_div; - OCR3BH=(capture>>8)&0xFF; - OCR3BL=capture&0xFF; - - // check if we have a full byte - if(uart_ttl_rx_bit_num >= 8) - { - // save data in receive buffer - uart_ttl_rx_data_buffer[uart_ttl_rx_write_ptr]=uart_ttl_rx_data; - uart_ttl_rx_write_ptr=(uart_ttl_rx_write_ptr+1)%UART_TTL_RX_BUFFER_SIZE; - uart_ttl_rx_num_data++; - // disable OC1B interrupt - ETIMSK&=~(1<<OCIE3B); - // enable ICP interrupt - ETIMSK|=(1<<TICIE3); - // clear start bit flag - uart_ttl_rx_busy = 0x00; - } -} - -ISR(TIMER3_COMPA_vect)//TX -{ - uint16_t capture; - - // clear OC1B interrupt flag - ETIFR|=(1<<OCF3A); - if(uart_ttl_tx_bit_num) - { - if(uart_ttl_tx_bit_num>1) - { - // transmit data bits (inverted, LSB first) - if((uart_ttl_tx_data&0x01)) - UART_TTL_TX_PORT|=(1<<UART_TTL_TX_PIN); - else - UART_TTL_TX_PORT&=~(1<<UART_TTL_TX_PIN); - // shift bits down - uart_ttl_tx_data = uart_ttl_tx_data>>1; - } - else - UART_TTL_TX_PORT|=(1<<UART_TTL_TX_PIN); - // schedule the next bit - capture=OCR3A+uart_ttl_baudrate_div; - OCR3AH=(capture>>8)&0xFF; - OCR3AL=capture&0xFF; - // count down - uart_ttl_tx_bit_num--; - } - else - { - // enable OC1A interrupt - ETIMSK&=~(1<<OCIE3A); - uart_ttl_tx_busy = 0x00; - } -} - -/* public functions */ -void uart_ttl_init(void) -{ - // configure GPIO ports - UART_TTL_TX_DDR|=(1<<UART_TTL_TX_PIN);// output - UART_TTL_RX_DDR&=~(1<<UART_TTL_RX_PIN);//input - // set input to 0 - UART_TLL_RX_PORT&=~(1<<UART_TTL_RX_PIN); - // initialize baud rate - uart_ttl_set_baudrate(UART_TTL_DEFAULT_BAUDRATE); - ram_data[UART_TTL_BAUDRATE_L]=UART_TTL_DEFAULT_BAUDRATE%256; - ram_data[UART_TTL_BAUDRATE_H]=UART_TTL_DEFAULT_BAUDRATE/256; - - // setup the transmitter - uart_ttl_tx_busy = 0x00; - ETIMSK&=~(1<<OCIE3A); - - // setup the receiver - uart_ttl_rx_busy = 0x00; - ETIMSK&=~(1<<OCIE3B); - // trigger on falling edge - TCCR3B&=~(1<<ICES3); - // disable ICP interrupt - ETIMSK&=~(1<<TICIE3); - - /* initlaize buffer variables */ - uart_ttl_rx_read_ptr=0; - uart_ttl_rx_write_ptr=0; - uart_ttl_rx_num_data=0; -} - -void uart_ttl_start(void) -{ - ETIMSK&=~(1<<OCIE3A); - ETIMSK&=~(1<<OCIE3B); - // clear ICP interrupt flag - ETIFR|=(1<<ICF3); - ETIMSK|=(1<<TICIE3); - ram_data[UART_TTL_CONTROL]|=0x20; -} - -void uart_ttl_stop(void) -{ - // disable interrupts - ETIMSK&=~(1<<OCIE3A); - ETIMSK&=~(1<<OCIE3B); - ETIMSK&=~(1<<TICIE3); - ram_data[UART_TTL_CONTROL]&=0xDF; -} - -void uart_ttl_set_baudrate(uint32_t baudrate) -{ - TCCR3B&=0xF8; - TCCR3B|=0x01; - // calculate division factor for requested baud rate, and set it - uart_ttl_baudrate_div = (uint16_t)((F_CPU+(baudrate/2L))/(baudrate*1L)); -} - -void uart_ttl_send_byte(uint8_t data) -{ - uint16_t capture; - - // wait until uart is ready - while(uart_ttl_tx_busy); - // set busy flag - uart_ttl_tx_busy = 0x01; - // save data - uart_ttl_tx_data = data; - // set number of bits (+1 for stop bit) - uart_ttl_tx_bit_num = 9; - - UART_TTL_TX_PORT&=~(1<<UART_TTL_TX_PIN); - - capture=TCNT3+uart_ttl_baudrate_div; - OCR3AH=(capture>>8)&0xFF; - OCR3AL=capture&0xFF; - // clear interrupts - ETIFR|=(1<<OCF3A); - // enable OC1A interrupt - ETIMSK|=(1<<OCIE3A); -} - -uint8_t uart_ttl_is_sending(void) -{ - return uart_ttl_tx_busy; -} - -uint8_t uart_ttl_receive_byte(uint8_t* data) -{ - // make sure we have a receive buffer - if(uart_ttl_rx_num_data>0) - { - *data=uart_ttl_rx_data_buffer[uart_ttl_rx_read_ptr]; - uart_ttl_rx_read_ptr=(uart_ttl_rx_read_ptr+1)%UART_TTL_RX_BUFFER_SIZE; - uart_ttl_rx_num_data--; - // make sure we have data - return 0x01; - } - else - return 0x00; -} - -uint8_t uart_ttl_is_data_available(void) -{ - if(uart_ttl_rx_num_data>0) - return 0x01; - else - return 0x00; -} diff --git a/src/uart_usb.c b/src/uart_usb.c deleted file mode 100644 index 8c82b88e76fad855cc4d7b0ddbd58928b987eef8..0000000000000000000000000000000000000000 --- a/src/uart_usb.c +++ /dev/null @@ -1,246 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include "uart_usb.h" -#include "mem.h" - -#define UART_USB_DEFAULT_BAUDRATE 9600 - -#define UART_USB_RX_BUFFER_SIZE 0x20 - -#define UART_USB_TX_PORT PORTD -#define UART_USB_TX_DDR DDRD -#define UART_USB_TX_PIN PD5 - -#define UART_USB_RX_PORT PORTD -#define UART_USB_RX_DDR DDRD -#define UART_USB_RX_PORTIN PIND -#define UART_USB_RX_PIN PD4 - -// uartsw transmit status and data variables -volatile uint8_t uart_usb_tx_busy; -volatile uint8_t uart_usb_tx_data; -volatile uint8_t uart_usb_tx_bit_num; - -// baud rate common to transmit and receive -volatile uint16_t uart_usb_baudrate_div; - -// uartsw receive status and data variables -volatile uint8_t uart_usb_rx_busy; -volatile uint8_t uart_usb_rx_data; -volatile uint8_t uart_usb_rx_bit_num; - -/* rx buffer */ -unsigned char uart_usb_rx_data_buffer[UART_USB_RX_BUFFER_SIZE]; -unsigned char uart_usb_rx_read_ptr; -unsigned char uart_usb_rx_write_ptr; -unsigned char uart_usb_rx_num_data; - -/* private functions */ - -/* interrupt handlers */ -ISR(TIMER1_CAPT_vect)//RX -{ - uint16_t capture; - // clear ICP interrupt flag - TIFR|=(1<<ICF1); - - if(!uart_usb_rx_busy) - { - // disable input capture interrutps - TIMSK&=~(1<<TICIE1); - capture=TCNT1+uart_usb_baudrate_div + uart_usb_baudrate_div/2; - // schedule data bit sampling 1.5 bit periods from now - OCR1BH=(capture>>8)&0xFF; - OCR1BL=capture&0xFF; - // clear OC1B interrupt flag - TIFR|=(1<<OCF1B); - // enable OC1B interrupt - TIMSK|=(1<<OCIE1B); - // set start bit flag - uart_usb_rx_busy = 0x01; - // reset bit counter - uart_usb_rx_bit_num = 0; - // reset data - uart_usb_rx_data = 0; - } -} - -ISR(TIMER1_COMPB_vect)//RX -{ - uint16_t capture; - - // clear OC1B interrupt flag - TIFR|=(1<<OCF1B); - // shift data byte to make room for new bit - uart_usb_rx_data = uart_usb_rx_data>>1; - - if(UART_USB_RX_PORTIN&(1<<UART_USB_RX_PIN)) - uart_usb_rx_data |= 0x80; - - // increment bit counter - uart_usb_rx_bit_num++; - // schedule next bit sample - capture=OCR1B+uart_usb_baudrate_div; - OCR1BH=(capture>>8)&0xFF; - OCR1BL=capture&0xFF; - - // check if we have a full byte - if(uart_usb_rx_bit_num >= 8) - { - // save data in receive buffer - uart_usb_rx_data_buffer[uart_usb_rx_write_ptr]=uart_usb_rx_data; - uart_usb_rx_write_ptr=(uart_usb_rx_write_ptr+1)%UART_USB_RX_BUFFER_SIZE; - uart_usb_rx_num_data++; - // disable OC1B interrupt - TIMSK&=~(1<<OCIE1B); - // enable ICP interrupt - TIMSK|=(1<<TICIE1); - // clear start bit flag - uart_usb_rx_busy = 0x00; - } -} - -ISR(TIMER1_COMPA_vect)//TX -{ - uint16_t capture; - - // clear OC1B interrupt flag - TIFR|=(1<<OCF1A); - if(uart_usb_tx_bit_num) - { - if(uart_usb_tx_bit_num>1) - { - // transmit data bits (inverted, LSB first) - if((uart_usb_tx_data&0x01)) - UART_USB_TX_PORT|=(1<<UART_USB_TX_PIN); - else - UART_USB_TX_PORT&=~(1<<UART_USB_TX_PIN); - // shift bits down - uart_usb_tx_data = uart_usb_tx_data>>1; - } - else - UART_USB_TX_PORT|=(1<<UART_USB_TX_PIN); - // schedule the next bit - capture=OCR1A+uart_usb_baudrate_div; - OCR1AH=(capture>>8)&0xFF; - OCR1AL=capture&0xFF; - // count down - uart_usb_tx_bit_num--; - } - else - { - // enable OC1A interrupt - TIMSK&=~(1<<OCIE1A); - uart_usb_tx_busy = 0x00; - } -} - -/* public functions */ -void uart_usb_init(void) -{ - // configure GPIO ports - UART_USB_TX_DDR|=(1<<UART_USB_TX_PIN);// output - UART_USB_RX_DDR&=~(1<<UART_USB_RX_PIN);//input - // set input to 0 - UART_USB_RX_PORT&=~(1<<UART_USB_RX_PIN); - // initialize baud rate - uart_usb_set_baudrate(UART_USB_DEFAULT_BAUDRATE); - ram_data[UART_TTL_BAUDRATE_L]=UART_USB_DEFAULT_BAUDRATE%256; - ram_data[UART_TTL_BAUDRATE_H]=UART_USB_DEFAULT_BAUDRATE/256; - - // setup the transmitter - uart_usb_tx_busy = 0x00; - TIMSK&=~(1<<OCIE1A); - - // setup the receiver - uart_usb_rx_busy = 0x00; - TIMSK&=~(1<<OCIE1B); - // trigger on falling edge - TCCR1B&=~(1<<ICES1); - // enable ICP interrupt - TIMSK|=(1<<TICIE1); - - /* initlaize buffer variables */ - uart_usb_rx_read_ptr=0; - uart_usb_rx_write_ptr=0; - uart_usb_rx_num_data=0; -} - -void uart_usb_start(void) -{ - TIMSK&=~(1<<OCIE1A); - TIMSK&=~(1<<OCIE1B); - // clear ICP interrupt flag - TIFR|=(1<<ICF1); - TIMSK|=(1<<TICIE1); - ram_data[UART_USB_CONTROL]|=0x20; -} - -void uart_usb_stop(void) -{ - // disable interrupts - TIMSK&=~(1<<OCIE1A); - TIMSK&=~(1<<OCIE1B); - TIMSK&=~(1<<TICIE1); - ram_data[UART_USB_CONTROL]&=0xDF; -} - -void uart_usb_set_baudrate(uint32_t baudrate) -{ - TCCR1B&=0xF8; - TCCR1B|=0x01; - // calculate division factor for requested baud rate, and set it - uart_usb_baudrate_div = (uint16_t)((F_CPU+(baudrate/2L))/(baudrate*1L)); -} - -void uart_usb_send_byte(uint8_t data) -{ - uint16_t capture; - - // wait until uart is ready - while(uart_usb_tx_busy); - // set busy flag - uart_usb_tx_busy = 0x01; - // save data - uart_usb_tx_data = data; - // set number of bits (+1 for stop bit) - uart_usb_tx_bit_num = 9; - - UART_USB_TX_PORT&=~(1<<UART_USB_TX_PIN); - - capture=TCNT1+uart_usb_baudrate_div; - OCR1AH=(capture>>8)&0xFF; - OCR1AL=capture&0xFF; - // clear interrupts - TIFR|=(1<<OCF1A); - // enable OC1A interrupt - TIMSK|=(1<<OCIE1A); -} - -uint8_t uart_usb_is_sending(void) -{ - return uart_usb_tx_busy; -} - -uint8_t uart_usb_receive_byte(uint8_t* data) -{ - // make sure we have a receive buffer - if(uart_usb_rx_num_data>0) - { - *data=uart_usb_rx_data_buffer[uart_usb_rx_read_ptr]; - uart_usb_rx_read_ptr=(uart_usb_rx_read_ptr+1)%UART_USB_RX_BUFFER_SIZE; - uart_usb_rx_num_data--; - // make sure we have data - return 0x01; - } - else - return 0x00; -} - -uint8_t uart_usb_is_data_available(void) -{ - if(uart_usb_rx_num_data>0) - return 0x01; - else - return 0x00; -} diff --git a/timer128.c b/timer128.c new file mode 100755 index 0000000000000000000000000000000000000000..eb608737ccb9c137d898cf401258c743e8a020ae --- /dev/null +++ b/timer128.c @@ -0,0 +1,687 @@ +/*! \file timer128.c \brief System Timer function library for Mega128. */ +//***************************************************************************** +// +// File Name : 'timer128.c' +// Title : System Timer function library for Mega128 +// Author : Pascal Stang - Copyright (C) 2000-2003 +// Created : 11/22/2000 +// Revised : 02/24/2003 +// Version : 1.2 +// Target MCU : Atmel AVR Series +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/pgmspace.h> +#include <avr/sleep.h> + +#include "global.h" +#include "timer128.h" + +// Program ROM constants +// the prescale division values stored in order of timer control register index +// STOP, CLK, CLK/8, CLK/64, CLK/256, CLK/1024 +const unsigned short __attribute__ ((progmem)) TimerPrescaleFactor[] = {0,1,8,64,256,1024}; +// the prescale division values stored in order of timer control register index +// STOP, CLK, CLK/8, CLK/32, CLK/64, CLK/128, CLK/256, CLK/1024 +const unsigned short __attribute__ ((progmem)) TimerRTCPrescaleFactor[] = {0,1,8,32,64,128,256,1024}; + +// Global variables +// time registers +volatile unsigned long TimerPauseReg; +volatile unsigned long Timer0Reg0; +volatile unsigned long Timer0Reg1; +volatile unsigned long Timer2Reg0; +volatile unsigned long Timer2Reg1; + +typedef void (*voidFuncPtr)(void); +volatile static voidFuncPtr TimerIntFunc[TIMER_NUM_INTERRUPTS]; + +// delay for a minimum of <us> microseconds +// the time resolution is dependent on the time the loop takes +// e.g. with 4Mhz and 5 cycles per loop, the resolution is 1.25 us +void delay_us(unsigned short time_us) +{ + unsigned short delay_loops; + register unsigned short i; + + delay_loops = (time_us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty) + + // one loop takes 5 cpu cycles + for (i=0; i < delay_loops; i++) {}; +} +/* +void delay_ms(unsigned char time_ms) +{ + unsigned short delay_count = F_CPU / 4000; + + unsigned short cnt; + asm volatile ("\n" + "L_dl1%=:\n\t" + "mov %A0, %A2\n\t" + "mov %B0, %B2\n" + "L_dl2%=:\n\t" + "sbiw %A0, 1\n\t" + "brne L_dl2%=\n\t" + "dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt) + :"r"(time_ms), "r"((unsigned short) (delay_count)) + ); +} +*/ +void timerInit(void) +{ + u08 intNum; + // detach all user functions from interrupts + for(intNum=0; intNum<TIMER_NUM_INTERRUPTS; intNum++) + timerDetach(intNum); + + // initialize all timers + timer0Init(); + timer1Init(); + timer2Init(); + timer3Init(); +} + +void timer0Init() +{ + // initialize timer 0 + timer0SetPrescaler( TIMER0PRESCALE ); // set prescaler + outb(TCNT0, 0); // reset TCNT0 + sbi(TIMSK, TOIE0); // enable TCNT0 overflow interrupt + + timer0ClearOverflowCount(); // initialize time registers +} + +void timer1Init(void) +{ + // initialize timer 1 + timer1SetPrescaler( TIMER1PRESCALE ); // set prescaler + outb(TCNT1H, 0); // reset TCNT1 + outb(TCNT1L, 0); + sbi(TIMSK, TOIE1); // enable TCNT1 overflow +} + +void timer2Init(void) +{ + // initialize timer 2 + timer2SetPrescaler( TIMER2PRESCALE ); // set prescaler + outb(TCNT2, 0); // reset TCNT2 + sbi(TIMSK, TOIE2); // enable TCNT2 overflow + + timer2ClearOverflowCount(); // initialize time registers +} + +void timer3Init(void) +{ + // initialize timer 3 + timer3SetPrescaler( TIMER3PRESCALE ); // set prescaler + outb(TCNT3H, 0); // reset TCNT3 + outb(TCNT3L, 0); + sbi(ETIMSK, TOIE3); // enable TCNT3 overflow +} + +void timer0SetPrescaler(u08 prescale) +{ + // set prescaler on timer 0 + outb(TCCR0, (inb(TCCR0) & ~TIMER_PRESCALE_MASK) | prescale); +} + +void timer1SetPrescaler(u08 prescale) +{ + // set prescaler on timer 1 + outb(TCCR1B, (inb(TCCR1B) & ~TIMER_PRESCALE_MASK) | prescale); +} + +void timer2SetPrescaler(u08 prescale) +{ + // set prescaler on timer 2 + outb(TCCR2, (inb(TCCR2) & ~TIMER_PRESCALE_MASK) | prescale); +} + +void timer3SetPrescaler(u08 prescale) +{ + // set prescaler on timer 2 + outb(TCCR3B, (inb(TCCR3B) & ~TIMER_PRESCALE_MASK) | prescale); +} + +u16 timer0GetPrescaler(void) +{ + // get the current prescaler setting + return (pgm_read_word(TimerPrescaleFactor+(inb(TCCR0) & TIMER_PRESCALE_MASK))); +} + +u16 timer1GetPrescaler(void) +{ + // get the current prescaler setting + return (pgm_read_word(TimerPrescaleFactor+(inb(TCCR1B) & TIMER_PRESCALE_MASK))); +} + +u16 timer2GetPrescaler(void) +{ + // get the current prescaler setting + return (pgm_read_word(TimerPrescaleFactor+(inb(TCCR2) & TIMER_PRESCALE_MASK))); +} + +u16 timer3GetPrescaler(void) +{ + // get the current prescaler setting + return (pgm_read_word(TimerPrescaleFactor+(inb(TCCR3B) & TIMER_PRESCALE_MASK))); +} + +void timerAttach(u08 interruptNum, void (*userFunc)(void) ) +{ + // make sure the interrupt number is within bounds + if(interruptNum < TIMER_NUM_INTERRUPTS) + { + // set the interrupt function to run + // the supplied user's function + TimerIntFunc[interruptNum] = userFunc; + } +} + +void timerDetach(u08 interruptNum) +{ + // make sure the interrupt number is within bounds + if(interruptNum < TIMER_NUM_INTERRUPTS) + { + // set the interrupt function to run nothing + TimerIntFunc[interruptNum] = 0; + } +} + +void timerPause(unsigned short pause_ms) +{ + // pauses for exactly <pause_ms> number of milliseconds + u08 timerThres; + u32 ticRateHz; + u32 pause; + + // capture current pause timer value + timerThres = inb(TCNT2); + // reset pause timer overflow count + TimerPauseReg = 0; + // calculate delay for [pause_ms] milliseconds + // prescaler division = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR2))) + ticRateHz = F_CPU/timer2GetPrescaler(); + // precision management + // prevent overflow and precision underflow + // -could add more conditions to improve accuracy + if( ((ticRateHz < 429497) && (pause_ms <= 10000)) ) + pause = (pause_ms*ticRateHz)/1000; + else + pause = pause_ms*(ticRateHz/1000); + + // loop until time expires + while( ((TimerPauseReg<<8) | inb(TCNT2)) < (pause+timerThres) ) + { + if( TimerPauseReg < (pause>>8)); + { + // save power by idling the processor + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_mode(); + } + } +} + +void timer0ClearOverflowCount(void) +{ + // clear the timer overflow counter registers + Timer0Reg0 = 0; // initialize time registers + Timer0Reg1 = 0; // initialize time registers +} + +long timer0GetOverflowCount(void) +{ + // return the current timer overflow count + // (this is since the last timer0ClearOverflowCount() command was called) + return Timer0Reg0; +} + +void timer2ClearOverflowCount(void) +{ + // clear the timer overflow counter registers + Timer2Reg0 = 0; // initialize time registers + Timer2Reg1 = 0; // initialize time registers +} + +long timer2GetOverflowCount(void) +{ + // return the current timer overflow count + // (this is since the last timer2ClearOverflowCount() command was called) + return Timer2Reg0; +} + + +void timer1PWMInit(u08 bitRes) +{ + // configures timer1 for use with PWM output + // on pins OC1A, OC1B, and OC1C + + // enable Timer1 as 8,9,10bit PWM + if(bitRes == 9) + { // 9bit mode + sbi(TCCR1A,WGMA1); + cbi(TCCR1A,WGMA0); + } + else if( bitRes == 10 ) + { // 10bit mode + sbi(TCCR1A,WGMA1); + sbi(TCCR1A,WGMA0); + } + else + { // default 8bit mode + cbi(TCCR1A,WGMA1); + sbi(TCCR1A,WGMA0); + } + + // set clear-timer-on-compare-match + //cbi(TCCR1B,CTC1); + // clear output compare value A + outb(OCR1AH, 0); + outb(OCR1AL, 0); + // clear output compare value B + outb(OCR1BH, 0); + outb(OCR1BL, 0); + // clear output compare value C + outb(OCR1CH, 0); + outb(OCR1CL, 0); +} + +void timer1PWMInitICR(u16 topcount) +{ + // set PWM mode with ICR top-count + cbi(TCCR1A,WGM10); + sbi(TCCR1A,WGM11); + sbi(TCCR1B,WGM12); + sbi(TCCR1B,WGM13); + + // set top count value + ICR1H = (u08)(topcount>>8); + ICR1L = (u08)topcount; + + // clear output compare value A + outb(OCR1AH, 0); + outb(OCR1AL, 0); + // clear output compare value B + outb(OCR1BH, 0); + outb(OCR1BL, 0); + // clear output compare value C + outb(OCR1CH, 0); + outb(OCR1CL, 0); +} + +void timer1PWMOff(void) +{ + // turn off PWM on Timer1 + cbi(TCCR1A,WGMA1); + cbi(TCCR1A,WGMA0); + // clear (disable) clear-timer-on-compare-match + //cbi(TCCR1B,CTC1); + // set PWM1A/B/C (OutputCompare action) to none + timer1PWMAOff(); + timer1PWMBOff(); + timer1PWMCOff(); +} + +void timer1PWMAOn(void) +{ + // turn on channel A (OC1A) PWM output + // set OC1A as non-inverted PWM + sbi(TCCR1A,COMA1); + cbi(TCCR1A,COMA0); +} + +void timer1PWMBOn(void) +{ + // turn on channel B (OC1B) PWM output + // set OC1B as non-inverted PWM + sbi(TCCR1A,COMB1); + cbi(TCCR1A,COMB0); +} + +void timer1PWMCOn(void) +{ + // turn on channel C (OC1C) PWM output + // set OC1C as non-inverted PWM + sbi(TCCR1A,COMC1); + cbi(TCCR1A,COMC0); +} + +void timer1PWMAOff(void) +{ + // turn off channel A (OC1A) PWM output + // set OC1A (OutputCompare action) to none + cbi(TCCR1A,COMA1); + cbi(TCCR1A,COMA0); +} + +void timer1PWMBOff(void) +{ + // turn off channel B (OC1B) PWM output + // set OC1B (OutputCompare action) to none + cbi(TCCR1A,COMB1); + cbi(TCCR1A,COMB0); +} + +void timer1PWMCOff(void) +{ + // turn off channel C (OC1C) PWM output + // set OC1C (OutputCompare action) to none + cbi(TCCR1A,COMC1); + cbi(TCCR1A,COMC0); +} + +void timer1PWMASet(u16 pwmDuty) +{ + // set PWM (output compare) duty for channel A + // this PWM output is generated on OC1A pin + // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM + // pwmDuty should be in the range 0-511 for 9bit PWM + // pwmDuty should be in the range 0-1023 for 10bit PWM + outb(OCR1AH, (pwmDuty>>8)); // set the high 8bits of OCR1A + outb(OCR1AL, (pwmDuty&0x00FF)); // set the low 8bits of OCR1A +} + +void timer1PWMBSet(u16 pwmDuty) +{ + // set PWM (output compare) duty for channel B + // this PWM output is generated on OC1B pin + // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM + // pwmDuty should be in the range 0-511 for 9bit PWM + // pwmDuty should be in the range 0-1023 for 10bit PWM + outb(OCR1BH, (pwmDuty>>8)); // set the high 8bits of OCR1B + outb(OCR1BL, (pwmDuty&0x00FF)); // set the low 8bits of OCR1B +} + +void timer1PWMCSet(u16 pwmDuty) +{ + // set PWM (output compare) duty for channel C + // this PWM output is generated on OC1C pin + // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM + // pwmDuty should be in the range 0-511 for 9bit PWM + // pwmDuty should be in the range 0-1023 for 10bit PWM + outb(OCR1CH, (pwmDuty>>8)); // set the high 8bits of OCR1C + outb(OCR1CL, (pwmDuty&0x00FF)); // set the low 8bits of OCR1C +} + + +void timer3PWMInit(u08 bitRes) +{ + // configures timer1 for use with PWM output + // on pins OC3A, OC3B, and OC3C + + // enable Timer3 as 8,9,10bit PWM + if(bitRes == 9) + { // 9bit mode + sbi(TCCR3A,WGMA1); + cbi(TCCR3A,WGMA0); + } + else if( bitRes == 10 ) + { // 10bit mode + sbi(TCCR3A,WGMA1); + sbi(TCCR3A,WGMA0); + } + else + { // default 8bit mode + cbi(TCCR3A,WGMA1); + sbi(TCCR3A,WGMA0); + } + + // set clear-timer-on-compare-match + //cbi(TCCR3B,CTC1); + // clear output compare value A + outb(OCR3AH, 0); + outb(OCR3AL, 0); + // clear output compare value B + outb(OCR3BH, 0); + outb(OCR3BL, 0); + // clear output compare value B + outb(OCR3CH, 0); + outb(OCR3CL, 0); +} + +void timer3PWMInitICR(u16 topcount) +{ + // set PWM mode with ICR top-count + cbi(TCCR3A,WGM30); + sbi(TCCR3A,WGM31); + sbi(TCCR3B,WGM32); + sbi(TCCR3B,WGM33); + + // set top count value + ICR3H = (u08)(topcount>>8); + ICR3L = (u08)topcount; + + // clear output compare value A + outb(OCR3AH, 0); + outb(OCR3AL, 0); + // clear output compare value B + outb(OCR3BH, 0); + outb(OCR3BL, 0); + // clear output compare value C + outb(OCR3CH, 0); + outb(OCR3CL, 0); +} + +void timer3PWMOff(void) +{ + // turn off PWM mode on Timer3 + cbi(TCCR3A,WGMA1); + cbi(TCCR3A,WGMA0); + // clear (disable) clear-timer-on-compare-match + //cbi(TCCR3B,CTC1); + // set OC3A/B/C (OutputCompare action) to none + timer3PWMAOff(); + timer3PWMBOff(); + timer3PWMCOff(); +} + +void timer3PWMAOn(void) +{ + // turn on channel A (OC3A) PWM output + // set OC3A as non-inverted PWM + sbi(TCCR3A,COMA1); + cbi(TCCR3A,COMA0); +} + +void timer3PWMBOn(void) +{ + // turn on channel B (OC3B) PWM output + // set OC3B as non-inverted PWM + sbi(TCCR3A,COMB1); + cbi(TCCR3A,COMB0); +} + +void timer3PWMCOn(void) +{ + // turn on channel C (OC3C) PWM output + // set OC3C as non-inverted PWM + sbi(TCCR3A,COMC1); + cbi(TCCR3A,COMC0); +} + +void timer3PWMAOff(void) +{ + // turn off channel A (OC3A) PWM output + // set OC3A (OutputCompare action) to none + cbi(TCCR3A,COMA1); + cbi(TCCR3A,COMA0); +} + +void timer3PWMBOff(void) +{ + // turn off channel B (OC3B) PWM output + // set OC3B (OutputCompare action) to none + cbi(TCCR3A,COMB1); + cbi(TCCR3A,COMB0); +} + +void timer3PWMCOff(void) +{ + // turn off channel C (OC3C) PWM output + // set OC3C (OutputCompare action) to none + cbi(TCCR3A,COMC1); + cbi(TCCR3A,COMC0); +} + +void timer3PWMASet(u16 pwmDuty) +{ + // set PWM (output compare) duty for channel A + // this PWM output is generated on OC3A pin + // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM + // pwmDuty should be in the range 0-511 for 9bit PWM + // pwmDuty should be in the range 0-1023 for 10bit PWM + outb(OCR3AH, (pwmDuty>>8)); // set the high 8bits of OCR3A + outb(OCR3AL, (pwmDuty&0x00FF)); // set the low 8bits of OCR3A +} + +void timer3PWMBSet(u16 pwmDuty) +{ + // set PWM (output compare) duty for channel B + // this PWM output is generated on OC3B pin + // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM + // pwmDuty should be in the range 0-511 for 9bit PWM + // pwmDuty should be in the range 0-1023 for 10bit PWM + outb(OCR3BH, (pwmDuty>>8)); // set the high 8bits of OCR3B + outb(OCR3BL, (pwmDuty&0x00FF)); // set the low 8bits of OCR3B +} + +void timer3PWMCSet(u16 pwmDuty) +{ + // set PWM (output compare) duty for channel B + // this PWM output is generated on OC3C pin + // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM + // pwmDuty should be in the range 0-511 for 9bit PWM + // pwmDuty should be in the range 0-1023 for 10bit PWM + outb(OCR3CH, (pwmDuty>>8)); // set the high 8bits of OCR3C + outb(OCR3CL, (pwmDuty&0x00FF)); // set the low 8bits of OCR3C +} + + +//! Interrupt handler for tcnt0 overflow interrupt +TIMER_INTERRUPT_HANDLER(TIMER0_OVF_vect) +{ + Timer0Reg0++; // increment low-order counter + if(!Timer0Reg0) // if low-order counter rollover + Timer0Reg1++; // increment high-order counter + + // if a user function is defined, execute it too + if(TimerIntFunc[TIMER0OVERFLOW_INT]) + TimerIntFunc[TIMER0OVERFLOW_INT](); +} + +//! Interrupt handler for Timer1 overflow interrupt +TIMER_INTERRUPT_HANDLER(TIMER1_OVF_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER1OVERFLOW_INT]) + TimerIntFunc[TIMER1OVERFLOW_INT](); +} + +//! Interrupt handler for Timer2 overflow interrupt +TIMER_INTERRUPT_HANDLER(TIMER2_OVF_vect) +{ + Timer2Reg0++; // increment low-order counter + if(!Timer2Reg0) // if low-order counter rollover + Timer2Reg1++; // increment high-order counter + + // increment pause counter + TimerPauseReg++; + + // if a user function is defined, execute it + if(TimerIntFunc[TIMER2OVERFLOW_INT]) + TimerIntFunc[TIMER2OVERFLOW_INT](); +} + +//! Interrupt handler for Timer3 overflow interrupt +TIMER_INTERRUPT_HANDLER(TIMER3_OVF_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER3OVERFLOW_INT]) + TimerIntFunc[TIMER3OVERFLOW_INT](); +} + +//! Interrupt handler for OutputCompare0 match (OC0) interrupt +TIMER_INTERRUPT_HANDLER(TIMER0_COMP_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER0OUTCOMPARE_INT]) + TimerIntFunc[TIMER0OUTCOMPARE_INT](); +} + +//! Interrupt handler for OutputCompare1A match (OC1A) interrupt +TIMER_INTERRUPT_HANDLER(TIMER1_COMPA_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER1OUTCOMPAREA_INT]) + TimerIntFunc[TIMER1OUTCOMPAREA_INT](); +} + +//! Interrupt handler for OutputCompare1B match (OC1B) interrupt +TIMER_INTERRUPT_HANDLER(TIMER1_COMPB_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER1OUTCOMPAREB_INT]) + TimerIntFunc[TIMER1OUTCOMPAREB_INT](); +} + +//! Interrupt handler for OutputCompare1C match (OC1C) interrupt +TIMER_INTERRUPT_HANDLER(TIMER1_COMPC_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER1OUTCOMPAREC_INT]) + TimerIntFunc[TIMER1OUTCOMPAREC_INT](); +} + +//! Interrupt handler for InputCapture1(IC1) interrupt +TIMER_INTERRUPT_HANDLER(TIMER1_CAPT_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER1INPUTCAPTURE_INT]) + TimerIntFunc[TIMER1INPUTCAPTURE_INT](); +} + +//! Interrupt handler for OutputCompare2 match (OC2) interrupt +TIMER_INTERRUPT_HANDLER(TIMER2_COMP_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER2OUTCOMPARE_INT]) + TimerIntFunc[TIMER2OUTCOMPARE_INT](); +} + +//! Interrupt handler for OutputCompare3A match (OC3A) interrupt +TIMER_INTERRUPT_HANDLER(TIMER3_COMPA_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER3OUTCOMPAREA_INT]) + TimerIntFunc[TIMER3OUTCOMPAREA_INT](); +} + +//! Interrupt handler for OutputCompare3B match (OC3B) interrupt +TIMER_INTERRUPT_HANDLER(TIMER3_COMPB_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER3OUTCOMPAREB_INT]) + TimerIntFunc[TIMER3OUTCOMPAREB_INT](); +} + +//! Interrupt handler for OutputCompare3C match (OC3C) interrupt +TIMER_INTERRUPT_HANDLER(TIMER3_COMPC_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER3OUTCOMPAREC_INT]) + TimerIntFunc[TIMER3OUTCOMPAREC_INT](); +} + +//! Interrupt handler for InputCapture3 (IC3) interrupt +TIMER_INTERRUPT_HANDLER(TIMER3_CAPT_vect) +{ + // if a user function is defined, execute it + if(TimerIntFunc[TIMER3INPUTCAPTURE_INT]) + TimerIntFunc[TIMER3INPUTCAPTURE_INT](); +} diff --git a/timer128.h b/timer128.h new file mode 100755 index 0000000000000000000000000000000000000000..99ff89345c65c3d4636de2aca2070874b2003605 --- /dev/null +++ b/timer128.h @@ -0,0 +1,300 @@ +/*! \file timer128.h \brief System Timer function library for Mega128. */ +//***************************************************************************** +// +// File Name : 'timer128.h' +// Title : System Timer function library for Mega128 +// Author : Pascal Stang - Copyright (C) 2000-2003 +// Created : 11/22/2000 +// Revised : 02/10/2003 +// Version : 1.1 +// Target MCU : Atmel AVR Series +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +/// \ingroup driver_avr +/// \defgroup timer128 Timer Function Library for ATmega128 (timer128.c) +/// \code #include "timer128.h" \endcode +/// \par Overview +/// This library provides functions for use with the timers internal to the +/// AVR ATmega128. Functions include initialization, set prescaler, +/// calibrated pause function (in milliseconds), attaching and detaching +/// of user functions to interrupts, overflow counters, and PWM. +/// +/// \par About Timers +/// The Atmel AVR-series processors each contain at least one +/// hardware timer/counter. Many of the processors contain 2 or 3 +/// timers. Generally speaking, a timer is a hardware counter inside +/// the processor which counts at a rate related to the main CPU clock +/// frequency. Because the counter value increasing (counting up) at +/// a precise rate, we can use it as a timer to create or measure +/// precise delays, schedule events, or generate signals of a certain +/// frequency or pulse-width. +/// \par +/// As an example, the ATmega163 processor has 3 timer/counters. +/// Timer0, Timer1, and Timer2 are 8, 16, and 8 bits wide respectively. +/// This means that they overflow, or roll over back to zero, at a +/// count value of 256 for 8bits or 65536 for 16bits. A prescaler is +/// avaiable for each timer, and the prescaler allows you to pre-divide +/// the main CPU clock rate down to a slower speed before feeding it to +/// the counting input of a timer. For example, if the CPU clock +/// frequency is 3.69MHz, and Timer0's prescaler is set to divide-by-8, +/// then Timer0 will "tic" at 3690000/8 = 461250Hz. Because Timer0 is +/// an 8bit timer, it will count to 256 in just 256/461250Hz = 0.555ms. +/// In fact, when it hits 255, it will overflow and start again at +/// zero. In this case, Timer0 will overflow 461250/256 = 1801.76 +/// times per second. +/// \par +/// Timer0 can be used a number of ways simultaneously. First, the +/// value of the timer can be read by accessing the CPU register \c TCNT0. +/// We could, for example, figure out how long it takes to execute a +/// C command by recording the value of \c TCNT0 before and after +/// execution, then subtract (after-before) = time elapsed. Or we can +/// enable the overflow interrupt which goes off every time T0 +/// overflows and count out longer delays (multiple overflows), or +/// execute a special periodic function at every overflow. +/// \par +/// The other timers (Timer1 and Timer2) offer all the abilities of +/// Timer0 and many more features. Both T1 and T2 can operate as +/// general-purpose timers, but T1 has special hardware allowing it to +/// generate PWM signals, while T2 is specially designed to help count +/// out real time (like hours, minutes, seconds). See the +/// Timer/Counter section of the processor datasheet for more info. +/// +//***************************************************************************** +//@{ + +#ifndef TIMER128_H +#define TIMER128_H + +#include "global.h" + +// constants/macros/typdefs + +// Timer/clock prescaler values and timer overflow rates +// tics = rate at which the timer counts up +// 8bitoverflow = rate at which the timer overflows 8bits (or reaches 256) +// 16bit [overflow] = rate at which the timer overflows 16bits (65536) +// +// overflows can be used to generate periodic interrupts +// +// for 8MHz crystal +// 0 = STOP (Timer not counting) +// 1 = CLOCK tics= 8MHz 8bitoverflow= 31250Hz 16bit= 122.070Hz +// 2 = CLOCK/8 tics= 1MHz 8bitoverflow= 3906.25Hz 16bit= 15.259Hz +// 3 = CLOCK/64 tics= 125kHz 8bitoverflow= 488.28Hz 16bit= 1.907Hz +// 4 = CLOCK/256 tics= 31250Hz 8bitoverflow= 122.07Hz 16bit= 0.477Hz +// 5 = CLOCK/1024 tics= 7812.5Hz 8bitoverflow= 30.52Hz 16bit= 0.119Hz +// 6 = External Clock on T(x) pin (falling edge) +// 7 = External Clock on T(x) pin (rising edge) + +// for 4MHz crystal +// 0 = STOP (Timer not counting) +// 1 = CLOCK tics= 4MHz 8bitoverflow= 15625Hz 16bit= 61.035Hz +// 2 = CLOCK/8 tics= 500kHz 8bitoverflow= 1953.125Hz 16bit= 7.629Hz +// 3 = CLOCK/64 tics= 62500Hz 8bitoverflow= 244.141Hz 16bit= 0.954Hz +// 4 = CLOCK/256 tics= 15625Hz 8bitoverflow= 61.035Hz 16bit= 0.238Hz +// 5 = CLOCK/1024 tics= 3906.25Hz 8bitoverflow= 15.259Hz 16bit= 0.060Hz +// 6 = External Clock on T(x) pin (falling edge) +// 7 = External Clock on T(x) pin (rising edge) + +// for 3.69MHz crystal +// 0 = STOP (Timer not counting) +// 1 = CLOCK tics= 3.69MHz 8bitoverflow= 14414Hz 16bit= 56.304Hz +// 2 = CLOCK/8 tics= 461250Hz 8bitoverflow= 1801.758Hz 16bit= 7.038Hz +// 3 = CLOCK/64 tics= 57625.25Hz 8bitoverflow= 225.220Hz 16bit= 0.880Hz +// 4 = CLOCK/256 tics= 14414.063Hz 8bitoverflow= 56.305Hz 16bit= 0.220Hz +// 5 = CLOCK/1024 tics= 3603.516Hz 8bitoverflow= 14.076Hz 16bit= 0.055Hz +// 6 = External Clock on T(x) pin (falling edge) +// 7 = External Clock on T(x) pin (rising edge) + +// for 32.768KHz crystal on timer 2 (use for real-time clock) +// 0 = STOP +// 1 = CLOCK tics= 32.768kHz 8bitoverflow= 128Hz +// 2 = CLOCK/8 tics= 4096kHz 8bitoverflow= 16Hz +// 3 = CLOCK/64 tics= 512Hz 8bitoverflow= 2Hz +// 4 = CLOCK/256 tics= 128Hz 8bitoverflow= 0.5Hz +// 5 = CLOCK/1024 tics= 32Hz 8bitoverflow= 0.125Hz + +#define TIMER_CLK_STOP 0x00 ///< Timer Stopped +#define TIMER_CLK_DIV1 0x01 ///< Timer clocked at F_CPU +#define TIMER_CLK_DIV8 0x02 ///< Timer clocked at F_CPU/8 +#define TIMER_CLK_DIV64 0x03 ///< Timer clocked at F_CPU/64 +#define TIMER_CLK_DIV256 0x04 ///< Timer clocked at F_CPU/256 +#define TIMER_CLK_DIV1024 0x05 ///< Timer clocked at F_CPU/1024 +#define TIMER_CLK_T_FALL 0x06 ///< Timer clocked at T falling edge +#define TIMER_CLK_T_RISE 0x07 ///< Timer clocked at T rising edge +#define TIMER_PRESCALE_MASK 0x07 ///< Timer Prescaler Bit-Mask + +#define TIMERRTC_CLK_STOP 0x00 ///< RTC Timer Stopped +#define TIMERRTC_CLK_DIV1 0x01 ///< RTC Timer clocked at F_CPU +#define TIMERRTC_CLK_DIV8 0x02 ///< RTC Timer clocked at F_CPU/8 +#define TIMERRTC_CLK_DIV32 0x03 ///< RTC Timer clocked at F_CPU/32 +#define TIMERRTC_CLK_DIV64 0x04 ///< RTC Timer clocked at F_CPU/64 +#define TIMERRTC_CLK_DIV128 0x05 ///< RTC Timer clocked at F_CPU/128 +#define TIMERRTC_CLK_DIV256 0x06 ///< RTC Timer clocked at F_CPU/256 +#define TIMERRTC_CLK_DIV1024 0x07 ///< RTC Timer clocked at F_CPU/1024 +#define TIMERRTC_PRESCALE_MASK 0x07 ///< RTC Timer Prescaler Bit-Mask + +// default prescale settings for the timers +// these settings are applied when you call +// timerInit or any of the timer<x>Init +#define TIMER0PRESCALE TIMER_CLK_DIV64 ///< timer 0 prescaler default +#define TIMER1PRESCALE TIMER_CLK_DIV64 ///< timer 1 prescaler default +#define TIMER2PRESCALE TIMER_CLK_DIV8 ///< timer 2 prescaler default +#define TIMER3PRESCALE TIMER_CLK_DIV64 ///< timer 3 prescaler default + +// interrupt macros for attaching user functions to timer interrupts +// use these with timerAttach( intNum, function ) +// timer 0 +#define TIMER0OVERFLOW_INT 0 +#define TIMER0OUTCOMPARE_INT 1 +// timer 1 +#define TIMER1OVERFLOW_INT 2 +#define TIMER1OUTCOMPAREA_INT 3 +#define TIMER1OUTCOMPAREB_INT 4 +#define TIMER1OUTCOMPAREC_INT 5 +#define TIMER1INPUTCAPTURE_INT 6 +// timer 2 +#define TIMER2OVERFLOW_INT 7 +#define TIMER2OUTCOMPARE_INT 8 +// timer 3 +#define TIMER3OVERFLOW_INT 9 +#define TIMER3OUTCOMPAREA_INT 10 +#define TIMER3OUTCOMPAREB_INT 11 +#define TIMER3OUTCOMPAREC_INT 12 +#define TIMER3INPUTCAPTURE_INT 13 + +#define TIMER_NUM_INTERRUPTS 14 + +// type of interrupt handler to use for timers +// *do not change unless you know what you're doing +// Value may be SIGNAL or INTERRUPT +#ifndef TIMER_INTERRUPT_HANDLER +#define TIMER_INTERRUPT_HANDLER SIGNAL +#endif + +// functions +#define delay delay_us +#define delay_ms timerPause +void delay_us(unsigned short time_us); + +// initializes timing system +// runs all timer init functions +// sets all timers to default prescale values #defined in systimer.c +void timerInit(void); + +// default initialization routines for each timer +void timer0Init(void); +void timer1Init(void); +void timer2Init(void); +void timer3Init(void); + +// Clock prescaler set/get commands for each timer/counter +// For setting the prescaler, you should use one of the #defines +// above like TIMER_CLK_DIVx, where [x] is the division rate +// you want. +// When getting the current prescaler setting, the return value +// will be the [x] division value currently set. +void timer0SetPrescaler(u08 prescale); ///< set timer0 prescaler division index +void timer1SetPrescaler(u08 prescale); ///< set timer1 prescaler division index +void timer2SetPrescaler(u08 prescale); ///< set timer2 prescaler division index +void timer3SetPrescaler(u08 prescale); ///< set timer3 prescaler division index +u16 timer0GetPrescaler(void); ///< get timer0 prescaler division rate +u16 timer1GetPrescaler(void); ///< get timer1 prescaler division rate +u16 timer2GetPrescaler(void); ///< get timer2 prescaler division rate +u16 timer3GetPrescaler(void); ///< get timer3 prescaler division rate + + +// TimerAttach and Detach commands +// These functions allow the attachment (or detachment) of any user function +// to a timer interrupt. "Attaching" one of your own functions to a timer +// interrupt means that it will be called whenever that interrupt happens. +// Using attach is better than rewriting the actual INTERRUPT() function +// because your code will still work and be compatible if the timer library +// is updated. Also, using Attach allows your code and any predefined timer +// code to work together and at the same time. (ie. "attaching" your own +// function to the timer0 overflow doesn't prevent timerPause from working, +// but rather allows you to share the interrupt.) +// +// timerAttach(TIMER1OVERFLOW_INT, myOverflowFunction); +// timerDetach(TIMER1OVERFLOW_INT) +// +// timerAttach causes the myOverflowFunction() to be attached, and therefore +// execute, whenever an overflow on timer1 occurs. timerDetach removes the +// association and executes no user function when the interrupt occurs. +// myOverflowFunction must be defined with no return value and no arguments: +// +// void myOverflowFunction(void) { ... } + +void timerAttach(u08 interruptNum, void (*userFunc)(void) ); +void timerDetach(u08 interruptNum); + + +// timing commands +// timerPause pauses for the number of milliseconds specified in <pause_ms> +void timerPause(unsigned short pause_ms); + +// overflow counters +// to be documented +void timer0ClearOverflowCount(void); +long timer0GetOverflowCount(void); +void timer2ClearOverflowCount(void); +long timer2GetOverflowCount(void); + +// PWM initialization and set commands for timerX (where X is either 1 or 3) +// timerXPWMInit() +// configures the timerX hardware for PWM mode on pins OCXA, OCXB, and OCXC. +// bitRes should be 8,9,or 10 for 8,9,or 10bit PWM resolution +// +// timerXPWMOff() +// turns off all timerX PWM output and set timer mode to normal state +// +// timerXPWMAOn(), timerXPWMBOn(), timerXPWMCOn() +// turn on output of PWM signals to OCXA,B,C pins +// NOTE: Until you define the OCXA,B,C pins as outputs, and run +// this "on" command, no PWM output will be output +// +// timerXPWMAOff(), timerXPWMBOff(), timerXPWMCOff() +// turn off output of PWM signals to OCXA,B,C pins +// +// timerXPWMASet(), timer1PWMBSet(), timerXPWMCSet() +// sets the PWM duty cycle for each channel +// NOTE: <pwmDuty> should be in the range 0-255 for 8bit PWM +// <pwmDuty> should be in the range 0-511 for 9bit PWM +// <pwmDuty> should be in the range 0-1023 for 10bit PWM +// NOTE: the PWM frequency can be controlled in increments by setting the +// prescaler for timer1 + +void timer1PWMInit(u08 bitRes); ///< initialize and set timer1 mode to PWM +void timer1PWMInitICR(u16 topcount);///< initialize and set timer1 mode to PWM with specific top count +void timer1PWMOff(void); ///< turn off all timer1 PWM output and set timer mode to normal +void timer1PWMAOn(void); ///< turn on timer1 Channel A (OC1A) PWM output +void timer1PWMBOn(void); ///< turn on timer1 Channel B (OC1B) PWM output +void timer1PWMCOn(void); ///< turn on timer1 Channel C (OC1C) PWM output +void timer1PWMAOff(void); ///< turn off timer1 Channel A (OC1A) PWM output +void timer1PWMBOff(void); ///< turn off timer1 Channel B (OC1B) PWM output +void timer1PWMCOff(void); ///< turn off timer1 Channel C (OC1C) PWM output +void timer1PWMASet(u16 pwmDuty); ///< set duty of timer1 Channel A (OC1A) PWM output +void timer1PWMBSet(u16 pwmDuty); ///< set duty of timer1 Channel B (OC1B) PWM output +void timer1PWMCSet(u16 pwmDuty); ///< set duty of timer1 Channel C (OC1C) PWM output + +void timer3PWMInit(u08 bitRes); ///< initialize and set timer3 mode to PWM +void timer3PWMInitICR(u16 topcount);///< initialize and set timer3 mode to PWM with specific top count +void timer3PWMOff(void); ///< turn off all timer3 PWM output and set timer mode to normal +void timer3PWMAOn(void); ///< turn on timer3 Channel A (OC3A) PWM output +void timer3PWMBOn(void); ///< turn on timer3 Channel B (OC3B) PWM output +void timer3PWMCOn(void); ///< turn on timer3 Channel C (OC3C) PWM output +void timer3PWMAOff(void); ///< turn off timer3 Channel A (OC3A) PWM output +void timer3PWMBOff(void); ///< turn off timer3 Channel B (OC3B) PWM output +void timer3PWMCOff(void); ///< turn off timer3 Channel C (OC3C) PWM output +void timer3PWMASet(u16 pwmDuty); ///< set duty of timer3 Channel A (OC3A) PWM output +void timer3PWMBSet(u16 pwmDuty); ///< set duty of timer3 Channel B (OC3B) PWM output +void timer3PWMCSet(u16 pwmDuty); ///< set duty of timer3 Channel C (OC3C) PWM output + +//@} + +// Pulse generation commands have been moved to the pulse.c library + +#endif diff --git a/uartsw.c b/uartsw.c new file mode 100755 index 0000000000000000000000000000000000000000..d7281d98dc112a83a9b2d6a775598cda19d4767d --- /dev/null +++ b/uartsw.c @@ -0,0 +1,375 @@ +/*! \file uartsw.c \brief Software Interrupt-driven UART Driver. */ +//***************************************************************************** +// +// File Name : 'uartsw.c' +// Title : Software Interrupt-driven UART Driver +// Author : Pascal Stang - Copyright (C) 2002-2004 +// Created : 7/20/2002 +// Revised : 4/27/2004 +// Version : 0.1 +// Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32) +// Editor Tabs : 4 +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "global.h" +#include "timer128.h" +#include "uartsw.h" + +// Program ROM constants + +// Global variables + +// uartsw transmit status and data variables +static volatile u08 UartswTxBusy; +static volatile u08 UartswTxData; +static volatile u08 UartswTxBitNum; + +// baud rate common to transmit and receive +static volatile u16 UartswBaudRateDiv; + +// uartsw receive status and data variables +static volatile u08 UartswRxBusy; +static volatile u08 UartswRxData; +static volatile u08 UartswRxBitNum; +// receive buffer +static cBuffer uartswRxBuffer; ///< uartsw receive buffer +// automatically allocate space in ram for each buffer +static unsigned char uartswRxData[UARTSW_RX_BUFFER_SIZE]; + +// functions + +//! enable and initialize the software uart +void uartswInit(void) +{ + // initialize the buffers + uartswInitBuffers(); + // initialize the ports + sbi(UARTSW_TX_DDR, UARTSW_TX_PIN); + cbi(UARTSW_RX_DDR, UARTSW_RX_PIN); + cbi(UARTSW_RX_PORT, UARTSW_RX_PIN); + // initialize baud rate + uartswSetBaudRate(9600); + + // setup the transmitter + UartswTxBusy = FALSE; + // disable OC1A interrupt + cbi(TIMSK, OCIE1A); + // attach TxBit service routine to OC1A + timerAttach(TIMER1OUTCOMPAREA_INT, uartswTxBitService); + + // setup the receiver + UartswRxBusy = FALSE; + // disable OC1B interrupt + cbi(TIMSK, OCIE1B); + // attach RxBit service routine to OC1B + timerAttach(TIMER1OUTCOMPAREB_INT, uartswRxBitService); + // attach RxBit service routine to ICP + timerAttach(TIMER1INPUTCAPTURE_INT, uartswRxBitService); + #ifdef UARTSW_INVERT + // trigger on rising edge + sbi(TCCR1B, ICES1); + #else + // trigger on falling edge + cbi(TCCR1B, ICES1); + #endif + // enable ICP interrupt + sbi(TIMSK, TICIE1); + + // flush queue + bufferFlush(&uartswRxBuffer); +} + +//! create and initialize the uart buffers +void uartswInitBuffers(void) +{ + // initialize the UART receive buffer + bufferInit(&uartswRxBuffer, uartswRxData, UARTSW_RX_BUFFER_SIZE); +} + +//! turns off software UART +void uartswOff(void) +{ + // disable interrupts + cbi(TIMSK, OCIE1A); + cbi(TIMSK, OCIE1B); + cbi(TIMSK, TICIE1); + // detach the service routines + timerDetach(TIMER1OUTCOMPAREA_INT); + timerDetach(TIMER1OUTCOMPAREB_INT); + timerDetach(TIMER1INPUTCAPTURE_INT); +} + +void uartswSetBaudRate(u32 baudrate) +{ + // set timer prescaler + timer1SetPrescaler(TIMER_CLK_DIV1); + // calculate division factor for requested baud rate, and set it + UartswBaudRateDiv = (u16)((F_CPU+(baudrate/2L))/(baudrate*1L)); +} + +//! returns the receive buffer structure +cBuffer* uartswGetRxBuffer(void) +{ + // return rx buffer pointer + return &uartswRxBuffer; +} + +void uartswSendByte(u08 data) +{ + // wait until uart is ready + while(UartswTxBusy); + // set busy flag + UartswTxBusy = TRUE; + // save data + UartswTxData = data; + // set number of bits (+1 for stop bit) + UartswTxBitNum = 9; + + // set the start bit + #ifdef UARTSW_INVERT + sbi(UARTSW_TX_PORT, UARTSW_TX_PIN); + #else + cbi(UARTSW_TX_PORT, UARTSW_TX_PIN); + #endif + + // schedule the next bit + outw(OCR1A, inw(TCNT1) + UartswBaudRateDiv); + // enable OC1A interrupt + sbi(TIMSK, OCIE1A); +} + +//! gets a byte (if available) from the uart receive buffer +u08 uartswReceiveByte(u08* rxData) +{ + // make sure we have a receive buffer + if(uartswRxBuffer.size) + { + // make sure we have data + if(uartswRxBuffer.datalength) + { + // get byte from beginning of buffer + *rxData = bufferGetFromFront(&uartswRxBuffer); + return TRUE; + } + else + { + // no data + return FALSE; + } + } + else + { + // no buffer + return FALSE; + } +} + +void uartswTxBitService(void) +{ + if(UartswTxBitNum) + { + // there are bits still waiting to be transmitted + if(UartswTxBitNum > 1) + { + // transmit data bits (inverted, LSB first) + #ifdef UARTSW_INVERT + if( !(UartswTxData & 0x01) ) + #else + if( (UartswTxData & 0x01) ) + #endif + sbi(UARTSW_TX_PORT, UARTSW_TX_PIN); + else + cbi(UARTSW_TX_PORT, UARTSW_TX_PIN); + // shift bits down + UartswTxData = UartswTxData>>1; + } + else + { + // transmit stop bit + #ifdef UARTSW_INVERT + cbi(UARTSW_TX_PORT, UARTSW_TX_PIN); + #else + sbi(UARTSW_TX_PORT, UARTSW_TX_PIN); + #endif + } + // schedule the next bit + outw(OCR1A, inw(OCR1A) + UartswBaudRateDiv); + // count down + UartswTxBitNum--; + } + else + { + // transmission is done + // clear busy flag + UartswTxBusy = FALSE; + } +} + +void uartswRxBitService(void) +{ + // this function runs on either: + // - a rising edge interrupt + // - OC1B + if(!UartswRxBusy) + { + // this is a start bit + // disable ICP interrupt + cbi(TIMSK, TICIE1); + // schedule data bit sampling 1.5 bit periods from now + outw(OCR1B, inw(TCNT1) + UartswBaudRateDiv + UartswBaudRateDiv/2); + // clear OC1B interrupt flag + sbi(TIFR, OCF1B); + // enable OC1B interrupt + sbi(TIMSK, OCIE1B); + // set start bit flag + UartswRxBusy = TRUE; + // reset bit counter + UartswRxBitNum = 0; + // reset data + UartswRxData = 0; + } + else + { + // start bit has already been received + // we're in the data bits + + // shift data byte to make room for new bit + UartswRxData = UartswRxData>>1; + + // sample the data line + #ifdef UARTSW_INVERT + if( !(inb(UARTSW_RX_PORTIN) & (1<<UARTSW_RX_PIN)) ) + #else + if( (inb(UARTSW_RX_PORTIN) & (1<<UARTSW_RX_PIN)) ) + #endif + { + // serial line is marking + // record '1' bit + UartswRxData |= 0x80; + } + + // increment bit counter + UartswRxBitNum++; + // schedule next bit sample + outw(OCR1B, inw(OCR1B) + UartswBaudRateDiv); + + // check if we have a full byte + if(UartswRxBitNum >= 8) + { + // save data in receive buffer + bufferAddToEnd(&uartswRxBuffer, UartswRxData); + // disable OC1B interrupt + cbi(TIMSK, OCIE1B); + // clear ICP interrupt flag + sbi(TIFR, ICF1); + // enable ICP interrupt + sbi(TIMSK, TICIE1); + // clear start bit flag + UartswRxBusy = FALSE; + } + } +} + +/* +void uartswRxBitService(void) +{ + u16 thisBitTime; + u08 bitperiods; + u08 i; + + // bit transition was detected + // record bit's edge time + thisBitTime = inw(ICR1); + + cbi(PORTB, 0); + + if(!UartswRxStartBit) + { + // this is a start bit + // switch to falling-edge trigger + cbi(TCCR1B, ICES1); + // record bit time + UartswRxBitTime = thisBitTime; + // set start bit flag + UartswRxStartBit = TRUE; + // reset bit counter + UartswRxBitNum = 0; + // reset data + UartswRxData = 0; + } + else + { + // start bit has already been received + // we're in the data bits + + // how many bit periods since last edge? + bitperiods = (thisBitTime - UartswRxBitTime + UartswBaudRateDiv/2)/UartswBaudRateDiv; + // set last edge time + UartswRxBitTime = thisBitTime; + + if(bitperiods > 10) + { + // switch to trigger on rising edge + sbi(TCCR1B, ICES1); + // clear start bit flag + UartswRxStartBit = FALSE; + } + else + { + + + if( inb(TCCR1B) & (1<<ICES1) ) + { + // just triggered on a rising edge + // previous bits were zero + // shift in the data (data bits are inverted) + for(i=0; i<bitperiods; i++) + { + UartswRxData = UartswRxData<<1; + UartswRxData |= 0x01; + } + // switch to trigger on falling edge + cbi(TCCR1B, ICES1); + } + else + { + // just triggered on a falling edge + // previous bits were one + // shift in the data (data bits are inverted) + for(i=0; i<bitperiods; i++) + { + UartswRxData = UartswRxData<<1; + } + // switch to trigger on rising edge + sbi(TCCR1B, ICES1); + } + + // increment bit counter + UartswRxBitNum += bitperiods; + + // check if we have a full byte + start bit + if(bitperiods > 8) + { + // save data in receive buffer + bufferAddToEnd(&uartswRxBuffer, UartswRxData); + // switch to trigger on rising edge + sbi(TCCR1B, ICES1); + // clear start bit flag + UartswRxStartBit = FALSE; + } + } + } + + // turn off debug LEDs + delay(10); + sbi(PORTB, 0); + sbi(PORTB, 1); +} +*/ diff --git a/uartsw.h b/uartsw.h new file mode 100755 index 0000000000000000000000000000000000000000..da02bb3deb7ca0fd3730393d4c52753a909eee14 --- /dev/null +++ b/uartsw.h @@ -0,0 +1,78 @@ +/*! \file uartsw.h \brief Software Interrupt-driven UART Driver. */ +//***************************************************************************** +// +// File Name : 'uartsw.h' +// Title : Software Interrupt-driven UART Driver +// Author : Pascal Stang - Copyright (C) 2002-2004 +// Created : 7/20/2002 +// Revised : 4/27/2004 +// Version : 0.1 +// Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32) +// Editor Tabs : 4 +// +/// \ingroup driver_sw +/// \defgroup uartsw Software Interrupt-driven UART Driver (uartsw.c) +/// \code #include "uartsw.h" \endcode +/// \par Overview +/// This uart library emulates the operation of a UART (serial port) using +/// the AVR's hardware timers, I/O pins, and some software. +/// +/// Specifically, this code uses: +/// -Timer 1 Output Compare A for transmit timing +/// -Timer 1 Output Compare B for receive timing +/// -Timer 1 Input Capture for receive triggering +/// +/// The above resources cannot be used for other purposes while this software +/// UART is enabled. The overflow interrupt from Timer1 can still be used for +/// other timing, but the prescaler for Timer1 must not be changed. +/// +/// Serial output from this UART can be routed to any I/O pin. Serial input +/// for this UART must come from the Timer1 Input Capture (IC1) I/O pin. +/// These options should be configured by editing your local copy of +/// "uartswconf.h". +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef UARTSW_H +#define UARTSW_H + +#include "global.h" +#include "buffer.h" + +// include configuration +#include "uartswconf.h" + +// constants/macros/typdefs + +// functions + +//! enable and initialize the software uart +void uartswInit(void); +//! create and initialize the uart buffers +void uartswInitBuffers(void); +//! turns off software UART +void uartswOff(void); +//! returns the receive buffer structure +cBuffer* uartswGetRxBuffer(void); +//! sets the uart baud rate +void uartswSetBaudRate(u32 baudrate); +//! sends a single byte over the uart +void uartswSendByte(u08 data); + +//! gets a single byte from the uart receive buffer +// Function returns TRUE if data was available, FALSE if not. +// Actual data is returned in variable pointed to by "data". +// example usage: +// char myReceivedByte; +// uartswReceiveByte( &myReceivedByte ); +u08 uartswReceiveByte(u08* rxData); + +//! internal transmit bit handler +void uartswTxBitService(void); +//! internal receive bit handler +void uartswRxBitService(void); + +#endif diff --git a/uartswconf.h b/uartswconf.h new file mode 100755 index 0000000000000000000000000000000000000000..2a465b19a33155967bce11c507459defdcca0941 --- /dev/null +++ b/uartswconf.h @@ -0,0 +1,69 @@ +/*! \file uartswconf.h \brief Interrupt-driven Software UART Driver Configuration. */ +//***************************************************************************** +// +// File Name : 'uartswconf.h' +// Title : Interrupt-driven Software UART Driver Configuration +// Author : Pascal Stang - Copyright (C) 2002-2004 +// Created : 7/20/2002 +// Revised : 4/27/2004 +// Version : 0.1 +// Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32) +// Editor Tabs : 4 +// +// Description : +// This uart library emulates the operation of a UART (serial port) using +// the AVR's hardware timers, I/O pins, and some software. +// +// Specifically, this code uses: +// -Timer 1 Output Compare A for transmit timing +// -Timer 1 Output Compare B for receive timing +// -Timer 1 Input Capture for receive triggering +// +// The above resources cannot be used for other purposes while this software +// UART is enabled. The overflow interrupt from Timer1 can still be used for +// other timing, but the prescaler for Timer1 must not be changed. +// +// Serial output from this UART can be routed to any I/O pin. Serial input +// for this UART must come from the Timer1 Input Capture (IC1) I/O pin. +// These options should be configured by editing your local copy of +// "uartswconf.h". +// +// This code is distributed under the GNU Public License +// which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef UARTSWCONF_H +#define UARTSWCONF_H + +// constants/macros/typdefs + +#define UARTSW_RX_BUFFER_SIZE 0x20 ///< UART receive buffer size in bytes + +//#define UARTSW_INVERT ///< define to invert polarity of RX/TX signals +// when non-inverted, the serial line is appropriate for passing though +// an RS232 driver like the MAX232. When inverted, the serial line can +// directly drive/receive RS232 signals to/from a DB9 connector. Be sure +// to use a current-limiting resistor and perhaps a diode-clamp circuit when +// connecting incoming RS232 signals to a microprocessor I/O pin. + +// if non-inverted, the serial line idles high (logic 1) between bytes +// if inverted, the serial line idles low (logic 0) between bytes + + +// UART transmit pin defines +#define UARTSW_TX_PORT PORTD ///< UART Transmit Port +#define UARTSW_TX_DDR DDRD ///< UART Transmit DDR +#define UARTSW_TX_PIN PD5 ///< UART Transmit Pin + +// UART receive pin defines +// This pin must correspond to the +// Timer1 Input Capture (ICP or IC1) pin for your processor + +// Current config is for a atmega8 +#define UARTSW_RX_PORT PORTD ///< UART Receive Port +#define UARTSW_RX_DDR DDRD ///< UART Receive DDR +#define UARTSW_RX_PORTIN PIND ///< UART Receive Port Input +#define UARTSW_RX_PIN PD4 ///< UART Receive Pin + +#endif diff --git a/utils.h b/utils.h new file mode 100755 index 0000000000000000000000000000000000000000..4ea22284c9b785e2c39bb44b9ab539d16ab01822 --- /dev/null +++ b/utils.h @@ -0,0 +1,6 @@ +#ifndef _UTILS_H +#define _UTILS_H + +#define NULL 0x00 + +#endif