From a1b865763ea03d223c35d11e9e31c3e1f6beb461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Hern=C3=A0ndez=20Juan?= <shernand@iri.upc.edu> Date: Tue, 20 Oct 2015 09:54:50 +0000 Subject: [PATCH] Improved version of the battery monitor firmware using the SMBus for the new batteries. --- Makefile | 43 +++ a2d.c | 186 ------------ a2d.h | 147 ---------- avrlibdefs.h | 83 ------ avrlibtypes.h | 84 ------ buffer.c | 163 ----------- buffer.h | 76 ----- fuel_gauge.c | 141 --------- fuel_gauge.h | 14 - global.h | 40 --- gpio.c | 120 -------- i2c.c | 606 --------------------------------------- i2c.h | 178 ------------ i2cconf.h | 28 -- include/comm.h | 12 + include/dyn_slave.h | 54 ++++ gpio.h => include/gpio.h | 7 +- include/i2c.h | 92 ++++++ include/mem.h | 62 ++++ include/smbus.h | 31 ++ include/time_base.h | 9 + src/comm.c | 174 +++++++++++ src/dyn_slave.c | 267 +++++++++++++++++ src/gpio.c | 73 +++++ src/i2c.c | 201 +++++++++++++ src/main.c | 27 ++ src/mem.c | 48 ++++ src/smbus.c | 56 ++++ src/time_base.c | 24 ++ tibi_dabo_battery.c | 83 ------ timer.c | 468 ------------------------------ timer.h | 314 -------------------- uart.c | 289 ------------------- uart.h | 232 --------------- 34 files changed, 1174 insertions(+), 3258 deletions(-) create mode 100755 Makefile delete mode 100755 a2d.c delete mode 100755 a2d.h delete mode 100755 avrlibdefs.h delete mode 100755 avrlibtypes.h delete mode 100755 buffer.c delete mode 100755 buffer.h delete mode 100755 fuel_gauge.c delete mode 100755 fuel_gauge.h delete mode 100755 global.h delete mode 100755 gpio.c delete mode 100755 i2c.c delete mode 100755 i2c.h delete mode 100755 i2cconf.h create mode 100644 include/comm.h create mode 100644 include/dyn_slave.h rename gpio.h => include/gpio.h (56%) create mode 100755 include/i2c.h create mode 100644 include/mem.h create mode 100644 include/smbus.h create mode 100644 include/time_base.h create mode 100644 src/comm.c create mode 100644 src/dyn_slave.c create mode 100755 src/gpio.c create mode 100755 src/i2c.c create mode 100755 src/main.c create mode 100644 src/mem.c create mode 100644 src/smbus.c create mode 100644 src/time_base.c delete mode 100755 tibi_dabo_battery.c delete mode 100755 timer.c delete mode 100755 timer.h delete mode 100755 uart.c delete mode 100755 uart.h diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..3469850 --- /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 df980bc..0000000 --- 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 076a654..0000000 --- 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 a8dea50..0000000 --- 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 4d44ac5..0000000 --- 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 304221f..0000000 --- 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 40b35d1..0000000 --- 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 5a4dd64..0000000 --- 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 c3f4d5a..0000000 --- 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 075dfe6..0000000 --- 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 72e5ba7..0000000 --- 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 33e42b1..0000000 --- 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 21b68e3..0000000 --- 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 8152167..0000000 --- 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 0000000..6f50800 --- /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 0000000..9917056 --- /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 d7b19d4..bfdead3 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 0000000..6bc1665 --- /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 0000000..75a5ff1 --- /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 0000000..a360ffa --- /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 0000000..d44eea5 --- /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 0000000..bbb7137 --- /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 0000000..b2ebc45 --- /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 0000000..abaf568 --- /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 0000000..4abf6b6 --- /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 0000000..3f5e769 --- /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 0000000..0951c6b --- /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 0000000..62db762 --- /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 0000000..f8974c5 --- /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 e35378b..0000000 --- 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 33933d1..0000000 --- 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 5e3bb60..0000000 --- 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 3795f27..0000000 --- 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 6be57f5..0000000 --- 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 -//@} - - -- GitLab