//ULTIMO
//caratteri del tastierino
const uint8_t keymap[4][3] =
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{10, 0, 11}
};
//pin connessi al keypad
const int rowPins[4] = {8, 7, 6, 5};
const int colPins[3] = {4, 3, 2};
//pin connessi ai Shift Register
const uint8_t clockPin = 11; // Pin di arduino connesso al Pin 11 del chip 74HC595 (SH Clock)
const uint8_t dataPin = 13; // Pin di arduino connesso al Pin 13 del chip 74HC595 (Data Serial In)
const uint8_t latchPin1 = 12; // Pin di arduino connesso al Pin 12 del chip 74HC595 per il PUNTEGGIO (Latch)
const uint8_t latchPin2 = 10; // Pin di arduino connesso al Pin 10 del chip 74HC595 per la SERIE DI NUMERI(Latch)
long time = 0; //conta il tempo [da 0 -> overflow]
uint8_t punti = 0;
bool lose = false;
bool isInit = true; //se premo * per la seconda volta sbaglio
bool isInit2 = true; //se premo # per la seconda volta sbaglio
uint8_t currentNumber;
long TIME_INTERVAL = 62496; //tempo di intervallo ( 4s = 62496) [da 0 -> 4s/3s/2s/1s]
long timeBetweenNewNumbers = 0; /// intervallo di tempo tra i due numeri ed è dinamico [da 0 -> TIME_INTERVAL]
uint8_t oldKey = 15;
bool isCorrectKey = false;
long time1; //tempo dall'ultimo tasto premuto [da 0s -> 10s]
long speedFactor = 4;
long time2 = 0; //tempo in cui è stato cambiato l'ultimo numero visualizzato
void setup() {
Serial.begin(9600);
DDRD &= 0B11100011; //pin 2, 3, 4 INPUT (put 1)
DDRB |= 0B00111100; //set pin 10-13 OUTPUT
DDRD |= 0B11100000; //pin 5, 6, 7 OUTPUT (set 0)
PORTD |= 0B00011100; //pin 2, 3, 4 pullUp
DDRB |= 0B00000001; //set pin 8 OUTPUT
TCCR0A = (1 << WGM01); //modalità CTC
TCCR0B = (1 << CS02) | (1 << CS00); //Prescaler 1024
OCR0A = 255; //valore di overflow -> valore MAX
TIMSK0 = (1 << OCIE0A);//Abilità l'interrupt del timer 0
TCCR2A = (1 << WGM21); //modalità CTC
TCCR2B = (1 << CS21); //Prescaler 8 (CS22 e CS20 sono settati a 0)
OCR2A = 200; //valore di confronto
TIMSK2 &= ~(1 << OCIE2A); //Disabilita l'interruzione del Timer2
sei();
}
//ONE SECOND = 15625
void loop(){
if(lose){punteggio(20, latchPin2); return;}
uint8_t key = keypadPolling();
if (key == keymap[3][2] && isInit2 ){
speedFactor--;
TIME_INTERVAL = s_speed();
isInit2 = false;
}
if(key == 12 && oldKey == 11){
isInit2 = true;
}
if (key == keymap[3][0] && isInit){
newNumber();
isInit = false;
time = 0;
}
if(isInit){time = 0; return;}
/////////////////////
Serial.println("");//NON TOCCARE
/////////////////////
if(time - time1 >= 156250){ // vedo se sono passati o meno i 10s (prima 156160)
lose = true; return;
}else{
if(key != oldKey){
if(key == currentNumber){
punti++;
punteggio(punti, latchPin1);
timeBetweenNewNumbers = TIME_INTERVAL;
isCorrectKey = true;
time1 = time;
}else if(key < 10 && key != currentNumber){lose = true;}
}
}
oldKey = key;
if (!isCorrectKey){
timeBetweenNewNumbers = time - time2;
}else{
isCorrectKey = false;
}
if((TIME_INTERVAL - timeBetweenNewNumbers <= 0)){
time2 = time;
newNumber();
}
}
/*
input is ¬ pullup
4-> c1
3 -> c2
2 -> c3
8 -> R1...
*/
//@author: younas e un pochissimo martù
long s_speed(){
if (speedFactor > 0 && speedFactor < 5){return speedFactor * 15624;}
speedFactor = 4;return 15625 * speedFactor; // quando vado a 0 ritorno "lento"
}
void newNumber(){
currentNumber = randomic();
punteggio(punti, latchPin1);
punteggio(currentNumber, latchPin2);
}
volatile uint8_t giri = 0;
ISR(TIMER0_COMPA_vect) {
time = time + TCNT0 + 1;
}
ISR(TIMER2_COMPA_vect) {
giri++;
}
uint8_t keypadPolling(){
uint8_t colNumberPin = columnPressedDetected();
uint8_t rowNumberPin = 0;
if (colNumberPin != 0){
setColumn(0); //colonne settate a 0
rowNumberPin = 8 - rowPressedDetected(colNumberPin);
setColumn(1); //colonne settate a 1
return keymap[rowNumberPin][4-colNumberPin];
}else{
return 12;
}
}
// trova la colonna premuta
uint8_t columnPressedDetected(){
for (uint8_t i = 2; i < 5; i++){
if(pinState(i) == 0){return i;}
}
return 0;
}
//trova la riga premuta
uint8_t rowPressedDetected(uint8_t colPin){
for (uint8_t i = 8; i > 4; i--){
switchPinState(i,1);
if (pinState(colPin) == 1){switchPinState(i,0); return i;}
switchPinState(i,0);
}
return 0;
}
void setColumn(bool bitValue){
for(int i=2; i<5; i++){
switchPinState(i,bitValue);
}
}
//metodo che mostra i valori sui display
void punteggio(byte num, uint8_t _latchPin){
byte byteData = numDisplay(num);
for(int i = 0; i < 8; i++){ //scorre di sette posizioni la decodifica del numero
bool bitValue = (byteData >> i) & 0x01; //contiene il contenuto del bit più a destra di byteData
switchPinState(dataPin, bitValue);
clockPulse();
}
switchPinState(_latchPin, 1);
switchPinState(_latchPin, 0);
}
//metodo che scandisce il clock
void clockPulse(){
TIMSK2 = (1 << OCIE2A);//Abilita l'interruzione del Timer2
giri = 0;
switchPinState(clockPin, 0);
while (giri < 2){asm(" ");}
switchPinState(clockPin, 1);
while (giri < 3){asm(" ");}
switchPinState(clockPin, 0);
TIMSK2 &= ~(1 << OCIE2A); //Disabilita l'interruzione del Timer2
}
//metodo che decodifica il numero in modo da rappresentarlo sul display
byte numDisplay(byte num){
byte stringa = 0B00000000;
switch(num){
case 0: stringa = 0B00000011; break;
case 1: stringa = 0B10011111; break;
case 2: stringa = 0B00100101; break;
case 3: stringa = 0B00001101; break;
case 4: stringa = 0B10011001; break;
case 5: stringa = 0B01001001; break;
case 6: stringa = 0B01000001; break;
case 7: stringa = 0B00011111; break;
case 8: stringa = 0B00000001; break;
case 9: stringa = 0B00001001; break;
case 20: stringa = 0B11100011; break;
}
return stringa;
}
//metodo che assegna al pin desiderato il valore di bitValue
void switchPinState(uint8_t pin, bool bitValue){
volatile uint8_t *portRegister;
uint8_t bitNumber;
// Assegna i numeri di porta e bit in base al pin
if(pin > 7){
portRegister = &PORTB;
}else{
portRegister = &PORTD;
}
switch (pin) {
case 13: bitNumber = 5; break;
case 12: bitNumber = 4; break;
case 11: bitNumber = 3; break;
case 10: bitNumber = 2; break;
case 9: bitNumber = 1; break;
case 8: bitNumber = 0; break;
default: bitNumber = pin;
}
if (bitValue) {
*portRegister |= (1 << bitNumber); // Setta il bit HIGH
} else {
*portRegister &= ~(1 << bitNumber); // Setta il bit LOW
}
}
uint8_t randomic(){
byte random_number = random(10);
return random_number;
}
bool pinState(uint8_t pin){
if(pin < 8){return PIND & (1 << pin);}
else {return PINB & (1 << pin-8);}
}