Add Rmodule project
This commit is contained in:
63
Rmodule/onewire/crc8.c
Normal file
63
Rmodule/onewire/crc8.c
Normal file
@ -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.
|
||||
*/
|
40
Rmodule/onewire/crc8.h
Normal file
40
Rmodule/onewire/crc8.h
Normal file
@ -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.
|
||||
*/
|
||||
|
287
Rmodule/onewire/onewire.c
Normal file
287
Rmodule/onewire/onewire.c
Normal file
@ -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 );
|
||||
}
|
||||
|
93
Rmodule/onewire/onewire.h
Normal file
93
Rmodule/onewire/onewire.h
Normal file
@ -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
|
Reference in New Issue
Block a user