summaryrefslogtreecommitdiffstats
path: root/boiler-monster/original-pic-4.2.5/ds1820.asm
blob: b9b06c1aa595d14db51c58eec8b46c94b736d803 (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
		title		"Outside sensor"
		list		p=16F88, b=8, r=dec

#include	"p16f88.inc"
		errorlevel	-302, -306

#define		IOPORT	PORTA,7		;I/O port used for 1-wire line

;1-wire ROM commands
#define		READROM		0x33
#define		SKIPROM		0xCC
;1-wire FUNCTION commands
#define		CONVERTT	0x44
#define		READSCRATCHPAD	0xBE
;1-wire family codes for supported temperature sensors
#define		DS_FAM_DS18S20	0x10
#define		DS_FAM_DS18B20	0x28
;Return codes, controlling when to perform the next step
#define		DONE		0	;Next step after one second
#define		CONTINUE	1	;Next step as soon as possible

		extern	float1, float2, flags, temp, StoreOutTemp

		UDATA
sensorstage	res	1
#define		ds18b20		sensorstage,7
#define		restart		sensorstage,6
lsbstorage	res	1


#define		OutsideTemp	flags,0	;Keep in sync with gateway.asm
#define		OutsideInvalid	flags,1	;Keep in sync with gateway.asm

		global	Temperature
Temperature	CODE
Temperature	skpz			;Zero bit indicates no message in prog
		goto	Restart		;Sequence interrupted by OT message
		btfsc	restart
		clrf	sensorstage
		;Split up the temperature measurement into several short steps,
		;each less than 1ms. That way the main loop is allowed to run
		;frequently enough for it to be able to do all the necessary
		;processing in time, like clearing out the serial receive
		;register.
		movlw	high StageTable
		movwf	PCLATH
		movfw	sensorstage
		andlw	b'11111'
		addlw	low StageTable
		skpnc
		incf	PCLATH,F
		incf	sensorstage,F	;Determine next step of the process
		movwf	PCL		;Jump to the current step
StageTable	goto	PresencePulse	;Step 0 - Transmit a reset pulse
		goto	SkipRom		;Step 1 - Address all devices on the bus
		goto	Measure		;Step 2 - Start a measurement
		retlw	DONE		;Step 3 - Allow time for measurement
		goto	PresencePulse	;Step 4 - Transmit a reset pulse
		goto	ReadRom		;Step 5 - Send Read ROM command
		goto	ReadFamily	;Step 6 - Read device family code
		goto	PresencePulse	;Step 7 - Transmit a reset pulse
		goto	SkipRom		;Step 8 - Address all devices
		goto	ReadCommand	;Step 9 - Send Read Scratchpad command
		goto	ReadLSB		;Step 10 - Read temperature value, LSB
		goto	ReadMSB		;Step 11 - Read temperature value, MSB
		goto	Restart		;Step 12 - Start over (never reached)

PresencePulse	bcf	IOPORT		;Prepare the output latch
		bsf	STATUS,RP0
		bcf	IOPORT		;Drive the output port low
		call	Delay480	;Wait for the minimum reset duration
		bsf	STATUS,RP0
		bsf	IOPORT		;Release the I/O port
		bcf	STATUS,RP0
		call	Delay60		;Allow the device time to respond
		btfsc	IOPORT		;Check the 1-wire line
		goto	NoDevice
		call	Delay240	;Wait for the presence pulse to end
		retlw	CONTINUE
NoDevice	bsf	OutsideInvalid	;Outside temperature is not valid
		goto	Restart		;Start the sequence from the top

Measure		movlw	CONVERTT	;Initiate temperature conversion
		call	WriteByte	;Send the command on the 1-wire bus
		retlw	DONE		;Give devices time to do the conversion

ReadFamily	call	ReadByte	;Read family code from the 1-wire bus
		movfw	temp
		sublw	DS_FAM_DS18S20	;Check if the sensor is a DS18S20 
		skpnz
		retlw	CONTINUE	;Found a DS18S20
		movfw	temp
		sublw	DS_FAM_DS18B20	;Check if the sensor is a DS18B20
		skpz
		goto	NoDevice	;Not a supported temperature sensor
		bsf	ds18b20		;Found a DS18B20
		retlw	CONTINUE

ReadCommand	movlw	READSCRATCHPAD	;The scratchpad contains the temerature
		goto	WriteByte	;Send the command on the 1-wire bus

ReadLSB		call	ReadByte	;Read the first scratchpad byte
		movfw	temp
		movwf	lsbstorage	;Save the byte for later use
		retlw	CONTINUE

ReadMSB		call	ReadByte	;Read the second scratchpad byte
		btfsc	ds18b20		;Check which sensor type was found
		goto	HighPrecision	;A DS18B20 stores the value differently
		rrf	temp,W		;Sign of the temperature value
		rrf	lsbstorage,W	;Determine the full degrees
		movwf	float1
		clrf	float2
		rrf	float2,F	;Determine the half degrees
		goto	Success
HighPrecision	swapf	lsbstorage,W	;Get the 1/16 degrees in the high nibble
		andlw	b'11110000'
		movwf	float2		;Store as outside temperture low byte
		swapf	temp,W		;Get the upper nibble of the degrees
		andlw	b'11110000'
		movwf	temp		;Save for later use
		swapf	lsbstorage,W
		andlw	b'1111'		;Get the lower nibble of the degrees
		iorwf	temp,W		;Combine with the saved upper nibble
		movwf	float1		;Store as outside temperature high byte
Success		bsf	OutsideTemp	;Temperature measurement completed
		bsf	OutsideInvalid	;Invalid until validity is checked
		xorlw	85		;Test against powerup value
		skpnz
		goto	Restart		;Not a valid measurement
		lcall	StoreOutTemp	;Store the measurement
		retlw	CONTINUE

Restart		bsf	restart		;Don't clear sensorstage for debugging
		retlw	DONE

Delay480	call	Delay240	;480 = 2 * 240
Delay240	movlw	240 - 8		;Value for 240uS delay (compensated) 
		goto	Delay		;Wait for the specified amount of time
Delay60		movlw	60 - 6		;Value for 60uS delay (compensated) 
Delay		bsf	STATUS,RP0	;Bank 1
		bcf	PIE1,TMR2IE	;Disable interrupt from timer 2
		subwf	PR2,W		;Calculate the start value
		bcf	STATUS,RP0	;Bank 0
		addlw	10		;Overhead for starting and stopping
		movwf	TMR2		;Load the timer
		bsf	T2CON,TMR2ON	;Start timer 2
WaitTimer2	btfss	PIR1,TMR2IF	;Check if timer 2 expired
		goto	WaitTimer2	;Wait some more
		bcf	T2CON,TMR2ON	;Stop timer 2
		bcf	PIR1,TMR2IF	;Prevent unwanted interrupt
		return

Delay15		call	Delay5		;15 = 3 * 5
Delay10		call	Delay5		;10 = 2 * 5
Delay5		nop			;Wait 1 us
		return			;Subroutine Call + Return = 2us + 2us

ReadByte	call	ReadNibble	;Read 4 bits from 1-wire bus
ReadNibble	call	ReadBit		;Read 1 bit from 1-wire bus
		call	ReadBit		;Read 1 bit from 1-wire bus
		call	ReadBit		;Read 1 bit from 1-wire bus
ReadBit		bcf	IOPORT		;Prepare output latch
		bsf	STATUS,RP0	;TRIS register is in Bank 1
		bcf	IOPORT		;Drive the 1-wire line low
		clrc			;Prepare carry while waiting
		bsf	IOPORT		;Release the 1-wire bus
		bcf	STATUS,RP0	;Back to bank 0
		call	Delay10		;Allow device time to write the bit
		btfsc	IOPORT		;Read the 1-wire bus
		setc			;Device wrote a "1"
		rrf	temp,F		;Shift bit into the result varaible
		movlw	45		;Maximum time a device drives the bus
		call	Delay		;Wait for the device to release the bus
		return

ReadRom		movlw	READROM		;Command to read a device's ROM code
		goto	WriteByte	;Send the command on the 1-wire bus
SkipRom		movlw	SKIPROM		;Address all devices on the 1-wire bus
WriteByte	movwf	temp		;Temporarily store the 1-wire command
		call	WriteNibble	;Write 4 bits to the 1-wire bus
WriteNibble	call	WriteBit	;Write 1 bit to the 1-wire bus
		call	WriteBit	;Write 1 bit to the 1-wire bus
		call	WriteBit	;Write 1 bit to the 1-wire bus
WriteBit	rrf	temp,F		;Set carry to least significant bit
WriteSlot	bcf	IOPORT		;Prepare the output latch
		bsf	STATUS,RP0
		bcf	IOPORT		;Drive the 1-wire line low
		skpnc			;Carry contains the bit to send
		bsf	IOPORT		;Release the 1-wire line
		movlw	60 - 10		;Value for 60uS delay (compensated) 
		call	Delay		;Bit duration
		bsf	STATUS,RP0	;Bank 1
		bsf	IOPORT		;Float the 1-wire line, if necessary
		bcf	STATUS,RP0	;Bank 0
		retlw	CONTINUE

		end