/*
*
* with rotary encoder
* Big LCD Volume
* IR remote
*
*/
#include <Wire.h>
// #include <IRremote.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);//(Add, Total Col, Total Row)
TDA8425 audioChip;
#define IR_RECEIVE_PIN 7
#define muteBT 20
#define volUp 18
#define volDown 19
#define menuBT 58
#define powerBT 21
//Big Numbers Character
byte custom_num[8][8] = {
{ B00111, B01111, B11111, B11111, B11111, B11111, B11111, B11111 },
{ B11111, B11111, B11111, B00000, B00000, B00000, B00000, B00000 },
{ B11100, B11110, B11111, B11111, B11111, B11111, B11111, B11111 },
{ B11111, B11111, B11111, B11111, B11111, B11111, B01111, B00111 },
{ B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111 },
{ B11111, B11111, B11111, B11111, B11111, B11111, B11110, B11100 },
{ B11111, B11111, B11111, B00000, B00000, B00000, B11111, B11111 },
{ B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }
};
const int digit_width = 3;
const char custom_num_top[10][digit_width] = { 0, 1, 2, 1, 2, 32, 6, 6, 2, 6, 6, 2, 3, 4, 7, 7, 6, 6, 0, 6, 6, 1, 1, 2, 0, 6, 2, 0, 6, 2};
const char custom_num_bot[10][digit_width] = { 3, 4, 5, 4, 7, 4, 7, 4, 4, 4, 4, 5, 32, 32, 7, 4, 4, 5, 3, 4, 5, 32, 32, 7, 3, 4, 5, 4, 4, 5};
//Bar Character
byte a1[8]={0b00000,0b11011,0b11011,0b11011,0b11011,0b11011,0b11011,0b00000};
byte a2[8]={0b00000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b00000};
//Mute Character
byte mute1[] = {
B00000,
B00000,
B00000,
B00000,
B00000,
B00111,
B00111,
B00111
};
byte mute2[] = {
B00111,
B00111,
B00111,
B00000,
B00000,
B00000,
B00000,
B00000
};
byte mute3[] = {
B00000,
B00011,
B00011,
B01111,
B11111,
B11111,
B11111,
B11111
};
byte mute4[] = {
B11111,
B11111,
B11111,
B11111,
B01111,
B00011,
B00011,
B00000
};
byte mutex1[] = {
B00000,
B00000,
B00000,
B00000,
B01000,
B00100,
B00010,
B00001
};
byte mutex2[] = {
B10000,
B01000,
B00100,
B00010,
B00000,
B00000,
B00000,
B00000
};
byte mutex3[] = {
B00000,
B00000,
B00000,
B00000,
B00010,
B00100,
B01000,
B10000
};
byte mutex4[] = {
B00001,
B00010,
B00100,
B01000,
B00000,
B00000,
B00000,
B00000
};
// tactileSwitch High Active with pulldown resistor
enum PinAssignments {
dtPinA = 2, // DT
clkPinB = 3, // CLK
menuSwitch = 4, // SW
muteButton = 5, // Tactile Switch1
powerButton = 6 // Tactile Switch 2
};
int a,b,c,w,z,menu_active,menu,save_eeprom,bass_d,treb,treb_d,balans;
byte x,vol,bass,in,mute=0;
unsigned long time;
static boolean rotating=false; // debounce management
// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;
void setup(){
Serial.begin(9600);
lcd.begin();
IrReceiver.begin(IR_RECEIVE_PIN);
pinMode(muteButton,INPUT);// Mute
pinMode(powerButton,INPUT);// Power
pinMode(dtPinA, INPUT_PULLUP);
pinMode(clkPinB, INPUT_PULLUP);
pinMode(menuSwitch, INPUT_PULLUP); // Menu
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
eepromRead();
audio();
lcd.setCursor(0, 1);
lcd.print(" ..POWER ON.. ");
delay(3000);
lcd.clear();
power_up();
}
void loop()
{
powerSwitch();
rotaryE();
remoteIr();
if(x==1)
{
if(digitalRead(muteButton)==HIGH)
{
mute++;
delay(300);
time=millis();
if(mute>1)
{
mute=0;
}
if(mute == 1) {
menu_active=1;
lcd.clear();
delay(300);
lcd.setCursor(0, 1);
lcd.print("MUTE ");
lcd.createChar(0, mute1);
lcd.createChar(1, mute2);
lcd.createChar(2, mute3);
lcd.createChar(3, mute4);
lcd.createChar(4, mutex1);
lcd.createChar(5, mutex2);
lcd.createChar(6, mutex3);
lcd.createChar(7, mutex4);
lcd.setCursor(12, 0);
lcd.write(0);
lcd.setCursor(12, 1);
lcd.write(1);
lcd.setCursor(13, 0);
lcd.write(2);
lcd.setCursor(13, 1);
lcd.write(3);
lcd.setCursor(14, 0);
lcd.write(4);
lcd.setCursor(15, 1);
lcd.write(5);
lcd.setCursor(15, 0);
lcd.write(6);
lcd.setCursor(14, 1);
lcd.write(7);
menu = 99 ;
}
if (mute == 0 && menu_active==1) {
vol = EEPROM.read(0);
lcd.clear();
menu_active=0;
menu = 0 ;
}
audio();
}
}
if(millis()-time>10000 && save_eeprom==1)
{
eepromUpdate();
menu=0;
save_eeprom=0;
cl();
}
}
// Power Button
void powerSwitch()
{
if(digitalRead(powerButton)==HIGH)
{
x++;
delay(200);
if(x>1)
{
x=0;
}
if(x==1)
{
lcd.backlight();start_up();
}
else
{
power_up();
}
}
}
void eepromRead()
{
vol = EEPROM.read(0);// vol eeprom
bass = EEPROM.read(1);// bass eeprom
treb = EEPROM.read(2);// treb eeprom
in = EEPROM.read(3);// in eeprom
balans = EEPROM.read(4)-4;// balans eeprom
}
void eepromUpdate()
{
EEPROM.update(0,vol);
EEPROM.update(1,bass);
EEPROM.update(2,treb);
EEPROM.update(3,in);
EEPROM.update(4,balans+4);
}
void cl()
{
delay(200);
lcd.clear();
}
void audio(){
audioChip.setVolumeL(vol+balans);
audioChip.setVolumeR(vol-balans);
audioChip.setBass(bass);
audioChip.setTreble(treb);
audioChip.setMute(mute);
audioChip.setSource(in);
}
void power_up()
{
vol = 0;
audio();
menu=99;
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" ..STANDBY.. ");
delay(5000);
lcd.noBacklight();
}
//startUp -----------------------------------------------------//
void start_up() {
vol = 40;
audio();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" ...HELLO... ");
delay(2000);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("LOADING ");
for(int x=6; x<15; x++)
{
lcd.setCursor(x+1, 1);
lcd.print(".");
delay(300);
}
delay(1000);
//vol = 59;
lcd.clear();
vol = EEPROM.read(0);audio();
menu=0;
}
//lcd_Update-----------------------------------------------------//
void lcd_update(){
if(menu_active==0)
{
custom_num_shape();
lcd.setCursor(0, 1);
lcd.print("VOLUME");
int y;
if (c < 0) {
lcd.setCursor(8, 1);
lcd.print("-");
y = 10 - (c + 10);
}
else if (c == -10) {
lcd.setCursor(8, 1);
lcd.print("-");
y = 10;
}
else {
lcd.setCursor(8, 1);
lcd.print(" ");
y = c;
}
a = y / 10;
b = y - a * 10; // y%10
lcd.setCursor(9, 0);
for (int i = 0; i < digit_width; i++)
lcd.print(custom_num_top[a][i]);
lcd.setCursor(9, 1);
for (int i = 0; i < digit_width; i++)
lcd.print(custom_num_bot[a][i]);
lcd.setCursor(13, 0);
for (int i = 0; i < digit_width; i++)
lcd.print(custom_num_top[b][i]);
lcd.setCursor(13, 1);
for (int i = 0; i < digit_width; i++)
lcd.print(custom_num_bot[b][i]);
}
if(menu_active==1)
{
//...................../
}
}
//custom shape ------------------------------------------------------//
void custom_num_shape() {
for (int i = 0; i < 8; i++)
lcd.createChar(i, custom_num[i]);
}
//rotary menu------------------------------------------------/
void rotaryE()
{
if(x==1)
{
rotating = true; // reset the debouncer
if(menu==0)
{
if(w==1)
{
audio();
//cl();
time=millis();
save_eeprom=1;
w=0;
}
c = vol;
lcd.setCursor(0, 0);
lcd.print("IN-");
lcd.print(in);
lcd_update();
}
if(menu==1)
{
if(w==1)
{
audio();
cl();
time=millis();
save_eeprom=1;
w=0;
}
lcd.setCursor(0,0);
lcd.print("Bass ");
bass_d=bass*3-18;
if(bass_d>=0)
{
lcd.print("+");
}
else
{
lcd.print("-");
}
if(bass_d>-10&&bass_d<=0||bass_d<10&&bass_d>0)
{
{
lcd.print(" ");
}
}
lcd.print(abs(bass_d));
lcd.print(" dB ");
lcd.createChar(0,a1);
lcd.createChar(1,a2);
if(bass>1)
{
for(z=3;z<=bass+1;z++)
{
lcd.setCursor(z,1);
lcd.write((uint8_t)0);
}
}
}
if(menu==2)
{
if(w==1)
{
audio();
cl();
time=millis();
save_eeprom=1;
w=0;
}
lcd.setCursor(0,0);
lcd.print("Treble ");
treb_d=treb*3-18;
if(treb_d>=0)
{
lcd.print("+");
}
else
{
lcd.print("-");
}
if(treb_d>-10&&treb_d<=0||treb_d<10&&treb_d>0)
{
{
lcd.print(" ");
}
}
lcd.print(abs(treb_d));
lcd.print(" dB ");
lcd.createChar(0,a1);
lcd.createChar(1,a2);
if(treb>1)
{
for(z=3;z<=treb+1;z++)
{
lcd.setCursor(z,1);
lcd.write((uint8_t)0);
}
}
}
if(menu==3)
{
lcd.setCursor(0,0);
if(balans>=0)
{
lcd.print("-");
}
else
{
lcd.print("+");
}
lcd.print(abs(balans*2));
lcd.print(" dB ");
lcd.print(" <> ");
if(balans>=0)
{
lcd.print("+");
}
else
{
lcd.print("-");
}
lcd.print(abs(balans*2));
lcd.print(" dB ");
lcd.setCursor(0,1);
lcd.print("R");
lcd.setCursor(15,1);
lcd.print("L");
if(balans<0)
{
lcd.setCursor(balans+7,1);
lcd.write((uint8_t)0);
}
if(balans>0)
{
lcd.setCursor(balans+8,1);
lcd.write((uint8_t)0);
}
if(balans==0)
{
lcd.setCursor(7,1);
lcd.write((uint8_t)0);
lcd.setCursor(8,1);
lcd.write((uint8_t)0);
}
if(w==1)
{
audio();
cl();
time=millis();
save_eeprom=1;
w=0;
}
}
if(menu==4)
{
lcd.setCursor(0,0);
lcd.print("Channel Input");
lcd.setCursor(0,1);
lcd.print("Input: ");
lcd.print(in);
if(w==1)
{
audio();
cl();
time=millis();
save_eeprom=1;
w=0;
}
}
if (digitalRead(menuSwitch) == LOW ) {
menu++;
time=millis();
save_eeprom=1;
w=1;
cl();
if(menu>4)
{
menu=0;
}
}
}
}
// Interrupt on A changing state ........................./
void doEncoderA(){
if(x==1)
{
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
if( digitalRead(dtPinA) != A_set ) {
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
if(menu==0)
{
vol++;
w=1;
if(vol>63)// 63 = +6db
{
vol=63;
}
}
else if(menu==1)
{
bass++;
w=1;
if(bass>11)
{
bass=11;
}
}
else if(menu==2)
{
treb++;
w=1;
if(treb>7)
{
treb=7;
}
}
else if(menu==3)
{
balans++;
w=1;
if(balans>4)
{
balans=4;
}
}
else if(menu==4)
{
in++;
w=1;
if(in>1 && in<255)
{
in=0;
}
}
rotating = false; // no more debouncing until loop() hits again
}
}
}
// Interrupt on B changing state, same as A above........../
void doEncoderB(){
if(x==1)
{
if ( rotating ) delay (1);
if( digitalRead(clkPinB) != B_set ) {
B_set = !B_set;
// adjust counter + if B leads A
if( B_set && !A_set )
if(menu==0)
{
vol--;
w=1;
if(vol<=16)// 16 = -88db
{
vol=16;
}
}
else if(menu==1)
{
bass--;
w=1;
if(bass<2||bass==255)
{
bass=2;
}
}
else if(menu==2)
{
treb--;
w=1;
if(treb<-7)
{
treb=-7;
}
}
else if(menu==3)
{
balans--;
w=1;
if(balans<-4)
{
balans=-4;
}
}
else if(menu==4)
{
in--;
w=1;
if(in>2)
{
in=1;
}
}
rotating = false;
}
}
}
void remoteIr()
{
if (IrReceiver.decode()) {
delay(300);
//time=millis();
IrReceiver.resume();
int command = IrReceiver.decodedIRData.command;
switch (command) {
case muteBT: {
if(x==1)
{
mute++;
delay(300);
time=millis();
if(mute>1)
{
mute=0;
}
if(mute == 1) {
menu_active=1;
lcd.clear();
delay(300);
lcd.setCursor(0, 1);
lcd.print("MUTE ");
lcd.createChar(0, mute1);
lcd.createChar(1, mute2);
lcd.createChar(2, mute3);
lcd.createChar(3, mute4);
lcd.createChar(4, mutex1);
lcd.createChar(5, mutex2);
lcd.createChar(6, mutex3);
lcd.createChar(7, mutex4);
lcd.setCursor(12, 0);
lcd.write(0);
lcd.setCursor(12, 1);
lcd.write(1);
lcd.setCursor(13, 0);
lcd.write(2);
lcd.setCursor(13, 1);
lcd.write(3);
lcd.setCursor(14, 0);
lcd.write(4);
lcd.setCursor(15, 1);
lcd.write(5);
lcd.setCursor(15, 0);
lcd.write(6);
lcd.setCursor(14, 1);
lcd.write(7);
menu = 99 ;
}
if (mute == 0 && menu_active==1) {
vol = EEPROM.read(0);
lcd.clear();
menu_active=0;
menu = 0 ;
}
audio();
//Serial.println("Mutting");
}
break;
}
case menuBT: {
//Serial.println("DISPLAY");
if(x==1)
{
menu++;
delay(100);
time=millis();
save_eeprom=1;
w=1;
cl();
if(menu>4)
{
menu=0;
}
}
break;
}
case volUp: {
//Serial.println("volUp");
if(x==1)
{
if(menu==0)
{
vol++;
w=1;
if(vol>63) // 63 = +6db
{
vol=63;
}
}
else if(menu==1)
{
bass++;
w=1;
if(bass>11)
{
bass=11;
}
}
else if(menu==2)
{
treb++;
w=1;
if(treb>7)
{
treb=7;
}
}
else if(menu==3)
{
balans++;
w=1;
if(balans>4)
{
balans=4;
}
}
else if(menu==4)
{
in++;
w=1;
if(in>1 && in<255)
{
in=0;
}
}
}
break;
}
case volDown: {
//Serial.println("volDown");
if(x==1)
{
if(menu==0)
{
vol--;
w=1;
if(vol<=16)// 16 = -88db
{
vol=16;
}
}
else if(menu==1)
{
bass--;
w=1;
if(bass<2||bass==255)
{
bass=2;
}
}
else if(menu==2)
{
treb--;
w=1;
if(treb<-7)
{
treb=-7;
}
}
else if(menu==3)
{
balans--;
w=1;
if(balans<-4)
{
balans=-4;
}
}
else if(menu==4)
{
in--;
w=1;
if(in>2)
{
in=1;
}
}
}
break;
}
case powerBT:{
//Serial.println("Power");
x++;
delay(200);
if(x>1)
{
x=0;
}
if(x==0)
{
power_up();
}
else
{
lcd.backlight();start_up();
}
//Serial.println(x);
break;
}
default: {
Serial.println("Button not recognized");
}
}
}
}
/*
* Spesifikasi TDA8425:
Tegangan suplai minimum 7 V
Tegangan suplai maksimum 13,2 V
Rentang frekuensi 35…20000 Hz
Distorsi harmonik 0,05%
Tegangan keluaran maksimum 1 V
Kontrol volume 48 level dari -88dB hingga +6dB dalam langkah 2dB
Kontrol nada bass dari -12 dB hingga +15 dB dalam langkah 3 dB
Kontrol nada treble -12dB hingga +12dB dalam langkah 3dB
Penyesuaian keseimbangan 8dB dalam langkah 2dB
*/
/*
* kode remote sony
*
* power 21
* display 58
* muting 20
* TV 56
* Video 37
* Text 63
* 1 0
* 2 1
* 3 2
* 4 3
* .
* .
* .
* .
* 9 8
* 0 9
* -/-- 29
* jump 59
* Text CLR 43
* + 116
* Select 124
* A/B 23
* - 117
* PicMode 97
* WakeUp 60
* Sleep 54
* VolUp 18
* VolDown 19
* ProgUp 16
* ProgDown 17
*/