Can i tell the pre-compiler to not optimize out a loop ?

The issue is as follows, i am using an ATtiny13a to test for a minimum period in which there is no logical pin change using external interrupts (INT0), I am looking for a 'break' in the signal of about 80us or less, but i want to take action as soon as this condition is true.
It works, but in the while loop i need to make at least 'a' call to delayMicroseconds() for the while loop to be compiled at all, even though the execution of testing the condition takes 1us (about i think it's 10 clock cycles or thereabouts) , even with just a single NOP inserted (that would make 11) it requires me to drop the test to less than once per microsecond. Can i tell the compiler to compile the loop anyway even if it doesn't make sense ?
(adding delayMicroseconds(1) adds brne -4 + 2 NOPs so that would be 8 cycles, ideally i would not want any delay at all.

#include <avr/io.h>
#include <avr/interrupt.h>

#define _USENOP_

#define OUTPIN PB4  // PB0 is the other option

#if defined _USENOP_

#define CLICKS 70

/*asm(".MACRO Delay\n\t\n\t"
    ".rept 2\n\t"
    "NOP\n\t"
    ".endr\n\t"
    ".ENDM");
*/

asm(".MACRO Delay\n\t\n\t"
    "NOP\n\t"
    "NOP\n\t"
    ".ENDM");
    
#else

#define MICS 45  // 45 responds to 88us
#define CHUNKS 1
#define CLICKS (MICS / CHUNKS)

#endif


volatile uint8_t count = 0;

ISR (INT0_vect) {
  count = 0;
}

void setup() {
  noInterrupts();
  DDRB |= (1 << OUTPIN);  // PB0 OUTPUT
  DDRB &= ~(1 << PB1); // PB1 INPUT
  GIMSK |= (1 << INT0); // Enable INT0 interrupt
  //  ISCO1 ISCO0
  //    0     0     The LOW level of INT0 calls ISR
  //    0     1     any logical change
  //    1     0     Falling edge
  //    1     1     Rising edge
  /*MCUCR |= (1 << ISC01);  //   set for falling edge
    MCUCR &= ~(1 << ISC00);*/

  MCUCR &= ~(1 << ISC01); //   set for logical change
  MCUCR |= (1 << ISC00);
  interrupts();
}

void loop() {
  static bool pinhigh = true;

  while (count < CLICKS) {
    count++;
#if defined _USENOP_
    //asm("Delay");
    asm("NOP\n\t");
#else
    delayMicroseconds(CHUNKS);
#endif
  }
  pinhigh = !pinhigh;
  if (pinhigh) {
    PORTB |= (1 << OUTPIN);
  }
  else {
    PORTB &= ~(1 << OUTPIN);
  }
  while (count) {
    delayMicroseconds(1);
  }
}

note : i left some of the development in just for testing

What language is that?

That is part of the assembler macro implementation, found it somewhere, creates an assembler macro called 'Delay' that you can call using

asm("Delay");

which replaces that line with

asm("NOP\n\t"
    "NOP\n\t");

Not used atm, commented out, but rather practical i thought.

Then you have to do your own calculation and call delayMicroseconds() only with a delay greater than the implemented minimum time.

What do you mean by that ?
if i call delayMicroseconds() it will calculate the number of NOPs and add that to the compiled code, the minimum time is 1, and that results is 1 NOP cycled through 4 times, probably adding another cycle, I don't want any NOPs but i want the while loop to be compiled.
This is what the .lst file looks like


C:\Users\deva_\AppData\Local\Temp\arduino_build_136565/interrupt_findbreak.ino.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
__vectors():
   0:	09 c0       	rjmp	.+18     	; 0x14 <__ctors_end>
   2:	52 c0       	rjmp	.+164    	; 0xa8 <__vector_1>
   4:	50 c0       	rjmp	.+160    	; 0xa6 <__bad_interrupt>
   6:	4f c0       	rjmp	.+158    	; 0xa6 <__bad_interrupt>
   8:	4e c0       	rjmp	.+156    	; 0xa6 <__bad_interrupt>
   a:	4d c0       	rjmp	.+154    	; 0xa6 <__bad_interrupt>
   c:	4c c0       	rjmp	.+152    	; 0xa6 <__bad_interrupt>
   e:	4b c0       	rjmp	.+150    	; 0xa6 <__bad_interrupt>
  10:	4a c0       	rjmp	.+148    	; 0xa6 <__bad_interrupt>
  12:	49 c0       	rjmp	.+146    	; 0xa6 <__bad_interrupt>

00000014 <__ctors_end>:
__trampolines_start():
  14:	11 24       	eor	r1, r1
  16:	1f be       	out	0x3f, r1	; 63
  18:	cf e9       	ldi	r28, 0x9F	; 159
  1a:	cd bf       	out	0x3d, r28	; 61

0000001c <__do_copy_data>:
__do_copy_data():
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2409
  1c:	10 e0       	ldi	r17, 0x00	; 0
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2410
  1e:	a0 e6       	ldi	r26, 0x60	; 96
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2411
  20:	b0 e0       	ldi	r27, 0x00	; 0
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2412
  22:	e4 ec       	ldi	r30, 0xC4	; 196
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2413
  24:	f0 e0       	ldi	r31, 0x00	; 0
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2414
  26:	02 c0       	rjmp	.+4      	; 0x2c <__do_copy_data+0x10>
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2417
  28:	05 90       	lpm	r0, Z+
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2422
  2a:	0d 92       	st	X+, r0
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2424
  2c:	a2 36       	cpi	r26, 0x62	; 98
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2425
  2e:	b1 07       	cpc	r27, r17
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2426
  30:	d9 f7       	brne	.-10     	; 0x28 <__do_copy_data+0xc>

00000032 <__do_clear_bss>:
__do_clear_bss():
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2441
  32:	20 e0       	ldi	r18, 0x00	; 0
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2442
  34:	a2 e6       	ldi	r26, 0x62	; 98
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2443
  36:	b0 e0       	ldi	r27, 0x00	; 0
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2444
  38:	01 c0       	rjmp	.+2      	; 0x3c <.do_clear_bss_start>

0000003a <.do_clear_bss_loop>:
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2446
  3a:	1d 92       	st	X+, r1

0000003c <.do_clear_bss_start>:
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2448
  3c:	a3 36       	cpi	r26, 0x63	; 99
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2449
  3e:	b2 07       	cpc	r27, r18
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2450
  40:	e1 f7       	brne	.-8      	; 0x3a <.do_clear_bss_loop>
.do_clear_bss_start():
  42:	01 d0       	rcall	.+2      	; 0x46 <main>
  44:	3d c0       	rjmp	.+122    	; 0xc0 <_exit>

00000046 <main>:
init():
C:\Users\deva_\AppData\Local\Arduino15\packages\MicroCore\hardware\avr\2.1.0\cores\microcore/wiring.c:164
    // Set timer0 couter to zero
    TCNT0 = 0;
  #endif

  // Turn on global interrupts
  sei();
  46:	78 94       	sei
setup():
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:17
ISR (INT0_vect) {
  count = 0;
}

void setup() {
  noInterrupts();
  48:	f8 94       	cli
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:18
  DDRB |= (1 << OUTPIN);  // PB0 OUTPUT
  4a:	bc 9a       	sbi	0x17, 4	; 23
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:19
  DDRB &= ~(1 << PB1); // PB1 INPUT
  4c:	b9 98       	cbi	0x17, 1	; 23
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:20
  GIMSK |= (1 << INT0); // Enable INT0 interrupt
  4e:	8b b7       	in	r24, 0x3b	; 59
  50:	80 64       	ori	r24, 0x40	; 64
  52:	8b bf       	out	0x3b, r24	; 59
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:29
  //    1     0     Falling edge
  //    1     1     Rising edge
  /*MCUCR |= (1 << ISC01);  //   set for falling edge
  MCUCR &= ~(1 << ISC00);*/
  
  MCUCR &= ~(1 << ISC01); //   set for logical change
  54:	85 b7       	in	r24, 0x35	; 53
  56:	8d 7f       	andi	r24, 0xFD	; 253
  58:	85 bf       	out	0x35, r24	; 53
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:30
  MCUCR |= (1 << ISC00);  
  5a:	85 b7       	in	r24, 0x35	; 53
  5c:	81 60       	ori	r24, 0x01	; 1
  5e:	85 bf       	out	0x35, r24	; 53
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:31
  interrupts();
  60:	78 94       	sei
loop():
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:41

  while (count < CLICKS) {
    count++;
    delayMicroseconds(CHUNKS);  
  }
  pinhigh = !pinhigh;
  62:	91 e0       	ldi	r25, 0x01	; 1
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:37
}

void loop() {
  static bool pinhigh = true;

  while (count < CLICKS) {
  64:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  68:	8d 32       	cpi	r24, 0x2D	; 45
  6a:	50 f4       	brcc	.+20     	; 0x80 <main+0x3a>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:38
    count++;
  6c:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  70:	8f 5f       	subi	r24, 0xFF	; 255
  72:	80 93 62 00 	sts	0x0062, r24	; 0x800062 <__data_end>
_delay_us():
c:\users\deva_\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\util/delay.h:276
	#else
		//round up by default
		__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
	#endif

	__builtin_avr_delay_cycles(__ticks_dc);
  76:	83 e0       	ldi	r24, 0x03	; 3
  78:	8a 95       	dec	r24
  7a:	f1 f7       	brne	.-4      	; 0x78 <main+0x32>
  7c:	00 00       	nop
  7e:	f2 cf       	rjmp	.-28     	; 0x64 <main+0x1e>
loop():
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:41
    delayMicroseconds(CHUNKS);  
  }
  pinhigh = !pinhigh;
  80:	80 91 60 00 	lds	r24, 0x0060	; 0x800060 <__DATA_REGION_ORIGIN__>
  84:	89 27       	eor	r24, r25
  86:	80 93 60 00 	sts	0x0060, r24	; 0x800060 <__DATA_REGION_ORIGIN__>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:42
  if (pinhigh) {
  8a:	88 23       	and	r24, r24
  8c:	51 f0       	breq	.+20     	; 0xa2 <__stack+0x3>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:43
    PORTB |= (1 << OUTPIN);
  8e:	c4 9a       	sbi	0x18, 4	; 24
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:48
  }
  else {
    PORTB &= ~(1 << OUTPIN);
  }
  while (count) {
  90:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  94:	88 23       	and	r24, r24
  96:	31 f3       	breq	.-52     	; 0x64 <main+0x1e>
_delay_us():
c:\users\deva_\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\util/delay.h:276
  98:	83 e0       	ldi	r24, 0x03	; 3
  9a:	8a 95       	dec	r24
  9c:	f1 f7       	brne	.-4      	; 0x9a <main+0x54>
  9e:	00 00       	nop
  a0:	f7 cf       	rjmp	.-18     	; 0x90 <main+0x4a>
loop():
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:46
  pinhigh = !pinhigh;
  if (pinhigh) {
    PORTB |= (1 << OUTPIN);
  }
  else {
    PORTB &= ~(1 << OUTPIN);
  a2:	c4 98       	cbi	0x18, 4	; 24
  a4:	f5 cf       	rjmp	.-22     	; 0x90 <main+0x4a>

000000a6 <__bad_interrupt>:
__bad_interrupt():
  a6:	ac cf       	rjmp	.-168    	; 0x0 <__vectors>

000000a8 <__vector_1>:
__vector_1():
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:12
#define CHUNKS 1
#define CLICKS (MICS / CHUNKS)

volatile uint8_t count = 0;

ISR (INT0_vect) {
  a8:	1f 92       	push	r1
  aa:	0f 92       	push	r0
  ac:	0f b6       	in	r0, 0x3f	; 63
  ae:	0f 92       	push	r0
  b0:	11 24       	eor	r1, r1
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:13
  count = 0;
  b2:	10 92 62 00 	sts	0x0062, r1	; 0x800062 <__data_end>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:14
}
  b6:	0f 90       	pop	r0
  b8:	0f be       	out	0x3f, r0	; 63
  ba:	0f 90       	pop	r0
  bc:	1f 90       	pop	r1
  be:	18 95       	reti

000000c0 <_exit>:
exit():
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2278
  c0:	f8 94       	cli

000000c2 <__stop_program>:
__stop_program():
/home/jenkins-mingw32/workspace/avr-gcc-staging/label/Ubuntu14.04x64-mingw32/gcc-build/avr/avr25/tiny-stack/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2280
  c2:	ff cf       	rjmp	.-2      	; 0xc2 <__stop_program>

the relevant section is here

  while (count < CLICKS) {
  64:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  68:	8d 32       	cpi	r24, 0x2D	; 45
  6a:	50 f4       	brcc	.+20     	; 0x80 <main+0x3a>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:38
    count++;
  6c:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  70:	8f 5f       	subi	r24, 0xFF	; 255
  72:	80 93 62 00 	sts	0x0062, r24	; 0x800062 <__data_end>
_delay_us():
c:\users\deva_\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\util/delay.h:276
	#else
		//round up by default
		__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
	#endif

	__builtin_avr_delay_cycles(__ticks_dc);
  76:	83 e0       	ldi	r24, 0x03	; 3
  78:	8a 95       	dec	r24
  7a:	f1 f7       	brne	.-4      	; 0x78 <main+0x32>
  7c:	00 00       	nop
  7e:	f2 cf       	rjmp	.-28     	; 0x64 <main+0x1e>

whereas with just a NOP it looks like this

C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:64
#if defined _USENOP_
    //asm("Delay");
    asm("NOP\n\t");
  76:	00 00       	nop
  78:	f5 cf       	rjmp	.-22     	; 0x64 <main+0x1e>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:69
#else
    delayMicroseconds(CHUNKS);
#endif
  }
  pinhigh = !pinhigh;

which is just a single NOP
Hmm maybe it does compile it after all, this is the result of the commented out NOP

  while (count < CLICKS) {
  64:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  68:	86 34       	cpi	r24, 0x46	; 70
  6a:	30 f4       	brcc	.+12     	; 0x78 <main+0x32>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:61
    count++;
  6c:	80 91 62 00 	lds	r24, 0x0062	; 0x800062 <__data_end>
  70:	8f 5f       	subi	r24, 0xFF	; 255
  72:	80 93 62 00 	sts	0x0062, r24	; 0x800062 <__data_end>
  76:	f6 cf       	rjmp	.-20     	; 0x64 <main+0x1e>
C:\Data\Arduino\Sketches\ATtiny\interrupt_findbreak/interrupt_findbreak.ino:69
    //asm("NOP\n\t");
#else
    delayMicroseconds(CHUNKS);
#endif
  }

Maybe it doesn't get optimized out and i was mistaken to begin with. Still the question remains, how to make the compiler compiler code that is considered useless by the pre-compiler ?

Not sure what you mean by "pre-compiler", all compilation phases are in the compiler, the pre-processor does not do any optimization.

The C++ standard allows quite a lot of leeway to a compiler, the general principle is "equivalent effect". If the compiler determines there code that has no effect, it can remove it. By marking your variable as volatile, that forces the compiler to generate code that does have an effect. Generally turning off optimization avoids elimination of code.

Otherwise you can sometimes trick the compiler to defect optimization, e.g. by making a function where the compiler can't predict the result. These sort of tricks are rather crude, and can depend on particular conditions which may not hold (e.g. if you install a new version of the compiler).

Ultimately if you need cycle accurate control of execution the best method is probably to use assembler.

1 Like

But that may result in slower code, the variable must now always be read from the memory address rather than taken from a register it may already be in, but yes that does do the trick somehow i guess.

You can simply use the
#pragma GCC optimize ...
directive to tell the compiler which optimization to use ( or do no optimization at all ). This overwrites the optimization parameters that have been set when calling gcc from the commandline.

1 Like

So what options do i have ?

The same as on the commandline

#pragma GCC optimize "O0"  // no optimization ( possible numbers are from 0...3 )
#pragma GCC optimize "Os"  // optimize for size
#pragma GCC optimize "Ofast"  // may make your code faster ;-)

[EDIT] I'm not quite shure if "O0" really does no optimizations. At least it is the lowest level. Maybe it does very obvious optimizations anyway - you have to try.

1 Like

why do you think that? Your "count" variable is volatile, which should mean that its updating is forced for each loop, and indeed the code produce without either delay or nops still loops:

void loop() {
  static bool pinhigh = true;

  while (count < CLICKS) {
  5c:   80 91 62 00     lds     r24, 0x0062     ;;; load volatile count
  60:   86 34           cpi     r24, 0x46       ;;; compare
  62:   30 f4           brcc    .+12            ;;;  branch out of loop if less
    count++;
  64:   80 91 62 00     lds     r24, 0x0062     ;;; load volatile again  (that's the way it works!)
  68:   8f 5f           subi    r24, 0xFF       ;;; increment
  6a:   80 93 62 00     sts     0x0062, r24     ;;; store incremented value
  6e:   f6 cf           rjmp    .-20            ;;; go back to while loop
    delayMicroseconds(CHUNKS);
#else
#warning no loop filler
#endif
  }
  pinhigh = !pinhigh;
  70:   80 91 60 00     lds     r24, 0x0060     ; 0x800060 <__DATA_REGION_ORIGIN__>
  74:   89 27           eor     r24, r25
  76:   80 93 60 00     sts     0x0060, r24     ; 0x800060 <__DATA_REGION_ORIGIN__>
  if (pinhigh) {
  7a:   88 23           and     r24, r24
  7c:   11 f0           breq    .+4             ; 0x82 <__SREG__+0x43>
    PORTB |= (1 << OUTPIN);
  7e:   c4 9a           sbi     0x18, 4 ; 24
  80:   01 c0           rjmp    .+2             ; 0x84 <__SREG__+0x45>
  }

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.