nanoseconds

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

nanoseconds

Post by ulao » Tue Jul 14, 2009 4:18 am

This may be a really dumb question, but I have to ask. Is there anyway to get down to a nanosecond with a 12 mhz? I some how need to get .25 us. OR for that matter what is the amount of time one instruction ( comparison) of code elapses?

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Re: nanoseconds

Post by Grendel » Tue Jul 14, 2009 8:05 am

One clock period at 12MHz is 83.33ns (1/f). Instruction timings can be found here. avr-libc comes w/ a macro for small delays -- void _delay_us( double __us ), ustil/delay.h

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: nanoseconds

Post by ulao » Tue Jul 14, 2009 2:04 pm

So with C I could then write _delay_us( 0.25 ) and this should give my 250 ns?

Or do I need a nop? __asm__("nop\n\t""nop\n\t""nop\n\t"); 3 nops = 250 ns?

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Re: nanoseconds

Post by Grendel » Tue Jul 14, 2009 9:41 pm

ulao wrote:So with C I could then write _delay_us( 0.25 ) and this should give my 250 ns?

Yes, but keep the resolution (1/f) in mind. I would use the three nop's tho since results in exactly 250ns.

horo
Rank 2
Rank 2
Posts: 63
Joined: Tue Mar 04, 2008 2:26 pm
Location: Berlin & Lindau, Germany

Re: nanoseconds

Post by horo » Wed Jul 15, 2009 9:31 am

FROM avr-libc manual:
void _delay_us ( double __us )
Perform a delay of __us microseconds, using _delay_loop_1().

void _delay_loop_1 ( uint8_t __count )
Delay loop using an 8-bit counter __count, so up to 256 iterations are possible. (The value 256 would have to be passed as 0.) The loop executes three CPU cycles per iteration, not including the overhead the compiler needs to setup the counter register.

You will have overhead from calling the function too - use "nop nop nop" !

Ciao Martin

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Re: nanoseconds

Post by Grendel » Wed Jul 15, 2009 9:50 am

horo wrote:You will have overhead from calling the function too [..]

Nope, it's an inline macro.

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: nanoseconds

Post by ulao » Wed Jul 15, 2009 2:22 pm

Grendel wrote:Nope, it's an inline macro.
Yeah I recently learned the wonders of inline and speed. WOW.


Ok so it turns out out to be able to time this pattern I need to use all ASM. I'm trying to learn asm for the first time. I'm using asm code in c, not an S file but having learning struggles. Any tips, advice or, tuts that would help specific to avr asm calls? I have learned how to get data from a port and dump to a register, and take a bit from that register put on a other registers bit. But for the life of me a can not get this register to a usable variable in my code.

Here is what I want to do . Data will be coming across PB5 as a vary fast rate. I need to grab the current condition ( hi/low) and store it in a var for later use all with in a few nops. Later ( after the asm )I need to use that var.

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Re: nanoseconds

Post by Grendel » Wed Jul 15, 2009 8:31 pm

ulao wrote:Here is what I want to do . Data will be coming across PB5 as a vary fast rate. I need to grab the current condition ( hi/low) and store it in a var for later use all with in a few nops. Later ( after the asm )I need to use that var.

avr-libc gives you native C access to all the registers, I don't think you'll need an inline assembler at all for that. Something like

Code: Select all

#include <avr/io.h>

uint8_t
    arr[n], i, *p ;

for ( i = n, p = arry ; i-- ; )
{
    *p++ = PINB ;
    asm ("nop\n\t" ) ; // may not be necessary
}

should do nicely. Check out the *.lss file created by the compiler to verify the timing, fine tune w/ nops accordingly.

For a in-depth discussion of the asm interface check out the file doc/gcc/HTML/gcc-4.3.2/gcc/Extended-Asm.html in the directory where you installed WinAvr (should be the same for avr-gcc).

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: nanoseconds

Post by ulao » Mon Jul 20, 2009 10:13 pm

If I'm working with NS timing, will the usb interrupt get in the way?

Assuming yes.. I know I can disable it and I get 20 cycles before I must re enable but I need to do some NS work for a bit more then that. I'm reading 32 bits of data and they are 6 NS apart. Not sure but I may be able to watch for a falling edge to time it better. If I can figure out how to do that in asm.

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Re: nanoseconds

Post by Grendel » Tue Jul 21, 2009 10:44 am

Any chance you could "miss"-use the SPI interface for reading those bits ?

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: nanoseconds

Post by ulao » Tue Jul 21, 2009 2:32 pm

You know I thought about this after seeing the psx2 project. Personally I feel the SPI could be used for this but not sure how I could get it to work. The device I'm talking to uses a two line async serial bus. The two serial data lines alternate between clock and data every bit.
Would I be able to sample and talk to two lines with it?

here is the signal I'm trying t read.

Image

If my thoughts are right maybe I could use a 1 bit buffer sampling SDCKA 6 cycles Prior to a watch for a falling edge on SDCKB, and when it sees one, read both the current bit on SDCKB and the buffered bit SDCKA. This would allow one pin to be looked at. And allow me to only deal with a 1MHz clock.

Now If this is plausible.. how to ASM code it? I guess I could write it long-hand and and go to disassembly and see. but I'm not even surch how to use the SPI to get the job done ;(

Grendel
Rank 4
Rank 4
Posts: 167
Joined: Sat Dec 16, 2006 9:53 pm
Location: Oregon, USA
Contact:

Re: nanoseconds

Post by Grendel » Wed Jul 22, 2009 11:22 am

Doesn't look like you could do it w/o extra hardware to split the clock & data signal :( But then, it's late and I could easily miss something.. ;) If it's not a random signal (ie. it's there on a fast period or you can trigger for it), another possibility would be to synchronize to the USB and receive it just after a keep-alive SOF (gives you about 1ms w/o any USB activity).

ulao
Rank 4
Rank 4
Posts: 481
Joined: Mon Aug 25, 2008 8:45 pm

Re: nanoseconds

Post by ulao » Wed Jul 22, 2009 2:10 pm

Doesn't look like you could do it w/o extra hardware to split the clock & data signal :( But then, it's late and I could easily miss something..
meh, yeah 2 shift register would be best, but I know one other guy that did it with one avr. He decided to keep his code a hush though.

I know when the signal is coming and the data is timed with in 6 ns. So I can read at 6 ns intervals or watching a falling edge.

another possibility would be to synchronize to the USB and receive it just after a keep-alive SOF (gives you about 1ms w/o any USB activity).


This may work, 1ms is more then enough for me to get the data. How do you detect this SOF ?


Hmm, but
I call my update func using the TIFR . update would need to know about the sof, would it be able to based on how I'm calling it.

Code: Select all

/* Read the controller periodically*/
      if (TIFR & (1<<OCF2))
      {
         TIFR = 1<<OCF2;

         curGamepad->update();

         /* Check what will have to be reported */
         for (i=0; i<curGamepad->num_reports; i++) {
            if (curGamepad->changed(i+1)) {
               must_report |= (1<<i);
            }
         }
      }


unless I could do something like this in my update function.

wait for SOF, if not wait more, else do it.. This could introduce a 1m delay on my controller at max, not to bad. But my guess is I can not watch for the SOF with out running a full code loop.

Post Reply