Mercurial > public > hwos_code
comparison src/math.asm @ 0:11d4fc797f74
init
author | heinrichsweikamp |
---|---|
date | Wed, 24 Apr 2013 19:22:45 +0200 |
parents | |
children | 653a3ab08062 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:11d4fc797f74 |
---|---|
1 ;============================================================================= | |
2 ; | |
3 ; File math.asm | |
4 ; | |
5 ; Math subroutines | |
6 ; | |
7 ; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. | |
8 ;============================================================================= | |
9 ; HISTORY | |
10 ; 2011-08-03 : [mH] moving from OSTC code | |
11 | |
12 | |
13 #include "ostc3.inc" ; Mandatory header | |
14 | |
15 basic CODE | |
16 ;============================================================================= | |
17 global convert_time | |
18 convert_time: ; converts hi:lo in minutes to hours (hi) and minutes (lo) | |
19 movff lo,xA+0 ; divide by 60... | |
20 movff hi,xA+1 ; | |
21 movlw d'60' ; | |
22 movwf xB+0 ; | |
23 clrf xB+1 ; | |
24 rcall div16x16 ; xA/xB=xC with xA as remainder | |
25 movff xC+0,hi ; Hours | |
26 movff xA+0,lo ; =remaining minutes (0.....59) | |
27 return | |
28 | |
29 global div16 | |
30 div16: | |
31 ; divA=divA/2^divB (divB: 8Bit only!) | |
32 bcf STATUS,C | |
33 rrcf divA+1 | |
34 rrcf divA+0 | |
35 decfsz divB | |
36 bra div16 | |
37 return | |
38 | |
39 global sub16 | |
40 sub16: | |
41 ; sub_c = sub_a - sub_b (with signed values) | |
42 bcf neg_flag | |
43 movf sub_b+0, W ; Get Value to be subtracted | |
44 subwf sub_a+0, W ; Do the High Byte | |
45 movwf sub_c+0 | |
46 movf sub_b+1, W ; Get the Value to be Subbed | |
47 subwfb sub_a+1, W | |
48 movwf sub_c+1 | |
49 | |
50 btfss STATUS,N ; Negativ result ? | |
51 return ; NO: result positive done. | |
52 | |
53 bsf neg_flag ; MARK result negative | |
54 | |
55 comf sub_c+1 ; 16bit sign change. | |
56 negf sub_c+0 | |
57 btfsc STATUS,C ; Carry to propagate ? | |
58 incf sub_c+1,F ; YES: do it. | |
59 | |
60 return | |
61 | |
62 global subU16 | |
63 subU16: | |
64 ; sub_c = sub_a - sub_b (with UNSIGNED values) | |
65 bcf neg_flag | |
66 movf sub_b+0, W ; Get Value to be subtracted | |
67 subwf sub_a+0, W ; Do the High Byte | |
68 movwf sub_c+0 | |
69 movf sub_b+1, W ; Get the Value to be Subbed | |
70 subwfb sub_a+1, W | |
71 movwf sub_c+1 | |
72 btfsc STATUS,C ; Borrow to propagate ? (B == /CARRY) | |
73 return ; NO: result positive done. | |
74 bsf neg_flag ; MARK result negative | |
75 comf sub_c+1 ; 16bit sign change. | |
76 negf sub_c+0 | |
77 btfsc STATUS,C ; Carry to propagate ? | |
78 incf sub_c+1,F ; YES: do it. | |
79 return | |
80 | |
81 global mult16x16 | |
82 mult16x16: ;xA*xB=xC | |
83 clrf xC+2 ; Clear the High-Order Bits | |
84 clrf xC+3 | |
85 movf xA, w ; Do the "L" Multiplication first | |
86 mulwf xB | |
87 movf PRODL, w ; Save result | |
88 movwf xC | |
89 movf PRODH, w | |
90 movwf xC+1 | |
91 movf xA, w ; Do the "I" Multiplication | |
92 mulwf xB+1 | |
93 movf PRODL, w ; Save the Most Significant Byte First | |
94 addwf xC+1, f | |
95 movf PRODH, w | |
96 addwfc xC+2, f ; Add to the Last Result | |
97 movf xA+1, w ; Do the "O" Multiplication | |
98 mulwf xB | |
99 movf PRODL, w ; Add the Lower Byte Next | |
100 addwf xC+1, f | |
101 movf PRODH, w ; Add the High Byte First | |
102 addwfc xC+2, f | |
103 btfsc STATUS, C ; Add the Carry | |
104 incf xC+3, f | |
105 movf xA+1, w ; Do the "F" Multiplication | |
106 mulwf xB+1 | |
107 movf PRODL, w | |
108 addwf xC+2, f | |
109 movf PRODH, w | |
110 addwfc xC+3, f | |
111 return | |
112 | |
113 global div16x16 | |
114 div16x16: ;xA/xB=xC with xA+0 as remainder | |
115 ;uses divB as temp variable | |
116 clrf xC+0 | |
117 clrf xC+1 | |
118 MOVF xB+0,W ; Check for zero | |
119 IORWF xB+1,W ; | |
120 BTFSC STATUS,Z ; Check for zero | |
121 RETLW H'FF' ; return 0xFF if illegal | |
122 MOVLW 1 ; Start count at 1 | |
123 MOVWF divB ; Clear Count | |
124 div16x16_1: | |
125 BTFSC xB+1,7 ; High bit set ? | |
126 bra div16x16_2 ; Yes then continue | |
127 INCF divB,F ; Increment count | |
128 | |
129 bcf STATUS,C | |
130 rlcf xB+0,F | |
131 rlcf xB+1,F | |
132 bra div16x16_1 | |
133 div16x16_2: | |
134 ; Shift result left | |
135 bcf STATUS,C | |
136 rlcf xC+0,F | |
137 rlcf xC+1,F | |
138 | |
139 ; Reduce Divisor | |
140 | |
141 MOVF xB,W ; Get low byte of subtrahend | |
142 SUBWF xA,F ; Subtract DST(low) - SRC(low) | |
143 MOVF xB+1,W ; Now get high byte of subtrahend | |
144 BTFSS STATUS,C ; If there was a borrow, rather than | |
145 INCF xB+1,W ; decrement high byte of dst we inc src | |
146 SUBWF xA+1,F ; Subtract the high byte and we're done | |
147 | |
148 | |
149 BTFSC STATUS, C ; Did it reduce? | |
150 bra div16x16_3 ; No, so it was less than | |
151 | |
152 movf xB+0,W ; Reverse subtraction | |
153 addwf xA+0,F | |
154 movf xB+1,W | |
155 addwfc xA+1,F | |
156 | |
157 bra div16x16_4 ; Continue the process | |
158 div16x16_3: | |
159 BSF xC+0,0 ; Yes it did, this gets a 1 bit | |
160 div16x16_4: | |
161 DECF divB,F ; Decrement N_COUNT | |
162 BTFSC STATUS,Z ; If its not zero then continue | |
163 return | |
164 | |
165 bcf STATUS,C | |
166 rrcf xB+1,F | |
167 rrcf xB+0,F | |
168 | |
169 bra div16x16_2 ; Next bit. | |
170 | |
171 global div32x16 | |
172 div32x16: ; xC:4 / xB:2 = xC+3:xC+2 with xC+1:xC+0 as remainder | |
173 ; Setup | |
174 movlw .32 ; setup shift counter | |
175 movwf divB | |
176 movff xC+3,xA+1 ; move ACCb to ACCf | |
177 movff xC+2,xA+0 | |
178 movff xC+1,sub_a+1 ; move ACCc to ACCe | |
179 movff xC+0,sub_a+0 | |
180 clrf xC+3 | |
181 clrf xC+2 | |
182 clrf xC+1 | |
183 clrf xC+0 | |
184 clrf sub_b+1 | |
185 clrf sub_b+0 | |
186 div32x16_2: | |
187 bcf STATUS,C | |
188 rlcf sub_a+0,F | |
189 rlcf sub_a+1,F | |
190 rlcf xA+0,F | |
191 rlcf xA+1,F | |
192 rlcf sub_b+0,F | |
193 rlcf sub_b+1,F | |
194 movf xB+1,W | |
195 subwf sub_b+1,W ; check if a>d | |
196 btfss STATUS,Z | |
197 bra div32x16_3 | |
198 movf xB+0,W | |
199 subwf sub_b+0,W ; if msb equal then check lsb | |
200 div32x16_3: | |
201 btfss STATUS,C ; carry set if d>a | |
202 bra div32x16_4 | |
203 movf xB+0,W ; d-a into d | |
204 subwf sub_b+0,F | |
205 btfss STATUS,C | |
206 decf sub_b+1,F | |
207 movf xB+1,W | |
208 subwf sub_b+1,F | |
209 bsf STATUS,C ; shift a 1 into b (result) | |
210 div32x16_4: | |
211 rlcf xC+0,F | |
212 rlcf xC+1,F | |
213 rlcf xC+2,F | |
214 rlcf xC+3,F | |
215 decfsz divB,F ; loop until all bits checked | |
216 bra div32x16_2 | |
217 return | |
218 | |
219 ;;============================================================================= | |
220 ;; u16 * u16 --> 32bit multiply (xA * xB --> xC) | |
221 ;; Used in interupt service routines, to compute temperature and pressure. | |
222 ;; | |
223 ; global isr_mult16x16 | |
224 ;isr_mult16x16: | |
225 ; clrf isr_xC+2 ; Clear the High-Order Bits | |
226 ; clrf isr_xC+3 | |
227 ; movf isr_xA, w ; Do the "L" Multiplication first | |
228 ; mulwf isr_xB | |
229 ; movf PRODL, w ; Save result | |
230 ; movwf isr_xC+0 | |
231 ; movf PRODH, w | |
232 ; movwf isr_xC+1 | |
233 ; movf isr_xA+0, w ; Do the "I" Multiplication | |
234 ; mulwf isr_xB+1 | |
235 ; movf PRODL, w ; Save the Most Significant Byte First | |
236 ; addwf isr_xC+1, f | |
237 ; movf PRODH, w | |
238 ; addwfc isr_xC+2, f ; Add to the Last Result | |
239 ; movf isr_xA+1, w ; Do the "O" Multiplication | |
240 ; mulwf isr_xB | |
241 ; movf PRODL, w ; Add the Lower Byte Next | |
242 ; addwf isr_xC+1, f | |
243 ; movf PRODH, w ; Add the High Byte First | |
244 ; addwfc isr_xC+2, f | |
245 ; btfsc STATUS, C ; Add the Carry | |
246 ; incf isr_xC+3, f | |
247 ; movf isr_xA+1, w ; Do the "F" Multiplication | |
248 ; mulwf isr_xB+1 | |
249 ; movf PRODL, w | |
250 ; addwf isr_xC+2, f | |
251 ; movf PRODH, w | |
252 ; addwfc isr_xC+3, f | |
253 ; return | |
254 | |
255 ;============================================================================= | |
256 ; 24bit shift, repeted WREG times. | |
257 ; Because we shift less than 8bits, and keep only C[2:1], we don't care what | |
258 ; bit is inserted... | |
259 ; | |
260 global isr_shift_C31 | |
261 isr_shift_C31: | |
262 rrcf isr_xC+3,F ; Shift the three bytes... | |
263 rrcf isr_xC+2,F | |
264 rrcf isr_xC+1,F | |
265 decfsz WREG | |
266 bra isr_shift_C31 | |
267 return | |
268 | |
269 ;============================================================================= | |
270 ; s16 * s16 --> 32bit multiply (xA * xB --> xC) | |
271 ; Signed multiplication. | |
272 ; Code from... the Pic18F documentation ;-) | |
273 global isr_unsigned_mult16x16 | |
274 isr_unsigned_mult16x16: | |
275 MOVF isr_xA+0, W ; Lowest is simply a[0] * b[0] | |
276 MULWF isr_xB+0 | |
277 MOVFF PRODL, isr_xC+0 | |
278 MOVFF PRODH, isr_xC+1 | |
279 ; | |
280 MOVF isr_xA+1, W ; And highest a[1] * b[1] | |
281 MULWF isr_xB+1 | |
282 MOVFF PRODL, isr_xC+2 | |
283 MOVFF PRODH, isr_xC+3 | |
284 ; | |
285 MOVF isr_xA+0, W ; Intermediates do propagate: | |
286 MULWF isr_xB+1 | |
287 MOVF PRODL, W | |
288 ADDWF isr_xC+1, F ; Add cross products | |
289 MOVF PRODH, W | |
290 ADDWFC isr_xC+2, F ; with propagated carry | |
291 CLRF WREG | |
292 ADDWFC isr_xC+3, F ; on the three bytes. | |
293 ; | |
294 MOVF isr_xA+1, W ; And the second one, similarly. | |
295 MULWF isr_xB+0 | |
296 MOVF PRODL, W | |
297 ADDWF isr_xC+1, F ; Add cross products | |
298 MOVF PRODH, W | |
299 ADDWFC isr_xC+2, F | |
300 CLRF WREG | |
301 ADDWFC isr_xC+3, F | |
302 return | |
303 | |
304 global isr_signed_mult16x16 | |
305 isr_signed_mult16x16: | |
306 rcall isr_unsigned_mult16x16 | |
307 | |
308 ; Manage sign extension of operand B | |
309 BTFSS isr_xB+1,7 ; Is B negatif ? | |
310 BRA isr_signed_mult_checkA ; No: check ARG1 | |
311 MOVF isr_xA+0, W ; Yes: add -65536 * A | |
312 SUBWF isr_xC+2, F | |
313 MOVF isr_xA+1, W | |
314 SUBWFB isr_xC+3, F | |
315 ; And of operand A | |
316 isr_signed_mult_checkA | |
317 BTFSS isr_xA+1, 7 ; Is A negatif ? | |
318 RETURN ; No: done | |
319 MOVF isr_xB+0, W | |
320 SUBWF isr_xC+2, F | |
321 MOVF isr_xB+1, W | |
322 SUBWFB isr_xC+3, F | |
323 RETURN | |
324 | |
325 END |