#include "U8glib.h"
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
#include <IRremote.h>
//#define DEBUG true
#define USE_SPI_LIB true
#define RESET_VOL 9
/* The following are defined in <standard/pins_arduino.h>. We will use pin 10 to select the CS3318.
static const uint8_t SS = 10; // Slave Select
static const uint8_t MOSI = 11; // Master Out Slave In
static const uint8_t MISO = 12; // Master In Slave Out
static const uint8_t SCK = 13; // Serial Clock; this also happens to be connected to the yellow LED on the Arduino UNO R3 board
*/
#define HW_MUTE 7 /* control the hardware mute pin of CS3318*/
#define CS3318_ADDR 0x80 /* CS3318 chip address and R/W bit */
#define VOL_MIN 0x12 /* -96dB is the maximum attenuation available in the CS3318 */
#define VOL_MAX 0xd4 /* I want +1dB to be the maximum gain for my application */
#define MASTER_VOL_REG 0x11 /* CS3318 master volume control register */
#define MUTE_CONTROL_REG 0x0b /* register for setting up control of CS3318 mute pin */
#define ZERO_X_CONTROL_REG 0x0c /* register for controlling zero-crossing detector */
#define PDN_ALL_REG 0x0e /* register for master power down bit */
#define PDN_ALL_CLEAR 0 /* clear all bits (but bit 0 is the only one of interest) */
#define MUTE_PIN_DISABLE 0 /* clear all bits (but bit 5 is the only one of interest) */
#define N_CHANNELS 8 /* number of channels in CS3811 */
#define EEPROM_SIZE 4096 /* the Arduino Mega has 4KB of EEPROM */
#define EEPROM_ERASE_BYTE 0xff
#define WRITE_VOL_DELAY 60000 /* delay 1 minute (60000 ms) after volume change before sending value to EEPROM */
volatile byte CurrentVolume = VOL_MIN;
byte PreviousVolume = VOL_MIN;
int CurrentBufferPosition = 0;
boolean TriggerVolumePersist = false;
boolean EEPROMMalfunction = false;
unsigned long TriggerStartMS = 0L; /* persistence delay start time in milliseconds */
int RECV_PIN = 8; //IR input pin on Arduino
IRrecv irrecv(RECV_PIN);
decode_results results;
// keycodes for remote
//const int R_PWR = 0xFFA25D;
const int R_MUTE = 0xFFE21D; //MENU KEY
const int R_VOL_UP = 0xFF629D;
const int R_VOL_DOWN = 0xFFA857;
unsigned int lastcode;
int code_count;
int increment;
/*
This sketch uses the rotary encoder handler written by Ben Buxton.
At this time, the code can be downloaded from https://github.com/brianlow/Rotary
*/
Rotary RotaryEncoder = Rotary(14, 15); /* The pins the rotary encoder uses must be interrupt pins. */
// Relating to debouncing the mute and channel select pins
#define muteSwitchPin 5 // INPUT Momentary switch for mute
#define switchDebounceTime 50 // Milliseconds switch needs to be in state before effect (ms)
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
// 'mute128x64', 128x64px
const unsigned char epd_bitmap_mute128x64 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x0c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0x80, 0x00, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0f, 0xc0, 0x01, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xe0, 0x03, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x03, 0xf0, 0x07, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x01, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfc, 0x1f, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7e, 0x3f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7e, 0x3f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfc, 0x1f, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x01, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x03, 0xf0, 0x07, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xe0, 0x03, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0f, 0xc0, 0x01, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0x80, 0x00, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x0c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#ifdef USE_SPI_LIB
void sendByteToVol(byte registr, byte data)
{
digitalWrite(SS, LOW); /* select the CS3318 */
// delayMicroseconds(1); /* CS3312 requires at least 20 ns (.02 microsecond) from chip select to clock edge */
SPI.transfer(CS3318_ADDR);
// delayMicroseconds(8); /* 1 clock cycle with 125 kHz clock */
SPI.transfer(registr);
// delayMicroseconds(8); /* 1 clock cycle with 125 kHz clock */
SPI.transfer(data);
// delayMicroseconds(8); /* 1 clock cycle with 125 kHz clock */
digitalWrite(SS, HIGH); /* deselect the CS3318 */
delayMicroseconds(2); /* CS3312 requires at least 1 microsecond between transmissions */
#ifdef DEBUG
Serial.print("Sent byte to CS3318 at ");
Serial.print(CS3318_ADDR, HEX);
Serial.print(", register ");
Serial.print(registr, HEX);
Serial.print(", data ");
Serial.println(data, HEX);
#endif
}
#else
/* try some code from linux_man */
// data sent on RISING edge of clock
void spi_send_byte (unsigned char data)
{
int i;
for (i = 0; i < 8; i++) {
if (data & 0x80) {
digitalWrite(MOSI, HIGH);
}
else {
digitalWrite(MOSI, LOW);
}
delay(1);
// strobe clock
digitalWrite(SCK, HIGH);
delay(1);
digitalWrite(SCK, LOW);
delay(1);
data = (data << 1); // left shift next bit over
} // for
}
//void spi_write_register (unsigned char map_byte, unsigned char data_byte)
void sendByteToVol(unsigned char map_byte, unsigned char data_byte)
{
digitalWrite(SS, LOW); // start an SPI transaction
delay(1);
spi_send_byte(B10000000); // chip_addr and r/w bit
delay(2);
spi_send_byte(map_byte); // memory 'addr' (register addr)
delay(2);
spi_send_byte(data_byte); // the 8bits of user data (write that to the register)
// to be a little cleaner, we also turn data off when done
digitalWrite(MOSI, LOW);
delay(1);
digitalWrite(SS, HIGH); // finish an SPI transaction
delay(1);
}
#endif
int findCurrentBufferPosition()
{
for (int i = 0; i < EEPROM_SIZE; i++)
{
byte v = EEPROM.read(i);
if (v != EEPROM_ERASE_BYTE)
{
return i;
}
}
return 0;
}
byte getPersistedVolume()
{
return EEPROM.read(CurrentBufferPosition);
}
void setVolume()
{
sendByteToVol(MASTER_VOL_REG, CurrentVolume);
#ifdef DEBUG
Serial.print("New volume: ");
Serial.println(CurrentVolume, HEX);
#endif
}
boolean persistVolume()
{
#ifdef DEBUG
Serial.print("Persisting volume: ");
Serial.println(CurrentVolume, HEX);
#endif
EEPROM.write(CurrentBufferPosition, EEPROM_ERASE_BYTE);
if (EEPROM.read(CurrentBufferPosition) != EEPROM_ERASE_BYTE)
{
#ifdef DEBUG
Serial.print("Cannot erase EEPROM at ");
Serial.println(CurrentBufferPosition, HEX);
#endif
return false;
}
if (++CurrentBufferPosition >= EEPROM_SIZE)
{
CurrentBufferPosition = 0;
}
EEPROM.write(CurrentBufferPosition, CurrentVolume);
if (EEPROM.read(CurrentBufferPosition) != CurrentVolume)
{
#ifdef DEBUG
Serial.print("Cannot write to EEPROM at ");
Serial.println(CurrentBufferPosition, HEX);
#endif
return false;
}
#ifdef DEBUG
Serial.print("Persisted volume: ");
Serial.print(CurrentVolume, HEX);
Serial.print(" at: ");
Serial.println(CurrentBufferPosition, HEX);
#endif
return true;
}
// display volume reading
void PrintMute() {
u8g.setColorIndex(1);
u8g.firstPage();
do {
} while ( u8g.nextPage());
}
// display volume reading
void PrintVol() {
u8g.setColorIndex(1);
u8g.firstPage();
do {
char buf[9];
int VoldB = (CurrentVolume - 210) / 2;
sprintf (buf, "%d", VoldB);
u8g.setFont(u8g_font_fub42n);
u8g.setPrintPos(15, 54);
u8g.print(buf); //replace the number with the volume reading
u8g.setFont(u8g_font_fub14);
u8g.setPrintPos(105, 54);
Serial.print(CurrentVolume);
Serial.print('\n'); // prints a new line character
u8g.print("dB");
if (CurrentVolume == 2 * VoldB + 210)
{
u8g.setFont(u8g_font_fub25);
u8g.setPrintPos(100, 38);
u8g.print(".0");
}
else
{
u8g.setFont(u8g_font_fub25);
u8g.setPrintPos(100, 38);
u8g.print(".5");
}
} while ( u8g.nextPage());
}
void setup()
{
digitalWrite(RESET_VOL, LOW); /* # 1 in CS3318 Recommended Power-Up sequence: set low until everything is stabilized */
pinMode(RESET_VOL, OUTPUT); /* CS3318 active low reset */
#ifdef DEBUG
Serial.begin(9600); /* set up Serial library at 9600 bps */
#endif
#ifdef USE_SPI_LIB
digitalWrite(SCK, LOW); /* clock is idle when low, data is clocked into the CS3318 on the rising edge; the yellow LED will light up when this is HIGH */
/* will be done by SPI.begin()
pinMode(SCK, OUTPUT); /* SPI clock line */
digitalWrite(MOSI, LOW);
/* will be done by SPI.begin()
pinMode(MOSI, OUTPUT); /* SPI data line */
/* will be done by SPI.begin()
digitalWrite(SS, HIGH); /* set high so it is deselected for now */
/* will be done by SPI.begin()
pinMode(SS, OUTPUT); /* SPI active low chip select */
/* slow down SPI clock??? */
/* note: CS3318 datasheet says chip can handle 6 MHz clock. Arduino default is 4 MHz */
// SPI.setClockDivider(SPI_CLOCK_DIV16); /* 1 MHz clock */
// SPI.setClockDivider(SPI_CLOCK_DIV128); /* 125 kHz clock */
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
SPI.begin();
/* Atmel AVR151 app note (doc2585.pdf) page 11 says, "Clear SPI Interrupt Flag by reading SPSR and SPDR" during initialization. */
byte x = SPSR;
x = SPDR;
#else
digitalWrite(SCK, LOW); /* clock is idle when low, data is clocked into the CS3318 on the rising edge; the yellow LED will light up when this is HIGH */
pinMode(SCK, OUTPUT); /* SPI clock line */
digitalWrite(MOSI, LOW);
pinMode(MOSI, OUTPUT); /* SPI data line */
digitalWrite(SS, HIGH); /* set high so it is deselected for now */
pinMode(SS, OUTPUT); /* SPI active low chip select */
pinMode(HW_MUTE, OUTPUT);
#endif
/* setup rotary encoder interrupt */
PCICR |= (1 << PCIE1); /* Select port J */
PCMSK1 |= (1 << PCINT9) | (1 << PCINT10); /* PJ0 pin15 and PJ1 pin14*/
sei();
delay(2000); /* wait for other hardware to stabilize */
CurrentBufferPosition = findCurrentBufferPosition(); /* position of last write in circular buffer */
digitalWrite(RESET_VOL, HIGH); /* #2 in CS3318 Recommended Power-Up Sequence: take CS3318 out of reset mode */
delay(20); /* wait for CS3318 come out of reset mode */
/* the CS3318 datasheet says, "SPI Mode is selected if there is a high-to-low transition on the CS pin after the RESET pin has been brought high." */
/* so here is the high-to-low transition noted above, selecting SPI serial control */
digitalWrite(SS, LOW);
delay(1);
digitalWrite(SS, HIGH);
/* Dr_EM found that a minimum of 250 ms delay is necessary here. */
/* see http://www.diyaudio.com/forums/analog-line-level/239950-cs3318-pcb-layout-15.html#post4116958 */
delay(250);
/* write strange errata sequence to CS3318 per Cirrus_PCN_CS3308-18_B0_C0.pdf */
sendByteToVol(0x00, 0x99);
sendByteToVol(0x1d, 0x86);
sendByteToVol(0x1f, 0x02);
sendByteToVol(0x00, 0x00);
/* disable hardware mute pin of the CS3318 */
//sendByteToVol(MUTE_CONTROL_REG, MUTE_PIN_DISABLE);
/* Default zero crossing detection timeout 18ms, which is about 1/2 cycle for a 31 Hz signal */
// sendByteToVol(ZERO_X_CONTROL_REG, ); /* keep defaults???? */
/* init master volume */
CurrentVolume = PreviousVolume = getPersistedVolume();
digitalWrite(HW_MUTE, HIGH); /* switch off HW mute*/
PrintVol();
#ifdef DEBUG
Serial.print("Startup persisted volume: ");
Serial.println(CurrentVolume, HEX);
#endif
if (CurrentVolume > VOL_MAX || CurrentVolume < VOL_MIN)
{
CurrentVolume = PreviousVolume = VOL_MIN;
}
sendByteToVol(MASTER_VOL_REG, CurrentVolume);
/* # 4 in CS3318 Recommended Power-Up Sequence: clear PDN_ALL bit */
sendByteToVol(PDN_ALL_REG, PDN_ALL_CLEAR);
}
//Rotary Encoder interrupt
ISR(PCINT1_vect)
//void VolRot()
{
unsigned char result = RotaryEncoder.process();
if (result)
{
if (result == DIR_CW)
{
if (CurrentVolume < VOL_MAX)
{
CurrentVolume++;
}
}
else
{
if (CurrentVolume > VOL_MIN)
{
CurrentVolume--;
}
}
}
}
//IR interrupt
// ISR(PCINT8_vect)
// {
// if (irrecv.decode(&results)) {
// Serial.println(results.value, HEX);
// // remote has a repeat function
// if (results.value != 0xFFFFFFFF) {
// lastcode = (results.value);
// code_count = 1;
// }
// else {code_count++;}
// switch (code_count){
// case 1:
// increment = 1;
// break;
// case 2 ... 4:
// increment = 2;
// break;
// default: increment = 5;
// if (lastcode == R_VOL_UP)
// if(CurrentVolume < VOL_MAX)
// {
// CurrentVolume++;
// }
// }
// if (lastcode == R_VOL_DOWN)
// if(CurrentVolume > VOL_MIN)
// {
// CurrentVolume--;
// }
// }
// }
void loop()
{
if (!EEPROMMalfunction)
{
if (PreviousVolume != CurrentVolume)
{
setVolume();
PreviousVolume = CurrentVolume;
if (EEPROM.read(CurrentBufferPosition) != CurrentVolume)
{
TriggerStartMS = millis();
TriggerVolumePersist = true;
}
}
if (TriggerVolumePersist)
{
if (millis() - TriggerStartMS >= WRITE_VOL_DELAY) /* this will accomodate wrap-around of millis() return value */
{
if (!persistVolume()) /* write to EEPROM and check for malfunction */
{
/* EEPROM not functioning correctly */
EEPROMMalfunction = true;
}
TriggerVolumePersist = false;
}
}
}
else
{
/* blink the Arduino UNO's internal yellow LED, which also happens to be connected internally to the SCK pin on the UNO */
digitalWrite(SCK, HIGH);
delay(1000);
digitalWrite(SCK, LOW);
delay(1000);
}
PrintVol();
}