changeset 315:7d409dded901

Import ds18x20 code
author Matt Johnston <matt@ucc.asn.au>
date Fri, 18 May 2012 23:57:08 +0800
parents 7aebb1452422
children 8f32eb67a279
files Makefile crc8.c crc8.h crc8.o diskio.h ds18x20.c ds18x20.h main.c onewire.h uart_addon.c uart_addon.h
diffstat 11 files changed, 1359 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri May 18 20:38:40 2012 +0800
+++ b/Makefile	Fri May 18 23:57:08 2012 +0800
@@ -19,12 +19,18 @@
 
 DEVICE     = atmega328
 PROGDEVICE     = atmega328p
-CLOCK      = 1000000
+CLOCK      = 2000000
 PROGRAMMER = #-c stk500v2 -P avrdoper
 PROGRAMMER = -c stk500 -P ~/dev/stk500 -p $(PROGDEVICE) 
-OBJECTS    = main.o #ff.o mmc.o onewire.o
+OBJS_1WIRE = onewire.o ds18x20.o uart_addon.o crc8.o
+OBJS_SD = ff.o mmc.o
+OBJECTS    = main.o
+OBJECTS += $(OBJS_1WIRE)
+#OBJECTS += OBJS_SD
 LIBS       = -lm
-FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
+
+# default but 2mhz
+FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0x62:m
 
 # ATMega8 fuse bits used above (fuse bits for other devices are different!):
 # Example for 8 MHz internal oscillator
@@ -33,17 +39,17 @@
 #        ^ ^ ^ ^   ^ ^ ^------ BOOTSZ0
 #        | | | |   | +-------- BOOTSZ1
 #        | | | |   +---------- EESAVE (set to 0 to preserve EEPROM over chip erase)
-#        | | | +-------------- CKOPT (clock option, depends on oscillator type)
+#        | | | +-------------- WDTON
 #        | | +---------------- SPIEN (if set to 1, serial programming is disabled)
-#        | +------------------ WDTON (if set to 0, watchdog is always on)
+#        | +------------------ DWEN
 #        +-------------------- RSTDISBL (if set to 0, RESET pin is disabled)
 # Fuse low byte:
-# 0x24 = 0 0 1 0   0 1 0 0
+# 0x62 = 0 1 1 0   0 0 1 0
 #        ^ ^ \ /   \--+--/
 #        | |  |       +------- CKSEL 3..0 (8M internal RC)
 #        | |  +--------------- SUT 1..0 (slowly rising power)
-#        | +------------------ BODEN (if 0, brown-out detector is enabled)
-#        +-------------------- BODLEVEL (if 0: 4V, if 1: 2.7V)
+#        | +------------------ CKOUT
+#        +-------------------- CLKDIV8
 #
 # For computing fuse byte values for other devices and options see
 # the fuse bit calculator at http://www.engbedded.com/fusecalc/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crc8.c	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,63 @@
+/* please read copyright-notice at EOF */
+
+#include <stdint.h>
+
+#define CRC8INIT    0x00
+#define CRC8POLY    0x18              //0X18 = X^8+X^5+X^4+X^0
+
+uint8_t crc8( uint8_t *data, uint16_t number_of_bytes_in_data )
+{
+	uint8_t  crc;
+	uint16_t loop_count;
+	uint8_t  bit_counter;
+	uint8_t  b;
+	uint8_t  feedback_bit;
+	
+	crc = CRC8INIT;
+
+	for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++)
+	{
+		b = data[loop_count];
+		
+		bit_counter = 8;
+		do {
+			feedback_bit = (crc ^ b) & 0x01;
+	
+			if ( feedback_bit == 0x01 ) {
+				crc = crc ^ CRC8POLY;
+			}
+			crc = (crc >> 1) & 0x7F;
+			if ( feedback_bit == 0x01 ) {
+				crc = crc | 0x80;
+			}
+		
+			b = b >> 1;
+			bit_counter--;
+		
+		} while (bit_counter > 0);
+	}
+	
+	return crc;
+}
+
+/*
+This code is from Colin O'Flynn - Copyright (c) 2002 
+only minor changes by M.Thomas 9/2004
+
+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.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crc8.h	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,40 @@
+#ifndef CRC8_H_
+#define CRC8_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+uint8_t crc8( uint8_t* data, uint16_t number_of_bytes_in_data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*
+This is based on code from :
+
+Copyright (c) 2002 Colin O'Flynn
+
+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.
+*/
+
Binary file crc8.o has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/diskio.h	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,74 @@
+/*-----------------------------------------------------------------------
+/  Low level disk interface modlue include file   (C)ChaN, 2010
+/-----------------------------------------------------------------------*/
+
+#ifndef _DISKIO
+
+#define _READONLY	0	/* 1: Remove write functions */
+#define _USE_IOCTL	1	/* 1: Use disk_ioctl fucntion */
+
+#include "integer.h"
+
+
+/* Status of Disk Functions */
+typedef BYTE	DSTATUS;
+
+/* Results of Disk Functions */
+typedef enum {
+	RES_OK = 0,		/* 0: Successful */
+	RES_ERROR,		/* 1: R/W Error */
+	RES_WRPRT,		/* 2: Write Protected */
+	RES_NOTRDY,		/* 3: Not Ready */
+	RES_PARERR		/* 4: Invalid Parameter */
+} DRESULT;
+
+
+/*---------------------------------------*/
+/* Prototypes for disk control functions */
+
+DSTATUS disk_initialize (BYTE);
+DSTATUS disk_status (BYTE);
+DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
+#if	_READONLY == 0
+DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
+#endif
+DRESULT disk_ioctl (BYTE, BYTE, void*);
+void	disk_timerproc (void);
+
+
+
+/* Disk Status Bits (DSTATUS) */
+
+#define STA_NOINIT		0x01	/* Drive not initialized */
+#define STA_NODISK		0x02	/* No medium in the drive */
+#define STA_PROTECT		0x04	/* Write protected */
+
+
+/* Command code for disk_ioctrl fucntion */
+
+/* Generic command (mandatory for FatFs) */
+#define CTRL_SYNC			0	/* Flush disk cache (for write functions) */
+#define GET_SECTOR_COUNT	1	/* Get media size (for only f_mkfs()) */
+#define GET_SECTOR_SIZE		2	/* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
+#define GET_BLOCK_SIZE		3	/* Get erase block size (for only f_mkfs()) */
+
+/* Generic command */
+#define CTRL_POWER			4	/* Get/Set power status */
+#define CTRL_LOCK			5	/* Lock/Unlock media removal */
+#define CTRL_EJECT			6	/* Eject media */
+
+/* MMC/SDC command */
+#define MMC_GET_TYPE		10	/* Get card type */
+#define MMC_GET_CSD			11	/* Get CSD */
+#define MMC_GET_CID			12	/* Get CID */
+#define MMC_GET_OCR			13	/* Get OCR */
+#define MMC_GET_SDSTAT		14	/* Get SD status */
+
+/* ATA/CF command */
+#define ATA_GET_REV			20	/* Get F/W revision */
+#define ATA_GET_MODEL		21	/* Get model name */
+#define ATA_GET_SN			22	/* Get serial number */
+
+
+#define _DISKIO
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ds18x20.c	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,760 @@
+/*********************************************************************************
+Title:    DS18X20-Functions via One-Wire-Bus
+Author:   Martin Thomas <[email protected]>   
+          http://www.siwawi.arubi.uni-kl.de/avr-projects
+Software: avr-gcc 4.3.3 / avr-libc 1.6.7 (WinAVR 3/2010) 
+Hardware: any AVR - tested with ATmega16/ATmega32/ATmega324P and 3 DS18B20
+
+Partly based on code from Peter Dannegger and others.
+
+changelog:
+20041124 - Extended measurements for DS18(S)20 contributed by Carsten Foss (CFO)
+200502xx - function DS18X20_read_meas_single
+20050310 - DS18x20 EEPROM functions (can be disabled to save flash-memory)
+           (DS18X20_EEPROMSUPPORT in ds18x20.h)
+20100625 - removed inner returns, added static function for read scratchpad
+         . replaced full-celcius and fractbit method with decicelsius
+           and maxres (degreeCelsius*10e-4) functions, renamed eeprom-functions,
+           delay in recall_e2 replaced by timeout-handling
+20100714 - ow_command_skip_last_recovery used for parasite-powerd devices so the
+           strong pull-up can be enabled in time even with longer OW recovery times
+20110209 - fix in DS18X20_format_from_maxres() by Marian Kulesza
+**********************************************************************************/
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+
+#include "ds18x20.h"
+#include "onewire.h"
+#include "crc8.h"
+
+#if DS18X20_EEPROMSUPPORT
+// for 10ms delay in copy scratchpad
+#include <util/delay.h>
+#endif /* DS18X20_EEPROMSUPPORT */
+
+/*----------- start of "debug-functions" ---------------*/
+
+#if DS18X20_VERBOSE
+#if (!DS18X20_DECICELSIUS)
+#error "DS18X20_DECICELSIUS must be enabled for verbose-mode"
+#endif
+
+/* functions for debugging-output - undef DS18X20_VERBOSE in .h
+   if you run out of program-memory */
+#include <string.h>
+#include "uart.h"
+#include "uart_addon.h"
+
+static int16_t DS18X20_raw_to_decicelsius( uint8_t fc, uint8_t sp[] );
+
+void DS18X20_show_id_uart( uint8_t *id, size_t n )
+{
+	size_t i;
+
+	for( i = 0; i < n; i++ ) {
+		if ( i == 0 ) { uart_puts_P( "FC:" ); }
+		else if ( i == n-1 ) { uart_puts_P( "CRC:" ); }
+		if ( i == 1 ) { uart_puts_P( "SN: " ); }
+		uart_puthex_byte(id[i]);
+		uart_puts_P(" ");
+		if ( i == 0 ) {
+			if ( id[0] == DS18S20_FAMILY_CODE ) { uart_puts_P ("(18S)"); }
+			else if ( id[0] == DS18B20_FAMILY_CODE ) { uart_puts_P ("(18B)"); }
+			else if ( id[0] == DS1822_FAMILY_CODE ) { uart_puts_P ("(22)"); }
+			else { uart_puts_P ("( ? )"); }
+		}
+	}
+	if ( crc8( id, OW_ROMCODE_SIZE) )
+		uart_puts_P( " CRC FAIL " );
+	else 
+		uart_puts_P( " CRC O.K. " );
+}
+
+static void show_sp_uart( uint8_t *sp, size_t n )
+{
+	size_t i;
+
+	uart_puts_P( "SP:" );
+	for( i = 0; i < n; i++ ) {
+		if ( i == n-1 ) { uart_puts_P( "CRC:" ); }
+		uart_puthex_byte(sp[i]);
+		uart_puts_P(" ");
+	}
+}
+
+/* 
+   convert raw value from DS18x20 to Celsius
+   input is: 
+   - familycode fc (0x10/0x28 see header)
+   - scratchpad-buffer
+   output is:
+   - cel full celsius
+   - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits)
+   - subzero =0 positiv / 1 negativ
+   always returns  DS18X20_OK
+*/
+static uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp, 
+	uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits)
+{
+	uint16_t meas;
+	uint8_t  i;
+	
+	meas = sp[0];  // LSB
+	meas |= ( (uint16_t)sp[1] ) << 8; // MSB
+	
+	//  only work on 12bit-base
+	if( fc == DS18S20_FAMILY_CODE ) { // 9 -> 12 bit if 18S20
+		/* Extended res. measurements for DS18S20 contributed by Carsten Foss */
+		meas &= (uint16_t) 0xfffe;    // Discard LSB, needed for later extended precicion calc
+		meas <<= 3;                   // Convert to 12-bit, now degrees are in 1/16 degrees units
+		meas += ( 16 - sp[6] ) - 4;   // Add the compensation and remember to subtract 0.25 degree (4/16)
+	}
+	
+	// check for negative 
+	if ( meas & 0x8000 )  {
+		*subzero=1;      // mark negative
+		meas ^= 0xffff;  // convert to positive => (twos complement)++
+		meas++;
+	}
+	else {
+		*subzero=0;
+	}
+	
+	// clear undefined bits for B != 12bit
+	if ( fc == DS18B20_FAMILY_CODE || fc == DS1822_FAMILY_CODE ) {
+		i = sp[DS18B20_CONF_REG];
+		if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) { ; }
+		else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) {
+			meas &= ~(DS18B20_11_BIT_UNDF);
+		} else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) {
+			meas &= ~(DS18B20_10_BIT_UNDF);
+		} else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) { 
+			meas &= ~(DS18B20_9_BIT_UNDF);
+		}
+	}
+	
+	*cel  = (uint8_t)(meas >> 4); 
+	*cel_frac_bits = (uint8_t)(meas & 0x000F);
+	
+	return DS18X20_OK;
+}
+
+static void DS18X20_uart_put_temp(const uint8_t subzero, 
+	const uint8_t cel, const uint8_t cel_frac_bits)
+{
+	char buffer[sizeof(int)*8+1];
+	size_t i;
+	
+	uart_putc((subzero)?'-':'+');
+	uart_put_int((int)cel);
+	uart_puts_P(".");
+	itoa(cel_frac_bits*DS18X20_FRACCONV,buffer,10);
+	for ( i = 0; i < 4-strlen(buffer); i++ ) {
+		uart_puts_P("0");
+	}
+	uart_puts(buffer);
+	uart_puts_P("�C");
+}
+
+/* verbose output rom-search follows read-scratchpad in one loop */
+uint8_t DS18X20_read_meas_all_verbose( void )
+{
+	uint8_t id[OW_ROMCODE_SIZE], sp[DS18X20_SP_SIZE], diff;
+	uint8_t i;
+	uint16_t meas;
+	int16_t decicelsius;
+	char s[10];
+	uint8_t subzero, cel, cel_frac_bits;
+	
+	for( diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
+	{
+		diff = ow_rom_search( diff, &id[0] );
+
+		if( diff == OW_PRESENCE_ERR ) {
+			uart_puts_P( "No Sensor found\r" );
+			return OW_PRESENCE_ERR; // <--- early exit!
+		}
+		
+		if( diff == OW_DATA_ERR ) {
+			uart_puts_P( "Bus Error\r" );
+			return OW_DATA_ERR;     // <--- early exit!
+		}
+		
+		DS18X20_show_id_uart( id, OW_ROMCODE_SIZE );
+		
+		if( id[0] == DS18B20_FAMILY_CODE || id[0] == DS18S20_FAMILY_CODE ||
+		    id[0] == DS1822_FAMILY_CODE ) { 
+			// temperature sensor
+			
+			uart_putc ('\r');
+			
+			ow_byte_wr( DS18X20_READ );           // read command
+			
+			for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) {
+				sp[i]=ow_byte_rd();
+			}
+			
+			show_sp_uart( sp, DS18X20_SP_SIZE );
+
+			if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
+				uart_puts_P( " CRC FAIL " );
+			} else {
+				uart_puts_P( " CRC O.K. " );
+			}
+			uart_putc ('\r');
+		
+			meas = sp[0]; // LSB Temp. from Scrachpad-Data
+			meas |= (uint16_t) (sp[1] << 8); // MSB
+			
+			uart_puts_P( " T_raw=");
+			uart_puthex_byte( (uint8_t)(meas >> 8) );
+			uart_puthex_byte( (uint8_t)meas );
+			uart_puts_P( " " );
+
+			if( id[0] == DS18S20_FAMILY_CODE ) { // 18S20
+				uart_puts_P( "S20/09" );
+			}
+			else if ( id[0] == DS18B20_FAMILY_CODE ||
+			          id[0] == DS1822_FAMILY_CODE ) { // 18B20 or 1822
+				i=sp[DS18B20_CONF_REG];
+				if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) {
+					uart_puts_P( "B20/12" );
+				}
+				else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) {
+					uart_puts_P( "B20/11" );
+				}
+				else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) {
+					uart_puts_P( " B20/10 " );
+				}
+				else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) { 
+					uart_puts_P( "B20/09" );
+				}
+			}			
+			uart_puts_P(" ");
+			
+			DS18X20_meas_to_cel( id[0], sp, &subzero, &cel, &cel_frac_bits );
+			DS18X20_uart_put_temp( subzero, cel, cel_frac_bits );
+
+			decicelsius = DS18X20_raw_to_decicelsius( id[0], sp );
+			if ( decicelsius == DS18X20_INVALID_DECICELSIUS ) {
+				uart_puts_P("* INVALID *");
+			} else {
+				uart_puts_P(" conv: ");
+				uart_put_int(decicelsius);
+				uart_puts_P(" deci�C ");
+				DS18X20_format_from_decicelsius( decicelsius, s, 10 );
+				uart_puts_P(" fmt: ");
+				uart_puts(s);
+				uart_puts_P(" �C ");
+			}
+
+			uart_puts("\r");
+			
+		} // if meas-sensor
+		
+	} // loop all sensors
+	
+	uart_puts_P( "\r" );
+	
+	return DS18X20_OK;
+}
+
+#endif /* DS18X20_VERBOSE */
+
+#if DS18X20_VERBOSE
+#define uart_puts_P_verbose(s__) uart_puts_P(s__)
+#else 
+#define uart_puts_P_verbose(s__)
+#endif
+
+
+/*----------- end of "debug-functions" ---------------*/
+
+
+/* find DS18X20 Sensors on 1-Wire-Bus
+   input/ouput: diff is the result of the last rom-search
+                *diff = OW_SEARCH_FIRST for first call
+   output: id is the rom-code of the sensor found */
+uint8_t DS18X20_find_sensor( uint8_t *diff, uint8_t id[] )
+{
+	uint8_t go;
+	uint8_t ret;
+
+	ret = DS18X20_OK;
+	go = 1;
+	do {
+		*diff = ow_rom_search( *diff, &id[0] );
+		if ( *diff == OW_PRESENCE_ERR || *diff == OW_DATA_ERR ||
+		     *diff == OW_LAST_DEVICE ) { 
+			go  = 0;
+			ret = DS18X20_ERROR;
+		} else {
+			if ( id[0] == DS18B20_FAMILY_CODE || id[0] == DS18S20_FAMILY_CODE ||
+			     id[0] == DS1822_FAMILY_CODE ) { 
+				go = 0;
+			}
+		}
+	} while (go);
+
+	return ret;
+}
+
+/* get power status of DS18x20 
+   input:   id = rom_code 
+   returns: DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE */
+uint8_t DS18X20_get_power_status( uint8_t id[] )
+{
+	uint8_t pstat;
+
+	ow_reset();
+	ow_command( DS18X20_READ_POWER_SUPPLY, id );
+	pstat = ow_bit_io( 1 );
+	ow_reset();
+	return ( pstat ) ? DS18X20_POWER_EXTERN : DS18X20_POWER_PARASITE;
+}
+
+/* start measurement (CONVERT_T) for all sensors if input id==NULL 
+   or for single sensor where id is the rom-code */
+uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[])
+{
+	uint8_t ret;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		if ( with_power_extern != DS18X20_POWER_EXTERN ) {
+			ow_command_with_parasite_enable( DS18X20_CONVERT_T, id );
+			/* not longer needed: ow_parasite_enable(); */
+		} else {
+			ow_command( DS18X20_CONVERT_T, id );
+		}
+		ret = DS18X20_OK;
+	} 
+	else { 
+		uart_puts_P_verbose( "DS18X20_start_meas: Short Circuit!\r" );
+		ret = DS18X20_START_FAIL;
+	}
+
+	return ret;
+}
+
+// returns 1 if conversion is in progress, 0 if finished
+// not available when parasite powered.
+uint8_t DS18X20_conversion_in_progress(void)
+{
+	return ow_bit_io( 1 ) ? DS18X20_CONVERSION_DONE : DS18X20_CONVERTING;
+}
+
+static uint8_t read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
+{
+	uint8_t i;
+	uint8_t ret;
+
+	ow_command( DS18X20_READ, id );
+	for ( i = 0; i < n; i++ ) {
+		sp[i] = ow_byte_rd();
+	}
+	if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
+		ret = DS18X20_ERROR_CRC;
+	} else {
+		ret = DS18X20_OK;
+	}
+
+	return ret;
+}
+
+
+#if DS18X20_DECICELSIUS
+
+/* convert scratchpad data to physical value in unit decicelsius */
+static int16_t DS18X20_raw_to_decicelsius( uint8_t familycode, uint8_t sp[] )
+{
+	uint16_t measure;
+	uint8_t  negative;
+	int16_t  decicelsius;
+	uint16_t fract;
+
+	measure = sp[0] | (sp[1] << 8);
+	//measure = 0xFF5E; // test -10.125
+	//measure = 0xFE6F; // test -25.0625
+
+	if( familycode == DS18S20_FAMILY_CODE ) {   // 9 -> 12 bit if 18S20
+		/* Extended measurements for DS18S20 contributed by Carsten Foss */
+		measure &= (uint16_t)0xfffe;   // Discard LSB, needed for later extended precicion calc
+		measure <<= 3;                 // Convert to 12-bit, now degrees are in 1/16 degrees units
+		measure += (16 - sp[6]) - 4;   // Add the compensation and remember to subtract 0.25 degree (4/16)
+	}
+
+	// check for negative 
+	if ( measure & 0x8000 )  {
+		negative = 1;       // mark negative
+		measure ^= 0xffff;  // convert to positive => (twos complement)++
+		measure++;
+	}
+	else {
+		negative = 0;
+	}
+
+	// clear undefined bits for DS18B20 != 12bit resolution
+	if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
+		switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
+		case DS18B20_9_BIT:
+			measure &= ~(DS18B20_9_BIT_UNDF);
+			break;
+		case DS18B20_10_BIT:
+			measure &= ~(DS18B20_10_BIT_UNDF);
+			break;
+		case DS18B20_11_BIT:
+			measure &= ~(DS18B20_11_BIT_UNDF);
+			break;
+		default:
+			// 12 bit - all bits valid
+			break;
+		}
+	}
+
+	decicelsius = (measure >> 4);
+	decicelsius *= 10;
+
+	// decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
+	// 625/1000 = 640/1024
+	fract = ( measure & 0x000F ) * 640;
+	if ( !negative ) {
+		fract += 512;
+	}
+	fract /= 1024;
+	decicelsius += fract;
+
+	if ( negative ) {
+		decicelsius = -decicelsius;
+	}
+
+	if ( /* decicelsius == 850 || */ decicelsius < -550 || decicelsius > 1250 ) {
+		return DS18X20_INVALID_DECICELSIUS;
+	} else {
+		return decicelsius;
+	}
+}
+
+/* format decicelsius-value into string, itoa method inspired 
+   by code from Chris Takahashi for the MSP430 libc, BSD-license 
+   modifications mthomas: variable-types, fixed radix 10, use div(), 
+   insert decimal-point */
+uint8_t DS18X20_format_from_decicelsius( int16_t decicelsius, char str[], uint8_t n)
+{
+	uint8_t sign = 0;
+	char temp[7];
+	int8_t temp_loc = 0;
+	uint8_t str_loc = 0;
+	div_t dt;
+	uint8_t ret;
+
+	// range from -550:-55.0�C to 1250:+125.0�C -> min. 6+1 chars
+	if ( n >= (6+1) && decicelsius > -1000 && decicelsius < 10000 ) {
+
+		if ( decicelsius < 0) {
+			sign = 1;
+			decicelsius = -decicelsius;
+		}
+
+		// construct a backward string of the number.
+		do {
+			dt = div(decicelsius,10);
+			temp[temp_loc++] = dt.rem + '0';
+			decicelsius = dt.quot;
+		} while ( decicelsius > 0 );
+
+		if ( sign ) {
+			temp[temp_loc] = '-';
+		} else {
+			///temp_loc--;
+			temp[temp_loc] = '+';
+		}
+
+		// reverse the string.into the output
+		while ( temp_loc >=0 ) {
+			str[str_loc++] = temp[(uint8_t)temp_loc--];
+			if ( temp_loc == 0 ) {
+				str[str_loc++] = DS18X20_DECIMAL_CHAR;
+			}
+		}
+		str[str_loc] = '\0';
+
+		ret = DS18X20_OK;
+	} else {
+		ret = DS18X20_ERROR;
+	}
+	
+	return ret;
+}
+
+/* reads temperature (scratchpad) of sensor with rom-code id
+   output: decicelsius 
+   returns DS18X20_OK on success */
+uint8_t DS18X20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
+{
+	uint8_t sp[DS18X20_SP_SIZE];
+	uint8_t ret;
+	
+	ow_reset();
+	ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
+	if ( ret == DS18X20_OK ) {
+		*decicelsius = DS18X20_raw_to_decicelsius( id[0], sp );
+	}
+	return ret;
+}
+
+/* reads temperature (scratchpad) of sensor without id (single sensor)
+   output: decicelsius 
+   returns DS18X20_OK on success */
+uint8_t DS18X20_read_decicelsius_single( uint8_t familycode, int16_t *decicelsius )
+{
+	uint8_t sp[DS18X20_SP_SIZE];
+	uint8_t ret;
+	
+	ret = read_scratchpad( NULL, sp, DS18X20_SP_SIZE );
+	if ( ret == DS18X20_OK ) {
+		*decicelsius = DS18X20_raw_to_decicelsius( familycode, sp );
+	}
+	return ret;
+}
+
+#endif /* DS18X20_DECICELSIUS */
+
+
+#if DS18X20_MAX_RESOLUTION
+
+static int32_t DS18X20_raw_to_maxres( uint8_t familycode, uint8_t sp[] )
+{
+	uint16_t measure;
+	uint8_t  negative;
+	int32_t  temperaturevalue;
+
+	measure = sp[0] | (sp[1] << 8);
+	//measure = 0xFF5E; // test -10.125
+	//measure = 0xFE6F; // test -25.0625
+
+	if( familycode == DS18S20_FAMILY_CODE ) {   // 9 -> 12 bit if 18S20
+		/* Extended measurements for DS18S20 contributed by Carsten Foss */
+		measure &= (uint16_t)0xfffe;   // Discard LSB, needed for later extended precicion calc
+		measure <<= 3;                 // Convert to 12-bit, now degrees are in 1/16 degrees units
+		measure += ( 16 - sp[6] ) - 4; // Add the compensation and remember to subtract 0.25 degree (4/16)
+	}
+
+	// check for negative 
+	if ( measure & 0x8000 )  {
+		negative = 1;       // mark negative
+		measure ^= 0xffff;  // convert to positive => (twos complement)++
+		measure++;
+	}
+	else {
+		negative = 0;
+	}
+
+	// clear undefined bits for DS18B20 != 12bit resolution
+	if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
+		switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
+		case DS18B20_9_BIT:
+			measure &= ~(DS18B20_9_BIT_UNDF);
+			break;
+		case DS18B20_10_BIT:
+			measure &= ~(DS18B20_10_BIT_UNDF);
+			break;
+		case DS18B20_11_BIT:
+			measure &= ~(DS18B20_11_BIT_UNDF);
+			break;
+		default:
+			// 12 bit - all bits valid
+			break;
+		}
+	}
+
+	temperaturevalue  = (measure >> 4);
+	temperaturevalue *= 10000;
+	temperaturevalue +=( measure & 0x000F ) * DS18X20_FRACCONV;
+
+	if ( negative ) {
+		temperaturevalue = -temperaturevalue;
+	}
+
+	return temperaturevalue;
+}
+
+uint8_t DS18X20_read_maxres( uint8_t id[], int32_t *temperaturevalue )
+{
+	uint8_t sp[DS18X20_SP_SIZE];
+	uint8_t ret;
+	
+	ow_reset();
+	ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
+	if ( ret == DS18X20_OK ) {
+		*temperaturevalue = DS18X20_raw_to_maxres( id[0], sp );
+	}
+	return ret;
+}
+
+uint8_t DS18X20_read_maxres_single( uint8_t familycode, int32_t *temperaturevalue )
+{
+	uint8_t sp[DS18X20_SP_SIZE];
+	uint8_t ret;
+	
+	ret = read_scratchpad( NULL, sp, DS18X20_SP_SIZE );
+	if ( ret == DS18X20_OK ) {
+		*temperaturevalue = DS18X20_raw_to_maxres( familycode, sp );
+	}
+	return ret;
+
+}
+
+uint8_t DS18X20_format_from_maxres( int32_t temperaturevalue, char str[], uint8_t n)
+{
+	uint8_t sign = 0;
+	char temp[10];
+	int8_t temp_loc = 0;
+	uint8_t str_loc = 0;
+	ldiv_t ldt;
+	uint8_t ret;
+
+	// range from -550000:-55.0000�C to 1250000:+125.0000�C -> min. 9+1 chars
+	if ( n >= (9+1) && temperaturevalue > -1000000L && temperaturevalue < 10000000L ) {
+
+		if ( temperaturevalue < 0) {
+			sign = 1;
+			temperaturevalue = -temperaturevalue;
+		}
+
+		do {
+			ldt = ldiv( temperaturevalue, 10 );
+			temp[temp_loc++] = ldt.rem + '0';
+			temperaturevalue = ldt.quot;
+		} while ( temperaturevalue > 0 );
+		
+		// mk 20110209
+		if ((temp_loc < 4)&&(temp_loc > 1)) {
+			temp[temp_loc++] = '0';
+		} // mk end
+
+		if ( sign ) {
+			temp[temp_loc] = '-';
+		} else {
+			temp[temp_loc] = '+';
+		}
+
+		while ( temp_loc >= 0 ) {
+			str[str_loc++] = temp[(uint8_t)temp_loc--];
+			if ( temp_loc == 3 ) {
+				str[str_loc++] = DS18X20_DECIMAL_CHAR;
+			}
+		}
+		str[str_loc] = '\0';
+
+		ret = DS18X20_OK;
+	} else {
+		ret = DS18X20_ERROR;
+	}
+	
+	return ret;
+}
+
+#endif /* DS18X20_MAX_RESOLUTION */
+
+
+#if DS18X20_EEPROMSUPPORT
+
+uint8_t DS18X20_write_scratchpad( uint8_t id[], 
+	uint8_t th, uint8_t tl, uint8_t conf)
+{
+	uint8_t ret;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		ow_command( DS18X20_WRITE_SCRATCHPAD, id );
+		ow_byte_wr( th );
+		ow_byte_wr( tl );
+		if ( id[0] == DS18B20_FAMILY_CODE || id[0] == DS1822_FAMILY_CODE ) {
+			ow_byte_wr( conf ); // config only available on DS18B20 and DS1822
+		}
+		ret = DS18X20_OK;
+	} 
+	else { 
+		uart_puts_P_verbose( "DS18X20_write_scratchpad: Short Circuit!\r" );
+		ret = DS18X20_ERROR;
+	}
+
+	return ret;
+}
+
+uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
+{
+	uint8_t ret;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		ret = read_scratchpad( id, sp, n );
+	} 
+	else {
+		uart_puts_P_verbose( "DS18X20_read_scratchpad: Short Circuit!\r" );
+		ret = DS18X20_ERROR;
+	}
+
+	return ret;
+}
+
+uint8_t DS18X20_scratchpad_to_eeprom( uint8_t with_power_extern, 
+	uint8_t id[] )
+{
+	uint8_t ret;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		if ( with_power_extern != DS18X20_POWER_EXTERN ) {
+			ow_command_with_parasite_enable( DS18X20_COPY_SCRATCHPAD, id );
+			/* not longer needed: ow_parasite_enable(); */
+		} else {
+			ow_command( DS18X20_COPY_SCRATCHPAD, id );
+		}
+		_delay_ms(DS18X20_COPYSP_DELAY); // wait for 10 ms 
+		if ( with_power_extern != DS18X20_POWER_EXTERN ) {
+			ow_parasite_disable();
+		}
+		ret = DS18X20_OK;
+	} 
+	else { 
+		uart_puts_P_verbose( "DS18X20_copy_scratchpad: Short Circuit!\r" );
+		ret = DS18X20_START_FAIL;
+	}
+
+	return ret;
+}
+
+uint8_t DS18X20_eeprom_to_scratchpad( uint8_t id[] )
+{
+	uint8_t ret;
+	uint8_t retry_count=255;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		ow_command( DS18X20_RECALL_E2, id );
+		while( retry_count-- && !( ow_bit_io( 1 ) ) ) { 
+			;
+		}
+		if ( retry_count ) {
+			ret = DS18X20_OK;
+		} else {
+			uart_puts_P_verbose( "DS18X20_recall_E2: timeout!\r" );
+			ret = DS18X20_ERROR;
+		}
+	} 
+	else { 
+		uart_puts_P_verbose( "DS18X20_recall_E2: Short Circuit!\r" );
+		ret = DS18X20_ERROR;
+	}
+
+	return ret;
+}
+
+#endif /* DS18X20_EEPROMSUPPORT */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ds18x20.h	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,140 @@
+#ifndef DS18X20_H_
+#define DS18X20_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+
+// DS18x20 EERPROM support disabled(0) or enabled(1) :
+#define DS18X20_EEPROMSUPPORT     1
+// decicelsius functions disabled(0) or enabled(1):
+#define DS18X20_DECICELSIUS       1
+// max. resolution functions disabled(0) or enabled(1):
+#define DS18X20_MAX_RESOLUTION    1
+// extended output via UART disabled(0) or enabled(1) :
+#define DS18X20_VERBOSE           1
+
+
+/* return values */
+#define DS18X20_OK                0x00
+#define DS18X20_ERROR             0x01
+#define DS18X20_START_FAIL        0x02
+#define DS18X20_ERROR_CRC         0x03
+
+#define DS18X20_INVALID_DECICELSIUS  2000
+
+#define DS18X20_POWER_PARASITE    0x00
+#define DS18X20_POWER_EXTERN      0x01
+
+#define DS18X20_CONVERSION_DONE   0x00
+#define DS18X20_CONVERTING        0x01
+
+/* DS18X20 specific values (see datasheet) */
+#define DS18S20_FAMILY_CODE       0x10
+#define DS18B20_FAMILY_CODE       0x28
+#define DS1822_FAMILY_CODE        0x22
+
+#define DS18X20_CONVERT_T         0x44
+#define DS18X20_READ              0xBE
+#define DS18X20_WRITE             0x4E
+#define DS18X20_EE_WRITE          0x48
+#define DS18X20_EE_RECALL         0xB8
+#define DS18X20_READ_POWER_SUPPLY 0xB4
+
+#define DS18B20_CONF_REG          4
+#define DS18B20_9_BIT             0
+#define DS18B20_10_BIT            (1<<5)
+#define DS18B20_11_BIT            (1<<6)
+#define DS18B20_12_BIT            ((1<<6)|(1<<5))
+#define DS18B20_RES_MASK          ((1<<6)|(1<<5))
+
+// undefined bits in LSB if 18B20 != 12bit
+#define DS18B20_9_BIT_UNDF        ((1<<0)|(1<<1)|(1<<2))
+#define DS18B20_10_BIT_UNDF       ((1<<0)|(1<<1))
+#define DS18B20_11_BIT_UNDF       ((1<<0))
+#define DS18B20_12_BIT_UNDF       0
+
+// conversion times in milliseconds
+#define DS18B20_TCONV_12BIT       750
+#define DS18B20_TCONV_11BIT       DS18B20_TCONV_12_BIT/2
+#define DS18B20_TCONV_10BIT       DS18B20_TCONV_12_BIT/4
+#define DS18B20_TCONV_9BIT        DS18B20_TCONV_12_BIT/8
+#define DS18S20_TCONV             DS18B20_TCONV_12_BIT
+
+// constant to convert the fraction bits to cel*(10^-4)
+#define DS18X20_FRACCONV          625
+
+// scratchpad size in bytes
+#define DS18X20_SP_SIZE           9
+
+// DS18X20 EEPROM-Support
+#define DS18X20_WRITE_SCRATCHPAD  0x4E
+#define DS18X20_COPY_SCRATCHPAD   0x48
+#define DS18X20_RECALL_E2         0xB8
+#define DS18X20_COPYSP_DELAY      10 /* ms */
+#define DS18X20_TH_REG            2
+#define DS18X20_TL_REG            3
+
+#define DS18X20_DECIMAL_CHAR      '.'
+
+
+extern uint8_t DS18X20_find_sensor(uint8_t *diff, 
+	uint8_t id[]);
+extern uint8_t DS18X20_get_power_status(uint8_t id[]);
+extern uint8_t DS18X20_start_meas( uint8_t with_external,
+	uint8_t id[]);
+// returns 1 if conversion is in progress, 0 if finished
+// not available when parasite powered
+extern uint8_t DS18X20_conversion_in_progress(void);
+
+
+#if DS18X20_DECICELSIUS
+extern uint8_t DS18X20_read_decicelsius( uint8_t id[],
+	int16_t *decicelsius );
+extern uint8_t DS18X20_read_decicelsius_single( uint8_t familycode,
+	int16_t *decicelsius );
+extern uint8_t DS18X20_format_from_decicelsius( int16_t decicelsius, 
+	char s[], uint8_t n);
+#endif /* DS18X20_DECICELSIUS */
+
+
+#if DS18X20_MAX_RESOLUTION
+// temperature unit for max. resolution is �C * 10e-4
+// examples: -250625 -> -25.0625�C, 1250000 -> 125.0000 �C
+extern uint8_t DS18X20_read_maxres( uint8_t id[],
+	int32_t *temperaturevalue );
+extern uint8_t DS18X20_read_maxres_single( uint8_t familycode,
+	int32_t *temperaturevalue );
+extern uint8_t DS18X20_format_from_maxres( int32_t temperaturevalue, 
+	char s[], uint8_t n);
+#endif /* DS18X20_MAX_RESOLUTION */
+
+
+#if DS18X20_EEPROMSUPPORT
+// write th, tl and config-register to scratchpad (config ignored on DS18S20)
+uint8_t DS18X20_write_scratchpad( uint8_t id[], 
+	uint8_t th, uint8_t tl, uint8_t conf);
+// read scratchpad into array SP
+uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n);
+// copy values int scratchpad into DS18x20 eeprom
+uint8_t DS18X20_scratchpad_to_eeprom( uint8_t with_power_extern,
+	uint8_t id[] );
+// copy values from DS18x20 eeprom into scratchpad
+uint8_t DS18X20_eeprom_to_scratchpad( uint8_t id[] );
+#endif /* DS18X20_EEPROMSUPPORT */
+
+
+#if DS18X20_VERBOSE
+extern void DS18X20_show_id_uart( uint8_t *id, size_t n );
+extern uint8_t DS18X20_read_meas_all_verbose( void );
+#endif /* DS18X20_VERBOSE */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/main.c	Fri May 18 20:38:40 2012 +0800
+++ b/main.c	Fri May 18 23:57:08 2012 +0800
@@ -14,6 +14,7 @@
 #include <util/crc16.h>
 
 #include "integer.h"
+#include "onewire.h"
 
 // configuration params
 // - measurement interval
@@ -186,8 +187,6 @@
 		comms_count = 0;
 		need_comms = 1;
 	}
-
-    PORT_LED ^= _BV(PIN_LED);
 }
 
 DWORD get_fattime (void)
@@ -313,7 +312,7 @@
 blink()
 {
     PORT_LED &= ~_BV(PIN_LED);
-    _delay_ms(100);
+    _delay_ms(1);
     PORT_LED |= _BV(PIN_LED);
 }
 
@@ -334,8 +333,26 @@
     printf_P(PSTR("Bad interrupt\n"));
 }
 
+static void
+set_2mhz()
+{
+    cli();
+    CLKPR = _BV(CLKPCE);
+    // divide by 4
+    CLKPR = _BV(CLKPS1);
+    sei();
+}
+
+static void
+test1wire()
+{
+    ow_reset();
+}
+
 int main(void)
 {
+    set_2mhz();
+
     DDR_LED |= _BV(PIN_LED);
     blink();
 
@@ -376,6 +393,9 @@
     }
 #else
     for(;;){
+
+        test1wire();
+
         /* insert your main loop code here */
         if (need_measurement)
         {
@@ -390,6 +410,7 @@
         }
 
 		deep_sleep();
+        blink();
     }
 #endif
     return 0;   /* never reached */
--- a/onewire.h	Fri May 18 20:38:40 2012 +0800
+++ b/onewire.h	Fri May 18 23:57:08 2012 +0800
@@ -16,14 +16,14 @@
    If not defined make sure to call ow_set_bus() before using 
    a bus. Runtime bus-select increases code size by around 300 
    bytes so use OW_ONE_BUS if possible */
-// #define OW_ONE_BUS
+#define OW_ONE_BUS
 
 #ifdef OW_ONE_BUS
 
-#define OW_PIN  PD6
-#define OW_IN   PIND
-#define OW_OUT  PORTD
-#define OW_DDR  DDRD
+#define OW_PIN  PB1
+#define OW_IN   PINB
+#define OW_OUT  PORTB
+#define OW_DDR  DDRB
 #define OW_CONF_DELAYOFFSET 0
 
 #else 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uart_addon.c	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,118 @@
+/*************************************************************************
+Title:     UART addon-library 
+Author:    Martin Thomas <[email protected]>   
+           http://www.siwawi.arubi.uni-kl.de/avr_projects
+Software:  AVR-GCC 3.3/3.4, Peter Fleury's UART-Library
+
+DESCRIPTION:
+    
+USAGE:
+    Refere to the header file uart_addon.h for a description of the routines. 
+
+*************************************************************************/
+
+#include <stdlib.h>
+
+#include <avr/io.h>
+#include "uart.h"
+
+
+/*************************************************************************
+Function: uart_put_int()
+Purpose:  transmit integer as ASCII to UART
+Input:    integer value
+Returns:  none
+**************************************************************************/
+void uart_put_int( const int val )
+{
+	char buffer[10];
+	uart_puts( itoa( val, buffer, 10 ) );
+} /* uart_puti */
+
+/*************************************************************************
+Function: uart_put_longint()
+Purpose:  transmit long integer as ASCII to UART
+Input:    integer value
+Returns:  none
+**************************************************************************/
+void uart_put_longint( const long int val )
+{
+	char buffer[15];
+	uart_puts( ltoa( val, buffer, 10 ) );
+} /* uart_puti */
+
+/*************************************************************************
+Function: uart_put_ulongint()
+Purpose:  transmit long integer as ASCII to UART
+Input:    integer value
+Returns:  none
+**************************************************************************/
+void uart_put_ulongint( const unsigned long int val )
+{
+	char buffer[15];
+	uart_puts( utoa( val, buffer, 10 ) );
+} /* uart_puti */
+
+/*************************************************************************
+Function: uart_puthex_nibble()
+Purpose:  transmit lower nibble as ASCII-hex to UART
+Input:    byte value
+Returns:  none
+**************************************************************************/
+void uart_puthex_nibble(const unsigned char b)
+{
+	unsigned char  c = b & 0x0f;
+	if ( c > 9 ) { 
+		c += 'A'-10; 
+	}
+	else {
+		c += '0';
+	}
+	uart_putc(c);
+} /* uart_puthex_nibble */
+
+/*************************************************************************
+Function: uart_puthex_byte()
+Purpose:  transmit upper and lower nibble as ASCII-hex to UART
+Input:    byte value
+Returns:  none
+**************************************************************************/
+void uart_puthex_byte( const unsigned char  b )
+{
+	uart_puthex_nibble( b >> 4 );
+	uart_puthex_nibble( b );
+} /* uart_puthex_byte */
+
+/*************************************************************************
+Function: uart_puthex_long()
+Purpose:  transmit unsigned long as ASCII-hex to UART
+Input:    uint32_t value
+Returns:  none
+**************************************************************************/
+void uart_puthex_long( const unsigned long l )
+{
+	uart_puthex_byte( (unsigned char)( l >> 24 ) );
+	uart_puthex_byte( (unsigned char)( l >> 16 ) );
+	uart_puthex_byte( (unsigned char)( l >> 8 ) );
+	uart_puthex_byte( (unsigned char)( l ) );
+} /* uart_puthex_byte */
+
+
+/*************************************************************************
+Function: uart_putbin_byte()
+Purpose:  transmit byte as ASCII-bin to UART
+Input:    byte value
+Returns:  none
+**************************************************************************/
+void uart_putbin_byte( const unsigned char b )
+{
+	signed char i;
+	for ( i= 7;i >= 0;i-- ) {
+		if ( b & ( 1 << i ) ) {
+			uart_putc( '1' );
+		}
+		else {
+			uart_putc( '0' );
+		}
+	}
+} /* uart_putbin_byte */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uart_addon.h	Fri May 18 23:57:08 2012 +0800
@@ -0,0 +1,121 @@
+#ifndef UART_ADDON_H
+#define UART_ADDON_H
+/************************************************************************
+Title:     UART addon-library 
+Author:    Martin Thomas <[email protected]>   
+           http://www.siwawi.arubi.uni-kl.de/avr_projects
+Software:  AVR-GCC 3.3/3.4, Peter Fleury's UART-Library
+************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+ *  @defgroup UART library-addon
+ *  @code #include <uart_addon.h> @endcode
+ * 
+ *  @brief Additional functions for send numbers as decimal and hex to UART
+ *
+ *  @note needs Peter Fleury's UART-Library http://jump.to/fleury
+ *  @author  Martin Thomas [email protected]   
+ */
+ 
+/*@{*/
+
+/**
+ * @brief    Put long integer to ringbuffer for transmitting via UART.
+ *
+ * The integer is converted to a string which is buffered by the uart 
+ * library in a circular buffer and one character at a time is transmitted 
+ * to the UART using interrupts.
+ *
+ * @param    value to transfer
+ * @return   none
+ * @see      uart_puts_p
+ */
+extern void uart_put_longint( long int i );
+
+
+/**
+ * @brief    Put unsigned long integer to ringbuffer for transmitting via UART.
+ *
+ * The integer is converted to a string which is buffered by the uart 
+ * library in a circular buffer and one character at a time is transmitted 
+ * to the UART using interrupts.
+ *
+ * @param    value to transfer
+ * @return   none
+ * @see      uart_puts_p
+ */
+extern void uart_put_ulongint( unsigned long int i );
+
+
+/**
+ * @brief    Put integer to ringbuffer for transmitting via UART.
+ *
+ * The integer is converted to a string which is buffered by the uart 
+ * library in a circular buffer and one character at a time is transmitted 
+ * to the UART using interrupts.
+ *
+ * @param    value to transfer
+ * @return   none
+ * @see      uart_puts_p
+ */
+extern void uart_put_int( int i );
+
+
+/**
+ * @brief    Put nibble as hex to ringbuffer for transmit via UART.
+ *
+ * The lower nibble of the parameter is convertet to correspondig
+ * hex-char and put in a circular buffer and one character at a time 
+ * is transmitted to the UART using interrupts.
+ *
+ * @param    value to transfer (byte, only lower nibble converted)
+ * @return   none
+ * @see      uart_putc
+ */
+extern void uart_puthex_nibble( const unsigned char b );
+
+/**
+ * @brief    Put byte as hex to ringbuffer for transmit via UART.
+ *
+ * The upper and lower nibble of the parameter are convertet to 
+ * correspondig hex-chars and put in a circular buffer and one 
+ * character at a time is transmitted to the UART using interrupts.
+ *
+ * @param    value to transfer
+ * @return   none
+ * @see      uart_puthex_nibble
+ */
+extern void uart_puthex_byte( const unsigned char b );
+
+/**
+ * @brief    Put unsigned long as ASCII to ringbuffer for transmit via UART.
+ *
+ * @param    value to transfer
+ * @return   none
+ * @see      none
+ */
+extern void uart_puthex_long( unsigned long l );
+
+/**
+ * @brief    Put byte as bin to ringbuffer for transmit via UART.
+ *
+ * @param    value to transfer
+ * @return   none
+ * @see      uart_putc
+ */
+extern void uart_putbin_byte( const unsigned char b );
+
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* UART_ADDON_H */
+