#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
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 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_triger 33
#define b_analog 32
#define b_on_off 14
#define b_emul_dpad 26
#define b_sw 4
#define p_dt 3
#define p_clk 2
#define thandle_touch_button 27
//Mf_EncoderButton();
//#define click 13
#define press 20
#define hol_but 21
#define released 22
#define released_const 23
#define press_const 24
#define hol_const 25
#define hol_released 26
#define status_button 27
//Md_Display(byte Receiving) {
#define reminder_display_on 20
#define info_display_on 21
#define menu_on 22
#define finishing_work 23
#define finishing_work_reset 24
#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 23
#define address_entered 24
#define delete_last 27
#define get_add 29
#define int_add 30 //introduction введення
#define int_last 31 //introduction введення
#define previous_address 32
#define backpoint 33
#define deselect 34
//int Md_cursor();
//#define reset 11
#define selection_inversion 21
#define freeze_position 22
#define get_pos 23
#define return_pos 24
//Ae_InterruptReadPinDtEncoder()
//Mf_Encoder();
#define rotated_rights 20
#define rotated_left 21
//Mf_consenDisplay()
//#define gyro 15
//#define profil 16
#define click_mod 21
#define hold_mod 22
//Mf_changeInspector();
//#define gyro 15
//#define profil 16
#define copy_profile 21
#define gyro_check 22
#define return_save 23
#define doesnt_match 24//не збігається
#define data_match 25//збіг даних
#define profilSp 26
#define profilMp 27
#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);
//char ProfileName(char Letter);
//char LetterSelect();
void setup() {
pinMode(b_sw, INPUT_PULLUP);
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
attachInterrupt(digitalPinToInterrupt(p_dt), Ae_InterruptReadPinDtEncoder, CHANGE);
}
void loop() {
display.clearDisplay();
Name(); //принимаєм получ бук
display.display();
}
//String NameTest = "Y fddfgdf ";
String NameTest = " ";
void Name(){
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 = 20; i >= 0; i--) {
if (NameTest[i] != ' '){
inputIndicator = i+1;
break;
}
else if (!i){
ptrLetter = letterBig;
inputIndicator = 0;
break;
}
}
}
else if (inputIndicator && storedAction) {
storedAction = 0;
}
switch (Mf_EncoderButton(200)) {
case click:
switch (ptrLetter[AxisY][AxisX]) {
case '!': //міняємо величину букв
if (ptrLetter == letterBig) {
ptrLetter = letterSmall;
}
else {ptrLetter = letterBig;}
break;
case '>'://вихыд
break;
case '<': //видаляємо букви
if (inputIndicator ) {
inputIndicator--;
NameTest[inputIndicator] = ' ';
}
break;
default://введення вибраної букви
if (inputIndicator <= 19) {
NameTest[inputIndicator] = ptrLetter [AxisY][AxisX];
if (inputIndicator == 0) {
ptrLetter = letterSmall;
}
inputIndicator++;
}
}
break;
case hol_const://якщо кнопка зажата курсор переміщається по вертикалі
if (!axisChange) {
axisChange = !axisChange;
}
break;
case hol_released://повертаємо звичайний режим роботи
if (axisChange) {
axisChange = !axisChange;
}
if (AxisY == 4 ){//переміщаємо курсор для коректної роботи якщо останній масив
if (AxisX <= 7){
AxisX = 0;
}
else{AxisX = 9;}
}
break;
}
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;
}
NamePrint(ptrLetter, inputIndicator, AxisX, AxisY);
}
byte NamePrint(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]){display.drawRoundRect(112, 54, 9, 9, 0, WHITE);}//рамка s.
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(NameTest);
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;
}
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;
}
int8_t Mf_encoderActionStorage(int8_t acceptedCommand) {
static int8_t operationRetention;//збереження спрацювання
if (acceptedCommand == rotated_left || acceptedCommand == rotated_rights) {
operationRetention = acceptedCommand;
}
else if (acceptedCommand == get_status ) {
acceptedCommand = operationRetention;
operationRetention = 0;
return acceptedCommand;
}
return 0;
}
int Mf_EncoderButton(int retentionAfter) {
static byte buttonState = released_const;
static uint32_t tmr;
if (Ae_BatR(b_sw)){
if (buttonState == released_const) {
buttonState = press_const;
tmr = millis() + retentionAfter;
return press;
}
else if (tmr && tmr < millis()) {
buttonState = hol_const;
tmr = 0;
return hol_but;
}
}
else if (!Ae_BatR(b_sw)){
if (buttonState == hol_const) {buttonState = released_const; return hol_released;}
else if (buttonState == press_const) {buttonState = released_const; return click;}
}
return buttonState;
}
byte Ae_BatR(byte Taking) {
return !digitalRead(Taking);
}