0
Offline
Jr. Member
Karma: 0
Posts: 77
Arduino rocks
|
 |
« Reply #15 on: September 18, 2011, 02:48:36 pm » |
As I mentioned I saw these functions in Wiring source. After testing them I put them in wiring_digital.c to make them built-in.
They works well in regular code also. But you should add "false" after return of statement "if (inputregister == NOT_A_PORT) return;" in portRead function.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 249
Posts: 16540
Available for Design & Build services
|
 |
« Reply #16 on: September 18, 2011, 02:51:46 pm » |
if (inputregister == NOT_A_PORT) return false;
Like that?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #17 on: September 18, 2011, 04:59:19 pm » |
in the last 2 cases, what does cli(); do?
He is protecting the port change from interrupts. So to comment it: uint8_t oldSREG = SREG; // remember interrupt flag (and other flags) cli(); // turn interrupts off *portregister = val; // do something, knowing interrupts won't occur SREG = oldSREG; // put interrupt flag back (set it again, if it was set before)
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #18 on: September 18, 2011, 05:01:44 pm » |
They works well in regular code also. But you should add "false" after return of statement "if (inputregister == NOT_A_PORT) return;" in portRead function.
You could return 0 (false is a bit misleading), but you can't tell the difference between supplying an invalid port (which returns zero) and reading a valid port, and them all being off (which returns zero).
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 249
Posts: 16540
Available for Design & Build services
|
 |
« Reply #19 on: September 18, 2011, 06:59:49 pm » |
So what should this line be then?
if (inputregister == NOT_A_PORT) return;
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #20 on: September 18, 2011, 07:12:33 pm » |
Since portRead is declared to return a byte (uint8_t) it seems reasonable to return a number in the range 0 to 255. (Returning true or false would be more reasonable if it was declared to return a boolean type). A reasonable value would be 0, like this: uint8_t portRead(uint8_t port) { volatile uint8_t *inputregister;
inputregister = portInputRegister(port);
if (inputregister == NOT_A_PORT) return 0;
uint8_t oldSREG = SREG; cli(); uint8_t portValue = *inputregister; SREG = oldSREG; return portValue; } Bear in mind, as I said before, a return of 0 could either mean "not a port" or "it is a port and all bits are off".
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 249
Posts: 16540
Available for Design & Build services
|
 |
« Reply #21 on: September 18, 2011, 07:16:13 pm » |
Okay, I changed my sample code to be return 0, altho hopefully I'll be awake enough when I write some code to use this to no try & access nonexistent ports.
|
|
|
|
|
Logged
|
|
|
|
|
Guatemala
Offline
Newbie
Karma: 0
Posts: 16
|
 |
« Reply #22 on: September 18, 2011, 08:16:42 pm » |
I have mooched the port manipulation functions from wiring platform. Copy them into "wiring_digital.c" to have built-in port manipulation. Functions void portMode(uint8_t port, uint8_t mode) { volatile uint8_t *moderegister;
moderegister = portModeRegister(port);
if (moderegister == NOT_A_PORT) return;
uint8_t oldSREG = SREG; cli();
//*moderegister = mode; if (mode == OUTPUT) *moderegister = 0xff; else *moderegister = 0x00;
SREG = oldSREG; }
uint8_t portRead(uint8_t port) { volatile uint8_t *inputregister;
inputregister = portInputRegister(port);
if (inputregister == NOT_A_PORT) return;
uint8_t oldSREG = SREG; cli(); uint8_t portValue = *inputregister; SREG = oldSREG; return portValue; }
void portWrite(uint8_t port, uint8_t val) { volatile uint8_t *portregister;
portregister = portOutputRegister(port);
if (portregister == NOT_A_PORT) return;
uint8_t oldSREG = SREG; cli(); *portregister = val; SREG = oldSREG; } Example void setup() { portMode(PD, OUTPUT); }
void loop() { portWrite(PD, B0001000); delay(500); portWrite(PD, B0000000); delay(500); } Well... I can't understand this code
|
|
|
|
|
Logged
|
|
|
|
|
Guatemala
Offline
Newbie
Karma: 0
Posts: 16
|
 |
« Reply #23 on: September 18, 2011, 08:47:16 pm » |
My Wiring_digital.c have this: /* wiring_digital.c - digital input and output functions Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Modified 28 September 2010 by Mark Sproul
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ */
#include "wiring_private.h" #include "pins_arduino.h"
void pinMode(uint8_t pin, uint8_t mode) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *reg;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this? reg = portModeRegister(port);
if (mode == INPUT) { uint8_t oldSREG = SREG; cli(); *reg &= ~bit; SREG = oldSREG; } else { uint8_t oldSREG = SREG; cli(); *reg |= bit; SREG = oldSREG; } }
// Forcing this inline keeps the callers from having to push their own stuff // on the stack. It is a good performance win and only takes 1 more byte per // user than calling. (It will take more bytes on the 168.) // // But shouldn't this be moved into pinMode? Seems silly to check and do on // each digitalread or write. // // Mark Sproul: // - Removed inline. Save 170 bytes on atmega1280 // - changed to a switch statment; added 32 bytes but much easier to read and maintain. // - Added more #ifdefs, now compiles for atmega645 // //static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); //static inline void turnOffPWM(uint8_t timer) static void turnOffPWM(uint8_t timer) { switch (timer) { #if defined(TCCR1A) && defined(COM1A1) case TIMER1A: cbi(TCCR1A, COM1A1); break; #endif #if defined(TCCR1A) && defined(COM1B1) case TIMER1B: cbi(TCCR1A, COM1B1); break; #endif #if defined(TCCR2) && defined(COM21) case TIMER2: cbi(TCCR2, COM21); break; #endif #if defined(TCCR0A) && defined(COM0A1) case TIMER0A: cbi(TCCR0A, COM0A1); break; #endif #if defined(TIMER0B) && defined(COM0B1) case TIMER0B: cbi(TCCR0A, COM0B1); break; #endif #if defined(TCCR2A) && defined(COM2A1) case TIMER2A: cbi(TCCR2A, COM2A1); break; #endif #if defined(TCCR2A) && defined(COM2B1) case TIMER2B: cbi(TCCR2A, COM2B1); break; #endif #if defined(TCCR3A) && defined(COM3A1) case TIMER3A: cbi(TCCR3A, COM3A1); break; #endif #if defined(TCCR3A) && defined(COM3B1) case TIMER3B: cbi(TCCR3A, COM3B1); break; #endif #if defined(TCCR3A) && defined(COM3C1) case TIMER3C: cbi(TCCR3A, COM3C1); break; #endif
#if defined(TCCR4A) && defined(COM4A1) case TIMER4A: cbi(TCCR4A, COM4A1); break; #endif #if defined(TCCR4A) && defined(COM4B1) case TIMER4B: cbi(TCCR4A, COM4B1); break; #endif #if defined(TCCR4A) && defined(COM4C1) case TIMER4C: cbi(TCCR4A, COM4C1); break; #endif #if defined(TCCR5A) case TIMER5A: cbi(TCCR5A, COM5A1); break; case TIMER5B: cbi(TCCR5A, COM5B1); break; case TIMER5C: cbi(TCCR5A, COM5C1); break; #endif } }
void digitalWrite(uint8_t pin, uint8_t val) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off // before doing a digital write. if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
if (val == LOW) { uint8_t oldSREG = SREG; cli(); *out &= ~bit; SREG = oldSREG; } else { uint8_t oldSREG = SREG; cli(); *out |= bit; SREG = oldSREG; } }
int digitalRead(uint8_t pin) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off // before getting a digital reading. if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH; return LOW; }
void portMode(uint8_t port, uint8_t mode) { volatile uint8_t *moderegister;
moderegister = portModeRegister(port);
if (moderegister == NOT_A_PORT) return;
uint8_t oldSREG = SREG; cli();
//*moderegister = mode; if (mode == OUTPUT) *moderegister = 0xff; else *moderegister = 0x00;
SREG = oldSREG; }
uint8_t portRead(uint8_t port) { volatile uint8_t *inputregister;
inputregister = portInputRegister(port);
if (inputregister == NOT_A_PORT) return;
uint8_t oldSREG = SREG; cli(); uint8_t portValue = *inputregister; SREG = oldSREG; return portValue; }
void portWrite(uint8_t port, uint8_t val) { volatile uint8_t *portregister;
portregister = portOutputRegister(port);
if (portregister == NOT_A_PORT) return;
uint8_t oldSREG = SREG; cli(); *portregister = val; SREG = oldSREG; } now how to use it? :S Well I tried to add it to regular code and it doesn't work... sends me a lot of errors :/ even if I put the functions on the C program...
|
|
|
|
« Last Edit: September 18, 2011, 08:57:37 pm by jrlc »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 249
Posts: 16540
Available for Design & Build services
|
 |
« Reply #24 on: September 18, 2011, 08:57:56 pm » |
The example was given back reply #11
void setup() { portMode(PD, OUTPUT); // sets the pins in Port D to be outputs }
void loop() { portWrite(PD, B0001000); //sets the Port D outputs to B00001000 delay(500); portWrite(PD, B0000000); //sets the Port D outputs to B00000000 delay(500); } and I imagine that byte variablePort = portRead (PD); would read the port bit states into variablePort
|
|
|
|
|
Logged
|
|
|
|
|
Guatemala
Offline
Newbie
Karma: 0
Posts: 16
|
 |
« Reply #25 on: September 18, 2011, 09:06:15 pm » |
The example was given back reply #11
void setup() { portMode(PD, OUTPUT); // sets the pins in Port D to be outputs }
void loop() { portWrite(PD, B0001000); //sets the Port D outputs to B00001000 delay(500); portWrite(PD, B0000000); //sets the Port D outputs to B00000000 delay(500); } and I imagine that byte variablePort = portRead (PD); would read the port bit states into variablePort
yes, I copied that and added the functions but it sends me a lot of errors. I copied into the c progrman under the void loop function also I copied into the wiring_digital.c but it still sending me errors...
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 77
Arduino rocks
|
 |
« Reply #26 on: September 19, 2011, 12:27:26 am » |
Sorry my fault you also have to put function prototypes in "Arduino.h". Function prototypes are; void portMode(uint8_t port, uint8_t mode); uint8_t portRead(uint8_t port); void portWrite(uint8_t port, uint8_t val);
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Edison Member
Karma: 15
Posts: 1009
Arduino rocks
|
 |
« Reply #27 on: September 19, 2011, 12:43:25 am » |
How is value = portRead(PB); different from value = PINB; besides being a lot slower to execute? Pretty much the same thing for the other two. Edit: fixing code tags...
|
|
|
|
« Last Edit: September 19, 2011, 07:14:37 pm by WizenedEE »
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 77
Arduino rocks
|
 |
« Reply #28 on: September 19, 2011, 03:08:10 am » |
@WizenedEE
Yes you are right, direct hardware usage is always faster than prototype functions. But most of Arduino users including me have not electronic background. For us really hard to understand MCU hardware basics. And the aim of Arduino platform is to make the usage of microcontroller easier to everyone. IMO with these port functions every Arduino user can easily use the ports.
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6830
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #29 on: September 19, 2011, 06:53:48 am » |
I think there are some potential gotchas with this code uint8_t oldSREG = SREG; cli(); uint8_t portValue = *inputregister; SREG = oldSREG; return portValue; What if you get an interrupt after you save SREG but before the cli()? I think you should swap those two lines. And what if you get one that modifies the port after the SREG restore but before the return? In this case I guess it's essentially the same as a port changing state just after you read it so maybe no harm done. ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
|