62.5 Nanosecond Pulse Generator

Hello all. XD I have a need to test some pulsed laser diodes, specifically the Osram SPL LL85 which have a built-in MOSFET driver stage. This task requires a pulse lasting between 40 and 100ns at a 0.1% maximum duty cycle. Thus the 62.5ns single clock cycle time of the Arduino is nearly perfect.

Thus far, I have been able to pine down the pulses to triple that length using the following code.

int laser = 10;
int pulseOn = B00000100;
int pulseOff = B00000000;

void setup() {
  // setup:
  pinMode(laser, OUTPUT);
  PORTB = B00000000;
}

void loop() {
  // main loop: 
  PORTB = pulseOn;
  PORTB = pulseOff;
  delay(1);
}

Compiling this results in the following opcodes.

knoppix@Microknoppix:/tmp/build8787306317458512415.tmp$ avr-objdump -d ns_Pulser.cpp.o

ns_Pulser.cpp.o:     file format elf32-avr


Disassembly of section .text.setup:

00000000 <setup>:
   0:	61 e0       	ldi	r22, 0x01	; 1
   2:	80 91 00 00 	lds	r24, 0x0000
   6:	0e 94 00 00 	call	0	; 0x0 <setup>
   a:	15 b8       	out	0x05, r1	; 5
   c:	08 95       	ret

Disassembly of section .text.loop:

00000000 <loop>:
   0:	80 91 00 00 	lds	r24, 0x0000
   4:	85 b9       	out	0x05, r24	; 5
   6:	80 91 00 00 	lds	r24, 0x0000
   a:	85 b9       	out	0x05, r24	; 5
   c:	61 e0       	ldi	r22, 0x01	; 1
   e:	70 e0       	ldi	r23, 0x00	; 0
  10:	80 e0       	ldi	r24, 0x00	; 0
  12:	90 e0       	ldi	r25, 0x00	; 0
  14:	0c 94 00 00 	jmp	0	; 0x0 <loop>
knoppix@Microknoppix:/tmp/build8787306317458512415.tmp$

As you can see, the "meat" of the operation is an lds followed by an out and another lds and out, resulting in the aforementioned 187.5ns pulse. I'm hoping to get this down to something like

lds r25 0x0000
lds r24 0x0000
out 0x05, r25
out 0x05, r24

I could code this directly in ASM, but I'm not familiar with the peculiarities of the AVR. Also, if other people need to use this functionality someday, it would be beneficial to have ino format source code. Any help is much appreciated.

You could probably make a circuit to deliver the 62.5 nsec pulse you want.

You will never do it using Arduino finctions (or any functions for that matter). Try some inline assembly

#define PULSE	asm("sbi 5,0\ncbi 5,0");  // PORTB bit 0, 328 Arduino D8

I used to use this to generate a debugging pulse, it should be one cycle.

Note, SBI = set bit, CBI = clear bit, 5 = address of PORTB, 0 = bit number


Rob

Thank you. That is exactly what I was looking for. :grin:

Graynomad:
You will never do it using Arduino finctions (or any functions for that matter). Try some inline assembly

Assembly not always needed, for instance to put out 62.5ns pulses on pin 2 (Uno):

void setup ()
{
  DDRD |= 4 ; // pin 2 set to output - 4 == 1<<2
}

void loop ()
{
  PIND = 4 ;  // toggle pin 2 with 1 instruction
  PIND = 4 ;  // toggle pin 2 with 1 instruction
  delayMicroseconds (2) ;
}

But I think this only works for pins with a low bit number so that the
constant is an immediate field in the instruction. A 1 written to the port
input registers (PINx) actually toggles the relevant bit in the output
register (PORTx) on ATmega microcontrollers.

Note that the register / pin assignments are completely different on the Mega
Arduinos, and this only applies to ATmega family of chips.

Thanks Mark. You have indeed saved the day. That code does exactly what I need. Here is my sketch in its current configuration.

int laser = 2;

void setup() {
  // setup:
  pinMode(laser, OUTPUT);
  noInterrupts();          // disable interrupts just in case
}

void loop() {
  // main loop: 
  PIND = B00000100;        // writing to the pin register toggles
  PIND = B00000100;        // output on ATmega microcontrollers
  delayMicroseconds(100);
}

LS, do you know hex?

Do you really mean nanoseconds that's 10 to the -9 not micro (10 to the -6)!.

Mark

1 sec / 16000000 = 1 usec / 16 hence the 62.5 nanos