changeset 310:0a64532c1de1

Fill out more main.c structure Add onewire files
author Matt Johnston <matt@ucc.asn.au>
date Wed, 09 May 2012 00:22:28 +0800
parents 49e83333e546
children fc96a51bdce6
files Makefile main.c onewire.c onewire.h
diffstat 4 files changed, 442 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue May 08 22:51:38 2012 +0800
+++ b/Makefile	Wed May 09 00:22:28 2012 +0800
@@ -20,7 +20,7 @@
 DEVICE     = atmega328
 CLOCK      = 1000000
 PROGRAMMER = #-c stk500v2 -P avrdoper
-OBJECTS    = main.o ff.o mmc.o
+OBJECTS    = main.o ff.o mmc.o onewire.o
 FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m
 
 # ATMega8 fuse bits used above (fuse bits for other devices are different!):
@@ -49,7 +49,7 @@
 # Tune the lines below only if you know what you are doing:
 
 AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)
-COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g
+COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99
 
 # symbolic targets:
 all:	main.hex
--- a/main.c	Tue May 08 22:51:38 2012 +0800
+++ b/main.c	Wed May 09 00:22:28 2012 +0800
@@ -21,7 +21,9 @@
 
 // 1 second. we have 1024 prescaler, 32768 crystal.
 #define SLEEP_COMPARE 32
-#define SECONDS_WAKE 60
+#define MEASURE_WAKE 60
+
+#define COMMS_WAKE 3600
 
 #define BAUD 9600
 #define UBRR ((F_CPU)/16/(BAUD)-1)
@@ -33,12 +35,18 @@
 static uint8_t n_measurements;
 static uint8_t measurements[500];
 
+// boolean flags
 static uint8_t need_measurement;
+static uint8_t need_comms;
+static uint8_t comms_done;
 
 static uint8_t readpos;
 static char readbuf[30];
 
 static uint8_t sec_count;
+static uint16_t bt_count;
+
+static void deep_sleep();
 
 static void 
 uart_init(unsigned int ubrr)
@@ -82,6 +90,7 @@
 static void
 cmd_btoff()
 {
+	comms_done = 1;
 }
 
 static void
@@ -127,12 +136,19 @@
 
 ISR(TIMER2_COMPA_vect)
 {
-    sec_count ++;
-    if (sec_count == SECONDS_WAKE)
+    measure_count ++;
+	comms_count ++;
+    if (measure_count == MEASURE_WAKE)
     {
-        sec_count = 0;
+        measure_count = 0;
         need_measurement = 1;
     }
+
+	if (comms_count == COMMS_WAKE)
+	{
+		comms_count = 0;
+		need_comms = 1;
+	}
 }
 
 DWORD get_fattime (void)
@@ -152,11 +168,42 @@
 }
 
 static void
+idle_sleep()
+{
+    set_sleep_mode(SLEEP_MODE_IDLE);
+    sleep_mode();
+}
+
+static void
 do_measurement()
 {
     need_measurement = 0;
 }
 
+static void
+do_comms()
+{
+	need_comms = 0;
+
+	// turn on bluetooth
+	// turn on serial (interrupts)
+	
+	// write sd card here? same 3.3v regulator...
+	
+	comms_done = 0;
+	for (;;)
+	{
+		if (comms_done)
+		{
+			break;
+		}
+		idle_sleep();
+	}
+
+	// turn off bluetooth
+	// turn off serial (interrupts)
+}
+
 int main(void)
 {
     uart_init(UBRR);
@@ -177,7 +224,16 @@
         if (need_measurement)
         {
             do_measurement();
+			continue;
         }
+
+        if (need_comms)
+        {
+            do_comms();
+			continue;
+        }
+
+		deep_sleep();
     }
     return 0;   /* never reached */
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/onewire.c	Wed May 09 00:22:28 2012 +0800
@@ -0,0 +1,287 @@
+/* 
+Access Dallas 1-Wire Devices with ATMEL AVRs
+Author of the initial code: Peter Dannegger (danni(at)specs.de)
+modified by Martin Thomas (mthomas(at)rhrk.uni-kl.de)
+ 9/2004 - use of delay.h, optional bus configuration at runtime
+10/2009 - additional delay in ow_bit_io for recovery
+ 5/2010 - timing modifcations, additonal config-values and comments,
+          use of atomic.h macros, internal pull-up support
+ 7/2010 - added method to skip recovery time after last bit transfered
+          via ow_command_skip_last_recovery
+*/
+
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include <util/atomic.h>
+
+#include "onewire.h"
+
+#ifdef OW_ONE_BUS
+
+#define OW_GET_IN()   ( OW_IN & (1<<OW_PIN))
+#define OW_OUT_LOW()  ( OW_OUT &= (~(1 << OW_PIN)) )
+#define OW_OUT_HIGH() ( OW_OUT |= (1 << OW_PIN) )
+#define OW_DIR_IN()   ( OW_DDR &= (~(1 << OW_PIN )) )
+#define OW_DIR_OUT()  ( OW_DDR |= (1 << OW_PIN) )
+
+#else
+
+/* set bus-config with ow_set_bus() */
+uint8_t OW_PIN_MASK; 
+volatile uint8_t* OW_IN;
+volatile uint8_t* OW_OUT;
+volatile uint8_t* OW_DDR;
+
+#define OW_GET_IN()   ( *OW_IN & OW_PIN_MASK )
+#define OW_OUT_LOW()  ( *OW_OUT &= (uint8_t) ~OW_PIN_MASK )
+#define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t)  OW_PIN_MASK )
+#define OW_DIR_IN()   ( *OW_DDR &= (uint8_t) ~OW_PIN_MASK )
+#define OW_DIR_OUT()  ( *OW_DDR |= (uint8_t)  OW_PIN_MASK )
+
+void ow_set_bus(volatile uint8_t* in,
+	volatile uint8_t* out,
+	volatile uint8_t* ddr,
+	uint8_t pin)
+{
+	OW_DDR=ddr;
+	OW_OUT=out;
+	OW_IN=in;
+	OW_PIN_MASK = (1 << pin);
+	ow_reset();
+}
+
+#endif
+
+uint8_t ow_input_pin_state()
+{
+	return OW_GET_IN();
+}
+
+void ow_parasite_enable(void)
+{
+	OW_OUT_HIGH();
+	OW_DIR_OUT();
+}
+
+void ow_parasite_disable(void)
+{
+	OW_DIR_IN();
+#if (!OW_USE_INTERNAL_PULLUP)
+	OW_OUT_LOW();
+#endif
+}
+
+
+uint8_t ow_reset(void)
+{
+	uint8_t err;
+	
+	OW_OUT_LOW();
+	OW_DIR_OUT();            // pull OW-Pin low for 480us
+	_delay_us(480);
+
+	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+		// set Pin as input - wait for clients to pull low
+		OW_DIR_IN(); // input
+#if OW_USE_INTERNAL_PULLUP
+		OW_OUT_HIGH();
+#endif
+	
+		_delay_us(64);       // was 66
+		err = OW_GET_IN();   // no presence detect
+		                     // if err!=0: nobody pulled to low, still high
+	}
+	
+	// after a delay the clients should release the line
+	// and input-pin gets back to high by pull-up-resistor
+	_delay_us(480 - 64);       // was 480-66
+	if( OW_GET_IN() == 0 ) {
+		err = 1;             // short circuit, expected low but got high
+	}
+	
+	return err;
+}
+
+
+/* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
+   The master should sample at the end of the 15-slot after initiating
+   the read-time-slot. The variable bus-settings need more
+   cycles than the constant ones so the delays had to be shortened 
+   to achive a 15uS overall delay 
+   Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
+   but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
+static uint8_t ow_bit_io_intern( uint8_t b, uint8_t with_parasite_enable )
+{
+	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+#if OW_USE_INTERNAL_PULLUP
+		OW_OUT_LOW();
+#endif
+		OW_DIR_OUT();    // drive bus low
+		_delay_us(2);    // T_INT > 1usec accoding to timing-diagramm
+		if ( b ) {
+			OW_DIR_IN(); // to write "1" release bus, resistor pulls high
+#if OW_USE_INTERNAL_PULLUP
+			OW_OUT_HIGH();
+#endif
+		}
+
+		// "Output data from the DS18B20 is valid for 15usec after the falling
+		// edge that initiated the read time slot. Therefore, the master must 
+		// release the bus and then sample the bus state within 15ussec from 
+		// the start of the slot."
+		_delay_us(15-2-OW_CONF_DELAYOFFSET);
+		
+		if( OW_GET_IN() == 0 ) {
+			b = 0;  // sample at end of read-timeslot
+		}
+	
+		_delay_us(60-15-2+OW_CONF_DELAYOFFSET);
+#if OW_USE_INTERNAL_PULLUP
+		OW_OUT_HIGH();
+#endif
+		OW_DIR_IN();
+	
+		if ( with_parasite_enable ) {
+			ow_parasite_enable();
+		}
+	
+	} /* ATOMIC_BLOCK */
+
+	_delay_us(OW_RECOVERY_TIME); // may be increased for longer wires
+
+	return b;
+}
+
+uint8_t ow_bit_io( uint8_t b )
+{
+	return ow_bit_io_intern( b & 1, 0 );
+}
+
+uint8_t ow_byte_wr( uint8_t b )
+{
+	uint8_t i = 8, j;
+	
+	do {
+		j = ow_bit_io( b & 1 );
+		b >>= 1;
+		if( j ) {
+			b |= 0x80;
+		}
+	} while( --i );
+	
+	return b;
+}
+
+uint8_t ow_byte_wr_with_parasite_enable( uint8_t b )
+{
+	uint8_t i = 8, j;
+	
+	do {
+		if ( i != 1 ) {
+			j = ow_bit_io_intern( b & 1, 0 );
+		} else {
+			j = ow_bit_io_intern( b & 1, 1 );
+		}
+		b >>= 1;
+		if( j ) {
+			b |= 0x80;
+		}
+	} while( --i );
+	
+	return b;
+}
+
+
+uint8_t ow_byte_rd( void )
+{
+	// read by sending only "1"s, so bus gets released
+	// after the init low-pulse in every slot
+	return ow_byte_wr( 0xFF ); 
+}
+
+
+uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
+{
+	uint8_t i, j, next_diff;
+	uint8_t b;
+	
+	if( ow_reset() ) {
+		return OW_PRESENCE_ERR;         // error, no device found <--- early exit!
+	}
+	
+	ow_byte_wr( OW_SEARCH_ROM );        // ROM search command
+	next_diff = OW_LAST_DEVICE;         // unchanged on last device
+	
+	i = OW_ROMCODE_SIZE * 8;            // 8 bytes
+	
+	do {
+		j = 8;                          // 8 bits
+		do {
+			b = ow_bit_io( 1 );         // read bit
+			if( ow_bit_io( 1 ) ) {      // read complement bit
+				if( b ) {               // 0b11
+					return OW_DATA_ERR; // data error <--- early exit!
+				}
+			}
+			else {
+				if( !b ) {              // 0b00 = 2 devices
+					if( diff > i || ((*id & 1) && diff != i) ) {
+						b = 1;          // now 1
+						next_diff = i;  // next pass 0
+					}
+				}
+			}
+			ow_bit_io( b );             // write bit
+			*id >>= 1;
+			if( b ) {
+				*id |= 0x80;            // store bit
+			}
+			
+			i--;
+			
+		} while( --j );
+		
+		id++;                           // next byte
+	
+	} while( i );
+	
+	return next_diff;                   // to continue search
+}
+
+
+static void ow_command_intern( uint8_t command, uint8_t *id, uint8_t with_parasite_enable )
+{
+	uint8_t i;
+
+	ow_reset();
+
+	if( id ) {
+		ow_byte_wr( OW_MATCH_ROM );     // to a single device
+		i = OW_ROMCODE_SIZE;
+		do {
+			ow_byte_wr( *id );
+			id++;
+		} while( --i );
+	} 
+	else {
+		ow_byte_wr( OW_SKIP_ROM );      // to all devices
+	}
+	
+	if ( with_parasite_enable  ) {
+		ow_byte_wr_with_parasite_enable( command );
+	} else {
+		ow_byte_wr( command );
+	}
+}
+
+void ow_command( uint8_t command, uint8_t *id )
+{
+	ow_command_intern( command, id, 0);
+}
+
+void ow_command_with_parasite_enable( uint8_t command, uint8_t *id )
+{
+	ow_command_intern( command, id, 1 );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/onewire.h	Wed May 09 00:22:28 2012 +0800
@@ -0,0 +1,93 @@
+#ifndef ONEWIRE_H_
+#define ONEWIRE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/*******************************************/
+/* Hardware connection                     */
+/*******************************************/
+
+/* Define OW_ONE_BUS if only one 1-Wire-Bus is used
+   in the application -> shorter code.
+   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
+
+#ifdef OW_ONE_BUS
+
+#define OW_PIN  PD6
+#define OW_IN   PIND
+#define OW_OUT  PORTD
+#define OW_DDR  DDRD
+#define OW_CONF_DELAYOFFSET 0
+
+#else 
+#if ( F_CPU < 1843200 )
+#warning | Experimental multi-bus-mode is not tested for 
+#warning | frequencies below 1,84MHz. Use OW_ONE_WIRE or
+#warning | faster clock-source (i.e. internal 2MHz R/C-Osc.).
+#endif
+#define OW_CONF_CYCLESPERACCESS 13
+#define OW_CONF_DELAYOFFSET ( (uint16_t)( ((OW_CONF_CYCLESPERACCESS) * 1000000L) / F_CPU ) )
+#endif
+
+// Recovery time (T_Rec) minimum 1usec - increase for long lines 
+// 5 usecs is a value give in some Maxim AppNotes
+// 30u secs seem to be reliable for longer lines
+//#define OW_RECOVERY_TIME        5  /* usec */
+//#define OW_RECOVERY_TIME      300 /* usec */
+#define OW_RECOVERY_TIME         10 /* usec */
+
+// Use AVR's internal pull-up resistor instead of external 4,7k resistor.
+// Based on information from Sascha Schade. Experimental but worked in tests
+// with one DS18B20 and one DS18S20 on a rather short bus (60cm), where both 
+// sensores have been parasite-powered.
+#define OW_USE_INTERNAL_PULLUP     1  /* 0=external, 1=internal */
+
+/*******************************************/
+
+
+#define OW_MATCH_ROM    0x55
+#define OW_SKIP_ROM     0xCC
+#define OW_SEARCH_ROM   0xF0
+
+#define OW_SEARCH_FIRST 0xFF        // start new search
+#define OW_PRESENCE_ERR 0xFF
+#define OW_DATA_ERR     0xFE
+#define OW_LAST_DEVICE  0x00        // last device found
+
+// rom-code size including CRC
+#define OW_ROMCODE_SIZE 8
+
+extern uint8_t ow_reset(void);
+
+extern uint8_t ow_bit_io( uint8_t b );
+extern uint8_t ow_byte_wr( uint8_t b );
+extern uint8_t ow_byte_rd( void );
+
+extern uint8_t ow_rom_search( uint8_t diff, uint8_t *id );
+
+extern void ow_command( uint8_t command, uint8_t *id );
+extern void ow_command_with_parasite_enable( uint8_t command, uint8_t *id );
+
+extern void ow_parasite_enable( void );
+extern void ow_parasite_disable( void );
+extern uint8_t ow_input_pin_state( void );
+
+#ifndef OW_ONE_BUS
+extern void ow_set_bus( volatile uint8_t* in,
+	volatile uint8_t* out,
+	volatile uint8_t* ddr,
+	uint8_t pin );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif