top of page

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]));

       } 

}

 

 

© 2023 by Radiome. Proudly created with Wix.com

bottom of page