We are reading some signals from pins and setting some more events based on this reading.
To be safe, I want to sample the pins 3 times, compare the three values and use the most common value (i.e. sample A is 1, B is 3 and C is 1, I want to use 1, if A B and C are all 2 then use 2 but if A is 1 , B is 2 and C is 3, I want to capture the three samples again).
Currently I'm using:
int getCAPValues (void)
{
// Get three samples to check CAP signals are stable:
uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // First set of CAP values
for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // second set
for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // third set
if (x == y) || (x == z)
{
//use the x value
}
else if (y == z)
{
// use the y value
x = y;
}
else
{
x = -1;
}
return x;
}
But this doesn't seem very efficient to me, is there a better way to do this?
This is on a SAMD21 Xplained Pro development board in C.
EDIT:
I have changed the code as per answers, only reading the "z" value if it will be used, and using delay_us() instead of the dummy loops:
int getCAPValues (void)
{
// Get three samples to check CAP signals are stable:
uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // First set of CAP values
delay_us(1);
//for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // second set
// Using most common value, or error code of -1 if all different
if (!(x == y))
{
delay_us(1);
//for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // third set
if (x == z)
{
// use the x/z value
return x;
}
else if (y == z)
{
// use the y/z value
return y;
}
else
{
return -1;
}
}
return x;
}
If x==y
you're going to use the value of x
. So in that case you can dodge the third reading.
I don't know how volatile your values are but it could effectively almost double peformance to avoid that second delay if disputed values are in fact rare.
Indeed if they're not rare the whole rationale might be invalid.
int getCAPValues (void)
{
// Get three samples to check CAP signals are stable:
uint32_t x = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // First set of CAP values
for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t y = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // second set
if(x!=y){
//x & y are different. Get a tie-breaker...
for (uint32_t i = 0; i < 7; i++) dummy = i; // Pause
uint32_t z = (PORT->Group[IN_PORT_CAP].IN.reg & IN_PORT_CAP_MASK) >> IN_PORT_CAP_PIN; // third set
if (y == z) {
// use the y value
x = y;
} else if(x!=z){
//tie-breaking failed...
x=-1;
}
}
return x;
}
PS: I also think you should use `usleep()' rather than dummy loops. It depends what is available on your platform.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With