Car stereo control using TDA7419 for input select, audio control. Adafruit 96x64 monochrome 0.96" display to show the audio selections four buttons to control selections. Next steps: take input from the car steering wheel controls!

Dependencies:   Adafruit_GFX PinDetect_KL25Z PreampTDA7419 mbed

main.cpp

Committer:
danielashercohen
Date:
2014-10-19
Revision:
2:2b0cf4d80668
Parent:
1:f5b8687f67b8
Child:
3:8d3cc3488cd8

File content as of revision 2:2b0cf4d80668:

#include "mbed.h"
#include "PinDetect.h"
#include "Adafruit_SSD1306.h"
#include "PreampTDA7419.h"

PinDetect  PinUp    ( PTA1  );
PinDetect  PinLeft  ( PTD4  );
PinDetect  PinRight ( PTA2  );
PinDetect  PinDown  ( PTA12 );

class SPI2 : public SPI
{
public:
    SPI2(PinName mosi, PinName miso, PinName clk) : SPI(mosi,miso,clk)
    {
        format(8,3);
        frequency(2000000);
    };
};

SPI2 gSpi(PTD2,NC,PTD1);
Adafruit_SSD1306 display (gSpi, PTD0, PTD5, PTA13);  // SPI obect, DC, RST, CS
PreampTDA7419    Preamp  (PTE0, PTE1);

void testfillrect(void) {
  uint8_t color = 1;
  for (int16_t i=0; i<display.height()/2; i+=3) {
    // alternate colors
    wait(0.05);
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
    display.display();
    color++;
  }
}

void displayWrite(char firstLine[], int value)
{
  display.clearDisplay();
  display.setCursor(0,0);
  display.setTextSize(2);
  display.printf("%s\r\n", firstLine);
  display.setCursor(0,30);
  display.setTextSize(5);
  display.printf("  %d\r\n", value);
  display.display();    
}

////////////////////////////////////
// register addresses for TDA7419 //
////////////////////////////////////
char s_main_source    = 0;
char s_main_loud      = 1   | 0x40;
char s_softmute       = 2   | 0x40;
char s_volume         = 3   | 0x40;
char s_treble         = 4   | 0x40;
char s_middle         = 5   | 0x40;
char s_bass           = 6   | 0x40;
char s_second_source  = 7   | 0x40;
char s_sub_mid_bass   = 8   | 0x40;
char s_mix_gain       = 9   | 0x40;
char s_atten_lf       = 10  | 0x40;
char s_atten_rf       = 11  | 0x40;
char s_atten_lr       = 12  | 0x40;
char s_atten_rr       = 13  | 0x40;
char s_atten_mix      = 14  | 0x40;
char s_atten_sub      = 15  | 0x40;
char s_spectrum       = 16  | 0x40;
char s_test           = 17  | 0x40;

#define NUM_OPTIONS 12 // how many different options can be selected by the display?
char option           = NUM_OPTIONS; // selectOption() in setup to 
                                     // set this to 0 and set up display
char volume           = 4;
char input            = 1;

char mute             = 0;
char mix              = 0;

// for register 4 Treble Filter
int  referenceInE     = 0;
int  trebleCenterFreq = 0;
int  treble;

// for middle frequecy filter
int  middleSoftStep   = 0;
int  middleQ          = 0;
int  middle           = 0;

// for bass frequecy filter
int  bassSoftStep     = 0;
int  bassQ            = 0;
int  bass             = 0;

// for output attenuators
char atten_lf  = 8;
char atten_rf  = 8;
char atten_lr  = 8;
char atten_rr  = 8;
char atten_mix = 8;
char atten_sub = 10;


void writeToTDA7419 (char address, char value) {
  if (!Preamp.i2c_write(address, value)) {
    //displayWrite("Trans Failed", 0);
  }
}  

/////////////////////////////////
// set the speaker attenuators //
/////////////////////////////////
// attenuation can be set from 0 to 11 and this is mapped to the 
// values that the TDA7419 uses for it's attenuation (0->h60)

//
//  (FL/FR/RL/RR/SWL/SWR) (13-18)
void TDA7419SetAttenuation(int address, int attenuation) {
  char regAtten;
  if (volume == 11) {  
    regAtten = 13;
  } else if (attenuation == 10) {
    regAtten = 6;
  } else {
    regAtten = (99-(attenuation*9));
  }
  writeToTDA7419(address, regAtten);
}

// update all of the registers in the TDA7419
void updateReg() {
  char regVolume;
  char regTreble;
  char regMiddle;
  char regBass;

  //////////////////////////////////////////////////////////////////
  // Calculate actual register values from the variables that the //
  // buttons control                                              //
  //////////////////////////////////////////////////////////////////

  // set the master volume //
  // need to calculate the regVolume from the global volume signal
  // volume can be set from 0 to 11 and this is mapped to the 
  // values that the TDA7419 uses for it's volume register 
  // which are a little odd (11 is appropriate because 0->15 register
  // values actually specify a gain,  16->96 specify attenuation)
  if (volume == 11) {  
    regVolume = 13;
  } else if (volume == 10) {
    regVolume = 6;
  } else {
    regVolume = (99-(volume*9));
  }

  // set the tone controls //
  // Expect treble to have the values -5 to +5 //
  // Expect trebleCenterFreq to be 0 to 3      //
  // Expect referenceInE to be 0 or 1          //
  // we define treble as -5 to +5 the TDA7419 register value is more complex
  if (treble > 0) {
    regTreble = 16 + (treble * 3);
  } else if (treble == 0) {
    regTreble = 0;
  } else if (treble  < 0) {
    regTreble = 0 - (treble * 3); 
  }  

  if (middle > 0) {
    regMiddle = 16 + (middle * 3);
  } else if (middle == 0) {
    regMiddle = 0;
  } else if (middle  < 0) {
    regMiddle = 0 - (middle * 3); 
  }  

  if (bass > 0) {
    regBass = 16 + (bass * 3);
  } else if (bass == 0) {
    regBass = 0;
  } else if (bass  < 0) {
    regBass = 0 - (bass * 3); 
  }  

  //////////////////////////  
  // update the registers //
  //////////////////////////  
  writeToTDA7419(s_main_source,   ((0x78) | (input & 0x3) ));
  writeToTDA7419(s_main_loud,      (0xc0));
  writeToTDA7419(s_softmute,       (0xa7));
  TDA7419SetAttenuation(s_volume,   regVolume  );

  writeToTDA7419(s_treble,        
     ( (referenceInE     &  0x1 ) << 7 ) | 
     ( (trebleCenterFreq &  0x3 ) << 5 ) |
     ( (regTreble        & 0x1f )      ) );

  writeToTDA7419(s_middle,      
     ( (middleSoftStep   &  0x1 ) << 7 ) | 
     ( (middleQ          &  0x3 ) << 5 ) |
     ( (regMiddle        & 0x1f )      ) );

  writeToTDA7419(s_bass,   
     ( (bassSoftStep     &  0x1 ) << 7 ) | 
     ( (bassQ            &  0x3 ) << 5 ) |
     ( (regBass          & 0x1f )      ) );

  // this register allows the second source to be routed to the rear speakers
  // not useful in the context of this project
  writeToTDA7419(s_second_source, (0x07));

  // this is the subwoofer cut-off frequency
  // 11 which is 160Khz)
  writeToTDA7419(s_sub_mid_bass,  (0x63));

  // mix to the front speakers,  enable the sub,  no gain
  if (mix == 1) {
    writeToTDA7419(s_mix_gain,    (0xf7));
  } else {
    writeToTDA7419(s_mix_gain,    (0xf0));
  }

  TDA7419SetAttenuation(s_atten_lf,      atten_lf   );
  TDA7419SetAttenuation(s_atten_rf,      atten_rf   );
  TDA7419SetAttenuation(s_atten_lr,      atten_lr   );
  TDA7419SetAttenuation(s_atten_rr,      atten_rr   );

  TDA7419SetAttenuation(s_atten_mix,     atten_mix  );
  TDA7419SetAttenuation(s_atten_sub,     atten_sub  );

  writeToTDA7419       (s_spectrum,      (0x09));  

}

/////////////////////////////////////////////
// Helper functions for the serial display // 
/////////////////////////////////////////////
void processButtonPress (int button) {

  if (button == 0) {
    if (option < (NUM_OPTIONS-1)) {
      option++;
    } else {
      option = 0;
    }
  }

  if (button == 1) {
    if (option > 0) {
      option--;
    } else {
      option = (NUM_OPTIONS-1);
    }
  }

  switch (option) {
  case (0):  // if volume option is selected change volume when button 1 and 2 are pressed
    if (button == 2) {
      if (volume > 0 ) {
        volume--;
      }
    }
    if (button == 3) {
      if (volume < 11) {
        volume++;
      }
    }
    displayWrite("Volume",  volume );
  break;
  case (1):  // manage the input - 1,2,3 are the standard single ended inputs
      if (button == 2) {
        if (input > 1) {
          input--;
        }
      }
      if (button == 3) {
        if (input < 3) {
          input++;
        }
      }
      displayWrite("Input",  input );
  break;
  case (2):  // manage the treble value
    if (button == 2) {
      if (treble > -5) {
        treble--;
      }
    }
    if (button == 3) {
      if (treble < 5) {
        treble++;
      }
    }
    displayWrite("Treble",  treble );
  break;
  case (3):  // manage the middle value
    if (button == 2) {
      if (middle > -5) {
        middle--;
      }
    }
    if (button == 3) {
      if (middle < 5) {
        middle++;
      }
    }
    displayWrite("Middle",  middle );
    break;
  case (4):  // manage the bass value
    if (button == 2) {
      if (bass > -5) {
        bass--;
      }
    }
    if (button == 3) {
      if (bass < 5) {
        bass++;
      }
    }
    displayWrite("Bass",  bass );
  break;

  // Manage the attenuators
  case (5):  // manage the atten_lf value
    if (button == 2) {
      if (atten_lf > 0) {
        atten_lf--;
      }
    }
    if (button == 3) {
      if (atten_lf < 11) {
        atten_lf++;
      }
    }
    displayWrite("LF",  atten_lf );
  break;
  case (6):  // manage the atten_rf value
    if (button == 2) {
      if (atten_rf > 0) {
        atten_rf--;
      }
    }
    if (button == 3) {
      if (atten_rf < 11) {
        atten_rf++;
      }
    }
    displayWrite("RF",  atten_rf );
  break;
  case (7):  // manage the atten_lr value
    if (button == 2) {
      if (atten_lr > 0) {
        atten_lr--;
      }
    }
    if (button == 3) {
      if (atten_lr < 11) {
        atten_lr++;
      }
    }
    displayWrite("LR",  atten_lr );
  break;
  case (8):  // manage the atten_rr value
    if (button == 2) {
      if (atten_rr > 0) {
        atten_rr--;
      }
    }
    if (button == 3) {
      if (atten_rr < 11) {
        atten_rr++;
      }
    }
    displayWrite("RR",  atten_rr );
  break;
  case (9):  // manage the atten_mix value
    if (button == 2) {
      if (atten_mix > 0) {
        atten_mix--;
      }
    }
    if (button == 3) {
      if (atten_mix < 11) {
        atten_mix++;
      }
    }
    displayWrite("Mix",  atten_mix );
  break;
  case (10):  // manage the atten_sub value
    if (button == 2) {
      if (atten_sub > 0) {
        atten_sub--;
      }
    }
    if (button == 3) {
      if (atten_sub < 11) {
        atten_sub++;
      }
    }
    displayWrite("SUB",  atten_sub );
  break;
  case (11):  // manage the atten_sub value
    if (button == 2) {
      mix = 0;
    }
    if (button == 3) {
      mix = 1;
    }
    displayWrite("Mix",  mix );
  break;

  }
  updateReg();  // update the TDA7419 registers to reflect any values changed above
}

void UpPressed( void )
{
    processButtonPress(0);
}

void LeftPressed( void )
{
    processButtonPress(2);
}

void RightPressed( void )
{
    processButtonPress(3);
}

void DownPressed( void )
{
    processButtonPress(1);
}

int main()
{
    PinUp   .mode( PullUp );
    PinLeft .mode( PullUp );
    PinRight.mode( PullUp );
    PinDown .mode( PullUp );

    PinUp   .attach_asserted( &UpPressed    );
    PinLeft .attach_asserted( &LeftPressed  );
    PinRight.attach_asserted( &RightPressed );
    PinDown .attach_asserted( &DownPressed  );

    display.clearDisplay();
    // draw multiple rectangles
    testfillrect();
    wait(0.5);
    display.display();
    display.clearDisplay();
    display.display();
  

    // Sampling does not begin until you set a frequency.
    // The default is 20ms. If you want a different frequency
    // then pass the period in microseconds for example, for 10ms :-
    //     pin.setSampleFrequency( 10000 );
    //
    PinUp   .setSampleFrequency(); // Defaults to 20ms.
    PinLeft .setSampleFrequency(); // Defaults to 20ms.
    PinRight.setSampleFrequency(); // Defaults to 20ms.
    PinDown .setSampleFrequency(); // Defaults to 20ms.

    processButtonPress(0);

    while (1) {
        wait(1);
    }

}

// EOF