need help reading data in nanosecond timing.

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

For reference here is my timing chart.


http://img31.picoodle.com/img/im...

I can set up my pins and get ready for the first falling edge but I need to read the first data (d7) with in 3 nops in to tmp.

This is how I normally read a pin.

if ( pinStatus(1<<5) ) { tmp |= 1; } else { tmp |= 0; } 
tmp <<= 1;

my pin status is
char pinStatus(char pin ){ return ~PINC & pin; }

but I'm sure this is going to be 4 or 5 nops to run.. Is there a way to read a pin in to a char in 3 nops?

For reference I'm running a 12 hmz that is about 83.33 a clock period.

Here is the code I'm attempting. only doing 8 bits for now.

PORTC = 0x1;/*a nop */
	DDRC = 0;//set to input	//nop
	for ( char i=0;i<8;i++)
	{
		if (pinStatus(1<<5) ) {tmp |= 1; } else { tmp |= 0; } tmp <<= 1; //Too slow

		__asm__( "nop\n\t"  "nop\n\t");//nop
		PORTC = 0x1;// white low ( both will be low ) //nop
	
		if (pinStatus(1<<4) ) {tmp |= 1; } else { tmp |= 0; }tmp <<= 1; //Too slow

		__asm__( "nop\n\t"  "nop\n\t");//nop
		PORTC = 0x0;// white low ( both will be low ) //nop
	}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you're call of "pinStatus" is going to take longer than you have. You will need to re-structure your code. But given the tight timing (approx 6 cycles clock to clock), you may need to drop down to assembler to keep up with this data-train. [in fact I'd say you HAVE to use assembler here to guarantee your timing]

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Is there a simple reference for reading registers and make comparisons on the net for someone that has no asm experience? I tried

tmp |= (1 & PINC); tmp <<= 1;

but I still think its 4 nops.

but like you said ASM would be best, I have no idea where to even start. I know a few things about asm but with the limited form of output avr programming has to begin with I'd be lost. I wish there was a simple console app I could use to debug stuff.

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

In assembler there are two handy opcodes: BST and BLD. What they do is read a bit from a register to the T bit in SREG, and the reverse. So something like this:

if (pinStatus(1<<5) ) {tmp |= 1; } else { tmp |= 0; }

can be replaced with this:

IN Rx, PORTC
BST Rx, 5
BLD Rtemp, 7

This takes bit 5 from Rx and puts it into bit 7 of Rtemp.

By the way this does nothing:

tmp |= 0;

Regards,
Steve A.

The Board helps those that help themselves.

Last Edited: Tue. Jul 14, 2009 - 10:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can run at 16MHz, then you get 4 nop's.

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

You are trying to read a 2 MBps signal in software. On a 20 MHz AVR (most are slower) you would have 10 clock cycles per bit. 10 cycles to detect the falling edge of one signal, get the other signal, store the bit, switch edge detection to the other signal and look for the next falling edge.

And you want to do something useful with the data once you received it.

Wow. That is so tight, I would start looking for a hardware solution.

Stealing Proteus doesn't make you an engineer.

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

Quote:

only doing 8 bits for now

Is this a continuous stream? then you might be in trouble--you've got to >>put<< the completed bytes somewhere.

Can you tell us the device? Perhaps there are some app notes.

This has to be the strangest sequence that I've ever seen. :) But I'm pretty naive.

If there is more than one byte, are they continuous? Or is there a gap between?

What AVR model are you using? Is there any possibility of cranking up the clock?

You'll never do it with a loop (as my first guess) in ASM or C. You'll need to unroll the loop for each byte, at least.

You have hit upon one of the drawbacks in the AVR instruction set--there is no "real fast" way [flame bait--suggestions welcome] to copy a bit from I/O space to a register bit. AFAIK the fastest way is a conditional set/clear of the T flag, and then BST.

Quote:

But given the tight timing (approx 6 cycles clock to clock), you may need to drop down to assembler to keep up with this data-train.

;) I tried a couple methods in CV, and they are pretty close. The problem is we don't know from that timing diagram how long the pulse will be high before the falling-edge clock.

// Bank 0
bit    bank0_0;        // GPIOR0 Bit 0 (least significant)
bit    bank0_1;
bit    bank0_2;
bit    bank0_3;
bit    bank0_4;
bit    bank0_5;
bit    bank0_6;
bit    bank0_7;        // GPIOR0 Bit 7 (most significant)

// Bank 1
bit	bank1_0;		// R2 Bit 0 (least significant)
bit	bank1_1;
bit	bank1_2;
bit	bank1_3;
bit	bank1_4;
bit	bank1_5;
bit	bank1_6;
bit	bank1_7;		// R2 Bit 7 (most significant)

void main(void)
{
// PB0 = channel A; PB1 = channel B

// GPIOR Test
// D7
while (PINB.0);
bank0_7 = PINB.1;

// D6
while (PINB.1);
bank0_6 = PINB.0;

// R2 Test
// D5
while (PINB.0);
bank1_5 = PINB.1;

// D4
while (PINB.1);
bank1_4 = PINB.0;

                 	.CSEG
                 _main:
                 ; 0000 0026 // PB0 = channel A; PB1 = channel B
                 ; 0000 0027
                 ; 0000 0028 // GPIOR Test
                 ; 0000 0029 // D7
                 ; 0000 002A while (PINB.0);
                 _0x3:
000041 9918      	SBIC 0x3,0
000042 cffe      	RJMP _0x3
                 ; 0000 002B bank0_7 = PINB.1;
000043 9919      	SBIC 0x3,1
000044 c002      	RJMP _0x6
000045 98f7      	CBI  0x1E,7
000046 c001      	RJMP _0x7
                 _0x6:
000047 9af7      	SBI  0x1E,7
                 _0x7:
                 ; 0000 002C
                 ; 0000 002D // D6
                 ; 0000 002E while (PINB.1);
                 _0x8:
000048 9919      	SBIC 0x3,1
000049 cffe      	RJMP _0x8
                 ; 0000 002F bank0_6 = PINB.0;
00004a 9918      	SBIC 0x3,0
00004b c002      	RJMP _0xB
00004c 98f6      	CBI  0x1E,6
00004d c001      	RJMP _0xC
                 _0xB:
00004e 9af6      	SBI  0x1E,6
                 _0xC:
                 ; 0000 0030
                 ; 0000 0031 // R2 Test
                 ; 0000 0032 // D5
                 ; 0000 0033 while (PINB.0);
                 _0xD:
00004f 9918      	SBIC 0x3,0
000050 cffe      	RJMP _0xD
                 ; 0000 0034 bank1_5 = PINB.1;
000051 94e8      	CLT
000052 9919      	SBIC 0x3,1
000053 9468      	SET
000054 b5aa      	IN   R26,0x2A
000055 f9a5      	BLD  R26,5
000056 bdaa      	OUT  0x2A,R26
                 ; 0000 0035
                 ; 0000 0036 // D4
                 ; 0000 0037 while (PINB.1);
                 _0x10:
000057 9919      	SBIC 0x3,1
000058 cffe      	RJMP _0x10
                 ; 0000 0038 bank1_4 = PINB.0;
000059 94e8      	CLT
00005a 9918      	SBIC 0x3,0
00005b 9468      	SET
00005c b5aa      	IN   R26,0x2A
00005d f9a4      	BLD  R26,4
00005e bdaa      	OUT  0x2A,R26

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

The only sequence that makes sense is IN, BST, BLD which takes 3 cycles. The problem is we can't tell how long the "clock" will be high before the falling edge, so 3 cycles may not be enough. I assume the preamble is for clock determination but we don't have the luxury here.

Given the 3 cycles above and the budget of 6 then the SBIC/RJMP loop is 3 cycles per, right? But I hate that jitter. May have to count and NOP the unrolled loop. Even getting in sync on the first bit is going to be hard. Probably a fighting chance at 20MHz.

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

theusch wrote:
This has to be the strangest sequence that I've ever seen.
Sega has patented this. US Patent 6324603 "Data transmission system and game system using the same"

Stealing Proteus doesn't make you an engineer.

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

Lee, don't get me wrong, one could probably coax their compiler into generating code that is fast enough (assuming it's possible to accomplish in assembly). BUT the effort in doing so by compiling, checking generated code, editing and repeating until it works far outweighs the effort in writing in assembler in the first place.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Wow would you look at how this post blow up…

Quote:
If you can run at 16MHz, then you get 4 nop's.
yup have to ovoid that ;( I wish I could use a 16.

Koshchi, thx for the info this was help full, and I see what you mean that’s was pointless code…

ArnoldB, I know its tight, and going to be near impossible. One guy claims he did it but he keeps his source as tight as the code I need. I trust his word given his reputation. As any rate I’m locked in to a 12mhz for now..

Quote:
Can you tell us the device? Perhaps there are some app notes.
Most certainly. the device is a dreamCast controller. Aka Maple bus. There are 16 and 20 mhz implementations out there. And done for obvious reasons.

Here are some details..
All the info a person would need http://mc.pp.se/dc/controller.html ( see serial protoco link )

plenty of talk about the 12,mhz and why it’s hard but the user mojochan not in that particular post has claimed to do it.
http://216.246.50.234/showthread...

Quote:
This has to be the strangest sequence that I've ever seen. But I'm pretty naive.
it is a technique to oscillate ( clock ) and read at the same tim use two pins. The switch roles and create the clock in one shot. pretty neat..

Quote:
What AVR model are you using?
atmega 168

Quote:
I tried a couple methods in CV, and they are pretty close. The problem is we don't know from that timing diagram how long the pulse will be high before the falling-edge clock.
That was not clear? I don’t mean to sound as I’m correcting you but I thought the timing chart illustrated this, perhaps I’m more wrong that I though. Did you see the blown up image?

line 1 goes hi then in 250 ns 2 goes low at what point you get the data, then 750 more and 1 goes low then 2 after another 250.. I think.

Going to have a look at this asm and try to learn something here thx guys!!!!!!!!!!!!!

Last Edited: Tue. Jul 14, 2009 - 10:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thinking about it more, I'd go for some external hardware. A couple of 4 bit shift registers should do the trick:

SDCKA -> Data of SRA
SDCKB -> Clock of SRA

SDCKB -> Data of SRB
SDCKA -> Clock of SRB

The outputs of the two shift registers would then need to be interleaved to reconstruct the byte.

Additional logic would need to be added to count pulses in order to signal when a byte is ready to be read. (or, possibly, this counting could be done in the AVR)

Edit:
Looks l;ike this is how the Sega Patent proposes decoding as well

http://www.patentgenius.com/pate...

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Tue. Jul 14, 2009 - 10:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
Thinking about it more, I'd go for some external hardware. A couple of 4 bit shift registers should do the trick:

SDCKA -> Data of SRA
SDCKB -> Clock of SRA

SDCKB -> Data of SRB
SDCKA -> Clock of SRB

The outputs of the two shift registers would then need to be interleaved to reconstruct the byte.

Additional logic would need to be added to count pulses in order to signal when a byte is ready to be read. (or, possibly, this counting could be done in the AVR)

Is this what this guy is trying?

http://img37.picoodle.com/img/im...

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

Yep, that is exactly what the pic circuit is doing.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Well I may try a few hardware options, can anyone point blank say this is not going to happen with my setup alone?

Quote:
This takes bit 5 from Rx and puts it into bit 7 of Rtemp.
How do I get the data out of Rtemp once I'm out of asm?

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

S_K_U_N_X wrote:

Quote:
This has to be the strangest sequence that I've ever seen. But I'm pretty naive.
it is a technique to oscillate ( clock ) and read at the same tim use two pins. The switch roles and create the clock in one shot. pretty neat..

Actually not all that neat, one could have transmitted data on one line, and clock on the other, and only required 1/4 the clock rate to transmit the same amount of data. (the clock required to generate the stream you have is 2x what you see in the stream)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

S_K_U_N_X wrote:
Well I may try a few hardware options, can anyone point blank say this is not going to happen with my setup alone?

Quote:
This takes bit 5 from Rx and puts it into bit 7 of Rtemp.
How do I get the data out of Rtemp once I'm out of asm?

you might be able to squeeze it out, provided that there is no variance in the timing, and the stream is not too long, and you aren't needing to do anything else at the time.

If there is any variance in the clocking speed of the data you're screwed in the software approach.

The hardware approach is immune to clock speed variance. And reduces your sample rate to 1/8 that of what you have now. Add to that fewer instructions are going to be needed, you'll have plenty of time to do other things.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

thx glitch

Quote:
Actually not all that neat, one could have transmitted data on one line, and clock on the other, and only required 1/4 the clock rate to transmit the same amount of data.
I think they were after the bandwidth for each signal at 1MHz, and the data transfer rate at 2Mbps.

Last Edited: Wed. Jul 15, 2009 - 02:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

That was not clear? I don’t mean to sound as I’m correcting you but I thought the timing chart illustrated this, perhaps I’m more wrong that I though. Did you see the blown up image?

line 1 goes hi then in 250 ns 2 goes low at what point you get the data, then 750 more and 1 goes low then 2 after another 250.. I think.


Quote:
then 750 more and 1 goes low

Yes, but 1 could be high or low, and we don't know from that diagram how long 1 will hold the data. Put another way, what is the minimum time 1 (or 2) will be high before going low again?

1 has to be high before you can check for going low. If you check too soon it could be low from the previous data bit.

Lee

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, thx for the help.

“1 could be high or low” Yes I see your point but I don’t see how that’s a problem. The data block is set by the controller, the high and low oscillation is set by the avr. So I know what the oscillation should be. If the data block is hi when it was set to low by the avr , I know the data coming to me is hi. I’m going to be setting it hi either way for my next oscillation. Did I missing something?

"how long 1 will hold the data" for 333 ns by the timing chart? But I need to get it with in 166.6 as the next oscillation will occur. that gives me two cycles to get it. and one more cycle to set the next oscillation. This may be one cycle short unless there is a way to get the data and set the lines in 3 cycles.

Alternative I could go the expensive rout, if its possible. Can I IN PORTB to something other then the T -bit? Just make enough room to hold all the bites read and assemble it later? Or worse yet, copy the PORTB to a Register, build all 8 of them then later I can strip of the first bits of each?