Skip to content

Instantly share code, notes, and snippets.

@uXeBoy

uXeBoy/main.c Secret

Created January 9, 2023 09:59
Embed
What would you like to do?
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdbool.h>
static void init(void);
#define A_BUTTON 128
#define B_BUTTON 64
#define RIGHT_BUTTON 32
#define DOWN_BUTTON 16
#define UP_BUTTON 8
#define LEFT_BUTTON 4
#define NOTE_A5 1136
#define NOTE_GS5 1203
#define NOTE_G5 1275
#define NOTE_F5 1431
#define NOTE_E5 1516
#define NOTE_D5 1702
#define NOTE_C5 1911
#define NOTE_B4 2024
#define NOTE_A4 2272
#define NOTE_GS4 2407
typedef struct
{
int8_t second;
int8_t minute;
int8_t hour;
} time;
time t;
bool clockMode;
uint16_t counter;
int8_t d2, d3, d4, position, player, obstacles;
uint8_t SEG_1B, SEG_1C;
uint8_t SEG_2A, SEG_2B, SEG_2C, SEG_2D, SEG_2E, SEG_2F, SEG_2G;
uint8_t SEG_3A, SEG_3B, SEG_3C, SEG_3D, SEG_3E, SEG_3F, SEG_3G;
uint8_t noteIndex, currentButtonState, previousButtonState;
const uint16_t notes[192] PROGMEM = {NOTE_E5, NOTE_E5, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_D5, NOTE_F5, NOTE_A5, NOTE_A5, NOTE_G5, NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_D5, NOTE_F5, NOTE_A5, NOTE_A5, NOTE_G5, NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_D5, NOTE_D5, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_GS4, NOTE_GS4, NOTE_GS4, NOTE_GS4, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_D5, NOTE_D5, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_C5, NOTE_E5, NOTE_E5, NOTE_A5, NOTE_A5, NOTE_A5, NOTE_A5, NOTE_GS5, NOTE_GS5, NOTE_GS5, NOTE_GS5, NOTE_GS5, NOTE_GS5, NOTE_A4, NOTE_C5};
uint8_t buttonsState(void)
{
return ((~PINE) & 0b11111100);
}
void pollButtons(void)
{
previousButtonState = currentButtonState;
currentButtonState = buttonsState();
}
bool pressed(uint8_t buttons)
{
return (buttonsState() & buttons) == buttons;
}
bool justPressed(uint8_t button)
{
return (!(previousButtonState & button) && (currentButtonState & button));
}
bool justReleased(uint8_t button)
{
return ((previousButtonState & button) && !(currentButtonState & button));
}
int main(void)
{
ASSR = 0b00001000; // Asynchronous Timer/Counter2
ADCSRA = 0b00000000; // Disable ADC
PRR = 0b00000011; // Power Reduction Register (Shutdown USART/ADC)
LCDFRR = 0b01000000; // Prescaler clkLCD/512
LCDCCR = 0b00010000; // LCD Maximum Drive Time
LCDCRB = 0b10000111; // LCD Clock Select, LCD Mux Select, LCD Port Mask
LCDCRA = 0b10000110; // LCD Enable, LCD Buffer Disable, LCD Contrast Control Disable
DDRA = 0b11110001; // COM0, SEG0-SEG3
DDRB = 0b01000110; // SPI, Buzzer
DDRC = 0b11111111; // SEG12-SEG5
DDRD = 0b11111111; // SEG22-SEG15
DDRE = 0b00000000; // Button Inputs
DDRF = 0b10001101; // XOR 1A,3A,4A,2A
DDRG = 0b00011111; // SEG14,SEG13,SEG4,SEG24,SEG23
// enable pull-ups on inputs and unused pins
PORTA = 0b00001110;
PORTB = 0b10110001;
PORTE = 0b11111111;
PORTF = 0b01110010;
// set up Timer 1
TCCR1A = 0; // set normal mode (which disconnects the pin)
TCCR1B = 0b00001001; // CTC mode, No prescaling
t.hour = 12;
clockMode = true;
/* Initialize registers and configure RTC. */
init();
while (1)
{
pollButtons();
if (justReleased(B_BUTTON))
{
if (clockMode) // leaving clock mode
{
clockMode = false;
SEG_1C = 0;
SEG_1B = 0;
counter = 0;
position = 4;
obstacles = 0;
d2 = -1;
d3 = -1;
d4 = -1;
}
else if (!clockMode) // leaving game mode
{
clockMode = true;
PORTF = 0b01110010;
TCCR1A = 0; // set normal mode (which disconnects the pin)
}
}
if (clockMode)
{
if (justReleased(UP_BUTTON) || justReleased(DOWN_BUTTON))
{
t.second = 0;
TIMSK2 = 1; // Enable Overflow Interrupt
TCCR1A = 0; // set normal mode (which disconnects the pin)
}
if (justPressed(UP_BUTTON) || justPressed(DOWN_BUTTON))
{
TIMSK2 = 0; // Disable Overflow Interrupt
PORTF = 0b01110010; // Disable Colon
OCR1A = pgm_read_word(&notes[noteIndex]);
TCCR1A = 0b00010000; // set toggle on compare mode (which connects the pin)
counter = 0;
}
if (pressed(UP_BUTTON) && ++counter == 200)
{
counter = 0;
if(++noteIndex == 192) noteIndex = 0;
OCR1A = pgm_read_word(&notes[noteIndex]);
if (++t.minute == 60)
{
t.minute = 0;
if (++t.hour == 13)
{
t.hour = 1;
}
}
}
else if (pressed(DOWN_BUTTON) && ++counter == 200)
{
counter = 0;
if(++noteIndex == 192) noteIndex = 0;
OCR1A = pgm_read_word(&notes[noteIndex]);
if (--t.minute == -1)
{
t.minute = 59;
if (--t.hour == 0)
{
t.hour = 12;
}
}
}
d3 = 0;
d4 = t.minute;
while (d4 > 9)
{
d4 = d4 - 10;
d3 = d3 + 1;
}
if (t.hour > 9)
{
d2 = t.hour - 10;
SEG_1C = 2;
SEG_1B = 128;
}
else
{
d2 = t.hour;
SEG_1C = 0;
SEG_1B = 0;
}
}
else // game mode
{
if (pressed(UP_BUTTON))
{
PORTF = 0b00001000; // player top (SEG_1A)
player = 10;
}
else if (pressed(DOWN_BUTTON))
{
PORTF = 0b10000000; // player bottom (SEG_1D)
player = 11;
}
else
{
PORTF = 0b00000001; // player middle (SEG_1G)
}
if (counter == 1500)
{
OCR1A = 2272; // 440Hz
TCCR1A = 0b00010000; // set toggle on compare mode (which connects the pin)
}
if (++counter == 2000)
{
switch(position)
{
case 1:
if (player == d2) // GAME OVER!
{
for (uint16_t z = 0; z < 65535; z++)
{
switch(z)
{
case 0: // SEG A
OCR1A = 1136; // 880Hz, see https://pages.mtu.edu/~suits/notefreqs.html and https://eleccelerator.com/avr-timer-calculator/
LCDDR2 = 0b00010001;
LCDDR1 = 0b00010000;
LCDDR0 = 0;
PORTF = 0b00001000;
break;
case 4096:
OCR1A = 1203; // 830.61Hz
break;
case 8192: // SEG F
OCR1A = 1275; // 783.99Hz
LCDDR3 = 0b00000001;
LCDDR2 = 0b00100010;
LCDDR1 = 0b00100000;
PORTF = 0;
break;
case 12288:
OCR1A = 1351; // 739.99Hz
break;
case 16384: // SEG G
OCR1A = 1431; // 698.46Hz
LCDDR3 = 0;
LCDDR2 = 0b01000100;
LCDDR1 = 0b01000000;
PORTF = 0b00000001;
break;
case 20480:
OCR1A = 1516; // 659.25Hz
break;
case 24576: // SEG C
OCR1A = 1607; // 622.25Hz
LCDDR2 = 0;
LCDDR1 = 0b00000100;
LCDDR0 = 0b10010010;
PORTF = 0;
break;
case 28672:
OCR1A = 1702; // 587.33Hz
break;
case 32768: // SEG D
OCR1A = 1803; // 554.37Hz
LCDDR1 = 0b00000010;
LCDDR0 = 0b01001000;
PORTF = 0b10000000;
break;
case 36864:
OCR1A = 1911; // 523.25Hz
break;
case 40960: // SEG E
OCR1A = 2024; // 493.88Hz
LCDDR1 = 0b00000001;
LCDDR0 = 0b00100101;
PORTF = 0;
break;
case 45056:
OCR1A = 2145; // 466.16Hz
break;
case 49152: // SEG G
OCR1A = 2272; // 440Hz
LCDDR2 = 0b01000100;
LCDDR1 = 0b01000000;
LCDDR0 = 0;
PORTF = 0b00000001;
break;
case 53248:
OCR1A = 2407; // 415.3Hz
break;
case 57344: // SEG B
OCR1A = 2551; // 392Hz
LCDDR2 = 0b10001000;
LCDDR1 = 0b10001000;
PORTF = 0b01110010;
break;
}
}
clockMode = true;
}
else
{
for (uint16_t z = 0; z < 20000; z++)
{
switch(z)
{
case 0:
OCR1A = 1136; // 880Hz
break;
case 10000:
OCR1A = 568; // 1760Hz
break;
}
}
}
d2 = -1;
position = 4;
break;
case 2:
d2 = d3;
d3 = -1;
player = d2;
position--;
break;
case 3:
d3 = d4;
d4 = -1;
position--;
break;
case 4:
if (TCNT2 & 1) d4 = 10;
else d4 = 11;
position--;
break;
}
TCCR1A = 0; // set normal mode (which disconnects the pin)
counter = ++obstacles * 10;
if (counter > 1450) counter = 1450;
}
}
// DIGIT2
if (d2 == 0 || d2 == 2 || d2 == 3 || d2 == 5 || d2 == 6 || d2 == 7 || d2 == 8 || d2 == 9 || d2 == 10) SEG_2A = 16;
else SEG_2A = 0;
if (d2 == 0 || d2 == 1 || d2 == 2 || d2 == 3 || d2 == 4 || d2 == 7 || d2 == 8 || d2 == 9 || d2 == 10) SEG_2B = 8;
else SEG_2B = 0;
if (d2 == 0 || d2 == 1 || d2 == 3 || d2 == 4 || d2 == 5 || d2 == 6 || d2 == 7 || d2 == 8 || d2 == 9 || d2 == 11) SEG_2C = 16;
else SEG_2C = 0;
if (d2 == 0 || d2 == 2 || d2 == 3 || d2 == 5 || d2 == 6 || d2 == 8 || d2 == 9 || d2 == 11) SEG_2D = 8;
else SEG_2D = 0;
if (d2 == 0 || d2 == 2 || d2 == 6 || d2 == 8 || d2 == 11) SEG_2E = 4;
else SEG_2E = 0;
if (d2 == 0 || d2 == 4 || d2 == 5 || d2 == 6 || d2 == 7 || d2 == 8 || d2 == 9 || d2 == 10) SEG_2F = 32;
else SEG_2F = 0;
if (d2 == 2 || d2 == 3 || d2 == 4 || d2 == 5 || d2 == 6 || d2 == 8 || d2 == 9 || d2 == 10 || d2 == 11) SEG_2G = 64;
else SEG_2G = 0;
// DIGIT3
if (d3 == 0 || d3 == 2 || d3 == 3 || d3 == 5 || d3 == 10) SEG_3A = 1;
else SEG_3A = 0;
if (d3 == 0 || d3 == 1 || d3 == 2 || d3 == 3 || d3 == 4 || d3 == 10) SEG_3B = 128;
else SEG_3B = 0;
if (d3 == 0 || d3 == 1 || d3 == 3 || d3 == 4 || d3 == 5 || d3 == 11) SEG_3C = 128;
else SEG_3C = 0;
if (d3 == 0 || d3 == 2 || d3 == 3 || d3 == 5 || d3 == 11) SEG_3D = 64;
else SEG_3D = 0;
if (d3 == 0 || d3 == 2 || d3 == 11) SEG_3E = 32;
else SEG_3E = 0;
if (d3 == 0 || d3 == 4 || d3 == 5 || d3 == 10) SEG_3F = 2;
else SEG_3F = 0;
if (d3 == 2 || d3 == 3 || d3 == 4 || d3 == 5 || d3 == 10 || d3 == 11) SEG_3G = 4;
else SEG_3G = 0;
LCDDR0 = SEG_3C + SEG_3D + SEG_3E + SEG_2C + SEG_2D + SEG_2E + SEG_1C;
LCDDR2 = SEG_1B + SEG_2G + SEG_2F + SEG_2A + SEG_2B + SEG_3G + SEG_3F + SEG_3A;
// DIGIT4
switch(d4)
{
case 0:
LCDDR1 = 0b00111111 + SEG_3B;
break;
case 1:
LCDDR1 = 0b00001100 + SEG_3B;
break;
case 2:
LCDDR1 = 0b01011011 + SEG_3B;
break;
case 3:
LCDDR1 = 0b01011110 + SEG_3B;
break;
case 4:
LCDDR1 = 0b01101100 + SEG_3B;
break;
case 5:
LCDDR1 = 0b01110110 + SEG_3B;
break;
case 6:
LCDDR1 = 0b01110111 + SEG_3B;
break;
case 7:
LCDDR1 = 0b00111100 + SEG_3B;
break;
case 8:
LCDDR1 = 0b01111111 + SEG_3B;
break;
case 9:
LCDDR1 = 0b01111110 + SEG_3B;
break;
case 10: // top obstacle
LCDDR1 = 0b01111000;
break;
case 11: // bottom obstacle
LCDDR1 = 0b01000111;
break;
default:
LCDDR1 = 0b00000000 + SEG_3B;
}
}
}
// AVR134: Real Time Clock (RTC) Using the Asynchronous Timer
static void init(void)
{
/* Wait for external clock crystal to stabilize */
for (uint16_t j = 0; j < 0xFFFF; j++)
{
/* Do a nop instruction to keep the empty
* loop from being optimized away */
asm volatile("nop");
}
/* Make sure all TC2 interrupts are disabled */
TIMSK2 = 0;
/* Reset timer */
TCNT2 = 0;
/* Prescale the timer to be clock source/64 to make */
/* TC2 overflow precisely twice every second. */
TCCR2A = (1 << CS22);
/* Wait until TC2 is updated */
while (ASSR & ((1 << TCN2UB) | (1 << OCR2UB) | (1 << TCR2UB))) {}
/* Enable Timer/Counter2 Overflow Interrupt */
TIMSK2 = 1;
/* Set the Global Interrupt Enable Bit */
sei();
}
/* keep track of time */
ISR(TIMER2_OVF_vect)
{
if (clockMode) PINF = 0b00000100; // toggle colon
if (++t.second == 120)
{
t.second = 0;
if (++t.minute == 60)
{
t.minute = 0;
if (++t.hour == 13)
{
t.hour = 1;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment