#define DELAY 512
#define DIR 0 // direzione
// Questa soluzione usa le FLAG
// GPIOR0 sta per General Purpose Input Output Register
// Tramite tale registro possiamo definire due variabili booleane SMY_FLAG e TMY_FLAG
// Nota : T e S non sono significative nel nome delle due flag, servono solo a
// distinguerle
// Per accendere e spegnere i LED viene definita...
#define SMY_FLAG(n, mode) (mode == 1? (GPIOR0 |= _BV(n)) : (GPIOR0 &= ~_BV(n)))
// Con
// * n = n-esimo LED puntato dalla direzione
// * mode = 1 ==> Turn ON
// * mode = 0 ==> Turn OFF
// Per cambiare direzione viene definita...
#define TMY_FLAG(n, mode) (mode == 1? (GPIOR0 & _BV(n)) : (GPIOR0 & _BV(n) == 0))
// Con
// * n = la direzione corrente
// * mode = 1 per cambiare la direzione da LED 5 a LED 1
// * mode = 0 per cambiare la direzione da LED 1 a LED 5
volatile uint16_t counter = DELAY; // circa 0,5 secondi
// Questa soluzione è la soluzione mv2 friendly cercata, dove nessuna funzione
// di libreria è stata usata e, come risultato, si ha un codice assembly di
// dimensioni ridotte (da F1 View Compiled Assembly Code Listing si può vedere che
// le righe di listing sono davvero poche a confronto delle righe di listing
// della soluzione di pag 135 ///380 righe vs le 1571 di pag 135///)
void setup() {
TIMSK0 = 0x04; // E' IL REGISTRO DI DIS/ATTIVAZIONE DEGLI INTERRUPT DEI TIMER
DDRB = 0x1F; // LE PORTE DA 0 A 4 ABILITATE
PORTB = 0x01; // ACCENSIONE PRIMO LED
}
void loop() {}
ISR(TIMER0_COMPB_vect){
if(--counter == 0) {
uint8_t i = PORTB;
if(TMY_FLAG(DIR,1))i>>=1; else i<<=1;
PORTB = i;
if(i & 0x10)SMY_FLAG(DIR, 1);
if(i & 0x01)SMY_FLAG(DIR, 0);
counter = DELAY;
}
}
// Non abbiamo fatto altro che assecondare il compilatore, non abbiamo scritto
// righe di codice assembly