#include <ezButton.h>
#include <ezBuzzer.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
//#include <HyperDisplay
#include <Adafruit_SSD1306.h>
//#include <Adafruit_SSD1309.h>
//#include <Adafruit_SSD1327.h>
//#include <U8g2lib.h>
//https://www.arduino.cc/reference/en/libraries/ezbuzzer/
//https://arduinogetstarted.com/library/button/example/arduino-single-button
//#define DEG2RAD 0.0174532925
//#define SSD1306_WHITE 1
//#define SSD1306_BLACK 0
//#define NOTE_FUCKOFF 0
//const int BLACK = SSD1327_BLACK;
//const int WHITE = SSD1327_WHITE;
const unsigned long Minute = 60000;
const unsigned long Second = 1000;
const unsigned long LoadTime = 30000;
const unsigned long RifleTime = 150000;
const unsigned long Intermission = 12000;
const unsigned long HandgunTime = 120000;
//const unsigned long Intermission = 1500;
//const unsigned long LoadTime = 2000;
//const unsigned long RifleTime = 2000;
//Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
//Adafruit_SSD1327 display = Adafruit_SSD1327 (128, 128, &Wire, -1, 1000000); //https://www.waveshare.com/wiki/1.5inch_OLED_Module
//Adafruit_SSD1327(128, 128, &Wire); //https://www.waveshare.com/wiki/1.5inch_OLED_Module
//U8GLIB_SSD1306_128X64 u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//ezButton btnSelect(5);
//ezButton btnHandgun(6);
ezButton btnLoad(3);
ezButton btnFire(4);
ezBuzzer buzzer(11); // create ezBuzzer object that attach to a pin;
// // notes in the melody:
// int melody[] = {
// NOTE_E5,
// NOTE_E5, NOTE_D5, NOTE_G5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_G5, NOTE_D5, NOTE_C5,
// NOTE_C5, NOTE_D5, NOTE_G5, NOTE_D5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_G5, NOTE_D5, NOTE_C5
// };
// // note durations: 4 = quarter note, 8 = eighth note, etc, also called tempo:
// int noteDurations[] = {
// 2,
// 3, 12, 12, 12, 12, 3, 12, 12, 12, 12,
// 3, 12, 12, 12, 12, 3, 12, 12, 12, 12
// };
//
int melody[] = {
NOTE_E4, NOTE_E4, NOTE_E4, NOTE_E5, NOTE_AS6, NOTE_B6, NOTE_AS6, NOTE_FS6, NOTE_AS6, NOTE_A6, NOTE_F6, NOTE_A6, NOTE_GS6,
NOTE_E4, NOTE_E4, NOTE_E4, NOTE_E5, NOTE_AS6, NOTE_B6, NOTE_AS6, NOTE_FS6, NOTE_AS6, NOTE_A6, NOTE_F6, NOTE_A6, NOTE_GS6,
};
// note durations: 4 = quarter note, 8 = eighth note, etc, also called tempo:
int noteDurations[] = {
8, 8, 8, 8, 8, 8, 4, 8, 8, 4, 8, 8, 4,
8, 8, 8, 8, 8, 8, 4, 8, 8, 4, 8, 8, 4,
};
char time_buffer[10];
unsigned long Elapsed_millis = 0;
long CurrentTime = 0;
long TargetTime = 0;
byte isLoad = 0;
byte isDisplayRefresh = 0;
byte IsRun = 0;
byte IsIntermission = 0;
byte isFirstRun = 1;
uint8_t timer_mode = 2;
uint8_t loop_count = 0;
// 0 = off
// 1 = Rifles Mode
// 2 = Handgun Mode
void setup() {
pinMode(5, INPUT_PULLUP);
//Serial.begin(9600);
//Serial.println("Hallo");
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
//display.begin(SSD1306_SWITCHCAPVCC, 0x78);
//display.begin(0x78);
//display.begin(SSD1327_SWITCHCAPVCC, 0x3C);
// if (!display.begin(0x3D) ){
// // Serial.begin(9600);
// // Serial.println("Could not init display");
// // Serial.End
// }
//if ( !display.begin(SSD1306_SWITCHCAPVCC, 0x3C) ) //{
// if ( !display.begin(SSD1306_SWITCHCAPVCC, 0, false, true) ) {
// //Serial.println("Unable to initialize SSD1306 OLED");
// while (1) yield();
// }
//display.begin(0x3C);
//btnSelect.setDebounceTime(50);
//btnHandgun.setDebounceTime(50);
btnLoad.setDebounceTime(50);
btnFire.setDebounceTime(50);
timer_mode = 0;
isDisplayRefresh = 1;
isFirstRun = 1;
// display.setCursor((display.width() / 2) - 42, (display.height() / 2) - 13);
// display.setTextSize(3);
// display.setTextColor(1);
// display.print("START");
// display.display();
// buzzer.beep(100);
}
void loop() {
if (isFirstRun == 1) {
isFirstRun = 0;
display.clearDisplay();
display.fillRect(36, 0, 55, 50, WHITE);
display.fillTriangle(44, 12, 44, 42, 57, 42, BLACK);
display.fillTriangle(84, 12, 84, 42, 71, 42, BLACK);
display.fillTriangle(53, 8, 75, 8, 64, 35, BLACK);
display.setTextColor(WHITE);
display.setTextSize(1.6);
display.setCursor((display.width() / 2) - 24, display.height() - 12);
display.print("MILITECH");
display.fillRect(36, display.height() - 3, 55, 3, WHITE);
display.display();
delay(1000);
}
buzzer.loop();
// put your main code here, to run repeatedly:
if ((millis() - Elapsed_millis) > 47) {
check_mode();
}
handle_buttons();
if ((TargetTime > 0 && CurrentTime > 0 && (millis() - Elapsed_millis) > 47) || isDisplayRefresh > 0)
{
isDisplayRefresh = 0;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
if (timer_mode == 1) {
display.setCursor((display.width() / 2) - (5 * 6), 4);
display.print("RIFLE MODE");
} else {
display.setCursor((display.width() / 2) - (6 * 6), 4);
display.print("HANDGUN MODE");
}
display.setTextSize(3);
display.setCursor((display.width() / 2) - 42, (display.height() / 2) - 13);
CurrentTime -= (millis() - Elapsed_millis);
Elapsed_millis = millis();
if (CurrentTime < 0) {
CurrentTime = 0;
}
display.print(get_time(CurrentTime));
//draw progress bar outer border
display.drawRect(10, display.height() - 18, display.width() - 20, 15, 1);
//draw progress bar
display.fillRect(12, display.height() - 16, (display.width() - 24) * ((CurrentTime * 1.00) / TargetTime), 11, 1);
display.setTextColor(BLACK);
display.setTextSize(1);
display.setCursor((display.width() / 2) - 9, display.height() - 15);
if (isLoad && !IsIntermission)
{
if (CurrentTime > (TargetTime - LoadTime)){
display.print("LOAD");
}
else
{
if (CurrentTime < (TargetTime - LoadTime)/2)
{
display.setTextColor(WHITE);
}
display.print("FIRE");
}
//draw /load/ indicator
display.drawFastVLine(display.width() - 12 - ((display.width() - 24) * ( (LoadTime*1.00) / TargetTime)), display.height() - 21, 3, 1);
display.drawFastVLine(display.width() - 12 - ((display.width() - 24) * ((LoadTime*1.00) / TargetTime)), display.height() - 3, 3, 1);
}
else if (IsIntermission == 0)
{
if (CurrentTime < TargetTime/2)
{
display.setTextColor(WHITE);
}
display.print("FIRE");
} else if (IsIntermission == 1)
{
if (CurrentTime < TargetTime/2)
{
display.setTextColor(WHITE);
}
display.print("WAIT");
}
display.display();
if (CurrentTime <= 0 && IsRun > 0)
{
if (IsIntermission == 1)
{
load_pressed();
return;
}
else
{
play_tune();
}
if (++loop_count >= 5)
{
TargetTime = 0;
IsRun = 0;
loop_count = 0;
}
else
{
TargetTime = Intermission;
CurrentTime = Intermission;
if (timer_mode == 2) { //if handguns, add additional 30s
TargetTime += LoadTime;
CurrentTime += LoadTime;
}
IsIntermission = 1;
}
}
}
}
void handle_buttons() {
btnLoad.loop();
btnFire.loop();
if (btnLoad.isPressed() && btnFire.isPressed())
{
IsRun = 0;
CurrentTime = 0;
TargetTime = 0;
isDisplayRefresh = 1;
return;
}
if (btnLoad.isPressed()) {
buzzer.beep(100);
load_pressed();
loop_count = 0;
}
if (btnFire.isPressed()) {
buzzer.beep(100);
fire_pressed();
loop_count = 0;
}
}
void fire_pressed(){
Elapsed_millis = millis();
if (timer_mode == 1) //rifles
{
TargetTime = RifleTime;
//Serial.println("Rifle Fire Timer Activated");
} else if (timer_mode == 2) //handguns
{
TargetTime = HandgunTime;
//Serial.println("Handgun Fire Timer Activated");
}
CurrentTime = TargetTime;
isLoad = 0;
IsRun = 1;
IsIntermission = 0;
}
void load_pressed(){
Elapsed_millis = millis();
if (timer_mode == 1) //rifles
{
TargetTime = LoadTime + RifleTime;
//Serial.println("Rifle Load Timer Activated");
} else if (timer_mode == 2) //handguns
{
TargetTime = LoadTime + HandgunTime;
//Serial.println("Handgun Load Timer Activated");
}
CurrentTime = TargetTime;
isLoad = 1;
IsRun = 1;
IsIntermission = 0;
}
void check_mode() {
int v = digitalRead(5);
if (v > 0 && timer_mode != 1) { // high for rifles
timer_mode = 1;
CurrentTime = 0;
TargetTime = 0;
isDisplayRefresh = 1;
IsRun = 0;
loop_count = 0;
}
else if (v <= 0 && timer_mode != 2) //(timer_mode != 2 && btnHandgun.getState() > 0 ){
{
timer_mode = 2;
CurrentTime = 0;
TargetTime = 0;
isDisplayRefresh = 1;
IsRun = 0;
loop_count = 0;
}
}
void play_tune() {
//Serial.println("tubez");
int length = sizeof(noteDurations) / sizeof(int);
buzzer.playMelody(melody, noteDurations, length); // playing
}
char* get_time(float remaining) {
time_buffer[0] = (char)0;
int m = (remaining / Minute);
int s = ((remaining - (m * Minute)) / Second);
// //Serial.print("Time ");
// //Serial.print(remaining);
// //Serial.print("/");
// //Serial.print(Minute);
// //Serial.print("=");
// //Serial.println(m);
//char fbuf[4];
//dtostrf(, 0, 0, fbuf);
//sprintf(buffer, "%f:%.2f", (remaining / Minute), (((int)remaining % Minute)/Second) );
sprintf(time_buffer, "%02i:%02d", m, s);
return time_buffer;
}
// //SLOW AF
// int fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour)
// {
// byte seg = 3; // Segments are 3 degrees wide = 120 segments for 360 degrees
// byte inc = 3; // Draw segments every 3 degrees, increase to 6 for segmented ring
// // Draw colour blocks every inc degrees
// for (int i = start_angle; i < start_angle + seg * seg_count; i += inc) {
// // Calculate pair of coordinates for segment start
// float sx = cos((i - 90) * DEG2RAD);
// float sy = sin((i - 90) * DEG2RAD);
// uint16_t x0 = sx * (rx - w) + x;
// uint16_t y0 = sy * (ry - w) + y;
// uint16_t x1 = sx * rx + x;
// uint16_t y1 = sy * ry + y;
// // Calculate pair of coordinates for segment end
// float sx2 = cos((i + seg - 90) * DEG2RAD);
// float sy2 = sin((i + seg - 90) * DEG2RAD);
// int x2 = sx2 * (rx - w) + x;
// int y2 = sy2 * (ry - w) + y;
// int x3 = sx2 * rx + x;
// int y3 = sy2 * ry + y;
// display.fillTriangle(x0, y0, x1, y1, x2, y2, colour);
// display.fillTriangle(x1, y1, x2, y2, x3, y3, colour);
// }
// }