#include <Wire.h>
#include <EEPROM.h>
#include <BleGamepad.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
BleGamepad bleGamepad("FS-Gun", "Es", 100);
//Profiles 1
//Profiles
#define t_sp 1//не міняти число!
#define t_mp 2//не міняти число!
#define r_off 0 // = off
#define r_on 12 // = on
#define get_name 20
#define get_name_a_f 21
#define change_letter 22
//*prof()
#define direct_p_sp 20
#define direct_p_mp 21
#define act_dir 22
#define activate_p_sp 23
#define activate_p_mp 24
#define eeprom_initialization 25
uint32_t tmrProf = 0;
byte defButton[11] = {0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
class Profiles {
public:
Profiles(int deZoH, byte senHor, int deZoV, byte senVer, char* nameProf, byte tpProf, byte nabProf)
: deadZoneHor(deZoH),
sensitivityHor(senHor),
deadZoneVer(deZoV),
sensitivityVer(senVer),
tape(tpProf),
namber(nabProf),
status(r_off),
buttonArray{0, 18, 19, 2, 26, 25, 16, 17, 5, 33, 14, 23, 27} { //при глюках замінити на memcpy(buttonArray, defaultButtonArray, sizeof(buttonArray));
strncpy(nameArray, nameProf, 20);
nameArray[20] = '\0';
}
int setDeZoHor(int deZoH) {//set
if (deadZoneHor != deZoH) {sensitivityHor = 0;}
deadZoneHor = deZoH;
return 0;
}
byte setSenHor(byte senHor) {
sensitivityHor = senHor;
return 0;
}
int setDeZoVer(int deZoV) {
if (deadZoneVer != deZoV) {sensitivityVer = 0;}
deadZoneVer = deZoV;
return 0;
}
byte setSenVer(byte senVer) {
sensitivityVer = senVer;
return 0;
}
byte setStatus(byte st) {
status = st;
return 0;
}
const char* nameProfiles(byte acceptedCommand, byte index = 0, char Letter = ' '){
char baldness[] = "";//baldness беззмістовність
if (status == r_on && tmrProf < millis()){
tmrProf = millis()+600;
Flag = !Flag;
}
else if (status == r_off && !Flag){
Flag = 1;
}
switch (acceptedCommand) {
case get_name:
return nameArray;
break;
case get_name_a_f:
if (Flag) {
return nameArray;
}
else {
return baldness;
}
break;
case change_letter:
nameArray[index] = Letter;
break;
return baldness;
}
return baldness;
}
byte centroName() {
for (int i = 19; i >= 0; i--) {
if (nameArray[i] != ' '){
return 61-i*3;
break;
}
}
return 0;
}
byte getNamberTape(){
return tape * 10 +namber;//логіка роботи тип може бути 1 або 2 множимо на 10 щоб не збігалася числа
}
void resetButtons(){
for (int i = 0; i < sizeof(defButton); i++) {
buttonArray[i] = defButton[i];
}
}
void copyFrom(const Profiles& other) {
deadZoneHor = other.deadZoneHor;
sensitivityHor = other.sensitivityHor;
deadZoneVer = other.deadZoneVer;
sensitivityVer = other.sensitivityVer;
tape = other.tape;
namber = other.namber;
status = other.status;
memcpy(buttonArray, other.buttonArray, sizeof(buttonArray));
memcpy(nameArray, other.nameArray, sizeof(nameArray));
}
bool operator!=(const Profiles& other) const {
return (deadZoneHor != other.deadZoneHor) ||
(sensitivityHor != other.sensitivityHor) ||
(deadZoneVer != other.deadZoneVer) ||
(sensitivityVer != other.sensitivityVer) ||
(tape != other.tape) ||
(namber != other.namber) ||
(status != other.status) ||
(memcmp(buttonArray, other.buttonArray, sizeof(buttonArray)) != 0) ||
(memcmp(nameArray, other.nameArray, sizeof(nameArray)) != 0);
}
// prof(act_dir)->sensitivityHor;
char nameArray[21];
byte buttonArray[13];
byte Flag;
int deadZoneHor;//(primary початкова) початок руху
byte sensitivityHor;
int deadZoneVer;
byte sensitivityVer;
byte tape;
byte namber;
byte status;
private:
};
// Ініціалізуємо статичну змінну класу Profiles
Profiles profilSeve(0, 0, 0, 0, "0", 0, 0);
Profiles profilSpOne(2000, 100, 2556, 92, "CodMW", t_sp, 1);
Profiles profilSpTwo(166, 120, 1965, 112, "Batl3", t_sp, 2);
Profiles profilSpThree(2000, 100, 2556, 92, "SP 33", t_sp, 3);
Profiles profilSpFour(166, 120, 1965, 112, "SP 44", t_sp, 4);
Profiles profilSpFive(2000, 100, 2556, 92, "SP 55", t_sp, 5);
Profiles profilSpSix(166, 120, 1965, 112, "SP 66", t_sp, 6);
Profiles profilSpSeven(2000, 100, 2556, 92, "SP 77", t_sp, 7);
Profiles profilMpOne(2000, 100, 2556, 92, "05461 ", t_mp, 1);
Profiles profilMpTwo(166, 120, 1965, 112, "Xmen 74 ", t_mp, 2);
Profiles profilMpThree(2000, 100, 2556, 92, "Mp 3 ", t_mp, 3);
Profiles profilMpFour(166, 120, 1965, 112, "Mp 4 ", t_mp, 4);
Profiles profilMpFive(2000, 100, 2556, 92, "Mp 5 ", t_mp, 5);
Profiles profilMpSix(166, 120, 1965, 112, "Mp 6 ", t_mp, 6);
Profiles profilMpSeven(2000, 100, 2556, 92, "Mp 7 ", t_mp, 7);
Profiles *prof(byte acceptedCommand, byte number = 0){
static byte acting = []() -> byte {//одноразова інт пер лямбда функція оскільки метод не повертає значення потрібно зробити так
byte temp;
EEPROM.get(7 * sizeof(Profiles) + 1, temp); // Читаємо значення з EEPROM
return temp; // Повертаємо прочитане значення
}();
Profiles *profArray[] = {&profilSeve, &profilSpOne, &profilSpTwo, &profilSpThree, &profilSpFour, &profilSpFive, &profilSpSix, &profilSpSeven,
&profilMpOne, &profilMpTwo, &profilMpThree, &profilMpFour, &profilMpFive, &profilMpSix, &profilMpSeven};
if (acceptedCommand == act_dir) {//скерування до активного профілю
return profArray[acting];
}
else if (acceptedCommand == direct_p_sp) {//скеровує до стандартного профіля Для певних настройок
return profArray[number];
}
else if (acceptedCommand == direct_p_mp) {//скеровує до власного профіля Для певних настройок
return profArray[number+7];
}
else if (acceptedCommand == activate_p_sp || acceptedCommand == activate_p_mp) {//вибраний профіль активується
for (int i = 1; i < 15; i++){
profArray[i]->setStatus(r_off);
}
if (acceptedCommand == activate_p_sp ) {
profArray[number] -> setStatus(r_on);
acting = number;
}
else {
profArray[number+7] -> setStatus(r_on);
acting = number+7;
}
EEPROM.put(7 * sizeof(Profiles) + 1, acting);
EEPROM.commit();
//Serial.println(sizeof(Profiles));
//Serial.println(EEPROM.get(0, acting));
}
else if (acceptedCommand == eeprom_initialization) {
//Serial.println("sizeof(Profiles)");
//Serial.println(sizeof(Profiles));
if (acting == 255) {//Якщо правда то це самий перший запуск потрібно зберегти в профілі і перемінну енергонезалежну пам'ять
acting = 8;
EEPROM.put(0 * sizeof(Profiles), profilMpOne);
EEPROM.put(1 * sizeof(Profiles), profilMpTwo);
EEPROM.put(2 * sizeof(Profiles), profilMpThree);
EEPROM.put(3 * sizeof(Profiles), profilMpFour);
EEPROM.put(4 * sizeof(Profiles), profilMpFive);
EEPROM.put(5 * sizeof(Profiles), profilMpSix);
EEPROM.put(6 * sizeof(Profiles), profilMpSeven);
EEPROM.put(7 * sizeof(Profiles) + 1, acting);
EEPROM.commit();
/*
for (int i = 0; i <= 6; i++){
EEPROM.put(i * sizeof(Profiles), profArray[i+8]);
Serial.println(i);
}
EEPROM.commit();
*/
}
else{//якщо Дані були вже збережені раніше то повертаємо їх з енергонезалежної пам'яті
EEPROM.get(0 * sizeof(Profiles), profilMpOne);
EEPROM.get(1 * sizeof(Profiles), profilMpTwo);
EEPROM.get(2 * sizeof(Profiles), profilMpThree);
EEPROM.get(3 * sizeof(Profiles), profilMpFour);
EEPROM.get(4 * sizeof(Profiles), profilMpFive);
EEPROM.get(5 * sizeof(Profiles), profilMpSix);
EEPROM.get(6 * sizeof(Profiles), profilMpSeven);
}
/*
for (int i = 0; i <= 6; i++){
EEPROM.get(i * sizeof(Profiles), *profArray[i+8]); //*profArray[i+8]???
Serial.println(i);
}
*/
profArray[acting] -> setStatus(r_on);
}
return 0;
}
//P
//Additional_elements 2
bool Vibrgyro;
// СПІЛЬНІ КОНСТАНТИ ПІД ХОД ДЛЯ БАГ ФУНК
#define no_action 0 // НЕМА ДІЇ
#define no_data 0 // немає даних
#define no_indication 0 // немає вказівки
#define off 0
#define get_status 1 // получити настройки
#define yes 1
#define save_settings 4 // зберехти настройки
#define reset 11
#define on 12
#define click 13
#define execute_code 14// execution without comman - виконання без команди
#define gyro 15
#define profil 16
#define centering 17
#define melody_start 1
#define melody_off_power 2
#define x_axis_hor 1
#define y_axis_ver 2
#define z_axis_ver 3
#define get_y 2
#define get_z 3
#define get_vibr 4
//Піни карта
//#define b_mein 25
#define b_emul_dpad 1
#define b_handle 4
#define b_triger 33
#define b_analog 32
#define b_on_off 14
#define b_emul_dpad 26
#define b_sw 32
#define p_dt 34
#define p_clk 35
#define thandle_touch_button 27
//Mf_EncoderButton();
//#define click 13
#define press_b_e 20
#define hold_b_e 21
#define reset_status 23
//Md_Display(byte Receiving) {
#define info_display 20
#define menu 21
#define confirm_selection 22
#define lang_eng 25
#define lang_ukr 26
#define click_in_dis_on 27
//Md_MainDisplayENG();
#define menu_off 21
#define menu_start 22
//byte Md_addres();
//#define click 13
#define back 20
#define address_entered 21
#define get_add 22
#define int_add 23
#define add_status 24
#define int_add_last 25
#define address_deleted 26
#define click_reset_off 27
//int Md_cursor();
//#define reset 11
#define selection_inversion 21
#define freeze_position 22
#define get_pos 23
#define return_pos 24
#define cursor_type_one 25
#define cursor_type_two 26
byte noData[1];
byte posOne[] = {1};
byte posTwo[] = {2};
byte posThree[] = {3};
byte posFour[] = {4};
byte posFive[] = {5};
byte posSix[] = {6};
byte posEight[] = {7};
//Ae_InterruptReadPinDtEncoder()
//Mf_Encoder();
#define rotated_rights 20
#define rotated_left 21
//MdAf_confirmYesNo()
//MdAf_consenDisplay()
#define choice_yes 20
#define choice_no 21
//MdAf_profileStorage()
#define copy_profile 20
#define return_save 21
#define check_changes 22
#define recorded_changes 23//зафіксовані зміни
//Mf_Buttons()
//#define reset 11
#define next_animation 20
// прототипи
//int8_t Md_addres(int8_t addNumb = 0, int8_t acceptedCommand = 0, int8_t acceptedData = 0);
byte Md_p_Buttons(byte receivedData = 0, byte selectedButton = 0);
int Md_movingButtons(int acceptedCommand = 0);
byte Mf_EncoderButton(byte acceptedCommand = 0);
byte MdAf_infoDisplay(byte acceptedCommand = 0);
byte Md_Display(byte Receiving = 0);
byte Ae_autoShutdown(byte acceptedCommand = 0);
byte Ae_BatR(byte Taking) {
return !digitalRead(Taking);
}
void Ae_InterruptReadPinDtEncoder() { //дивитися на початку в void setup працюэ разом з attachInterrupt(digitalPinToInterrupt(p_dt), Ae_InterruptReadPinDtEncoder, CHANGE);
static int8_t clkStateCurrent;
static int8_t clkStateLast;
clkStateCurrent = digitalRead(p_clk);
if ((clkStateLast == LOW) && (clkStateCurrent == HIGH)) {
if (digitalRead(p_dt) == HIGH) {
Mf_encoderActionStorage(rotated_rights);
}
else {
Mf_encoderActionStorage(rotated_left);
}
}
clkStateLast = clkStateCurrent;
}
byte Ae_autoShutdown(byte acceptedCommand){
static uint32_t tmr = 300000;
if (acceptedCommand == reset) {
tmr = 300000 + millis();// 5 hv
}
else if (tmr < millis()){
delay(400);
esp_deep_sleep_start();
}
return 0;
}
void Ae_buttonOnOff(){
if (!digitalRead(13)) {
delay(400);
esp_deep_sleep_start();
}
delay(100);
}
//Ae
//Main_display 3
// add1-----------------------------------------------------------------------------------------------------------
void Md_MainDisplay() {// головна фунція виклик решта функцій дисплея
display.clearDisplay();
switch (Md_addres(1, int_add)) {
case no_action:
MdAf_BluetoothPrint();
MdAf_typeNumberPrint();
MdAf_batteryPrint();
Md_ItemOne();
break;//1
case 1:
Md_Profile();
break;//a2
case 2:
//qr-код ссылка на інструкцію
break;//a2
case address_entered:
if (Md_addres(1, get_add) == 3) {
Md_Display(info_display);
Md_cursor(posOne, return_pos);
Md_addres(1, back);
}
else{
Md_cursor(posOne, return_pos);
}
break;
}
display.display();
}
void Md_ItemOne(){
byte Lines[] = {22, 32, 43};
Md_cursor(Lines, sizeof(Lines));
display.setCursor(0, 22);
display.println(" Profile");
display.setCursor(0, 32);
display.println(" Instruction ");
display.setCursor(0, 43);
display.println(" Exit menu ");
}
//
// add2-----------------------------------------------------------------------------------------------------------
void Md_Profile() {
if (prof(act_dir)->tape == t_sp) {//в залежності від типу профілю вид меню міняється
switch (Md_addres(2, int_add)) {
case no_action:
Md_p_Profile();
break;
case 1:
Md_ProfileSettings();
break;//a3
case 2:// QR code
break;
case 3:
Md_SelectProfile();
break;//a3
case address_entered:
if (Md_addres(2, get_add) == 4) {
Md_addres(1, back);
}
else if (Md_addres(2, get_add) == 1) {
MdAf_profileStorage(copy_profile);////копіюємо профіль при вдоході в настройки для подальшої перевірки на зміни при виході
}
Md_cursor(posOne, return_pos);
break;
}
}
else {
switch (Md_addres(2, int_add)) {
case no_action:
Md_p_Profile();
break;
case 1://a3
Md_ProfileSettings();
break;
case 2: //a3
Md_SelectProfile();
break;
case address_entered:
if (Md_addres(2, get_add) == 3) {
Md_addres(1, back);
}
else if (Md_addres(2, get_add) == 1) {
MdAf_profileStorage(copy_profile);////копіюємо профіль при вдоході в настройки для подальшої перевірки на зміни при виході
}
Md_cursor(posOne, return_pos);
break;
}
}
}
void Md_p_Profile() {
byte LinesSp[] = {31, 39, 49, 57};
byte LinesMp[] = {35, 49, 57};
if (prof(act_dir)->tape == t_sp) {
Md_cursor(LinesSp, sizeof( LinesSp));
}
else {
Md_cursor(LinesMp, sizeof(LinesMp));
}
display.setCursor(3, 1);//стрілки по боках активний профіль
display.write(25);
display.setCursor(118, 1);
display.write(25);
display.drawRoundRect(0, 0, 127, 10, 2, WHITE);// РАМКА АКТИВ ПРОФ НАЗВА ГРИ
display.drawRect(0, 9, 127, 19, WHITE);
display.drawRect(10, 29, 51, 19, WHITE);// РАМКА НАСТРОЙКИ КЮАР КОД
display.setCursor(21, 1);
display.print("Active profile");
display.setCursor(98, 36); //РИСКА В лыво РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
display.println("_" );
display.setCursor(93, 36);
display.println("_" );
display.setCursor(91, 36);// СТРЫЛКА ВВЕРХ РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
display.write(24);
display.setCursor(91, 34);
display.write(30);
display.drawCircle(113, 42, 11, WHITE);// КРУГ НАВК Sp
display.setCursor(105, 39);
if (prof(act_dir)->tape == t_sp) {
display.print("Sp");
display.println(prof(act_dir)->namber);
}
else {
display.print("Mp");
display.println(prof(act_dir)->namber);
}
display.setCursor(prof(act_dir)->centroName(), 15);//функція centroName() в залежності від кількості ім'я вранці
display.println(prof(act_dir)->nameProfiles(get_name));
display.setCursor(0, 32); //РИСКА В ПРАВО РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
display.println(" _" );
display.setCursor(4, 32);
display.println(" _" );
display.setCursor(66, 32);// СТРЫЛКА ВВЕРХ РАЗОМ ПОЛУЧАЭТСЯ КРИВА СТРЫЛКА
display.write(24);
display.setCursor(66, 30);
display.write(30);
if (prof(act_dir)->tape == t_sp) {
display.setCursor(0, 31);
display.println(" Settings " );
display.println(" QR code");
}
else {
display.setCursor(0, 35);
display.println(" Settings " );
}
display.setCursor(0, 49);
display.println(" Select profile ");
display.println(" Back" );
}
/*
void Md_p_Settings() {
display.setCursor(0, 0);
display.println(" Hibernation ");
display.println(" Sounds ");
display.println(" Gamepad mode ");
display.println(" Back" );
}
*/
//
// add3-----------------------------------------------------------------------------------------------------------
void Md_SelectProfile() {
switch (Md_addres(3, int_add)) {
case no_action:
Md_p_SelectProfile();
break;
case 1:
Md_StandardProfiles();
break;
case 2:
Md_MyProfiles();
break;
case address_entered:
if (Md_addres(3, get_add) == 3) {
if (prof(act_dir)->tape == t_sp) {
Md_cursor(posThree, return_pos);
}
else{
Md_cursor(posTwo, return_pos);
}
Md_addres(2, back);
}
else{
Md_cursor(posOne, return_pos);
}
break;
}
}
void Md_p_SelectProfile() {
byte Lines[] = {16, 24, 32};
Md_cursor(Lines, sizeof(Lines));
display.setCursor(0, 16);
display.println(" Standard profiles" );
display.println(" My profiles");
display.println(" Back" );
}
void Md_ProfileSettings() {
if (prof(act_dir)->tape == t_sp) { //вид пунктiv меню якщо профіль стандартний
switch (Md_addres(3, int_add)) {
case no_action:
Md_p_ProfileSettings();
break;
case 1:
Md_Buttons();
break;//Buttons
case 2:// якщо були зміни то повернення відбудеться через функцію MdAf_profileStorage
if (MdAf_profileStorage(check_changes) == recorded_changes) {//перевірка на наявність змін
switch (MdAf_consenDisplay()) {//якщо є зміни запуститься дисплей підтвердження при виході з настройок
case choice_yes:
MdAf_profileStorage(copy_profile);//якщо виберемо так профіль повторно скопірується і функція MdAf_profileStorage перестане видавати recorded_changes
Md_addres(2, back);
break;
case choice_no:
MdAf_profileStorage(return_save);//якщо виберемо Ні функція dAf_profileStorage перестане видавати recorded_changes і умова перестане виконуватися
Md_addres(2, back);
break;
}
}else{
Md_addres(2, back);
}
break;
case address_entered:
Md_cursor(posOne, return_pos);
break;
}
}
else { // вид пунктів якщо вибрано власний профіль
switch (Md_addres(3, int_add)) {
case no_action: //a2
Md_p_ProfileSettings();//відображення пунктів настройки
break;
case 1://Gyroscope //a4
Md_gyroscopeSettings();
break;
case 2://Buttons
Md_Buttons();
break;
case 3://Name
Md_changeNameProfile();
break;
case 4:// якщо були зміни то повернення в попередній пункт меню відбудеться через функцію MdAf_profileStorage
if (MdAf_profileStorage(check_changes) == recorded_changes) {//перевірка на наявність змін
switch (MdAf_consenDisplay()) {//якщо є зміни запуститься дисплей підтвердження при виході з настройок
case choice_yes:
MdAf_profileStorage(reset);//якщо виберемо так перестане видавати recorded_changes
Md_addres(2, back);
break;
case choice_no:
MdAf_profileStorage(return_save);//якщо виберемо Ні функція dAf_profileStorage перестане видавати recorded_changes і умова перестане виконуватися
Md_addres(2, back);
break;
}
}
else{//якщо змін не було то просто повертаємося
Md_addres(2, back);
}
break;
case address_entered:
Md_cursor(posOne, return_pos);
break;
}
}
}
void Md_p_ProfileSettings() {
byte LinesSp[] = {16, 24};
byte LinesMp[] = {16, 24, 32, 50};
if (prof(act_dir)->tape == t_sp) {
Md_cursor(LinesSp, sizeof(LinesSp));
display.setCursor(0, 16);
display.println(" Buttons" );//не добавляти пункт reset не потрібно
display.println(" Back" );
} else {
Md_cursor(LinesMp, sizeof(LinesMp));
display.drawRoundRect(9, 14, 59, 28, 0, WHITE);
display.setCursor(0, 16);
display.println(" Gyroscope" );
display.println(" Buttons" );
display.println(" Name" );
display.setCursor(0, 50);
display.println(" Back" );
}
}
//
// add4-----------------------------------------------------------------------------------------------------------
void Md_StandardProfiles() {
switch (Md_addres(4, int_add)) {
case no_action:
Md_p_StandardProfiles();//відображення списку профілів вибір
break;
case address_entered:
if (Md_addres(4, get_add) == 8) {
Md_cursor(posOne, return_pos);
Md_addres(3, back);
}
else{
if (prof(act_dir)->getNamberTape() != prof(direct_p_sp, Md_addres(4, get_add))->getNamberTape()) {
prof(activate_p_sp, Md_addres(4, get_add));
Md_cursor(posOne, return_pos);
Md_addres(2, back);
}
else{Md_addres(4, back); }
}
break;
}
}
void Md_p_StandardProfiles(){
byte Lines[] = {0, 8, 16, 24, 32, 40, 48, 56};
Md_cursor(Lines, sizeof(Lines));
for (int i = 0; i < 7; i++) {//виводим імена профілів діючий профіль мигає
display.setCursor(6, i*8);
display.print(prof(direct_p_sp, i+1)->nameProfiles(get_name_a_f));
}
display.setCursor(0, 56);
display.println(" Back" );
}
void Md_MyProfiles(){
switch (Md_addres(4, int_add)){//третій параметр забороняє вибирати діючий профіль
case no_action:
Md_p_MyProfiles();
break;
case address_entered:
if (Md_addres(4, get_add) == 8) {//повертаємося в передній пункт
Md_cursor(posOne, return_pos);
Md_addres(3, back);
}
else{//якщо вибраний профіль не є діючий виконуємо заміну якщо так просто повертаємося
if (prof(act_dir)->getNamberTape() != prof(direct_p_mp, Md_addres(4, get_add))->getNamberTape()) {
prof(activate_p_mp, Md_addres(4, get_add));
Md_cursor(posOne, return_pos);
Md_addres(2, back);//не міняти двоєчку будуть глюки
}
else{Md_addres(4, back);}
}
break;
}
}
void Md_p_MyProfiles() {
byte Lines[] = {0, 8, 16, 24, 32, 40, 48, 56};
Md_cursor(Lines, sizeof(Lines));
for (int i = 0; i < 7; i++) {
display.setCursor(6, i*8);
display.print(prof(direct_p_mp, i+1)->nameProfiles(get_name_a_f));
}
display.setCursor(6, 56);
display.println("Back" );
}
void Md_gyroscopeSettings(){//a3
int seveData;//використовую щоб було більш зрозуміліше
if (Md_addres(4, get_add) != 5){Md_p_gyroscopeSettings();}
switch (Md_addres(4, int_add_last)) {//4
case no_action:break;
case 1:
seveData = Mf_Magnifier(prof(act_dir)->deadZoneHor, 0, 9999, 100);
prof(act_dir)->setDeZoHor(seveData);
break;
case 2:
seveData = Mf_Magnifier(prof(act_dir)->sensitivityHor, 0, 100, 100);
prof(act_dir)->setSenHor(seveData);
break;
case 3:
seveData = Mf_Magnifier(prof(act_dir)->deadZoneVer, 0, 9999, 100);
prof(act_dir)->setDeZoVer(seveData);
break;
case 4:
seveData = Mf_Magnifier(prof(act_dir)->sensitivityVer, 0, 100, 100);
prof(act_dir)->setSenVer(seveData);
break;
case 5:
Md_cursor(posOne, return_pos);
Md_addres(3, back);
break;
}
}
void Md_p_gyroscopeSettings(){
static uint32_t tmr;
static byte dashFlag;//прапорець м'ягання
if (tmr < millis()) {
tmr = millis() + 500;
dashFlag = ! dashFlag;
}
byte Lines[] = {5, 15, 34, 44, 55};
Md_cursor(Lines, sizeof(Lines));
display.setCursor(8, 5);
display.println("Dead zone ");
display.setCursor(8, 15);
display.println("Sensitivity");
display.setCursor(8, 34);
display.println("Dead zone ");
display.setCursor(8, 44);
display.println("Sensitivity");
display.setCursor(8, 55);
display.println("Back");
display.setCursor(84, 10);
display.println("H");
display.setCursor(84, 39);
display.println("V");
display.setCursor(102, 4);
display.println(prof(act_dir)->deadZoneHor);
display.setCursor(104, 17);
display.println(prof(act_dir)->sensitivityHor);
display.setCursor(102, 33);
display.println(prof(act_dir)->deadZoneVer);
display.setCursor(104, 46);
display.println(prof(act_dir)->sensitivityVer);
display.drawRoundRect(6, 2, 69, 23, 3, WHITE); //РАМКА НАВКОЛО Dead zone Sensitivity H
display.drawRoundRect(6, 31, 69, 23, 0, WHITE);//РАМКА НАВКОЛО Dead zone Sensitivity V
//H
if((Md_cursor(noData, get_pos) == 1 || Md_cursor(noData, get_pos) == 2) && !Md_addres(4, get_add)){// РАМКА НВКОЛО H
if(dashFlag){display.drawRoundRect(79, 6, 15, 15, 0, WHITE);}
}
else{display.drawRoundRect(79, 6, 15, 15, 0, WHITE);}
//V
if((Md_cursor(noData, get_pos) == 3 || Md_cursor(noData, get_pos) == 4) && !Md_addres(4, get_add)){// РАМКА НВКОЛО V
if(dashFlag){display.drawCircle(86, 42, 7, WHITE);}
}
else{display.drawCircle(86, 42, 7, WHITE);}
if(Md_addres(4, get_add) == 1){ // число рамка DZ H
if(dashFlag){display.drawRoundRect(99, 2, 29, 11, 4, WHITE);}
}
else{display.drawRoundRect(99, 2, 29, 11, 4, WHITE);}
if(Md_addres(4, get_add) == 2){ // число рамка S H
if(dashFlag){display.drawRect(101, 15, 23, 11, WHITE);}
}
else{display.drawRect(101, 15, 23, 11, WHITE);}
if(Md_addres(4, get_add) == 3){ // число рамка DZ V
if(dashFlag){display.drawRect(99, 31, 29, 11, WHITE);}
}
else{display.drawRect(99, 31, 29, 11, WHITE);}
if(Md_addres(4, get_add) == 4){ // число рамка S V
if(dashFlag){display.drawRoundRect(101, 44, 23, 11, 4, WHITE);}
}
else{display.drawRoundRect(101, 44, 23, 11, 4, WHITE);}
}
void Md_Buttons() {//замінити if на Switch в кінці при використанні свіч глюки
Md_p_Buttons();
if(Md_addres(no_data, add_status) == address_deleted){//якщо адрес був видалений скидає функцію
Md_p_Buttons(reset);
Md_movingButtons(reset);
}
switch (Md_addres(4, int_add_last)) {
case no_action:
break;
case 1:
Md_movingButtons();
break;
case 2:
switch (MdAf_confirmYesNo(37, 46)) {
case no_action:
break;
case choice_yes:
Md_addres(4, back);
prof(act_dir)->resetButtons();
break;
case choice_no:
Md_addres(4, back);
break;
}
break;
case 3:
Md_cursor(posTwo, return_pos);
Md_addres(3, back);
break;
case address_entered:
Serial.print("address_entered");
if(Md_addres(4, get_add) == 1){
Md_p_Buttons(next_animation);
}
else if(Md_addres(4, get_add) == 2){
Md_addres(no_data, click_reset_off);//потрібно для того щоб Клік працював тепер в функції MdAf_confirmYesNo(37, 46)
}
break;
}
}
int Md_movingButtons(int acceptedCommand){//не закінчено тест кнопки опитуються не повністю
static unsigned long tmr;//таймер для захисту від тремтіння контактів кнопки
static int8_t buttonFlag;//затвор кнопки захист від тремтіння
static int8_t sequenceNumber;//при першому натиску зберігаємо порядковий номер піна-кнопки яка спрацювала
if (acceptedCommand == reset) {
buttonFlag = sequenceNumber = 0;
return 0;
}
else if (!buttonFlag && tmr < millis()) { //кнопка одноразово спрацьовує з захистом
for (int i = 3; i <= 12; i++) {
if (Ae_BatR(prof(act_dir)->buttonArray[i])) {
//Serial.println(i);
tmr = millis()+500;
buttonFlag = 1;
Md_p_Buttons(next_animation, i);
if(!sequenceNumber){//якщо була натиснута перша кнопка зберігаємо порядковий номер
sequenceNumber = i;
}else{//якщо натиснули другу кнопку міняємо місцями елементи масиву-кнопки
int temp = prof(act_dir)->buttonArray[sequenceNumber];// переміщення даних між елементами масиву Напряги мозги і поймеш
prof(act_dir)->buttonArray[sequenceNumber] = prof(act_dir)->buttonArray[i];
prof(act_dir)->buttonArray[i] = temp;
buttonFlag = sequenceNumber = 0;
Md_addres(4, back);
}
break;
}
}
}
else if (buttonFlag && tmr < millis() && digitalRead(prof(act_dir)->buttonArray[sequenceNumber])) {//захист від брязки до першої кнопки захист натиску другої кнопки не потрібен програма завершує роботу
buttonFlag = 0;
}
return 0;
}
void Md_resetButtons(){///масив буде потрібно змінити в кінці
const byte defaultButton[] = {0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
for (int i = 0; i < sizeof(defaultButton); i++) {
prof(act_dir)->buttonArray[i] = defaultButton[i];
}
}
byte Md_p_Buttons(byte receivedData, byte selectedButton){
//бегуща стрілка. анімація. кнопка один збереження. крапка 2 збереження. анімація кнопка ліва. анімація кнопка права
static byte runningArrow, animation, buttonOne, buttonTwo, accumulationL, accumulationR;
static unsigned long tmr; //таймер для виконання анімації
const char *buttonNames[] = {//масив імена кнопок виводим при натиску
" ",
" ",
" ",
"A",
"B",
"X",
"Y",
"LB",
"RB",
"LT",
"RT",
"LA",
"RA",
};
display.drawRect(6, 5, 31, 31, WHITE); // квадрат L
display.drawRect(90, 5, 31, 31, WHITE);// квадрат R
display.drawCircle(21, 16, 8, WHITE);//кружки над кнопками
display.drawCircle(105, 16, 8, WHITE);
display.drawRect(12, 26+accumulationL, 19, 5, WHITE);//ліва кнопка accumulationL збільшення зменшення анімація кнопки
display.fillRect(9, 30, 25, 4, WHITE);
display.drawRect(96, 26+accumulationR, 19, 5, WHITE);//ПРАВА кнопка accumulationR збільшення зменшення анімація кнопки
display.fillRect(93, 30, 25, 4, WHITE);
byte Lines[] = {40, 48, 56};//передаємо координати переміщення функції
Md_cursor(Lines, sizeof(Lines));
display.setCursor(0, 40);//понятно
display.println(" Move buttons");
display.println(" Reset");
display.println(" Back");
if (!receivedData && !animation) {//якщо фаус то закінчуємо роботу функції економія ресурсів
return 0;
}
if (receivedData == reset) {
animation = accumulationL = accumulationR = runningArrow = 0;
}
else if (receivedData == next_animation) {//в коді викликаємо функцію переключаємо анімацію
accumulationL = accumulationR = runningArrow = 0;
if (animation != 3) {
animation++;
}
if (animation == 2) {
buttonOne = selectedButton;
}else if (animation == 3) {
buttonTwo = selectedButton;
tmr = millis()+1000;
}
}
if (animation == 1 && tmr < millis()) { //анімація кнопок за допомогою перемінної
accumulationL++;
if (accumulationL == 4) {
accumulationL = 0;
}
}
else if (animation == 2 && tmr < millis()) {
accumulationR++;
runningArrow++;
if (accumulationR == 4 ) {
accumulationR = 0;
}
if (runningArrow == 8 ) {
runningArrow = 0;
}
}
else if (animation == 3 && tmr < millis()) {//відображення другої кнопки завершення роботи з запізнення
animation = 0;
}
if (animation == 1 ) {
if (accumulationL){//знак запитання мигає якщо кнопка не натиснута
display.setCursor(19, 13);
display.println('?');
}
}
else if (animation == 2 ) {
display.setCursor(22-strlen(buttonNames[buttonOne])*3, 13);//strlen автоцентровка в колі може бути одна або дві букви
display.println(buttonNames[buttonOne]);
if(accumulationR){//знак запитання мигає якщо кнопка не натиснута
display.setCursor(103, 13);
display.println('?');
}
for (int i = 0; i < 8; ++i) {//відображаємо кутові складки
display.setCursor(40+i*6, 13);
display.write(62);
}
display.setCursor(40+runningArrow*6, 13);//трикутник переміщається по углових скобках анімація
display.write(16);
}
else if (animation == 3 ) {//завершення програми відображення натиснутих кнопок
display.setCursor(22-strlen(buttonNames[buttonOne])*3, 13);
display.println(buttonNames[buttonOne]);
display.setCursor(106-strlen(buttonNames[buttonTwo])*3, 13);
display.println(buttonNames[buttonTwo]);
}
if (tmr < millis()) {//всі дії виконуються по таймеру
tmr = millis()+400;
}
return 0;
}
void Md_changeNameProfile(){
static int8_t AxisX, AxisY, storedAction, inputIndicator, axisChange;
static uint32_t tmr;
char letterBig[5][10] = {
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
{'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'},
{'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '-'},
{'!', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '.', '<'},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>'}
};
char letterSmall[5][10] = {
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
{'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'},
{'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-'},
{'!', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '.', '<'},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', '>', '>', '>'}
};
static char (*ptrLetter)[10] = letterSmall;//вказівник вказує в залежності від настройки на великі або малі букви
if (!inputIndicator && ptrLetter == letterSmall && !storedAction) {//якщо видаляється остання буква одноразово всі букви робляться великими
storedAction = 1;
for (int i = 19; i >= 0; i--) {
if (prof(act_dir)->nameProfiles(get_name)[i] != ' '){
inputIndicator = i+1;
break;
}
else if (!i){
ptrLetter = letterBig;
inputIndicator = 0;
break;
}
}
}
else if (inputIndicator && storedAction) {
storedAction = 0;
}
switch (Mf_EncoderButton()) {
case click:
switch (ptrLetter[AxisY][AxisX]) {
case '!': //міняємо величину букв
if (ptrLetter == letterBig) {
ptrLetter = letterSmall;
}
else {
ptrLetter = letterBig;
}
break;
case '>'://вихыд
AxisX = AxisY = inputIndicator = 0;
Md_cursor(posThree, return_pos);
Md_addres(3, back);
break;
case '<': //видаляємо букви
if (inputIndicator ) {
inputIndicator--;
prof(act_dir)->nameProfiles(change_letter, inputIndicator, ' ');
}
break;
default://введення вибраної букви
if (inputIndicator <= 19) {//обмеження на кількість букв
prof(act_dir)->nameProfiles(change_letter, inputIndicator, ptrLetter [AxisY][AxisX]);
if (inputIndicator == 0) {//якщо вводиться перша буква всі букви стають малими одноразовo
ptrLetter = letterSmall;
}
inputIndicator++;
}
}
break;
}
if (!axisChange && Mf_EncoderButton(get_status) == press_b_e && Mf_encoderActionStorage(get_status)) {///проверяем статус кнопки якщо енкодер спрацьовує то міняємо режими роботи курсора
Mf_EncoderButton(reset_status);
axisChange = 1;
}
else if (axisChange && !Mf_EncoderButton(get_status)) {
axisChange = 0;
if (AxisY == 4 ){//переміщаємо курсор для коректної роботи якщо останній масив
if (AxisX <= 7){
AxisX = 0;
}
else{
AxisX = 9;
}
}
}
switch (Mf_encoderActionStorage(get_status)) {
case 0:
break;
case rotated_rights:
if (!axisChange) {AxisX--;}//\переміщення в залежності від режиму
else {AxisY--;}
if (AxisY == 4 && AxisX == 8) {//корекція курсора якщо попали на останній масив костильі)
AxisX = 0;
}
if (AxisX < 0) {
AxisX = 9;
AxisY--;
}
if (AxisY < 0) {AxisY = 4;}
break;
case rotated_left:
if (!axisChange) {AxisX++;}
else {AxisY++;}
if (AxisY == 4 && AxisX == 1) {
AxisX = 9;
}
if (AxisX > 9) {
AxisX = 0;
AxisY++;
}
if (AxisY > 4 ) {AxisY = 0;}
break;
}
Md_p_changeNameProfile(ptrLetter, inputIndicator, AxisX, AxisY);
}
byte Md_p_changeNameProfile(char letter[][10], byte inputIndicator, byte AxisX, byte AxisY){
static char tracking;//використовується для відслідковування позиції рамки
char str[] = {'!', '<', ' ', '>'};//маси використовується для мигання необхідної рамки
static byte flagBlink[5];
static uint32_t tmr, tmrInd;
display.setCursor(6, 44);///набір різних стрілок
if(letter[1][1] == 'W'){//якщо в масиві є великі букви значить стрілочка вниз
display.write(25);//стрілочка вниз малі букви
}
else{display.write(24);}//стрілочка вверх великі букви
display.setCursor(114, 54);//back
display.print('s');
display.drawPixel(120, 60, WHITE); //крапка
if(!flagBlink[0]){//кружок стрілка вниз вверх
display.drawCircle(8, 47, 5, WHITE);
}
if(!flagBlink[1]){// видалення
display.setCursor(114, 43);
display.print('x');
display.drawCircle(116, 47, 4, WHITE);
}
display.fillRect(36, 54, 54, 6, WHITE);//пробіл
if(letter[AxisY][AxisX] == ' '){//додаткова рамка якщо навели на пробіл
display.drawRect(34, 52, 58, 10, WHITE);
}
if(!flagBlink[3]){//рамка s.
display.drawRoundRect(112, 54, 9, 9, 0, WHITE);
}
for (int i = 0; i < 4; i++) {
if(tracking != letter[AxisY][AxisX]){//можливі розрив захист від зникнення рамки
flagBlink[0] = flagBlink[1] = flagBlink[2] = flagBlink[3] = tmr = 0;//якщо було переміщення обнуляємо всі переміни
tracking = letter[AxisY][AxisX];//перезаписуємо перемінно новими даними
}
if(letter[AxisY][AxisX] == str[i]){
if(tmr < millis()){
tmr = millis()+400;
flagBlink[i] = !flagBlink[i];
}
break;
}
else if(i == 3 ){//
display.drawRect(4+AxisX*12, 12+AxisY*10, 9, 11, WHITE);//рамка курса 10 вверх вниз, вліво вправо 12
break;
}
}
if(inputIndicator != 20){//вертикальна риска біля букви мигання
if(tmrInd < millis()){
tmrInd = millis()+400;
flagBlink[4] = !flagBlink[4];
}
}
if(flagBlink[4] || inputIndicator == 20){//перестає мигати якщо 20 символів
display.drawRect(2+6*inputIndicator, 0, 1, 9, WHITE);
}
display.setCursor(2, 1);//виводив ім'я профіля
display.print(prof(act_dir)->nameProfiles(get_name));
for (int i = 0; i < 4; i++) {//виводим масив букв на дисплей
for (int j = 0; j < 10; j++) {
display.setCursor(6+j*12, 14+i*10);
if(letter[i][j] != '!' && letter[i][j] != '<'){//ці знаки не можна виводити використовується для виконання дій
display.print(letter[i][j]);
}
}
}
return 0;
}
//
// Md_Additional functions-------------------------------------------------------------------------------------------
byte MdAf_consenDisplay(){ //викликається для підтвердження вибору
static int8_t flagChoice;
switch (Mf_encoderActionStorage(get_status)) {//керування рамкою вліво вправо
case no_action:
break;
case rotated_rights:
if (flagChoice > -2) {
flagChoice--;
}
break;
case rotated_left:
if (flagChoice < 2) {
flagChoice++;
}
break;
}
if ((flagChoice == -2 || flagChoice == 2) && Mf_EncoderButton() == click) {// V1 якщо відбувся Клік виконується дії в залежності від вибору
if (flagChoice == -2) {//якщо вибрали ні виконуються дії//вихід виконується в любому випадку з збереженими настройками або ні
flagChoice = 0;
return choice_no;
}
else if (flagChoice == 2) {
flagChoice = 0;
return choice_yes;
}
}
MdAf_p_consenDisplay(flagChoice);//візуальна частина коду
return 0;
}
int8_t MdAf_p_consenDisplay(int8_t acceptedFlag){
static uint32_t tmr;
static int8_t FlagFrame;
display.drawRoundRect(20, 8, 87, 22, 0, WHITE); //рамка навколо слова зверху
display.setCursor(25, 15);
display.println("Save settings");
if (tmr < millis()) {// виконує механія рамкою навколо слова так ні
tmr = millis() + 400;
FlagFrame = !FlagFrame;
}
if (FlagFrame) {//виводим рамку навколо слова і мигаємо нею
display.drawRect(52+acceptedFlag*18, 39, 21, 13, WHITE);//переміна приймає число від -2 до +2 І в залежності від числа міняє координати рамки
}
for (int i=39; i <= 75; i+=18){//відображаємо стрілки вліво вправо
display.setCursor(i,42);
display.write(27);display.write(26);
}
display.setCursor(21, 42);
display.println("NO");
display.setCursor(18, 42);
display.println(" YES");
return 0;
}
byte MdAf_profileStorage(byte acceptedCommand) {//функція викликається якщо Md_addres(3, get_add) == 1
switch (acceptedCommand) {//false якщо повертаємо збережені настройки
case return_save:
prof(act_dir)->copyFrom(profilSeve);//це означає що ми вибрали ні і повертаємо настройки
break;
case copy_profile:
profilSeve.copyFrom(*prof(act_dir));//копіювання діючий профіль
break;
case check_changes:
if (profilSeve != *prof(act_dir)) {return recorded_changes;}
break;
case reset://провести спосіб скинути функцію перестане відправляти recorded_changes
profilSeve.copyFrom(*prof(act_dir));
break;
}
return 0;
}
byte MdAf_infoDisplay(byte acceptedCommand) {
static byte flagPermit = 1;
if (acceptedCommand) {
if (acceptedCommand == reset) {
flagPermit = 1;
return 0;
}
else if (acceptedCommand == get_status) {
return flagPermit;
}
}
if (flagPermit || !bleGamepad.isConnected()) {
//if (flagPermit) {
if (flagPermit) {
flagPermit = 0;
}
display.clearDisplay();//не забути доробити періодичне виведення
MdAf_BluetoothPrint();
MdAf_typeNumberPrint();
MdAf_batteryPrint();
display.drawRect(0, 14, 127, 19, WHITE);// РАМКА НАВКОЛО НАЗВИ
display.setCursor(prof(act_dir)->centroName(), 20);// функція centroName() в залежності від кількості ім'я вранці
display.print(prof(act_dir)->nameProfiles(get_name));
display.setCursor(44,44);
display.write(26);
display.drawRect(50, 42, 27, 11, WHITE);
display.setCursor(52,44);
display.print("Menu");
display.display();
}
return 0;
}
void MdAf_BluetoothPrint() {
static uint32_t tmr;
static byte Flag;
display.drawCircle(6, 6, 6, WHITE);//кружок
display.setCursor(4, 3);
if (bluetoothSimulation) {
display.print("b");
}
else{
if (tmr < millis()) {
Flag = !Flag;
tmr = millis() + 1000;
}
if (Flag) {
display.print("b");
}
}
}
void MdAf_batteryPrint() {
display.setCursor(17 * 6, 0);
display.print("123");
}
void MdAf_typeNumberPrint() {
display.setCursor(49, 0);
if (prof(act_dir)->tape == t_sp) {
display.print("(Sp");
display.print(prof(act_dir)->namber);
}
else {
display.print("(Mp");
display.print(prof(act_dir)->namber);
}
display.print(")");
}
byte MdAf_confirmYesNo(byte azixX, byte azixY){
//функцію можна відобразити в любому місці біля слова рецепт після завершення потрібно скинути вручну
static byte flagChoice;
if (Mf_encoderActionStorage(get_status)) {
flagChoice = !flagChoice;
}
if (Mf_EncoderButton() == click) {
byte temp = flagChoice;
flagChoice = 0;
if (!temp) {
Serial.print("yes");
return choice_no;
}else{
return choice_yes;
}
}
display.setCursor(azixX+4, azixY+4);
display.println("NO YES");
if(!flagChoice) {
display.drawRect(azixX+2, azixY+2, 15, 11, WHITE);//NO
}else{
display.drawRect(azixX+32, azixY+2, 21, 11, WHITE);//YES
}
display.drawRect(37, 46, 55, 15, WHITE);//рамка навколо так ні
//MdAf_p_confirmYesNo(flagChoice, 37, 46);
return 0;
}
// Md_Af
//Md
//Display 4
byte Md_Display(byte Receiving) {
static byte Regime = info_display;
//static byte Regime = menu;
if (Receiving) {
Regime = Receiving;
}
switch (Regime) {
case info_display:
if (Mf_EncoderButton() == click) {
MdAf_infoDisplay(reset);
Md_Display(menu);
}
else{
MdAf_infoDisplay();
}
break;
case menu:
Md_MainDisplay();
break;
}
return 0;
}
//D
//Menu_functions 5
byte Md_cursor(byte* arr, byte dataCommand) {
static int8_t permissionArrow, Point = 1, workPermit = 1;
switch (dataCommand) {
case return_pos:
Point = arr[0];
permissionArrow = 0;
break;
case cursor_type_two:
permissionArrow = 1;
break;
case cursor_type_one:
permissionArrow = 0;
break;
case get_pos:
return Point;
break;
default:
if(!permissionArrow){
switch (Mf_encoderActionStorage(get_status)) {
case no_action:
break;
case rotated_left:
Point--;
if (Point == 0) {Point = dataCommand;}
break;
case rotated_rights:
Point++;
if (dataCommand < Point) {Point = 1;}
break;
}
}
if (!permissionArrow) {
display.setCursor(0, arr[Point-1]); //21,8 максимум символів
display.write(26);
}
else if (permissionArrow) {
display.setCursor(0, arr[Point-1]); //21,8 максимум символів
display.write(16);
}
}
return 0;
}
int8_t Md_addres(int8_t addNumb, int8_t acceptedCommand) {
static byte adr[19], modeSwitch = 1, namb = 1, workPermit = 1, del;
switch (acceptedCommand) {
case back:
Serial.print("case back:");
Md_cursor(noData, cursor_type_one);
workPermit = modeSwitch = 1;
for (int i=18; i >= 1; i--){//команда back виконує видалення всіх адресів до числа вказаного в addNumb
adr[i] = 0;
if (i == addNumb) {
namb = addNumb;
break;
}
}
break;
case get_add:
return adr[addNumb];
break;
case add_status:
if (del){
del = 0;
return address_deleted;
}
break;
case click_reset_off:
workPermit = 0;
break;
case int_add:
if (!adr[addNumb] && Mf_EncoderButton() == click){//набір адреса
adr[namb] = Md_cursor(noData, get_pos);//позиція курс означає набраний адрес
namb++;
return address_entered;
}
break;
case int_add_last:
if (workPermit && Mf_EncoderButton() == click){//набір адреса
if (modeSwitch){
adr[namb] = Md_cursor(noData, get_pos);//позиція курс означає набраний адрес
Md_cursor(noData, cursor_type_two);//міняємо вид курсора
modeSwitch = 0;//міняємо флажок наступний кліп буде означати скидання адресу
return address_entered;
}
else if (!modeSwitch){
adr[namb] = 0;
del = modeSwitch = 1;
Md_cursor(noData, cursor_type_one);//міняємо вид курсора
}
}
break;
}
return adr[addNumb];
}
int8_t Mf_encoderActionStorage(int8_t acceptedCommand) {
static int8_t operationRetention;//збереження спрацювання
if (acceptedCommand == rotated_left || acceptedCommand == rotated_rights) {
Ae_autoShutdown(reset);
operationRetention = acceptedCommand;
}
else if (acceptedCommand == get_status) {
acceptedCommand = operationRetention;
operationRetention = 0;
return acceptedCommand;
}
return 0;
}
byte Mf_EncoderButton(byte acceptedCommand) {
static byte buttonState;
static uint32_t tmr;
if (acceptedCommand == reset){//в Kodi можемо зробити reset щоб не поверталося утримання hold_b_e або click
buttonState = reset_status;
}
else if (acceptedCommand == get_status){ //викликаємо стан кнопки
return buttonState;
}
if (Ae_BatR(b_sw) && buttonState != reset_status){//дія в залежності від того що нам потрібно в основному Коді
if (!buttonState) {
Ae_autoShutdown(reset);
buttonState = press_b_e;
tmr = millis() + 500;
return press_b_e;
}
else if (tmr < millis()) {
buttonState = hold_b_e;
tmr = 0;
return hold_b_e;
}
}
else if (buttonState && !Ae_BatR(b_sw)){//якщо в основному Коді не скидали функцію то повернеться Клік
byte temp = buttonState;
buttonState = 0;
if (temp == press_b_e) {
return click;
}
}
return 0;
}
int Mf_Magnifier(int Numeric, int Min, int Max, int Speed) {
static uint32_t tmr;
static int counter = 1;
switch (Mf_encoderActionStorage(get_status)) {
case rotated_rights:
tmr = millis()+500;
Numeric += counter;
if (Speed > counter) {
counter++;
}
break;
case rotated_left:
tmr = millis()+500;
Numeric += -counter;
if (Speed > counter) {
counter++;
}
break;
}
if (counter != 1 && tmr < millis()) {
tmr = millis()+counter/2;
counter--;
}
if (Numeric > Max) {
Numeric = Min;
} else if (Numeric < Min) {
Numeric = Max;
}
return Numeric;
}
//Mf
//Gamepad_function 6
void Gf_GiroAnalogR() {
static uint32_t tmr;
static int GiroDedZone;
static int rightStickX;
static int rightStickY;
static int x; //x
static int z; //z
/*
Quaternion q;
VectorFloat gravity;
VectorInt16 gyro;
static float ypr[3];
*/
if (Ae_BatR(b_handle) && tmr < millis()) {
Ae_autoShutdown(reset);
/*
if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) {
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGyro(&gyro, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
tmr = millis() + 11;
}
*/
if (abs(x) > 1) {
GiroDedZone = map(z, -150, 150, -30, 30);
GiroDedZone = abs(GiroDedZone);
if (x < -GiroDedZone) {
x = map(x, -1, -prof(act_dir)->sensitivityHor, -prof(act_dir)->deadZoneHor, -32767);
x = constrain(x, -32767, -1);
bleGamepad.setZ(x);
}
else if (x > GiroDedZone) {
x = map(x, 1, prof(act_dir)->sensitivityHor, prof(act_dir)->deadZoneHor, 32767);
x = constrain(x, 1, 32767);
bleGamepad.setZ(x);
}
}
else{
bleGamepad.setZ(0);
}
if (abs(z) > 1) {
GiroDedZone = map(x, -150, 150, -30, 30);
GiroDedZone = abs(GiroDedZone);
if (z < -GiroDedZone) {
z = map(z, -1, -prof(act_dir)->sensitivityHor, prof(act_dir)->deadZoneHor, 32767);
z = constrain(z, -32767, -1);
bleGamepad.setRZ(z);
}
else if (z > GiroDedZone) {
z = map(z, 1, prof(act_dir)->sensitivityHor, -prof(act_dir)->deadZoneHor, -32767);
z = constrain(z, 1, 32767);
bleGamepad.setRZ(z);
}
}
else{
bleGamepad.setRZ(0);
}
}
else if (rightStickX || rightStickY){
rightStickX = rightStickY = 0;
bleGamepad.setRightThumb(0, 0);
}
}
void Gf_AnLeftDpad(){
static bool flag;
int AxisX = constrain(analogRead(39), 45, 4050);
int AxisY = constrain(analogRead(36), 45, 4050);
if ((AxisX < 1800 || AxisX > 2200) || (AxisY < 1800 || AxisY > 2200)) {
if (!Ae_BatR(b_emul_dpad)) {
if (flag) {
flag = 0;
bleGamepad.setHat1(HAT_CENTERED);
}
AxisX = map(AxisX, 45, 4050, -32767, 32767);
AxisY = map(AxisY, 45, 4050, -32767, 32767);
bleGamepad.setLeftThumb(AxisX, AxisY);
}
else{
if (!flag) {
flag = 1;
bleGamepad.setLeftThumb(0, 0);
}
if (AxisX < 1800 || AxisX > 2200) {
AxisX = constrain(AxisX, 1800, 2200);
AxisX = map(AxisX, 1800, 2200, 2, 4);
}
else{
AxisX = 0;
}
if (AxisY < 1800 || AxisY > 2200) {
AxisY = constrain(AxisY, 1800, 2200);
AxisY = map(AxisY, 1800, 2200, 1, 6);
}
else{
AxisY = 0;
}
const byte dpadArr[] = {0, 1, 3, 2, 7, 8, 5, 0, 4, 0, 6};
bleGamepad.setHat1(dpadArr[AxisX+AxisY]);
}
}
else{
bleGamepad.setLeftThumb(0, 0);
bleGamepad.setHat1(0);
}
}
void Gf_gamepadButtons(){
if (Ae_BatR(prof(act_dir)->buttonArray[1])) {
bleGamepad.pressSelect();
}
else{
bleGamepad.releaseSelect();
}
if (Ae_BatR(prof(act_dir)->buttonArray[2])) {
bleGamepad.pressStart();
}
else{
bleGamepad.releaseStart();
}
if (Ae_BatR(prof(act_dir)->buttonArray[11])) {
bleGamepad.setLeftTrigger(32767);
}
else{
bleGamepad.setLeftTrigger(0);
}
if (Ae_BatR(prof(act_dir)->buttonArray[12])) {
bleGamepad.setRightTrigger(32767);
}
else{
bleGamepad.setRightTrigger(0);
}
for (int i = 3; i <= 12; i++) {
if (Ae_BatR(prof(act_dir)->buttonArray[i])) {
bleGamepad.press(i);
}
else{
bleGamepad.release(i);
}
}
}
//Gf
void setup() {
Serial.begin(9600);// В ФЫНАЛЫ НЕЗАБУТИ ЗАКОМЕНТУВАТИ!!!
bleGamepad.begin();
EEPROM.begin(512);
prof(eeprom_initialization);//ініціалізація з енергонезалежної пам'яті профілів
byte pinsWithPullup[] = {33, 14, 27, 26, 25, 16, 17, 5, 23, 2, 18, 19, 32, 15, 13, 4};//добавити 1
for (int i = 0; i < sizeof(pinsWithPullup); i++) {
pinMode(pinsWithPullup[i], INPUT_PULLUP);
}
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
pinMode(3, OUTPUT);//подаємо живлення на датчики
digitalWrite(3, HIGH);
//Ae_InterruptReadPinDtEncoder() зчитування енкодера по пририванню
attachInterrupt(digitalPinToInterrupt(p_dt), Ae_InterruptReadPinDtEncoder, CHANGE);
//----------Display--------------
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextSize(1);
display.setTextColor(WHITE);
}
void loop() {
Ae_autoShutdown();
Ae_buttonOnOff();
//Ae_batteryCheck
Md_Display();
if (bleGamepad.isConnected()) {
Gf_GiroAnalogR();
Gf_AnLeftDpad();
Gf_gamepadButtons();
bleGamepad.sendReport();
}
} //void loop()