Mercurial > templog
changeset 4:54d369e3d689
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 | 888be1b234b6 |
children | 011160e5b1ce |
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