-
Notifications
You must be signed in to change notification settings - Fork 1
/
ds-rom.asm
412 lines (395 loc) · 13.6 KB
/
ds-rom.asm
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
;========================================================================
; WORKS! 12/3/08
;========================================================================
; -----------------------------------------------------------------------
; Template source file generated by piklab
#include <p16f84.inc>
; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
__CONFIG _HS_OSC & _WDT_ON & _PWRTE_ON & _CP_OFF
; -----------------------------------------------------------------------
;EEPROM data is the ROM codes transmitted by the DS1820s. It must be
;stored in the order it was transmitted, and must include the checksum.
EEPROM ORG 0x2100
DE 0x10, 0x9C, 0x05, 0x4D, 0x00, 0x00, 0x00, 0x98
DE 0x10, 0x9D, 0x52, 0x4D, 0x00, 0x00, 0x00, 0x6B
DE 0x10, 0xA1, 0x0B, 0x4D, 0x00, 0x00, 0x00, 0x9D
DE 0x10, 0xF9, 0x45, 0x4D, 0x00, 0x00, 0x00, 0x59
; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA 0x0C
w_saved RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
dvar RES 1 ; used by dswait (and delay)
dvar2 RES 1 ; used by longdelay
temp RES 1 ; general purpose variable, value must not matter across CALLs except delay calls
count1 RES 1 ; used by serhex
count2 RES 1 ; used by serbyte
centigrade RES 1 ;
cremain RES 1 ;
cperc RES 1 ;
ctemp RES 1 ;
ds_r RES 1 ;
; -----------------------------------------------------------------------
;Symbols
;internal (not IO)
RP0 equ 5
;external (IO)
serport equ PORTB
serpin equ 2
dsport equ PORTB
dspin equ 1
dstris equ TRISB
; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
nop ; needed for ICD2 debugging
movlw high start ; load upper byte of 'start' label
movwf PCLATH ; initialize PCLATH
goto start ; go to start of main code
; interrupt vector
INT_VECTOR CODE 0x004
goto interrupt ; go to start of interrupt code
; relocatable code
PROG CODE
interrupt
movwf w_saved ; save context
swapf STATUS,w
movwf status_saved
; << insert interrupt code >>
swapf status_saved,w ; restore context
movwf STATUS
swapf w_saved,f
swapf w_saved,w
retfie
;================================================================================
start ;configure stuff
bsf STATUS,RP0 ;bank select
movlw 0x01 ;portb
movwf TRISB
movlw 0x1D ;11101 - was 0x11 - porta
movwf TRISA
bcf serport,serpin ;out
bsf dsport,dspin ;in/open drain
bcf STATUS,RP0
bcf dsport,dspin
clrf EEADR ;reset to zero
;================================================================================
main ;movf EEADR,w
call initmp ;initialize DS1820
btfsc ctemp,dspin ;is ds present?
goto present
movlw 'X'
call serbyte
goto stop
present call skipandconvert ;skip rom, begin temp conversion
movlw .50
call longdelay ;delay is in hundredths of a second
;-------------------- no address
; movlw 'N'
; call serbyte
; movlw 'A'
; call serbyte
; call initmp
; movlw 0xCC ;skip rom code
; movwf ctemp
; call wbyte
; call readtemp
; call xmit3 ;transmit 3 bytes
;-------------------- with address from eeprom
nextds movlw 0x0D
call serbyte
movlw 0x0A
call serbyte
call initmp
movlw EEADR
movwf FSR
call serhex
call matchrom
call readtemp
call xmit3 ;transmit 3 bytes
movlw 0x20
subwf EEADR,w
btfss STATUS,Z
goto nextds
clrf EEADR
goto main
stop sleep
goto stop ; loop forever
;================================================================================
;transmit 3 bytes as hex: centigrade,cremain,cperc
xmit3 movlw centigrade
movwf FSR
call serhex
movlw cremain
movwf FSR
call serhex
movlw cperc
movwf FSR
call serhex
goto done
;================================================================================
;skip rom, convert temp
skipandconvert movlw 0xCC ;skip rom code
movwf ctemp
call wbyte
movlw 0x44 ;begin conversion code
movwf ctemp
call wbyte
;need to delay .5s before reading temp
;but for flexibility, that is not done here
goto done
;================================================================================
;read temp into four vars
;save first two bytes, skip four, save next two
;returns 3 bytes
;uses ctemp,centigrade,temp,cremain,cperc
readtemp movlw 0xBE ;read scratchpad cmd
movwf ctemp
call wbyte
call rbyte
movf ctemp,w
movwf centigrade ;LSB
call rbyte
movf ctemp,w
movwf temp ;MSB (sign)
call rbyte ;skip
call rbyte ;skip
call rbyte ;skip
call rbyte ;skip
call rbyte
movf ctemp,w
movwf cremain ;count remain
call rbyte
movf ctemp,w
movwf cperc ;count per c
bsf STATUS,0
btfss temp,0 ;make carry match sign byte
bcf STATUS,0
rrf centigrade,f ;get rid of LSb (.5 degree)
;and put sign bit in MSb.
goto done
;================================================================================
;select a DS1820 using its ROM code
;reads rom code from EEPROM, starting with address in EEADR
;uses FSR/INDF,count1
;if codes are packed in rom, EEADR will point to next code when this returns
;uses count1
matchrom movlw 8
movwf count1 ;loop counter
movlw 0x55 ;match rom command
movwf ctemp
call wbyte
nexteebyte movlw EECON1 ;EECON1 address
movwf FSR ;to FSR
bsf INDF,0 ;EECON1 bit 0 is read EEPROM signal
movf EEDATA,w
movwf ctemp
call wbyte
incf EEADR,f
decfsz count1,f ;loop test
goto nexteebyte
goto done ;clean up
;================================================================================
;take byte in indf, convert to two ascii hex chars (0-F)
;then transmit it via serial
;uses count1, temp
serhex clrf count1 ;counter for hex decode
nibb swapf INDF,f ;swap nibbles; start with high nibble
movlw 0x09 ;use to check whether numeric (0-9) or alpha (A-F) below
movwf temp
movlw 0x0F ;00001111
andwf INDF,w ;and with the byte
subwf temp,f ;put result in temp - w is not disturbed
btfss STATUS,0 ;if carry is clear, this nibble >9, so use additional offset
addlw 0x07 ;extra offset for ascii A-F (0x41 - 0x0A = 0x37)
addlw 0x30 ;offset for ascii 0-9
call serbyte ;serial out for byte in w
btfsc count1,0 ;don't return unless we have done both nibbles
goto done ;clean up
incf count1,f ;low nibble flag
goto nibb ;do low nibble
;================================================================================
;serial transmit one byte (W) @ 4800 8N1, pin serpin@serport
;uses count2, temp
serbyte clrf count2 ; put count2 to zero
bcf serport,serpin ;start bit
nop
nop
nop
nop
nop ;several nops to meet timing
movwf temp
newbit call delay ;go to delay
btfsc temp,0 ;is bit 0 = 0 on variable memory address?
goto one ;no, is 1
zero bcf serport,serpin ;yes, send a 0
rrf temp,f ;move all bits down one place
incf count2,f ;count2=count2+1
btfss count2, 3 ;is it 8?
goto newbit ;no, go and find a new bit
goto stopbit ;yes, go and send stop bit
one bsf serport,serpin ;send a 1
rrf temp,f ;move all bits down one place
incf count2,f ;count2=count2+1
btfss count2, 3 ;is it 8?
goto newbit ;no, go and find a new bit
stopbit call delay ;delay
bsf serport,serpin ;send a 1
call delay ;delays between bytes
call delay ;
goto done ;clean up
;================================================================================
;delay in hundredths of a second
;A delay of 0x32 is actually 500008 us.
;A delay of 0x19 is actually 250008 us.
;uses dvar2
;Without NOP, 0x32 is 42 us short.
longdelay movwf dvar2 ;counter for outer loop
ldouter movlw 0x0C ;counter for inner loop
movwf temp
ldinner movlw 0xff
call DSWAIT
decfsz temp,f
goto ldinner ;end of inner loop - 9275us in this loop
movlw 0xee
clrwdt ;was a nop
call DSWAIT
decfsz dvar2,f
goto ldouter
goto done
;for dswait, 165=499us; 255=769us
;12x with 255, then another 760us delay (for 10ms) (w=251 -> 757us)
;================================================================================
delay movlw 0x40 ;fall through
;================================================================================
DSWAIT ;wait - number of reps in W
;use: W and dvar
;timing: 7Tcy + 3*(W-1)Tcy counting the call & return
;"MOVLW 19" for 61us@4MHz
MOVWF dvar ;move count from W to dvar
DSWT DECFSZ dvar,f ;dvar=dvar-1 - if that's 0 then skip the next opcode
goto DSWT ;loop
return
;================================================================================
;=============================cleanup routine====================================
;================================================================================
done bcf STATUS,RP0 ;reset to bank 0
clrwdt ;reset watchdog timer
return
;================================================================================
;================================================================================
;================================DS stuff========================================
;================================================================================
;================================================================================
DSLOW ;1-wire LOW output - rb1
;what to do: hold low min. 60 us, then make input (high)
movlw dstris ;put 86h in w (the address of dstris)
movwf FSR ;now put that 86h in the FSR
BCF dsport,dspin ;rb1 low
BCF INDF,dspin ;make rb1 output - accessing INDF actually accesses
;the address stored in the FSR - which is 86h, or dstris
MOVLW .19 ;how many times to loop - 61us
call DSWAIT
BSF INDF,dspin ;rb1 input (and high -- due to pullup)
;total of 63us low
goto done
;================================================================================
DSHIGH ;1-wire HIGH output - rb1
;what to do: low 1<t<15us, then high remainder of 60us
movlw dstris ;put 86h in w (the address of dstris)
movwf FSR ;now put that 86h in the FSR
BCF dsport,dspin ;rb1 low
BCF INDF,dspin ;rb1 output
MOVLW 2 ;delay 10us - 11 counting this line
call DSWAIT
BSF INDF,dspin ;rb1 high
MOVLW .16 ;delay value - 52us
call DSWAIT
;leave with output high via pullup
;total 66us
goto done
;================================================================================
DSRD ;create read time slot & read result - rb1
;what to do: low for >1us then read before 15us is up, wait 45us+ more
;uses: dvar2, ctemp (BYTE var that returns BIT value)
movlw dstris ;put 86h in w (the address of dstris)
movwf FSR ;now put that 86h in the FSR
BCF dsport,dspin ;low
BCF INDF,dspin ;output
clrf ctemp ;clear the ctemp byte var in prep for below - putting it here
;makes for faster code (replaces a nop)
nop ;wait
bsf INDF,dspin ;input - pullup
movlw 2 ;10us worth - 14 total to end of dswait from output going low
call DSWAIT
movf PORTB,0 ;15us total
;this copies portb to W
movwf dvar2 ;now "move" it to var dvar2
btfsc dvar2,dspin ;was input low? skip next instruction if is was
incf ctemp,1 ;bit was high, increment ctemp (0+1=1)
movlw .15 ;18us from drop of portb, need 42 more -- 49 will work
call DSWAIT ;wait the remainder of the 60us
goto done
;================================================================================
initmp ;initialize pulse over rb1
;todo:send low >480us, ds waits 15-60us, then it holds low 60-240us
;presence if low after released for 60us; presence signal
;valid for add'l 60us min.
;uses: ctemp - bit 1 - high for presence, low for none
;rest of ctemp is cleared
;166,19-values for dswait - 502,61us
;had to add setting of fsr and use of INDF wherever there was a tris access
;due to TRIS being on the second memory page
;at first, used status-rp0, but this didn't work for unknown reasons.
movlw dstris ;put 86h in w (the address of dstris)
movwf FSR ;now put that 86h in the FSR
bcf dsport,dspin ;low rb1
bcf INDF,dspin ;output rb1
movlw .166 ;set up 502us delay
call DSWAIT
bsf INDF,dspin ;input, high by pullup
movlw .19 ;61us
call DSWAIT
clrf ctemp ;clear the variable
btfss dsport,dspin ;check if temp1 responded (low if present)
bsf ctemp,dspin ;if it did, set corresponding bit in ctemp
;if it isn't responding,
;the bit stays zero (cleared).
movlw .166 ;finish up required wait period
call DSWAIT ;502 us is good enough
goto done
;================================================================================
wbyte ;write a byte to the DS1820 on PortB.1 (rb1)
;uses: ctemp (value to write), count2
bcf STATUS,RP0 ;select page 0
movlw 8 ;loop value, 8 reps
movwf count2 ;put that value in the counter variable
w1loop
btfss ctemp,0 ;skip next if bit 0 is high
call DSLOW ;write a 0 bit
btfsc ctemp,0 ;skip next if bit 0 is low
call DSHIGH ;write a 1 bit
RRF ctemp,1 ;rotate (shift) right
decfsz count2,f ;subtract 1, then check: exit loop if 0
goto w1loop
goto done
;================================================================================
rbyte ;read byte from ds1820 on rb1
;uses: ctemp(temporary & returning value), count2(count),ds_r(temporary value)
;put bit returned from dsrd in MSb, shift down (right)
bcf STATUS,RP0
movlw 8 ;loop value, 8 reps
movwf count2 ;put that value in the counter variable
r1loop
RRF ds_r,1 ;rotate (shift) right
call DSRD ;read bit from rb1, returned as lsb of ctemp
bsf ds_r,7 ;set MSb of ds_r
btfss ctemp,0 ;skip next if set
bcf ds_r,7 ;clear the MSb of ds_r - if returned was low
decfsz count2,1 ;exit loop counter check
goto r1loop
movf ds_r,0 ;copy ds_r to W
movwf ctemp ;copy W to ctemp
goto done
END