Arduino Forum

Products => Arduino Due => Topic started by: jiblets on Mar 20, 2013, 08:46 pm

Title: Synchronous Port Manipulation on Due
Post by: jiblets on Mar 20, 2013, 08:46 pm
Coming from this thread on port manipulation:

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

I was able to put together the following sketch:

Code: [Select]

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?
Title: Re: Synchronous Port Manipulation on Due
Post by: Gericom on Mar 20, 2013, 08:50 pm

Coming from this thread on port manipulation:

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

I was able to put together the following sketch:

Code: [Select]

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:
Code: [Select]

REGISTER &= ~1<<bit;
Title: Re: Synchronous Port Manipulation on Due
Post by: jiblets on Mar 20, 2013, 09:02 pm

If you want to clear a bit, you can do it like this:
Code: [Select]

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.
Title: Re: Synchronous Port Manipulation on Due
Post by: Gericom on Mar 20, 2013, 09:07 pm


If you want to clear a bit, you can do it like this:
Code: [Select]

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
Code: [Select]

REGISTER = 8bitvalue << firstbitnr;
Title: Re: Synchronous Port Manipulation on Due
Post by: jiblets on Mar 20, 2013, 09:14 pm

Code: [Select]

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.
Title: Re: Synchronous Port Manipulation on Due
Post by: stimmer on Mar 20, 2013, 09:22 pm
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
Title: Re: Synchronous Port Manipulation on Due
Post by: Grumpy_Mike on Mar 21, 2013, 09:06 am
Quote
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.
Title: Re: Synchronous Port Manipulation on Due
Post by: jiblets on Mar 21, 2013, 03:39 pm
Awesome! Got it working. Thanks a lot everyone.
Title: Re: Synchronous Port Manipulation on Due
Post by: dishimwe on Apr 16, 2013, 02:44 am

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
Code: [Select]

    REG_PIOC_ODR = 0x3fc;
    REG_PIOC_PER = 0x3fc;
    int pixelData = REG_PIOC_PDSR >> 2;
Title: Re: Synchronous Port Manipulation on Due
Post by: ssclark88 on Apr 16, 2013, 07:43 pm


Code: [Select]


    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?
Title: Re: Synchronous Port Manipulation on Due
Post by: Markus_L811 on Apr 16, 2013, 09:50 pm



Code: [Select]


    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 (http://arduino.cc/forum/index.php/topic,132130.0.html)
Title: Re: Synchronous Port Manipulation on Due
Post by: ssclark88 on Apr 17, 2013, 12:52 am
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.

Code: [Select]

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