Cannot get digitalWrite fast with ATTinyCore

I'm using ATTinyCore V 1.5.2 fpr am Attiny 84a. I've tried variations and some versions of in line assy with out luck.

Does the ATTinyCore have a fast digital read or write? If so can someone post the syntax?

Is there a better way to gain speed by port/pin manipulation?

Thanks
John

What is the meaning of fast digialWrite()/digitalRead()?

@JohnRob is likely referring to GitHub - NicksonYap/digitalWriteFast: Arduino library for faster digitalWrite using port manipulation and macro for ease in pin assignments.

The doc states

Compatibility

  • Arduino Due
  • Arduino Zero
  • Arduino Mega
  • Arduino with ATmega644 or Atmega644P chip
  • Arduino Leonardo
  • Arduino Uno (I have only tested with uno)

If not in the list, the macro will revert back to digitalWrite(), pinMode() or digitalRead()

Maybe doc like this can help

The fastest way I know is direct port manipulation like:

void setup() {
  DDRB |= _BV(PB0);//PB0 as output
}

void loop() {
  if (PINB & _BV(PB3)) {// true if PB3 is HIGH
    PORTB |= _BV(PB0); // set output HIGH
    delay(500);
    PORTB &= ~_BV(PB0); // set output LOW
    delay(500);
  }
}

The modern attinies (MegatinyCore) have DigitalwriteFast and PinmodeFast, that compile to a single instruction, but I never heard of the old Attinies having something similar.

[EDIT]

I did a little test to see how the port manipulation compiles.

I compiled this: ( note: I did not care delay() is not working without setup and loop)

int main(void) {
  DDRB |= _BV(PB0);//PB0 as output
  while (1) {
    if (PINB & _BV(PB3)) {// true if PB3 is HIGH
      PORTB |= _BV(PB0); // set output HIGH
      delay(500);
      PORTB &= ~_BV(PB0); // set output LOW
      delay(500);
    }
  }
}

And the port manipulation lines also seem to compile to a single instruction
See lines 30: 36: and 4a: in the compile listing is below:

Disassembly of section .text:

00000000 <__vectors>:
__vectors():
   0:	0e c0       	rjmp	.+28     	; 0x1e <__ctors_end>
   2:	15 c0       	rjmp	.+42     	; 0x2e <__bad_interrupt>
   4:	14 c0       	rjmp	.+40     	; 0x2e <__bad_interrupt>
   6:	13 c0       	rjmp	.+38     	; 0x2e <__bad_interrupt>
   8:	12 c0       	rjmp	.+36     	; 0x2e <__bad_interrupt>
   a:	11 c0       	rjmp	.+34     	; 0x2e <__bad_interrupt>
   c:	10 c0       	rjmp	.+32     	; 0x2e <__bad_interrupt>
   e:	0f c0       	rjmp	.+30     	; 0x2e <__bad_interrupt>
  10:	0e c0       	rjmp	.+28     	; 0x2e <__bad_interrupt>
  12:	0d c0       	rjmp	.+26     	; 0x2e <__bad_interrupt>
  14:	0c c0       	rjmp	.+24     	; 0x2e <__bad_interrupt>
  16:	0b c0       	rjmp	.+22     	; 0x2e <__bad_interrupt>
  18:	0a c0       	rjmp	.+20     	; 0x2e <__bad_interrupt>
  1a:	09 c0       	rjmp	.+18     	; 0x2e <__bad_interrupt>
  1c:	08 c0       	rjmp	.+16     	; 0x2e <__bad_interrupt>

0000001e <__ctors_end>:
__trampolines_start():
  1e:	11 24       	eor	r1, r1
  20:	1f be       	out	0x3f, r1	; 63
  22:	cf e5       	ldi	r28, 0x5F	; 95
  24:	d1 e0       	ldi	r29, 0x01	; 1
  26:	de bf       	out	0x3e, r29	; 62
  28:	cd bf       	out	0x3d, r28	; 61
  2a:	02 d0       	rcall	.+4      	; 0x30 <main>
  2c:	19 c0       	rjmp	.+50     	; 0x60 <_exit>

0000002e <__bad_interrupt>:
__vector_1():
  2e:	e8 cf       	rjmp	.-48     	; 0x0 <__vectors>

00000030 <main>:
main():
E:\Arduino\arduino-1.8.13 - attinycore\portable\sketchbook\portmanipulationtest/portmanipulationtest.ino:2
int main(void) {
  DDRB |= _BV(PB0);//PB0 as output
  30:	b8 9a       	sbi	0x17, 0	; 23
E:\Arduino\arduino-1.8.13 - attinycore\portable\sketchbook\portmanipulationtest/portmanipulationtest.ino:4
  while (1) {
    if (PINB & _BV(PB3)) {// true if PB3 is HIGH
  32:	b3 9b       	sbis	0x16, 3	; 22
  34:	fe cf       	rjmp	.-4      	; 0x32 <main+0x2>
E:\Arduino\arduino-1.8.13 - attinycore\portable\sketchbook\portmanipulationtest/portmanipulationtest.ino:5
      PORTB |= _BV(PB0); // set output HIGH
  36:	c0 9a       	sbi	0x18, 0	; 24
_delay_ms():
e:\arduino\arduino-1.8.13 - attinycore\hardware\tools\avr\avr\include\util/delay.h:187
	#else
		//round up by default
		__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
	#endif

	__builtin_avr_delay_cycles(__ticks_dc);
  38:	2f ef       	ldi	r18, 0xFF	; 255
  3a:	84 e3       	ldi	r24, 0x34	; 52
  3c:	9c e0       	ldi	r25, 0x0C	; 12
  3e:	21 50       	subi	r18, 0x01	; 1
  40:	80 40       	sbci	r24, 0x00	; 0
  42:	90 40       	sbci	r25, 0x00	; 0
  44:	e1 f7       	brne	.-8      	; 0x3e <__SP_H__>
  46:	00 c0       	rjmp	.+0      	; 0x48 <__SREG__+0x9>
  48:	00 00       	nop
main():
E:\Arduino\arduino-1.8.13 - attinycore\portable\sketchbook\portmanipulationtest/portmanipulationtest.ino:7
      delay(500);
      PORTB &= ~_BV(PB0); // set output LOW
  4a:	c0 98       	cbi	0x18, 0	; 24
_delay_ms():
e:\arduino\arduino-1.8.13 - attinycore\hardware\tools\avr\avr\include\util/delay.h:187
  4c:	2f ef       	ldi	r18, 0xFF	; 255
  4e:	84 e3       	ldi	r24, 0x34	; 52
  50:	9c e0       	ldi	r25, 0x0C	; 12
  52:	21 50       	subi	r18, 0x01	; 1
  54:	80 40       	sbci	r24, 0x00	; 0
  56:	90 40       	sbci	r25, 0x00	; 0
  58:	e1 f7       	brne	.-8      	; 0x52 <__SREG__+0x13>
  5a:	00 c0       	rjmp	.+0      	; 0x5c <__SREG__+0x1d>
  5c:	00 00       	nop
  5e:	e9 cf       	rjmp	.-46     	; 0x32 <main+0x2>

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

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

In the ATTinyCore Github page Spence was talking about implementing a "FastDataWrite()" or perhaps "DataWriteFast()" with their complimentary read functions.
However, either it was never implemented or I just couldn't find how to use it properly.

Thank you!

With your suggested code I can get a pulse as low as 1µs.

I'm powering a strip of LED's installed under the overhang on our stairway. Its a simple eBay COB 12V strip but its so bright I need a very short on time (period is 240 Hz). I could probably get by with 6 or 7 µs. I don't want to go below the 240 Hz as it gets into the area where blinking may be perceived.

Thanks again
John

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