This is an old revision of the document!
Grupa: 332CD
Îndrumător: Florin Stancu
Proiectul presupune crearea unei variante simplificate a jocului clasic Whac-A-Mole. Cârtițele vor fi reprezentate de LED-uri care se vor aprinde la intervale din ce în ce mai mici, pe măsura ce jocul progresează, și vor avea un timeout la expirarea căruia se vor stinge, astfel jucătorul ratând șansa de a-și crește scorul. LED-urile vor avea asociate câte un buton care va fi acționat prin apăsare, ducând astfel la stingerea LED-ului asociat, respectiv omorârea cârtiței. Scorul va fi calculat în funcție de reacția cât mai rapidă a jucătorului (cu cât omoară cârtițele mai repede cu atât scorul va fi mai mare) și va fi afișat pe un ecran LCD.
Pentru a acționa LED-urile vor fi folosite timere și întreruperi.
De asemenea, pentru a contoriza scorul, se va măsura tensiunea la buton printr-un pin analogic și cu ajutorul ADC.
Pentru a afișa scorul pe LCD se va folosi protocolul SPI.
#include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> #include <stdbool.h> #include <SPI.h> #include <Adafruit_I2CDevice.h> #include <Adafruit_ST7735.h>
#define NO_LED 4 #define TFT_CS 10 #define TFT_RST 8 #define TFT_DC 9 #define TIMEOUT 2.490368
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
double score = 0; volatile bool led_on = false; volatile bool timeout_occurred = false; volatile int sel; int look_at_voltage = -1; volatile int timer2_ovf_count = 0; volatile int timer0_ovf_count = 0; volatile int timer2_total_ticks = 0;
void init_display() {
tft.initR(INITR_BLACKTAB); tft.setTextColor(ST7735_WHITE); tft.fillScreen(ST7735_BLACK); tft.setTextSize(2); tft.setRotation(2);
}
ISR(TIMER1_COMPA_vect) {
if (led_on == false) { timer2_total_ticks = 0; timer2_ovf_count = 0; TCNT2 = 0; sel = rand() % NO_LED + 2; PORTD |= (1 << sel); led_on = true; timeout_occurred = false; look_at_voltage = -1; }
}
ISR(TIMER1_COMPB_vect) {
tft.fillRect(40, 20, 60, 20, ST7735_BLACK);
}
ISR(TIMER2_OVF_vect) {
timer2_total_ticks += 256; timer2_ovf_count++; if (timer2_ovf_count == 76 && led_on == true) { led_on = false; timeout_occurred = true; look_at_voltage = -1; PORTD &= ~(1 << sel); }
}
ISR(TIMER0_COMPA_vect) {
timer0_ovf_count++; if (timer0_ovf_count == 611) { if (OCR1A - 3906 > 15625) { OCR1A = OCR1A - 3906; } else { OCR1A = 46875; } TCNT1 = min(TCNT1, OCR1A - 1); timer0_ovf_count = 0; }
}
void my_setup() {
DDRD |= (1 << PD3); DDRD |= (1 << PD2); DDRD |= (1 << PD4); DDRD |= (1 << PD5);
TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 46875; OCR1B = 15625; TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS12) | (1 << CS10); TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);
TCCR2A = 0; TCCR2B = 0; TCNT2 = 0; TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); TIMSK2 |= (1 << TOIE2);
TCCR0A = 0; TCCR0B = 0; TCNT0 = 0; OCR0A = 255; TCCR0A |= (1 << WGM01); TCCR0B |= (1 << CS02) | (1 << CS00); TIMSK0 |= (1 << OCIE0A);
}
void adc_init(int port) {
ADMUX |= (1 << REFS0); ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); ADMUX &= ~(1 << MUX0); ADMUX &= ~(1 << MUX1); ADMUX &= ~(1 << MUX2); ADMUX &= ~(1 << MUX3); if (port == 0) { } else if (port == 1) { ADMUX |= (1 << MUX0); } else if (port == 2) { ADMUX |= (1 << MUX1); } else if (port == 3) { ADMUX |= (1 << MUX1) | (1 << MUX0); } else if (port == 4) { ADMUX |= (1 << MUX2); } else if (port == 5) { ADMUX |= (1 << MUX2) | (1 << MUX0); }
}
int adc_read() {
ADCSRA |= (1 << ADSC); while ((ADCSRA & (1 << ADSC))); int res = ADC; return res;
}
void my_loop() {
for (int analog_pin = 0; analog_pin < NO_LED; analog_pin++) { adc_init(analog_pin); int analog_in = adc_read(); int v_in = analog_in * (5.0 / 1024.0); if (v_in > 0) { look_at_voltage = analog_pin; }
int voltage_to_check = -1; if (look_at_voltage == analog_pin) { voltage_to_check = v_in; } if (voltage_to_check == 0 && led_on == true && !timeout_occurred) { timer2_total_ticks += TCNT2; TCNT1 = 0; PORTD &= ~(1 << sel); led_on = false; look_at_voltage = -1; double react_time = 0.000064 * timer2_total_ticks; double percent = react_time / TIMEOUT; score += (1 - percent); tft.setCursor(40, 20); tft.print("+"); tft.print(1 - percent); tft.setCursor(40, 40); tft.print("SCORE"); tft.fillRect(40, 60, 88, 128, ST7735_BLACK); tft.setCursor(40, 60); tft.print(score); } }
}
int main(void) {
init(); init_display(); sei(); my_setup(); while (1) { my_loop(); } return 0;
}