nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6803
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #30 on: August 31, 2011, 08:32:44 pm » |
I think you could use SPI CLK directly into the SR and counter (gated by SS) and Qc to write the FIFO.
As the FIFO writes on the falling edge it will write just before the 9th clock pulse (when Qc goes low) so as long as the propagation delay of the SR isn't so fast (and the Qc signal slow) that it violates the FIFO hold time (unlikely) you should be OK.
There is a potential race condition with Qc probably happening at the same time as the SR OPs change. maybe the SR could use an inverted version of SPI CLK so it's running out of phase.
Just thinking out aloud, pity we don't have a white board.
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 240
Posts: 16426
Available for Design & Build services
|
 |
« Reply #31 on: August 31, 2011, 08:34:19 pm » |
Yeah, Qd only works every other byte.
I thought the open collector NAND was a pretty good solution. If all SS & the Qx are low, then the output is controlled by the SS clock. Thinking maybe run SPI Clock thru couple stages of spare 74LS32 to move it out past the Qa transition.
FIFO writes in with W going high. Got to treat it like a latch.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 240
Posts: 16426
Available for Design & Build services
|
 |
« Reply #32 on: August 31, 2011, 08:38:57 pm » |
http://www.farnell.com/datasheets/57883.pdf"Data set-up and hold times must be adhered to, with respect to the rising edge of the Write Enable (W)." See Figure 3.
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6803
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #33 on: August 31, 2011, 08:48:43 pm » |
Qd only works every other byte. Yep, I changed it to Qc. WRT the W/ signal, I just read the first line in the data sheet WRITE ENABLE ( W ) — A write cycle is initiated on the falling edge of this input And figured it wrote on the falling edge, but then there's the next sentence Data set-up and hold times must be adhered to,with respect to the rising edge of the Write Enable So yes it's rising edge, so wouldn't an inverted Qc still work? ______ Rob
|
|
|
|
« Last Edit: August 31, 2011, 09:14:10 pm by Graynomad »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 240
Posts: 16426
Available for Design & Build services
|
 |
« Reply #34 on: August 31, 2011, 09:06:36 pm » |
Just realized I had the W/ pulse drawn wrong - the '06 output goes to the FIFO, SPI Clk goes to the shift register clock.
The data has to be out of the shift register 12-15-18nS before the Write pulse goes high. Data takes 10nS to go thru shift register after the clock. So I think Qc/ would go high too early unless I delay it.
I'm gonna dig up a couple parts & give it a try. Not sure if I have a LS161, think I have some LS193's aound.
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6803
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #35 on: August 31, 2011, 09:24:47 pm » |
I love these kind of circuits having made a few logic analyzers over the years, but is all this circuitry really necessary? An AVR could easily work as a FIFO, as I said in a previous post as long as it doesn't have to do anything else it could sample at full speed I'm sure. So using a 1284 will give a FIFO of up to 16k bytes. Then transfer the data to the host Arduino or just make it standalone. Any Arduino could to this, so I don't think I understand the original problem  , I'll review the posts. ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 240
Posts: 16426
Available for Design & Build services
|
 |
« Reply #36 on: September 01, 2011, 01:53:12 am » |
Rob, Here's what I was able to confirm using 74LS163A, 74LS04, 74F32. The 2 signals are the Clear into the '163 (bottom) and the W/ at the 'F32 pin 11. I had to run it as discrete writes like this int SS = 10; // need for SPI byte byte1 = 0x55; byte pin13 = 13;
void setup(){ pinMode (SS, OUTPUT); pinMode (pin13, OUTPUT); }
void loop (){ byte x=0; byte y=0; digitalWrite(SS,LOW); while (x<33){ digitalWrite(pin13, y); y=1-y; x=x+1;} digitalWrite(SS,HIGH); } Any time I tried to go faster, or to set my scope to faster than 10uS/div, I got so much aliasing I couldn't make out anything. I varied between x = 17 for 8 clock pulses to the counter, adn 33 for 16 pulses. The final low going pulse out of the last OR gate was confirmed to match up with the high portion of the 8th clock pulse in the 1 and 2 byte simuation. The wired-Or wasn't working too well, had too low of a pullup resister so the signal didn't come up sharp. Tried the '32 instead of hunting for another resistor to see if I could get a cleaner edge, and did, and then fooled around seeing how fast I could go. Was not able to run with actual SPI clock pulses and capture data with this USP scope. Need something better. I don't see any glitches where I thought they might occur, so I think the routing of the clock thru the gates is gonna take care of that. Now to order some FIFOs. Newark UK (and US) has them, $20 handling charge! Circuit might be overkill to monitor the SPI bus, but the software solutions Nick G was trying didn't seem to be working. This way we can sample for as much as the FIFO will allow. IDT makes 64K parts, if they can be located. I think the biggest I was was 8K.
|
|
|
|
« Last Edit: September 01, 2011, 01:57:57 am by CrossRoads »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 240
Posts: 16426
Available for Design & Build services
|
 |
« Reply #37 on: September 01, 2011, 02:23:34 am » |
Here we go - 64K x 9! http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=800-2143-ND1 part is Cheaper than 2 8kx9 parts from Newark/Farnell UK and without the extra $20 handling fee. If I put a pair on, I could do high speed audio sampling and let the SdFat library store it to SD card. Getting some ideas ...
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6803
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #38 on: September 01, 2011, 04:48:00 am » |
or to set my scope to faster than 10uS/div, I got so much aliasing I couldn't make out anything. Then you need a way better scope, or even better a logic analyzer. Here we go - 64K x 9! Jeez, do they still make PLCCs? ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #39 on: September 01, 2011, 07:09:21 am » |
Back to the base question. What about using a 74HC595 shift register and a 74HC93 counter without FIFO? Looking at my oscilloscope measures the clock speed is 4 MHz and one byte arrives every 6,5 us. Since the shift register is triggered at the positive egde and the counter at negative edge I'm thinking one could use the same clock signal (SCLK) and setup the 7493 as a mod-8 counter. The only additional logic needed would be ~Qb & ~Qc & ~Qd & ~SS connected to the shift register latch clock and to an interrupt pin on the Arduino. Reading parallell inputs every 6,5 us wouldn't be a problem I guess? Otherwise polling could be done in a tight loop.
Wiring ~SS to shift register reset and to MR1 and MR2 on the counter would reset both the counter and shift register on SS high -> low.
Only problem is that this occupies 9 input pins on the Arduino. My goal is to monitor the heater controller and I'll need some of those pins. I'm thinking maybe using two Arduinos, one for monitoring SPI and one for alarm, onewire and hall sensor input.
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6803
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #40 on: September 01, 2011, 08:09:55 am » |
Everything you describe is already present in the CPU, it's called an SPI interface. I can't see how moving the logic outside will help. I think you can record bytes every 6.5uS but I haven't tried I admit. This is the fastest code I can think of byte buffer [100]; byte *buffer_end = buffer + sizeof(buffer) + 1; byte *pos = buffer; byte mask = (1<<SPIF); // assume this will wind up in a reg and so will be faster than a literal byte temp;
do { while(!(SPSR & mask)); temp = SPSR; // dummy read to setup a clear of SPIF *pos++ = SPDR; // get the data and clear SPIF } while (pos < buff_end)
That will record 100 bytes then exit. After that you print the array to the serial port. If that (or something similar) doesn't do the trick then it doesn't doesn't matter how many Arduinos you have you need either a faster processor, write the code in assembler, or use some hardware like what Crossroads has designed. ______ Rob
|
|
|
|
« Last Edit: September 01, 2011, 08:13:30 am by Graynomad »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #41 on: September 01, 2011, 08:39:59 am » |
Everything you describe is already present in the CPU, it's called an SPI interface. I can't see how moving the logic outside will help.
The AVR running as a slave samples the clock signal in software. That is the reason to why the 4 MHz clock signal is missed. The clock is not high long enough for the AVR to recognize it as a clock pulse. This could be solved using an external shift register?
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6803
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #42 on: September 01, 2011, 09:01:00 am » |
as a slave samples the clock signal in software. Not sure where you get that from, AFAIK its all done with hardware. However there is a speed limitation and unfortunately the data sheet is a bit ambiguous here To ensure correct sampling of the clock signal, the minimum low and high periods should be: Low periods: Longer than 2 CPU clock cycles. High periods: Longer than 2 CPU clock cycles. So does that mean 3 clock cycles? Bottom line is that without some really good code you will never know if it's the hardware or the software that's not working. This could be solved using an external shift register? That's true if the SPI can't use a 4MHz clock. Only problem is that this occupies 9 input pins on the Arduino. My goal is to monitor the heater controller and I'll need some of those pins So this is needed permanently on the final application is it? ______ Rob
|
|
|
|
« Last Edit: September 01, 2011, 09:21:14 am by Graynomad »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Offline
Brattain Member
Karma: 240
Posts: 16426
Available for Design & Build services
|
 |
« Reply #43 on: September 01, 2011, 09:16:15 am » |
@rob, Yes, better 'scope or logic analzer would certainly help. I bet wirewrapping this up would help also, signals are pretty crappy looking with jumper wires all over a breaboard.
@torgil, What you describe in #39 is what I have working in #36 (just control signals so far). You can do it without the FIFO - capture serially in one shift register, move in parallel to a 2nd, and read it in serially with SPI command, that way its hardware all the way thru and not software sampling. Have to check the control signals, make sure the parallell load signal is seperate from the clock out signal. Still have to know when to bring the data in - so use the same parallel load signal to the 2nd shift register to create an interrupt to read the data? I think interrupts have the same issue of having to be valid in time to be clocked in.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #44 on: September 01, 2011, 07:00:17 pm » |
Here's some test code ... Master: // Written by Nick Gammon // September 2011
#include <SPI.h> #include "pins_arduino.h"
void setup (void) { SPI.begin ();
// Slow down the master a bit SPI.setClockDivider(SPI_CLOCK_DIV8); } // end of setup
void loop (void) { delay (2000);
// enable Slave Select digitalWrite(SS, LOW); // SS is pin 10
for (byte i = 0; i < 255; i++) SPI.transfer (i);
// disable Slave Select digitalWrite(SS, HIGH);
} // end of loop
This sends out 255 bytes (where each byte is itself, ie. 0, 1, 2, 3, 4, 5 etc.). Slave: // Written by Nick Gammon // September 2011
#include "pins_arduino.h"
byte buf [256]; byte pos;
void setup (void) { Serial.begin (115200); // debugging
// have to send on master in, *slave out* pinMode(MISO, OUTPUT); // turn on SPI in slave mode SPCR |= _BV(SPE);
} // end of setup
// main loop - wait for flag set in interrupt routine void loop (void) {
Serial.println ("Starting ..."); pos = 0; while (pos < 255) { /* Wait for reception complete */ while(!(SPSR & (1<<SPIF))) {} buf [pos++] = SPDR; } // check valid Serial.println ("Checking ..."); for (byte i = 0; i < 255; i++) if (buf [i] != i) { Serial.print ("Error at position "); Serial.print (i, DEC); Serial.print (" got "); Serial.println (buf [i], DEC); return; } Serial.println ("Passed."); } // end of loop Now to save CPU cycles the slave does not use interrupts. It uses a tight loop waiting for the byte to appear in the hardware register. Once 255 bytes have arrived it checks that each byte is itself (eg. 0, 1, 2, 3, 4, 5 ...). My results with the above code are: Starting ... Checking ... Passed. Starting ... Checking ... Passed. Starting ... Checking ... Passed. Starting ... Checking ... Error at position 198 got 199 Starting ... Checking ... Error at position 0 got 254 Starting ... Checking ... Passed. Starting ... Checking ... Error at position 153 got 154 Starting ... Checking ... Error at position 0 got 254 Starting ... Checking ... Error at position 0 got 254 Starting ... Checking ... Passed. Starting ... Checking ... Passed. Starting ... Checking ... Passed. Starting ... Checking ... Passed.
So it seems to sometimes send all 255 bytes without error. But sometimes not. And this is with clock/8. With this instead: SPI.setClockDivider(SPI_CLOCK_DIV16); ... it ran without errors.
|
|
|
|
« Last Edit: September 01, 2011, 07:01:58 pm by Nick Gammon »
|
Logged
|
|
|
|
|
|