/
singlwolf
/
Radiola-2S3
Обзор
Документация
Войти
/
singlwolf
/
Radiola-2S3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/tda7313.cpp
510 строк
10 KB
SinglWolf
Public access
27 мар 2026, 07:00
27 мар 2026, 07:00
642fcfc
Код
Авторство
О чём код?
/** * @file tda7313.cpp * * arduino-esp32 driver for TDA7313 audioprocessors * * Copyright (C) 2019 Alex Wolf <singlwolf@gmail.com> * * Licensed as is */ #include "tda7313.h" #include "Wire.h" // // #define txtPrintInfo(fmt, ...) \ do \ { \ printf(LOG_COLOR_I); \ printf(fmt, ##__VA_ARGS__); \ printf(LOG_RESET_COLOR "\n"); \ } while (0) // #define txtPrintWarn(fmt, ...) \ do \ { \ printf(LOG_COLOR_W); \ printf(fmt, ##__VA_ARGS__); \ printf(LOG_RESET_COLOR "\n"); \ } while (0) // #define txtPrintError(fmt, ...) \ do \ { \ printf(LOG_COLOR_E); \ printf(fmt, ##__VA_ARGS__); \ printf(LOG_RESET_COLOR "\n"); \ } while (0) // TDA7313::TDA7313(const char *name_space, const char *part_lbl) : _name_space(name_space), _part_lbl(part_lbl) { // Build the initial byte: Mask (0x40) | SLA 0dB (11 << 3) | Loud OFF (1 << 2) // Bits 0-1 remain 0 (Input 0) iSelector = INPUT_MASK | (3 << 3) | (1 << 2); } TDA7313::~TDA7313() { if (_i2cMutex != nullptr) { vSemaphoreDelete(_i2cMutex); _i2cMutex = nullptr; } if (_nvsMutex != nullptr) { vSemaphoreDelete(_nvsMutex); _nvsMutex = nullptr; } } // bool TDA7313::begin(uint8_t address, SemaphoreHandle_t i2cMutex) { _i2cMutex = (i2cMutex != nullptr) ? i2cMutex : xSemaphoreCreateMutex(); if (_i2cMutex == nullptr) { txtPrintError("Failed to create _i2cMutex!"); while (true) { delay(10); } } _address = address; xSemaphoreTake(_i2cMutex, portMAX_DELAY); present = true; Wire.beginTransmission(_address); if (Wire.endTransmission() != 0) { present = false; txtPrintError("Audioprocessor not found!"); } else { txtPrintInfo("Audioprocessor OK!"); } xSemaphoreGive(_i2cMutex); return !present; } bool TDA7313::init_nvs(SemaphoreHandle_t nvsMutex) { if (!present) return false; _nvsMutex = (nvsMutex != nullptr) ? nvsMutex : xSemaphoreCreateMutex(); if (_nvsMutex == nullptr) { txtPrintError("Failed to create _nvsMutex!"); while (true) { delay(10); } } return false; } // bool TDA7313::load_nvs(bool reset) { if (!present || _nvsMutex == nullptr) return false; xSemaphoreTake(_nvsMutex, portMAX_DELAY); _preferences.begin(_name_space, false, _part_lbl); uint16_t currentMagic = _preferences.getUShort("tda_magic", 0); if (reset || currentMagic != TDA_MAGIC) { memset(&_settings, 0, sizeof(_settings)); _settings.Input = 1; _settings.Volume = 9; _settings.Bass = 0; _settings.Treble = 0; _settings.AttLF = 13; _settings.AttRF = 13; size_t ret = _preferences.putBytes("tda_cfg", &_settings, sizeof(_settings)); ret &= _preferences.putUShort("tda_magic", TDA_MAGIC); if (!ret) { txtPrintError("NVS Write Fatal!"); while (true) delay(10); } } else { _preferences.getBytes("tda_cfg", &_settings, sizeof(_settings)); } _preferences.end(); xSemaphoreGive(_nvsMutex); _sync(); return false; } bool TDA7313::save_nvs() { if (!present || _nvsMutex == nullptr) return false; xSemaphoreTake(_nvsMutex, portMAX_DELAY); _preferences.begin(_name_space, false, _part_lbl); _preferences.putBytes("tda_cfg", &_settings, sizeof(_settings)); _preferences.end(); xSemaphoreGive(_nvsMutex); _sync(); return false; } bool TDA7313::erase_nvs() { if (!present || _nvsMutex == nullptr) return false; txtPrintWarn("Erasing NVS..."); xSemaphoreTake(_nvsMutex, portMAX_DELAY); _preferences.begin(_name_space, false, _part_lbl); _preferences.clear(); _preferences.putUShort("tda_magic", TDA_MAGIC); _preferences.end(); xSemaphoreGive(_nvsMutex); txtPrintInfo("Erasing NVS... success."); return false; } // bool TDA7313::isChanged() const { return (_settings != _backup); } // bool TDA7313::set_sla(uint8_t arg) { switch (arg) { case 0: iSelector |= (1 << 3); iSelector |= (1 << 4); break; case 1: iSelector &= ~(1 << 3); iSelector |= (1 << 4); break; case 2: iSelector |= (1 << 3); iSelector &= ~(1 << 4); break; case 3: iSelector &= ~(1 << 3); iSelector &= ~(1 << 4); break; default: return false; } _settings.Sla[_settings.Input - 1] = arg; // ESP_LOGV(TAG, "SLA: %.2f dB for Input: %u", SLA_PRINT[arg], _settings.Input); return _command(iSelector); } // uint8_t TDA7313::get_sla(uint8_t input) { if ((input > 0) && (input < 4)) return _settings.Sla[input - 1]; // ESP_LOGE(TAG, "Value input: %u wrong!", input); return 0xFF; } // bool TDA7313::set_mute(bool muteEnabled) { bool err = false; if (muteEnabled) { _settings.Mute = true; err = _command(0x9F); err |= _command(0xBF); err |= _command(0xDF); err |= _command(0xFF); // ESP_LOGV(TAG, "Mute Enabled"); } else { _settings.Mute = false; err = set_attlf(_settings.AttLF); err |= set_attrf(_settings.AttRF); err |= set_attlr(_settings.AttLR); err |= set_attrr(_settings.AttRR); // ESP_LOGV(TAG, "Mute Disabled"); } return err; } // bool TDA7313::get_mute() { return _settings.Mute; } // bool TDA7313::set_loud(bool loudEnabled) { if (loudEnabled) { iSelector &= ~(1 << 2); // ESP_LOGV(TAG, "Loud ON for Input: %u", _settings.Input); } else { iSelector |= (1 << 2); // ESP_LOGV(TAG, "Loud OFF for Input: %u", _settings.Input); } _settings.Loud[_settings.Input - 1] = loudEnabled; return _command(iSelector); } bool TDA7313::get_loud(uint8_t input) { if ((input > 0) && (input < 4)) return _settings.Loud[input - 1]; // ESP_LOGE(TAG, "Value input: %u wrong!", input); return false; } // bool TDA7313::set_input(uint8_t arg) { switch (arg) { case 1: iSelector &= ~(1 << 0); iSelector &= ~(1 << 1); break; case 2: iSelector |= (1 << 0); iSelector &= ~(1 << 1); break; case 3: iSelector &= ~(1 << 0); iSelector |= (1 << 1); break; default: return true; } _settings.Input = arg; bool err = _command(iSelector); // ESP_LOGV(TAG, "Input: %u", arg); err |= set_loud(_settings.Loud[arg - 1]); err |= set_sla(_settings.Sla[arg - 1]); return err; } // uint8_t TDA7313::get_input() { return _settings.Input; } // bool TDA7313::set_volume(uint8_t val) { if (val > 17) val = 17; bool err = true; if (_settings.Mute) err = set_mute(false); err |= _command((int8_t)val, VOL_MASK); if (!err) { _settings.Volume = val; } return err; } // uint8_t TDA7313::get_volume(const char **label) { if (label) *label = VOL_STR[_settings.Volume]; return _settings.Volume; } // bool TDA7313::set_bass(int8_t val) { bool err = _command(val, BASS_MASK); if (!err) { _settings.Bass = val; } return err; } // int8_t TDA7313::get_bass(const char **label) { if (label) *label = TONE_STR[_settings.Bass + 7]; return _settings.Bass; } // bool TDA7313::set_treble(int8_t val) { bool err = _command(val, TREBLE_MASK); if (!err) { _settings.Treble = val; } return err; } // int8_t TDA7313::get_treble(const char **label) { if (label) *label = TONE_STR[_settings.Treble + 7]; return _settings.Treble; } // bool TDA7313::set_attlf(uint8_t val) { if (_settings.Mute) return false; bool err = _command((int8_t)val, LF_MASK); if (!err) { _settings.AttLF = val; } return err; } // uint8_t TDA7313::get_attlf(const char **label) { if (label) *label = ATT_STR[_settings.AttLF]; return _settings.AttLF; } // bool TDA7313::set_attrf(uint8_t val) { if (_settings.Mute) return false; bool err = _command((int8_t)val, RF_MASK); if (!err) { _settings.AttRF = val; } return err; } // uint8_t TDA7313::get_attrf(const char **label) { if (label) *label = ATT_STR[_settings.AttRF]; return _settings.AttRF; } // bool TDA7313::set_attlr(uint8_t val) { if (_settings.Mute) return false; bool err = _command((int8_t)val, LR_MASK); if (!err) { if (_settings.rear_on) { // ESP_LOGV(TAG, "The Rear speakers are on."); _settings.AttLR = val; } else _settings.AttLR = 0; } return err; } // uint8_t TDA7313::get_attlr(const char **label) { if (label) *label = ATT_STR[_settings.AttLR]; return _settings.AttLR; } // bool TDA7313::set_attrr(uint8_t val) { if (_settings.Mute) return false; bool err = _command((int8_t)val, RR_MASK); if (!err) { if (_settings.rear_on) { // ESP_LOGV(TAG, "The Rear speakers are on."); _settings.AttRR = val; } else _settings.AttRR = 0; } return err; } // uint8_t TDA7313::get_attrr(const char **label) { if (label) *label = ATT_STR[_settings.AttRR]; return _settings.AttRR; } // bool TDA7313::set_rear(bool rear_on) { bool err = false; _settings.rear_on = rear_on; return err; } // bool TDA7313::get_rear() { return _settings.rear_on; } // bool TDA7313::_command(uint8_t cmd) { bool ret = false; if (!present || _i2cMutex == nullptr) return ret; xSemaphoreTake(_i2cMutex, portMAX_DELAY); Wire.beginTransmission(_address); Wire.write(cmd); if (Wire.endTransmission(true) != 0) { ret = true; } xSemaphoreGive(_i2cMutex); return ret; } // bool TDA7313::_command(int8_t val, uint8_t mask) { uint8_t cmd = 0; if ((mask | 0x10) == 0x70) // BASS and TREBLE { if (val < -7) val = -7; if (val > 7) val = 7; cmd = (val == 0) ? 0x07 : (val > 0 ? 7 - val : 7 + abs(val)); } else if (mask >= 0x80) // ATT { if (val > 13) val = 13; cmd = ATT_MASK[val]; } else if (mask == 0x00) // VOLUME { if (val > 17) val = 17; cmd = VOLUME_MASK[val]; } return _command(mask | cmd); } // void TDA7313::_sync() { _backup = _settings; }