Contiki 2.5
ds2401.c
1 /*
2  * Copyright (c) 2009, University of Colombo School of Computing
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /*
34  * Device driver for the Dallas Semiconductor DS2401 chip. Heavily
35  * based on the application note 126 "1-Wire Communications Through
36  * Software".
37  *
38  * http://www.maxim-ic.com/appnotes.cfm/appnote_number/126
39  */
40 
41 /*
42  * For now we stuff in Crossbow Technology, Inc's unique OUI.
43  * 00:1A:4C Crossbow Technology, Inc
44  *
45  * The EUI-64 is a concatenation of the 24-bit OUI value assigned by
46  * the IEEE Registration Authority and a 40-bit extension identifier
47  * assigned by the organization with that OUI assignment.
48  */
49 
50 #include <avr/io.h>
51 #include <string.h>
52 #include "contiki.h"
53 
54 #include "ds2401.h"
55 
56 unsigned char ds2401_id[8];
57 
58 /* 1-wire is at PortA.4 */
59 #define SERIAL_ID_PIN_READ PINA
60 #define SERIAL_ID_PIN_MASK _BV(4)
61 #define SERIAL_ID_PxOUT PORTA
62 #define SERIAL_ID_PxDIR DDRA
63 
64 #define SET_PIN_INPUT() (SERIAL_ID_PxDIR &= ~SERIAL_ID_PIN_MASK)
65 #define SET_PIN_OUTPUT() (SERIAL_ID_PxDIR |= SERIAL_ID_PIN_MASK)
66 
67 #define OUTP_0() (SERIAL_ID_PxOUT &= ~SERIAL_ID_PIN_MASK)
68 #define OUTP_1() (SERIAL_ID_PxOUT |= SERIAL_ID_PIN_MASK)
69 
70 #define PIN_INIT() do{ \
71  SET_PIN_INPUT(); \
72  OUTP_0(); \
73  } while(0)
74 
75 
76 /* Drive the one wire interface low */
77 #define OW_DRIVE() do { \
78  SET_PIN_OUTPUT(); \
79  OUTP_0(); \
80  } while (0)
81 
82 /* Release the one wire by turning on the internal pull-up. */
83 #define OW_RELEASE() do { \
84  SET_PIN_INPUT(); \
85  OUTP_1(); \
86  } while (0)
87 
88 /* Read one bit. */
89 #define INP() (SERIAL_ID_PIN_READ & SERIAL_ID_PIN_MASK)
90 
91 /*
92  * Delay times in us.
93  */
94 #define tA 6 /* min-5, recommended-6, max-15 */
95 #define tB 64 /* min-59, recommended-64, max-N/A */
96 #define tC 60 /* min-60, recommended-60, max-120 */
97 #define tD 10 /* min-5.3, recommended-10, max-N/A */
98 #define tE 9 /* min-0.3, recommended-9, max-9.3 */
99 #define tF 55 /* min-50, recommended-55, max-N/A */
100 #define tG 0 /* min-0, recommended-0, max-0 */
101 #define tH 480 /* min-480, recommended-480, max-640 */
102 #define tI 70 /* min-60.3, recommended-70, max-75.3 */
103 #define tJ 410 /* min-410, recommended-410, max-N/A */
104 /*---------------------------------------------------------------------------*/
105 /*
106  * The delay caused by calling the delay_loop is given by the following
107  * formula.
108  * delay(us) = (4n + 1)/XTAL
109  * where n is the number of iterations and XTAL is the clock frequency(in MHz).
110  * TODO: Moving the delay_loop to dev/clock.c
111  */
112 static void
113 delay_loop(uint16_t __count)
114 {
115  asm volatile ("1: sbiw %0,1" "\n\t"
116  "brne 1b"
117  : "=w" (__count)
118  : "0" (__count)
119  );
120 }
121 /*---------------------------------------------------------------------------*/
122 /*
123  * This macro relies on the compiler doing the arithmetic during compile time
124  * for the needed iterations.!!
125  * In MICAz, XTAL = 7.3728 MHz
126  */
127 #define udelay(u) delay_loop(((7.3728F * u)-1)/4)
128 /*---------------------------------------------------------------------------*/
129 static uint8_t
130 reset(void)
131 {
132  uint8_t result;
133  OW_DRIVE();
134  udelay(500); /* 480 < tH < 640 */
135  OW_RELEASE(); /* Releases the bus */
136  udelay(tI);
137  result = INP();
138  udelay(tJ);
139  return result;
140 }
141 /*---------------------------------------------------------------------------*/
142 static void
143 write_byte(uint8_t byte)
144 {
145  uint8_t i = 7;
146  do {
147  if (byte & 0x01) {
148  OW_DRIVE();
149  udelay(tA);
150  OW_RELEASE(); /* Releases the bus */
151  udelay(tB);
152  } else {
153  OW_DRIVE();
154  udelay(tC);
155  OW_RELEASE(); /* Releases the bus */
156  udelay(tD);
157  }
158  if (i == 0)
159  return;
160  i--;
161  byte >>= 1;
162  } while (1);
163 }
164 /*---------------------------------------------------------------------------*/
165 static unsigned
166 read_byte(void)
167 {
168  unsigned result = 0;
169  int i = 7;
170  do {
171  OW_DRIVE();
172  udelay(tA);
173  OW_RELEASE(); /* Releases the bus */
174  udelay(tE);
175  if (INP())
176  result |= 0x80; /* LSbit first */
177  udelay(tF);
178  if (i == 0)
179  return result;
180  i--;
181  result >>= 1;
182  } while (1);
183 }
184 /*---------------------------------------------------------------------------*/
185 /* Polynomial ^8 + ^5 + ^4 + 1 */
186 static unsigned
187 crc8_add(unsigned acc, unsigned byte)
188 {
189  int i;
190  acc ^= byte;
191  for (i = 0; i < 8; i++)
192  if (acc & 1)
193  acc = (acc >> 1) ^ 0x8c;
194  else
195  acc >>= 1;
196 
197  return acc;
198 }
199 /*---------------------------------------------------------------------------*/
200 int
201 ds2401_init()
202 {
203  int i;
204  uint8_t volatile sreg;
205  unsigned family, crc, acc;
206 
207  PIN_INIT();
208 
209  sreg = SREG; /* Save status register before disabling interrupts. */
210  cli(); /* Disable interrupts. */
211 
212  if (reset() == 0) {
213  write_byte(0x33); /* Read ROM command. */
214  family = read_byte();
215  for (i = 7; i >= 2; i--) {
216  ds2401_id[i] = read_byte();
217  }
218  crc = read_byte();
219 
220  SREG = sreg; /* Enable interrupts. */
221 
222  if(family != 0x01) {
223  goto fail;
224  }
225  acc = crc8_add(0x0, family);
226  for (i = 7; i >= 2; i--) {
227  acc = crc8_add(acc, ds2401_id[i]);
228  }
229  if (acc == crc) {
230  /* 00:1A:4C OUI for Crossbow Technology, Inc. */
231  ds2401_id[0] = 0x00;
232  ds2401_id[1] = 0x1A;
233  ds2401_id[2] = 0x4C;
234  return 1; /* Success! */
235  }
236  } else {
237  SREG = sreg; /* Enable interrupts. */
238  }
239 
240 fail:
241  memset(ds2401_id, 0x0, sizeof(ds2401_id));
242  return 0; /* Fail! */
243 }
244 /*---------------------------------------------------------------------------*/