Synchronous Port Manipulation on Due

Coming from this thread on port manipulation:

http://arduino.cc/forum/index.php/topic,129868.15.html

I was able to put together the following sketch:

void setup() 
  { 
    int k ;  
    
    for( k = 44 ; k <= 51 ; k++ )
      pinMode( k, OUTPUT ) ; // Sets Port C12-C19 to output pins. Necessary or no data is written.
  
    for( k = 34 ; k <= 41 ; k++ )
      pinMode( k, OUTPUT ) ; // Sets Port C2-C9 to output pins
  
    // Set the output pins in the Output Write Enable Register
    REG_PIOC_OWER = 0x000FF3FC ; 
  
    // Disable writing to all other pins on the same port
    REG_PIOC_OWDR = 0xFFF00C03 ;
  }

void loop() 
  {
    int i ;
    
// Writes data to pins 44-51 (PortC 12-19)
    for( i = 0 ; i <= 128 ; i++ )
      REG_PIOC_ODSR = i << 12 ; 

// Writes data to pins 34-41 (PortC 2-9)
    for( i = 0 ; i <= 128 ; i++ )
      REG_PIOC_ODSR = i << 2 ;       
   
  }

What I can't figure out, is how to write data to a specific 8 pins without modifying all of the other pins on the port. In the sketch above, the value 128 should remain present on PortC19 until I start writing to that block again, but what actually happens is it gets set to zero as soon as I start the next loop. I realize that I could OR the port with the new value but then if the pin was already high and I need to write a 0 to it it won't change. Has anyone been able to solve this problem?

jiblets:
Coming from this thread on port manipulation:

http://arduino.cc/forum/index.php/topic,129868.15.html

I was able to put together the following sketch:

void setup() 

{
    int k ; 
   
    for( k = 44 ; k <= 51 ; k++ )
      pinMode( k, OUTPUT ) ; // Sets Port C12-C19 to output pins. Necessary or no data is written.
 
    for( k = 34 ; k <= 41 ; k++ )
      pinMode( k, OUTPUT ) ; // Sets Port C2-C9 to output pins
 
    // Set the output pins in the Output Write Enable Register
    REG_PIOC_OWER = 0x000FF3FC ;
 
    // Disable writing to all other pins on the same port
    REG_PIOC_OWDR = 0xFFF00C03 ;
  }

void loop()
  {
    int i ;
   
// Writes data to pins 44-51 (PortC 12-19)
    for( i = 0 ; i <= 128 ; i++ )
      REG_PIOC_ODSR = i << 12 ;

// Writes data to pins 34-41 (PortC 2-9)
    for( i = 0 ; i <= 128 ; i++ )
      REG_PIOC_ODSR = i << 2 ;       
   
  }




What I can't figure out, is how to write data to a specific 8 pins without modifying all of the other pins on the port. In the sketch above, the value 128 should remain present on PortC19 until I start writing to that block again, but what actually happens is it gets set to zero as soon as I start the next loop. I realize that I could OR the port with the new value but then if the pin was already high and I need to write a 0 to it it won't change. Has anyone been able to solve this problem?

If you want to clear a bit, you can do it like this:

REGISTER &= ~1<<bit;

Gericom:
If you want to clear a bit, you can do it like this:

REGISTER &= ~1<<bit;

Thanks, I will remember that, but it doesnt quite solve the problem. I still need to be able to write all values synchronously. I suppose I could clear that block on the port and then OR it with the new value, but its an extra step that would need to be performed each time and I would like to avoid it.

jiblets:

Gericom:
If you want to clear a bit, you can do it like this:

REGISTER &= ~1<<bit;

Thanks, I will remember that, but it doesnt quite solve the problem. I still need to be able to write all values synchronously. I suppose I could clear that block on the port and then OR it with the new value, but its an extra step that would need to be performed each time and I would like to avoid it.

I don't think that's possible. The registers are 32 bit. But if you don't use the remaining pins, you can just use

REGISTER = 8bitvalue << firstbitnr;

Gericom:

REGISTER = 8bitvalue << firstbitnr;

Yea, that's what I was using before but the problem is that I do need to use the other pins on the port, and it's important that they stay at the same level while the data is being written.

You're almost there - what you have to do is use REG_PIOC_OWER and REG_PIOC_OWDR to mask off which pins you want to alter before writing REG_PIOC_ODSR to change them - the other bits will stay as outputs and stay unchanged.
REG_PIOC_OWER = 0x000003FC ; REG_PIOC_OWDR = 0x000FF000 ; lets you change 2-9 leaving 12-19 unchanged
REG_PIOC_OWER = 0x000FF000 ; REG_PIOC_OWDR = 0x000003FC ; lets you change 12-19 leaving 2-9 unchanged

I suppose I could clear that block on the port and then OR it with the new value, but its an extra step that would need to be performed each time and I would like to avoid it.

That is what you have to do in order to write any value you want. Mask AND to clear and OR to set.

Awesome! Got it working. Thanks a lot everyone.

stimmer:
You're almost there - what you have to do is use REG_PIOC_OWER and REG_PIOC_OWDR to mask off which pins you want to alter before writing REG_PIOC_ODSR to change them - the other bits will stay as outputs and stay unchanged.
REG_PIOC_OWER = 0x000003FC ; REG_PIOC_OWDR = 0x000FF000 ; lets you change 2-9 leaving 12-19 unchanged
REG_PIOC_OWER = 0x000FF000 ; REG_PIOC_OWDR = 0x000003FC ; lets you change 12-19 leaving 2-9 unchanged

how can i do the same thing but instead of setting them as output, use them as input?
I have tried this but it does not seem to work

    REG_PIOC_ODR = 0x3fc;
    REG_PIOC_PER = 0x3fc;
    int pixelData = REG_PIOC_PDSR >> 2;

jiblets:

    for( k = 44 ; k <= 51 ; k++ )

pinMode( k, OUTPUT ) ; // Sets Port C12-C19 to output pins. Necessary or no data is written.
 
    for( k = 34 ; k <= 41 ; k++ )
      pinMode( k, OUTPUT ) ; // Sets Port C2-C9 to output pins

Is there a list of which due pins correspond to which port registers?

ssclark88:

jiblets:

    for( k = 44 ; k <= 51 ; k++ )

pinMode( k, OUTPUT ) ; // Sets Port C12-C19 to output pins. Necessary or no data is written.
 
    for( k = 34 ; k <= 41 ; k++ )
      pinMode( k, OUTPUT ) ; // Sets Port C2-C9 to output pins

Is there a list of which due pins correspond to which port registers?

May a little bit inconvenient but you can put it yourself together from the Pinout http://arduino.cc/forum/index.php/topic,132130.0.html

I was looking everywhere for that, and it was right there the whole time! I put it into a table for reference if it's useful to anyone.

Due Pin	Port	Channel
0	A	8
1	A	9
2	B	25
3	C	28
4	C	26
5	C	25
6	C	24
7	C	23
8	C	22
9	C	21
10	C	29
11	D	7
12	D	8
13	B	27
14	D	4
15	D	5
16	A	13
17	A	12
18	A	11
19	A	10
20	A	12
21	A	13
22	B	26
23	A	14
24	A	15
25	D	0
26	D	1
27	D	2
28	D	3
29	D	6
30	D	9
31	A	7
32	D	10
33	C	1
34	C	2
35	C	3
36	C	4
37	C	5
38	C	6
39	C	7
40	C	8
41	C	9
42	A	19
43	A	20
44	C	19
45	C	18
46	C	17
47	C	16
48	C	15
49	C	14
50	C	13
51	C	12
52	B	21
53	B	14