Hello,

I'm trying to generate pattern with the PRU in several channel at the same 
time.
So the objective is to be able to send different sequence of value on six 
channel of the PRU and all of them need to be sent at the same (based on a 
clock signal).
For example send 
channel 0 : 0 1 1 0 0 0 1 1 0 0
channel 1 : 1 0 1 0 0 1 1 1 0 0
channel 2 : 0 1 1 0 0 0 1 0 0 0
channel 3 : 0 1 1 0 1 0 1 1 0 0
channel 4 : 0 0 1 0 0 1 0 1 0 0
channel 5 : 1 1 1 0 0 0 1 1 0 1
And on each rise up of the clock, the data are sending out.
(The value of the data are not important, it's just an example).
To do so I'have follow the chapter 13 of Derek molloy book on ADC 
<http://exploringbeaglebone.com/chapter13/#prettyPhoto>.  

Then from the PRUADC.p program, I have extract the part which allowed me to 
do shift out of data, I have regroup it in the file 
pru_sequence_one_channel_out.p.
I have also use a pru_sequence.c (based on the PRUADC.c program) which 
allow me to send the assembly code into the PRU 
(Just to be clear I have rename pru_sequence.p into 
pru_sequence_one_channel_out.p in order be able to explain you the 
difference with pru_sequence_two_channel_out.p).


This example works very well, I observe the expected data on the pin P9_29.

However, when I tried to send two data at the same time it is not working, 
in the way that I can't observe anything on P9_27 (but I still observed the 
same signal on the P9_29).
It's not due to the DTS, because if I change the PIN of the DATA_OUT to 
P9_27, it's work well.
The code is on the pru_sequence_two_channel_out.p program, it is use with 
the same pru_sequence.c program. The main change are on SEQCLK part.
I have also tried to move the part for the OUT_2 on different places in the 
program, but I didn't succeed to making it works.
In addition, I have tried to shift out the same data in two channels, but 
it's still doesn't work.


So I'm wondering if it's possible to do shift out on multiple Pins at the 
same time ? If yes, have you got an example which can do that,
or have you some clue on what I'm doing wrong ?


Remark : 
I have also think to the Direct Connection mode instead of the Shift out 
one. However, I didn't know how can I do such a thing with a clock 
synchronization because each movement will cost me one clock cycle.

Thanks by advance 
Regards
Vincent 

-- 
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 beagleboard+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beagleboard/f1b39d9c-072a-4cd5-962f-87d25afe8c12%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
/*  This program loads the two PRU programs into the PRU-ICSS transfers the configuration
*   to the PRU memory spaces and starts the execution of both PRU programs.
*   pressed.
*/

#include <stdio.h>
#include <stdlib.h>
#include <prussdrv.h>
#include <pruss_intc_mapping.h>

#define PRU_NUM_0	   0   // using PRU0 for the ADC capture
#define MMAP1_LOC   "/sys/class/uio/uio0/maps/map1/"

#define NUMBER_OF_PINS 2
#define SIZE_UNSIGNED_INT 4 
#define DEDICATED_DATA 2
#define SIZE_ARRAY_SEQUENCE  DEDICATED_DATA+NUMBER_OF_PINS


// Short function to load a single unsigned int from a sysfs entry
unsigned int readFileValue(char filename[]){
   FILE* fp;
   unsigned int value = 0;
   fp = fopen(filename, "rt");
   fscanf(fp, "%x", &value);
   fclose(fp);
   return value;
}

int main (void)
{
   if(getuid()!=0){
      printf("You must run this program as root. Exiting.\n");
      exit(EXIT_FAILURE);
   }
   // Initialize structure used by prussdrv_pruintc_intc
   // PRUSS_INTC_INITDATA is found in pruss_intc_mapping.h
   tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

   // data for PRU0 based on the MCPXXXX datasheet
   unsigned int sequenceData[SIZE_ARRAY_SEQUENCE];

   sequenceData[0] = readFileValue(MMAP1_LOC "addr");
   sequenceData[1] = readFileValue(MMAP1_LOC "size");
   sequenceData[2] = 0xaa500000; // an example of data send on the DATA OUT PIN 
   sequenceData[3] = 0xaaa00000; // use in case of two channel pru sequence only
   printf("Sending the SPI Control Data: 0x%x and 0x%x\n", sequenceData[2],sequenceData[3]);
   printf("The DDR External Memory pool has location: 0x%x and size: 0x%x bytes\n", sequenceData[0], sequenceData[1]);
   int numberSamples = sequenceData[1]/2;
   printf("-> this space has capacity to store %d 16-bit samples (max)\n", numberSamples);

   // Allocate and initialize memory
   prussdrv_init ();
   prussdrv_open (PRU_EVTOUT_0);

   // Write the address and size into PRU0 Data RAM0. 
   prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0, sequenceData, SIZE_ARRAY_SEQUENCE*SIZE_UNSIGNED_INT);  // sequence code


   // Map the PRU's interrupts
   prussdrv_pruintc_init(&pruss_intc_initdata);

   // Load and execute the PRU program on the PRU
   prussdrv_exec_program (PRU_NUM_0, "./pru_sequence.bin");


   // Wait for event completion from PRU, returns the PRU_EVTOUT_0 number
   int n = prussdrv_pru_wait_event (PRU_EVTOUT_0);
   printf("EBBADC PRU0 program completed, event number %d.\n", n);

// Disable PRU and close memory mappings 
   prussdrv_pru_disable(PRU_NUM_0);

   prussdrv_exit ();
   return EXIT_SUCCESS;
}
//The program generates a sequence on DATA OUT(P9_29h is send on every clock cycle of the PIN_CLK(P9_30)

//   sequence out    :   P9_29    pr1_pru0_pru_r30_1  r30.t1
//   CLK             :   P9_30    pr1_pru0_pru_r30_2  r30.t2


.setcallreg  r29.w2		 // set a non-default CALL/RET register

.origin 0                        // start of program in PRU memory
.entrypoint START                // program entry point (for a debugger)


#define BASE_ADRESSE 0x00000000

#define SIZE_UNSIGNED_INT 4
#define PRU0_R31_VEC_VALID 32    // allows notification of program completion
#define PRU_EVTOUT_0    3        // the event number that is sent back

#define DATA_OUT_1 r30.t1 //P9_29 mode OUT 
#define DATA_OUT_2 r30.t5 //P9_27 mode OUT 
#define PIN_CLK r30.t2 //P9_30_OUT

#define PARA_0 0 //parameter number 0
#define PARA_1 1 //parameter number 1	
#define PARA_2 2 //parameter number 2
#define PARA_3 3 //parameter number 3

#define REGISTER_OUT_1 r9  // can be any register but I prefer to define it here
#define REGISTER_OUT_2 r10 // can be any register but I prefer to define it here

#define TIME_CLOCK      12       // T_hi and t_lo = 125ns = 25 instructions (min)

//For now DELAY_HIGH=DELAY_LOW=TIME_CLOCK, but the objectif is latter to change them
#define DELAY_HIGH TIME_CLOCK 
#define DELAY_LOW TIME_CLOCK

#define NUMBER_OF_LOOP 10

#define NUMBER_OF_BITS_READ 24 // you have to keep it under or equal to 31 otherwise it will cost you an additional clock cycle


START:
//Initialisation part
	MOV r5, NUMBER_OF_LOOP

	MOV	r1, BASE_ADRESSE	 // load the base address into r1
				 // PRU memory 0x00 stores the sequence command - e.g., 0x01 0x80 0x00

	LBBO	r7, r1, PARA_0*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT	 	// load the Linux address that is passed into r7 -- to store sample values
	LBBO    r8, r1, PARA_1*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT     // load the size that is passed into r8 -- the number of samples to take
	
	CLR DATA_OUT_1		// clear the data out 1
	
GET_SAMPLE:			 // load the send value on each sample, allows sampling re-configuration

//Load the 2 value form the C program

	LBBO	REGISTER_OUT_1, r1, PARA_2*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT	 	//send value on each sample the MCP3XXX states are now stored in r9 -- need the 16 MSBs		
SAMPLE_WAIT_HIGH:
	MOV	r4, NUMBER_OF_BITS_READ		 // going to write/read 24 bits (3 bytes)

SEQCLK_BIT:                      // loop for each of the NUMBER_OF_BITS_READ bits
	SUB	r4, r4, 1        // count down through the bits
	CALL	SEQCLK           // repeat call the SPEQCLK_BIT procedure until all NUMBER_OF_BITS_READ-bits written/read
	QBNE	SEQCLK_BIT, r4, 0

	SUB	r5,r5,1	//decrese the r5 counter 
	QBNE	GET_SAMPLE, r5, 0	//allow you to send multiple time the data

END:
	MOV	r31.b0, PRU0_R31_VEC_VALID | PRU_EVTOUT_0	
	HALT 



// This procedure applies an SEQUENCE clock cycle to the PIN_CLK clock and on the rising edge of the clock
// it writes the current MSB bit in r2 (i.e. r31) to the P9_29 pin. 
// The clock cycle is determined by the datasheet of the product where DELAY_LOW and  DELAY_HIGH are the
// time that the clock must remain low and the time it must remain high 
// The outputs data are shifted left on each clock cycle

SEQCLK:
	MOV	r0, DELAY_HIGH	 // time for clock low -- assuming clock low before cycle
CLKLOW:	
	SUB	r0, r0, 1	 // decrement the counter by 1 and loop (next line)
	QBNE	CLKLOW, r0, 0	 // check if the count is still low	

//for OUT_1				 
	QBBC DATALOW_1, REGISTER_OUT_1.t31  // The write state needs to be set right here -- bit 31 shifted left
	SET	DATA_OUT_1

	QBA	DATACONTD
DATALOW_1:
	CLR	DATA_OUT_1

DATACONTD:
	SET	PIN_CLK		 // set the clock high
	MOV	r0, DELAY_LOW	 // time for clock high
	
CLKHIGH:
	SUB	r0, r0, 1	 // decrement the counter by 1 and loop (next line)
	QBNE	CLKHIGH, r0, 0	 // check the count
	LSL	REGISTER_OUT_1, REGISTER_OUT_1, 1 	//shift left the data	

	CLR	PIN_CLK		 // set the clock low

DATAINLOW:	

	RET
//The program generates a sequence on DATA OUT(P9_29h is send on every clock cycle of the PIN_CLK(P9_30)

//   sequence out 1  :   P9_29    pr1_pru0_pru_r30_1  r30.t1
//   sequence out 2  :   P9_27    pr1_pru0_pru_r30_5  r30.t5
//   CLK             :   P9_30    pr1_pru0_pru_r30_2  r30.t2


.setcallreg  r29.w2		 // set a non-default CALL/RET register

.origin 0                        // start of program in PRU memory
.entrypoint START                // program entry point (for a debugger)


#define BASE_ADRESSE 0x00000000

#define SIZE_UNSIGNED_INT 4
#define PRU0_R31_VEC_VALID 32    // allows notification of program completion
#define PRU_EVTOUT_0    3        // the event number that is sent back

#define DATA_OUT_1 r30.t1 //P9_29 mode OUT 
#define DATA_OUT_2 r30.t5 //P9_27 mode OUT 
#define PIN_CLK r30.t2 //P9_30_OUT

#define PARA_0 0 //parameter number 0
#define PARA_1 1 //parameter number 1	
#define PARA_2 2 //parameter number 2
#define PARA_3 3 //parameter number 3

#define REGISTER_OUT_1 r9  // can be any register but I prefer to define it here
#define REGISTER_OUT_2 r10 // can be any register but I prefer to define it here

#define TIME_CLOCK      12       // T_hi and t_lo = 125ns = 25 instructions (min)

//For now DELAY_HIGH=DELAY_LOW=TIME_CLOCK, but the objectif is latter to change them
#define DELAY_HIGH TIME_CLOCK 
#define DELAY_LOW TIME_CLOCK

#define NUMBER_OF_LOOP 10

#define NUMBER_OF_BITS_READ 24 // you have to keep it under or equal to 31 otherwise it will cost you an additional clock cycle



START:
//Initialisation part
	MOV r5, NUMBER_OF_LOOP

	MOV	r1, BASE_ADRESSE	 // load the base address into r1
				 // PRU memory 0x00 stores the SPI command - e.g., 0x01 0x80 0x00
				 // the SGL/DIFF and D2, D1, D0 are the four LSBs of byte 1 - e.g. 0x80

	LBBO	r7, r1, PARA_0*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT	 	// load the Linux address that is passed into r7 -- to store sample values
	LBBO    r8, r1, PARA_1*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT     // load the size that is passed into r8 -- the number of samples to take
	
	CLR DATA_OUT_1		// clear the data out 1
	CLR DATA_OUT_2		// clear the data out 2
	
GET_SAMPLE:			 // load the send value on each sample, allows sampling re-configuration

//Load the 2 value form the C program

	LBBO	REGISTER_OUT_1, r1, PARA_2*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT	 	//send value on each sample the MCP3XXX states are now stored in r9 -- need the 16 MSBs
	LBBO	REGISTER_OUT_2, r1, PARA_3*SIZE_UNSIGNED_INT, SIZE_UNSIGNED_INT	//send value on each sample the MCP3XXX states are now stored in r10 -- need the 16 MSBs			
SAMPLE_WAIT_HIGH:
	MOV	r4, NUMBER_OF_BITS_READ		 // going to write/read 24 bits (3 bytes)

SEQCLK_BIT:                      // loop for each of the NUMBER_OF_BITS_READ bits
	SUB	r4, r4, 1        // count down through the bits
	CALL	SEQCLK           // repeat call the SPEQCLK_BIT procedure until all NUMBER_OF_BITS_READ-bits written/read
	QBNE	SEQCLK_BIT, r4, 0

	SUB	r5,r5,1	//decrese the r5 counter 
	QBNE	GET_SAMPLE, r5, 0	//allow you to send multiple time the data

END:
	MOV	r31.b0, PRU0_R31_VEC_VALID | PRU_EVTOUT_0	
	HALT 



// This procedure applies an SEQUENCE clock cycle to the PIN_CLK clock and on the rising edge of the clock
// it writes the current MSB bit in r2 (i.e. r31) to the MOSI pin. 
// The clock cycle is determined by the datasheet of the product where DELAY_LOW and  DELAY_HIGHare the
// time that the clock must remain low and the time it must remain high 
// The outputs data are shifted left on each clock cycle

SEQCLK:
	MOV	r0, DELAY_HIGH	 // time for clock low -- assuming clock low before cycle
CLKLOW:	
	SUB	r0, r0, 1	 // decrement the counter by 1 and loop (next line)
	QBNE	CLKLOW, r0, 0	 // check if the count is still low	

//for OUT_1				 
	QBBC DATALOW_1, REGISTER_OUT_1.t31  // The write state needs to be set right here -- bit 31 shifted left
	SET	DATA_OUT_1

	
	QBA	DATACONTD
DATALOW_1:
	CLR	DATA_OUT_1
	
DATACONTD:
	SET	PIN_CLK		 // set the clock high
	MOV	r0, DELAY_LOW	 // time for clock high

	LSL	REGISTER_OUT_1, REGISTER_OUT_1, 1 	//shift left the data
	
	//for OUT_2	
	QBBC DATALOW_2, REGISTER_OUT_2.t31  // The write state needs to be set right here -- bit 31 shifted left
	SET	DATA_OUT_2
	
	QBA	CLKHIGH
DATALOW_2:
	CLR	DATA_OUT_2
	
CLKHIGH:
	SUB	r0, r0, 1	 // decrement the counter by 1 and loop (next line)
	QBNE	CLKHIGH, r0, 0	 // check the count
	LSL	REGISTER_OUT_2, REGISTER_OUT_2, 1 	//shift left the data	

				 // clock goes low now 
	CLR	PIN_CLK		 // set the clock low

DATAINLOW:	

	RET
		

Reply via email to