Reading a 5 bit encoder on a Port with 0ne instruction

Hi,
I am fairly new to Arduino and is using a Due to experiment with a 5 bit encoder giving me 0 to 31 decimal positions in a project where I will eventually run at high speed of 50 microseconds per count and perhaps less on a machine to be developed.
I am doing it in a primitive way at present because I am not familiar with the Due port reading abilities and instructions and my programming is limited to the basic Arduino library.
Can you advise me on a how to convert the code below to a much better and faster code please?


// Author Cobus Verster 13 May 2021,
//5 bit position sensor and terminal printing position test 01.
//Speed in this test is not important,but will be later.


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

const int Bt1 = 25; //lsb this does not have to be these pins,
const int Bt3 = 29;
const int Bt4 = 31;
const int Bt5 = 33; //msb*/
int BIT5state = 0;
int BIT4state = 0;
int BIT3state = 0;
int BIT2state = 0;
int BIT1state = 0;
int bitcount = 0;
void sensoread();
void decposition();
void printposition();
void setup()
{
pinMode(Bt5, INPUT);//msb
pinMode(Bt4, INPUT);
pinMode(Bt3, INPUT);
pinMode(Bt2, INPUT);
pinMode(Bt1, INPUT);//lsb*/
Serial.begin(9600);
}
void loop()
{
sensoread();
decposition();
printposition();
}
void sensoread()
{
BIT1state = digitalRead(Bt1);
BIT2state = digitalRead(Bt2);
BIT3state = digitalRead(Bt3);
BIT4state = digitalRead(Bt4);
BIT5state = digitalRead(Bt5);
}
void decposition()
{
if (BIT1state == LOW && BIT2state == LOW && BIT3state == LOW && BIT4state == LOW && BIT5state == LOW)
{
bitcount = 0;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == LOW && BIT4state == LOW && BIT5state == LOW)
{
bitcount = 1;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == LOW && BIT4state == LOW && BIT5state == LOW)
{
bitcount = 2;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == LOW && BIT4state == LOW && BIT5state == LOW)
{
bitcount = 3;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == HIGH && BIT4state == LOW && BIT5state == LOW)
{
bitcount = 4;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == HIGH && BIT4state == LOW && BIT5state == LOW )
{
bitcount = 5;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == HIGH && BIT4state == LOW && BIT5state == LOW )
{
bitcount = 6;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == HIGH && BIT4state == LOW && BIT5state == LOW )
{
bitcount = 7;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == LOW && BIT4state == HIGH && BIT5state == LOW )
{
bitcount = 8;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == LOW && BIT4state == HIGH && BIT5state == LOW )
{
bitcount = 9;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == LOW && BIT4state == HIGH && BIT5state == LOW )
{
bitcount = 10;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == LOW && BIT4state == HIGH && BIT5state == LOW)
{
bitcount = 11;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == HIGH && BIT4state == HIGH && BIT5state == LOW)
{
bitcount = 12;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == HIGH && BIT4state == HIGH && BIT5state == LOW)
{
bitcount = 13;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == HIGH && BIT4state == HIGH && BIT5state)
{
bitcount = 14;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == HIGH && BIT4state == HIGH && BIT5state == LOW)
{
bitcount = 15;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == LOW && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 16;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == LOW && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 17;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == LOW && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 18;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == LOW && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 19;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == HIGH && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 20;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == HIGH && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 21;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == HIGH && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 22;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == HIGH && BIT4state == LOW && BIT5state == HIGH)
{
bitcount = 23;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == LOW && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 24;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == LOW && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 25;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == LOW && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 26;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == LOW && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 27;
}
if (BIT1state == LOW && BIT2state == LOW && BIT3state == HIGH && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 28;
}
if (BIT1state == HIGH && BIT2state == LOW && BIT3state == HIGH && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 29;
}
if (BIT1state == LOW && BIT2state == HIGH && BIT3state == HIGH && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 30;
}
if (BIT1state == HIGH && BIT2state == HIGH && BIT3state == HIGH && BIT4state == HIGH && BIT5state == HIGH)
{
bitcount = 31;
}
}
Void printposition()
{
Serial.println(" Position : ");
Serial.print(bitcount);
delay(100);
}

The easier you make it to read and copy the code the more likely it is that you will get help

Please follow the advice given in the link below when posting code , use code tags and post the code here

Google Arduino due direct port access
Be aware that a Due differs from AVR based boards, so you will have to filter.

One link of many: Arduino DUE How to Direrct Port Access?.

Other post/duplicate DELETED
Please do NOT cross post / duplicate as it wastes peoples time and efforts to have more than one post for a single topic.

Continued cross posting could result in a time out from the forum.

Could you also take a few moments to Learn How To Use The Forum.

Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

Hi,
What is the application?
Why do you need a 50uS period count?

All those if statements can be replaced by switch.. case..
Also make each of the parallel inputs have a binary value, then each combination of inouts will have a unique number that you can use with switch.. case.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

Hi,
Thank for replying. The 50us is the amount of time the sensor bit will visible on a specific bit. The sensor is a disc and the rotating speed gives me 50 us to see the bit, All 5 bits in parallel on the port can change within 50us. So I need to read the whole port hopefully twice in 50us as I see it. The outcome is 32 positions which my machine will need to make 32 decisions based on the position sensor indication.
I will certainly try Switch......case option, but is hoping for a port read as a byte with 3 zeros for MSB`s and I use the 5 LSB bits to read the position in binary or decimal preferably.

Use shift and add of the 5 input bits.
Position = bit1 + bit2<< 1 + bit3<<2 + bit4<<3 + bit5<< 4.

Eventually use the boolean OR operator.

What @sterretje said #3.

https://www.arduino.cc/en/Reference/PortManipulation

if you are overwhelmed by google, or you don't have it in your area.

I used that link recently to go from near zero, an idea, to a working function that reads four bits on the D port of an UNO, so.

Do not be intimidated, just put in the time it will take to read and adapt the information it covers.

Edit: Sry, I am hasty. The Due is evident a different animal, so google and follow Due specific links…

a7

Hi Railroader,
Thank you, this is very new to me, I will give a go. I dont quite follow the bit about boolean and OR ?
Regards
Cobus

Thank you @sterretje! Yes the Due does not use DDR etc. It is not in the Arduino library. So I am searching for an example or description now. This is just one of my avenues now.
Thank you for taking the time to answer and support!
Regards
Cobus

Thank you sterretje for the Arduino Due link, I found some interesting things there that I will try out!
Regards
Cobus

HI Sterretje, I am new to this blog and I am sending replies in the wrong places, please bear with me!!!!!!!!!

Guys, in my pursuit to address a port directly and with all the bits and pieces you all were so generous to give me, I have been able to put 2 sketches together, but not one of them turns the LED on yet. I did get the pin layout and port table for the Due and believe I worked with it.
Perhaps I misunderstand the Pin and port affiliation and that is why I include both sketches to ask for your guidance please.
In both cases the Serial print terminal prints LED ON and LED OFF, but no switching takes place.
Example code 1.

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

#define pinnum 33
#define pinport PIOC
#define pinmask (1<<33)

void setup() {
PIOC->PIO_PER = 0x01FF;
PIOC->PIO_OER = 0x01FF; // Configure PORTD to PIO controller, pins 33-40

pinMode (pinnum, OUTPUT) ; // I dont understand why this is here as the previous instruction does that?
Serial.begin(9600);
}

void loop() {
pinport -> PIO_SODR = pinmask ; // set pin
Serial.print(" LED ON");
delay (1000) ;
pinport -> PIO_CODR = pinmask ; // clear pin
Serial.println(" LED OFF");
delay (1000) ;

}

Example 2

#include <stdio.h>
#include <stdlib.h>
int LED = 34;

void setup() {
PIOC->PIO_PER = 0x01FF;
PIOC->PIO_OER = 0x01FF; // Configure PORTD to PIO controller, pins 33-40
PIOC->PIO_ODSR = 0x01FF;// Enable PORTD to output .... // Write something on pins 33-40.
pinMode (LED, OUTPUT) ;
Serial.begin(9600);

}

void loop()
{
REG_PIOC_SODR |= (0x01 << 34); // Turn on the LED
Serial.print(" LED OFF: ");
delay(1000);
REG_PIOC_CODR |= (0x01 << 34); // Turn off the LED using the CODR register
Serial.print(" LED ON : ");
delay(1000);
}

Guys, here is my 1st attempt to read PortC pins 33 to 40. I tried (int Bitstate and byte Bitstate) with no change. It does not see the input changing.
Example of PortC Read.

#include <stdio.h>
#include <stdlib.h>
void setup() {
PIOC->PIO_PER = 0x01FF;// write 1’s here to override other peripherals and allow GPIO use for pins
PIOC->PIO_ODR = 0x01FF;// write 1’s here to set pins as INPUT
Serial.begin(9600);
}

void loop() {
byte Bitstate = PIOC->PIO_PDSR;// - read’s actual state of the pins on the port.
Serial.print(" Bitstate : ");
Serial.println(Bitstate);
delay(1000);
}

Guys,
I just managed to get the Port C write to pins 33 to 40 working.
Code is attached.

void setup() {
PIOC->PIO_PER = 0x01FF;
PIOC->PIO_OER = 0x01FF; // Configure PORTD to PIO controller, pins 33-40
Serial.begin(9600);
}

void loop() {
REG_PIOC_SODR |= (0x01FF); // Turn on the LED
Serial.print(" LED ON");
delay (1000) ;
REG_PIOC_CODR |= (0x01FF); // Turn off the LED using the CODR register
Serial.print(" LED OFF");
byte Bitstate = REG_PIOC_CODR;
Serial.print(" : Bitstate : ");
Serial.println(Bitstate);
delay (1000) ;
}

Guys, the last example code I sent you only works when I switch them all on and off. I tried 0B00000001 and 0B00000111 and that does nothing.

Hi,
Try this bit of code, it is supposed to flash pin 33.

void setup() 
{
  pinMode(33, OUTPUT); 
  REG_PIOC_OWER = 0x00000002; 
  REG_PIOC_OWDR = 0xfffffffd; 
}

void loop() 
{
  REG_PIOC_ODSR = 0x00000002; 
  delay(1000);             
  REG_PIOC_ODSR = 0x00000000;    
  delay(1000);   
}

I got it from this thread.

Tom.... :grinning: :+1: :coffee: :australia:

Hi Tom, Thanks a million! It does indeed. I need to find out why 0x00000002; works on pin 33. But thanks for the link, appreciate it.

Hi,
Good to hear, I had to use port manipulation for a SSI interface about 3 years ago, the DUE was used because of the speed.
Its been a while since I've had a play, must dig my DUE out and see.

Tom.... :grinning: :+1: :coffee: :australia:

Hi Tom,
I visited the link where you pointed to and read the explanation. I need to read a port with 5 inputs with 1 instruction into a byte or int and write to 4 outputs as well, with 1 instruction if possible, but the information I read is still vague for me. I can do pin 33 and can write to 8 pins at the same time but all on or off. The 0xfffffffd is a very big number in decimal and I dont see logic in this to be able to calculate the value for pins 34 to 40!
But I will keep on reading! Thanks.