simon
Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Entrambe le parti precedenti la revisioneRevisione precedenteProssima revisione | Revisione precedenteProssima revisioneEntrambe le parti successive la revisione | ||
simon [2021/01/11 18:23] – [Software] admin | simon [2021/01/17 18:24] – [Software] admin | ||
---|---|---|---|
Linea 250: | Linea 250: | ||
Prerequisiti: | Prerequisiti: | ||
- | * sapere come funzionano gli [[wpi> | + | * sapere come funzionano gli [[wpi> |
* essere in grado di trovare le informazioni nel datasheet di un microcontrollore, | * essere in grado di trovare le informazioni nel datasheet di un microcontrollore, | ||
* saper programmare in C | * saper programmare in C | ||
Linea 293: | Linea 293: | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. | OTHER DEALINGS IN THE SOFTWARE. | ||
+ | */ | ||
- | + | /* | |
**** SPIEGAZIONI INTRODUTTIVE **** | **** SPIEGAZIONI INTRODUTTIVE **** | ||
SCOPO DEL PROGRAMMA | SCOPO DEL PROGRAMMA | ||
Il codice implementa il classico gioco Simon con 4 LED, 4 pulsanti | Il codice implementa il classico gioco Simon con 4 LED, 4 pulsanti | ||
- | e una sequenza | + | e una sequenza |
- | | + | |
- | | + | |
- | punteggio massimo viene salvto su EEPROM (si può cancellare l' | + | |
- | score premendo | + | |
+ | score tenere premuto | ||
+ | il watchdog timer viene usato per il debouncing, lo sleep mode e all' | ||
+ | avvio per il random generator | ||
+ | il timer viene usato per generare il segnale PWM per il buzzer | ||
PREREQUISITI | PREREQUISITI | ||
Linea 311: | Linea 316: | ||
CONFIGURAZIONE | CONFIGURAZIONE | ||
- | | + | |
- | | + | |
- | | + | l' |
- | | + | |
- | | + | |
REGISTRI PIU' IMPORTANTI UTILIZZATI | REGISTRI PIU' IMPORTANTI UTILIZZATI | ||
Linea 328: | Linea 331: | ||
INGRESSI E USCITE | INGRESSI E USCITE | ||
- | DDRB imposta come uscite i bit a 1 (pagina 50). I pin sono usati | + | DDRB imposta come uscite i bit a 1 (pagina 50). I pin sono sempre |
- | come ingressi tranne quando viene chiamata play(). | + | |
Il pin 5 (PB5) viene usato pulsante di start (RESET attivo basso) | Il pin 5 (PB5) viene usato pulsante di start (RESET attivo basso) | ||
e subito dopo come ingresso analogico (ADC0) scollegato per generare | e subito dopo come ingresso analogico (ADC0) scollegato per generare | ||
- | il seed del random generator (una volta sola all' | + | il seed del random generator (una volta sola all' |
Il pin 6 (PB1/OC0B) è usato per pilotare il buzzer con un' | Il pin 6 (PB1/OC0B) è usato per pilotare il buzzer con un' | ||
- | quadra generata col timer/ | + | quadra generata col timer/ |
+ | |||
Per la gestione del timer/ | Per la gestione del timer/ | ||
- TCNT0 che contiene il valore del conteggio | - TCNT0 che contiene il valore del conteggio | ||
Linea 342: | Linea 345: | ||
frequenza, e quello in corrispondenza del quale c'è la commutazione | frequenza, e quello in corrispondenza del quale c'è la commutazione | ||
tra livello alto e basso. Il waveform generator usa il risultato | tra livello alto e basso. Il waveform generator usa il risultato | ||
- | della comparazione per produrre un segnale PWM nel pin OC0B del buzzer. | + | della comparazione per produrre un segnale PWM nel pin OC0B del buzzer |
- | + | ||
- | Il timer/clock, che si ferma se non si seleziona una sorgente di clock, | + | Il timer/clock si ferma se non si seleziona una sorgente di clock; |
- | ha più modi di funzionamento che si impostano con WGM0[2:0] e COM0x[1: | + | ha più modi di funzionamento che dipendono da WGM0[2:0] e COM0x[1: |
- | - normal: conta in su fino a 0xFF poi produce | + | - normal: conta in su fino a 0xFF poi genera |
- CTC: conta fino a OCR0A | - CTC: conta fino a OCR0A | ||
- fast PWM: va basso sul match con OCR0A e alto su 0xFF (fig. 11-6) | - fast PWM: va basso sul match con OCR0A e alto su 0xFF (fig. 11-6) | ||
- phase correct PWM: conta in su e in giù | - phase correct PWM: conta in su e in giù | ||
- | Nel programma si usa la modalità phase correct PWM per il buzzer. | + | Nel programma si usa la modalità phase correct PWM per il buzzer |
*/ | */ | ||
Linea 356: | Linea 359: | ||
// LIBRERIE UTILIZZATE (da https:// | // LIBRERIE UTILIZZATE (da https:// | ||
- | // sleep mode per ridurre il consumo. | + | // sleep mode |
- | // scade il watchdog timer il MCU va in POWER-DOWN per ridurre | + | // Al termine di ogni partita, se scade il watchdog timer il MCU va in |
- | // il consumo; si risveglia col un reset | + | // POWER-DOWN per ridurre il consumo; si risveglia col un reset |
#include < | #include < | ||
+ | // delay | ||
// funzione simile a delay() di Arduino (cicli di CPU buttati). Va va | // funzione simile a delay() di Arduino (cicli di CPU buttati). Va va | ||
// bene per piccole temporizzazioni, | // bene per piccole temporizzazioni, | ||
Linea 369: | Linea 373: | ||
#include < | #include < | ||
+ | // eeprom | ||
// per salvare l' | // per salvare l' | ||
#include < | #include < | ||
Linea 377: | Linea 382: | ||
// https:// | // https:// | ||
- | // i quattro elementi dell' | + | // nella fase di gioco in cui viene mostrata la sequenza con la funzione |
- | // come uscite PB1 (il buzzer) e uno tra PB3, PB2, PB0 e PB4 per accendere | + | // play() |
- | // rispettivamente | + | // impostano |
- | // mostrata la sequenza con la funzione play() | + | // (i LED 1, 4, 3 e 2) |
const uint8_t buttons[4] = { | const uint8_t buttons[4] = { | ||
0b00001010, 0b00000110, 0b00000011, 0b00010010 | 0b00001010, 0b00000110, 0b00000011, 0b00010010 | ||
Linea 392: | Linea 397: | ||
}; | }; | ||
- | uint8_t lastKey; // ultimo tasto premuto per il debouncing | + | uint8_t lastKey; // ultimo tasto premuto |
uint8_t lvl = 0; // livello (parte da 0 -> sequenza con un solo LED) | uint8_t lvl = 0; // livello (parte da 0 -> sequenza con un solo LED) | ||
- | uint8_t maxLvl; | + | uint8_t maxLvl; |
- | // variabili per pseudo-random generator | + | // variabili per pseudo-random generator |
uint16_t seed; // generato con l'ADC su un pin scollegato (e mischiato) | uint16_t seed; // generato con l'ADC su un pin scollegato (e mischiato) | ||
uint16_t ctx; // valori successivi generati a partire dal seed | uint16_t ctx; // valori successivi generati a partire dal seed | ||
Linea 410: | Linea 415: | ||
void sleepNow() { | void sleepNow() { | ||
- | // power-down riduce al massimo il consumo; il risveglio avviene col | + | // power-down riduce al massimo il consumo |
- | // pulsant start/reset | + | // il risveglio avviene col pulsant start/reset |
// di default tutti i pin sono ingressi; in power-down gli ingressi | // di default tutti i pin sono ingressi; in power-down gli ingressi | ||
- | // flottanti è meglio che siano scollegati (pag. 53) | + | // flottanti è meglio che siano scollegati |
- | PORTB = 0b00000000; // tri-state (disabilita la resitenza | + | PORTB = 0b00000000; // tri-state (disabilita la resistenza |
cli(); // disabilita gli interrupt | cli(); // disabilita gli interrupt | ||
WDTCR = 0; // spegne il Watchdog timer | WDTCR = 0; // spegne il Watchdog timer | ||
Linea 424: | Linea 429: | ||
void play(uint8_t i, uint16_t t = 45000) { | void play(uint8_t i, uint16_t t = 45000) { | ||
// accende un LED e suona la nota corrisponente col buzzer | // accende un LED e suona la nota corrisponente col buzzer | ||
- | // i è l' | + | // i è l' |
- | // per ritardare di (4/1.2M)*t sec (45000 -> il delay è di 150ms) | + | // t è usato nella funzione delay per ritardare di (4/1.2M)*t sec |
+ | // il valore | ||
- | // con i pin impostati come ingressi | + | // quando non viene eseguita la funzione play() |
- | // 0 -> se è un input disabilita la resistenza di pull-up | + | // come ingressi |
- | // 0 -> se è un output imposta il livello basso di tensione | + | // prima di passare da ingresso a uscita bisogna impostarli come |
- | // questa operazione serve nel passaggio da ingresso con pull-up a | + | //tri-state (pagina 51) quindi si modifica |
- | // uscita ed è indicata a pagina 51 | + | // 0 -> come input disabilita la resistenza di pull-up |
+ | // 0 -> come output imposta il livello basso di tensione | ||
PORTB = 0b00000000; | PORTB = 0b00000000; | ||
Linea 439: | Linea 446: | ||
DDRB = buttons[i]; | DDRB = buttons[i]; | ||
+ | // a pagina 67 un diagramma temporale del funzionamento phase-correct | ||
// assegno a OCR0A il valore massimo del conteggio del timer/ | // assegno a OCR0A il valore massimo del conteggio del timer/ | ||
- | // in modo da modificare la frequenza; da pag. 68 si capisce che la | + | // in modo da modificare la frequenza |
- | // frequenza minima si otterrebbe senza usare OCR0A (quindi contando | + | // da pag. 68 si capisce che la frequenza minima si otterrebbe senza |
- | // sempre fino a 0xFF - 255) f = 1.2M/ | + | // usare OCR0A (quindi contando sempre fino a 0xFF - 255 |
+ | // f = 1.2M/ | ||
// con i valori in tones si ottiene ad es. f=1.2M/ | // con i valori in tones si ottiene ad es. f=1.2M/ | ||
// gli altri valori sono 3.3, 4.2 e 5 kHz (re# sol# do re#) | // gli altri valori sono 3.3, 4.2 e 5 kHz (re# sol# do re#) | ||
Linea 451: | Linea 460: | ||
// TCCR0A/B sono impostati nel main prima di chiamare play() in modo | // TCCR0A/B sono impostati nel main prima di chiamare play() in modo | ||
// che il waveform generator funzioni in modalità PWM phase correct | // che il waveform generator funzioni in modalità PWM phase correct | ||
- | // WGM02 imposta il conteggio fino a OCR0A, CS01 il prescaler a 8 | + | // WGM02 imposta il conteggio fino a OCR0A (pag. 73) |
+ | // CS01 imposta | ||
TCCR0B = (1 << WGM02) | (1 << CS01); | TCCR0B = (1 << WGM02) | (1 << CS01); | ||
Linea 462: | Linea 472: | ||
// spegne il LED e disabilita il buzzer (tutti i pin come ingressi) | // spegne il LED e disabilita il buzzer (tutti i pin come ingressi) | ||
DDRB = 0b00000000; | DDRB = 0b00000000; | ||
- | // abilita le resistenze di pul-up per i pulsanti | + | // abilita le resistenze di pull-up per i pulsanti |
PORTB = 0b00011101; | PORTB = 0b00011101; | ||
} | } | ||
Linea 490: | Linea 500: | ||
uint8_t simple_random4() { | uint8_t simple_random4() { | ||
- | // linear-feedback shift register (Galois) | + | // LFSR linear-feedback shift register (Galois) |
// per una spiegazione di come funziona vedi il progetto originale | // per una spiegazione di come funziona vedi il progetto originale | ||
// o la pagina wikipedia (e l'AN della Maxim linkata): | // o la pagina wikipedia (e l'AN della Maxim linkata): | ||
// it.wikipedia.org/ | // it.wikipedia.org/ | ||
- | // modifica ctx e restituisce un indice tra 0 e 3 per i LED | + | // modifica ctx e restituisce un indice tra 0 e 3 corrispondente a |
+ | // uno dei quattro | ||
// la sequenza pseudo-casuale di valori di ctx si ripete sempre | // la sequenza pseudo-casuale di valori di ctx si ripete sempre | ||
- | // uguale | + | // allo stesso modo se non cambia il seed; riportando ctx al valore |
- | // si può ripetere | + | // del seed si può ripercorrere |
- | // pulsanti | + | // pressione dei pulsanti |
+ | |||
// servono due bit per un nuovo indice da 0 a 3 (00 -> 11) | // servono due bit per un nuovo indice da 0 a 3 (00 -> 11) | ||
for (uint8_t i = 0; i < 2; i++) { | for (uint8_t i = 0; i < 2; i++) { | ||
Linea 506: | Linea 517: | ||
if (lsb || !ctx) { // se LSB (uscita) è 1 o se ctx contiene tutti 0 | if (lsb || !ctx) { // se LSB (uscita) è 1 o se ctx contiene tutti 0 | ||
// (con tutti zeri la sequenza non cambia mai) | // (con tutti zeri la sequenza non cambia mai) | ||
- | ctx ^= 0xB400; // inverte i bit secondo la maschera (XOR con 1) | + | ctx ^= 0xB400; |
+ | // 0xB400 -> 1011010000000000 quindi XOR con i | ||
+ | // bit 16, 14, 13 e 11, vedi su wikipedia en | ||
+ | // Linear-feedback_shift_register# | ||
} | } | ||
} | } | ||
Linea 514: | Linea 528: | ||
} | } | ||
- | ISR(WDT_vect) { // Watchdog Timeout Interrupt da avr-libc | + | ISR(WDT_vect) { |
- | // eseguita ogni volta che scade il timer (16ms) | + | |
- | // ogni 16ms viene incrementato il valore della variabile usata per | + | // eseguita ogni volta che scade il timer |
- | // gestire il poweroff | + | // ogni 16ms viene incrementato il valore della variabile |
+ | // per gestire il poweroff | ||
time++; // increase each 16 ms | time++; // increase each 16 ms | ||
- | // dopo ogni reset viene mischiato | + | // il watch timer viene usato anche all' |
- | // cabia più fino al reset successivo | + | // seed con l'ADC; il seed non cambia |
if (nrot) { | if (nrot) { | ||
nrot--; | nrot--; | ||
- | // mischia il seed facendo uno shift a sinistra e XOR con valore | + | // mischia il seed facendo uno shift a sinistra e XOR con il valore |
- | // del timer/ | + | // del timer/ |
+ | // a 8bit senza prescaler, quindi | ||
seed = (seed << 1) ^ TCNT0; | seed = (seed << 1) ^ TCNT0; | ||
} | } | ||
Linea 535: | Linea 551: | ||
int main(void) { | int main(void) { | ||
- | // pull-up sui 4 pulsanti dei LED (tutti ingressi di default) | + | // pull-up sui 4 pulsanti dei LED (sono tutti ingressi di default) |
PORTB = 0b00011101; | PORTB = 0b00011101; | ||
// GENERAZIONE DEL SEED | // GENERAZIONE DEL SEED | ||
- | | + | |
// Il pin PB5/ADC0 (start/ | // Il pin PB5/ADC0 (start/ | ||
- | // attivando l' | + | // attivando l' |
- | // il valore viene poi mischiato otto volte nella ISR usando il timer | + | // il valore viene poi mischiato |
+ | // allo scadere del watchdog | ||
+ | |||
+ | // ADC | ||
+ | | ||
ADCSRA |= (1 << ADEN); // abilita l'ADC (pagina 82 e 92) | ADCSRA |= (1 << ADEN); // abilita l'ADC (pagina 82 e 92) | ||
ADCSRA |= (1 << ADSC); // parte la conversione sul pin ADC0 scollegato | ADCSRA |= (1 << ADSC); // parte la conversione sul pin ADC0 scollegato | ||
Linea 553: | Linea 573: | ||
seed = ADCL; | seed = ADCL; | ||
ADCSRA = 0b00000000; // spegne l'ADC | ADCSRA = 0b00000000; // spegne l'ADC | ||
+ | | ||
// WATCHDOG TIMER | // WATCHDOG TIMER | ||
+ | | ||
// abilita l' | // abilita l' | ||
- | // il WDT usa un oscillatore separato a 128kHz (il timer va col clock) | + | // il WDT usa un oscillatore separato |
+ | // va col clock) | ||
// senza prescaling c'è un timeout ogni 16ms (2048 cicli, pag 43) e | // senza prescaling c'è un timeout ogni 16ms (2048 cicli, pag 43) e | ||
// viene eseguita la ISR | // viene eseguita la ISR | ||
WDTCR = (1 << WDTIE); // parte il watchdog timer con prescaler da 16ms | WDTCR = (1 << WDTIE); // parte il watchdog timer con prescaler da 16ms | ||
sei(); // global interrupt enable (mette a 1 il bit I nello SREG) | sei(); // global interrupt enable (mette a 1 il bit I nello SREG) | ||
+ | | ||
// TIMER/ | // TIMER/ | ||
+ | | ||
// imposta il timer/ | // imposta il timer/ | ||
- | // prescaler (CS00 a uno): conta fino a 0xFF poi ricomincia e segnala | + | // prescaler (CS00 a uno): conta fino a 0xFF, segnala |
- | // con TOV0 (pag. 64) | + | // ricomincia il conteggio |
// il timer comincia a contare quando si imposta una sorgente per il | // il timer comincia a contare quando si imposta una sorgente per il | ||
// clock (pag. 60) | // clock (pag. 60) | ||
Linea 573: | Linea 598: | ||
// IMPOSTAZIONE TIMER/ | // IMPOSTAZIONE TIMER/ | ||
- | // cambia | + | // la modalità di funzionamento del timer cambia |
- | // a PWM phase correct (WGM0[2: | + | // phase correct (WGM0[2: |
- | // a 0xFF (nella funzione play() conterà fino al valore contenuto nel | + | // a 0xFF |
- | // registro OCR0A per modificare la frequenza e produrre più note)) | + | // nella funzione play() |
+ | // note diverse, | ||
// Si imposta il compare output mode del waveform generator in modo | // Si imposta il compare output mode del waveform generator in modo | ||
// che il pin del buzzer PB1/OC0B (COM0B[1: | // che il pin del buzzer PB1/OC0B (COM0B[1: | ||
// match col valore del registro OCR0B mentre conta in su e alto | // match col valore del registro OCR0B mentre conta in su e alto | ||
// mentre conta in giù (OCR0B è impostato nella funzione play() come | // mentre conta in giù (OCR0B è impostato nella funzione play() come | ||
- | // OCR0A) | + | // OCR0A / 2) |
+ | // in questo modo si genera | ||
// NB il segnale PWM è presente solo se il pin è impostato come uscita | // NB il segnale PWM è presente solo se il pin è impostato come uscita | ||
// (pag 68) quindi il buzzer non suona finche non si chiama play() | // (pag 68) quindi il buzzer non suona finche non si chiama play() | ||
TCCR0A = (1 << COM0B1) | (0 << COM0B0) | (0 << WGM01) | TCCR0A = (1 << COM0B1) | (0 << COM0B0) | (0 << WGM01) | ||
- | // LETTURA | + | // LETTURA DELL' |
- | + | | |
- | // maxLvl viene scritto e letto negato | + | // maxLvl viene complementato |
- | // valore di default | + | // o letto perché il valore di default |
+ | // e con la EEPROM " | ||
// (uint8_t*) 0 è un puntatore a un byte che parte dall' | // (uint8_t*) 0 è un puntatore a un byte che parte dall' | ||
maxLvl = ~eeprom_read_byte((uint8_t*) 0); | maxLvl = ~eeprom_read_byte((uint8_t*) 0); | ||
+ | // EVENTUALE RESET DELL' | ||
+ | | ||
// legge lo stato dei pin della port B e lo confronta con la maschera | // legge lo stato dei pin della port B e lo confronta con la maschera | ||
switch (PINB & 0b00011101) { | switch (PINB & 0b00011101) { | ||
- | // AND tra gli ingressi e la maschera sopra; 0 significa premuto, | + | |
- | // PB1 è il buzzer | + | // attivare altre funzioni tenedo premuti altri pulsanti all' |
- | // questo punto del programma sarà già alto); i pin dei pulsanti | + | // per ridurre le dimensioni dell' |
- | // non premuti sono al livello alto (pull-up) | + | // sono state eliminate |
- | // se PB3 (LED rosso) è premuto | + | |
+ | // PB1 e PB5 non contano: uno è il buzzer e l' | ||
+ | // basso (che a questo punto del programma sarà già alto); i pin dei | ||
+ | // pulsanti | ||
+ | // all' | ||
case 0b00010101: // PB3 premuto dopo il reset -> azzera high-score | case 0b00010101: // PB3 premuto dopo il reset -> azzera high-score | ||
eeprom_write_byte((uint8_t*) 0, 255); // scrive 255 -> livello 0 | eeprom_write_byte((uint8_t*) 0, 255); // scrive 255 -> livello 0 | ||
Linea 608: | Linea 642: | ||
while (1) { | while (1) { | ||
// MOSTRA LA SEQUENZA | // MOSTRA LA SEQUENZA | ||
+ | | ||
// reimposta ctx al valore del seed; la sequenza di valori di ctx | // reimposta ctx al valore del seed; la sequenza di valori di ctx | ||
// sarà sempre la stessa sequenza finché non si resetta | // sarà sempre la stessa sequenza finché non si resetta | ||
Linea 613: | Linea 648: | ||
// accende in sequenza un numero di LED pari al livello più uno | // accende in sequenza un numero di LED pari al livello più uno | ||
for (uint8_t cnt = 0; cnt <= lvl; cnt++) { | for (uint8_t cnt = 0; cnt <= lvl; cnt++) { | ||
- | // attesa tra un LED e il successivo; valore massimo | + | // attesa tra un LED e il successivo |
- | // -> 218ms poi scende se aumenta lvl | + | // il valore |
+ | // poi diminuisce all' | ||
_delay_loop_2(4400 + 489088 / (8 + lvl)); | _delay_loop_2(4400 + 489088 / (8 + lvl)); | ||
- | // accende il LED con indice | + | // accende il LED con l'indice restituito da simple_random4(), un |
- | // generato come resto della divisione per 4 di ctx, il cui valore | + | // numero tra 0 e 3 che è il resto della divisione per 4 di ctx |
- | // viene aggiornato ad ogni chiamata | + | // il valore di ctx viene aggiornato ad ogni chiamata |
play(simple_random4()); | play(simple_random4()); | ||
} | } | ||
Linea 624: | Linea 660: | ||
// INSERIMENTO SEQUENZA DA PARTE DEL GIOCATORE | // INSERIMENTO SEQUENZA DA PARTE DEL GIOCATORE | ||
- | // azzera il conteggio che porta al poweroff | + | // azzera il conteggio che porta al power-off |
time = 0; | time = 0; | ||
- | // imposta lastKey a un valore che non corrisponde a nessun pulsante | + | // per il debouncing |
+ | // a nessun pulsante | ||
lastKey = 5; | lastKey = 5; | ||
// riporta ctx al valore iniziale uguale al seed | // riporta ctx al valore iniziale uguale al seed | ||
Linea 632: | Linea 669: | ||
// tante volte quanti sono i LED da indovinare | // tante volte quanti sono i LED da indovinare | ||
for (uint8_t cnt = 0; cnt <= lvl; cnt++) { | for (uint8_t cnt = 0; cnt <= lvl; cnt++) { | ||
+ | // azzero pressed | ||
bool pressed = false; | bool pressed = false; | ||
// finché non si preme un bottone | // finché non si preme un bottone | ||
Linea 638: | Linea 676: | ||
for (uint8_t i = 0; i < 4; i++) { | for (uint8_t i = 0; i < 4; i++) { | ||
// controlla se il pulsante i è premuto | // controlla se il pulsante i è premuto | ||
- | // buttons & maschera -> bit a 1 solo per il pin/ | + | // buttons & maschera -> bit a 1 solo per il pin/ |
// PINB ha tutti i bit a 1 (resistenze di pull-up attivate | // PINB ha tutti i bit a 1 (resistenze di pull-up attivate | ||
// nella funzione play) tranne quello del pulsante premuto | // nella funzione play) tranne quello del pulsante premuto | ||
Linea 645: | Linea 683: | ||
if (!(PINB & buttons[i] & 0b00011101)) { | if (!(PINB & buttons[i] & 0b00011101)) { | ||
// DEBOUNCE | // DEBOUNCE | ||
- | // se sono passati 16ms (tempo max per eventuali rimbalzi o | + | // se sono passati 16ms (tempo max per eventuali rimbalzi) o |
// se è stato premuto un pulsante diverso (non è rimbalzo) | // se è stato premuto un pulsante diverso (non è rimbalzo) | ||
if (time > 1 || i != lastKey) { | if (time > 1 || i != lastKey) { | ||
Linea 674: | Linea 712: | ||
} | } | ||
} | } | ||
- | // se passano 64s (time = 4000) e non succede niente poweroff | + | // se passano 64s (time = 4000) e non viene premuto nessun |
+ | // pulsante si attiva il power-off | ||
if (time > 4000) { | if (time > 4000) { | ||
sleepNow(); | sleepNow(); | ||
Linea 689: | Linea 728: | ||
} | } | ||
} | } | ||
+ | |||
</ | </ |
simon.txt · Ultima modifica: 2023/10/27 18:02 da admin