annotate core/I2c_Codec.cpp @ 151:e9c9404e3d1f ClockSync

Pff partially working. No PID. When setting the audio clock on the bbb to 44098 the master and slave clock keep diverging instead of converging ...
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 22 Sep 2015 04:10:07 +0100
parents 134bff10e561
children
rev   line source
andrewm@0 1 /*
andrewm@0 2 * I2c_Codec.cpp
andrewm@0 3 *
andrewm@0 4 * Handle writing the registers to the TLV320AIC310x
andrewm@0 5 * series audio codecs, used on the BeagleBone Audio Cape.
andrewm@0 6 * This code is designed to bypass the ALSA driver and
andrewm@0 7 * configure the codec directly in a sensible way. It
andrewm@0 8 * is complemented by code running on the PRU which uses
andrewm@0 9 * the McASP serial port to transfer audio data.
andrewm@0 10 *
andrewm@0 11 * Created on: May 25, 2014
andrewm@0 12 * Author: Andrew McPherson
andrewm@0 13 */
andrewm@0 14
andrewm@0 15 #include "../include/I2c_Codec.h"
andrewm@0 16
andrewm@0 17 I2c_Codec::I2c_Codec()
andrewm@0 18 : running(false), dacVolumeHalfDbs(0), adcVolumeHalfDbs(0), hpVolumeHalfDbs(0)
andrewm@0 19 {}
andrewm@0 20
andrewm@0 21 // This method initialises the audio codec to its default state
andrewm@0 22 int I2c_Codec::initCodec()
andrewm@0 23 {
andrewm@0 24 // Write the reset register of the codec
andrewm@0 25 if(writeRegister(0x01, 0x80)) // Software reset register
andrewm@0 26 {
andrewm@0 27 cout << "Failed to reset codec\n";
andrewm@0 28 return 1;
andrewm@0 29 }
andrewm@0 30
andrewm@0 31 // Wait for codec to process the reset (for safety)
andrewm@0 32 usleep(5000);
andrewm@0 33
andrewm@0 34 return 0;
andrewm@0 35 }
andrewm@0 36
andrewm@0 37 // Tell the codec to start generating audio
andrewm@0 38 // See the TLV320AIC3106 datasheet for full details of the registers
andrewm@0 39 // The dual_rate flag, when true, runs the codec at 88.2kHz; otherwise
andrewm@0 40 // it runs at 44.1kHz
andrewm@0 41 int I2c_Codec::startAudio(int dual_rate)
andrewm@0 42 {
giuliomoro@142 43 // see datasehet for TLV320AIC3104 from page 44
andrewm@0 44 if(writeRegister(0x02, 0x00)) // Codec sample rate register: fs_ref / 1
andrewm@0 45 return 1;
giuliomoro@145 46 // The sampling frequency is given as f_{S(ref)} = (PLLCLK_IN × K × R)/(2048 × P)
giuliomoro@145 47 // The master clock PLLCLK_IN is 12MHz
giuliomoro@145 48 // K can be varied in intervals of resolution of 0.0001 up to 63.9999
giuliomoro@145 49 // using P=8 and R=1 gives a resolution of 0.0732421875Hz ( 0.000166% at 44.1kHz)
giuliomoro@145 50 // to obtain Fs=44100 we need to have K=60.2112
giuliomoro@145 51
giuliomoro@151 52 if(setPllP(1))
giuliomoro@145 53 return 1;
giuliomoro@145 54 if(setPllR(1))
giuliomoro@145 55 return 1;
giuliomoro@145 56 if(setAudioSamplingRate(44100)) //this will automatically find and set K for the given P and R so that Fs=44100
giuliomoro@145 57 return 1;
giuliomoro@142 58 // if(writeRegister(0x03, 0x91)) // PLL register A: enable
giuliomoro@142 59 // return 1;
giuliomoro@132 60 // if(writeRegister(0x04, 0x1C)) // PLL register B
giuliomoro@132 61 // return 1;
giuliomoro@132 62 // if(writeRegister(0x05, 0x52)) // PLL register C
giuliomoro@132 63 // return 1;
giuliomoro@132 64 // if(writeRegister(0x06, 0x40)) // PLL register D
giuliomoro@132 65 // return 1;
giuliomoro@145 66 // if(writeRegister(0x0B, 0x01)) // Audio codec overflow flag register: PLL R = 1
giuliomoro@145 67 // return 1;
giuliomoro@145 68
giuliomoro@145 69 // if(setPllD(5264)) //7.5264 gives 44.1kHz nominal value with a 12MHz master clock
giuliomoro@145 70 // return 1;
giuliomoro@145 71 // if(setPllJ(7))
giuliomoro@145 72 // return 1;
andrewm@0 73 if(dual_rate) {
andrewm@0 74 if(writeRegister(0x07, 0xEA)) // Codec datapath register: 44.1kHz; dual rate; standard datapath
andrewm@0 75 return 1;
andrewm@0 76 }
andrewm@0 77 else {
andrewm@0 78 if(writeRegister(0x07, 0x8A)) // Codec datapath register: 44.1kHz; std rate; standard datapath
andrewm@0 79 return 1;
andrewm@0 80 }
andrewm@0 81 if(writeRegister(0x08, 0xC0)) // Audio serial control register A: BLCK, WCLK outputs
andrewm@0 82 return 1;
andrewm@0 83 if(writeRegister(0x09, 0x40)) // Audio serial control register B: DSP mode, word len 16 bits
andrewm@0 84 return 1;
andrewm@0 85 if(writeRegister(0x0A, 0x00)) // Audio serial control register C: 0 bit offset
andrewm@0 86 return 1;
andrewm@0 87 if(writeRegister(0x0C, 0x00)) // Digital filter register: disabled
andrewm@0 88 return 1;
andrewm@0 89 if(writeRegister(0x0D, 0x00)) // Headset / button press register A: disabled
andrewm@0 90 return 1;
andrewm@0 91 if(writeRegister(0x0E, 0x00)) // Headset / button press register B: disabled
andrewm@0 92 return 1;
andrewm@0 93 if(writeRegister(0x0F, 0x20)) // Left ADC PGA gain control: not muted; 0x20 = 16dB
andrewm@0 94 return 1;
andrewm@0 95 if(writeRegister(0x10, 0x20)) // Right ADC PGA gain control: not muted; 0x20 = 16dB
andrewm@0 96 return 1;
andrewm@0 97
andrewm@0 98 if(writeRegister(0x25, 0xC0)) // DAC power/driver register: DAC power on (left and right)
andrewm@0 99 return 1;
andrewm@0 100 if(writeRegister(0x26, 0x04)) // High power output driver register: Enable short circuit protection
andrewm@0 101 return 1;
andrewm@0 102 if(writeRegister(0x28, 0x02)) // High power output stage register: disable soft stepping
andrewm@0 103 return 1;
andrewm@0 104
andrewm@0 105 if(writeRegister(0x52, 0x80)) // DAC_L1 to LEFT_LOP volume control: routed, volume 0dB
andrewm@0 106 return 1;
andrewm@0 107 if(writeRegister(0x5C, 0x80)) // DAC_R1 to RIGHT_LOP volume control: routed, volume 0dB
andrewm@0 108 return 1;
andrewm@0 109
andrewm@0 110 if(writeHPVolumeRegisters()) // Send DAC to high-power outputs
andrewm@0 111 return 1;
andrewm@0 112
giuliomoro@142 113 if(writeRegister(0x66, 0x02)) // Clock generation control register: use MCLK, PLL N = 2
andrewm@0 114 return 1;
andrewm@0 115
andrewm@0 116 if(writeRegister(0x33, 0x0D)) // HPLOUT output level control: output level = 0dB, not muted, powered up
andrewm@0 117 return 1;
andrewm@0 118 if(writeRegister(0x41, 0x0D)) // HPROUT output level control: output level = 0dB, not muted, powered up
andrewm@0 119 return 1;
andrewm@0 120 if(writeRegister(0x56, 0x09)) // LEFT_LOP output level control: 0dB, not muted, powered up
andrewm@0 121 return 1;
andrewm@0 122 if(writeRegister(0x5D, 0x09)) // RIGHT_LOP output level control: 0dB, not muted, powered up
andrewm@0 123 return 1;
andrewm@0 124
andrewm@0 125 if(writeDACVolumeRegisters(false)) // Unmute and set volume
andrewm@0 126 return 1;
andrewm@0 127
andrewm@0 128 if(writeRegister(0x65, 0x00)) // GPIO control register B: disabled; codec uses PLLDIV_OUT
andrewm@0 129 return 1;
andrewm@0 130
andrewm@0 131 if(writeADCVolumeRegisters(false)) // Unmute and set ADC volume
andrewm@0 132 return 1;
andrewm@0 133
andrewm@0 134 running = true;
andrewm@0 135 return 0;
andrewm@0 136 }
andrewm@0 137
giuliomoro@97 138 //set the numerator multiplier for the PLL
giuliomoro@97 139 int I2c_Codec::setPllK(float k){
giuliomoro@97 140 short unsigned int j=(int)k;
giuliomoro@132 141 unsigned int d=(int)(0.5+(k-j)*10000); //fractional part, between 0 and 9999
giuliomoro@97 142 if(setPllJ(j)>0)
giuliomoro@97 143 return 1;
giuliomoro@97 144 if(setPllD(d)>0)
giuliomoro@97 145 return 2;
giuliomoro@97 146 return 0;
giuliomoro@97 147 }
giuliomoro@97 148
giuliomoro@97 149
giuliomoro@97 150 //set integer part of the numerator mutliplier of the PLL
giuliomoro@97 151 int I2c_Codec::setPllJ(short unsigned int j){
giuliomoro@97 152 if(j>=64 || j<1){
giuliomoro@97 153 return 1;
giuliomoro@97 154 }
giuliomoro@97 155 if(writeRegister(0x04, j<<2)){ // PLL register B: j<<2
giuliomoro@97 156 printf("I2C error while writing PLL j: %d", j);
giuliomoro@97 157 return 1;
giuliomoro@97 158 }
giuliomoro@132 159 pllJ=j;
giuliomoro@97 160 return 0;
giuliomoro@97 161 }
giuliomoro@97 162
giuliomoro@97 163 //set fractional part(between 0 and 9999) of the numerator mutliplier of the PLL
giuliomoro@97 164 int I2c_Codec::setPllD(unsigned int d){
giuliomoro@97 165 if(d<0 || d>9999)
giuliomoro@97 166 return 1;
giuliomoro@97 167 if(writeRegister(0x05, (d>>6)&255)){ // PLL register C: part 1 : 8 most significant bytes of a 14bit integer
giuliomoro@97 168 printf("I2C error while writing PLL d part 1 : %d", d);
giuliomoro@97 169 return 1;
giuliomoro@97 170 }
giuliomoro@97 171 if(writeRegister(0x06, (d<<2)&255)){ // PLL register D: D=5264, part 2
giuliomoro@97 172 printf("I2C error while writing PLL d part 2 : %d", d);
giuliomoro@97 173 return 1;
giuliomoro@97 174 }
giuliomoro@132 175 pllD=d;
giuliomoro@97 176 return 0;
giuliomoro@97 177 }
giuliomoro@132 178
giuliomoro@142 179 //set integer part of the numerator mutliplier of the PLL
giuliomoro@142 180 //
giuliomoro@142 181 int I2c_Codec::setPllP(short unsigned int p){
giuliomoro@142 182 if(p > 8 || p < 1){
giuliomoro@142 183 return 1;
giuliomoro@142 184 }
giuliomoro@142 185 short unsigned int bits = 0;
giuliomoro@142 186 bits |= 1 << 7; //this means PLL enabled
giuliomoro@142 187 bits |= 0b0010 << 3; // this is the reset value for Q, which is anyhow unused when PLL is active
giuliomoro@142 188 if (p == 8) // 8 is a special value: PLL P Value 000: P = 8
giuliomoro@142 189 bits = bits | 0;
giuliomoro@142 190 else
giuliomoro@142 191 bits = bits | p; // other values are written with their binary representation.
giuliomoro@142 192 if(writeRegister(0x03, bits)){ // PLL register B: j<<2
giuliomoro@142 193 printf("I2C error while writing PLL p: %d", p);
giuliomoro@142 194 return 1;
giuliomoro@142 195 }
giuliomoro@142 196 pllP = p;
giuliomoro@142 197 return 0;
giuliomoro@142 198 }
giuliomoro@142 199 int I2c_Codec::setPllR(unsigned int r){
giuliomoro@142 200 if(r > 16){ //value out of range
giuliomoro@142 201 return 1;
giuliomoro@142 202 }
giuliomoro@142 203 unsigned int bits = 0;
giuliomoro@142 204 //bits D7-D4 are for ADC and DAC overflow flags and are read only
giuliomoro@142 205 if(r == 16) // 16 is a special value: PLL R Value 0000: R = 16
giuliomoro@142 206 bits |= 0;
giuliomoro@142 207 else
giuliomoro@142 208 bits |= r; // other values are written with their binary representation.
giuliomoro@142 209 if(writeRegister(0x0B, bits)){ // PLL register B: j<<2
giuliomoro@142 210 printf("I2C error while writing PLL r: %d", r);
giuliomoro@142 211 return 1;
giuliomoro@142 212 }
giuliomoro@142 213 pllR = r;
giuliomoro@142 214 return 0;
giuliomoro@142 215 }
giuliomoro@132 216 int I2c_Codec::setAudioSamplingRate(float newSamplingRate){
giuliomoro@132 217 long int PLLCLK_IN=12000000;
giuliomoro@132 218 // f_{S(ref)} = (PLLCLK_IN × K × R)/(2048 × P)
giuliomoro@132 219 float k = ((double)(newSamplingRate * pllP * 2048.0f/(float)pllR)) / PLLCLK_IN ;
giuliomoro@147 220 int ret = setPllK(k);
giuliomoro@151 221 // printf("P: %d, R: %d, J: %d, D: %d, samplingRate= %f\n", pllP, pllR, pllJ, pllD, getAudioSamplingRate());
giuliomoro@151 222 // printf("fs_ref=%f;\n",getAudioSamplingRate());
giuliomoro@151 223 // printf("0 0 0 0 0 0\n");
giuliomoro@147 224 return ret;
giuliomoro@132 225 }
giuliomoro@132 226
giuliomoro@132 227 short unsigned int I2c_Codec::getPllJ(){
giuliomoro@132 228 return pllJ;
giuliomoro@132 229 }
giuliomoro@132 230 unsigned int I2c_Codec::getPllD(){
giuliomoro@132 231 return pllD;
giuliomoro@132 232 }
giuliomoro@142 233 unsigned int I2c_Codec::getPllR(){
giuliomoro@142 234 return pllR;
giuliomoro@142 235 }
giuliomoro@142 236 unsigned int I2c_Codec::getPllP(){
giuliomoro@142 237 return pllP;
giuliomoro@142 238 }
giuliomoro@132 239 float I2c_Codec::getPllK(){
giuliomoro@132 240 float j=getPllJ();
giuliomoro@132 241 float d=getPllD();
giuliomoro@132 242 float k=j+d/10000.0f;
giuliomoro@132 243 return k;
giuliomoro@132 244 }
giuliomoro@132 245
giuliomoro@151 246 double I2c_Codec::getAudioSamplingRate(){
giuliomoro@132 247 int pllP=1; //TODO: create get/set for pllP and pllR
giuliomoro@132 248 int pllR=1;
giuliomoro@132 249 long int PLLCLK_IN=12000000;
giuliomoro@132 250 // f_{S(ref)} = (PLLCLK_IN × K × R)/(2048 × P)
giuliomoro@132 251 float fs = (PLLCLK_IN/2048.0f) * getPllK()*pllR/(float)pllP;
giuliomoro@132 252 return fs;
giuliomoro@132 253 }
andrewm@0 254 // Set the volume of the DAC output
andrewm@0 255 int I2c_Codec::setDACVolume(int halfDbSteps)
andrewm@0 256 {
andrewm@0 257 dacVolumeHalfDbs = halfDbSteps;
andrewm@0 258 if(running)
andrewm@0 259 return writeDACVolumeRegisters(false);
andrewm@0 260
andrewm@0 261 return 0;
andrewm@0 262 }
andrewm@0 263
andrewm@0 264 // Set the volume of the DAC output
andrewm@0 265 int I2c_Codec::setADCVolume(int halfDbSteps)
andrewm@0 266 {
andrewm@0 267 adcVolumeHalfDbs = halfDbSteps;
andrewm@0 268 if(running)
andrewm@0 269 return writeADCVolumeRegisters(false);
andrewm@0 270
andrewm@0 271 return 0;
andrewm@0 272 }
andrewm@0 273
andrewm@0 274 // Update the DAC volume control registers
andrewm@0 275 int I2c_Codec::writeDACVolumeRegisters(bool mute)
andrewm@0 276 {
andrewm@0 277 int volumeBits = 0;
andrewm@0 278
andrewm@0 279 if(dacVolumeHalfDbs < 0) { // Volume is specified in half-dBs with 0 as full scale
andrewm@0 280 volumeBits = -dacVolumeHalfDbs;
andrewm@0 281 if(volumeBits > 127)
andrewm@0 282 volumeBits = 127;
andrewm@0 283 }
andrewm@0 284
andrewm@0 285 if(mute) {
andrewm@0 286 if(writeRegister(0x2B, volumeBits | 0x80)) // Left DAC volume control: muted
andrewm@0 287 return 1;
andrewm@0 288 if(writeRegister(0x2C, volumeBits | 0x80)) // Right DAC volume control: muted
andrewm@0 289 return 1;
andrewm@0 290 }
andrewm@0 291 else {
andrewm@0 292 if(writeRegister(0x2B, volumeBits)) // Left DAC volume control: not muted
andrewm@0 293 return 1;
andrewm@0 294 if(writeRegister(0x2C, volumeBits)) // Right DAC volume control: not muted
andrewm@0 295 return 1;
andrewm@0 296 }
andrewm@0 297
andrewm@0 298 return 0;
andrewm@0 299 }
andrewm@0 300
andrewm@0 301 // Update the ADC volume control registers
andrewm@0 302 int I2c_Codec::writeADCVolumeRegisters(bool mute)
andrewm@0 303 {
andrewm@0 304 int volumeBits = 0;
andrewm@0 305
andrewm@0 306 // Volume is specified in half-dBs with 0 as full scale
andrewm@0 307 // The codec uses 1.5dB steps so we divide this number by 3
andrewm@0 308 if(adcVolumeHalfDbs < 0) {
andrewm@0 309 volumeBits = -adcVolumeHalfDbs / 3;
andrewm@0 310 if(volumeBits > 8)
andrewm@0 311 volumeBits = 8;
andrewm@0 312 }
andrewm@0 313
andrewm@0 314 if(mute) {
andrewm@0 315 if(writeRegister(0x13, 0x00)) // Line1L to Left ADC control register: power down
andrewm@0 316 return 1;
andrewm@0 317 if(writeRegister(0x16, 0x00)) // Line1R to Right ADC control register: power down
andrewm@0 318 return 1;
andrewm@0 319 }
andrewm@0 320 else {
andrewm@0 321 if(writeRegister(0x13, 0x7C)) // Line1L disabled; left ADC powered up with soft step
andrewm@0 322 return 1;
andrewm@0 323 if(writeRegister(0x16, 0x7C)) // Line1R disabled; right ADC powered up with soft step
andrewm@0 324 return 1;
andrewm@0 325 if(writeRegister(0x11, (volumeBits << 4) | 0x0F)) // Line2L connected to left ADC
andrewm@0 326 return 1;
andrewm@0 327 if(writeRegister(0x12, volumeBits | 0xF0)) // Line2R connected to right ADC
andrewm@0 328 return 1;
andrewm@0 329 }
andrewm@0 330
andrewm@0 331 return 0;
andrewm@0 332 }
andrewm@0 333
andrewm@0 334 // Set the volume of the headphone output
andrewm@0 335 int I2c_Codec::setHPVolume(int halfDbSteps)
andrewm@0 336 {
andrewm@0 337 hpVolumeHalfDbs = halfDbSteps;
andrewm@0 338 if(running)
andrewm@0 339 return writeHPVolumeRegisters();
andrewm@0 340
andrewm@0 341 return 0;
andrewm@0 342 }
andrewm@0 343
andrewm@0 344
andrewm@0 345 // Update the headphone volume control registers
andrewm@0 346 int I2c_Codec::writeHPVolumeRegisters()
andrewm@0 347 {
andrewm@0 348 int volumeBits = 0;
andrewm@0 349
andrewm@0 350 if(hpVolumeHalfDbs < 0) { // Volume is specified in half-dBs with 0 as full scale
andrewm@0 351 volumeBits = -hpVolumeHalfDbs;
andrewm@0 352 if(volumeBits > 127)
andrewm@0 353 volumeBits = 127;
andrewm@0 354 }
andrewm@0 355
andrewm@0 356 if(writeRegister(0x2F, volumeBits | 0x80)) // DAC_L1 to HPLOUT register: route to HPLOUT, volume 0dB
andrewm@0 357 return 1;
andrewm@0 358 if(writeRegister(0x40, volumeBits | 0x80)) // DAC_R1 to HPROUT register: route to HPROUT, volume 0dB
andrewm@0 359 return 1;
andrewm@0 360
andrewm@0 361 return 0;
andrewm@0 362 }
andrewm@0 363
andrewm@0 364 // This tells the codec to stop generating audio and mute the outputs
andrewm@0 365 int I2c_Codec::stopAudio()
andrewm@0 366 {
andrewm@0 367 if(writeDACVolumeRegisters(true)) // Mute the DACs
andrewm@0 368 return 1;
andrewm@0 369 if(writeADCVolumeRegisters(true)) // Mute the ADCs
andrewm@0 370 return 1;
andrewm@0 371
andrewm@0 372 usleep(10000);
andrewm@0 373
andrewm@0 374 if(writeRegister(0x33, 0x0C)) // HPLOUT output level register: muted
andrewm@0 375 return 1;
andrewm@0 376 if(writeRegister(0x41, 0x0C)) // HPROUT output level register: muted
andrewm@0 377 return 1;
andrewm@0 378 if(writeRegister(0x56, 0x08)) // LEFT_LOP output level control: muted
andrewm@0 379 return 1;
andrewm@0 380 if(writeRegister(0x5D, 0x08)) // RIGHT_LOP output level control: muted
andrewm@0 381 return 1;
andrewm@0 382 if(writeRegister(0x25, 0x00)) // DAC power/driver register: power off
andrewm@0 383 return 1;
andrewm@0 384 if(writeRegister(0x03, 0x11)) // PLL register A: disable
andrewm@0 385 return 1;
andrewm@0 386 if(writeRegister(0x01, 0x80)) // Reset codec to defaults
andrewm@0 387 return 1;
andrewm@0 388
andrewm@0 389 running = false;
andrewm@0 390 return 0;
andrewm@0 391 }
andrewm@0 392
andrewm@0 393 // Write a specific register on the codec
andrewm@0 394 int I2c_Codec::writeRegister(unsigned int reg, unsigned int value)
andrewm@0 395 {
andrewm@0 396 char buf[2] = { reg & 0xFF, value & 0xFF };
andrewm@0 397
andrewm@0 398 if(write(i2C_file, buf, 2) != 2)
andrewm@0 399 {
andrewm@0 400 cout << "Failed to write register " << reg << " on codec\n";
andrewm@0 401 return 1;
andrewm@0 402 }
andrewm@0 403
andrewm@0 404 return 0;
andrewm@0 405 }
andrewm@0 406
andrewm@0 407
andrewm@0 408 int I2c_Codec::readI2C()
andrewm@0 409 {
andrewm@0 410 // Nothing to do here, we only write the registers
andrewm@0 411 return 0;
andrewm@0 412 }
andrewm@0 413
andrewm@0 414
andrewm@0 415 I2c_Codec::~I2c_Codec()
andrewm@0 416 {
andrewm@0 417 if(running)
andrewm@0 418 stopAudio();
andrewm@0 419 }
andrewm@0 420