Le meraviglie dell' #ifdef

Buongiorno a tutti,

Sto cercando di fare pratica con la compilazione condizionale ( di cui ho scoperto l'esistenza da poco, essendo un po scarsino in programmazione)

Vorrei applicare quindi degli #ifdef al mio codice, che , banalmente , gestisce 4 interrupt su una board UNO ( 2 di quelli predefiniti e 2 ottenuti con la pinChangeInt)

Il mio programma è una semplice macchina a stati che passa allo stato successivo in caso si presenti uno di questi interrupt. Ora però ho necessità di "isolare" alcuni di questi interrupt, in caso ad esempio, la mia scheda disponga di 3 pulsanti invece di 4 ( in questo modo posso modulare la mia piccola applicazione a molti piu casi)

Il mio problema nasce nella parte del codice che verifica gli interrupt ,che non è altro se non un "if" a condizione multipla

if ( en_A==0 || en_B==0 || en_C==0 ||en_D ==0){
 //// Cambia stato 
}

il mio problema è che ho provato a scrivere

 if ( #ifdef DSB0 en_A==0 ||#endif en_B==0 || en_C==0 ||en_D ==0){
}

Ovviamente ho definito DSB0 in testa al programma.
Visti il numerosi errori comparsi, deduco la sintassi non sia corretta.
Quindi il mio problema è : come isolo queste condizioni con l'ifdef?
Come posso fare in modo che a seconda delle direttive che do in testa al file, questo scarti alcune condizioni ?

A me viene in mente solo di fare più if condizionate da più #ifdef
Qualcosa del genere:

#ifdef DSB0
if ( en_A==0 )
#elif DSB1
if ( en_B==0 ) 
#endif
{ 
}

Proprio quello che temevo....pensavo di aver trovato l'america, invece era gabicce mare :slight_smile:

Siccome dentro al mio ciclo vengono eseguite delle funzioni ( che hanno all'interno quel controllo per l'interrupt , e che a loro volta richiamano funzioni che controllano a loro volta la presenza dell'interrupt) , l'alternativa è perdere un pomeriggio e scrivere 4 versioni del software ottimizzate a seconda del numero di pulsanti... che cmq rispetto a splittare tutti gli if di controllo, forse mi richiederebbe meno tempo....

Comunque, resto in attesa se qualcuno conoscesse altri trucchi / consigli / suggerimenti
Nel frattempo, grazie nid69ita

Potresti fare un controllo su 8 input fissi (che poi sono i tuoi stati), quelli che a te non interessano li forzi a 0 o a 1 dipende quale logica usi, stabilisci nel setup quali controllare.

fai un if che controlla un numero byte che conprende i tuoi 8 bit (stati H/L), oppure un array tipo
EN[0] .... EN[7] che controlli con un FOR oppure un IF con gli 8 stati predeterminato

if ( !en_A || !en_B || !en_C || !en_D ........ ){
//// Cambia stato
}

5if ( en_A == 0 || semplificato if ( !en_A || ....corrisponde "se è FALSE (0)

if ( en_A == 1 || semplificato if ( en_A || ....corrisponde "se è TRUE (1)

nicostak:
Visti il numerosi errori comparsi, deduco la sintassi non sia corretta.
Quindi il mio problema è : come isolo queste condizioni con l'ifdef?
Come posso fare in modo che a seconda delle direttive che do in testa al file, questo scarti alcune condizioni ?

Di sicuro le direttive al precompilatore DEVONO stare su righe separate, cosi a me compila

#define DSB0
int en_A,en_B,en_C,en_D;
void setup()
{
 if ( 
 #ifdef DSB0 
 en_A==0 ||
 #endif 
 en_B==0 || en_C==0 ||en_D ==0)
 {
 }
}
void loop() {}

x nicostak: esiste un equivalente dell' ifdef che e' if defined, esso funziona meglio su strutture complesse su singolo rigo come vuoi fare tu

Intanto grazie a tutti per la collaborazione. Per quanto riguarda il consiglio di @pablos ( una specie di registro dei vari interrupt ) ci avevo pensato, ma veniva meno il motivo per cui mi ero inoltrato nella compilazione condizionale, ovvero ridurre la memoria. Ma è una buona soluzione.

@nid69ita : se davvero cosi compila, ho fatto tombola! magari il codice ne risentirà un po in leggibilità, ma alla fine lo devo leggere solo io, quindi anche chissenefrega! :smiling_imp: , ma a questo punto voglio provare anche la soluzione proposta da @testato, cosi faccio un po di pratica e cerco di entrare nell'ottica

Gia che sono qui vi chiedo a questo punto, conoscete un buon manuale dove imparare anche aspetti un po meno immediati di C per arduino? Io ho una copia di "Beginning C for arduino" , ma anche su questo argomento ad esempio, spiega le cose un po cosi a grandi linee...
Altrimenti mi metto su un manuale di C tipo bibbia e taglio la testa al toro

Partiamo da un presupposto. Le direttive al precompilatore sono usate per inserire/togliere delle porzioni di codice in base a qualche cosa. Nel caso di nicostak cambiare un test condizionale in base al chip per cui si compila.

Ora, siccome appunto la direttiva serve a inserire e/o togliere del test, perché rendersi la vita complicata con soluzioni tipo questa, che poi diventa illeggibile?

if (
#ifdef DSB0
en_A==0 ||
#endif
en_B==0 || en_C==0 ||en_D ==0)
{}

Qual'era il codice di partenza? Questo:

if ( #ifdef DSB0 en_A==0 ||#endif en_B==0 || en_C==0 ||en_D ==0){
}

Bene, non abbiate timore a scrivere un pò di più, tanto il precompilatore toglie ciò che non usa, quindi non si consumano risorse. Ma si ottiene codice più leggibile:

#ifdef DSB0
if(en_A==0 || en_B==0 || en_C==0 ||en_D ==0)
#else
if(en_B==0 || en_C==0 ||en_D ==0)
#endif
{}

Visto poi che sono confronti con zero, si può usare l'operatore not (ma questa è una sottigliezza):

#ifdef DSB0
if(!en_A || !en_B || !en_C || !en_D)
#else
if(!en_B || !en_C || !en_D)
#endif
{}

@leo... siccome volevo tenere gli interrupt il piu indipendenti possibili ( non dico di avere 16 casi possibili ma qualcuno si ) , a questo punto cercherei di raggruppare le situazioni piu comuni.

con l'ifdef si possono mettere condizioni multiple?
Mi spiego meglio , ammettiamo che io abbia definito le due variabili di attivazione DSB0 e DSB1

nell'ifdef possono mettere una condizione multipla del tipo :

#ifdef DBS0 && DSB1
if(!en_A || !en_B || !en_C || !en_D)
#elif DBS1
if(!en_A || !en_C || !en_D)
#endif

N.B ( il codice nell'esempio non avrebbe senso nella mia applicazione, è solo per capire il concetto :slight_smile:

Nel frattempo ho testato l'if defined di testato ( ;D ) ma anche quello me lo compila solo su piu righe

nicostak:
@nid69ita : se davvero cosi compila, ho fatto tombola! magari il codice ne risentirà un po in leggibilità, ma alla fine lo devo leggere solo io, quindi anche chissenefrega! :smiling_imp: , ma a questo punto voglio provare anche la soluzione proposta da @testato, cosi faccio un po di pratica e cerco di entrare nell'ottica

Meglio come dice @Leo, il mio esempi, poco leggibile, voleva solo sottolineare che le direttive #if non possono stare su una unica riga

Puoi anche creare una macro così:

#if FVER==4

    #define EN_INT() (en_A==0 || en_B==0 || en_C==0 || en_D ==0)

#elif FVER==3

    #define EN_INT() (en_B==0 || en_C==0 || en_D ==0)

#elif FVER==2

    #define EN_INT() (en_C==0 || en_D ==0)

#endif

if ( EN_INT() ) {
   // ...

}

Puoi anche creare macro di en_C, en_D ecc e quando non serve la macro la crei costante 0 o 1 come se esistesse:

#if FVER==4
    
    #define EN_A (en_A)
    #define EN_B (en_B )
    #define EN_C (en_C)
    #define EN_D (en_D)

#elif FVER==3

    #define EN_A (1)
    #define EN_B (en_B )
    #define EN_C (en_C)
    #define EN_D (en_D)

#elif FVER==2

    #define EN_A (1)
    #define EN_B (1)
    #define EN_C (en_C)
    #define EN_D (en_D)

Ciao.

+1