diff --git a/mote/v2/avr/avrlibdefs.h b/mote/v2/avr/avrlibdefs.h new file mode 100644 index 0000000..9d8c38d --- /dev/null +++ b/mote/v2/avr/avrlibdefs.h @@ -0,0 +1,83 @@ +// +// avrlibdefs.h : AVRlib global defines and macros include file +// +// Copyright (c) 2001-2002 Pascal Stang +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#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) ((ab)?(a):(b)) +#define ABS(x) ((x>0)?(x):(-x)) + +// constants +#define PI 3.14159265359 + +#endif diff --git a/mote/v2/avr/avrlibtypes.h b/mote/v2/avr/avrlibtypes.h new file mode 100644 index 0000000..5149eb2 --- /dev/null +++ b/mote/v2/avr/avrlibtypes.h @@ -0,0 +1,84 @@ +// +// avrlibtypes.h : AVRlib global types and typedefines include file +// +// Copyright (c) 2001-2002 Pascal Stang +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#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/mote/v2/avr/basiciotest.c b/mote/v2/avr/basiciotest.c new file mode 100644 index 0000000..3fb0030 --- /dev/null +++ b/mote/v2/avr/basiciotest.c @@ -0,0 +1,173 @@ +// +// basiciotest.c : test code for the io and buffer ops of the UART and SPI ports +// +// Copyright (c) 2010 flukso.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#include // include I/O definitions (port names, pin names, etc) +#include // include interrupt support + +#include "uart.h" // include uart function library +#include "spi.h" +#include "ctrl.h" + + +#define NO_OP_1 1 +#define NO_OP_2 2 +#define TRANSMIT 4 +#define HIGH_HEX 8 +#define TO_FROM_UART 16 +#define NEW_CTRL_MSG 32 + +#define SPI_END_OF_TX 0x00 +#define SPI_END_OF_MESSAGE ':' +#define SPI_FORWARD_TO_UART_PORT 'u' +#define SPI_FORWARD_TO_CTRL_PORT 'l' + + +volatile uint8_t high_hex; +volatile uint8_t spi_status; + +uint8_t htoi(uint16_t hex) { + uint8_t low_hex = (uint8_t) hex; + uint8_t high_hex = (uint8_t) (hex >> 8); + uint8_t byte; + + byte = (high_hex > 0x40) ? (high_hex & 0x0F) + 9 : high_hex & 0x0F; + byte = byte << 4; + byte |= (low_hex > 0x40) ? (low_hex & 0x0F) + 9 : low_hex & 0x0F; + return byte; +} + +uint16_t itoh(uint8_t byte) { + uint8_t low_nibble = (byte & 0x0F); + uint8_t high_nibble = (byte & 0xF0) >> 4; + uint16_t hex; + + hex = (high_nibble > 0x09) ? high_nibble - 9 + 0x60 : high_nibble + 0x30; + hex = hex << 8; + hex |= (low_nibble > 0x09) ? low_nibble - 9 + 0x60 : low_nibble + 0x30; + return hex; +} + + +SIGNAL(SPI_STC_vect) { + uint8_t spi_rx, spi_tx, uart_tx; + + if (spi_status & (NO_OP_1 | NO_OP_2)) { + spi_status--; + return; + } + + // are we in transmit mode? + if (spi_status & TRANSMIT) { + if (spi_status & TO_FROM_UART) { + + } + else { + if (ctrlGetFromTxBuffer(&spi_tx)) { + received_from_spi(spi_tx); + } + else { + received_from_spi(SPI_END_OF_TX); + spi_status &= ~TRANSMIT; + spi_status |= NO_OP_2; + uartAddToTxBuffer('r'); //debugging + } + } + + return; + } + +// switch (spi_rx = received_from_spi(ctrlGetFromTxBuffer())) { + switch (spi_rx = received_from_spi(0x00)) { + case SPI_END_OF_TX: + spi_status |= TRANSMIT; + spi_status &= ~(HIGH_HEX | TO_FROM_UART); + uartAddToTxBuffer('t'); //debugging + break; + case SPI_END_OF_MESSAGE: + if (spi_status & TO_FROM_UART) { + spi_status &= ~TO_FROM_UART; + } + else { + ctrlAddToRxBuffer(spi_rx); + spi_status |= NEW_CTRL_MSG; + } + break; + case SPI_FORWARD_TO_UART_PORT: + spi_status |= TO_FROM_UART; + break; + default: + //check whether the incoming hex-encoded stream needs to be forwarded to the UART port + if (spi_status & TO_FROM_UART) { + if (spi_status & HIGH_HEX) { + uart_tx = htoi(((uint16_t)high_hex << 8) + spi_rx); + uartAddToTxBuffer(uart_tx); + } + else { + high_hex = spi_rx; + } + // toggle to the HEX bit in spi_status + spi_status ^= HIGH_HEX; + } + else { + // forward to CTRL_RX buffer + ctrlAddToRxBuffer(spi_rx); + } + } +} + +int main(void) { + // initialize the CTRL buffers + ctrlInit(); + + // initialize the UART buffers with a default UART baud rate of 4800 + uartInit(); + + // initialize the SPI in slave mode + setup_spi(SPI_MODE_0, SPI_MSB, SPI_INTERRUPT, SPI_SLAVE); + + uint8_t data; + uint16_t send; + + for(;;) { + if (uartReceiveByte(&data)) { + // check the HEX bit in spi_status + if (spi_status & HIGH_HEX) { + // loopback on the UART itf + send = itoh(htoi(((uint16_t)high_hex << 8) + data)); + uartAddToTxBuffer((uint8_t)(send >> 8)); + uartAddToTxBuffer((uint8_t)(send)); + } + else { + high_hex = data; + } + // toggle to the HEX bit in spi_status + spi_status ^= HIGH_HEX; + + } + + if (spi_status & NEW_CTRL_MSG) { + ctrlLoop(); + spi_status &= ~NEW_CTRL_MSG; + } + } + + return 0; +} diff --git a/mote/v2/avr/buffer.c b/mote/v2/avr/buffer.c new file mode 100644 index 0000000..fa400d4 --- /dev/null +++ b/mote/v2/avr/buffer.c @@ -0,0 +1,153 @@ +// +// buffer.c : Multipurpose byte buffer structure and methods +// +// Copyright (c) 2001 Pascal Stang +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#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; +} + +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/mote/v2/avr/buffer.h b/mote/v2/avr/buffer.h new file mode 100644 index 0000000..a9d4434 --- /dev/null +++ b/mote/v2/avr/buffer.h @@ -0,0 +1,73 @@ +// +// buffer.h : Multipurpose byte buffer structure and methods +// +// 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. +// +// Copyright (c) 2001-2002 Pascal Stang +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#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); + +#endif + diff --git a/mote/v2/avr/ctrl.c b/mote/v2/avr/ctrl.c new file mode 100644 index 0000000..fa9464e --- /dev/null +++ b/mote/v2/avr/ctrl.c @@ -0,0 +1,64 @@ +// +// ctrl.c : AVR uC code for ctrl buffer initialisation and put/get ops +// +// Copyright (c) 2010 flukso.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#include "global.h" +#include "buffer.h" +#include "ctrl.h" + +cBuffer ctrlRxBuffer; // ctrl receive buffer +cBuffer ctrlTxBuffer; // ctrl transmit buffer + +static char ctrlRxData[CTRL_RX_BUFFER_SIZE]; +static char ctrlTxData[CTRL_TX_BUFFER_SIZE]; + +void ctrlInit(void) { + // initialize the CTRL receive buffer + bufferInit(&ctrlRxBuffer, (u08*) ctrlRxData, CTRL_RX_BUFFER_SIZE); + // initialize the CTRL transmit buffer + bufferInit(&ctrlTxBuffer, (u08*) ctrlTxData, CTRL_TX_BUFFER_SIZE); +} + +uint8_t ctrlAddToRxBuffer(uint8_t data) { + return bufferAddToEnd(&ctrlRxBuffer, data); +} + +uint8_t ctrlGetFromTxBuffer(uint8_t* data) { + // make sure we have data in the Tx buffer + if(ctrlTxBuffer.datalength) { + // get byte from beginning of buffer + *data = bufferGetFromFront(&ctrlTxBuffer); + return TRUE; + } + else { + // no data + return FALSE; + } +} + +uint8_t ctrlAddToTxBuffer(uint8_t data) { + return bufferAddToEnd(&ctrlTxBuffer, data); +} + +void ctrlLoop(void) { + while (ctrlRxBuffer.datalength) { + bufferAddToEnd(&ctrlTxBuffer, bufferGetFromFront(&ctrlRxBuffer)); + } +} diff --git a/mote/v2/avr/ctrl.h b/mote/v2/avr/ctrl.h new file mode 100644 index 0000000..11535b7 --- /dev/null +++ b/mote/v2/avr/ctrl.h @@ -0,0 +1,44 @@ +// +// ctrl.h : AVR uC code for ctrl buffer initialisation and put/get ops +// +// Copyright (c) 2010 flukso.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#ifndef CTRL_H +#define CTRL_H +#endif + +#include +#include "buffer.h" + +#ifndef CTRL_RX_BUFFER_SIZE +#define CTRL_RX_BUFFER_SIZE 16 +#endif +#ifndef CTRL_TX_BUFFER_SIZE +#define CTRL_TX_BUFFER_SIZE 16 +#endif + +void ctrlInit(void); + +uint8_t ctrlAddToRxBuffer(uint8_t data); + +uint8_t ctrlGetFromTxBuffer(uint8_t* data); + +uint8_t ctrlAddToTxBuffer(uint8_t data); + +void ctrlLoop(void); diff --git a/mote/v2/avr/global.h b/mote/v2/avr/global.h new file mode 100644 index 0000000..cdf887a --- /dev/null +++ b/mote/v2/avr/global.h @@ -0,0 +1,42 @@ +// +// global.h : AVR project global include +// +// Copyright (c) 2001-2002 Pascal Stang +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#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/mote/v2/avr/makefile b/mote/v2/avr/makefile new file mode 100644 index 0000000..5b09bce --- /dev/null +++ b/mote/v2/avr/makefile @@ -0,0 +1,524 @@ +# +# makefile +# +# Copyright (c) Eric B. Weddington, Jörg Wunsch, et al. +# Peter Fleury +# Bart Van Der Meerssche +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# $Id$ + +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device, using avrdude. +# Please customize the avrdude settings below first! +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + + +# MCU name +MCU = atmega48 + + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +F_CPU = 1000000 + + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + + +# Target file name (without extension). +TARGET = basiciotest + + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c buffer.c uart.c spi.c ctrl.c + + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + + +# Debugging format. +# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. +# AVR Studio 4.10 requires dwarf-2. +# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. +DEBUG = dwarf-2 + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRAINCDIRS = + + +# Compiler flag to set the C Standard level. +# c89 = "ANSI" C +# gnu89 = c89 plus GCC extensions +# c99 = ISO C99 standard (not yet fully implemented) +# gnu99 = c99 plus GCC extensions +CSTANDARD = -std=gnu99 + + +# Place -D or -U options here +CDEFS = -DF_CPU=$(F_CPU)UL + +# uncomment and adapt these line if you want different UART library buffer size +CDEFS += -DUART_RX_BUFFER_SIZE=32 +CDEFS += -DUART_TX_BUFFER_SIZE=32 + +CDEFS += -DUART_DEFAULT_BAUD_RATE=4800 + +# override default CTRL buffer sizes +CDEFS += -DCTRL_RX_BUFFER_SIZE=16 +CDEFS += -DCTRL_TX_BUFFER_SIZE=16 + +# Place -I options here +CINCS = + + + +#---------------- Compiler Options ---------------- +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CFLAGS = -g$(DEBUG) +CFLAGS += $(CDEFS) $(CINCS) +CFLAGS += -O$(OPT) +CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -Wall -Wstrict-prototypes +CFLAGS += -Wa,-adhlns=$(<:.c=.lst) +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +CFLAGS += $(CSTANDARD) + + +#---------------- Assembler Options ---------------- +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlms: create listing +# -gstabs: have the assembler create line number information; note that +# for use in COFF files, additional information about filenames +# and function names needs to be present in the assembler source +# files -- see avr-libc docs [FIXME: not yet described there] +ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs + + +#---------------- Library Options ---------------- +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +# If this is left blank, then it will use the Standard printf version. +#PRINTF_LIB = +PRINTF_LIB = $(PRINTF_LIB_MIN) +#PRINTF_LIB = $(PRINTF_LIB_FLOAT) + + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +# If this is left blank, then it will use the Standard scanf version. +#SCANF_LIB = +SCANF_LIB = $(SCANF_LIB_MIN) +#SCANF_LIB = $(SCANF_LIB_FLOAT) + + +MATH_LIB = -lm + + + +#---------------- External Memory Options ---------------- + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# used for variables (.data/.bss) and heap (malloc()). +#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# only used for heap (malloc()). +#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff + +EXTMEMOPTS = + + + +#---------------- Linker Options ---------------- +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref +LDFLAGS += $(EXTMEMOPTS) +#LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) + + + +#---------------- Programming Options (avrdude) ---------------- + +# Programming hardware: alf avr910 avrisp bascom bsd +# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 +# +# Type: avrdude -c ? +# to get a full listing. +# +AVRDUDE_PROGRAMMER = usbtiny + +# com1 = serial port. Use lpt1 to connect to parallel port. +AVRDUDE_PORT = /dev/ttyUSB* # programmer connected to serial device + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + + + +#---------------- Debugging Options ---------------- + +# For simulavr only - target MCU frequency. +DEBUG_MFREQ = $(F_CPU) + +# Set the DEBUG_UI to either gdb or insight. +# DEBUG_UI = gdb +DEBUG_UI = insight + +# Set the debugging back-end to either avarice, simulavr. +DEBUG_BACKEND = avarice +#DEBUG_BACKEND = simulavr + +# GDB Init Filename. +GDBINIT_FILE = __avr_gdbinit + +# When using avarice settings for the JTAG +JTAG_DEV = /dev/com1 + +# Debugging port used to communicate between GDB / avarice / simulavr. +DEBUG_PORT = 4242 + +# Debugging host used to communicate between GDB / avarice / simulavr, normally +# just set to localhost unless doing some sort of crazy debugging when +# avarice is running on a different computer. +DEBUG_HOST = localhost + + + +#============================================================================ + + +# Define programs and commands. +SHELL = sh +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -f +COPY = cp +WINSHELL = cmd + + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: + + + + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(SRC:.c=.lst) $(ASRC:.S=.lst) + + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + + + +# Default target. +all: begin gccversion sizebefore build sizeafter end + +build: elf hex eep lss sym + +elf: $(TARGET).elf +hex: $(TARGET).hex +eep: $(TARGET).eep +lss: $(TARGET).lss +sym: $(TARGET).sym + + + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +ELFSIZE = $(SIZE) -A $(TARGET).elf +AVRMEM = avr-mem.sh $(TARGET).elf $(MCU) + +sizebefore: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ + $(AVRMEM) 2>/dev/null; echo; fi + +sizeafter: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ + $(AVRMEM) 2>/dev/null; echo; fi + + + +# Display compiler version information. +gccversion : + @$(CC) --version + + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + +# Generate avr-gdb config/init file which does the following: +# define the reset signal, load the target file, connect to target, and set +# a breakpoint at main(). +gdb-config: + @$(REMOVE) $(GDBINIT_FILE) + @echo define reset >> $(GDBINIT_FILE) + @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) + @echo end >> $(GDBINIT_FILE) + @echo file $(TARGET).elf >> $(GDBINIT_FILE) + @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE) +ifeq ($(DEBUG_BACKEND),simulavr) + @echo load >> $(GDBINIT_FILE) +endif + @echo break main >> $(GDBINIT_FILE) + +debug: gdb-config $(TARGET).elf +ifeq ($(DEBUG_BACKEND), avarice) + @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. + @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ + $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) + @$(WINSHELL) /c pause + +else + @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ + $(DEBUG_MFREQ) --port $(DEBUG_PORT) +endif + @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) + + + + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ +--change-section-address .data-0x800000 \ +--change-section-address .bss-0x800000 \ +--change-section-address .noinit-0x800000 \ +--change-section-address .eeprom-0x810000 + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + $(NM) -n $< > $@ + + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + +# Create preprocessed source for use in sending a bug report. +%.i : %.c + $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ + + +# Target: clean project. +clean: begin clean_list end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lss + $(REMOVE) $(OBJ) + $(REMOVE) $(LST) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) .dep/* + + + +# Include the dependency files. +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + + +# Listing of phony targets. +.PHONY : all begin finish end sizebefore sizeafter gccversion \ +build elf hex eep lss sym coff extcoff \ +clean clean_list program debug gdb-config + diff --git a/mote/v2/avr/spi.c b/mote/v2/avr/spi.c new file mode 100644 index 0000000..27b0518 --- /dev/null +++ b/mote/v2/avr/spi.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009 Andrew Smallbone + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifdef __ARDUINO__ +#include +#endif + +void setup_spi(uint8_t mode, int dord, int interrupt, uint8_t clock) +{ + // specify pin directions for SPI pins on port B + if (clock == SPI_SLAVE) { // if slave SS and SCK is input + DDRB &= ~(1< + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef _spi_h__ +#define _spi_h__ + +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +// create alias for the different SPI chip pins - code assumes all on port B +#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__)) + #define SPI_SS_PIN PORTB0 + #define SPI_SCK_PIN PORTB1 + #define SPI_MOSI_PIN PORTB2 + #define SPI_MISO_PIN PORTB3 +#elif (defined(__AVR_ATmega48__) || defined(_AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)) + #define SPI_SS_PIN PORTB2 + #define SPI_SCK_PIN PORTB5 + #define SPI_MOSI_PIN PORTB3 + #define SPI_MISO_PIN PORTB4 +#else + #error unknown processor - add to spi.h +#endif + +// SPI clock modes +#define SPI_MODE_0 0x00 /* Sample (Rising) Setup (Falling) CPOL=0, CPHA=0 */ +#define SPI_MODE_1 0x01 /* Setup (Rising) Sample (Falling) CPOL=0, CPHA=1 */ +#define SPI_MODE_2 0x02 /* Sample (Falling) Setup (Rising) CPOL=1, CPHA=0 */ +#define SPI_MODE_3 0x03 /* Setup (Falling) Sample (Rising) CPOL=1, CPHA=1 */ + +// data direction +#define SPI_LSB 1 /* send least significant bit (bit 0) first */ +#define SPI_MSB 0 /* send most significant bit (bit 7) first */ + +// whether to raise interrupt when data received (SPIF bit received) +#define SPI_NO_INTERRUPT 0 +#define SPI_INTERRUPT 1 + +// slave or master with clock diviser +#define SPI_SLAVE 0xF0 +#define SPI_MSTR_CLK4 0x00 /* chip clock/4 */ +#define SPI_MSTR_CLK16 0x01 /* chip clock/16 */ +#define SPI_MSTR_CLK64 0x02 /* chip clock/64 */ +#define SPI_MSTR_CLK128 0x03 /* chip clock/128 */ +#define SPI_MSTR_CLK2 0x04 /* chip clock/2 */ +#define SPI_MSTR_CLK8 0x05 /* chip clock/8 */ +#define SPI_MSTR_CLK32 0x06 /* chip clock/32 */ + + + +// setup spi +void setup_spi(uint8_t mode, // timing mode SPI_MODE[0-4] + int dord, // data direction SPI_LSB|SPI_MSB + int interrupt, // whether to raise interrupt on recieve + uint8_t clock); // clock diviser + +// disable spi +void disable_spi(void); + +// send and receive a byte of data (master mode) +uint8_t send_spi(uint8_t out); + +// receive the byte of data waiting on the SPI buffer and +// set the next byte to transfer - for use in slave mode +// when interrupts are enabled. +uint8_t received_from_spi(uint8_t out); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/mote/v2/avr/uart.c b/mote/v2/avr/uart.c new file mode 100644 index 0000000..7a81a47 --- /dev/null +++ b/mote/v2/avr/uart.c @@ -0,0 +1,297 @@ +// +// uart.c : UART driver with buffer support +// +// Copyright (c) 2000-2002 Pascal Stang +// 2010 flukso.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#include +#include + +#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(RXCIE)|BV(RXEN)|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, (u08*) uartRxData, UART_RX_BUFFER_SIZE); + // initialize the UART transmit buffer + bufferInit(&uartTxBuffer, (u08*) 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) +{ + u08 status; + // add data byte to the end of the tx buffer + status = bufferAddToEnd(&uartTxBuffer, data); + // turn on buffered transmit + uartBufferedTx = TRUE; + // enable UDRIE0 interrupt + UCR |= 1<