Counting cycles in disassembly - am I doing it right?

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi folks,

I'm driving shift registers in an interrupt. I'm using Binary Coded Modulation so the time between interrupts varies, but the shortest one is 256 cycles. I want to fine out how long I'm spending in my interrupt to see how many shift registers I could possibly add and wanted to check and see if I'm looking at the right thing.

Here's the C code for the ISR:

ISR(TIMER0_COMPA_vect){
  //Latch data loaded into the shift register on last interrupt
  ShiftPort |= latch;
  ShiftPort &= ~latch;

  //Set interrupt for next BCM delay value
  if (BCMtracker == 0) OCR0A = 0x01;
  else OCR0A <<= 1;

  //Increment the BCM tracking index
  BCMtracker ++;
  BCMtracker &= 7;	//Flip back to zero when it gets to 8 

  //Strobe in data for next time
  for (signed char channelAdjustment=(channels/8)-1; channelAdjustment>=0; channelAdjustment--){
    for (unsigned char i=0; i<8; i++){
    
      //Set data pin
      if (bcmBuffer[BCMtracker+(channelAdjustment*8)] & (1<<(7-i))) ShiftPort |= data;
      else ShiftPort &= ~data;

      //Toggle clock pin
      ShiftPort |= clock;
      ShiftPort &= ~clock;
    }
  }
  //Do not Latch, that will happen on the next interrupt  
}

Below is the disassembly for entire file which I got by running 'avr-objdump -d main.o'. I have no problem looking up the cycle length and summing that for all of the commands after "000000a4 <__vector_14>:" but I also want to know where the shifting routine starts and how long it takes.

Is there a way I can include comments in the C code that will show up in the disassembled object file? How about a way to show the assembly side-by-side with the C?

Thanks!

main.o:     file format elf32-avr


Disassembly of section .text:

00000000 :
   0:	0f 93       	push	r16
   2:	1f 93       	push	r17
   4:	cf 93       	push	r28
   6:	df 93       	push	r29
   8:	80 e0       	ldi	r24, 0x00	; 0
   a:	90 e0       	ldi	r25, 0x00	; 0
   c:	a1 e0       	ldi	r26, 0x01	; 1
   e:	b0 e0       	ldi	r27, 0x00	; 0
  10:	00 c0       	rjmp	.+0      	; 0x12 
  12:	16 95       	lsr	r17
  14:	61 91       	ld	r22, Z+
  16:	70 e0       	ldi	r23, 0x00	; 0
  18:	6c 23       	and	r22, r28
  1a:	7d 23       	and	r23, r29
  1c:	61 15       	cp	r22, r1
  1e:	71 05       	cpc	r23, r1
  20:	01 f0       	breq	.+0      	; 0x22 
  22:	10 68       	ori	r17, 0x80	; 128
  24:	0f 5f       	subi	r16, 0xFF	; 255
  26:	08 30       	cpi	r16, 0x08	; 8
  28:	01 f4       	brne	.+0      	; 0x2a 
  2a:	fa 01       	movw	r30, r20
  2c:	e0 50       	subi	r30, 0x00	; 0
  2e:	f0 40       	sbci	r31, 0x00	; 0
  30:	10 83       	st	Z, r17
  32:	28 5f       	subi	r18, 0xF8	; 248
  34:	3f 4f       	sbci	r19, 0xFF	; 255
  36:	48 5f       	subi	r20, 0xF8	; 248
  38:	5f 4f       	sbci	r21, 0xFF	; 255
  3a:	20 31       	cpi	r18, 0x10	; 16
  3c:	31 05       	cpc	r19, r1
  3e:	01 f0       	breq	.+0      	; 0x40 
  40:	f9 01       	movw	r30, r18
  42:	e0 50       	subi	r30, 0x00	; 0
  44:	f0 40       	sbci	r31, 0x00	; 0
  46:	00 e0       	ldi	r16, 0x00	; 0
  48:	10 e0       	ldi	r17, 0x00	; 0
  4a:	00 c0       	rjmp	.+0      	; 0x4c 
  4c:	01 96       	adiw	r24, 0x01	; 1
  4e:	88 30       	cpi	r24, 0x08	; 8
  50:	91 05       	cpc	r25, r1
  52:	01 f0       	breq	.+0      	; 0x54 
  54:	ed 01       	movw	r28, r26
  56:	08 2e       	mov	r0, r24
  58:	00 c0       	rjmp	.+0      	; 0x5a 
  5a:	cc 0f       	add	r28, r28
  5c:	dd 1f       	adc	r29, r29
  5e:	0a 94       	dec	r0
  60:	02 f4       	brpl	.+0      	; 0x62 
  62:	ac 01       	movw	r20, r24
  64:	20 e0       	ldi	r18, 0x00	; 0
  66:	30 e0       	ldi	r19, 0x00	; 0
  68:	00 c0       	rjmp	.+0      	; 0x6a 
  6a:	df 91       	pop	r29
  6c:	cf 91       	pop	r28
  6e:	1f 91       	pop	r17
  70:	0f 91       	pop	r16
  72:	08 95       	ret

00000074 
: 74: 8a b1 in r24, 0x0a ; 10 76: 80 6e ori r24, 0xE0 ; 224 78: 8a b9 out 0x0a, r24 ; 10 7a: 8b b1 in r24, 0x0b ; 11 7c: 8f 71 andi r24, 0x1F ; 31 7e: 8b b9 out 0x0b, r24 ; 11 80: 0e 94 00 00 call 0 ; 0x0 84: f8 94 cli 86: 84 b5 in r24, 0x24 ; 36 88: 82 60 ori r24, 0x02 ; 2 8a: 84 bd out 0x24, r24 ; 36 8c: 85 b5 in r24, 0x25 ; 37 8e: 84 60 ori r24, 0x04 ; 4 90: 85 bd out 0x25, r24 ; 37 92: 80 91 6e 00 lds r24, 0x006E 96: 82 60 ori r24, 0x02 ; 2 98: 80 93 6e 00 sts 0x006E, r24 9c: 81 e0 ldi r24, 0x01 ; 1 9e: 87 bd out 0x27, r24 ; 39 a0: 78 94 sei a2: 00 c0 rjmp .+0 ; 0xa4 <__vector_14> 000000a4 <__vector_14>: a4: 1f 92 push r1 a6: 0f 92 push r0 a8: 0f b6 in r0, 0x3f ; 63 aa: 0f 92 push r0 ac: 11 24 eor r1, r1 ae: 2f 93 push r18 b0: 3f 93 push r19 b2: 4f 93 push r20 b4: 5f 93 push r21 b6: 8f 93 push r24 b8: 9f 93 push r25 ba: ef 93 push r30 bc: ff 93 push r31 be: 5e 9a sbi 0x0b, 6 ; 11 c0: 5e 98 cbi 0x0b, 6 ; 11 c2: 80 91 00 00 lds r24, 0x0000 c6: 88 23 and r24, r24 c8: 01 f4 brne .+0 ; 0xca <__vector_14+0x26> ca: 81 e0 ldi r24, 0x01 ; 1 cc: 00 c0 rjmp .+0 ; 0xce <__vector_14+0x2a> ce: 87 b5 in r24, 0x27 ; 39 d0: 88 0f add r24, r24 d2: 87 bd out 0x27, r24 ; 39 d4: 80 91 00 00 lds r24, 0x0000 d8: 8f 5f subi r24, 0xFF ; 255 da: 87 70 andi r24, 0x07 ; 7 dc: 80 93 00 00 sts 0x0000, r24 e0: 88 e0 ldi r24, 0x08 ; 8 e2: 90 e0 ldi r25, 0x00 ; 0 e4: 00 c0 rjmp .+0 ; 0xe6 <__vector_14+0x42> e6: 40 91 00 00 lds r20, 0x0000 ea: fc 01 movw r30, r24 ec: e4 0f add r30, r20 ee: f1 1d adc r31, r1 f0: e0 50 subi r30, 0x00 ; 0 f2: f0 40 sbci r31, 0x00 ; 0 f4: 40 81 ld r20, Z f6: 50 e0 ldi r21, 0x00 ; 0 f8: 02 2e mov r0, r18 fa: 00 c0 rjmp .+0 ; 0xfc <__vector_14+0x58> fc: 55 95 asr r21 fe: 47 95 ror r20 100: 0a 94 dec r0 102: 02 f4 brpl .+0 ; 0x104 <__vector_14+0x60> 104: 40 ff sbrs r20, 0 106: 00 c0 rjmp .+0 ; 0x108 <__vector_14+0x64> 108: 5d 9a sbi 0x0b, 5 ; 11 10a: 00 c0 rjmp .+0 ; 0x10c <__vector_14+0x68> 10c: 5d 98 cbi 0x0b, 5 ; 11 10e: 5f 9a sbi 0x0b, 7 ; 11 110: 5f 98 cbi 0x0b, 7 ; 11 112: 21 50 subi r18, 0x01 ; 1 114: 30 40 sbci r19, 0x00 ; 0 116: 4f ef ldi r20, 0xFF ; 255 118: 2f 3f cpi r18, 0xFF ; 255 11a: 34 07 cpc r19, r20 11c: 01 f4 brne .+0 ; 0x11e <__vector_14+0x7a> 11e: 08 97 sbiw r24, 0x08 ; 8 120: 2f ef ldi r18, 0xFF ; 255 122: 88 3f cpi r24, 0xF8 ; 248 124: 92 07 cpc r25, r18 126: 01 f0 breq .+0 ; 0x128 <__vector_14+0x84> 128: 27 e0 ldi r18, 0x07 ; 7 12a: 30 e0 ldi r19, 0x00 ; 0 12c: 00 c0 rjmp .+0 ; 0x12e <__vector_14+0x8a> 12e: ff 91 pop r31 130: ef 91 pop r30 132: 9f 91 pop r25 134: 8f 91 pop r24 136: 5f 91 pop r21 138: 4f 91 pop r20 13a: 3f 91 pop r19 13c: 2f 91 pop r18 13e: 0f 90 pop r0 140: 0f be out 0x3f, r0 ; 63 142: 0f 90 pop r0 144: 1f 90 pop r1 146: 18 95 reti
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I usually do objdump -h -S file.elf
Did you use the -Os option when you compiled the whole thing? If not, I suggest you try it before counting anything.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oooh... thank you! I get a lot more usable information from there. Below is the output (just the ISR portion) of "avr-objdump -h -S main.elf" for anyone interested. I'm going to retire to my couch of solitude and study this for a bit.

ISR(TIMER0_COMPA_vect){
 14a:	1f 92       	push	r1
 14c:	0f 92       	push	r0
 14e:	0f b6       	in	r0, 0x3f	; 63
 150:	0f 92       	push	r0
 152:	11 24       	eor	r1, r1
 154:	2f 93       	push	r18
 156:	3f 93       	push	r19
 158:	4f 93       	push	r20
 15a:	5f 93       	push	r21
 15c:	8f 93       	push	r24
 15e:	9f 93       	push	r25
 160:	ef 93       	push	r30
 162:	ff 93       	push	r31
  //Latch data loaded into the shift register on last interrupt
  ShiftPort |= latch;
 164:	5e 9a       	sbi	0x0b, 6	; 11
  ShiftPort &= ~latch;
 166:	5e 98       	cbi	0x0b, 6	; 11

  //Set interrupt for next BCM delay value
  if (BCMtracker == 0) OCR0A = 0x01;
 168:	80 91 10 01 	lds	r24, 0x0110
 16c:	88 23       	and	r24, r24
 16e:	11 f4       	brne	.+4      	; 0x174 <__vector_14+0x2a>
 170:	81 e0       	ldi	r24, 0x01	; 1
 172:	02 c0       	rjmp	.+4      	; 0x178 <__vector_14+0x2e>
  else OCR0A <<= 1;
 174:	87 b5       	in	r24, 0x27	; 39
 176:	88 0f       	add	r24, r24
 178:	87 bd       	out	0x27, r24	; 39

  //Increment the BCM tracking index
  BCMtracker ++;
 17a:	80 91 10 01 	lds	r24, 0x0110
 17e:	8f 5f       	subi	r24, 0xFF	; 255
  BCMtracker &= 7;	//Flip back to zero when it gets to 8 
 180:	87 70       	andi	r24, 0x07	; 7
 182:	80 93 10 01 	sts	0x0110, r24
 186:	88 e0       	ldi	r24, 0x08	; 8
 188:	90 e0       	ldi	r25, 0x00	; 0
 18a:	21 c0       	rjmp	.+66     	; 0x1ce <__vector_14+0x84>
  //Strobe in data for next time
  for (signed char channelAdjustment=(channels/8)-1; channelAdjustment>=0; channelAdjustment--){
    for (unsigned char i=0; i<8; i++){
    
      //Set data pin
      if (bcmBuffer[BCMtracker+(channelAdjustment*8)] & (1<<(7-i))) ShiftPort |= data;
 18c:	40 91 10 01 	lds	r20, 0x0110
 190:	fc 01       	movw	r30, r24
 192:	e4 0f       	add	r30, r20
 194:	f1 1d       	adc	r31, r1
 196:	ef 5e       	subi	r30, 0xEF	; 239
 198:	fe 4f       	sbci	r31, 0xFE	; 254
 19a:	40 81       	ld	r20, Z
 19c:	50 e0       	ldi	r21, 0x00	; 0
 19e:	02 2e       	mov	r0, r18
 1a0:	02 c0       	rjmp	.+4      	; 0x1a6 <__vector_14+0x5c>
 1a2:	55 95       	asr	r21
 1a4:	47 95       	ror	r20
 1a6:	0a 94       	dec	r0
 1a8:	e2 f7       	brpl	.-8      	; 0x1a2 <__vector_14+0x58>
 1aa:	40 ff       	sbrs	r20, 0
 1ac:	02 c0       	rjmp	.+4      	; 0x1b2 <__vector_14+0x68>
 1ae:	5d 9a       	sbi	0x0b, 5	; 11
 1b0:	01 c0       	rjmp	.+2      	; 0x1b4 <__vector_14+0x6a>
      else ShiftPort &= ~data;
 1b2:	5d 98       	cbi	0x0b, 5	; 11

      //Toggle clock pin
      ShiftPort |= clock;
 1b4:	5f 9a       	sbi	0x0b, 7	; 11
      ShiftPort &= ~clock;
 1b6:	5f 98       	cbi	0x0b, 7	; 11
 1b8:	21 50       	subi	r18, 0x01	; 1
 1ba:	30 40       	sbci	r19, 0x00	; 0
  BCMtracker ++;
  BCMtracker &= 7;	//Flip back to zero when it gets to 8 

  //Strobe in data for next time
  for (signed char channelAdjustment=(channels/8)-1; channelAdjustment>=0; channelAdjustment--){
    for (unsigned char i=0; i<8; i++){
 1bc:	4f ef       	ldi	r20, 0xFF	; 255
 1be:	2f 3f       	cpi	r18, 0xFF	; 255
 1c0:	34 07       	cpc	r19, r20
 1c2:	21 f7       	brne	.-56     	; 0x18c <__vector_14+0x42>
 1c4:	08 97       	sbiw	r24, 0x08	; 8
  //Increment the BCM tracking index
  BCMtracker ++;
  BCMtracker &= 7;	//Flip back to zero when it gets to 8 

  //Strobe in data for next time
  for (signed char channelAdjustment=(channels/8)-1; channelAdjustment>=0; channelAdjustment--){
 1c6:	2f ef       	ldi	r18, 0xFF	; 255
 1c8:	88 3f       	cpi	r24, 0xF8	; 248
 1ca:	92 07       	cpc	r25, r18
 1cc:	19 f0       	breq	.+6      	; 0x1d4 <__vector_14+0x8a>
  {
    //Loop Forever
  }
}

ISR(TIMER0_COMPA_vect){
 1ce:	27 e0       	ldi	r18, 0x07	; 7
 1d0:	30 e0       	ldi	r19, 0x00	; 0
 1d2:	dc cf       	rjmp	.-72     	; 0x18c <__vector_14+0x42>
      ShiftPort |= clock;
      ShiftPort &= ~clock;
    }
  }
  //Do not Latch, that will happen on the next interrupt  
}
 1d4:	ff 91       	pop	r31
 1d6:	ef 91       	pop	r30
 1d8:	9f 91       	pop	r25
 1da:	8f 91       	pop	r24
 1dc:	5f 91       	pop	r21
 1de:	4f 91       	pop	r20
 1e0:	3f 91       	pop	r19
 1e2:	2f 91       	pop	r18
 1e4:	0f 90       	pop	r0
 1e6:	0f be       	out	0x3f, r0	; 63
 1e8:	0f 90       	pop	r0
 1ea:	1f 90       	pop	r1
 1ec:	18 95       	reti
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I also want to know where the shifting routine starts and how long it takes.
What exactly means "shifting routine"? The loop "for (unsigned char i=0; i<8; i++)"?
Hard to tell with the disassembly of unlinked code (so we don't see where the branches/jumps go to) and the nested loops. A short simulation says about 320 cycles. A major improvement would be the avoidance of the variable shift (1<<(7-i)).

    for (unsigned char i = 0x80; i; i >>= 1) {
   
      //Set data pin
      if (bcmBuffer[BCMtracker+(channelAdjustment*8)] & i) ShiftPort |= data;
      else ShiftPort &= ~data;
      ...

With this modification the loop takes about 140 cycles.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Sternst: You're right... here's my code repository (for future reference, here's a snapshot tag of it right at this moment).

I haven't done any hand optimization, but your technique is a nice tip. Thank you!

What software do you use to run simulations that measure cycles?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

barney_1 wrote:
What software do you use to run simulations that measure cycles?
AVR-Studio 4

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have not bothered to look at your disassembly. If you want to count cycles, use Studio4 Simulator.

But you are making life difficult for yourself. You can use SPI to clock out to the shift register. A HC595 can be clocked far faster than the AVR can manage anyway. ( 16 cycles for F_CPU/2 )

Not only that, but you can 'start off' the SPI in your Timer ISR(). You can be certain that the SPI will have completed before the next Timer ISR(). (test if you are paranoid)

If you really need to bit-bang your SPI, you can achieve ~128 cycles per byte in C. Compare this to 16 cycles with the hardware. Obviously you have a small overhead for handling /CS.

I know that you can get shorter than 128 cycles with ASM. (possibly 88 cycles). I would be interested in anyone getting much better than this. No way can you compete with the hardware SPI.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

If you really need to bit-bang your SPI, you can achieve ~128 cycles per byte in C. Compare this to 16 cycles with the hardware. Obviously you have a small overhead for handling /CS.

I know that you can get shorter than 128 cycles with ASM. (possibly 88 cycles). I would be interested in anyone getting much better than this. No way can you compete with the hardware SPI.


Hmmm-->>Now<< you've made it interesting.

128 cycles/byte; 16 per bit. 11 per bit in ASM.

Unroll the work for a byte. If using hardware SPI you have to get the data byte and stuff it into SPDR, so let's call the setup a wash.

Unrolled loop needs to present the data bit, SBI/CBI the clock, and prepare the next bit.

There was a discussion on this a while back and someone showed a clever XOR method to prepare the data so that it was a fixed time per bit to present to the data line.

We need to know what AVR model/generation we are working with. E.g., can we write to PINx to toggle the data (and/or clock) bit? Are the ports located in reach of SBI and cousins?

SBI/CBI are normally two cycles, so three of them give us 6 minimum per bit. Need 5 more to shift/prepare the next bit?

If the compiler can be coerced into a register variable for the data I can't think of why C might have a 5-cycle penalty.

digging for that past thread...

Lee

[edit] Dang, I cannot find that thread. It was a few months ago. I think unrolled it was SBI+CBI (4 clocks)for the clock, and SBRS/SBI for the data (3 clocks), and one for the shift (total of 8 clocks per bit).

There would be some prep and cleanup but that should be a wash.

In most cases the C compiler should be able to find a register for the data and there should be no penalty.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Lee,

I cannot find the clever routine either. All the same, no-one is going to bit-bash at 2 cycles per bit! (16 cycles per byte)

How about a competition to see how swift you can bit-bash? I will let you have a PINx writeable chip, and you can trash a whole PORTx for yourself.

Someone claimed 8 cycles per bit. I cannot see this is possible.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Someone claimed 8 cycles per bit. I cannot see this is possible.

(setup)
  in  rPort, PORTX
  ldi rClock, ClockBitMask

(unrolled bit)
  bst rData, x
  bld rPort, DataBitPos
  out PORTX, rPort
  out PINX, rClock
  out PINX, rClock

5 cycles per bit

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have done 3 cycles per bit, but that was for video, so it did not require toggling a clock output as well.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:
Quote:
Someone claimed 8 cycles per bit. I cannot see this is possible.

(setup)
  in  rPort, PORTX
  ldi rClock, ClockBitMask

(unrolled bit)
  bst rData, x
  bld rPort, DataBitPos
  out PORTX, rPort
  out PINX, rClock
  out PINX, rClock

5 cycles per bit


(setup)
  LDI Rdmask, 1<<DataBitPos
  LDI Rcmask, 1<<ClockBitPos
  MOV Rd, Rdata
  LSR Rd
  XOR Rd, Rdata
  CBI PORTdata, DataBitPos

(unrolled bit)
  SBRC Rd, x
  OUT PINdata, Rdmask
  OUT PINclock, Rcmask
  OUT PINclock, Rcmask

4 cycles per bit, but a lot more setup.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am impressed. I rather like the XOR version. 7 + 8x4 = 39 cycles.
sternst's example is 2 + 8x5 = 42 cycles.

If you only have two scratch registers, the XOR version will end up worse if you have to push and pop the third register.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can compete with the XOR version ;-)
(prerequisite: data and clock on the same port)

(setup)
  in  rPort, PORTX
  ldi rClock, ClockBitMask
  sbr/cbr rPort, ClockBitMask

(unrolled bit)
  bst rData, x
  bld rPort, DataBitPos
  out PORTX, rPort
  out PINX, rClock 

3 + 8x4 = 35 cycles

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I switched over to using SPI and it greatly simplifies my code. The only concern I have now is the blocking function recommended to wait for the SPI Interrupt Flag to be set:

while(!(SPSR & (1<<SPIF)))

Is that really an okay thing to do within an ISR? I looked around to see if I could find some documentation for how long this shifting process takes but I didn't see anything. Is there an appnote I'm missing?

I'm really just counting cycles so I can figure out my theoretical limit (how many bits I can shift using this method in 256 cycles). But now that the question is in my head I really want to know how to go about calculating this timing. Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You know how often the TIMER0_COMP interrupt fires.
You know how many cycles hardware SPI takes.

I will put money on your SPI always being complete before you enter he next TIMER0 interrupt. Think about it. Even if you have stacked interrupts, the basic ISR() response, preamble, post-amble, return will take almost 16 cycles. So I would not bother testing SPIF.

If you have a modern AVR, you can write 16 bits to the USART_SPI since it has a buffer. OTOH, you need to have a spare USART available.

If you really want to shift as many bits as possible within 256 cycles, the answer is 'almost' 128 bits. 96 bits is probably more realistic.

Life is a lot simpler if you just explain what you want to do. Video timing or Christmas lights?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are on a quest for least cycles, why are you invoking an ISR every "few" cycles? ISR overhead is minimum 12 cycles, and probably double that with what has been discussed.

I guess you are between a rock an a hard place if this update needs to be done continually. And if so, perhaps it is a good approach if this is all your AVR is doing. I can't help think, though, that there is more to it--like getting new commands, calculating new values, ...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.