Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SPI.h>
- #include <Wire.h>
- #include <EEPROM.h>
- const byte
- STB = 6,
- MUTE = 5,
- TDA = 68;
- byte
- headunitSourceIndex = 0, // 0,1,2
- headunitMasterVolume = 0, // 0 to 63
- headunitFrontLeft = 0,
- headunitFrontRight = 0,
- headunitRearLeft = 0,
- headunitRearRight = 0;
- int
- headunitBass = 0,
- headunitTreble = 0;
- volatile unsigned long
- lastChangeTimestamp = 0,
- lastConfigTimestamp = 0;
- bool muteSequenceFound = false;
- static byte pml009State[17] = {
- 0x0B, 0x58, 0x58, 0x00,
- 0x00, 0x00, 0xB0, 0x00,
- 0x00, 0x10, 0x00, 0x40,
- 0x40, 0xC0, 0x86, 0xC0,
- 0x86
- };
- // 0 to 63 with a 1.25 db step,
- // rounded to nearest integer for PML009A
- const byte tda7303Decibels[64] = {
- 0,1,3,4,5,6,8,9,10,11,13,14,15,
- 16,18,19,20,21,23,24,25,26,28,29,
- 30,31,33,34,35,36,38,39,40,41,43,
- 44,45,46,48,49,50,51,53,54,55,56,
- 58,59,60,61,63,64,65,66,68,69,70,
- 71,73,74,75,76,78,79
- };
- // Loudness: low (PML009A loudness [15-0] against TDA7303 main volume index [0-63], reversed)
- const byte loudnessMode4[64] = {
- 13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,12,12,
- 12,12,12,11,11,11,11,10,10,10,
- 10,9,8,8,7,6,6,5,5,4,3,3,2,2,2,
- 1,1,1,0,0,0,0,0,0
- };
- // Loudness: mid
- const byte loudnessMode11[64] = {
- 13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,13,13,
- 13,12,11,11,10,9,9,8,8,7,6,6,5,
- 4,4,3,3,2,1,1,0,0,0,0
- };
- // Loudness: high
- const byte loudnessMode15[64] = {
- 15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,
- 15,14,14,14,14,14,14,14,14,14,
- 14,13,12,12,11,10,10,9,9,8,7,7,
- 6,5,5,4,4,3,2,2,1,0,0,0
- };
- void setup() {
- // save config
- if (EEPROM.read(0) == 2) {
- for (int i = 3; i <= 9; i++) {
- pml009State[i] = EEPROM.read(i);
- }
- }
- Serial.begin(115200);
- pinMode(STB, OUTPUT);
- pinMode(MUTE, OUTPUT);
- SPI.begin();
- Wire.begin(TDA);
- Wire.onReceive(tda7303Cmd);
- }
- int inputPos = 0;
- unsigned long inputTimer = 0;
- void loop() {
- if (lastChangeTimestamp > 0 && millis() - lastChangeTimestamp > 30) {
- digitalWrite(MUTE, LOW);
- pml009State[0] = headunitSourceIndex | 0b10000; // source and gain adjustment
- // TDA7303 has a wide range main volume control from 0 to -80db (1.25 db steps),
- // per-channel attenuators and automatic loudness control (on/off),
- // whereas PML009A has a narrower primary adjustment from 0 to -31db (1 db steps),
- // deeper per-channel attenuators (-63 to 0 db w/ mute, 1 db steps) and
- // manual loudness control (-15 to 0 db att 1 db steps w/ mode switches).
- //
- // The following code maps TDA7303 to PML009A state using lookups
- // defined above (obtained by sniffing DEH-P4500R commands to PML009A and
- // recalculated to match nearest matching decibel target value).
- byte dbTarget = tda7303Decibels[headunitMasterVolume];
- byte loudness = 0;
- switch(pml009State[6] >> 4) {
- case 4:
- loudness = loudnessMode4[63 - headunitMasterVolume];
- break;
- case 11:
- loudness = loudnessMode11[63 - headunitMasterVolume];
- break;
- case 15:
- loudness = loudnessMode15[63 - headunitMasterVolume];
- break;
- }
- // increase gain against volume drop in the loudness contour
- dbTarget -= loudness;
- // set loudness gain/att bits
- pml009State[6] = (pml009State[6] & 0b11110000) | loudness;
- // apply balance/fader
- byte fl = max(0, dbTarget + headunitFrontLeft);
- byte fr = max(0, dbTarget + headunitFrontRight);
- byte rl = max(0, dbTarget + headunitRearLeft);
- byte rr = max(0, dbTarget + headunitRearRight);
- // split dbTarget into primary and secondary controls
- byte primaryLeft = min(31, min(fl, rl));
- byte primaryRight = min(31, min(fr, rr));
- pml009State[01] = primaryLeft | 0b01000000;
- pml009State[02] = primaryRight | 0b01000000;
- pml009State[11] = min(63, fl - primaryLeft) | 0b01000000;
- pml009State[12] = min(63, fr - primaryRight) | 0b01000000;
- pml009State[13] = min(63, rl - primaryLeft) | 0b11000000;
- pml009State[15] = min(63, rr - primaryRight) | 0b11000000;
- auto commonSecLeft = min(fl, rl) - primaryLeft;
- auto commonSecRight = min(fr, rr) - primaryRight;
- pml009State[14] = min(63, commonSecLeft + 7 - headunitBass * 2 + max(0, min(headunitBass, headunitBass - commonSecLeft / 2))) | 0b10000000;
- pml009State[16] = min(63, commonSecRight + 7 - headunitBass * 2 + max(0, min(headunitBass, headunitBass - commonSecRight / 2))) | 0b10000000;
- // the purpose of the above binary constants is unknown
- SPI.beginTransaction(SPISettings(100000, LSBFIRST, SPI_MODE3));
- digitalWrite(STB, HIGH);
- for (int i = 0; i < 17; i++) {
- SPI.transfer(pml009State[i]);
- }
- digitalWrite(STB, LOW);
- SPI.endTransaction();
- Serial.write(0xFF); // sync
- Serial.write(pml009State + 3, 7);
- lastChangeTimestamp = 0;
- }
- while(Serial.available()) {
- if (millis() - inputTimer < 100 && inputPos > 0) {
- pml009State[inputPos++] = Serial.read();
- if (inputPos > 9) {
- inputPos = 0;
- inputTimer = 0;
- lastChangeTimestamp = millis();
- lastConfigTimestamp = millis();
- }
- }
- else if (Serial.read() == 0xFF) { // sync
- inputPos = 3;
- inputTimer = millis();
- }
- }
- if ((muteSequenceFound && lastConfigTimestamp > 0) || millis() - lastConfigTimestamp > 30000) {
- muteSequenceFound = false;
- lastConfigTimestamp = 0;
- // save config
- EEPROM.update(0, 2);
- for (int i = 3; i <= 9; i++) {
- EEPROM.update(i, pml009State[i]);
- }
- }
- }
- void tda7303Cmd(int byteCount) {
- while(1 < Wire.available());
- byte cmd = Wire.read();
- // mute sequence detection.
- // we're looking for these four bytes close to each other
- if (cmd == 0x9F || cmd == 0xBF || cmd == 0xDf || cmd == 0xFF) {
- muteSequenceFound = true;
- }
- if (cmd <= B00111111) {
- headunitMasterVolume = cmd;
- }
- else if (cmd <= B01011111) {
- headunitSourceIndex = cmd & 0b11;
- digitalWrite(MUTE, HIGH);
- }
- else if (cmd <= B01101111) {
- headunitBass = (cmd & 0b1000 ? +1 : -1) * (7 - cmd & 0b111);
- }
- else if (cmd <= B01111111) {
- headunitTreble = (cmd & 0b1000 ? +1 : -1) * (7 - cmd & 0b111);
- }
- else if (cmd <= B10011111) {
- headunitFrontLeft = cmd & 0b11111;
- }
- else if (cmd <= B10111111) {
- headunitFrontRight = cmd & 0b11111;
- }
- else if (cmd <= B11011111) {
- headunitRearLeft = cmd & 0b11111;
- }
- else if (cmd <= B11111111) {
- headunitRearRight = cmd & 0b11111;
- }
- lastChangeTimestamp = millis();
- //char buf[5] = { 0, 0, 0, 0, 0 };
- //sprintf(buf, " %x", cmd);
- //Serial.println(buf);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement