It was really a ping-pong buffer, not a ring.

I did check the timing with an Agilent 54846B scope.

this is snipped from a backup copy, I have re-purposed the BBB

I did comment about this here already a year ago or so.

My memory about that gets fuzzy...


volatile register unsigned int __R30;        // CPU register R30 connects directly to some output pins volatile register unsigned int __R31;        // CPU register R31 connects directly to some input pins

#define SELECT     8   /* 2 BITS addressing of the 4 bytes in CPLD  Bit8 = P8.27 und Bit9=p8.29 */
#define PROG_CLK  10   /* P8.28  prog_dat green wire to SDI of ADC*/
#define PROG_DAT  11   /* that works unexpectedly. probably the BBB handbook is wrong/incomplete. */                        /* should be possible according to CPU data sheet. */ #define DAT_AVAIL 16   /* Pin P9.26, the only PRU1 pin on P9 input  busy oŕ drl, depending on output used */

// GPIO, Clearing or setting takes about 40 nsec
#define PROG_ENA   (1<<2)
#define USE_CHAN_B (1<<4)


// variables in main end up on the stack. We only have 0x100 bytes by default. // global variables are on the heap. Stack and heap are on the bottom of the PRU data RAM.

volatile int      heapmarker = 0x22222222;  // Easy to find in a memory dump
volatile char     *bla = "HEAP @ @ @ ";
int             i;
volatile int     *pipo_pointer;
int             pipo_offset;



// data avail is either not busy or not drl. It is high active.
// When the ADC is busy, it is low for 600 nsec.
// The CPLD then takes a little more than 32 Clocks
// to get the 32 bits. Then we can read them out, bytewise.
// It is probably harmless if that extends slightly into the next
// conversion since the read activity is decoupled from the ADC core.
// inline saves 20 nsec.

inline void wait_data_avail(void){

    while  (  __R31 & (1 << DAT_AVAIL)) {};    // wait for the high time of p9.26 = data_avail
    while  (!(__R31 & (1 << DAT_AVAIL))){};    // wait for the low time

    //  now the ADC transaction window opens.
    // next 320 ns we will read the data into the CPLD or program the ADC
}




// read 4 bytes from the CPLD, mask them, shift them & convert to one int.
// I must read at least 3 times that the results are right ( for address setup time) // removing a single read makes it 60 nsec faster, 15 nsec per read. Should be 5 nsec???
// reading 3 times takes 40 nsec per bit. That should be enough.
// reading 4 times takes 60 nsec per bit. Reading __R31 takes abt. 20 ns. :-( // Von der steigenden Flanke von data_available am P9 bis zum return dauert 725 nsec.
    // kill 320 nsec, the time the CPLD needs to fill the shift register
    // das sind 340 nsec für 5 Schleifendurchläufe. LAHM??
    // 1 = 42 ns  2 = genauso??  11 = 104 ns  31 = 208 ns 51 = 304 ns
    // 61 = 355 nsec   60 = 350 ns

    // Once through the empty loop costs 5 nsec.
    // for( retval=60; retval;  retval--){};

// D.h. es bleiben 250 nsec zum ABspeichern im pingpong-Buffer. Das CPLD könnte sagen, // wann die Daten für den BBB fertig sind. Dann hätte man 350 nsec mehr Zeit für sonst was. // Das ist jetzt gemacht. Data_rdy_bb geht jetzt 330 nsec low, solange das CPLD den ADC auslutscht. // Wenn data_rdy_bbb hochgeht, können wir gleich anfangen, das CPLD leerzunuckeln.
// Genug Zeit für noch 2 Kanäle.


inline int read_adc(void){

    int retval;

    // Without volatile it runs 3 times as fast, even though __R31 is volatile
    volatile unsigned int byte0, byte1, byte2, byte3;

    wait_data_avail();


//    __R30   &= ~(3 << SELECT);    // address 0 Trigger
//    __R30   |=  (3 << SELECT);    // address 3

    // from here to parking address wires  at return it takes 350 nsec.

    __R30   &= ~(3 << SELECT);    // address 0
    byte0    = __R31;            // address setup time for byte 0
    byte0    = __R31;        // 5 nsec each line
//    byte0    = __R31;
    byte0    = __R31;

    __R30   |= (1 << SELECT);    // address 1
    byte1    = __R31;
    byte1    = __R31;
//    byte1    = __R31;
    byte1    = __R31;

    __R30   &= ~(3 << SELECT);    // address 2,   remove old bit field
    __R30   |=  (2 << SELECT);    // insert new bit field
    byte2   = __R31;
    byte2   = __R31;
//    byte2   = __R31;
    byte2   = __R31;

    __R30   |= (1<< SELECT);    // increment to address 3
    byte3   = __R31;            //
    byte3   = __R31;
//    byte3   = __R31;
    byte3   = __R31;            // get the last byte



    retval  = ((byte0 & 0xff)      )
            | ((byte1 & 0xff) << 8 )
            | ((byte2 & 0xff) << 16)
            | ((byte3 & 0xff) << 24);

    __R30   &= ~(3 << SELECT);    // park address at 0, may be removed.

    return  retval;
}


-----------------------


Am 24.04.21 um 08:16 schrieb Jason Kridner:
https://pub.pages.cba.mit.edu/ring/


On Thu, Apr 22, 2021 at 11:02 AM Gerhard Hoffmann <[email protected] <mailto:[email protected]>> wrote:

    I think I can read in about 3 pcs. LT2500-32 via the PRU in Software.

    The LT2500 ADC delivers 32 bit results via SPI, and with the
    capture and

    conversion time slots it needs 100 MHz SPI to process each 1MHz
    sample.

    The ADC feeds its data to a shift register in a Xilinx 2c64
    Coolrunner.

    The PRU then reads it bytewise and writes the collected 32 bit words

    into a ring buffer in the shared RAM.

    Up to now I have tested 1 ADC, but bandwidth should be enough for 3,

    just so.




    regards, Gerhard


--
For more options, visit http://beagleboard.org/discuss
--- You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beagleboard/f474108b-061d-5d2a-2aa0-b1e81f5f7790%40hoffmann-hochfrequenz.de.

Reply via email to