summaryrefslogtreecommitdiffhomepage
path: root/digital/zigbit/bitcloud/stack/Components/HAL/avr/atmega1281/zigBit/src/halAtmelUid.c
blob: 9c80dcbef52a0e3e3f37f03ca09176c8fde463e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/**************************************************************************//**
  \file  halAtmelUid.c

  \brief The header file describes the UID interface for Atmel MeshBean.

  \author
    Atmel Corporation: http://www.atmel.com \n
    Support email: avr@atmel.com

  Copyright (c) 2008-2011, Atmel Corporation. All rights reserved.
  Licensed under Atmel's Limited License Agreement (BitCloudTM).

  \internal
  History:
    10/12/10 A. Malkin - Created
 ******************************************************************************/
/******************************************************************************
 *   WARNING: CHANGING THIS FILE MAY AFFECT CORE FUNCTIONALITY OF THE STACK.  *
 *   EXPERT USERS SHOULD PROCEED WITH CAUTION.                                *
 ******************************************************************************/

/******************************************************************************
                   Includes section
******************************************************************************/
#include <halAtmelUid.h>
#include <halW1.h>

/******************************************************************************
                   Define(s) section
******************************************************************************/
#define UID_LEN  0x08  // size of UID (bytes)

#define SINGLE_WIRE_ZERO_BIT  0x00  // logical level zero
#define SINGLE_WIRE_ONE_BIT   0x01  // logical level one

#define BIT_DURATION  208                 // bit duration - 208 us
#define BIT_DURATION_HALF BIT_DURATION/2
#define MAX_START_BIT_WAITING     10      // waiting time(in bit) of Start bit

// Commands for Single-wire UART (Atmel MeshBean)
#define CMD_SYNCH         0xAA  // Synchronization
#define CMD_READ_MAC64_0  0x60  // Read 64-bit MAC address
#define NUM_OF_MAC64      0x00  // Number of MAC64 slot
/******************************************************************************
                   Prototypes section
******************************************************************************/
static void halWriteSingleWireBit(uint8_t value);
static void halWriteSingleWire(uint8_t value);
static int halWaitSingleWireStartBit(void);
static uint8_t halReadSingleWireBit(void);
static int halReadSingleWire(uint8_t *data);

/******************************************************************************
                   Global variables section
******************************************************************************/

/******************************************************************************
                   Implementations section
******************************************************************************/
/***************************************************************************//**
\brief Writes bit to the bus

\param[in]
    value - byte to write. The bit is placed to position of LSB.
*******************************************************************************/
static void halWriteSingleWireBit(uint8_t value)
{
  if (value)
    GPIO_SINGLE_WIRE_set();
  else
    GPIO_SINGLE_WIRE_clr();

  __delay_us(BIT_DURATION);
}

/***************************************************************************//**
\brief Writes byte to the bus

\param[in]
    value - byte to write.
*******************************************************************************/
static void halWriteSingleWire(uint8_t value)
{
  uint8_t i;

  // write Start bit
  halWriteSingleWireBit(SINGLE_WIRE_ZERO_BIT);

  // write Data
  for (i = 0; i < UID_LEN; i++)
  {
    halWriteSingleWireBit(value & 0x01);
    value >>= 1;
  }

  // add 2 Stop bits
  halWriteSingleWireBit(SINGLE_WIRE_ONE_BIT);
  halWriteSingleWireBit(SINGLE_WIRE_ONE_BIT);
}

/***************************************************************************//**
\brief Wait for Start bit from the bus.

\return
   SINGLE_WIRE_SUCCESS_STATUS - if Start bit has been found successfully; \n
   SINGLE_WIRE_ERROR_STATUS - if Start bit has been not found.
*******************************************************************************/
static int halWaitSingleWireStartBit(void)
{
  uint16_t i;

  for (i = BIT_DURATION * MAX_START_BIT_WAITING; i > 0; i--)
  {
    if (!GPIO_SINGLE_WIRE_read())
      return SINGLE_WIRE_SUCCESS_STATUS;
    __delay_us(1);
  }

  return SINGLE_WIRE_ERROR_STATUS;
}

/***************************************************************************//**
\brief Reads bit from the bus.

\return
  Read bit is placed to position of last significant bit.
*******************************************************************************/
static uint8_t halReadSingleWireBit(void)
{
  uint8_t result;

  // read pin level in half of bit period
  if (GPIO_SINGLE_WIRE_read())
    result = SINGLE_WIRE_ONE_BIT;
  else
    result = SINGLE_WIRE_ZERO_BIT;

  // wait for bit period before next bit reading
  __delay_us(BIT_DURATION);

  return result;
}

/***************************************************************************//**
\brief Reads byte from the Atmel Single-wire bus.

\param[in]
    data - byte read from the bus.

\return
    SINGLE_WIRE_SUCCESS_STATUS - if byte read without error;
    SINGLE_WIRE_ERROR_STATUS - if there are some errors during byte read.
*******************************************************************************/
static int halReadSingleWire(uint8_t *data)
{
  uint8_t reg = 0;
  uint8_t bit;
  uint8_t i;
  int result;

  // wait for Start bit of response
  result = halWaitSingleWireStartBit();

  if (result)
    return SINGLE_WIRE_ERROR_STATUS;

  // wait for half of bit period before reading Start bit
  __delay_us(BIT_DURATION_HALF);

  // read Start bit
  bit = halReadSingleWireBit();
  if (SINGLE_WIRE_ZERO_BIT != bit)
    return SINGLE_WIRE_ERROR_STATUS;

  // read byte
  for (i = 0; i < UID_LEN; i++)
  {
    if (SINGLE_WIRE_ONE_BIT == halReadSingleWireBit())
      reg |= (1 << i);
  }

  // read and check 1'st Stop bit
  bit = halReadSingleWireBit();
  if (SINGLE_WIRE_ONE_BIT != bit)
    return SINGLE_WIRE_ERROR_STATUS;

  // wait for bit period after reading
  __delay_us(BIT_DURATION_HALF);

  *data = reg;

   return SINGLE_WIRE_SUCCESS_STATUS;
}

/**************************************************************************//**
\brief Reads Atmel MeshBean UID from ATTiny13A

\param[in] uidBuffer - memory for unique ID.

\return
    SINGLE_WIRE_SUCCESS_STATUS - if UID read successfully;
    SINGLE_WIRE_ERROR_STATUS - if error occured during UID read.
******************************************************************************/
int halReadAtmelMeshbeanUid(uint8_t *uidBuffer)
{
  uint8_t i;
  uint8_t reg = 0;

  // port sets as output.
  GPIO_SINGLE_WIRE_make_out();

  // send synchronization byte
  halWriteSingleWire(CMD_SYNCH);

  // write command
  halWriteSingleWire(CMD_READ_MAC64_0);

  // write UID location
  halWriteSingleWire(NUM_OF_MAC64);

  // Tri-state (external pullup)
  GPIO_SINGLE_WIRE_make_in();

  // wait for synchronization
  if (halReadSingleWire(&reg))
    return SINGLE_WIRE_ERROR_STATUS;

  if (CMD_SYNCH != reg)
    return SINGLE_WIRE_ERROR_STATUS;

  // wait for response with same command ID
  if (halReadSingleWire(&reg))
    return SINGLE_WIRE_ERROR_STATUS;

  if (CMD_READ_MAC64_0 == reg)
  {
    // wait for 8 bytes of UID
    for (i = UID_LEN; i > 0; i--)
    {
      // fill array in reversionary order
      if (halReadSingleWire(uidBuffer + i - 1))
        return SINGLE_WIRE_ERROR_STATUS;
    }
  }
  return SINGLE_WIRE_SUCCESS_STATUS;
}

// eof halAtmelUid.c