feat(radio): TAS2505 driver
This commit is contained in:
committed by
Malte Langermann
parent
f22b9c0658
commit
9f8e2e313e
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "tas2505.h"
|
||||
#include "stm32_i2s.h"
|
||||
#include "timers_driver.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define TAS2505_NDAC_ENABLE (1U << 7)
|
||||
#define TAS2505_MDAC_ENABLE (1U << 7)
|
||||
#define TAS2505_MASTER_REF_ENABLE (1U << 4)
|
||||
#define TAS2505_HPL_OUT_UP (1U << 5)
|
||||
#define TAS2505_MIXER_P_TO_HP (1U << 2)
|
||||
|
||||
static int tas2505_i2c_write(tas2505_t* dev, uint16_t reg, uint8_t value)
|
||||
{
|
||||
if (!dev->addr) return -1;
|
||||
return i2c_write(dev->bus, dev->addr, reg, 1, (uint8_t*)&value, sizeof(value));
|
||||
}
|
||||
|
||||
static int tas2505_write_reg(tas2505_t* dev, uint16_t reg, uint8_t value)
|
||||
{
|
||||
uint8_t page = reg >> 8;
|
||||
if (tas2505_i2c_write(dev, 0, page) < 0) return -1;
|
||||
return tas2505_i2c_write(dev, reg & 0xFF, value);
|
||||
}
|
||||
|
||||
static void tas2505_delay(uint32_t ms)
|
||||
{
|
||||
uint32_t start = timersGetMsTick();
|
||||
while (timersGetMsTick() - start < ms) {}
|
||||
}
|
||||
|
||||
int tas2505_probe(tas2505_t* dev, etx_i2c_bus_t bus, uint16_t addr)
|
||||
{
|
||||
dev->bus = 0;
|
||||
dev->addr = 0;
|
||||
|
||||
if (i2c_init(bus) < 0) {
|
||||
TRACE("TAS2505 bus init error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i2c_dev_ready(bus, addr) < 0) {
|
||||
TRACE("TAS2505 device init error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->bus = bus;
|
||||
dev->addr = addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tas2505_init(tas2505_t* dev)
|
||||
{
|
||||
// software reset
|
||||
if (tas2505_write_reg(dev, TAS2505_RESET, 1) < 0) return -1;
|
||||
tas2505_delay(2);
|
||||
|
||||
if (dev->hp_drv < TAS2505_HP_DRV_MIN) {
|
||||
dev->hp_drv = TAS2505_HP_DRV_MIN;
|
||||
} else if (dev->hp_drv > TAS2505_HP_DRV_MAX) {
|
||||
dev->hp_drv = TAS2505_HP_DRV_MAX;
|
||||
}
|
||||
|
||||
const struct {
|
||||
uint16_t reg;
|
||||
uint8_t value;
|
||||
} params[] = {
|
||||
{TAS2505_LDO_CTRL, 0},
|
||||
{TAS2505_CLKMUX, 0}, // MCLK -> CODEC_CLKIN
|
||||
|
||||
{TAS2505_NDAC, (uint8_t)(TAS2505_NDAC_ENABLE | dev->ndac)},
|
||||
{TAS2505_MDAC, (uint8_t)(TAS2505_MDAC_ENABLE | dev->mdac)},
|
||||
{TAS2505_DOSRLSB, (uint8_t)(dev->dosr & 0xFF)},
|
||||
{TAS2505_DOSRMSB, (uint8_t)(dev->dosr >> 8)},
|
||||
|
||||
{TAS2505_IFACE1, 0}, // I2S, 16bit, BCLK in, WCLK in
|
||||
{TAS2505_IFACE2, 0}, // Data slot offset 00
|
||||
{TAS2505_DACINSTRSET, 0b00000010}, // PRB_P2
|
||||
|
||||
{TAS2505_DACVOL, (uint8_t)dev->dac_vol},
|
||||
{TAS2505_DACSETUP1, 0b10010100}, // DAC on, left channel
|
||||
{TAS2505_DACSETUP2, 0b00000100}, // DAC unmuted
|
||||
|
||||
{TAS2505_REF_POR_LDO_BGAP_CTRL, TAS2505_MASTER_REF_ENABLE},
|
||||
{TAS2505_HPL_OUT, TAS2505_HPL_OUT_UP}, // HPL output ON
|
||||
|
||||
{TAS2505_COMMON_MODE, 0}, // CM 0.9V
|
||||
{TAS2505_HP_ROUTING, TAS2505_MIXER_P_TO_HP}, // enable HP
|
||||
{TAS2505_HP_DRIVER, (uint8_t)(dev->hp_drv & 0x3F)},
|
||||
{TAS2505_HP_VOL, dev->hp_vol},
|
||||
|
||||
{TAS2505_SPKVOL1, dev->spk_vol},
|
||||
{TAS2505_SPKVOL2, dev->spk_drv},
|
||||
{TAS2505_SPKAMPCTRL1, 0b00000010}, // Spkr ON
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < DIM(params); i++) {
|
||||
uint16_t reg = params[i].reg;
|
||||
uint8_t value = params[i].value;
|
||||
if (tas2505_write_reg(dev, reg, value) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/i2c_driver.h"
|
||||
|
||||
#define TAS2505_REG(page, reg) ((page << 8) + reg)
|
||||
|
||||
#define TAS2505_PAGECTL TAS2505_REG(0, 0)
|
||||
#define TAS2505_RESET TAS2505_REG(0, 1)
|
||||
#define TAS2505_CLKMUX TAS2505_REG(0, 4)
|
||||
#define TAS2505_PLLPR TAS2505_REG(0, 5)
|
||||
#define TAS2505_PLLJ TAS2505_REG(0, 6)
|
||||
#define TAS2505_PLLDMSB TAS2505_REG(0, 7)
|
||||
#define TAS2505_PLLDLSB TAS2505_REG(0, 8)
|
||||
#define TAS2505_NDAC TAS2505_REG(0, 11)
|
||||
#define TAS2505_MDAC TAS2505_REG(0, 12)
|
||||
#define TAS2505_DOSRMSB TAS2505_REG(0, 13)
|
||||
#define TAS2505_DOSRLSB TAS2505_REG(0, 14)
|
||||
#define TAS2505_IFACE1 TAS2505_REG(0, 27)
|
||||
#define TAS2505_IFACE2 TAS2505_REG(0, 28)
|
||||
#define TAS2505_IFACE3 TAS2505_REG(0, 29)
|
||||
#define TAS2505_BCLKNDIV TAS2505_REG(0, 30)
|
||||
#define TAS2505_DACFLAG1 TAS2505_REG(0, 37)
|
||||
#define TAS2505_DACFLAG2 TAS2505_REG(0, 38)
|
||||
#define TAS2505_STICKYFLAG1 TAS2505_REG(0, 42)
|
||||
#define TAS2505_INTFLAG1 TAS2505_REG(0, 43)
|
||||
#define TAS2505_STICKYFLAG2 TAS2505_REG(0, 44)
|
||||
#define TAS2505_INTFLAG2 TAS2505_REG(0, 46)
|
||||
#define TAS2505_DACINSTRSET TAS2505_REG(0, 60)
|
||||
#define TAS2505_DACSETUP1 TAS2505_REG(0, 63)
|
||||
#define TAS2505_DACSETUP2 TAS2505_REG(0, 64)
|
||||
#define TAS2505_DACVOL TAS2505_REG(0, 65)
|
||||
#define TAS2505_REF_POR_LDO_BGAP_CTRL TAS2505_REG(1, 1)
|
||||
#define TAS2505_LDO_CTRL TAS2505_REG(1, 2)
|
||||
#define TAS2505_PLAYBACKCONF1 TAS2505_REG(1, 3)
|
||||
#define TAS2505_HPL_OUT TAS2505_REG(1, 9)
|
||||
#define TAS2505_COMMON_MODE TAS2505_REG(1, 10)
|
||||
#define TAS2505_HP_ROUTING TAS2505_REG(1, 12)
|
||||
#define TAS2505_HP_DRIVER TAS2505_REG(1, 16)
|
||||
#define TAS2505_HP_VOL TAS2505_REG(1, 22)
|
||||
#define TAS2505_MIXER_CTRL TAS2505_REG(1, 24)
|
||||
#define TAS2505_SPKAMPCTRL1 TAS2505_REG(1, 45)
|
||||
#define TAS2505_SPKVOL1 TAS2505_REG(1, 46)
|
||||
#define TAS2505_SPKVOL2 TAS2505_REG(1, 48)
|
||||
#define TAS2505_DACANLGAINFLAG TAS2505_REG(1, 63)
|
||||
|
||||
#define TAS2505_SPK_DRV_MUTED (0U << 4)
|
||||
#define TAS2505_SPK_DRV_6_DB (1U << 4)
|
||||
#define TAS2505_SPK_DRV_12_DB (2U << 4)
|
||||
#define TAS2505_SPK_DRV_18_DB (3U << 4)
|
||||
#define TAS2505_SPK_DRV_24_DB (4U << 4)
|
||||
#define TAS2505_SPK_DRV_32_DB (5U << 4)
|
||||
|
||||
#define TAS2505_HP_DRV_MIN -5
|
||||
#define TAS2505_HP_DRV_MAX 29
|
||||
|
||||
typedef struct {
|
||||
etx_i2c_bus_t bus;
|
||||
uint16_t addr;
|
||||
|
||||
uint8_t ndac;
|
||||
uint8_t mdac;
|
||||
uint16_t dosr;
|
||||
|
||||
int8_t dac_vol;
|
||||
|
||||
int8_t hp_drv;
|
||||
uint8_t hp_vol;
|
||||
|
||||
uint8_t spk_drv;
|
||||
uint8_t spk_vol;
|
||||
|
||||
} tas2505_t;
|
||||
|
||||
int tas2505_probe(tas2505_t* dev, etx_i2c_bus_t bus, uint16_t addr);
|
||||
int tas2505_init(tas2505_t* dev);
|
||||
Reference in New Issue
Block a user