Attachment 'useful_functions.asm'
Download 1 ; useful_functions.asm - a listing of useful functions in assembly for
2 ; microdec programming. register limitations are shown for each program.
3
4 ; to use these, just copy and paste into your program, and be sure that your
5 ; register usage doesnt overlap. a listing of all your register usage at the
6 ; beginning of your file is a good way to check for this. be sure to replace
7 ; UID with your unique id for your code, or you will get assembly conflicts.
8 ; check the microdec wiki to see which numbers have been assigned. if other
9 ; people use your code, it shouldnt conflict with their assembly either.
10
11 ; list of functions in this file
12 ;
13 ; 1. reading and writing to the codec.
14 ; 2. reading from the sram - 16b
15 ; 3. reading from the sram - 18b
16 ; 4. writing to the sram - 16b
17 ; 5. writing to the sram - 18b
18 ; 6. sampling the switch to change functions - no initialization
19 ; 7. sampling the switch to change functions - with initialization
20 ; 8. initialization routine
21 ; 9. 16b signed x 16b signed to (16b or 32b) signed number
22 ; 10. 16b signed x 8b unsigned to (16b or 24b) signed number
23 ; 11. 16b signed x 16b unsigned to (16b or 32b) signed number
24 ; 12. two's complement of 16b number
25 ; 13. two's complement of 24b number
26 ; 14. adding signed numbers of different lengths
27
28 ; 1. reading and writing to the codec.
29 ;
30 ; this function will write 16b stereo data to the codec, and read out 16b
31 ; stereo data from the codec. this function must be run at a fixed interval,
32 ; or audio glitches will be heard. you must read and write all 16b of both
33 ; channels each time, or the codec will not operate. you can change the bit
34 ; depth for the codec, and its rate in the setup registers in the main file.
35 ; only 16b stereo data has been tested at this point (both 44.1kHz and 48khz
36 ; have been tested, but the microdec hardware only supports 44.1kHz). this
37 ; function assumes you have the spi register configured appropriately (the
38 ; main file does this).
39
40 ; register usage:
41 ;
42 ; r2 left lsb out - can be any register
43 ; r3 left msb out - can be any register
44 ; r4 right lsb out - can be any register
45 ; r5 right msb out - can be any register
46 ; r6 left lsb in - can be any register
47 ; r7 left msb in - can be any register
48 ; r8 right lsb in - can be any register
49 ; r9 right msb in - can be any register
50 ; r17 temporary swap register - can be any register
51
52 ; code:
53 ;
54 ;the timing of this first operation is critical. do not change the next
55 ;three lines for any reason.
56 sbi portb,portb0 ; toggle slave select pin to begin transfer
57 out spdr,r3 ; send out left channel msb
58 cbi portb,portb0 ; clear slave select pin
59 ;
60 ;more code can be placed here to save cycles, up to 16 lines without much
61 ;effect on the total time that it takes to run this code.
62 ;
63 wait1_UID: ; check if byte has been sent
64
65 in r17,spsr
66 sbrs r17,spif
67 rjmp wait1_UID
68 in r7,spdr ; recieve in left channel msb
69 out spdr,r2 ; send out left channel lsb
70 ;
71 ;more code can be placed here to save cycles, up to 16 lines without much
72 ;effect on the total time that it takes to run this code.
73 ;
74 wait2_UID: ; check if byte has been sent
75
76 in r17,spsr
77 sbrs r17,spif
78 rjmp wait2_UID
79 in r6,spdr ; recieve in left channel lsb
80 out spdr,r5 ; send out right channel msb
81 ;
82 ;more code can be placed here to save cycles, up to 16 lines without much
83 ;effect on the total time that it takes to run this code.
84 ;
85 wait3_UID: ; check if byte has been sent
86
87 in r17,spsr
88 sbrs r17,spif
89 rjmp wait3_UID
90 in r9,spdr ; recieve in right channel msb
91 out spdr,r4 ; send out right channel lsb
92 ;
93 ;more code can be placed here to save cycles, up to 16 lines without much
94 ;effect on the total time that it takes to run this code.
95 ;
96 wait4_UID: ; check if byte has been sent
97
98 in r17,spsr
99 sbrs r17,spif
100 rjmp wait4_UID
101 in r8,spdr ; recieve in left channel lsb
102 ;
103 ; function end
104
105
106 ; 2. reading from the sram - 16b
107 ;
108 ; this code will read a 16b value from the sram, using a 16b address. this
109 ; is faster than using the full 18b address space. the 16b address space
110 ; is also convenient to use when difficult address calculations are
111 ; required (i.e. youre doing more than just incrementing the address).
112
113 ; register usage:
114 ;
115 ; r16 data lsb - can be any register
116 ; r17 data msb - can be any register
117 ; r18 swap register - must be one of r16 - r31
118 ; r28 read address lsb - can be any register
119 ; r29 read address msb - can be any register
120
121 ; code:
122 ;
123 ;setup sram for read - this can be omitted if your code already has these
124 ;registers set appropriately elsewhere. if you are unsure, you should set
125 ;them here, as you can severly damage your sram if its not setup
126 ;correctly. you only need to to do this once for any consecutive reads.
127 ;there are also other ways of accomplishing this task, but this is the
128 ;easiest way.
129 clr r18 ; prepare to set i/o to input for data read
130 out ddra,r18 ; set porta as input for data read
131 out ddrc,r18 ; set portc as input for data read
132 ldi r18,$04
133 out portg,r18 ; pull ce low, we high, and set high bits of register to b00
134
135 ;read data from sram
136 out portd,r28 ; set address lsb
137 sts porth,r29 ; set address msb
138 nop ; wait required microcontroller i/o setup time of 2 cycles
139 nop ; can place other code here for efficient usage of time
140 in r16,pina ; get data lsb
141 in r17,pinc ; get data msb
142 ;
143 ; function done
144
145
146 ; 3. reading from the sram - 18b
147 ;
148 ; this code will read a 16b value from the sram, using an 18b address.
149
150 ; register usage:
151 ;
152 ; r16 data lsb - can be any register
153 ; r17 data msb - can be any register
154 ; r18 swap register - must be one of r16 - r31
155 ; r23 read address high byte - can be any register
156 ; r28 read address lsb - can be any register
157 ; r29 read address msb - can be any register
158
159 ; code:
160 ;
161 ;setup sram for read - this can be omitted if your code already has these
162 ;registers set appropriately elsewhere. if you are unsure, you should set
163 ;them here, as you can severly damage your sram if its not setup
164 ;correctly. you only need to to do this once for any consecutive reads.
165 ;there are also other ways of accomplishing this task, but this is the
166 ;easiest way.
167 clr r18 ; prepare to set i/o to input for data read
168 out ddra,r18 ; set porta as input for data read
169 out ddrc,r18 ; set portc as input for data read
170 ldi r18,$04 ; this line and the next can be omitted if the "out portg,r23"
171 ; line directly follows "out ddrc,r18" from above.
172 out portg,r18 ; pull ce low, we high, and set high bits of register to b00
173
174 ;read data from sram
175 out portg,r23 ; pull ce low, we high, and set high bits of register
176 ; it is critical that r23 be of the format b000001dd where dd are the
177 ; address high bits (i.e. only $04 - $07 are valid). damage to the sram
178 ; can occur if this is not followed.
179 out portd,r28 ; set address lsb
180 sts porth,r29 ; set address msb
181 nop ; wait required microcontroller i/o setup time of 2 cycles
182 nop ; can place other code here for efficient usage of time
183 in r16,pina ; get data lsb
184 in r17,pinc ; get data msb
185 ;
186 ; function done
187
188
189 ; 4. writing to the sram - 16b
190 ;
191 ; this code will write a 16b value to the sram, using a 16b address. this
192 ; is faster than using the full 18b address space. the 16b address space
193 ; is also convenient to use when difficult address calculations are
194 ; required (i.e. youre doing more than just incrementing the address).
195
196 ; register usage:
197 ;
198 ; r16 data lsb - can be any register
199 ; r17 data msb - can be any register
200 ; r18 swap register - can be any register
201 ; r19 swap register - must be one of r16 - r31
202 ; r24 write address lsb - can be any register
203 ; r25 write address msb - can be any register
204
205 ; code:
206 ;
207 ; this is not the most efficient method of writing to the sram if you
208 ; are doing many consecutive writes, but is more efficient for
209 ; consecutive reads, as it leaves the sram in the read state, and assumes
210 ; it is in the read state to begin with. check the sram datasheet for
211 ; other write modes for your application if speed is critical.
212 ;
213 ;setup sram - can be omitted if already setup, or if previous operation
214 ;was a read as shown above.
215 clr r18 ; prepare to set i/o to input for data read
216 out ddra,r18 ; set porta as input for data read
217 out ddrc,r18 ; set portc as input for data read
218 ldi r19,$04
219 out portg,r19 ; pull ce low, we high, and set high bits of register to b00
220
221 ;sram write
222 clr r18 ; prepare for sram setting and microcontroller i/o setting - can be
223 ; omitted if a register is set to zero (null register) elsewhere.
224 out portd,r24 ; set address lsb
225 sts porth,r25 ; set address msb
226 out portg,r18 ; pull ce low,we low,and set high bits of address
227 ldi r19,$ff
228 out ddra,r19 ; set porta as output for data write
229 out ddrc,r19 ; set portc as output for data write
230 out porta,r16 ; set data lsb
231 out portc,r17 ; set data msb
232 sbi portg,portg2 ; pull we high to write
233 out ddra,r18 ; set porta as input for data lines
234 out ddrc,r18 ; set portc as input for data lines
235 ;
236 ; function end
237
238
239 ; 5. writing to the sram - 18b
240 ;
241 ; this code will write a 16b value to the sram, using an 18b address.
242
243 ; register usage:
244 ;
245 ; r16 data lsb - can be any register
246 ; r17 data msb - can be any register
247 ; r18 swap register - can be any register
248 ; r19 swap register - must be one of r16 - r31
249 ; r22 write address high byte - can be any register
250 ; r24 write address lsb - can be any register
251 ; r25 write address msb - can be any register
252
253 ; code:
254 ;
255 ; this is not the most efficient method of writing to the sram if you
256 ; are doing many consecutive writes, but is more efficient for
257 ; consecutive reads, as it leaves the sram in the read state, and assumes
258 ; it is in the read state to begin with. check the sram datasheet for
259 ; other write modes for your application if speed is critical.
260 ;
261 ;setup sram - can be omitted if already setup, or if previous operation
262 ;was a read as shown above.
263 clr r18 ; prepare to set i/o to input for data read
264 out ddra,r18 ; set porta as input for data read
265 out ddrc,r18 ; set portc as input for data read
266 ldi r19,$04
267 out portg,r19 ; pull ce low, we high, and set high bits of register to b00
268
269 ;sram write
270 clr r18 ; prepare for microcontroller i/o setting - can be
271 ; omitted if a register is set to zero (null register) elsewhere.
272 out portd,r24 ; set address lsb
273 sts porth,r25 ; set address msb
274 out portg,r22 ; pull ce low, we low, and set high bits of register
275 ; it is critical that r22 be of the format b000000dd where dd are the
276 ; address high bits (i.e. only $00 - $03 are valid). damage to the sram
277 ; can occur if this is not followed.
278 ldi r19,$ff
279 out ddra,r19 ; set porta as output for data write
280 out ddrc,r19 ; set portc as output for data write
281 out porta,r16 ; set data lsb
282 out portc,r17 ; set data msb
283 sbi portg,portg2 ; pull we high to write
284 out ddra,r18 ; set porta as input for data lines
285 out ddrc,r18 ; set portc as input for data lines
286 ;
287 ; function end
288
289
290 ; 6. sampling the switch to change functions - no initialization
291 ;
292 ; this must be done in a consistent fashion so all subprograms work with the
293 ; main loop. r31:r30 hold the jump vector, and must be reset at the end of
294 ; any subprogram. you can either not alter these register, store them on
295 ; the stack, or recalculate them on each pass through the subprogram. i
296 ; usually leave them unaltered, as this consumes the least time. the
297 ; program shown here samples the switch once every 256 cycles. this gives
298 ; a little bit more glitch immunity (as the switch is not debounced in
299 ; hardware), and keeps the microcontroller from starting every program it
300 ; passes along the way between the first switch position and the last. this
301 ; isnt required, but makes things a little nicer.
302
303 ; register usage
304 ;
305 ; r15 switch sample counter - can be any register
306 ; r17 temporary register - must be one of r16 - r31
307 ; r31 jump location msb - must be r31
308
309 ; code:
310 ;
311 ;this code assumes there is no initialization in the subprogram (i.e. the
312 ;program starts at initial jump location), and that r30 is set to $00, and
313 ;is not altered during the subprogram, ever.
314 dec r15 ; downcount sample counter
315 brne done_UID ; check switch every 256 cycles
316 lds r31,pinj ; get switch data
317 andi r31,$78 ; mask off rotary switch
318 ldi r17,$02 ; prepare to adjust switch position to program memory location
319 lsr r31
320 lsr r31
321 add r31,r17 ; adjust switch position to program memory location
322
323 done_UID:
324
325 reti ; i usually place the switch sampling at the end of my code, but other
326 ; code can follow in place of the reti
327 ;
328 ; function end
329
330
331 ; 7. sampling the switch to change functions - with initialization
332 ;
333 ; this must be done in a consistent fashion so all subprograms work with the
334 ; main loop. r31:r30 hold the jump vector, and must be reset at the end of
335 ; any subprogram. you can either not alter these register, store them on
336 ; the stack, or recalculate them on each pass through the subprogram. i
337 ; usually leave them unaltered, as this consumes the least time. the
338 ; program shown here samples the switch once every 256 cycles. this gives
339 ; a little bit more glitch immunity (as the switch is not debounced in
340 ; hardware), and keeps the microcontroller from starting every program it
341 ; passes along the way between the first switch position and the last. this
342 ; isnt required, but makes things a little nicer.
343
344 ; register usage
345 ;
346 ; r15 switch sample counter - can be any register
347 ; r16 temporary register - must be one of r16 - r31
348 ; r17 temporary register - must be one of r16 - r31
349 ; r30 jump locatoin lsb - must be r30
350 ; r31 jump location msb - must be r31
351
352 ; code
353 ;
354 ;this code assumes that r30 is modified in the initialization routine (the
355 ;routine at codespace corresponding to r30=$00), and that it is not modified
356 ;in any way by the subprogram after that.
357 dec r15 ; downcount sample counter
358 brne done_UID ; sample every 256 cycles
359 lds r16,pinj ; get switch data to temporary register
360 andi r16,$78 ; mask off rotary switch
361 ldi r17,$02 ; prepare to adjust switch position
362 lsr r16
363 lsr r16
364 add r16,r17 ; adjust switch position to program memory location
365 cpse r16,r31 ; check if location has changed - dont reset r30 if it hasnt
366 clr r30 ; reset jump location lsb to intial state ($00)
367 mov r31,r16 ; set jump location msb to current swtich position
368
369 done_UID:
370
371 reti ; i usually place the switch sampling at the end of my code, but other
372 ; code can follow in place of the reti
373 ;
374 ; function end
375
376
377 ; 8. initialization routine
378 ;
379 ; this places a small set of code which is only run once when a subprogram
380 ; is first called. it adjusts the jump location accordingly. this must be
381 ; used with the switchsample routine which accounts for initialization. r30
382 ; can not be modified anywhere in the subprogram.
383
384 ; register usage:
385 ;
386 ; r30 jump location lsb - must be r30
387
388 ; code:
389 ;
390 ;program starts here first time
391 ;initialze z pointer for correct jump
392 ;this assumes a less than 256 word jump
393 ldi r30,$05 ; set jump location to program start - this constant must be
394 ; calculated to coincide with the subsequent start location. this can
395 ; either be done by counting the instructions that follow, and noting
396 ; their memory usage (as given in the instruction set), or by assembling
397 ; the file and looking at the result in the disassembler (avrstudio has a
398 ; a nice disassembler that you can quickly look at to find the right value).
399 nop ; place your initialization routine here instead of the nops
400 nop
401 nop
402 reti ; return and wait for next interrupt
403 ;
404 ; function end
405
406
407 ; 9. 16b signed x 16b signed to (16b or 32b) signed number
408 ;
409 ; this is a simple multiplaction routine for 16b signed numbers that
410 ; returns a 32b number, of which you can use the upper 16b if thats all
411 ; that is required. multiplicands start out in r11:r10 and r9:r8, and the
412 ; result ends up in r5:r4:r3:r2. you can use whichever starting or ending
413 ; registers you wish.
414
415 ; register usage
416 ;
417 ; r0 = multiply interim result lsb - must be this register
418 ; r1 = multiply interim result msb - must be this register
419 ; r2 = multiply final result lsb - can be any register
420 ; r3 = multiply final resutl mlb - can be any register
421 ; r4 = multiply final result mhb - can be any register
422 ; r5 = multiply final result msb - can be any register
423 ; r18 = multiplicand A lsb - must be one of register r16 - r23
424 ; r19 = multiplicand A msb - must be one of register r16 - r23
425 ; r20 = multiplicand B lsb - must be one of register r16 - r23
426 ; r21 = multiplicand B msb - must be one of register r16 - r23
427 ; r22 = null register - can be any register
428
429 ; code
430 ;
431 clr r22 ; clear null register for carry addition/subtraction - not needed
432 ; if already done elsewhere in the code
433 movw r19:r18,r9:r8 ; move values to multiply register - not necessary if
434 ; your values are already in those registers
435 movw r21:r20,r11:r10 ; move values to multiply register - not necessary if
436 ; your values are already in those registers
437 muls r19,r21 ; (signed)Ah * (signed)Bh - multiply high bytes
438 movw r5:r4,r1:r0 ; store high bytes result for later
439 mul r18,r20 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
440 movw r3:r2,r1:r0 ; store low byets for later
441 mulsu r19,r20 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
442 sbc r5,r22 ; r22 is cleared above - subtract sign bit
443 add r3,r0 ; accumulate result
444 adc r4,r1
445 adc r5,r22 ; r22 is cleared above
446 mulsu r21,r18 ; (signed)Bh * (unsigned)Al - multiply middle bytes
447 sbc r5,r22 ; r22 is cleared above - subtract sign bit
448 add r3,r0 ; accumulate result
449 adc r4,r1
450 adc r5,r22 ; r22 is cleared above
451 ;
452 ; function end
453
454
455 ; 9. 16b signed x 8b unsigned to (16b or 24b) signed number
456 ;
457 ; this is a simple multiplaction routine for 16b signed numbers that
458 ; returns a 24b number, of which you can use the upper 16b if thats all
459 ; that is required. multiplicands start out in r11:r10 and r9, and the
460 ; result ends up in r5:r4:r3. you can use whichever starting or ending
461 ; registers you wish.
462
463 ; register usage
464 ;
465 ; r0 = multiply interim result lsb - must be this register
466 ; r1 = multiply interim result msb - must be this register
467 ; r3 = multiply final result fractional byte - can be any register
468 ; r4 = multiply final result lsb - can be any register
469 ; r5 = multiply final result msb - can be any register
470 ; r18 = multiplicand A lsb - can be any register
471 ; r19 = multiplicand A msb - must be one of register r16 - r23
472 ; r21 = multiplicand B - must be one of register r16 - r23
473 ; r22 = null register - can be any register
474
475 ; code
476 ;
477 clr r22 ; clear null register for carry addition/subtraction - not needed
478 ; if already done elsewhere in the code
479 mov r21,r9 ; move value to multiply register - not necessary if
480 ; your values are already in those registers
481 movw r19:r18,r11:r10 ; move values to multiply register - not necessary if
482 ; your values are already in those registers
483 mulsu r19,r21 ; (signed)Ah * (unsigned)B - multiply high byte
484 movw r5:r4,r1:r0 ; store result
485 mul r18,r21 ; (unsigned)Al * (unsigned)B - multiply low byte
486 mov r3,r0 ; store fractional byte - not needed for 16b result
487 add r4,r1 ; accumulate result
488 adc r5,r22 ; r22 is cleared above
489 ;
490 ; function end
491
492
493 ; 10. 16b signed x 16b unsigned to (16b or 32b) signed number
494 ;
495 ; this is a simple multiplaction routine for 16b signed/unsigned numbers
496 ; that returns a 32b number, of which you can use the upper 16b if thats all
497 ; that is required. multiplicands start out in r11:r10 and r9:r8, and the
498 ; result ends up in r5:r4:r3:r2. you can use whichever starting or ending
499 ; registers you wish.
500
501 ; register usage
502 ;
503 ; r0 = multiply interim result lsb - must be this register
504 ; r1 = multiply interim result msb - must be this register
505 ; r2 = multiply final result lsb - can be any register
506 ; r3 = multiply final resutl mlb - can be any register
507 ; r4 = multiply final result mhb - can be any register
508 ; r5 = multiply final result msb - can be any register
509 ; r18 = multiplicand A lsb - can be any register
510 ; r19 = multiplicand A msb - must be one of register r16 - r23
511 ; r20 = multiplicand B lsb - must be one of register r16 - r23
512 ; r21 = multiplicand B msb - must be one of register r16 - r23
513 ; r22 = null register - can be any register
514
515 ; code
516 ;
517 clr r22 ; clear null register for carry addition/subtraction - not needed
518 ; if already done elsewhere in the code
519 movw r19:r18,r9:r8 ; move values to multiply register - not necessary if
520 ; your values are already in those registers
521 movw r21:r20,r11:r10 ; move values to multiply register - not necessary if
522 ; your values are already in those registers
523 mulsu r19,r21 ; (signed)Ah * (unsigned)Bh - multiply high bytes
524 movw r5:r4,r1:r0 ; store high bytes result for later
525 mul r18,r20 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
526 movw r3:r2,r1:r0 ; store low byets for later
527 mulsu r19,r20 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
528 sbc r5,r22 ; r22 is cleared above - subtract sign bit
529 add r3,r0 ; accumulate result
530 adc r4,r1
531 adc r5,r22 ; r22 is cleared above
532 mul r21,r18 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
533 add r3,r0 ; accumulate result
534 adc r4,r1
535 adc r5,r22 ; r22 is cleared above
536 ;
537 ; function end
538
539
540 ; 11. two's complement of 16b number
541 ;
542 ; this function will give you the negative value of a signed number. i.e.
543 ; positive values will become negative, and negative values will become
544 ; positive. it is good for 16b numbers. value $8000 (-32768) stays the same
545 ; as there is no positive value that large (be careful of this if trying to
546 ; take the absolute value of a number). this function also gives you the
547 ; complementary distance from a value to $0000, i.e. $0000 - r5:r4.
548
549 ; register usage
550 ;
551 ; r4 = lsb - can be any register
552 ; r5 = msb - can be any register
553 ; r16 = temporary register - can be any register
554
555 ; code
556 ;
557 clr r16 ; not required if a register already has value $00
558 neg r4 ; invert
559 adc r5,r16
560 neg r5
561 ;
562 ; end function
563
564
565 ; 12. two's complement of 24b number
566 ;
567 ; this function will give you the negative value of a signed number. i.e.
568 ; positive values will become negative, and negative values will become
569 ; positive. it is good for 24b numbers. value starts in r5:r4:r3, and gets
570 ; modified, and remains in those registers. value $800000 (-8388608 decimal),
571 ; stays the same value, as there is no positive value that large (be careful
572 ; of this if trying to take the absolute value of a number). this function
573 ; also gives you the complementary distance from a value to $000000, i.e.
574 ; $000000 - r5:r4:r3.
575
576 ; register usage
577 ;
578 ; r3 = fractional byte - can be any register
579 ; r4 = lsb - can be any register
580 ; r5 = msb - can be any register
581 ; r16 = temporary register - must be one of r16 - r31
582 ; r17 = temporary register - can be any register
583
584 ; code
585 ;
586 ldi r16,$01 ; does not need to be done if a register already has value $01
587 clr r17 ; does not need to be done if a register already has value $00
588 com r3 ; invert value
589 com r4
590 com r5
591 add r3,r16 ; r16 set to $01 above
592 adc r4,r17 ; r17 cleared above
593 adc r5,r17
594 ;
595 ; end function
596
597
598 ; 14. adding signed numbers of different lengths
599 ;
600 ; this function adds signed number of different byte lengths, where the
601 ; shorter length number represents a fraction of the higher length number.
602 ; this is useful for accumulation, where 8b or 16b numbers will need to be
603 ; added to 24b or 32b accumulation registers. converting your number to an
604 ; unsigned integer before accumulation is a workaround for not having to do
605 ; this.
606
607 ; register usage
608 ;
609 ; r0 = value 1 lsb - can be any register
610 ; r1 = value 1 msb - can be any register
611 ; r2 = value 2 lsb - can be any register
612 ; r3 = value 2 mlb - can be any register
613 ; r4 = value 2 mhb - can be any register
614 ; r5 = value 2 msb - can be any register
615 ; r16 = null register - can be any register
616
617 ; code
618 ;
619 clr r16 ; does not need to be done if already cleared
620 add r2,r0 ; begin accumulation
621 adc r3,r1
622 sbrc r1,$07 ; check if r1:r0 is negative
623 dec r16 ; set null register to $ff if its negative (ldi r16,$ff could be
624 ; used here as well, but requires a register of r16 -> r31)
625 adc r4,r16 ; add in rest of carry bits
626 adc r5,r16
627 clr r16 ; reset null register - does not need to be done if later code does
628 ; not assume a null register
629 ;
630 ; end function
631
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.