pin mapping ?

Hey I added the ability of a serial control library to poll the status of a pin by checking the port bit, its fairly straightforward reading it and it works, but it takes alot of space to read every pin and print out what is requesting, basically 70 if( statements I couldn't see a for( statement being useful due to the non linear mapping of pins I was wondering if there was a built in reference to port bit named after each pin so instead of 70 if( it'd be like

serial.print(x); serial.print(" == "); serial.println(_pin(x) & 1);

_Pin(x) being some internal reference to PORTX(x) If anyone knows of such a thing or even just something shorter than 1 command per pin

You have a reason not to use digitalRead()???

Have you an example of your code, maybe it could be optimised.

You said a for loop wouldn't work, but if you had an array of the ports you wanted to test, then you could loop through that array testing ports.

Still it sounds interesting.

  for (int pin = 0 ; pin <= 19 ; pin++)
  {
    Serial.print(pin);
    Serial.print(" == ");
    Serial.println(digitalRead (pin));
  }

Heres my code right now, i just send a block of the status instead of if statements for now

 #include "Scon.H"

  	int _incoming = 0;
	int _command[4] = {0, 0, 0, 0};
	int _place = 0;
	int _pin = 99;
	int _pinstatus;
	int _aval = 0;
        long _timeout;


 void Scon::listen(){
    if(millis() - _timeout > 250){
    _timeout = millis();
    _place = 0;
    Serial.flush();
    }
      if(Serial.available() > 0){
    _incoming = (Serial.read());
    if(_incoming != 13 && _incoming != 10){
    _command[_place] = _incoming;
    _place++;
    }
    }

    if(_place >=3 && _aval == 1){
    _place = 0;
    _aval = 0;
    _aval = _command[0] - 48;
    _aval = _aval * 10;
    _aval +=_command[1] -48;
    _aval = _aval * 10;
    _aval += _command[2] -48;
    analogWrite(_pin, _aval);
    _aval = 0;
    Serial.flush();
    } 


    if(_place >= 4){
      _place = 0;
    Serial.flush();

      if(_command[0] == 'P' && _command[1] == 'I' && _command[2] == 'N' && _command[3] == 'G') Serial.write('A');
      if(_command[0] == 'R' && _command[1] == 'E' && _command[2] == 'A' && _command[3] == 'D') read();
      if(_command[0] == 'T' && _command[1] == 'E' && _command[2] == 'S' && _command[3] == 'T') test();
      if(_command[0] == 'A' && _command[1] == 'O' && _command[2] == 'F' && _command[3] == 'F') off();
 
      _pin = _command[0] - 48;
      _pin = _pin * 10;
      _pin += _command[1] - 48;

      if(_command[2] == 'O'){
      pinMode(_pin, 1);
      _pinstatus = _command[3];
         if(_command[3] != 'A'){
         _pinstatus = _command[3] - 48;
         digitalWrite(_pin, _pinstatus);
         }
         if(_command[3] == 'A'){
         _aval = 1;
         }
      }
      
      if(_command[2] == 'I'){
         if(_command[3] == 'D'){
         pinMode(_pin, 0);
         Serial.println(digitalRead(_pin));
         }
         if(_command[3] == 'A'){
         analogRead(_pin);
	 Serial.println(analogRead(_pin));
         }
      }      

       }
      }

void Scon::start(){
      Serial.begin(57600);
}

void Scon::test(){
for(int i = 0; i < 70; i++){
pinMode(i, 1);
digitalWrite(i, 1);
}
}

void Scon::off(){
for(int i = 0; i < 70; i++){
pinMode(i, 0);
digitalWrite(i, 0);
}
}

void Scon::read(){
Serial.print("2 is ");
Serial.println(bitRead(PORTE, 0));
Serial.print("3 is ");
Serial.println(bitRead(PORTE, 5));
Serial.print("4 is ");
Serial.println(bitRead(PORTG, 5));
Serial.print("5 is ");
Serial.println(bitRead(PORTE, 5));
Serial.print("6 is ");
Serial.println(bitRead(PORTH, 3));
Serial.print("7 is ");
Serial.println(bitRead(PORTH, 4));
Serial.print("8 is ");
Serial.println(bitRead(PORTH, 5));
Serial.print("9 is ");
Serial.println(bitRead(PORTH, 6));
Serial.print("10 is ");
Serial.println(bitRead(PORTB, 4));
Serial.print("11 is ");
Serial.println(bitRead(PORTB, 5));
Serial.print("12 is ");
Serial.println(bitRead(PORTB, 6));
Serial.print("13 is ");
Serial.println(bitRead(PORTB, 7));
Serial.print("14 is ");
Serial.println(bitRead(PORTJ, 1));
Serial.print("15 is ");
Serial.println(bitRead(PORTJ, 0)); 
Serial.print("16 is ");
Serial.println(bitRead(PORTH, 1));
Serial.print("17 is ");
Serial.println(bitRead(PORTH, 0));
Serial.print("18 is ");
Serial.println(bitRead(PORTD, 3));
Serial.print("19 is ");
Serial.println(bitRead(PORTD, 2));
Serial.print("20 is ");
Serial.println(bitRead(PORTD, 1));
Serial.print("21 is ");
Serial.println(bitRead(PORTD, 0));
Serial.print("22 is ");
Serial.println(bitRead(PORTH, 5));
Serial.print("23 is ");
Serial.println(bitRead(PORTA, 0));
Serial.print("24 is ");
Serial.println(bitRead(PORTA, 2));
Serial.print("25 is ");
Serial.println(bitRead(PORTA, 3));
Serial.print("26 is ");
Serial.println(bitRead(PORTA, 4));
Serial.print("27 is ");
Serial.println(bitRead(PORTA, 5));
Serial.print("28 is ");
Serial.println(bitRead(PORTA, 6));//FIND
Serial.print("29 is ");
Serial.println(bitRead(PORTA, 7)); 
Serial.print("30 is ");
Serial.println(bitRead(PORTC, 7));
Serial.print("31 is ");
Serial.println(bitRead(PORTC, 6));
Serial.print("32 is ");
Serial.println(bitRead(PORTC, 5));
Serial.print("33 is ");
Serial.println(bitRead(PORTC, 4));
Serial.print("34 is ");
Serial.println(bitRead(PORTC, 3));
Serial.print("35 is ");
Serial.println(bitRead(PORTC, 2));
Serial.print("36 is ");
Serial.println(bitRead(PORTC, 1));
Serial.print("37 is ");
Serial.println(bitRead(PORTC, 0));
Serial.print("38 is ");
Serial.println(bitRead(PORTD, 7));
Serial.print("39 is ");
Serial.println(bitRead(PORTG, 2));
Serial.print("40 is ");
Serial.println(bitRead(PORTG, 1));
Serial.print("41 is ");
Serial.println(bitRead(PORTG, 0));
Serial.print("42 is ");
Serial.println(bitRead(PORTL, 7));
Serial.print("43 is ");
Serial.println(bitRead(PORTL, 6)); 
Serial.print("44 is ");
Serial.println(bitRead(PORTL, 5));
Serial.print("45 is ");
Serial.println(bitRead(PORTL, 4));
Serial.print("46 is ");
Serial.println(bitRead(PORTL, 3));
Serial.print("47 is ");
Serial.println(bitRead(PORTL, 2));
Serial.print("48 is ");
Serial.println(bitRead(PORTL, 1));
Serial.print("49 is ");
Serial.println(bitRead(PORTL, 0));
Serial.print("50 is ");
Serial.println(bitRead(PORTB, 3));
Serial.print("51 is ");
Serial.println(bitRead(PORTB, 2));
Serial.print("52 is ");
Serial.println(bitRead(PORTB, 1));
Serial.print("53 is ");
Serial.println(bitRead(PORTB, 0));
Serial.print("A0 is ");
Serial.println(bitRead(PORTF, 0));
Serial.print("A1 is ");
Serial.println(bitRead(PORTF, 1));
Serial.print("A2 is ");
Serial.println(bitRead(PORTF, 2));
Serial.print("A3 is ");
Serial.println(bitRead(PORTF, 3));
Serial.print("A4 is ");
Serial.println(bitRead(PORTF, 4));
Serial.print("A5 is ");
Serial.println(bitRead(PORTF, 5));
Serial.print("A6 is ");
Serial.println(bitRead(PORTF, 6));
Serial.print("A7 is ");
Serial.println(bitRead(PORTF, 7));
Serial.print("A8 is ");
Serial.println(bitRead(PORTK, 0));
Serial.print("A9 is ");
Serial.println(bitRead(PORTK, 1));
Serial.print("A10 is ");
Serial.println(bitRead(PORTK, 2));
Serial.print("A11 is ");
Serial.println(bitRead(PORTK, 3));
Serial.print("A12 is ");
Serial.println(bitRead(PORTK, 4));
Serial.print("A13 is ");
Serial.println(bitRead(PORTK, 5)); 
Serial.print("A14 is ");
Serial.println(bitRead(PORTK, 6));
Serial.print("A15 is ");
Serial.println(bitRead(PORTK, 7)); 

}

So as Mark asked, why don't you want to use digitalRead() to read the pin values?

All those lines would collapse down into a small loop.

It would also make it much easier to run on different AVR chips.

--- bill

you can also use the PORT’s construct and the for loop by setting up two arrays

int   PORTS[] = { PORTE, PORTE, PORTG, ..... };
uint8_t BIT[] = {2,5,5, .....};

for (int i=0; i< xx; i++)
{
  Serial.print(i+2);
  Serial.print(" is ");
  Serial.println(bitRead(PORT[i] , BIT[i]));
}

Even better, make an array of structs which contain the PORT and BIT fields

get the idea?

Unless you are creating pin mappings that are different from
the the Arduino core library mapping tables why bother?

BTW, there are pin & bit mask mapping tables available
through macros provided in <pins_arduino.h>
digitalPinToPort(P)
digitalPinToBitMask(P)

I’m still curious as to the need to avoid digitalRead() especially
since other parts of the code use digitalWrite().

— bill

Good point Bill,

Also your question about digitalRead() If the OP uses 115200 iso 57600 for baudtrate a lot of time is gained ...

Ok, so if raw speed is the concern, I’m not so sure that the direct
port access in this case will be that much of a benefit to make a real difference.

a digitalRead() is a little over 4us on a 16mz AVR but a character time even at 115200 is about 87us.
(using about 10 bits/char = 10/115200 = .00086805 sec/char = .0868 ms/char = 86.8us/char)
Even if you reduced the time of reading/checking the port bit to 0 instead of 4us,
the percentage of the total time it takes to print everything will not be very much
since there is so much serial character output.

There are 68 pins being examined and printed.
Here is the breakdown: (assuming each line terminates with both a and )
8x8chars+44x9chars+10x9chars+6x9chars = 604 chars = 604 chars x 86.8 us/char = 52427 us = 52.43 ms

If you used digitalRead() on the 68 pins, that would be 68 x 4 = 272 us.
Even if you could reduce that to zero with a direct port access
(which you can’t especially if it is done in a loop), that
would allow only eliminating 272 us while the printing at 115200 still
takes 52,427 us.
or as a percentage: 272/52427 = .005188 = %0.52 or less than 1% overall increase.
In other words the “slow” digitalRead() port access method adds less than 1% to the total time overhead
vs being able to read the port in zero time.

But in reality it will be less difference than that because you can’t
read the bits from the ports in zero time. Even if you did it all inline,
you will more than likely need at least 4-5 instructions per access to test the bit
branch around the result and load the register pair with 0/1 for the call to print().
i.e. (5instructions x 62.5ns/instruction x 68 accesses = 21250ns = 21.25us)
So no more than about 250us total difference between raw inline accesses vs digitalRead()

So even for inline raw port access vs digitalRead() I’m not seeing “a lot of time” gained
since the vast majority of the time overhead is from the serial data transfer time and not the the port accesses.

— bill

Wow, I honestly never tried to just used digitalread
I thought it needed to set as input for it to work
just tried it I and wow I can’t believe it was that simple
bad case of overthinking something, thanks for the help

If you want high speed access then digitalRead() might be an issue as it has a definite speed overhead, but I figured if you are calling Serial.print() then speed wasn't critical...

I thought it needed to set as input for it to work

Nope. If the pin is set as output, the value of the port's register is returned. A handy way for code to find out the status of an output pin.

As already mentioned, there is some overhead involved. But as you have learned, anytime there is mapping involved there is going to be overhead.

    Serial.flush();

Do you know what this does? If not, why are you calling it.

If so, then please explain why you want to throw away random amounts of unread data.

    _aval = _command[0] - 48;

_aval = command[0] - '0'; is so much easier to understand.

      if(_command[0] == 'P' && _command[1] == 'I' && _command[2] == 'N' && _command[3] == 'G') Serial.write('A');
      if(_command[0] == 'R' && _command[1] == 'E' && _command[2] == 'A' && _command[3] == 'D') read();
      if(_command[0] == 'T' && _command[1] == 'E' && _command[2] == 'S' && _command[3] == 'T') test();
      if(_command[0] == 'A' && _command[1] == 'O' && _command[2] == 'F' && _command[3] == 'F') off();

Properly NULL terminating the array would allow you to use strncmp() to make the code much shorter and easier to understand (and maintain).

I thought it needed to set as input for it to work

Pins are input by default. They can only be input or output, there is no other state they can be in. If input then the pullups can be selected by 'writing' the pin HIGH (this is a useful feature). If output mode then digitalWrite drives them HIGH or LOW via the output transistors (which can handle upto a max of 40mA).