Тема: M62429 + OLED 128x32
// энкодер
#define ENC_DT 9
#define ENC_CLK 8
#define ENC_SW 10
// ИК датчик
#define IR 5
// кнопки управления
#define POWER_BUTTON 3
#define MUTE_BUTTON 4
// выход управления standby
#define STANDBY_OUT 13
// M62429
#define CLK 11
#define DATA 12
// коды кнопок ИК пульта
#define MENU 0x2FDB24D // button encoder
#define UP 0x2FDD02F // >>>
#define DW 0x2FD32CD // <<<
#define POWER_IR 0x2FD00FF // POWER
#define MUTE_IR 0x2FDB04F // MUTE
#include <Wire.h>
#include <U8glib.h> // https://github.com/olikraus/u8glib/
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <EEPROM.h>
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <boarddefs.h> // входит в состав библиотеки IRremote
#include <IRremote.h> // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.zip
#include <M62429.h> // http://rcl-radio.ru/wp-content/uploads/2026/01/M62429.zip
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // I2C / TWI
IRrecv irrecv(IR);
Encoder myEnc(ENC_DT, ENC_CLK);
decode_results ir;
extern uint8_t SmallFont[],BigNumbers[];
long times,oldPosition = -999,newPosition;
int vol,balans,bass,treb,in,menu;
bool mute=0,gr1,gr2,w,w1,power=0;
void setup(){
Wire.begin();
irrecv.enableIRIn();
Serial.begin(9600);
MsTimer2::set(3, to_Timer);MsTimer2::start();
if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
pinMode(POWER_BUTTON,INPUT_PULLUP);
pinMode(MUTE_BUTTON,INPUT_PULLUP);
pinMode(STANDBY_OUT,OUTPUT);
u8g.firstPage(); do {
u8g.setFont(u8g_font_profont29r);u8g.drawStr(5,25,"M62429");
}while( u8g.nextPage() );
delay(3000);
digitalWrite(STANDBY_OUT,LOW);
vol = EEPROM.read(0);balans = EEPROM.read(3)-8;
audio();
}
void loop(){
// IR ////////////////////////////////////////
if ( irrecv.decode( &ir )) {Serial.print("0x");Serial.println( ir.value,HEX);irrecv.resume();times=millis();w=1;}// IR приемник - чтение, в мониторе порта отображаются коды кнопок
if(ir.value==0){gr1=0;gr2=0;}// запрет нажатий не активных кнопок пульта
if(power==0){
if(digitalRead(ENC_SW)==LOW || ir.value==MENU){menu++;cl();delay(200);times=millis();w1=1;w=1;if(menu>1){menu=0;}} // меню
if((digitalRead(MUTE_BUTTON)==LOW || ir.value==MUTE_IR)&& mute==0){mute=1;cl();times=millis();w1=1;w=1;mute_conf();
u8g.firstPage(); do {u8g.setFont(u8g_font_profont29r);u8g.drawStr(25,25,"MUTE");}while( u8g.nextPage() );delay(300);menu=100;} // mute on
if((digitalRead(MUTE_BUTTON)==LOW || ir.value==MUTE_IR)&& mute==1){mute=0;cl();times=millis();w1=1;w=1;audio();
delay(300);menu=0;} // mute off
}
if((digitalRead(POWER_BUTTON)==LOW || ir.value==POWER_IR)&& power==0){power=1;cl();times=millis();w1=1;w=1;mute_conf();digitalWrite(STANDBY_OUT,HIGH);
u8g.firstPage(); do {u8g.setFont(u8g_font_profont29r);u8g.drawStr(10,25,"STANDBY");}while( u8g.nextPage() );delay(2000);menu=100;
u8g.firstPage(); do {}while( u8g.nextPage() );} // power on
if((digitalRead(POWER_BUTTON)==LOW || ir.value==POWER_IR)&& power==1){power=0;cl();times=millis();w1=1;w=1;audio();digitalWrite(STANDBY_OUT,LOW);delay(300);menu=0;} // power off
//////// VOLUME //////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(menu==0){
if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
vol=vol+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;vol_func();audio();}
if(ir.value==UP){vol++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка >
if(ir.value==0xFFFFFFFF and gr1==1){vol++;gr2=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка >>>>>>
if(ir.value==DW){vol--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка <
if(ir.value==0xFFFFFFFF and gr2==1){vol--;gr1=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка <<<<<<
if(w==1){w=0;
// Serial.println(63-vol+balans);
u8g.firstPage();
do {
u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"VOLUME");
u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(95, 24);u8g.print(vol-8);
for(int v_pos=0; v_pos<(75-8)*1.3;v_pos+=4){u8g.drawBox(v_pos+0,16, 2, 1);}
for(int v_pos=0; v_pos<(vol-8)*1.3;v_pos+=4){u8g.drawBox(v_pos+0,18, 2, 9);}
for(int v_pos=0; v_pos<(75-8)*1.3;v_pos+=4){u8g.drawBox(v_pos+0,28, 2, 1);}
} while( u8g.nextPage() );
}}
///////// BALL /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(menu==1){
if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
balans=balans+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;ball_func();audio();}
if(ir.value==UP){balans++;gr1=1;gr2=0;ir.value=0;times=millis();w=1;w1=1;ball_func();audio();}// кнопка >
if(ir.value==DW){balans--;gr1=0;gr2=1;ir.value=0;times=millis();w=1;w1=1;ball_func();audio();}// кнопка <
if(w==1){w=0;
// Serial.println(83-vol+balans);
// Serial.println(83-vol-balans);
u8g.firstPage();
do {
u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"BALANCE");
u8g.setFont(u8g_font_profont29r);
if(balans>=0){u8g.setPrintPos(112, 24);u8g.print(balans);u8g.drawStr(95,24,"+");}
else{u8g.setPrintPos(95, 24);u8g.print(balans);}
for(int v_pos=0; v_pos<(12-1)*8;v_pos+=4){u8g.drawBox(v_pos+0,16, 2, 1);}
const int SCREEN_WIDTH = 84;
u8g.drawBox(43,18, 1, 9);// 0 dB
if(balans >= 0){for(int v_pos=0; v_pos<(balans*4);v_pos+=4){u8g.drawBox(v_pos+48,18, 2, 9);}}
else{for(int v_pos=SCREEN_WIDTH-48; v_pos>(SCREEN_WIDTH-(abs(balans)*4)-48); v_pos-=4){u8g.drawBox(v_pos,18, 2, 9);}}
for(int v_pos=0; v_pos<(12-1)*8;v_pos+=4){u8g.drawBox(v_pos+0,28, 2, 1);}
} while( u8g.nextPage() );
}}
////////////// EEPROM /////////////////////////////////////////////////////////////////////
if(millis()-times>5000 && w1==1 && power==0 && mute==0){
EEPROM.update(0,vol);EEPROM.update(3,balans+8);
menu=0;w1=0;w=1;myEnc.write(0);}
}
void to_Timer(){newPosition = myEnc.read()/4;}
void audio(){
setVolume (CLK,DATA,0,0,83-vol+balans);
setVolume (CLK,DATA,0,1,83-vol-balans);
/* pin CLK
pin DATA
0 - по одному каналу, 1 - оба вместе
0 ПК 1 ЛК
83 ... 0 громкость 83 = -83 дБ */
}
void mute_conf(){
setVolume (CLK,DATA,0,0,84);
setVolume (CLK,DATA,0,1,84);
}
void vol_func(){if(vol>75){vol=75;}if(vol<=8){vol=8;}} // int 0 ... int 79
void ball_func(){if(balans>8){balans=8;}if(balans<=-8){balans=-8;}}
void cl(){ir.value=0;delay(200);}