

Nikotronic
Making audio for the people
arduino code as i have it now.
thanks to Andrew_h for sharing some :)
#include <EEPROMex.h>
#include <EEPROMAnything.h>
#include <stdint.h>
#include <SPI.h>
#include <Wire.h>
#include <Encoder.h>
#include <LiquidCrystal_I2C.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <Arduino.h>
//IR stuff
#include <IRremote.h>
int RECV_PIN = 14;
IRrecv irrecv(RECV_PIN);
decode_results results;
//******************************************
// Change these to suit your IR Remote.
// Codes that are not understood are printed via serial
// use the values printed to replce the ones here.
const unsigned long irOk = 16712445;
const unsigned long irLeft = 16720605;
const unsigned long irRight = 16761405;
const unsigned long irUp = 16736925;
const unsigned long irDown = 16754775;
const unsigned long irPower = 16728765;
//******************************************
// Radio module Library
#include <TEA5767.h>
//Sound Processor chip library
#include <TDA7439.h>
TDA7439 equ;
//Radio module
TEA5767 Radio;
int search_direction;
// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3f for a 16 chars and 2 line display
//General variables
boolean powerStateChanged = 1;
boolean IrOKbutton = 0;
boolean tmpPower = 0;
uint8_t menuButton = 4;
uint8_t powerButton = 5;
uint8_t backlight = 9;
uint8_t blBrightness = 250;
uint8_t timeCursor = 1;
uint8_t onPowerLED = 16;
uint8_t offPowerLED = 15;
uint8_t powerRelay = 6;
uint8_t fan = 17;
uint8_t loopCount = 0;
//Values that get stored in EEPROM
struct config_t
{
boolean powerState;
int activeInput;
int volumeLevel;
int bassLevel;
int midLevel;
int trebLevel;
int attLevel;
int gainLevel;
double frequency;
} configuration;
//Radio
int search_mode = 0;
unsigned char buf[5];
//For displaying time
char twoDigitNumber[3] = "00";
char tftTime[6] = "00:00";
//creating the custom fonts:
byte seg_1[8] = {
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,};
byte seg_2[8] = {
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,};
byte seg_3[8] = {
B11111,
B11111,
B00000,
B00000,
B00000,
B11111,
B11111,};
byte seg_4[8] = {
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,};
byte seg_5[8] = {
B00000,
B00000,
B00000,
B01110,
B01110,
B01110,
B00000,};
byte seg_6[8] = {
B00000,
B00000,
B00000,
B00000,
B00000,
B10000,
B10000,};
byte seg_7[8] = {
B00000,
B00000,
B00000,
B00100,
B00100,
B10100,
B10100,};
byte seg_8[8] = {
B00000,
B00001,
B00001,
B00101,
B00101,
B10101,
B10101,};
int customchar[10][6] ={{4,1,4,4,2,4}, //0
{1,4,32,2,4,2}, //1
{3,3,4,4,2,2},
{1,3,4,2,2,4},
{4,2,4,32,32,4},
{4,3,3,2,2,4},
{4,3,3,4,2,4},
{1,1,4,32,32,4},
{4,3,4,4,2,4},
{4,3,4,2,2,4}}; //9
const int menuTimeout = 5000;
unsigned long lastChange = 0;
//Encoder related
volatile byte enc=0; // flags for the interrupt routine
#define ENC_PIN_UP 3
#define ENC_PIN_DOWN 2
#define ENC_INT_UP 1
#define ENC_INT_DOWN 0
boolean encoderUpSet = false;
boolean encoderDownSet = false;
static boolean rotating=false; // debounce management
#define CONFIGURATION_MAX_GAIN 15
void init_encoder()
{
// Encoder setup...
pinMode(ENC_PIN_UP, INPUT_PULLUP);
pinMode(ENC_PIN_DOWN, INPUT_PULLUP);
attachInterrupt(ENC_INT_UP, encoderInterruptUp, CHANGE);
attachInterrupt(ENC_INT_DOWN, encoderInterruptDown, CHANGE);
}
void encoderInterruptUp() {
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if( digitalRead(ENC_PIN_UP) != encoderUpSet ) { // debounce once more
encoderUpSet = !encoderUpSet;
// adjust counter + if A leads B
if ( encoderUpSet && !encoderDownSet )
enc = 2;
rotating = false; // no more debouncing until loop() hits again
}
}
void encoderInterruptDown() {
if ( rotating ) delay (1);
if( digitalRead(ENC_PIN_DOWN) != encoderDownSet ) {
encoderDownSet = !encoderDownSet;
// adjust counter - 1 if B leads A
if( encoderDownSet && !encoderUpSet )
enc = 1;
rotating = false;
}
}
void setup()
{
lcd.begin();
lcd.backlight();
lcd.createChar(1, seg_1);
lcd.createChar(2, seg_2);
lcd.createChar(3, seg_3);
lcd.createChar(4, seg_4);
lcd.createChar(5, seg_5);
lcd.createChar(6, seg_6);
lcd.createChar(7, seg_7);
lcd.createChar(8, seg_8);
irrecv.enableIRIn(); // Start the receiver
init_encoder();
Serial.begin(9600);
Wire.begin();
Radio.init();
pinMode(powerButton, INPUT); //Set buttons as inputs
pinMode(menuButton, INPUT);
digitalWrite(powerButton, HIGH); //Enable internal pullups
digitalWrite(menuButton, HIGH);
pinMode(fan, OUTPUT);
digitalWrite(fan, 0);
pinMode(powerRelay, OUTPUT);
digitalWrite(powerRelay, 0);
pinMode(offPowerLED, OUTPUT);
digitalWrite(offPowerLED, HIGH);
pinMode(onPowerLED, OUTPUT);
digitalWrite(onPowerLED, HIGH);
EEPROM_readAnything(0, configuration);
if (configuration.activeInput == 255) configuration.activeInput = 0;
if (configuration.volumeLevel == 255) configuration.volumeLevel = 32;
if (configuration.bassLevel == 255) configuration.bassLevel = 0;
if (configuration.midLevel == 255) configuration.midLevel = 0;
if (configuration.trebLevel == 255) configuration.trebLevel = 0;
configuration.attLevel = 0;
if (configuration.gainLevel == 255) configuration.gainLevel = 0;
if (configuration.frequency < 88) configuration.frequency = 88;
equ.setInput(configuration.activeInput+1);
equ.inputGain(configuration.gainLevel);
equ.setVolume(configuration.volumeLevel);
equ.setSnd(configuration.bassLevel,1);
equ.setSnd(configuration.midLevel,2);
equ.setSnd(configuration.trebLevel,3);
equ.spkAtt(configuration.attLevel);
if (configuration.powerState == 0){
digitalWrite(offPowerLED, LOW);
digitalWrite(onPowerLED,HIGH);
}else{
digitalWrite(offPowerLED, HIGH);
digitalWrite(onPowerLED, LOW);
}
}
void loop()
{
processIR();
tmpPower = digitalRead(powerButton);
//Power button pressed?
if (tmpPower == 0){
delay(300); //Avoid rapid power cycles
configuration.powerState = ~configuration.powerState;
powerStateChanged = 1;
}
if (configuration.powerState == 0){
//Off
if (powerStateChanged == 1){
//But only just turned off
powerStateChanged = 0;
equ.setVolume(0);
analogWrite(backlight, 100);
digitalWrite(offPowerLED, LOW);
digitalWrite(onPowerLED,HIGH);
lastChange = millis();
lcd.clear();
EEPROM_writeAnything(0, configuration);
digitalWrite(powerRelay, 0); //Turn off relays etc
digitalWrite(fan, 0);
delay(500);
}
if (millis() - lastChange > 500){
updateTime();
lastChange = millis();
}
}else{
// We are on
if (powerStateChanged == 1){
//Only just turned on
EEPROM_writeAnything(0, configuration);
powerStateChanged = 0;
lcd.clear();
analogWrite(backlight, 200);
digitalWrite(offPowerLED, HIGH);
digitalWrite(onPowerLED, LOW);
lcd.setCursor(0,0);
lcd.print("Arduino Powered");
lcd.setCursor(0,1);
lcd.print(" Gainclone ");
delay(2000);
lcd.clear();
digitalWrite(powerRelay, 1);
digitalWrite(fan, 1);
equ.setInput(configuration.activeInput+1);
equ.inputGain(configuration.gainLevel);
equ.setVolume(configuration.volumeLevel);
equ.setSnd(configuration.bassLevel,1);
equ.setSnd(configuration.midLevel,2);
equ.setSnd(configuration.trebLevel,3);
equ.spkAtt(configuration.attLevel);
if (configuration.activeInput == 0) {
radio_on();
radio_status();
}
}
if (millis() - lastChange > 500){
if (loopCount > 200){ //Stop loopcount from overflowing
loopCount = 5;
}else{
loopCount++;
}
if (configuration.activeInput == 0){
if (loopCount > 3){
loopCount = 0;
radio_status();
}
}else{
if (loopCount == 4) lcd.clear();
if (loopCount > 3){
updateTime();
}
}
lastChange = millis();
}
if (search_mode == 1) {
if (Radio.process_search (buf, search_direction) == 1) {
search_mode = 0;
}
}
rotating = true;
//Volume control
if (enc != 0){
analogWrite(backlight,blBrightness);
lcd.clear();
lcd.print("Volume");
switch(enc){
case 1:
configuration.volumeLevel --;
enc = 0;
break;
case 2:
configuration.volumeLevel ++;
enc = 0;
break;
}
lastChange = millis();
configuration.volumeLevel = constrain(configuration.volumeLevel, 0, 48);
equ.setVolume(configuration.volumeLevel);
// EEPROM.write(volumeLevel,2);
force2Digits(configuration.volumeLevel);
printBigDigit(twoDigitNumber[0],9);
printBigDigit(twoDigitNumber[1],13);
loopCount = 0;
}
//Menu system
if (digitalRead(menuButton) == 0 | IrOKbutton == 1) {
analogWrite(backlight,blBrightness);
IrOKbutton = 0;
displayMenu();
}
}
}
void radio_on(){
Radio.set_frequency(configuration.frequency);
}
void radio_tune_up(){
search_mode = 1;
search_direction = TEA5767_SEARCH_DIR_UP;
Radio.search_up(buf);
radio_status();
}
void radio_tune_down(){
search_mode = 1;
search_direction = TEA5767_SEARCH_DIR_DOWN;
Radio.search_down(buf);
radio_status();
}
void radio_status(){
int stereo;
int signal_level;
double current_freq;
if (Radio.read_status(buf) == 1) {
current_freq = floor (Radio.frequency_available (buf) / 100000 + .5) / 10;
stereo = Radio.stereo(buf);
signal_level = Radio.signal_level(buf);
//print current_freq to lcd
lcd.setCursor(0,0);
lcd.print("Radio ");
lcd.setCursor(0,1);
lcd.print(current_freq);
configuration.frequency = current_freq;
lcd.setCursor(7,1);
lcd.print("Mhz ");
lcd.setCursor(15,0);
//signal_level /= 100; //signal level is in percent.
switch (signal_level){
case 1:
case 2:
case 3:
case 4:
case 5:
lcd.write(byte(6));
break;
case 6:
case 7:
case 8:
case 9:
case 10:
lcd.write(byte(7));
break;
case 11:case 12:case 13:case 14:
lcd.write(byte(8));
}
lcd.setCursor(15,1);
if (stereo){
lcd.print("S");
}else{
lcd.print("M");
}
}
}
void displayMenu() {
delay(300); // Saves selecting the first option from the original press
lcd.clear();
lcd.print("Menu");
int selected = 0;
int moved = 1;
// display options
lastChange = millis();
while (digitalRead(menuButton) != 0 && IrOKbutton == 0) {
rotating = true;
processIR();
if (millis() - lastChange < menuTimeout){
switch (enc){
case 1:
if (selected > 0){
selected--;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
case 2:
if (selected < 4){
selected++;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
}
if (moved) {
switch(selected) {
case 0:
//lcd.print("Change Units ");
lcd.setCursor(0,1);
lcd.print("Input Select");
moved = 0;
break;
case 1:
lcd.setCursor(0,1);
lcd.print("Bass ");
moved = 0;
break;
case 2:
lcd.setCursor(0,1);
lcd.print("Mid ");
moved = 0;
break;
case 3:
lcd.setCursor(0,1);
lcd.print("Treb ");
moved = 0;
break;
case 4:
lcd.setCursor(0,1);
lcd.print("Input Gain ");
moved = 0;
break;
}
}
}else{
// Timed out
lcd.clear();
return;
}
}
IrOKbutton = 0;
switch(selected) {
case 0:
changeInput();
break;
case 1:
changeSnd(1);
break;
case 2:
changeSnd(2);
break;
case 3:
changeSnd(3);
break;
case 4:
changeGain();
break;
}
delay(300); //Saves going back in to menu
}
void changeInput(){
delay(300);
int selected = configuration.activeInput;
int moved = 1;
// display options
lcd.clear();
lcd.print("Input selection");
lastChange = millis();
while (digitalRead(menuButton) != 0 && IrOKbutton == 0) {
rotating = true;
processIR();
if (millis() - lastChange < menuTimeout){
switch (enc){
case 1:
if (selected > 0){
selected--;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
case 2:
if (selected < 3){
selected++;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
}
if (moved) {
switch(selected) {
case 0:
lcd.setCursor(0,1);
lcd.print("Tuner ");
break;
case 1:
lcd.setCursor(0,1);
lcd.print("DAC ");
break;
case 2:
lcd.setCursor(0,1);
lcd.print("CD ");
break;
case 3:
lcd.setCursor(0,1);
lcd.print("AUX ");
break;
}
moved = 0;
}
}else{
lcd.clear();
return;
}
}
IrOKbutton = 0;
// when button is pressed...
equ.setInput(selected+1);
configuration.activeInput = selected;
EEPROM_writeAnything(0, configuration);
if (selected == 0) {
lcd.clear();
radio_on();
radio_status();
}else{
delay(500);
lcd.clear();
}
}
void changeSnd(int band){
int printValue;
delay(300);
lcd.clear();
int selected;
switch (band){
case 1:
lcd.print("Bass");
selected = configuration.bassLevel;
break;
case 2:
lcd.print("Mid ");
selected = configuration.midLevel;
break;
case 3:
lcd.print("Treb");
selected = configuration.trebLevel;
break;
}
if (selected < 0){
lcd.setCursor(10,0);
lcd.write(byte(2));
lcd.setCursor(11,0);
lcd.write(byte(2));
}else{
lcd.setCursor(10,0);
lcd.print(" ");
}
if (selected < 0){
printValue = selected * -1;
}else{
printValue = selected;
}
printBigDigit(printValue + 48,13);
//lcd.print(selected);
int moved = 0;
// display options
lastChange = millis();
while (digitalRead(menuButton) != 0 && IrOKbutton == 0) {
rotating = true;
processIR();
if (millis() - lastChange < menuTimeout){
switch (enc){
case 1:
if (selected > -7){
selected--;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
case 2:
if (selected < 7){
selected++;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
}
if (moved) {
if (selected < 0){
lcd.setCursor(10,0);
lcd.write(byte(2));
lcd.setCursor(11,0);
lcd.write(byte(2));
}else{
lcd.setCursor(10,0);
lcd.print(" ");
}
if (selected < 0){
printValue = selected * -1;
}else{
printValue = selected;
}
printBigDigit(printValue + 48,13);
moved = 0;
equ.setSnd(selected, band);
}
}else{
lcd.clear();
return;
}
}
// when button is pressed...
IrOKbutton = 0;
switch (band){
case 1:
configuration.bassLevel = selected;
break;
case 2:
configuration.midLevel = selected;
break;
case 3:
configuration.trebLevel = selected;
}
EEPROM_writeAnything(0, configuration);
lcd.clear();
lcd.print("Saved");
delay(500);
}
void changeGain(){
lcd.clear();
lcd.print("Gain");
force2Digits(configuration.gainLevel);
printBigDigit(twoDigitNumber[0],9);
printBigDigit(twoDigitNumber[1],13);
delay(300);
int selected = configuration.gainLevel;
int moved = 0;
// display options
lastChange = millis();
while (digitalRead(menuButton) != 0 && IrOKbutton == 0) {
rotating = true;
processIR();
if (millis() - lastChange < menuTimeout){
switch (enc){
case 1:
if (selected > 0){
selected--;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
case 2:
if (selected < CONFIGURATION_MAX_GAIN) {
selected++;
moved = 1;
}
enc = 0;
lastChange = millis();
break;
}
if (moved) {
equ.inputGain(selected);
force2Digits(selected);
printBigDigit(twoDigitNumber[0],9);
printBigDigit(twoDigitNumber[1],13);
moved = 0;
}
}else{
lcd.clear();
return;
}
}
// when button is pressed...
IrOKbutton = 0;
lcd.clear();
lcd.print("Saved");
configuration.gainLevel = selected;
EEPROM_writeAnything(0, configuration);
delay(500);
lcd.clear();
}
void processIR(){
if (irrecv.decode(&results)) {
switch (results.value){
case irOk:
Serial.println("Ok");
//ok button
IrOKbutton = 1;
lastChange = millis();
break;
case irRight:
// Rotary right
enc = 2;
lastChange = millis();
break;
case irLeft:
//Rotary left
enc = 1;
lastChange = millis();
break;
case irPower:
configuration.powerState = ~configuration.powerState;
powerStateChanged = 1;
break;
case irUp:
//tune up
if (configuration.activeInput == 0) radio_tune_up();
break;
case irDown:
if (configuration.activeInput == 0) radio_tune_down();
break;
default:
Serial.println(results.value);
}
irrecv.resume(); // Receive the next value
}
}
void updateTime(){
if (timeCursor == 1){
lcd.setCursor(7,0);
lcd.write(byte(5));
lcd.setCursor(7,1);
lcd.write(byte(5));
timeCursor = 0;
}else{
lcd.setCursor(7,0);
lcd.print(" ");
lcd.setCursor(7,1);
lcd.print(" ");
timeCursor = 1;
}
tmElements_t tm;
if (RTC.read(tm)) {
force2Digits(tm.Hour);
tftTime[0] = twoDigitNumber[0];
tftTime[1] = twoDigitNumber[1];
force2Digits(tm.Minute);
tftTime[2] = twoDigitNumber[0];
tftTime[3] = twoDigitNumber[1];
for (int i=0;i<4;i++){
int clockDigit = int(tftTime[i] -48 );
lcd.setCursor(i*4,0);
for (int x=0;x<3;x++){
lcd.write(byte(customchar[clockDigit][x]));
}
lcd.setCursor(i*4,1);
for (int x=3;x<6;x++){
lcd.write(byte(customchar[clockDigit][x]));
}
}
}
}
void force2Digits(int number){
itoa(number, twoDigitNumber,10);
if (number >= 0 && number < 10) {
twoDigitNumber[1] = twoDigitNumber[0];
twoDigitNumber[0] = '0';
}
}
void printBigDigit(int number, int xpos){
lcd.setCursor(xpos,0);
for (int x=0;x<3;x++){
lcd.write(byte(customchar[number - 48][x]));
}
lcd.setCursor(xpos,1);
for (int x=3;x<6;x++){
lcd.write(byte(customchar[number -48][x]));
}
}