summaryrefslogtreecommitdiff
path: root/final_project/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'final_project/main.c')
-rw-r--r--final_project/main.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/final_project/main.c b/final_project/main.c
new file mode 100644
index 0000000..f301ef5
--- /dev/null
+++ b/final_project/main.c
@@ -0,0 +1,218 @@
+/*
+ * final_project.c
+ *
+ * Created: 4/3/2024 10:08:56 AM
+ * Author : bsw9xd
+ */
+#define F_CPU 16000000UL
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <stdbool.h>
+
+#include "serial.h"
+#include "clock.h"
+
+
+volatile int seconds_remaining; //will be used by ISR
+
+#define SPEAKER_PORT PORTE
+#define SPEAKER_PIN 4 //rename?
+#define ELEMENT_COUNT 7
+
+//TODO get_button and display_element unnecessarily complex
+uint8_t get_button() {
+ if(~PINE & (1 << 6)) return (1 << 2);
+ return ((~PINA) & ~(0b1100)); //TODO clean up
+}
+
+void display_element(uint8_t element, unsigned int time) {
+ uint8_t portd_state = 0;
+ uint8_t porte_state = 0;
+ if(element & (1 << 2)) porte_state = (1<<5);
+ portd_state = element & ~(0b1100);
+
+ PORTD ^= portd_state;
+ PORTE ^= porte_state;
+ beep(329.63, .25);
+ _delay_ms(time * 1000);
+ PORTD ^= portd_state;
+ PORTE ^= porte_state;
+}
+
+void init_io() {
+ DDRA = 0x00;
+ PORTA = 0xff;
+
+ DDRD = 0xff;
+ PORTD = 0xff;
+
+ DDRE = (1 << 4) | (1 << 5);
+ PORTE = 0xff;
+}
+void test_timer() {
+ for(;;) {
+ usart_txstr("timer test\n");
+ start_timer();
+ while(!timer_done());
+ stop_timer();
+ }
+}
+
+int main(void) {
+ cli();
+ timer_init_ctc();
+ init_io();
+ usart_init();
+
+
+ while(1) {
+ int level = 0;
+
+ //get level
+ usart_txstr(
+ "SIMON GAME\n"
+ "Enter your starting difficulty level:\n"
+ "1. Easy\n"
+ "2. Moderate\n"
+ "3. Give me pain.");
+
+ while((level > 3) || (level < 1)) level = (int)(usart_rxt_blocking() - '0');
+
+
+ //main simon game
+ while(level < 3) {
+ int display_time;
+ int sets;
+ int response_time;
+ int elements_min;
+ int elements_max;
+ double score;
+ uint8_t element_list[5]; // TODO
+
+
+ switch(level) {
+ case 1:
+ sets = 3;
+ display_time = 3;
+ response_time = 5;
+ elements_min = 3;
+ elements_max = 5;
+ break;
+ case 2:
+ sets = 4;
+ display_time = 2;
+ response_time = 7;
+ elements_min = 3;
+ elements_max = 10;
+ break;
+ case 3:
+ sets = 5;
+ display_time = 1;
+ response_time = 10;
+ elements_min = 5;
+ elements_max = 15;
+ break;
+ }
+
+
+ //main level
+ int max_score = 0;
+ int current_score = 0;
+ for(int set = 0; set < sets; set++) {
+ int elements = elements_min + ceil(((elements_max - elements_min) / (float)(sets - 1)) * set);
+ //generate, display elements
+ for(int element = 0; element < elements; element++) {
+ uint8_t element_bit = (rand() % ELEMENT_COUNT);
+ if(element_bit == 3) element_bit = 7;
+ uint8_t this_element = 1 << element_bit;
+ usart_txt('\n');
+ usart_txt(element_bit + '0');
+ usart_txt('\n');
+ element_list[element] = this_element; // could optimize
+ display_element(this_element, display_time);
+
+ }
+ //get elements
+ seconds_remaining = response_time;
+ start_timer();
+ uint16_t guess;
+ for(int element = 0; element < elements; element++) {
+ usart_txstr("\ngot element, waiting...\n");
+ do {
+ if(timer_done()) {
+ seconds_remaining--;
+ stop_timer(); //TODO only need one function
+ start_timer();
+ beep(261.63, .1);
+ }
+ else { guess = get_button(); }
+ } while((!guess) && (seconds_remaining > 0));
+ _delay_ms(250); //prevent double press
+ max_score++;
+ if(guess == element_list[element]) {
+ current_score++;
+ correct_beep();
+ }
+ else {
+ incorrect_beep();
+ }
+ }
+ }
+ score = (float)current_score / max_score;
+ if(score >= .8) {
+ level++;
+ usart_txstr("\nnext level\n");
+ }
+ else {
+ loose();
+ break;
+ }
+ }
+ if(level >= 3) win();
+ }
+}
+
+//timer interrupt
+ISR(TIMER1_COMPA_vect) {
+ if(seconds_remaining-- > 0) return;
+ for(;;) {
+ beep();
+ }
+}
+
+void correct_beep() {
+ usart_txstr("\nCorrect!\n");
+ beep(440.0, .1);
+}
+
+void incorrect_beep() {
+ usart_txstr("\nIncorrect guess.\n");
+ beep(261.62, .2);
+ _delay_ms(25);
+ beep(261.62, .2);
+}
+
+void win() {
+ usart_txstr("\nYou beat the game!\n");
+ beep(262., .5);
+ beep(392., .5);
+}
+
+void loose() {
+ usart_txstr("\nYou loose, try again?\n");
+ beep(330., .5);
+ beep(294., .5);
+}
+
+
+//TODO move somewhere else
+void beep(double frequency, double durientation) {
+ double speaker_ms = ((1.0 / frequency) / 2.0) * 1000.0; //TODO clean up
+ int loop_count = durientation / (1.0 / frequency);
+ for(unsigned int i = 0; i < loop_count; i++) {
+ _delay_ms(speaker_ms);
+ SPEAKER_PORT ^= (1 << SPEAKER_PIN);
+ }
+} \ No newline at end of file