Printing out selected items from an enum flag - c++

I have the following enum (which later will grow larger!):
enum TrainingFilters {
NONE = 0,
GAUSS = 1,
SOBEL = 2,
FEATURE = 4
};
I have to print out string representation of the all possible combination. For now, a not-leangthy switch statement works fine, but if I add more items it will be disaster!
void Manager::setFilters(int filters)
{
QString what("Selected filters:");
switch (filters) {
case 0:
what.append(" NONE ");
break;
case 1:
what.append(" GAUSS ");
break;
case 1 | 2:
what.append(" GAUSS SOBEL ");
break;
case 2:
what.append(" SOBEL ");
break;
case 2 | 4:
what.append(" SOBEL FEATURE ");
break;
case 4:
what.append(" FEATURE ");
break;
case 1 | 4:
what.append(" GAUSS FEATURE ");
break;
case 1 | 2 | 4:
what.append(" GAUSS SOBEL FEATURE ");
break;
default:
qDebug() << "Invalid FILTERS enum received!";
return;
}
qDebug() << what;
mFilters = static_cast<TrainingFilters>(filters);
}
P.S: I have a few checkbox items in the user interface, and I should do some stuff according to the checked checkboxes. I use it like this:
var a, b,c;
cbGauss.checked ? a = 1 : a = 0;
cbSobel.checked ? b = 2 : b = 0;
cbFeat.checked ? c = 4 : c = 0;
cpManager.setFilters(a | b | c);
So my qustion is what is the best/easiest/smartest way to achieve this?

You could simply do
if (filters & 1)
what.append("GAUSS ");
if (filters & 2)
what.append("SOBEL ");
if (filters & 4)
what.append("FILTER ");
And so on. This way you can easily add new ones. Of course you have to check for zero and then add NONE.

Related

Creating a switch statement with multiple digital inputs? (c++, mbed, nucleo)

I am trying to compile a switch statement to create a combination lock of sorts from a nucleo board. At first I tried to tackle using multiple digital inputs in a switch statement by creating a bit mask and assigning integers, this seems to have gone alright however when I try to get my switch statement running it is stuck on case 0.
For a start case 0 should be no buttons pressed however it only activates once I press switch 1.
My second problem is that no other cases in my statement will activate at all.
I have no access to a debugger as mbed is not compatible with my nucleo board and I cannot get Keil Studio working so I am pretty stumped. Does anyone what is wrong with my statement or if there is an alternate way to refer to my digital inputs within the switch statement that may make it easier?
I am a coding n00b and have struggled to find much reference to my problem, any sample code I have looked at seems to work no problem and I cannot see where I have deviated from that code.
Code is below:
// You are to use these ojects to read the switch inputs
DigitalIn SW1(USER_BUTTON);
DigitalIn SW2(BTN1_PIN);
DigitalIn SW3(BTN2_PIN);
DigitalInOut SW4(BTN3_PIN, PIN_INPUT, PullDown, 0);
DigitalInOut SW5(BTN4_PIN, PIN_INPUT, PullDown, 0);
// You are to use this object to control the LEDs
BusOut leds(TRAF_RED1_PIN, TRAF_YEL1_PIN, TRAF_GRN1_PIN);
// Use this to sound an error
Buzzer alarm;
int main()
{
while (true)
{
leds = 0;
// Beep
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
// Wait for the blue button using a while loop
while (SW1==0) { };
// For full marks, debounce the switches with suitable delays
// This is a "combination lock" activity. Write some code to detect the following sequence of press-and-release inputs
// SW1, SW2, SW5, SW3 and SW4, SW2 and SW3
// If the full sequence is entered, correctly, the green LED should flash 3 times
// If a sequence of inputs was entered incorrectly, the red LED should light and the buzzer should sound for 5 seconds
// For full marks, debounce the switches and use flow control structures and arrays to avoid deep nesting of code
// ***** MODIFY THE CODE BELOW HERE *****
// ***** MODIFY THE CODE ABOVE HERE *****
int Inputs = (SW1==0) << 0 | (SW2==1) << 1 | (SW3==1) << 2 | (SW4==1) << 3 | (SW5==1) << 4;
int i;
switch (Inputs) {
case 0:
printf("Please Enter Combination\n");
if (false) {
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
leds = 4;
wait_us(5000000);
leds = 0;
}
break;
case 1:
printf("Input 1 is Correct\n");
if (false) {
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
leds = 4;
wait_us(5000000);
leds = 0;
}
break;
case 2:
printf("Input 2 is Correct\n");
if (false) {
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
leds = 4;
wait_us(5000000);
leds = 0;
}
break;
case 16:
printf("Input 3 is Correct\n");
if (false) {
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
leds = 4;
wait_us(5000000);
leds = 0;
}
break;
case 12:
printf("Input 4 is Correct\n");
if (false) {
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
leds = 4;
wait_us(5000000);
leds = 0;
}
break;
case 6:
printf("Combination is Correct!\n");
for (int i = 0; i < 3; i = i +1)
{
leds = 1;
wait_us(1000000);
leds = 0;
wait_us(1000000);
}
if (false) {
alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
wait_us(250000);
alarm.rest();
leds = 4;
wait_us(5000000);
leds = 0;
}
You can make a bitmask integer where each bit corresponds to the state of one button like this:
unsigned int inputs = (SW1==0) << 0 | (SW2==0) << 1 | (SW3==0) << 2 | (SW4==0) << 3 | (SW5==0) << 4;
If you haven't seen those operators before, << is a left shift operator and | is a logical OR operator and you can look them up in any decent C++ book or introductory resource.
Your switch statement might look like this:
switch(inputs) {
case 0: // No buttons pressed
break;
case 1: // SW1 pressed (bit 0 is 1)
break;
case 2: // SW2 pressed (bit 1 is 1)
break;
case 4: // SW3 pressed (bit 2 is 1)
break;
case 6: // SW2 and SW3 pressed
break;
case 8: // SW4 pressed (bit 4 is 1)
break;
// ...
case 31: // All switches pressed
break;
}

Reading CAN Bus bitmask

I have a netgain hyper9 motor and controller. Controller is hooked up to CAN bus. I am using an esp32 with mcp2515 to read the data. The format is as in the image here.
I can read a byte ok and get a number but can not correctly read the word (2bytes) nor can I get the correct bitmap.
I am using esphome to read this through a lambda function.
Are there any c++ / esphome lambda people that could help?
WORD FORMAT: All words are sent in Little-endian format which reverses the order and stores the least significant byte at the lower memory address with the most significant byte being stored at the highest memory address.
byte word format:
reading a bitmask:
reading rpm through 2 byte word:
canbus:
- platform: mcp2515
id: my_mcp2515
spi_id: McpSpi
cs_pin: GPIO14
can_id: 2
use_extended_id: false
bit_rate: 250KBPS
clock: 8MHZ
mode: NORMAL
on_frame:
- can_id: 0x301 #[canbus:066]: received can message std can_id=0x301 size=8
use_extended_id: false
then:
- lambda: |-
//State of Charge - works ok
int soc = x[2];
id(motor_battery_soc).publish_state(soc);
//RPM - word format
std::string r1 = to_string(x[0]);
std::string r2 = to_string(x[1]);
std::string rpmString = r2 + r1;
id(motor_rpm).publish_state(rpmString);
//System flags
ESP_LOGD("system_flags x3: ", "%d", x[3] );
ESP_LOGD("system_flags x4: ", "%d", x[4] );
std::string sf1 = to_string(x[3]);
std::string sf2 = to_string(x[4]);
std::string sfString = sf2 + sf1;
std::string sflag = " ";
ESP_LOGD("main", "sfString: %s", sfString);
// *** I know this is not correct because should search for a true/false flag on the bitmask ***
int sfInt = atoi(sfString.c_str());
ESP_LOGD("sfInt: ", "%d", sfInt);
switch(sfInt) {
case 0:
sflag = "SoC is Low For Traction";
id(motor_system_flags).publish_state("SoC is Low For Traction");
break;
case 1:
sflag = "SoC is Low For Hydraulic";
id(motor_system_flags).publish_state("SoC is Low For Hydraulic");
break;
case 2:
sflag = "Reverse Direction Active";
id(motor_system_flags).publish_state("Reverse Direction Active");
break;
case 3:
sflag = "Forward Direction Active";
id(motor_system_flags).publish_state("Forward Direction Active");
break;
case 4:
sflag = "Park Brake Active";
id(motor_system_flags).publish_state("Park Brake Active");
break;
case 5:
sflag = "Pedal Brake Active";
id(motor_system_flags).publish_state("Pedal Brake Active");
break;
case 6:
sflag = "Controller is in Overtemperature";
id(motor_system_flags).publish_state("Controller is in Overtemperature");
break;
case 7:
sflag = "Key Switch Overvoltage";
id(motor_system_flags).publish_state("Key Switch Overvoltage");
break;
case 8:
sflag = "Key Switch Undervoltage";
id(motor_system_flags).publish_state("Key Switch Undervoltage");
break;
case 9:
sflag = "Vehicle is Running";
id(motor_system_flags).publish_state("Vehicle is Running");
break;
case 10:
sflag = "Traction is Enabled";
id(motor_system_flags).publish_state("Traction is Enabled");
break;
case 11:
sflag = "Hydraulic is Enabled";
id(motor_system_flags).publish_state("Hydraulic is Enabled");
break;
case 12:
sflag = "Powering is Enabled";
id(motor_system_flags).publish_state("Powering is Enabled");
break;
case 13:
sflag = "Powering is Ready";
id(motor_system_flags).publish_state("Powering is Ready");
break;
case 14:
sflag = "Powering is Precharging";
id(motor_system_flags).publish_state("Powering is Precharging");
break;
case 15:
sflag = "Main Contactor Closing";
id(motor_system_flags).publish_state("Main Contactor Closing");
break;
default:
sflag = "No System Flag";
break;
}
id(motor_system_flags).publish_state(sflag);
//Fault code
int fault_code = x[5];
id(motor_fault_code).publish_state(fault_code);
//Motor Temp
int temp = x[6] - 40;
id(motor_temp).publish_state(temp);
text_sensor:
- platform: template
id: motor_system_flags
name: "Motor System Flags"
- platform: template
id: motor_rpm
name: "Motor RPM"
sensor:
- platform: template
id: motor_battery_soc
name: "Motor Battery SoC"
accuracy_decimals: 0
- platform: template
id: motor_fault_code
name: "Motor Fault Code"
- platform: template
id: motor_temp
name: "Motor Temp"
accuracy_decimals: 0

Defining variables esp32

i am trying to figure out a way in esp32 to have (a list) for lack of better terms, that i could call upon as a variable input. I have a void playwav(); function. I want to use a global variable to define the file that should be played. ie playwav('alarm'). I had a case switch setup but was using the a b c method. As my code is growing (next step is going to add 71 new wav files), i am quickly realizing that method will no longer work. I have been told to do an array but for the life of me no matter what ive read i just cant grasp how to do it nor call upon the files by name. Does anyone have advice on what i should do? Any help is much appreciated.
This is what i currently have.
void playWAV (char effect, int bg1248_general_volume)
{
Serial.println("Entered playWAV");
switch (effect)
{
case 'a':
file = new AudioFileSourceSD("/wav/alarm.wav");
break;
case 'b':
file = new AudioFileSourceSD("/wav/alarmhigh.wav");
break;
case 'c':
file = new AudioFileSourceSD("/wav/alarmlow.wav");
break;
case 'd':
file = new AudioFileSourceSD("/wav/error.wav");
break;
case 'e':
file = new AudioFileSourceSD("/wav/error1.wav");
break;
case 'f':
file = new AudioFileSourceSD("/wav/noread.wav");
break;
case 'g':
file = new AudioFileSourceSD("/wav/noreadings.wav");
break;
case 'h':
file = new AudioFileSourceSD("/wav/normalrange.wav");
break;
case 'i':
file = new AudioFileSourceSD("/wav/warning.wav");
break;
case 'j':
file = new AudioFileSourceSD("/wav/warninghigh.wav");
break;
case 'k':
file = new AudioFileSourceSD("/wav/warninglow.wav");
break;
case 'l':
file = new AudioFileSourceSD("/wav/startup.wav");
break;
case 'm':
file = new AudioFileSourceSD("/wav/startup.wav");
break;
case 'n':
file = new AudioFileSourceSD("/wav/update.wav");
break;
case 'o':
file = new AudioFileSourceSD("/wav/startup_dev.wav");
}
float volumeGain = ((float)bg1248_general_volume / 100.0) * 39.0;
Serial.print("volumeGain:");
Serial.println(volumeGain);
id3 = new AudioFileSourceID3(file);
out = new AudioOutputI2S(0, 0); // Output to builtInDAC
out->SetPinout(12, 0, 2);
out->SetOutputModeMono(true);
out->SetGain(volumeGain);
wav = new AudioGeneratorWAV();
wav->begin(id3, out);
However because I used the alphabet im going to run out of cases very very soon. I want to be able to call for a specific wav file anywhere in the project preferably like playWAV(filename) or something similar.
I call the function(file) like this (example condition)
if((ns->sensSgv<=cfg.snd_alarm) && (ns->sensSgv>=0.1)) {
// red alarm state
// M5.Lcd.fillRect(110, 220, 100, 20, TFT_RED);
Serial.println("ALARM LOW");
M5.Lcd.fillRect(0, 220, 320, 20, TFT_RED);
M5.Lcd.setTextColor(TFT_BLACK, TFT_RED);
int stw=M5.Lcd.textWidth(tmpStr);
M5.Lcd.drawString(tmpStr, 159-stw/2, 220, GFXFF);
if( (alarmDifSec>cfg.alarm_repeat*60) && (snoozeRemaining<=0) ) {
playWAV('a', 100);
'a'=case 100 = volume.
Alan, this is what I currently had in my enum, i was following a tutorial but doubt i did it right. even if i did i was getting errors saying i had duplicate cases when i don't.
EDIT:
The condition is set using this:
if((ns->sensSgv<=cfg.snd_alarm) && (ns->sensSgv>=0.1))
and if you notice at the bottom there is:
if( (alarmDifSec>cfg.alarm_repeat*60) && (snoozeRemaining<=0) ) {
playWAV('a', 100);
The a corelates to the case A in the switch case. shown above. currently all the places that use the playWAV function are manually specified.
My understanding was using the alphabets in switch case will ran out soon because of large no. of files (>26). So, I implemented the logic using enum first and below is the complete code.
#include<stdio.h>
enum soundEffects {
alarm,
alarm_high,
alarm_low,
Dev_startup,
error,
error1,
noread,
noreadings,
normalrange,
startup,
startup_dev,
update,
warning,
warning_high,
warning_low,
};
void playWav (enum soundEffects effect, int paci_volume)
{
//Serial.println("Entered paciplay_day");
//printf("Entered paciplay_day\n");
switch (effect)
{
case alarm:
//file = new AudioFileSourceSD("/wav/alarm.wav");
printf("/wav/alarm.wav\n");
break;
case alarm_high:
//file = new AudioFileSourceSD("/wav/alarmhigh.wav");
printf("/wav/alarmhigh.wav\n");
break;
case alarm_low:
//file = new AudioFileSourceSD("/wav/alarmlow.wav");
printf("/wav/alarmlow.wav\n");
break;
case error:
//file = new AudioFileSourceSD("/wav/error.wav");
printf("/wav/error.wav\n");
break;
case error1:
//file = new AudioFileSourceSD("/wav/error1.wav");
printf("/wav/error1.wav\n");
break;
case noread:
//file = new AudioFileSourceSD("/wav/noread.wav");
printf("/wav/noread.wav\n");
break;
case noreadings:
//file = new AudioFileSourceSD("/wav/noreadings.wav");
printf("/wav/noreadings.wav\n");
break;
case normalrange:
//file = new AudioFileSourceSD("/wav/normalrange.wav");
printf("/wav/normalrange.wav\n");
break;
case warning:
//file = new AudioFileSourceSD("/wav/warning.wav");
printf("/wav/warning.wav\n");
break;
case warning_high:
//file = new AudioFileSourceSD("/wav/warninghigh.wav");
printf("/wav/warninghigh.wav\n");
break;
case warning_low:
//file = new AudioFileSourceSD("/wav/warninglow.wav");
printf("/wav/warninglow.wav\n");
break;
case startup:
//file = new AudioFileSourceSD("/wav/startup.wav");
printf("/wav/startup.wav\n");
break;
case update:
//file = new AudioFileSourceSD("/wav/update.wav");
printf("/wav/update.wav\n");
break;
}
}
int main()
{
//below are the 3 ways of calling your playWav() function
//1 - using direct numbers
//this will throw compilation error when compiled using cpp compilers
for (int i = 0; i<14; i++)
{
printf("enum value: %d\n", i);
playWav(i, 50);
}
//2 - directly calling using the enum
playWav(startup, 100);
//3 - Just another way of calling
enum soundEffects sound;
sound = error;
playWav(sound, 100);
return 0;
}
Also, I implemented this same logic using double array's. Please do find it below. This uses the name of the file as a parameter so altogether we can eliminate the use of switch statement.
#include<stdio.h>
void playWav (const char *filename, int paci_volume)
{
//Serial.println("Entered paciplay_day");
printf("Entered paciplay_day\n");
//file = new AudioFileSourceSD("/wav/update.wav");
printf("/wav/%s\n", filename);
}
int main()
{
const char list_of_files[][25] = { "startup.wav", "update.wav", "warning.wav", "alarm.wav" };
for (int i = 0; i<4; i++)
{
printf("name: %s\n", list_of_files[i]);
playWav(list_of_files[i], 50);
}
return 0;
}
Please omit my printf statements which I used for debugging. I hope this is useful.

What is the most efficient logic to check for all possible combinations of three flags?

I have three flags which may be True or False. I need to display an icon for each possible combination of flags. Since there are three flags that means, in combination, there are eight possible states. (Shown below, where bold represents true.)
A B C
A B C
A B C
A B C
A B C
A B C
A B C
A B C
Is there an advantageous control flow to use in checking the flags to minimize unnecessary checking? (Would this vary by which flags are likely to be on or off?)
Edit:
For example, when I was looking at simply flags A and B, my control flow was -
if(A & B)
{
// Display icon for A+B
}
else if (A)
{
// Display icon for A
}
else if (B)
{
// Display icon for B
}
I would set up an 8 bit variable, allowing bits 2,1,0 to store your flag states.
Then
switch(variablename)
{
case 0:
break;
..
..
case 7:
break;
}
protected void grdDemo_ItemDataBound(object sender, GridItemEventArgs e)
{
if (!(e.Item is GridDataItem) || (e.Item.DataItem == null))
{
return;
}
///////////////////
//// Solution 1 ///
///////////////////
// If it is possible to manipulate image name
MyClass M1 = e.Item.DataItem as MyClass;
ImageButton imgStatus = (ImageButton)e.Item.FindControl("imgStatus");
StringBuilder sb = new StringBuilder();
sb.Append(M1.A ? "1" : "0");
sb.Append(M1.B ? "1" : "0");
sb.Append(M1.C ? "1" : "0");
string ImageName = "imgStaus" + sb.ToString() + ".jpg";
imgStatus.ImageUrl = "~/path/" + ImageName;
///////////////////
//// Solution 2 ///
///////////////////
ImageName = string.Empty;
double FlagCount = 0;
FlagCount += Math.Pow((M1.A ? 0 : 1) * 2, 3);
FlagCount += Math.Pow((M1.B ? 0 : 1) * 2, 2);
FlagCount += Math.Pow((M1.B ? 0 : 1) * 2, 1);
var intFlagCount = (int)FlagCount;
switch (intFlagCount)
{
case 0:
ImageName = "imgStausFFF.jpg";
break;
case 1:
ImageName = "imgStausFFT.jpg";
break;
case 2:
ImageName = "imgStausFTF.jpg";
break;
case 3:
ImageName = "imgStausFTT.jpg";
break;
case 4:
ImageName = "imgStausTFF.jpg";
break;
case 5:
ImageName = "imgStausTFT.jpg";
break;
case 6:
ImageName = "imgStausTTF.jpg";
break;
case 7:
ImageName = "imgStausTTT.jpg";
break;
}
imgStatus.ImageUrl = "~/path/" + ImageName;
//////DONE!!!!!!!!!!
}
class MyClass
{
public bool A { get; set; }
public bool B { get; set; }
public bool C { get; set; }
}

Writing Java equivalent of the Fortran program

I have something like this in fortran.
20: call TESTBEGIN(a,b,c)
if(c<1) goto 40
30: call TESTMIDDLE(e,f,g)
if(g==1) goto 20
40: return
But my code is like this
Subroutine testCase()
20: CALL beginTest(a,b)
IF (b.EQ.-1) GOTO 999
30: CALL middleTest(c,b)
IF (b.EQ.-1) GOTO 20
40: CALL endTest(d,b)
IF (b.EQ.-1) GOTO 30
CALL LastTest(e,b)
IF (.b.EQ.-1) GOTO 40
DO I =1,j
DTEMP(j)=1.0
END DO
some code
999:return
Something like that?
do
{
c = TESTBEGIN(a,b);
if (c < 1) break;
g = TESTMIDDLE(e,f);
} while ( g == 1 );
For the second code snippet try a state machine:
for(int state = 1; state != 0; )
{
switch(state)
{
case 1:
state = (beginTest(a) == -1) ? 0 : 2;
break;
case 2:
state = (middleTest(c) == -1) ? 1 : 3;
break;
case 3:
state = (endTest(d) == -1) ? 2 : 4;
break;
case 4:
state = (lastTest(e) == -1) ? 3 : 5;
break;
}
case 5:
state = 0;
// DO I =1,j // Honestly I don't know what does it do.
// DTEMP(j)=1.0
break;
}
Or better try to reconsider the algorithm, I think you could do it more easy to read and understand using Java.