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 }