#include <LiquidCrystal.h>
class Matrixbutton {
public:
Matrixbutton(byte* setPinX, byte setCountX, byte* setPinY, byte setCountY){
_x=setCountX;
_y=setCountY;
pin_x=setPinX;
pin_y=setPinY;
byte nnr=_x*_y;
boolean *current_state0 = new boolean [nnr]; //высвобождаем место в памяти под массивы нужной длины
current_state=current_state0; //ссылку на освобождённое место передаём в private, для
boolean *last_state0 = new boolean [nnr]; //организации доступа к данной области памяти из других функций класса
last_state=last_state0;
boolean *event_up0 = new boolean [nnr];
event_up=event_up0;
boolean *event_down0 = new boolean [nnr];
event_down=event_down0;
boolean *event_fastclick0 = new boolean [nnr];
event_fastclick=event_fastclick0;
boolean *event_longclick0 = new boolean [nnr];
event_longclick=event_longclick0;
unsigned long *eventdown_start0 = new unsigned long [nnr];
eventdown_start=eventdown_start0;
}
void read(){
for (byte xm=0;xm<_x;xm++){ // перебираем столбики
digitalWrite(pin_x[xm],1);
delay(20); //Физика, при длинных проводах обязательно делать небольшую задержку
for (byte ym=0;ym<_y;ym++){ //Читаем строчки
current_state[xm*_x+ym]=digitalRead(pin_y[ym]);
if (last_state[xm*_x+ym]==0 && current_state[xm*_x+ym]==1){ //Если предыдущее 0, а новое 1, значит клавиша нажата
event_down[xm*_x+ym]=1;
eventdown_start[xm*_x+ym]=millis(); //Стартуем таймер, дабы отследить длительность нажатия кнопки
}
if (eventdown_start[xm*_x+ym]!=0){ //Если клавиша долго нажата то перестаём пытаться регистрировать события быстрого и долгого клика
if ((millis()-eventdown_start[xm*_x+ym])>= 5000){
eventdown_start[xm*_x+ym]=0;
}
}
if (last_state[xm*_x+ym]==1 && current_state[xm*_x+ym]==0){ //Если предыдущая 1, а новое 0, значит клавиша отпущена
event_up[xm*_x+ym]=1; //Регистрируем события отпускания клавиши, но ещё необходимо проверить события быстрого или долгого клика
if (eventdown_start[xm*_x+ym]!=0){
if ((millis()-eventdown_start[xm*_x+ym]) < 1100) { // Если клик меньше 1.1 сек, то будем считать это быстрым кликом, если от 1.1 до 5 сек, то долгий
event_fastclick[xm*_x+ym]=1;
eventdown_start[xm*_x+ym]=0;
} else {
event_longclick[xm*_x+ym]=1;
eventdown_start[xm*_x+ym]=0;
}
}
}
last_state[xm*_x+ym]=current_state[xm*_x+ym];
}
digitalWrite(pin_x[xm],0); //реверс
}
}
void init(){
for (byte i=0; i<_x;i++){ //Инициализируем пины
pinMode(pin_x[i],OUTPUT);
digitalWrite(pin_x[i],0); //На тот случай, если делать puulup
}
for (byte i=0; i<_y;i++){
pinMode(pin_y[i],INPUT); //Не забываем подтянуть строки к земле через резисторы, иначе будет весело, можно правда сделать puulup, но придётся немного программу изменить
}
for (byte xm=0;xm<(_x*_y);xm++){ //Обнуляем матрицы состояний и таймеров
current_state[xm]=0;
last_state[xm]=0;
event_up[xm]=0;
event_down[xm]=0;
event_fastclick[xm]=0;
event_longclick[xm]=0;
eventdown_start[xm]=0;
}
}
boolean clickUp(byte button){ //Просто события, после считывания события - сбрасываем событие
if (event_up[button] == 1){
event_up[button] =0;
return true;
} else {
return false;
}
}
boolean clickDown(byte button){
if (event_down[button] == 1){
event_down[button] =0;
return true;
} else {
return false;
}
}
boolean fastclick(byte button){
if (event_fastclick[button] == 1){
event_fastclick[button] =0;
return true;
} else {
return false;
}
}
boolean longclick(byte button){
if (event_longclick[button] == 1){
event_longclick[button] =0;
return true;
} else {
return false;
}
}
private:
byte _x; //Количество столбиков
byte _y; //Количество строк
byte* pin_x; //Пины столбиков (Выходы)
byte* pin_y; //Пины строк (Входы)
boolean* current_state;
boolean* last_state;
boolean* event_up;
boolean* event_down;
boolean* event_fastclick;
boolean* event_longclick;
unsigned long* eventdown_start;
};
byte pinx_Str[]={37,39,41,43,45,47,49,51,53};
byte piny_Cool[]={36,38,40,42,44,46,48,50,52};
Matrixbutton knop(pinx_Str,9,piny_Cool,9);
LiquidCrystal lcd(12,11,5,4,3,2);
String str,str1,str2;
bool fl_cur,LightLcd;
unsigned long LcdTimeStart;
void setup() {
lcd.begin(16, 2);
fl_cur=false;
pinMode(8,OUTPUT); //Управление подсветкой LCD
lcd.noDisplay();
pinMode (13,OUTPUT);
knop.init();
Serial.begin(9600); // отладка
}
void loop() {
knop.read(); //Читаем кнопки
byte f=0;
while (f<=80){ //Если была нажата любая кнопка, то условие в цикле сработает
if (knop.clickUp(f)) {
str=str+"Up="+String(f)+" ";
fl_cur=true;
}
if (knop.longclick(f)){
str=str+"LongClick="+String(f)+" ";
fl_cur=true;
}
if (knop.fastclick(f)){
str=str+"FastClick="+String(f)+" ";
fl_cur=true;
}
if (knop.clickDown(f)){
str=str+"DOWN="+String(f)+" ";
fl_cur=true;
}
f++;
}
if (LightLcd){
if ((millis()-LcdTimeStart)>15000){ //Тушим подсветку при простое более 15 сек
lcd.noDisplay();
digitalWrite(8,LOW);
LightLcd=false;
}
}
if (fl_cur){ //Если были события с кнопок, кидаем их на экран
Serial.println(str);
digitalWrite(8,HIGH);
lcd.display();
LcdTimeStart=millis();
LightLcd=true;
lcd.clear();
str1=str2;
str2=str;
lcd.setCursor(0,0);
lcd.print(str1);
lcd.setCursor(0,1);
lcd.print(str2);
fl_cur=false;
str="";
}
}