1 //---------------------------------------------------------------------------
2 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Except as contained in this notice, the name of Dallas Semiconductor
23 // shall not be used except as stated in the Dallas Semiconductor
24 // Branding Policy.
25 //---------------------------------------------------------------------------
26 //
27 // DS520LNK.C - Link Layer functions required by general 1-Wire drive
28 // implementation for DS80C520 microcontroller.
29 //
30 // Version: 2.00
31 //
32 // History: 1.00 -> 1.01 Added function msDelay.
33 // 1.02 -> 1.03 Added function msGettick.
34 // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for
35 // multiple ports.
36 // 2.10 -> 3.00 Added owReadBitPower and owWriteBytePower
37 //
38
39 // -- Keil c51 control directives
40 // Using inline assembly means we have to dump the output of the entire file to
41 // an intermediate assembly assembly source file, then assemble that file so
42 // we can have our object for linking.
43 #pragma SRC(ds520lnk.a51)
44 // -- End directives
45
46 #include "ownet.h"
47 #include <ds8xc520.h>
48 #include <intrins.h>
49
50 // Port for 1Wire communication. Defaults here, but defined in Makefile also
51 // WARNING: See appnote ??? to select an appropriate port pin and
52 // allow for appropriate protection of the pin.
53 // If this is changed, also change in session file
54 #ifndef OW_PORT
55 #define OW_PORT P3_4
56 #endif
57
58 // exportable link-level functions
59 SMALLINT owTouchReset(int);
60 SMALLINT owTouchBit(int,SMALLINT);
61 SMALLINT owTouchByte(int,SMALLINT);
62 SMALLINT owWriteByte(int,SMALLINT);
63 SMALLINT owReadByte(int);
64 SMALLINT owSpeed(int,SMALLINT);
65 SMALLINT owLevel(int,SMALLINT);
66 SMALLINT owProgramPulse(int);
67 void msDelay(unsigned int);
68 void usDelay(unsigned int);
69 long msGettick(void);
70 SMALLINT owWriteBytePower(int,SMALLINT);
71 SMALLINT owReadBitPower(int,SMALLINT);
72 SMALLINT hasPowerDelivery(int);
73 SMALLINT hasOverDrive(int);
74 SMALLINT hasProgramPulse(int);
75
76 static SMALLINT USpeed; // current 1-Wire Net communication speed
77 static SMALLINT ULevel; // current 1-Wire Net level
78
79 //--------------------------------------------------------------------------
80 // Reset all of the devices on the 1-Wire Net and return the result.
81 //
82 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
83 // indicate the symbolic port number.
84 //
85 // Returns: TRUE(1): presense pulse(s) detected, device(s) reset
86 // FALSE(0): no presense pulses detected
87 //
owTouchReset(int portnum)88 SMALLINT owTouchReset(int portnum)
89 {
90 uchar result;
91 portnum = 0;
92
93 // Code from appnote 126.
94 OW_PORT = 0; // drive bus low.
95 usDelay(500); // 500-(3% error) ~= 480 us
96 OW_PORT = 1; // bus high.
97 usDelay(125); // 125-(3% error) ~= 120 us
98 result = !OW_PORT; // get presence detect pulse.
99 usDelay(372); // 372-(3% error) ~= 360 us
100
101 return result;
102 }
103
104 //--------------------------------------------------------------------------
105 // Send 1 bit of communication to the 1-Wire Net and return the
106 // result 1 bit read from the 1-Wire Net. The parameter 'sendbit'
107 // least significant bit is used and the least significant bit
108 // of the result is the return bit.
109 //
110 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
111 // indicate the symbolic port number.
112 // 'sendbit' - the least significant bit is the bit to send
113 //
114 // Returns: 0: 0 bit read from sendbit
115 // 1: 1 bit read from sendbit
116 //
owTouchBit(int portnum,SMALLINT sendbit)117 SMALLINT owTouchBit(int portnum, SMALLINT sendbit)
118 {
119 unsigned char result;
120 portnum = 0;
121
122
123 //timing critical, so I'll disable interrupts here
124 //EA = 0;
125
126 // start timeslot.
127 OW_PORT = 0;
128 usDelay(5);
129
130 // send bit out.
131 OW_PORT = sendbit;
132 usDelay(10);
133
134 // sample result @ 15 us.
135 result = OW_PORT;
136
137 usDelay(60);
138
139 // timeslot done.
140 OW_PORT = 1;
141 usDelay(5);
142
143 //restore interrupts
144 //EA = 1;
145
146 return result;
147 }
148
149 //--------------------------------------------------------------------------
150 // Send 8 bits of communication to the 1-Wire Net and return the
151 // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte'
152 // least significant 8 bits are used and the least significant 8 bits
153 // of the result is the return byte.
154 //
155 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
156 // indicate the symbolic port number.
157 // 'sendbyte' - 8 bits to send (least significant byte)
158 //
159 // Returns: 8 bits read from sendbyte
160 //
owTouchByte(int portnum,SMALLINT sendbyte)161 SMALLINT owTouchByte(int portnum, SMALLINT sendbyte)
162 {
163 uchar i;
164 uchar result = 0;
165 portnum = 0;
166
167 for (i = 0; i < 8; i++)
168 {
169 result |= (owTouchBit(portnum,sendbyte & 1) << i);
170 sendbyte >>= 1;
171 }
172
173 return result;
174 }
175
176 //--------------------------------------------------------------------------
177 // Send 8 bits of communication to the 1-Wire Net and verify that the
178 // 8 bits read from the 1-Wire Net is the same (write operation).
179 // The parameter 'sendbyte' least significant 8 bits are used.
180 //
181 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
182 // indicate the symbolic port number.
183 // 'sendbyte' - 8 bits to send (least significant byte)
184 //
185 // Returns: TRUE: bytes written and echo was the same
186 // FALSE: echo was not the same
187 //
owWriteByte(int portnum,SMALLINT sendbyte)188 SMALLINT owWriteByte(int portnum, SMALLINT sendbyte)
189 {
190 return (owTouchByte(portnum,sendbyte) == sendbyte) ? TRUE : FALSE;
191 }
192
193 //--------------------------------------------------------------------------
194 // Send 8 bits of read communication to the 1-Wire Net and and return the
195 // result 8 bits read from the 1-Wire Net.
196 //
197 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
198 // indicate the symbolic port number.
199 //
200 // Returns: 8 bytes read from 1-Wire Net
201 //
owReadByte(int portnum)202 SMALLINT owReadByte(int portnum)
203 {
204 return owTouchByte(portnum,0xFF);
205 }
206
207 //--------------------------------------------------------------------------
208 // Set the 1-Wire Net communucation speed.
209 //
210 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
211 // indicate the symbolic port number.
212 // 'new_speed' - new speed defined as
213 // MODE_NORMAL 0x00
214 // MODE_OVERDRIVE 0x01
215 //
216 // Returns: current 1-Wire Net speed
217 //
owSpeed(int portnum,SMALLINT new_speed)218 SMALLINT owSpeed(int portnum, SMALLINT new_speed)
219 {
220 portnum = 0;
221
222 USpeed = new_speed;
223 // not supported yet
224
225 // TODO: Research overdrive. 33mhz should handle it.
226
227 return 0;
228 }
229
230 //--------------------------------------------------------------------------
231 // Set the 1-Wire Net line level. The values for NewLevel are
232 // as follows:
233 //
234 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
235 // indicate the symbolic port number.
236 // 'new_level' - new level defined as
237 // MODE_NORMAL 0x00
238 // MODE_STRONG5 0x02
239 // MODE_PROGRAM 0x04
240 // MODE_BREAK 0x08
241 //
242 // Returns: current 1-Wire Net level
243 //
244 // Note: Strong and Program not supported on 520 target.
owLevel(int portnum,SMALLINT new_level)245 SMALLINT owLevel(int portnum, SMALLINT new_level)
246 {
247 portnum = 0;
248 switch(new_level)
249 {
250 case MODE_BREAK:
251 OW_PORT = 0; //send a break on one-wire port
252 break;
253 default:
254 case MODE_NORMAL:
255 OW_PORT = 1;
256 break;
257 }
258 ULevel = new_level;
259 return new_level;
260 }
261
262 //--------------------------------------------------------------------------
263 // This procedure creates a fixed 480 microseconds 12 volt pulse
264 // on the 1-Wire Net for programming EPROM iButtons.
265 //
266 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
267 // indicate the symbolic port number.
268 //
269 // Returns: TRUE successful
270 // FALSE program voltage not available
271 //
owProgramPulse(int portnum)272 SMALLINT owProgramPulse(int portnum)
273 {
274 portnum = 0;
275 // Not supported
276 return 0;
277 }
278
279 //--------------------------------------------------------------------------
280 // Description:
281 // Delay for at least 'len' ms
282 //
msDelay(unsigned int delay)283 void msDelay(unsigned int delay)
284 {
285 while(delay--)
286 {
287 usDelay(1030); // -3% error puts us right at 1ms.
288 }
289 }
290
291 //--------------------------------------------------------------------------
292 // Description:
293 // Delay for at least 'len' microseconds
294 //
295 // Adapted from Kevin Vigor's TINI 1Wire code.
296 //
297 // Works only @33Mhz. We need 8.25 machine cycles per iteration to get the microsecond
298 // delay. Can't have .25 of a cycle, so this function uses 8 cycles per iteration. This
299 // produces an error of 3% ( .03 = (8.25-8)/8 ). Most of the use of this function by
300 // 1-Wire routines calls for delays under 50 microseconds, in which case it is under by
301 // less than 1.5 microseconds. It is assumed the overhead of calling the function will
302 // add enough to account for the difference. For values much greater than 50 (only in
303 // reset function), a "fudge factor" is added to account for any error.
304 //
305 //
usDelay(unsigned int delay)306 void usDelay(unsigned int delay)
307 {
308 #pragma asm
309 ; delay is in r6/r7
310 ; double-check in output assembly
311 mov a, r7
312 orl a, r6 ; quick out for zero case.
313 jz _usDelayDone
314
315 inc r6
316 cjne r7, #0, _usDelayLoop
317 dec r6
318
319 _usDelayLoop:
320 nop
321 nop
322 nop
323 nop
324 nop
325 djnz r7, _usDelayLoop
326 djnz r6, _usDelayLoop
327 _usDelayDone:
328
329 #pragma endasm
330 delay = 0;
331 }
332
333 //--------------------------------------------------------------------------
334 // Get the current millisecond tick count. Does not have to represent
335 // an actual time, it just needs to be an incrementing timer.
336 //
msGettick(void)337 long msGettick(void)
338 {
339 // not supported yet
340 return 0;
341 }
342
343 //--------------------------------------------------------------------------
344 // Send 8 bits of communication to the 1-Wire Net and verify that the
345 // 8 bits read from the 1-Wire Net is the same (write operation).
346 // The parameter 'sendbyte' least significant 8 bits are used. After the
347 // 8 bits are sent change the level of the 1-Wire net.
348 //
349 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
350 // OpenCOM to indicate the port number.
351 // 'sendbyte' - 8 bits to send (least significant byte)
352 //
353 // Returns: TRUE: bytes written and echo was the same
354 // FALSE: echo was not the same
355 //
owWriteBytePower(int portnum,SMALLINT sendbyte)356 SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte)
357 {
358 // not supported on the by the DS520
359 return FALSE;
360 }
361
362 //--------------------------------------------------------------------------
363 // Send 1 bit of communication to the 1-Wire Net and verify that the
364 // response matches the 'applyPowerResponse' bit and apply power delivery
365 // to the 1-Wire net. Note that some implementations may apply the power
366 // first and then turn it off if the response is incorrect.
367 //
368 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
369 // OpenCOM to indicate the port number.
370 // 'applyPowerResponse' - 1 bit response to check, if correct then start
371 // power delivery
372 //
373 // Returns: TRUE: bit written and response correct, strong pullup now on
374 // FALSE: response incorrect
375 //
owReadBitPower(int portnum,SMALLINT applyPowerResponse)376 SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse)
377 {
378 // not supported on the by the DS520
379 return FALSE;
380 }
381
382 //--------------------------------------------------------------------------
383 // This procedure indicates wether the adapter can deliver power.
384 //
385 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
386 // OpenCOM to indicate the port number.
387 //
388 // Returns: TRUE if adapter is capable of delivering power.
389 //
owHasPowerDelivery(int portnum)390 SMALLINT owHasPowerDelivery(int portnum)
391 {
392 // add adapter specific code here
393 return TRUE;
394 }
395
396 //--------------------------------------------------------------------------
397 // This procedure indicates wether the adapter can deliver power.
398 //
399 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
400 // OpenCOM to indicate the port number.
401 //
402 // Returns: TRUE if adapter is capable of over drive.
403 //
owHasOverDrive(int portnum)404 SMALLINT owHasOverDrive(int portnum)
405 {
406 // add adapter specific code here
407 return TRUE;
408 }
409 //--------------------------------------------------------------------------
410 // This procedure creates a fixed 480 microseconds 12 volt pulse
411 // on the 1-Wire Net for programming EPROM iButtons.
412 //
413 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
414 // OpenCOM to indicate the port number.
415 //
416 // Returns: TRUE program volatage available
417 // FALSE program voltage not available
owHasProgramPulse(int portnum)418 SMALLINT owHasProgramPulse(int portnum)
419 {
420 // add adapter specific code here
421 return TRUE;
422 }