Add Rmodule project

This commit is contained in:
Aleksandr Filippov
2013-11-15 14:42:41 +07:00
parent ec40c679d7
commit bd6ec0b4d1
12 changed files with 1739 additions and 0 deletions

63
Rmodule/onewire/crc8.c Normal file
View 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
View 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
View 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
View 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