diff --git a/Makefile b/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..34698503b85923ad81773d2e3197cd805da9a544 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +PROJECT=tibi_dabo_battery +######################################################## +# afegir tots els fitxers que s'han de compilar aquà +######################################################## +SOURCES=src/main.c src/dyn_slave.c src/mem.c src/comm.c src/gpio.c src/i2c.c src/smbus.c src/time_base.c +OBJS=$(SOURCES:.c=.o) +SRC_DIR=./src/ +INCLUDE_DIR=./include/ +BUILD_DIR=./build/ +BIN_DIR=./bin/ +CC=avr-gcc +OBJCOPY=avr-objcopy +MMCU=atmega8 + +CFLAGS=-mmcu=$(MMCU) -Wall -Os -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 avrisp2 -P usb -p m8 -U flash:w:$(PROJECT).hex + avrdude -c avrisp2 -P usb -p m8 -U eeprom:w:$(PROJECT)_eeprom.hex + +clean: + rm $(PROJECT).* + rm $(PROJECT)_eeprom.* + rm $(OBJS) diff --git a/a2d.c b/a2d.c deleted file mode 100755 index df980bc77f35257dc6f6de822a17f8bb425a7834..0000000000000000000000000000000000000000 --- a/a2d.c +++ /dev/null @@ -1,186 +0,0 @@ -/*! \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) -{ - 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=6; - 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++; - if(current_ch==NUM_CH) - current_ch=6; - 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 deleted file mode 100755 index 076a6545b542e6b52c2de1f2055f2d1817572c64..0000000000000000000000000000000000000000 --- a/a2d.h +++ /dev/null @@ -1,147 +0,0 @@ -/*! \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 deleted file mode 100755 index a8dea50342b2dd159ebb5035ae658f9b79816c97..0000000000000000000000000000000000000000 --- a/avrlibdefs.h +++ /dev/null @@ -1,83 +0,0 @@ -/*! \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 deleted file mode 100755 index 4d44ac56223bd8fb421a64ef3cab79779c376b7d..0000000000000000000000000000000000000000 --- a/avrlibtypes.h +++ /dev/null @@ -1,84 +0,0 @@ -/*! \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 deleted file mode 100755 index 304221f39baa32bd9dd2fb4e00167a3e8a27ca6d..0000000000000000000000000000000000000000 --- a/buffer.c +++ /dev/null @@ -1,163 +0,0 @@ -/*! \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 deleted file mode 100755 index 40b35d1fa9ea256d1cd7c8eef855d39264948908..0000000000000000000000000000000000000000 --- a/buffer.h +++ /dev/null @@ -1,76 +0,0 @@ -/*! \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/fuel_gauge.c b/fuel_gauge.c deleted file mode 100755 index 5a4dd64bdb165809f20321fdebf7c2b1f9bfdf72..0000000000000000000000000000000000000000 --- a/fuel_gauge.c +++ /dev/null @@ -1,141 +0,0 @@ -#include "fuel_gauge.h" - -#include <avr/eeprom.h> -#include "timer.h" -#include "i2c.h" -#include "a2d.h" - -short int battery_voltage; -float input_current; -float output_current; - -// battery I2C slave address -unsigned char battery_id; -unsigned char EEMEM ee_battery_id=0x60; - -// remaining_capacity -volatile unsigned short int remaining_capacity; -unsigned short int EEMEM ee_remaining_capacity=30000;//mAh -// maximum capacity -volatile unsigned short int maximum_capacity; -unsigned short int EEMEM ee_maximum_capacity=30000;//mAh -// charge cycles -volatile unsigned short int charge_cycles; -unsigned short int EEMEM ee_charge_cycles=0; -// accumutaed_capacity -float accumulated_capacity; - -const double current_gain=48.828125;//mA -const double period=0.00000222222;//h (8 ms) - -void update_fuel_gauge(void) -{ - short int increment=0; - - outb(TCNT0,131);// reload the timer value - // read the voltage and temperature from the battery - // read the current from the A2D module - input_current=adc_get_averaged_channel(6)*current_gain; - output_current=adc_get_averaged_channel(7)*current_gain; - // update the internal variables - accumulated_capacity+=(input_current-output_current)*period; - increment=(short int)accumulated_capacity; - accumulated_capacity-=increment; - remaining_capacity-=increment; - if(remaining_capacity>maximum_capacity) - remaining_capacity=maximum_capacity; - if(remaining_capacity<0) - remaining_capacity=0; -} - -void fuel_gauge_init(void) -{ - // read the data from the EEPROM - battery_id=eeprom_read_byte(&ee_battery_id); - remaining_capacity=eeprom_read_word(&ee_remaining_capacity); - maximum_capacity=eeprom_read_word(&ee_maximum_capacity); - charge_cycles=eeprom_read_word(&ee_charge_cycles); - accumulated_capacity=0.0; - - // initialize the timer - timerInit(); - timer0SetPrescaler(TIMER_CLK_DIV1024); - outb(TCNT0,131); - timerAttach(TIMER0OVERFLOW_INT,update_fuel_gauge); - // attach timer functions - // initialize the i2c peripheral - i2cInit(); - // initialize the a2d converter - a2dInit(); - a2dSetPrescaler(ADC_PRESCALE_DIV128); - a2dSetReference(ADC_REFERENCE_AREF); - - // call the update function to initialize all the variables - update_fuel_gauge(); -} - -short int get_time_to_charged(void) -{ - return ((maximum_capacity-remaining_capacity)*60.0)/output_current; -} - -short int get_time_to_discharged(void) -{ - return (remaining_capacity*60.0)/input_current; -} - -short int get_input_current(void) -{ - return (short int)input_current; -} - -short int get_output_current(void) -{ - return (short int)output_current; -} - -void get_voltage(unsigned char *voltage) -{ - unsigned char read_cmd,i; - unsigned char voltage_data[18]; - - // read the voltage registers of the battery - // send the read request - read_cmd=0x30; - if(i2cMasterSendNI(battery_id,1,&read_cmd)==I2C_OK) - { - if(i2cMasterReceiveNI(battery_id,18,voltage_data)==I2C_OK) - { - for(i=0;i<16;i++) - voltage[i]=voltage_data[i+2]; - } - } -} - -void get_temperature(unsigned char *temp1, unsigned char *temp2) -{ - unsigned char temp_data[6]; - unsigned char read_cmd; - - read_cmd=0x4A;// device start read address - if(i2cMasterSendNI(battery_id,1,&read_cmd)==I2C_OK) - { - if(i2cMasterReceiveNI(battery_id,6,temp_data)==I2C_OK) - { - temp1[0]=temp_data[2]; - temp1[1]=temp_data[3]; - temp2[0]=temp_data[4]; - temp2[1]=temp_data[5]; - } - } -} - -short int get_remaining_capacity(void) -{ - return (short int)(remaining_capacity); -} - -short int get_max_capacity(void) -{ - return (short int)(maximum_capacity); -} diff --git a/fuel_gauge.h b/fuel_gauge.h deleted file mode 100755 index c3f4d5acb63501752cc265ed9e7801cfbcc5c101..0000000000000000000000000000000000000000 --- a/fuel_gauge.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _FUEL_GAUGE_H -#define _FUEL_GAUGE_H - -void fuel_gauge_init(void); -short int get_time_to_charged(void); -short int get_time_to_discharged(void); -short int get_input_current(void); -short int get_output_current(void); -void get_voltage(unsigned char *voltage); -void get_temperature(unsigned char *temp1, unsigned char *temp2); -short int get_remaining_capacity(void); -short int get_max_capacity(void); - -#endif diff --git a/global.h b/global.h deleted file mode 100755 index 075dfe6423d6854ca7ff608197ec53ef7a8ac667..0000000000000000000000000000000000000000 --- a/global.h +++ /dev/null @@ -1,40 +0,0 @@ -/*! \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/gpio.c b/gpio.c deleted file mode 100755 index 72e5ba7675b16d11b4d1c09b894301a67108f10c..0000000000000000000000000000000000000000 --- a/gpio.c +++ /dev/null @@ -1,120 +0,0 @@ -#include "gpio.h" - -void InitGPIO(void) -{ - DDRD=0x02;// PD1 as an output (TXD) - // PD0 as an input (RXD) - // PD5 as an input (battery_present) - // PD6 as an input (on_off) - // PD7 as an input (chg_present) - - DDRC=DDRC|0x03;// PC0 as an output (battery_control) - // PC1 as an output (load_control) - DDRC=DDRC&0xF3;// PC2 as an input (UVP) - // Pc3 as an input (OVP) - - - PORTC=PORTC&0xF0; -} - -void enable_battery(void) -{ - PORTC=PORTC|0x01; -} - -void disable_battery(void) -{ - PORTC=PORTC&0xFE; -} - -void enable_load(void) -{ - PORTC=PORTC|0x02; -} - -void disable_load(void) -{ - PORTC=PORTC&0xFD; -} - -void handle_battery(void) -{ - if(is_battery_present()) - { -// if(under_voltage_protection()) -// disable_battery(); -// else - enable_battery(); - } - else - disable_battery(); -} - -void handle_load(void) -{ - if(is_battery_present()) - { -// if(under_voltage_protection()) -// disable_load(); -// else -// { - if(is_load_on()) - enable_load(); - else - disable_load(); -// } - } - else - { - if(is_charger_present()) - { - if(is_load_on()) - enable_load(); - else - disable_load(); - } - else - disable_load(); - } -} - -unsigned char is_battery_present(void) -{ - if(PIND&0x20) - return 0x01; - else - return 0x00; -} - -unsigned char is_load_on(void) -{ - if(PIND&0x40) - return 0x01; - else - return 0x00; -} - -unsigned char is_charger_present(void) -{ - if(PIND&0x80) - return 0x01; - else - return 0x00; -} - -unsigned char under_voltage_protection(void) -{ - if(PINC&0x04) - return 0x01; - else - return 0x00; -} - -unsigned char over_voltage_protection(void) -{ - if(PINC&0x08) - return 0x01; - else - return 0x00; -} - diff --git a/i2c.c b/i2c.c deleted file mode 100755 index 33e42b12226b50a8222b8bbbc4582d611285d286..0000000000000000000000000000000000000000 --- a/i2c.c +++ /dev/null @@ -1,606 +0,0 @@ -/*! \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(TWEA)) ); - - // 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 deleted file mode 100755 index 21b68e3140e6bd8baec6378242161e66f26be2d1..0000000000000000000000000000000000000000 --- a/i2c.h +++ /dev/null @@ -1,178 +0,0 @@ -/*! \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 deleted file mode 100755 index 81521675be5df58f2cd4db2520c3ae661bee5040..0000000000000000000000000000000000000000 --- a/i2cconf.h +++ /dev/null @@ -1,28 +0,0 @@ -/*! \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/comm.h b/include/comm.h new file mode 100644 index 0000000000000000000000000000000000000000..6f5080049c66948d5c98b4269d3bef081c684b76 --- /dev/null +++ b/include/comm.h @@ -0,0 +1,12 @@ +#ifndef _COMM_H +#define _COMM_H + +#include <avr/interrupt.h> +#include <avr/io.h> + +void comm_init(void); +void comm_loop(void); +void comm_set_error(uint8_t error); +void comm_clear_error(void); + +#endif diff --git a/include/dyn_slave.h b/include/dyn_slave.h new file mode 100644 index 0000000000000000000000000000000000000000..99170561f52b897cf6ac4cd3fb19cc956cfe1d79 --- /dev/null +++ b/include/dyn_slave.h @@ -0,0 +1,54 @@ +#ifndef DYN_SLAVE_H +#define DYN_SLAVE_H + +#include <avr/interrupt.h> +#include <avr/io.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 + +void dyn_slave_init(uint8_t baudrate,uint8_t id); +void dyn_slave_set_baudrate(uint8_t baudrate); +void dyn_slave_set_id(uint8_t id); +uint8_t dyn_slave_is_packet_ready(void); +uint8_t dyn_slave_check_id(void); +uint8_t dyn_slave_check_checksum(void); +uint8_t dyn_slave_get_instruction(void); +uint8_t dyn_slave_get_received_id(void); +// read operation +uint8_t dyn_slave_get_address(void); +uint8_t dyn_slave_get_read_length(void); +// write operation +uint8_t dyn_slave_get_write_length(void); +uint8_t *dyn_slave_get_write_data(void); +// sync read operation +uint8_t dyn_slave_sync_read_id_present(void); +// sync write operation +uint8_t dyn_slave_sync_write_id_present(uint8_t **data); +// bulk read operation +uint8_t dyn_slave_bulk_read_id_present(uint8_t *address,uint8_t *length); +// bulk write operation +uint8_t dyn_slave_bulk_write_id_present(uint8_t *address,uint8_t *length,uint8_t **data); +void dyn_slave_send_status(uint8_t error,uint8_t length, uint8_t *data); +uint8_t dyn_slave_is_send_done(void); + +#endif diff --git a/gpio.h b/include/gpio.h similarity index 56% rename from gpio.h rename to include/gpio.h index d7b19d4147bdd6fe32619a784592dd872c18f39f..bfdead3c1472b568403c2df683fefe1270c96ecd 100755 --- a/gpio.h +++ b/include/gpio.h @@ -4,18 +4,13 @@ #include <avr/io.h> #include <avr/interrupt.h> -void InitGPIO(void); -void handle_battery(void); +void gpio_init(void); void handle_load(void); unsigned char is_battery_present(void); unsigned char is_load_on(void); unsigned char is_charger_present(void); -unsigned char under_voltage_protection(void); -unsigned char over_voltage_protection(void); -void enable_battery(void); -void disable_battery(void); void enable_load(void); void disable_load(void); diff --git a/include/i2c.h b/include/i2c.h new file mode 100755 index 0000000000000000000000000000000000000000..6bc1665a4fdd1fd283d36e3da3773b6da422351b --- /dev/null +++ b/include/i2c.h @@ -0,0 +1,92 @@ +#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 +// 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(unsigned short int bitrateKHz); + +// 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(unsigned char 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(unsigned char ackFlag); +//! Pick up the data that was received with i2cReceiveByte() +unsigned char i2cGetReceivedByte(void); +//! Get current I2c bus status from TWSR +unsigned char i2cGetStatus(void); + +// high-level I2C transaction commands +//! send I2C data to a device on the bus (non-interrupt based) +unsigned char i2cMasterSendNI(unsigned char deviceAddr, unsigned char length, unsigned char* data); +//! receive I2C data from a device on the bus (non-interrupt based) +unsigned char i2cMasterReceiveNI(unsigned char deviceAddr, unsigned char length, unsigned char *data); + +//! Get the current high-level state of the I2C interface +eI2cStateType i2cGetState(void); + +#endif diff --git a/include/mem.h b/include/mem.h new file mode 100644 index 0000000000000000000000000000000000000000..75a5ff188805f44013a3cac09ca9d1cf1143e6fb --- /dev/null +++ b/include/mem.h @@ -0,0 +1,62 @@ +#ifndef _MEM_H +#define _MEM_H + +#include <avr/io.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 +#define Status_Return_Level 0X10 +// Register Id RAM - declared in dynamixel +#define Bat_temperature_L 0x20 +#define Bat_temperature_H 0x21 +#define Bat_voltage_L 0x22 +#define Bat_voltage_H 0x23 +#define Bat_current_L 0x24 +#define Bat_current_H 0x25 +#define Bat_avg_current_L 0x26 +#define Bat_avg_current_H 0x27 +#define Bat_rel_state_charge_L 0x28 +#define Bat_rel_state_charge_H 0x29 +#define Bat_abs_state_charge_L 0x2A +#define Bat_abs_state_charge_H 0x2B +#define Bat_rem_capacity_L 0x2C +#define Bat_rem_capacity_H 0x2D +#define Bat_full_capacity_L 0x2E +#define Bat_full_capacity_H 0x2F +#define Bat_run_time_empty_L 0x30 +#define Bat_run_time_empty_H 0x31 +#define Bat_avg_time_empty_L 0x32 +#define Bat_avg_time_empty_H 0x33 +#define Bat_avg_time_full_L 0x34 +#define Bat_avg_time_full_H 0x35 +#define Bat_charge_current_L 0x36 +#define Bat_charge_current_H 0x37 +#define Bat_charge_voltage_L 0x38 +#define Bat_charge_voltage_H 0x39 +#define Bat_design_capacity_L 0x3A +#define Bat_design_capacity_H 0x3B +#define Bat_design_voltage_L 0x3C +#define Bat_design_voltage_H 0x3D +#define Bat_cell4_voltage_L 0x3E +#define Bat_cell4_voltage_H 0x3F +#define Bat_cell3_voltage_L 0x40 +#define Bat_cell3_voltage_H 0x41 +#define Bat_cell2_voltage_L 0x42 +#define Bat_cell2_voltage_H 0x43 +#define Bat_cell1_voltage_L 0x44 +#define Bat_cell1_voltage_H 0x45 + +#define RAM_SIZE 70 + +extern unsigned char 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/smbus.h b/include/smbus.h new file mode 100644 index 0000000000000000000000000000000000000000..a360ffac19aae0250a54c09883df2b23f3623974 --- /dev/null +++ b/include/smbus.h @@ -0,0 +1,31 @@ +#ifndef _SMBUS_H +#define _SMBUS_H + +#include "i2c.h" +#include "mem.h" + +// SMBUS commands +#define Temperature 0x08 +#define Voltage 0x09 +#define Current 0x0a +#define AverageCurrent 0x0b +#define RelativeStateOfCharge 0x0d +#define AbsoluteStateOfCharge 0x0e +#define RemainingCapacity 0x0f +#define FullChargeCapacity 0x10 +#define RunTimeToEmpty 0x11 +#define AverageTimeToEmpty 0x12 +#define AverageTimeToFull 0x13 +#define ChargingCurrent 0x14 +#define ChargingVoltage 0x15 +#define DesignCapacity 0x18 +#define DesignVoltage 0x19 +#define VCELL4 0x3c +#define VCELL3 0x3d +#define VCELL2 0x3e +#define VCELL1 0x3f + +void smbus_init(void); +void smbus_loop(void); + +#endif diff --git a/include/time_base.h b/include/time_base.h new file mode 100644 index 0000000000000000000000000000000000000000..d44eea59e88597e2af87d816ddd6858c233233ab --- /dev/null +++ b/include/time_base.h @@ -0,0 +1,9 @@ +#ifndef _TIME_BASE_H +#define _TIME_BASE_H + +#include <avr/io.h> + +void time_base_init(void); +uint8_t time_base_period(void); + +#endif diff --git a/src/comm.c b/src/comm.c new file mode 100644 index 0000000000000000000000000000000000000000..bbb7137fe293d5f8df69cf9c880386712631a16e --- /dev/null +++ b/src/comm.c @@ -0,0 +1,174 @@ +#include "comm.h" +#include "dyn_slave.h" +#include "mem.h" + +uint8_t dyn_error; +uint8_t tmp_data[RAM_SIZE]; +uint8_t tmp_address; +uint8_t tmp_length; +uint8_t reg_pending; +uint8_t sync_read_pending; +uint8_t sync_read_previous; +uint8_t bulk_read_pending; +uint8_t bulk_read_previous; + +void do_write(uint8_t address,uint8_t length,uint8_t *data) +{ + uint8_t i,num=0; + + for(i=address;i<address+length;i++) + { + if(i==ID) + dyn_slave_set_id(data[num]); + else if(i==Baud_Rate) + dyn_slave_set_baudrate(data[num]); + num++; + } +} + +void comm_init(void) +{ + dyn_error=NO_ERROR; + tmp_address=0x00; + tmp_length=0x00; + reg_pending=0x00; + sync_read_pending=0x00; + bulk_read_pending=0x00; +} + +void comm_loop(void) +{ + static uint8_t *data,i; + + if(dyn_slave_is_packet_ready()) + { + if(dyn_slave_check_id()) + { + if(dyn_slave_check_checksum()) + { + switch(dyn_slave_get_instruction()) + { + case INST_PING: dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000); + break; + case INST_READ: if(ram_read(dyn_slave_get_address(),dyn_slave_get_read_length(),&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,dyn_slave_get_read_length(),data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + break; + case INST_WRITE: if(ram_write(dyn_slave_get_address(),dyn_slave_get_write_length(),dyn_slave_get_write_data())) + { + do_write(dyn_slave_get_address(),dyn_slave_get_write_length(),dyn_slave_get_write_data()); + dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000); + } + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + break; + case INST_REG_WRITE: tmp_address=dyn_slave_get_address(); + tmp_length=dyn_slave_get_write_length(); + data=dyn_slave_get_write_data(); + for(i=0;i<tmp_length;i++) + tmp_data[i]=data[i]; + reg_pending=0x01; + dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000); + break; + case INST_ACTION: if(reg_pending) + { + if(ram_write(tmp_address,tmp_length,tmp_data)) + { + do_write(tmp_address,tmp_length,tmp_data); + dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000); + } + } + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + break; + case INST_RESET: + break; + case INST_SYNC_READ: sync_read_previous=dyn_slave_sync_read_id_present(); + if(sync_read_previous!=0xFF) + { + if(sync_read_previous==0x00)// first device on the list + { + if(ram_read(dyn_slave_get_address(),dyn_slave_get_read_length(),&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,dyn_slave_get_read_length(),data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + else// sync read pending + { + tmp_address=dyn_slave_get_address(); + tmp_length=dyn_slave_get_read_length(); + sync_read_pending=0x01; + } + } + break; + case INST_SYNC_WRITE: if(dyn_slave_sync_write_id_present(&data)) + { + if(ram_write(dyn_slave_get_address(),dyn_slave_get_read_length(),data)) + do_write(dyn_slave_get_address(),dyn_slave_get_read_length(),data); + } + break; + case INST_BULK_READ: bulk_read_previous=dyn_slave_bulk_read_id_present(&tmp_address,&tmp_length); + if(bulk_read_previous!=0xFF) + { + if(bulk_read_previous==0x00)// first device on the list + { + if(ram_read(tmp_address,tmp_length,&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,tmp_length,data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + else// sync read pending + bulk_read_pending=0x01; + } + break; + case INST_BULK_WRITE: if(dyn_slave_bulk_write_id_present(&tmp_address,&tmp_length,&data)) + { + if(ram_write(tmp_address,tmp_length,data)) + do_write(tmp_address,tmp_length,data); + } + break; + default: dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + break; + } + } + else + dyn_slave_send_status(dyn_error|CHECKSUM_ERROR,0x00,0x00000000); + } + else + { + if(sync_read_pending) + { + if(dyn_slave_get_received_id()==sync_read_previous) + { + sync_read_pending=0x00; + if(ram_read(tmp_address,tmp_length,&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,tmp_length,data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + } + if(bulk_read_pending) + { + if(dyn_slave_get_received_id()==bulk_read_previous) + { + bulk_read_pending=0x00; + if(ram_read(tmp_address,tmp_length,&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,tmp_length,data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + } + } + } +} + +void comm_set_error(uint8_t error) +{ + dyn_error|=error; +} + +void comm_clear_error(void) +{ + dyn_error=NO_ERROR; +} diff --git a/src/dyn_slave.c b/src/dyn_slave.c new file mode 100644 index 0000000000000000000000000000000000000000..b2ebc45623a45b585854003be0171f96dca4f402 --- /dev/null +++ b/src/dyn_slave.c @@ -0,0 +1,267 @@ +#include <avr/interrupt.h> +#include <avr/io.h> +#include "dyn_slave.h" +#include "mem.h" + +uint8_t dyn_slave_id; +uint8_t dyn_slave_data[128]; +uint8_t dyn_slave_num_rx_bytes; +uint8_t dyn_slave_num_tx_bytes; +uint8_t dyn_slave_packet_ready; +uint8_t dyn_slave_send_done; + +ISR(USART_TXC_vect) +{ + if(dyn_slave_num_tx_bytes==dyn_slave_data[3]+4) + { + dyn_slave_send_done=1; + } + else + { + UDR=dyn_slave_data[dyn_slave_num_tx_bytes]; + dyn_slave_num_tx_bytes++; + } +} + +ISR(USART_RXC_vect) +{ + static uint8_t length; + + cli();// disable any other interrupt + dyn_slave_data[dyn_slave_num_rx_bytes]=UDR; + switch(dyn_slave_num_rx_bytes) + { + case 0: if(dyn_slave_data[dyn_slave_num_rx_bytes]==0xFF) + dyn_slave_num_rx_bytes++; + break; + case 1: if(dyn_slave_data[dyn_slave_num_rx_bytes]==0xFF) + dyn_slave_num_rx_bytes++; + else + dyn_slave_num_rx_bytes--; + break; + case 2: dyn_slave_num_rx_bytes++; + break; + case 3: length=dyn_slave_data[dyn_slave_num_rx_bytes]+3; + dyn_slave_num_rx_bytes++; + break; + default: if(dyn_slave_num_rx_bytes==length) + { + dyn_slave_num_rx_bytes=0; + dyn_slave_packet_ready=1; + } + else + dyn_slave_num_rx_bytes++; + break; + } + sei();// enable all interrutps +} + +void dyn_slave_init(uint8_t baudrate,uint8_t id) +{ + // DDRD - Port D Data Direction Register + DDRD=DDRD|0x02;// TX are outputs 0xC2=00000010 + DDRD=DDRD&0xFE;// RX is an input 0xFE=11111110 + + // initialize the rs485 ports + UCSRA = (1<<U2X);// double USART transmission speed + dyn_slave_set_baudrate(baudrate); + UCSRA|=0x40;// clear any pending interrupt + UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE); + UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<< UCSZ0); // 8 bit data, no parity, 1 stop bit + + dyn_slave_set_id(id); + // initialize private variables + dyn_slave_num_tx_bytes=0; + dyn_slave_num_rx_bytes=0; + dyn_slave_packet_ready=0; + dyn_slave_send_done=0; +} + +void dyn_slave_set_baudrate(uint8_t baudrate) +{ + UBRRH = 0; + UBRRL = baudrate; +} + +void dyn_slave_set_id(uint8_t id) +{ + dyn_slave_id=id; +} + +uint8_t dyn_slave_is_packet_ready(void) +{ + if(dyn_slave_packet_ready==0x01) + { + dyn_slave_packet_ready=0x00; + return 0x01; + } + else + return 0x00; +} + +uint8_t dyn_slave_check_id(void) +{ + if(dyn_slave_id==dyn_slave_data[2] || dyn_slave_data[2]==0xFE) + return 0x01; + else + { + dyn_slave_num_rx_bytes=0; + return 0x00; + } +} + +uint8_t dyn_slave_check_checksum(void) +{ + uint8_t i,cs=0x00; + + for(i=2;i<dyn_slave_data[3]+4;i++) + cs+=dyn_slave_data[i]; + if(cs==0xFF) + return 0x01; + else + return 0x00; +} + +uint8_t dyn_slave_get_instruction(void) +{ + return dyn_slave_data[4]; +} + +uint8_t dyn_slave_get_received_id(void) +{ + return dyn_slave_data[2]; +} + +// read operation +uint8_t dyn_slave_get_address(void) +{ + return dyn_slave_data[5]; +} + +uint8_t dyn_slave_get_read_length(void) +{ + return dyn_slave_data[6]; +} + +// write operation +uint8_t dyn_slave_get_write_length(void) +{ + return dyn_slave_data[3]-3; +} + +uint8_t *dyn_slave_get_write_data(void) +{ + return &dyn_slave_data[6]; +} + +// sync read operation +uint8_t dyn_slave_sync_read_id_present(void) +{ + uint8_t i,num; + + num=dyn_slave_data[3]-4; + for(i=0;i<num;i++) + { + if(dyn_slave_data[7+i]==dyn_slave_id) + { + if(i==0) + return 0x00; + else + return dyn_slave_data[6+i]; + } + } + return 0xFF; +} + +// sync write operation +uint8_t dyn_slave_sync_write_id_present(uint8_t **data) +{ + uint8_t i,num; + + num=(dyn_slave_data[3]-4)/(dyn_slave_data[6]+1); + for(i=0;i<num;i++) + { + if(dyn_slave_data[7+i*(dyn_slave_data[6]+1)]==dyn_slave_id) + { + (*data)=&dyn_slave_data[7+i*(dyn_slave_data[6]+1)+1]; + return 0x01; + } + } + return 0x00; +} + +// bulk read operation +uint8_t dyn_slave_bulk_read_id_present(uint8_t *address,uint8_t *length) +{ + uint8_t i,num; + + num=(dyn_slave_data[3]-2)/3; + for(i=0;i<num;i++) + { + if(dyn_slave_data[5+i*3]==dyn_slave_id) + { + (*address)=dyn_slave_data[6+i*3]; + (*length)=dyn_slave_data[7+i*3]; + if(i==0) + return 0x00; + else + return dyn_slave_data[5+(i-1)*3]; + } + } + return 0xFF; +} + +// bulk write operation +uint8_t dyn_slave_bulk_write_id_present(uint8_t *address,uint8_t *length,uint8_t **data) +{ + uint8_t i,num; + + num=dyn_slave_data[3]+4; + for(i=5;i<num;) + { + if(dyn_slave_data[i]==dyn_slave_id) + { + (*address)=dyn_slave_data[i+1]; + (*length)=dyn_slave_data[i+2]; + (*data)=&dyn_slave_data[i+3]; + return 0x01; + } + else + i+=dyn_slave_data[i+2]+3; + } + return 0x00; +} + +void dyn_slave_send_status(uint8_t error,uint8_t length, uint8_t *data) +{ + uint8_t i,cs=0; + + if(dyn_slave_data[2]!=0xFE) + { + if(dyn_slave_data[4]==INST_PING || ((dyn_slave_data[4]==INST_READ || + dyn_slave_data[4]==INST_SYNC_READ || dyn_slave_data[4]==INST_BULK_READ) && + ram_data[Status_Return_Level]!=0x00) || ram_data[Status_Return_Level]==0x02) + dyn_slave_data[0]=0xFF; + dyn_slave_data[1]=0xFF; + dyn_slave_data[2]=dyn_slave_id; + cs+=dyn_slave_id; + dyn_slave_data[3]=length+2; + cs+=length+2; + dyn_slave_data[4]=error; + cs+=error; + for(i=0;i<length;i++) + { + dyn_slave_data[5+i]=data[i]; + cs+=data[i]; + } + dyn_slave_data[5+i]=~cs; + // start transmission + dyn_slave_num_tx_bytes=1; + UDR=dyn_slave_data[0]; + } +} + +uint8_t dyn_slave_is_send_done(void) +{ + return dyn_slave_send_done; +} diff --git a/src/gpio.c b/src/gpio.c new file mode 100755 index 0000000000000000000000000000000000000000..abaf5689820fe6752241e00b68d739a4c567ce21 --- /dev/null +++ b/src/gpio.c @@ -0,0 +1,73 @@ +#include "gpio.h" + +void gpio_init(void) +{ + DDRD=0x02;// PD1 as an output (TXD) + // PD0 as an input (RXD) + // PD5 as an input (battery_present) + // PD6 as an input (on_off) + // PD7 as an input (chg_present) + + DDRC=DDRC|0x02; + // PC1 as an output (load_control) + + PORTC=PORTC&0xF0; +} + +void enable_load(void) +{ + PORTC=PORTC|0x02; +} + +void disable_load(void) +{ + PORTC=PORTC&0xFD; +} + +void handle_load(void) +{ + if(is_battery_present()) + { + if(is_load_on()) + enable_load(); + else + disable_load(); + } + else + { + if(is_charger_present()) + { + if(is_load_on()) + enable_load(); + else + disable_load(); + } + else + disable_load(); + } +} + +unsigned char is_battery_present(void) +{ + if(PIND&0x20) + return 0x01; + else + return 0x00; +} + +unsigned char is_load_on(void) +{ + if(PIND&0x40) + return 0x01; + else + return 0x00; +} + +unsigned char is_charger_present(void) +{ + if(PIND&0x80) + return 0x01; + else + return 0x00; +} + diff --git a/src/i2c.c b/src/i2c.c new file mode 100755 index 0000000000000000000000000000000000000000..4abf6b69c7cea170e28c1376262d5678660cd73e --- /dev/null +++ b/src/i2c.c @@ -0,0 +1,201 @@ +/*! \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; + +// functions +void i2cInit(void) +{ + // set pull-up resistors on I2C bus pins + // TODO: should #ifdef these + PORTC |= (1<<5); + PORTC |= (1<<4); + // set i2c bit rate to 100KHz + i2cSetBitrate(100); + // enable TWI (two-wire interface) + TWCR |= (1<<TWEN); + // set state + I2cState = I2C_IDLE; +} + +void i2cSetBitrate(unsigned short int bitrateKHz) +{ + unsigned char bitrate_div; + // set i2c bitrate + // SCL freq = F_CPU/(16+2*TWBR)) + // calculate bitrate division + bitrate_div = ((F_CPU/1000l)/bitrateKHz); + if(bitrate_div >= 16) + bitrate_div = (bitrate_div-16)/2; + TWBR=bitrate_div; +} + +inline void i2cSendStart(void) +{ + // send start condition + TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT)|(1<<TWSTA); +} + +inline void i2cSendStop(void) +{ + // transmit stop condition + // leave with TWEA on for slave receiving + TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO); +} + +inline void i2cWaitForComplete(void) +{ + // wait for i2c interface to complete operation + while( !(TWCR&(1<<TWINT))); +} + +inline void i2cSendByte(unsigned char data) +{ + // save data to the TWDR + TWDR=data; + // begin send + TWCR=(TWCR&TWCR_CMD_MASK)|(1<<TWINT); +} + +inline void i2cReceiveByte(unsigned char 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 unsigned char i2cGetReceivedByte(void) +{ + // retieve received data byte from i2c TWDR + return( TWDR ); +} + +inline unsigned char i2cGetStatus(void) +{ + // retieve current i2c status from i2c TWSR + return( TWSR ); +} + +unsigned char i2cMasterSendNI(unsigned char deviceAddr, unsigned char length, unsigned char* data) +{ + unsigned char retval = I2C_OK; + + // send start condition + i2cSendStart(); + i2cWaitForComplete(); + + // send device address with write + i2cSendByte( deviceAddr & 0xFE ); + i2cWaitForComplete(); + + // check if device is present and live + if( 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( !(TWCR&(1<<TWEA)) ); + + return retval; +} + +unsigned char i2cMasterReceiveNI(unsigned char deviceAddr, unsigned char length, unsigned char *data) +{ + unsigned char retval = I2C_OK; + + // send start condition + i2cSendStart(); + i2cWaitForComplete(); + + // send device address with read + i2cSendByte( deviceAddr | 0x01 ); + i2cWaitForComplete(); + + // check if device is present and live + if( TWSR == TW_MR_SLA_ACK) + { + // accept receive data and ack it + while(length > 1) + { + i2cReceiveByte(0x01); + i2cWaitForComplete(); + *data++ = i2cGetReceivedByte(); + // decrement length + length--; + } + + // accept receive data and nack it (last-byte signal) + i2cReceiveByte(0x00); + 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(); + + return retval; +} + +eI2cStateType i2cGetState(void) +{ + return I2cState; +} + diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000000000000000000000000000000000000..3f5e7695c31cdc3fa33bcb90dc5bd7f1f86915eb --- /dev/null +++ b/src/main.c @@ -0,0 +1,27 @@ +#include <avr/io.h> +#include <util/delay.h> +#include <avr/interrupt.h> +#include "dyn_slave.h" +#include "mem.h" +#include "comm.h" +#include "gpio.h" +#include "smbus.h" +#include "time_base.h" + +int16_t main(void) +{ + gpio_init(); + ram_init(); + dyn_slave_init(ram_data[Baud_Rate],ram_data[ID]); + comm_init(); + smbus_init(); + time_base_init(); + sei(); + + while (1) + { + comm_loop(); + handle_load(); + smbus_loop(); + } +} diff --git a/src/mem.c b/src/mem.c new file mode 100644 index 0000000000000000000000000000000000000000..0951c6b713585a9e48f033f486699a2649240d0f --- /dev/null +++ b/src/mem.c @@ -0,0 +1,48 @@ +#include "mem.h" +#include <avr/eeprom.h> + +// dynamixel RAM variables +unsigned char ram_data[RAM_SIZE]; + +// Dynamixel EEPROM variables +unsigned char EEMEM eeprom_data[17]={0x1C,0x00,0x00,0x01,0xCF,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/smbus.c b/src/smbus.c new file mode 100644 index 0000000000000000000000000000000000000000..62db76230b7588b997cbb5b91ecc9e570b064ed8 --- /dev/null +++ b/src/smbus.c @@ -0,0 +1,56 @@ +#include "smbus.h" +#include "time_base.h" +#include "mem.h" + +#define FUEL_GAUGE_ADDRESS 0x16 + +typedef struct +{ + unsigned char smbus_cmd; + unsigned char mem_address; +}TSMBusCmd; + +/* private variables */ +TSMBusCmd commands[]={{Temperature,Bat_temperature_L}, + {Voltage,Bat_voltage_L}, + {Current,Bat_current_L}, + {AverageCurrent,Bat_avg_current_L}, + {RelativeStateOfCharge,Bat_rel_state_charge_L}, + {AbsoluteStateOfCharge,Bat_abs_state_charge_L}, + {RemainingCapacity,Bat_rem_capacity_L}, + {FullChargeCapacity,Bat_full_capacity_L}, + {RunTimeToEmpty,Bat_run_time_empty_L}, + {AverageTimeToEmpty,Bat_avg_time_empty_L}, + {AverageTimeToFull,Bat_avg_time_full_L}, + {ChargingCurrent,Bat_charge_current_L}, + {ChargingVoltage,Bat_charge_voltage_L}, + {DesignCapacity,Bat_design_capacity_L}, + {DesignVoltage,Bat_design_voltage_L}, + {VCELL4,Bat_cell4_voltage_L}, + {VCELL3,Bat_cell3_voltage_L}, + {VCELL2,Bat_cell2_voltage_L}, + {VCELL1,Bat_cell1_voltage_L}}; +unsigned char current_cmd; + +#define NUM_COMMANDS 19 + +/* private functions */ + +/* public functions */ +void smbus_init(void) +{ + /* initialize I2C bus */ + i2cInit(); + /* initialize internal variables */ + current_cmd=0; +} + +void smbus_loop(void) +{ + if(time_base_period()) + { + if(i2cMasterSendNI(FUEL_GAUGE_ADDRESS,1,&commands[current_cmd].smbus_cmd)==I2C_OK) + i2cMasterReceiveNI(FUEL_GAUGE_ADDRESS,2,&ram_data[commands[current_cmd].mem_address]); + current_cmd=(current_cmd+1)%NUM_COMMANDS; + } +} diff --git a/src/time_base.c b/src/time_base.c new file mode 100644 index 0000000000000000000000000000000000000000..f8974c5d8e1f3acdd337fd64a0f140dae45229f6 --- /dev/null +++ b/src/time_base.c @@ -0,0 +1,24 @@ +#include "time_base.h" + +void time_base_init(void) +{ + TCCR0|=(1<<CS01)|(1<<CS00); // clk src with prescaler 64 + TIMSK=0x00; // disable all interrupts + TCNT0 = 0x00; +} + +uint8_t time_base_period(void) +{ + if(TIFR & (1<<TOV0)) + { + TIFR|=(1<<TOV0); + return 0x01; + } + else + return 0x00; +} + +uint8_t time_base_get_counter(void) +{ + return TCNT0; +} diff --git a/tibi_dabo_battery.c b/tibi_dabo_battery.c deleted file mode 100755 index e35378be421a4b0963c87cf0102f65edff0932fe..0000000000000000000000000000000000000000 --- a/tibi_dabo_battery.c +++ /dev/null @@ -1,83 +0,0 @@ -#include <inttypes.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include <avr/sleep.h> - -#include "uart.h" - -#include "gpio.h" - -#include "timer.h" - -#include "fuel_gauge.h" - -#include "i2c.h" - -#include <util/delay.h> - -typedef struct -{ - unsigned char header[2]; - unsigned char battery_voltage[16]; - unsigned char temperature1[2]; - unsigned char temperature2[2]; - unsigned char status; - // bit 0: battery_present - // bit 1: charger_present; - // bit 2: load_on; - // bit 3: UVP; - // bit 4: OVP; - short int current_in; - short int current_out; - short int rem_capacity; - short int time_to_charged; - short int time_to_discharged; -}TBatteryInfo; - -int main (void) -{ - unsigned char i; - TBatteryInfo info; - - // initialize the GPIO - InitGPIO(); - - // initialize uart - uartInit(); - // set desired baud rate in bps - uartSetBaudRate(9600); - // initialize the fuel gauge module - fuel_gauge_init(); - - // initialize the header - info.header[0]=0x55; - info.header[1]=0xAA; - while(1) - { - _delay_ms(1000); - handle_battery(); - handle_load(); - get_voltage(info.battery_voltage); - get_temperature(info.temperature1,info.temperature2); - info.status=0x00; - if(is_battery_present()) - info.status|=0x01; - if(is_charger_present()) - info.status|=0x02; - if(is_load_on()) - info.status|=0x04; - if(under_voltage_protection()) - info.status|=0x08; - if(over_voltage_protection()) - info.status|=0x10; - info.current_in=get_input_current(); - info.current_out=get_output_current(); - info.rem_capacity=get_remaining_capacity(); - info.time_to_charged=get_time_to_charged(); - info.time_to_discharged=get_time_to_discharged(); - // send the information packet - for(i=0;i<sizeof(TBatteryInfo);i++) - uartSendByte(((unsigned char *)&info)[i]); - } -} - diff --git a/timer.c b/timer.c deleted file mode 100755 index 33933d134c0ec3e64a8745c69120e7677f100fe3..0000000000000000000000000000000000000000 --- a/timer.c +++ /dev/null @@ -1,468 +0,0 @@ -/*! \file timer.c \brief System Timer function library. */ -//***************************************************************************** -// -// File Name : 'timer.c' -// Title : System Timer function library -// Author : Pascal Stang - Copyright (C) 2000-2002 -// Created : 11/22/2000 -// Revised : 07/09/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 -// -//***************************************************************************** - -#include <avr/io.h> -#include <avr/interrupt.h> -#include <avr/pgmspace.h> -#include <avr/sleep.h> - -#include "global.h" -#include "timer.h" - -//#include "rprintf.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 Timer2Reg0; - -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(); - #ifdef TCNT2 // support timer2 only if it exists - timer2Init(); - #endif - // enable interrupts - sei(); -} - -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 -} - -#ifdef TCNT2 // support timer2 only if it exists -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 -} -#endif - -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); -} - -#ifdef TCNT2 // support timer2 only if it exists -void timer2SetPrescaler(u08 prescale) -{ - // set prescaler on timer 2 - outb(TCCR2, (inb(TCCR2) & ~TIMER_PRESCALE_MASK) | prescale); -} -#endif - -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))); -} - -#ifdef TCNT2 // support timer2 only if it exists -u16 timer2GetPrescaler(void) -{ - //TODO: can we assume for all 3-timer AVR processors, - // that timer2 is the RTC timer? - - // get the current prescaler setting - return (pgm_read_word(TimerRTCPrescaleFactor+(inb(TCCR2) & TIMER_PRESCALE_MASK))); -} -#endif - -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; - } -} -/* -u32 timerMsToTics(u16 ms) -{ - // calculate the prescaler division rate - u16 prescaleDiv = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0))); - // calculate the number of timer tics in x milliseconds - return (ms*(F_CPU/(prescaleDiv*256)))/1000; -} - -u16 timerTicsToMs(u32 tics) -{ - // calculate the prescaler division rate - u16 prescaleDiv = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0))); - // calculate the number of milliseconds in x timer tics - return (tics*1000*(prescaleDiv*256))/F_CPU; -} - -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(TCNT0); - // reset pause timer overflow count - TimerPauseReg = 0; - // calculate delay for [pause_ms] milliseconds - // prescaler division = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0))) - ticRateHz = F_CPU/timer0GetPrescaler(); - // 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(TCNT0)) < (pause+timerThres) ) - { - if( TimerPauseReg < (pause>>8)); - { - // save power by idling the processor - set_sleep_mode(SLEEP_MODE_IDLE); - sleep_mode(); - } - } - - //old inaccurate code, for reference - - // calculate delay for [pause_ms] milliseconds - u16 prescaleDiv = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0))); - u32 pause = (pause_ms*(F_CPU/(prescaleDiv*256)))/1000; - - TimerPauseReg = 0; - while(TimerPauseReg < pause); -}*/ - -void timer0ClearOverflowCount(void) -{ - // clear the timer overflow counter registers - Timer0Reg0 = 0; // initialize time registers -} - -long timer0GetOverflowCount(void) -{ - // return the current timer overflow count - // (this is since the last timer0ClearOverflowCount() command was called) - return Timer0Reg0; -} - -#ifdef TCNT2 // support timer2 only if it exists -void timer2ClearOverflowCount(void) -{ - // clear the timer overflow counter registers - Timer2Reg0 = 0; // initialize time registers -} - -long timer2GetOverflowCount(void) -{ - // return the current timer overflow count - // (this is since the last timer2ClearOverflowCount() command was called) - return Timer2Reg0; -} -#endif - -void timer1PWMInit(u08 bitRes) -{ - // configures timer1 for use with PWM output - // on OC1A and OC1B pins - - // enable timer1 as 8,9,10bit PWM - if(bitRes == 9) - { // 9bit mode - sbi(TCCR1A,PWM11); - cbi(TCCR1A,PWM10); - } - else if( bitRes == 10 ) - { // 10bit mode - sbi(TCCR1A,PWM11); - sbi(TCCR1A,PWM10); - } - else - { // default 8bit mode - cbi(TCCR1A,PWM11); - sbi(TCCR1A,PWM10); - } - - // clear output compare value A - outb(OCR1AH, 0); - outb(OCR1AL, 0); - // clear output compare value B - outb(OCR1BH, 0); - outb(OCR1BL, 0); -} - -#ifdef WGM10 -// include support for arbitrary top-count PWM -// on new AVR processors that support it -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 - ICR1 = topcount; - - // clear output compare value A - OCR1A = 0; - // clear output compare value B - OCR1B = 0; - -} -#endif - -void timer1PWMOff(void) -{ - // turn off timer1 PWM mode - cbi(TCCR1A,PWM11); - cbi(TCCR1A,PWM10); - // set PWM1A/B (OutputCompare action) to none - timer1PWMAOff(); - timer1PWMBOff(); -} - -void timer1PWMAOn(void) -{ - // turn on channel A (OC1A) PWM output - // set OC1A as non-inverted PWM - sbi(TCCR1A,COM1A1); - cbi(TCCR1A,COM1A0); -} - -void timer1PWMBOn(void) -{ - // turn on channel B (OC1B) PWM output - // set OC1B as non-inverted PWM - sbi(TCCR1A,COM1B1); - cbi(TCCR1A,COM1B0); -} - -void timer1PWMAOff(void) -{ - // turn off channel A (OC1A) PWM output - // set OC1A (OutputCompare action) to none - cbi(TCCR1A,COM1A1); - cbi(TCCR1A,COM1A0); -} - -void timer1PWMBOff(void) -{ - // turn off channel B (OC1B) PWM output - // set OC1B (OutputCompare action) to none - cbi(TCCR1A,COM1B1); - cbi(TCCR1A,COM1B0); -} - -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 - //outp( (pwmDuty>>8), OCR1AH); // set the high 8bits of OCR1A - //outp( (pwmDuty&0x00FF), OCR1AL); // set the low 8bits of OCR1A - OCR1A = pwmDuty; -} - -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 - //outp( (pwmDuty>>8), OCR1BH); // set the high 8bits of OCR1B - //outp( (pwmDuty&0x00FF), OCR1BL); // set the low 8bits of OCR1B - OCR1B = pwmDuty; -} - -//! Interrupt handler for tcnt0 overflow interrupt -TIMER_INTERRUPT_HANDLER(TIMER0_OVF_vect) -{ - Timer0Reg0++; // increment low-order counter - - // increment pause counter - TimerPauseReg++; - - // if a user function is defined, execute it too - if(TimerIntFunc[TIMER0OVERFLOW_INT]) - TimerIntFunc[TIMER0OVERFLOW_INT](); -} - -//! Interrupt handler for tcnt1 overflow interrupt -TIMER_INTERRUPT_HANDLER(TIMER1_OVF_vect) -{ - // if a user function is defined, execute it - if(TimerIntFunc[TIMER1OVERFLOW_INT]) - TimerIntFunc[TIMER1OVERFLOW_INT](); -} - -#ifdef TCNT2 // support timer2 only if it exists -//! Interrupt handler for tcnt2 overflow interrupt -TIMER_INTERRUPT_HANDLER(TIMER2_OVF_vect) -{ - Timer2Reg0++; // increment low-order counter - - // if a user function is defined, execute it - if(TimerIntFunc[TIMER2OVERFLOW_INT]) - TimerIntFunc[TIMER2OVERFLOW_INT](); -} -#endif - -#ifdef OCR0 -// include support for Output Compare 0 for new AVR processors that support it -//! Interrupt handler for OutputCompare0 match (OC0) interrupt -TIMER_INTERRUPT_HANDLER(TIMER0_OVF_vect) -{ - // if a user function is defined, execute it - if(TimerIntFunc[TIMER0OUTCOMPARE_INT]) - TimerIntFunc[TIMER0OUTCOMPARE_INT](); -} -#endif - -//! Interrupt handler for CutputCompare1A 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 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](); -} diff --git a/timer.h b/timer.h deleted file mode 100755 index 5e3bb60364afede25fda5e013e8c2687df90a342..0000000000000000000000000000000000000000 --- a/timer.h +++ /dev/null @@ -1,314 +0,0 @@ -/*! \file timer.h \brief System Timer function library. */ -//***************************************************************************** -// -// File Name : 'timer.h' -// Title : System Timer function library -// Author : Pascal Stang - Copyright (C) 2000-2002 -// 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 timer Timer Function Library (timer.c) -/// \code #include "timer.h" \endcode -/// \par Overview -/// This library provides functions for use with the timers internal -/// to the AVR processors. Functions include initialization, set prescaler, -/// calibrated pause function (in milliseconds), attaching and detaching of -/// user functions to interrupts, overflow counters, PWM. Arbitrary -/// frequency generation has been moved to the Pulse Library. -/// -/// \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 TIMER_H -#define TIMER_H - -#include "global.h" - -// constants/macros/typdefs - -// processor compatibility fixes -#ifdef __AVR_ATmega323__ - // redefinition for the Mega323 - #define CTC1 CTC10 -#endif -#ifndef PWM10 - // mega128 PWM bits - #define PWM10 WGM10 - #define PWM11 WGM11 -#endif - - -// 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/32 tics= 1024kHz 8bitoverflow= 4Hz -// 4 = CLOCK/64 tics= 512Hz 8bitoverflow= 2Hz -// 5 = CLOCK/128 tics= 256Hz 8bitoverflow= 1Hz -// 6 = CLOCK/256 tics= 128Hz 8bitoverflow= 0.5Hz -// 7 = 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_DIV8 ///< timer 0 prescaler default -#define TIMER1PRESCALE TIMER_CLK_DIV64 ///< timer 1 prescaler default -#define TIMER2PRESCALE TIMERRTC_CLK_DIV64 ///< timer 2 prescaler default - -// interrupt macros for attaching user functions to timer interrupts -// use these with timerAttach( intNum, function ) -#define TIMER0OVERFLOW_INT 0 -#define TIMER1OVERFLOW_INT 1 -#define TIMER1OUTCOMPAREA_INT 2 -#define TIMER1OUTCOMPAREB_INT 3 -#define TIMER1INPUTCAPTURE_INT 4 -#define TIMER2OVERFLOW_INT 5 -#define TIMER2OUTCOMPARE_INT 6 -#ifdef OCR0 // for processors that support output compare on Timer0 -#define TIMER0OUTCOMPARE_INT 7 -#define TIMER_NUM_INTERRUPTS 8 -#else -#define TIMER_NUM_INTERRUPTS 7 -#endif - -// default 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 (all timers) -// 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); ///< initialize timer0 -void timer1Init(void); ///< initialize timer1 -#ifdef TCNT2 // support timer2 only if it exists -void timer2Init(void); ///< initialize timer2 -#endif - -// 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 -u16 timer0GetPrescaler(void); ///< get timer0 prescaler -void timer1SetPrescaler(u08 prescale); ///< set timer1 prescaler -u16 timer1GetPrescaler(void); ///< get timer0 prescaler -#ifdef TCNT2 // support timer2 only if it exists -void timer2SetPrescaler(u08 prescale); ///< set timer2 prescaler -u16 timer2GetPrescaler(void); ///< get timer2 prescaler -#endif - - -// 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) { ... } - -//! Attach a user function to a timer interrupt -void timerAttach(u08 interruptNum, void (*userFunc)(void) ); -//! Detach a user function from a timer interrupt -void timerDetach(u08 interruptNum); - - -// timing commands -/// A timer-based delay/pause function -/// @param pause_ms Number of integer milliseconds to wait. -void timerPause(unsigned short pause_ms); - -// overflow counters -void timer0ClearOverflowCount(void); ///< Clear timer0's overflow counter. -long timer0GetOverflowCount(void); ///< read timer0's overflow counter -#ifdef TCNT2 // support timer2 only if it exists -void timer2ClearOverflowCount(void); ///< clear timer2's overflow counter -long timer2GetOverflowCount(void); ///< read timer0's overflow counter -#endif - -/// @defgroup timerpwm Timer PWM Commands -/// @ingroup timer -/// These commands control PWM functionality on timer1 -// PWM initialization and set commands for timer1 -// timer1PWMInit() -// configures the timer1 hardware for PWM mode on pins OC1A and OC1B. -// bitRes should be 8,9,or 10 for 8,9,or 10bit PWM resolution -// -// timer1PWMOff() -// turns off all timer1 PWM output and set timer mode to normal state -// -// timer1PWMAOn() and timer1PWMBOn() -// turn on output of PWM signals to OC1A or OC1B pins -// NOTE: Until you define the OC1A and OC1B pins as outputs, and run -// this "on" command, no PWM output will be output -// -// timer1PWMAOff() and timer1PWMBOff() -// turn off output of PWM signals to OC1A or OC1B pins -// -// timer1PWMASet() and timer1PWMBSet() -// 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 -//@{ - - -/// Enter standard PWM Mode on timer1. -/// \param bitRes indicates the period/resolution to use for PWM output in timer bits. -/// Must be either 8, 9, or 10 bits corresponding to PWM periods of 256, 512, or 1024 timer tics. -void timer1PWMInit(u08 bitRes); - -/// Enter PWM Mode on timer1 with a specific top-count value. -/// \param topcount indicates the desired PWM period in timer tics. -/// Can be a number between 1 and 65535 (16-bit). -void timer1PWMInitICR(u16 topcount); - -/// Turn off all timer1 PWM output and set timer mode to normal. -void timer1PWMOff(void); - -/// Turn on/off Timer1 PWM outputs. -void timer1PWMAOn(void); ///< Turn on timer1 Channel A (OC1A) PWM output. -void timer1PWMBOn(void); ///< Turn on timer1 Channel B (OC1B) 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 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 - -//@} -//@} - -// Pulse generation commands have been moved to the pulse.c library - -#endif diff --git a/uart.c b/uart.c deleted file mode 100755 index 3795f273128da497b2ac24ebd4c56365a413b9e1..0000000000000000000000000000000000000000 --- a/uart.c +++ /dev/null @@ -1,289 +0,0 @@ -/*! \file uart.c \brief UART driver with buffer support. */ -// ***************************************************************************** -// -// File Name : 'uart.c' -// Title : UART driver with buffer support -// Author : Pascal Stang - Copyright (C) 2000-2002 -// Created : 11/22/2000 -// Revised : 06/09/2003 -// Version : 1.3 -// 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 "buffer.h" -#include "uart.h" - -// UART global variables -// flag variables -volatile u08 uartReadyTx; ///< uartReadyTx flag -volatile u08 uartBufferedTx; ///< uartBufferedTx flag -// receive and transmit buffers -//cBuffer uartRxBuffer; ///< uart receive buffer -//cBuffer uartTxBuffer; ///< uart transmit buffer -unsigned short uartRxOverflow; ///< receive overflow counter - -//#ifndef UART_BUFFERS_EXTERNAL_RAM - // using internal ram, - // automatically allocate space in ram for each buffer -//static char uartRxData[UART_RX_BUFFER_SIZE]; -//static char uartTxData[UART_TX_BUFFER_SIZE]; -//#endif - -typedef void (*voidFuncPtru08)(unsigned char); -volatile static voidFuncPtru08 UartRxFunc; - -// enable and initialize the uart -void uartInit(void) -{ - // initialize the buffers -// uartInitBuffers(); - // initialize user receive handler - UartRxFunc = 0; - - // enable RxD/TxD and interrupts - outb(UCR, BV(TXCIE)|BV(TXEN)); - - // set default baud rate - uartSetBaudRate(UART_DEFAULT_BAUD_RATE); - // initialize states - uartReadyTx = TRUE; - uartBufferedTx = FALSE; - // clear overflow count - uartRxOverflow = 0; - // enable interrupts - sei(); -} - -// create and initialize the uart transmit and receive buffers -/* -void uartInitBuffers(void) -{ - #ifndef UART_BUFFERS_EXTERNAL_RAM - // initialize the UART receive buffer - bufferInit(&uartRxBuffer, uartRxData, UART_RX_BUFFER_SIZE); - // initialize the UART transmit buffer - bufferInit(&uartTxBuffer, uartTxData, UART_TX_BUFFER_SIZE); - #else - // initialize the UART receive buffer - bufferInit(&uartRxBuffer, (u08*) UART_RX_BUFFER_ADDR, UART_RX_BUFFER_SIZE); - // initialize the UART transmit buffer - bufferInit(&uartTxBuffer, (u08*) UART_TX_BUFFER_ADDR, UART_TX_BUFFER_SIZE); - #endif -} -*/ -// redirects received data to a user function -void uartSetRxHandler(void (*rx_func)(unsigned char c)) -{ - // set the receive interrupt to run the supplied user function - UartRxFunc = rx_func; -} - -// set the uart baud rate -void uartSetBaudRate(u32 baudrate) -{ - // calculate division factor for requested baud rate, and set it - u16 bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1); - outb(UBRRL, bauddiv); - #ifdef UBRRH - outb(UBRRH, bauddiv>>8); - #endif -} - -// returns the receive buffer structure -/* -cBuffer* uartGetRxBuffer(void) -{ - // return rx buffer pointer - return &uartRxBuffer; -} - -// returns the transmit buffer structure -cBuffer* uartGetTxBuffer(void) -{ - // return tx buffer pointer - return &uartTxBuffer; -} -*/ -// transmits a byte over the uart -void uartSendByte(u08 txData) -{ - // wait for the transmitter to be ready - while(!uartReadyTx); - // send byte - outb(UDR, txData); - // set ready state to FALSE - uartReadyTx = FALSE; -} - -// gets a single byte from the uart receive buffer (getchar-style) -/* -int uartGetByte(void) -{ - u08 c; - if(uartReceiveByte(&c)) - return c; - else - return -1; -} - -// gets a byte (if available) from the uart receive buffer - -u08 uartReceiveByte(u08* rxData) -{ - // make sure we have a receive buffer - if(uartRxBuffer.size) - { - // make sure we have data - if(uartRxBuffer.datalength) - { - // get byte from beginning of buffer - *rxData = bufferGetFromFront(&uartRxBuffer); - return TRUE; - } - else - { - // no data - return FALSE; - } - } - else - { - // no buffer - return FALSE; - } -} - -// flush all data out of the receive buffer -void uartFlushReceiveBuffer(void) -{ - // flush all data from receive buffer - //bufferFlush(&uartRxBuffer); - // same effect as above - uartRxBuffer.datalength = 0; -} - -// return true if uart receive buffer is empty -u08 uartReceiveBufferIsEmpty(void) -{ - if(uartRxBuffer.datalength == 0) - { - return TRUE; - } - else - { - return FALSE; - } -} - -// add byte to end of uart Tx buffer -u08 uartAddToTxBuffer(u08 data) -{ - // add data byte to the end of the tx buffer - return bufferAddToEnd(&uartTxBuffer, data); -} - -// start transmission of the current uart Tx buffer contents -void uartSendTxBuffer(void) -{ - // turn on buffered transmit - uartBufferedTx = TRUE; - // send the first byte to get things going by interrupts - uartSendByte(bufferGetFromFront(&uartTxBuffer)); -} - -// transmit nBytes from buffer out the uart -u08 uartSendBuffer(char *buffer, u16 nBytes) -{ - register u08 first; - register u16 i; - - // check if there's space (and that we have any bytes to send at all) - if((uartTxBuffer.datalength + nBytes < uartTxBuffer.size) && nBytes) - { - // grab first character - first = *buffer++; - // copy user buffer to uart transmit buffer - for(i = 0; i < nBytes-1; i++) - { - // put data bytes at end of buffer - bufferAddToEnd(&uartTxBuffer, *buffer++); - } - - // send the first byte to get things going by interrupts - uartBufferedTx = TRUE; - uartSendByte(first); - // return success - return TRUE; - } - else - { - // return failure - return FALSE; - } -}*/ - -// UART Transmit Complete Interrupt Handler - -UART_INTERRUPT_HANDLER(USART_TXC_vect) -{ - // check if buffered tx is enabled -/* if(uartBufferedTx) - { - // check if there's data left in the buffer - if(uartTxBuffer.datalength) - { - // send byte from top of buffer - outb(UDR, bufferGetFromFront(&uartTxBuffer)); - } - else - { - // no data left - uartBufferedTx = FALSE; - // return to ready state - uartReadyTx = TRUE; - } - } - else - {*/ - // we're using single-byte tx mode - // indicate transmit complete, back to ready - uartReadyTx = TRUE; - //} -} -/* -// UART Receive Complete Interrupt Handler -UART_INTERRUPT_HANDLER(SIG_UART_RECV) -{ - u08 c; - - // get received char - c = inb(UDR); - - // if there's a user function to handle this receive event - if(UartRxFunc) - { - // call it and pass the received data - UartRxFunc(c); - } - else - { - // otherwise do default processing - // put received char in buffer - // check if there's space - if( !bufferAddToEnd(&uartRxBuffer, c) ) - { - // no space in buffer - // count overflow - uartRxOverflow++; - } - } -} -*/ diff --git a/uart.h b/uart.h deleted file mode 100755 index 6be57f5a728b8e036099055cbd737d6b37d97c7e..0000000000000000000000000000000000000000 --- a/uart.h +++ /dev/null @@ -1,232 +0,0 @@ -/*! \file uart.h \brief UART driver with buffer support. */ -//***************************************************************************** -// -// File Name : 'uart.h' -// Title : UART driver with buffer support -// Author : Pascal Stang - Copyright (C) 2000-2002 -// Created : 11/22/2000 -// Revised : 02/01/2004 -// Version : 1.3 -// 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 uart UART Driver/Function Library (uart.c) -/// \code #include "uart.h" \endcode -/// \par Overview -/// This library provides both buffered and unbuffered transmit and receive -/// functions for the AVR processor UART. Buffered access means that the -/// UART can transmit and receive data in the "background", while your code -/// continues executing. Also included are functions to initialize the -/// UART, set the baud rate, flush the buffers, and check buffer status. -/// -/// \note For full text output functionality, you may wish to use the rprintf -/// functions along with this driver. -/// -/// \par About UART operations -/// Most Atmel AVR-series processors contain one or more hardware UARTs -/// (aka, serial ports). UART serial ports can communicate with other -/// serial ports of the same type, like those used on PCs. In general, -/// UARTs are used to communicate with devices that are RS-232 compatible -/// (RS-232 is a certain kind of serial port). -/// \par -/// By far, the most common use for serial communications on AVR processors -/// is for sending information and data to a PC running a terminal program. -/// Here is an exmaple: -/// \code -/// uartInit(); // initialize UART (serial port) -/// uartSetBaudRate(9600); // set UART speed to 9600 baud -/// rprintfInit(uartSendByte); // configure rprintf to use UART for output -/// rprintf("Hello World\r\n"); // send "hello world" message via serial port -/// \endcode -/// -/// \warning The CPU frequency (F_CPU) must be set correctly in \c global.h -/// for the UART library to calculate correct baud rates. Furthermore, -/// certain CPU frequencies will not produce exact baud rates due to -/// integer frequency division round-off. See your AVR processor's -/// datasheet for full details. -// -//***************************************************************************** -//@{ - -#ifndef UART_H -#define UART_H - -#include "global.h" -#include "buffer.h" - -//! Default uart baud rate. -/// This is the default speed after a uartInit() command, -/// and can be changed by using uartSetBaudRate(). -#define UART_DEFAULT_BAUD_RATE 9600 - -// buffer memory allocation defines -// buffer sizes -#ifndef UART_TX_BUFFER_SIZE -//! Number of bytes for uart transmit buffer. -/// Do not change this value in uart.h, but rather override -/// it with the desired value defined in your project's global.h -#define UART_TX_BUFFER_SIZE 0x0040 -#endif -#ifndef UART_RX_BUFFER_SIZE -//! Number of bytes for uart receive buffer. -/// Do not change this value in uart.h, but rather override -/// it with the desired value defined in your project's global.h -#define UART_RX_BUFFER_SIZE 0x0040 -#endif - -// define this key if you wish to use -// external RAM for the UART buffers -//#define UART_BUFFER_EXTERNAL_RAM -#ifdef UART_BUFFER_EXTERNAL_RAM - // absolute address of uart buffers - #define UART_TX_BUFFER_ADDR 0x1000 - #define UART_RX_BUFFER_ADDR 0x1100 -#endif - -//! 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 - -// compatibility with most newer processors -#ifdef UCSRB - #define UCR UCSRB -#endif -// compatibility with old Mega processors -#if defined(UBRR) && !defined(UBRRL) - #define UBRRL UBRR -#endif -// compatibility with megaXX8 processors -#if defined(__AVR_ATmega88__) || \ - defined(__AVR_ATmega168__) || \ - defined(__AVR_ATmega644__) - #define UDR UDR0 - #define UCR UCSR0B - #define RXCIE RXCIE0 - #define TXCIE TXCIE0 - #define RXC RXC0 - #define TXC TXC0 - #define RXEN RXEN0 - #define TXEN TXEN0 - #define UBRRL UBRR0L - #define UBRRH UBRR0H - #define SIG_UART_TRANS SIG_USART_TRANS - #define SIG_UART_RECV SIG_USART_RECV - #define SIG_UART_DATA SIG_USART_DATA -#endif -// compatibility with mega169 processors -#if defined(__AVR_ATmega169__) - #define SIG_UART_TRANS SIG_USART_TRANS - #define SIG_UART_RECV SIG_USART_RECV - #define SIG_UART_DATA SIG_USART_DATA -#endif -// compatibility with dual-uart processors -// (if you need to use both uarts, please use the uart2 library) -#if defined(__AVR_ATmega161__) - #define UDR UDR0 - #define UCR UCSR0B - #define UBRRL UBRR0 - #define SIG_UART_TRANS SIG_UART0_TRANS - #define SIG_UART_RECV SIG_UART0_RECV - #define SIG_UART_DATA SIG_UART0_DATA -#endif -#if defined(__AVR_ATmega128__) -#ifdef UART_USE_UART1 - #define UDR UDR1 - #define UCR UCSR1B - #define UBRRL UBRR1L - #define UBRRH UBRR1H - #define SIG_UART_TRANS SIG_UART1_TRANS - #define SIG_UART_RECV SIG_UART1_RECV - #define SIG_UART_DATA SIG_UART1_DATA -#else - #define UDR UDR0 - #define UCR UCSR0B - #define UBRRL UBRR0L - #define UBRRH UBRR0H - #define SIG_UART_TRANS SIG_UART0_TRANS - #define SIG_UART_RECV SIG_UART0_RECV - #define SIG_UART_DATA SIG_UART0_DATA -#endif -#endif - -// functions - -//! Initializes uart. -/// \note After running this init function, the processor -/// I/O pins that used for uart communications (RXD, TXD) -/// are no long available for general purpose I/O. -void uartInit(void); - -//! Initializes transmit and receive buffers. -/// Automatically called from uartInit() -void uartInitBuffers(void); - -//! Redirects received data to a user function. -/// -void uartSetRxHandler(void (*rx_func)(unsigned char c)); - -//! Sets the uart baud rate. -/// Argument should be in bits-per-second, like \c uartSetBaudRate(9600); -void uartSetBaudRate(u32 baudrate); - -//! Returns pointer to the receive buffer structure. -/// -cBuffer* uartGetRxBuffer(void); - -//! Returns pointer to the transmit buffer structure. -/// -cBuffer* uartGetTxBuffer(void); - -//! Sends a single byte over the uart. -/// \note This function waits for the uart to be ready, -/// therefore, consecutive calls to uartSendByte() will -/// go only as fast as the data can be sent over the -/// serial port. -void uartSendByte(u08 data); - -//! Gets a single byte from the uart receive buffer. -/// Returns the byte, or -1 if no byte is available (getchar-style). -int uartGetByte(void); - -//! 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: -/// \code -/// char myReceivedByte; -/// uartReceiveByte( &myReceivedByte ); -/// \endcode -u08 uartReceiveByte(u08* data); - -//! Returns TRUE/FALSE if receive buffer is empty/not-empty. -/// -u08 uartReceiveBufferIsEmpty(void); - -//! Flushes (deletes) all data from receive buffer. -/// -void uartFlushReceiveBuffer(void); - -//! Add byte to end of uart Tx buffer. -/// Returns TRUE if successful, FALSE if failed (no room left in buffer). -u08 uartAddToTxBuffer(u08 data); - -//! Begins transmission of the transmit buffer under interrupt control. -/// -void uartSendTxBuffer(void); - -//! Sends a block of data via the uart using interrupt control. -/// \param buffer pointer to data to be sent -/// \param nBytes length of data (number of bytes to sent) -u08 uartSendBuffer(char *buffer, u16 nBytes); - -#endif -//@} - -