Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
74 arune 1
/************************************************************************/
2
/*                                                                      */
3
/*        Access Dallas 1-Wire Device with ATMEL AVRs                   */
4
/*                                                                      */
5
/*              Author: Peter Dannegger                                 */
6
/*                      danni@specs.de                                  */
7
/*                                                                      */
8
/* modified by Martin Thomas <eversmith@heizung-thomas.de> 9/2004       */
9
/************************************************************************/
10
 
11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
 
14
#include "delay.h"
15
#include "onewire.h"
16
 
17
#ifdef OW_ONE_BUS
18
 
19
#define OW_GET_IN()   ( OW_IN & (1<<OW_PIN))
20
#define OW_OUT_LOW()  ( OW_OUT &= (~(1 << OW_PIN)) )
21
#define OW_OUT_HIGH() ( OW_OUT |= (1 << OW_PIN) )
22
#define OW_DIR_IN()   ( OW_DDR &= (~(1 << OW_PIN )) )
23
#define OW_DIR_OUT()  ( OW_DDR |= (1 << OW_PIN) )
24
 
25
#else
26
 
27
/* set bus-config with ow_set_bus() */
28
uint8_t OW_PIN_MASK;
29
volatile uint8_t* OW_IN;
30
volatile uint8_t* OW_OUT;
31
volatile uint8_t* OW_DDR;
32
 
33
#define OW_GET_IN()   ( *OW_IN & OW_PIN_MASK )
34
#define OW_OUT_LOW()  ( *OW_OUT &= (uint8_t) ~OW_PIN_MASK )
35
#define OW_OUT_HIGH() ( *OW_OUT |= (uint8_t)  OW_PIN_MASK )
36
#define OW_DIR_IN()   ( *OW_DDR &= (uint8_t) ~OW_PIN_MASK )
37
#define OW_DIR_OUT()  ( *OW_DDR |= (uint8_t)  OW_PIN_MASK )
38
//#define OW_PIN2 PD6
39
//#define OW_DIR_IN2()   ( *OW_DDR &= ~(1 << OW_PIN2 ) )
40
 
41
void ow_set_bus(volatile uint8_t* in,
42
    volatile uint8_t* out,
43
    volatile uint8_t* ddr,
44
    uint8_t pin)
45
{
46
    OW_DDR=ddr;
47
    OW_OUT=out;
48
    OW_IN=in;
49
    OW_PIN_MASK=(1<<pin);
50
    ow_reset();
51
}
52
 
53
#endif
54
 
55
uint8_t ow_input_pin_state()
56
{
57
    return OW_GET_IN();
58
}
59
 
60
void ow_parasite_enable(void)
61
{
62
    OW_OUT_HIGH();
63
    OW_DIR_OUT();
64
}
65
 
66
void ow_parasite_disable(void)
67
{
68
    OW_OUT_LOW();
69
    OW_DIR_IN();
70
}
71
 
72
uint8_t ow_reset(void)
73
{
74
    uint8_t err;
75
    uint8_t sreg;
76
 
77
    OW_OUT_LOW(); // disable internal pull-up (maybe on from parasite)
78
    OW_DIR_OUT(); // pull OW-Pin low for 480us
79
 
80
    delay_us(480);
81
 
82
    sreg=SREG;
83
    cli();
84
 
85
    // set Pin as input - wait for clients to pull low
86
    OW_DIR_IN(); // input
87
 
88
    delay_us(66);
89
    err = OW_GET_IN();      // no presence detect
90
    // nobody pulled to low, still high
91
 
92
    SREG=sreg; // sei()
93
 
94
    // after a delay the clients should release the line
95
    // and input-pin gets back to high due to pull-up-resistor
96
    delay_us(480-66);
97
    if( OW_GET_IN() == 0 )      // short circuit
98
        err = 1;
99
 
100
    return err;
101
}
102
 
103
/* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
104
   The master should sample at the end of the 15-slot after initiating
105
   the read-time-slot. The variable bus-settings need more
106
   cycles than the constant ones so the delays had to be shortened
107
   to achive a 15uS overall delay
108
   Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
109
   but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
110
uint8_t ow_bit_io( uint8_t b )
111
{
112
    uint8_t sreg;
113
 
114
    sreg=SREG;
115
    cli();
116
 
117
    OW_DIR_OUT(); // drive bus low
118
 
119
    delay_us(1); // Recovery-Time wuffwuff was 1
120
    if ( b ) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)
121
 
122
    // wuffwuff delay was 15uS-1 see comment above
123
    delay_us(15-1-OW_CONF_DELAYOFFSET);
124
 
125
    if( OW_GET_IN() == 0 ) b = 0;  // sample at end of read-timeslot
126
 
127
    delay_us(60-15);
128
    OW_DIR_IN();
129
 
130
    SREG=sreg; // sei();
131
 
132
    return b;
133
}
134
 
135
 
136
uint8_t ow_byte_wr( uint8_t b )
137
{
138
    uint8_t i = 8, j;
139
 
140
    do {
141
        j = ow_bit_io( b & 1 );
142
        b >>= 1;
143
        if( j ) b |= 0x80;
144
    } while( --i );
145
 
146
    return b;
147
}
148
 
149
 
150
uint8_t ow_byte_rd( void )
151
{
152
  // read by sending 0xff (a dontcare?)
153
  return ow_byte_wr( 0xFF );
154
}
155
 
156
 
157
uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
158
{
159
    uint8_t i, j, next_diff;
160
    uint8_t b;
161
 
162
    if( ow_reset() ) return OW_PRESENCE_ERR;    // error, no device found
163
 
164
    ow_byte_wr( OW_SEARCH_ROM );            // ROM search command
165
    next_diff = OW_LAST_DEVICE;         // unchanged on last device
166
 
167
    i = OW_ROMCODE_SIZE * 8;                    // 8 bytes
168
 
169
    do {
170
        j = 8;                  // 8 bits
171
        do {
172
            b = ow_bit_io( 1 );         // read bit
173
            if( ow_bit_io( 1 ) ) {          // read complement bit
174
                if( b )                 // 11
175
                return OW_DATA_ERR;         // data error
176
            }
177
            else {
178
                if( !b ) {              // 00 = 2 devices
179
                    if( diff > i || ((*id & 1) && diff != i) ) {
180
                    b = 1;              // now 1
181
                    next_diff = i;          // next pass 0
182
                    }
183
                }
184
            }
185
            ow_bit_io( b );                 // write bit
186
            *id >>= 1;
187
            if( b ) *id |= 0x80;            // store bit
188
 
189
            i--;
190
 
191
        } while( --j );
192
 
193
        id++;                   // next byte
194
 
195
    } while( i );
196
 
197
    return next_diff;               // to continue search
198
}
199
 
200
 
201
void ow_command( uint8_t command, uint8_t *id )
202
{
203
    uint8_t i;
204
 
205
    ow_reset();
206
 
207
    if( id ) {
208
        ow_byte_wr( OW_MATCH_ROM );         // to a single device
209
        i = OW_ROMCODE_SIZE;
210
        do {
211
            ow_byte_wr( *id );
212
            id++;
213
        } while( --i );
214
    }
215
    else {
216
        ow_byte_wr( OW_SKIP_ROM );          // to all devices
217
    }
218
 
219
    ow_byte_wr( command );
220
}