This commit is contained in:
cfif 2024-12-04 13:10:49 +03:00
commit ff926fc784
5 changed files with 455 additions and 0 deletions

126
Inc/max9860.h Normal file
View File

@ -0,0 +1,126 @@
//
// Created by zemon on 24.06.2021.
//
#ifndef MAX_9860_H
#define MAX_9860_H
#include "I2cIO.h"
#include "stdbool.h"
#include "max9860_enums.h"
#define MAX9860_TOTAL_REG_COUNT 0x11
typedef struct {
MAX9860_MCLK_TO_PCLK_PrescalerMode MCLK_TO_PCLK_Prescaler;
MAX9860_IntegerClockMode IntegerClockMode;
bool EXACTLY_16KHZ;
bool PLL_Enable; //enable core clock as divided mclk
uint16_t LRCLK_Driver; //clock divider, depends on mclk and sample rate (lrclk)
} MAX9860_ClocksState;
typedef struct {
bool MasterMode;
bool LRCLK_Invert;
bool DAC_BCLK_Invert;
bool DAC_DelayMode;
bool SDOUT_HighImpedanceMode;
bool TDM_ModeSelect;
bool ADC_BCLK_Invert;
bool ADC_Delay_Mode;
bool StereoEnable;
uint8_t BCLK_Select;
} MAX9860_AudioInterfaceState;
typedef struct {
MAX9860_DigitalFilterType ADC_DigitalFilter;
MAX9860_DigitalFilterType DAC_DigitalFilter;
} MAX9860_DigitalFiltersState;
//range from +3dB to -90dB
#define MAX9860_DAC_LEVEL_ADJUST__DB(DB_VALUE) (DB_VALUE>3?0:(DB_VALUE<-90?0xBC:(6-(DB_VALUE*2))))
//range from +3dB to -12dB
#define MAX9860_ADC_OUTPUT_LEVEL__DB(DB_VALUE) (DB_VALUE>3?0:(DB_VALUE<-12?0xF:(3-DB_VALUE)))
#define MAX9860_DAC_GAIN__0 0b00
#define MAX9860_DAC_GAIN__PLUS_6DB 0b01
#define MAX9860_DAC_GAIN__PLUS_12DB 0b10
#define MAX9860_DAC_GAIN__PLUS_18DB 0b11
#define MAX9860_SIDETONE_DISABLED 0b0
typedef struct {
uint8_t DAC_LevelAdjust;
uint8_t ADC_OutputLevelRight;
uint8_t ADC_OutputLevelLeft;
uint8_t DAC_Gain;
uint8_t Sidetone;
} MAX9860_DigitalLevelControlState;
#define MAX9860_MIC_PREAMP_GAIN__DISABLED 0b00
#define MAX9860_MIC_PREAMP_GAIN__0 0b01
#define MAX9860_MIC_PREAMP_GAIN__PLUS_20 0b10
#define MAX9860_MIC_PREAMP_GAIN__PLUS_30 0b11
//range form 0 to +20dB
#define MAX9860_MIC_PROGRAMMABLE_GAIN_PLUS_DB(DB_VALUE) (DB_VALUE<0?0x20:(DB_VALUE>20?0:(20-DB_VALUE)))
typedef struct {
uint8_t MicrophonePreampGain;
uint8_t MicrophoneProgrammableGain;
} MAX9860_MicrophoneInputState;
typedef struct {
MAX9860_NoiseGateSignalSource NoiseGateSource;
MAX9860_AutomaticGainControlReleaseTime ReleaseTime;
MAX9860_AutomaticGainControlAttackTime AttackTime;
MAX9860_AutomaticGainControlHoldTime HoldTime;
uint8_t NoiseGateThreshold;
uint8_t AutomaticGainControlThreshold;
} MAX9860_AutomaticGainControlAndNoiseGateState;
typedef struct {
bool FullPowerOn;
bool DAC_Enabled;
bool ADC_EnabledLeft;
bool ADC_EnabledRight;
} MAX9860_PowerManagementState;
typedef struct {
MAX9860_DigitalFiltersState filters;
MAX9860_DigitalLevelControlState levelControl;
MAX9860_MicrophoneInputState microphoneGains;
MAX9860_AutomaticGainControlAndNoiseGateState autoGainAndNoiseGate;
} MAX9860_ComplexAudioConfig;
uint16_t xAudioCodecDebugGetRAW(tI2cIO *i2c, uint8_t *raw);
uint16_t xAudioCodecDebugSetRAW(tI2cIO *i2c, uint8_t *raw);
uint16_t xAudioCodecReadStatus(tI2cIO *i2c, uint8_t statuses[3]);
bool xAudioCodecSetClock(tI2cIO *i2c, MAX9860_ClocksState clocksState);
bool xAudioCodecSetInterface(tI2cIO *i2c, MAX9860_AudioInterfaceState interface);
bool xAudioCodecSetDigitalFilters(tI2cIO *i2c, MAX9860_DigitalFiltersState filters);
bool xAudioCodecSetDigitalLevelControls(tI2cIO *i2c, MAX9860_DigitalLevelControlState levels);
bool xAudioCodecSetMicrophoneInput(tI2cIO *i2c, MAX9860_MicrophoneInputState micro);
bool xAudioCodecSetAutomaticGainControlAndNoiseGate(
tI2cIO *i2c, MAX9860_AutomaticGainControlAndNoiseGateState values
);
bool xAudioCodecSetPowerManagement(tI2cIO *i2c, MAX9860_PowerManagementState values);
#endif //MAX_9860_H

73
Inc/max9860_enums.h Normal file
View File

@ -0,0 +1,73 @@
//
// Created by zemon on 25.06.2021.
//
#ifndef STM_MAIN_WORKSPACE_MAX9860_ENUMS_H
#define STM_MAIN_WORKSPACE_MAX9860_ENUMS_H
typedef enum {
MAX9860_PRESCALER_DISABLE_CLOCK = 0b00,
MAX9860_PRESCALER_MCLK_10_TO_20_MHZ = 0b01,
MAX9860_PRESCALER_MCLK_20_TO_40_MHZ = 0b10,
MAX9860_PRESCALER_MCLK_MORE_40_MHZ = 0b11,
} MAX9860_MCLK_TO_PCLK_PrescalerMode;
typedef enum {
MAX9860_ICM_NORMAL = 0b00,
MAX9860_ICM_PCLK_IS_12MHZ = 0b01,
MAX9860_ICM_PCLK_IS_13MHZ = 0b10,
MAX9860_ICM_PCLK_IS_19_2MHZ = 0b11,
} MAX9860_IntegerClockMode;
typedef enum {
MAX9860_DIGITAL_FILTER_DISABLED = 0x0,
MAX9860_DIGITAL_FILTER_ELLIPTICAL_16KHZ = 0x1,
MAX9860_DIGITAL_FILTER_BUTTERWORTH_16KHZ = 0x2,
MAX9860_DIGITAL_FILTER_ELLIPTICAL_8KHZ = 0x3,
MAX9860_DIGITAL_FILTER_BUTTERWORTH_8KHZ = 0x4,
MAX9860_DIGITAL_FILTER_BUTTERWORTH_48KHZ = 0x5,
} MAX9860_DigitalFilterType;
typedef enum {
MAX9860_NOISE_GATE_SOURCE_LEFT_ONLY = 0x0,
MAX9860_NOISE_GATE_SOURCE_SUM_BOTH = 0x1,
} MAX9860_NoiseGateSignalSource;
typedef enum {
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_78_MS = 0x000,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_156_MS = 0x001,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_312_MS = 0x010,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_652_MS = 0x011,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_1250_MS = 0x100,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_2500_MS = 0x101,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_5_S = 0x110,
MAX9860_AUTOMATIC_GAIN_CONTROL_RELEASE_TIME_10_S = 0x111,
} MAX9860_AutomaticGainControlReleaseTime;
typedef enum {
MAX9860_AUTOMATIC_GAIN_CONTROL_ATTACK_TIME_3_MS = 0x00,
MAX9860_AUTOMATIC_GAIN_CONTROL_ATTACK_TIME_12_MS = 0x01,
MAX9860_AUTOMATIC_GAIN_CONTROL_ATTACK_TIME_50_MS = 0x10,
MAX9860_AUTOMATIC_GAIN_CONTROL_ATTACK_TIME_200_MS = 0x11,
} MAX9860_AutomaticGainControlAttackTime;
typedef enum {
MAX9860_AUTOMATIC_GAIN_CONTROL_DISABLED = 0x00,
MAX9860_AUTOMATIC_GAIN_CONTROL_HOLD_TIME_50_MS = 0x01,
MAX9860_AUTOMATIC_GAIN_CONTROL_HOLD_TIME_100_MS = 0x10,
MAX9860_AUTOMATIC_GAIN_CONTROL_HOLD_TIME_400_MS = 0x11,
} MAX9860_AutomaticGainControlHoldTime;
typedef enum{
MAX9860_FULL_SHUTDOWN = 0x0,
MAX9860_POWER_ON = 0x1,
}MAX9860_SoftwareShutdownValue;
#endif //STM_MAIN_WORKSPACE_MAX9860_ENUMS_H

49
Inc/max9860_regs.h Normal file
View File

@ -0,0 +1,49 @@
//
// Created by zemon on 24.06.2021.
//
#ifndef STM_MAIN_WORKSPACE_MAX9860_REGS_H
#define STM_MAIN_WORKSPACE_MAX9860_REGS_H
#define MAX9860_ADDRESS_READ 0x21
#define MAX9860_ADDRESS_WRITE 0x20
#define MAX9860_IO_TIMEOUT 1000
//STATUS/INTERRUPT
#define MAX9860_REG_STATUS_INTERRUPTS_VALUES 0x00
#define MAX9860_REG_STATUS_NOISE_GAIN 0x01
#define MAX9860_REG_STATUS_INTERRUPTS_ENABLED 0x02
//CLOCK CONTROL
#define MAX9860_REG_SYSTEM_CLOCK 0x03
#define MAX9860_REG_STEREO_AUDIO_CLOCK_CONTROL_HIGH 0x04
#define MAX9860_REG_STEREO_AUDIO_CLOCK_CONTROL_LOW 0x05
//DIGITAL AUDIO INTERFACE TODO REDUCE UNUSED
#define MAX9860_REG_INTERFACE 0x06
#define MAX9860_REG_INTERFACE_FIRST 0x06
#define MAX9860_REG_INTERFACE_SECOND 0x07
//DIGITAL FILTERING
#define MAX9860_REG_VOICE_FILTERING 0x08
//DIGITAL LEVEL CONTROL
#define MAX9860_REG_DAC_ATTENUATION 0x09 //DAC - digital analog converter
#define MAX9860_REG_ADC_OUTPUT_LEVEL 0x0A //ADC - analog digital converter
#define MAX9860_REG_DAC_GAIN_AND_SIDETONE 0x0B
//MICROPHONE LEVEL CONTROL
#define MAX9860_REG_MICROPHONE_GAIN 0x0C
//MICROPHONE AUTOMATIC GAIN CONTROL
#define MAX9860_REG_MICROPHONE_AGC 0x0E //AGC -automatic gain control
#define MAX9860_REG_MICROPHONE_AGC_AND_NOISE_GATE 0x0F
//POWER MANAGEMENT
#define MAX9860_REG_SYSTEM_SHUTDOWN 0x10
#endif //STM_MAIN_WORKSPACE_MAX9860_REGS_H

190
Src/audio_codec.c Normal file
View File

@ -0,0 +1,190 @@
//
// Created by zemon on 24.06.2021.
//
#include <memory.h>
#include "max9860.h"
#include "max9860_regs.h"
bool xAudioCodecSetClock(tI2cIO *i2c, MAX9860_ClocksState clocksState) {
uint8_t I2C_Out[4] = {0};
I2C_Out[0] = MAX9860_REG_SYSTEM_CLOCK;
I2C_Out[1] = 0x00 |
((clocksState.MCLK_TO_PCLK_Prescaler & 0b11) << 4) |
((clocksState.IntegerClockMode & 0b11) << 1) |
((clocksState.EXACTLY_16KHZ & 0b1) << 0);
I2C_Out[2] = 0x00 |
((clocksState.PLL_Enable & 0b1) << 7) |
(((uint8_t) (clocksState.LRCLK_Driver >> 8)) & 0b01111111);
I2C_Out[3] = ((uint8_t) (clocksState.LRCLK_Driver & 0xFF));
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 4, MAX9860_IO_TIMEOUT) == 4;
}
bool xAudioCodecSetInterface(tI2cIO *i2c, MAX9860_AudioInterfaceState interface) {
uint8_t I2C_Out[3] = {0};
I2C_Out[0] = MAX9860_REG_INTERFACE;
I2C_Out[1] = 0x00 |
((interface.MasterMode & 0b1) << 7) |
((interface.LRCLK_Invert & 0b1) << 6) |
((interface.DAC_BCLK_Invert & 0b1) << 5) |
((interface.DAC_DelayMode & 0b1) << 4) |
((interface.SDOUT_HighImpedanceMode & 0b1) << 3) |
((interface.TDM_ModeSelect & 0b1) << 2);
I2C_Out[2] = 0x00 |
((interface.ADC_BCLK_Invert & 0b1) << 5) |
((interface.ADC_Delay_Mode & 0b1) << 4) |
((interface.StereoEnable & 0b1) << 3) |
((interface.BCLK_Select & 0b111) << 0);
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 3, MAX9860_IO_TIMEOUT) == 3;
}
bool xAudioCodecSetDigitalFilters(tI2cIO *i2c, MAX9860_DigitalFiltersState filters) {
uint8_t I2C_Out[2] = {0};
I2C_Out[0] = MAX9860_REG_VOICE_FILTERING;
I2C_Out[1] = 0x00 |
((filters.ADC_DigitalFilter & 0b1111) << 4) |
((filters.DAC_DigitalFilter & 0b1111) << 0);
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 2, MAX9860_IO_TIMEOUT) == 2;
}
bool xAudioCodecSetDigitalLevelControls(tI2cIO *i2c, MAX9860_DigitalLevelControlState levels) {
uint8_t I2C_Out[4] = {0};
I2C_Out[0] = MAX9860_REG_DAC_ATTENUATION;
I2C_Out[1] = levels.DAC_LevelAdjust;
I2C_Out[2] = 0x00 |
((levels.ADC_OutputLevelRight & 0b1111) << 4) |
((levels.ADC_OutputLevelLeft & 0b1111) << 0);
I2C_Out[3] = 0x00 |
((levels.DAC_Gain & 0b11) << 5) |
((levels.Sidetone & 0b11111) << 0);
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 4, MAX9860_IO_TIMEOUT) == 4;
}
bool xAudioCodecSetMicrophoneInput(tI2cIO *i2c, MAX9860_MicrophoneInputState micro) {
uint8_t I2C_Out[2] = {0};
I2C_Out[0] = MAX9860_REG_MICROPHONE_GAIN;
I2C_Out[1] = 0x00 |
((micro.MicrophonePreampGain & 0b11) << 5) |
((micro.MicrophoneProgrammableGain & 0b11111) << 0);
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 2, MAX9860_IO_TIMEOUT) == 2;
}
bool xAudioCodecSetAutomaticGainControlAndNoiseGate(
tI2cIO *i2c,
MAX9860_AutomaticGainControlAndNoiseGateState values
) {
uint8_t I2C_Out[3] = {0};
I2C_Out[0] = MAX9860_REG_MICROPHONE_AGC;
I2C_Out[1] = 0x00 |
((values.NoiseGateSource & 0b1) << 7) |
((values.ReleaseTime & 0b111) << 4) |
((values.AttackTime & 0b11) << 2) |
((values.HoldTime & 0b11) << 0);
I2C_Out[2] = 0x00 |
((values.NoiseGateThreshold & 0b1111) << 4) |
((values.AutomaticGainControlThreshold & 0b1111) << 0);
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 3, MAX9860_IO_TIMEOUT) == 3;
}
bool xAudioCodecSetPowerManagement(tI2cIO *i2c, MAX9860_PowerManagementState values) {
uint8_t I2C_Out[3] = {0};
I2C_Out[0] = MAX9860_REG_SYSTEM_SHUTDOWN;
I2C_Out[1] = 0x00 |
((values.FullPowerOn & 0b1) << 7) |
((values.DAC_Enabled & 0b1) << 3) |
((values.ADC_EnabledLeft & 0b1) << 1) |
((values.ADC_EnabledRight & 0b1) << 0);
return I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 2, MAX9860_IO_TIMEOUT) == 2;
}
uint16_t xAudioCodecDebugGetRAW(tI2cIO *i2c, uint8_t *raw) {
return I2cRead(i2c, MAX9860_ADDRESS_READ, raw, MAX9860_TOTAL_REG_COUNT, MAX9860_IO_TIMEOUT);
}
uint16_t xAudioCodecDebugSetRAW(tI2cIO *i2c, uint8_t *raw) {
return I2cRead(i2c, MAX9860_ADDRESS_WRITE, raw, MAX9860_TOTAL_REG_COUNT, MAX9860_IO_TIMEOUT);
}
uint16_t xAudioCodecReadStatus(tI2cIO *i2c, uint8_t statuses[3]) {
uint8_t I2C_Out[4] = {0};
I2C_Out[0] = MAX9860_REG_STATUS_INTERRUPTS_VALUES;
uint16_t write = I2cWrite(i2c, MAX9860_ADDRESS_WRITE, I2C_Out, 1, MAX9860_IO_TIMEOUT);
uint16_t reed = I2cRead(i2c, MAX9860_ADDRESS_READ, I2C_Out + 1, 3, MAX9860_IO_TIMEOUT);
memcpy(statuses, I2C_Out + 1, reed);
return reed;
}
//void PowerSuportInitAudioDevice(PowerSupportEnvironment* env){
// HAL_StatusTypeDef error;
//
// uint8_t I2C_Out[16] = {0};
// uint8_t I2C_In[17] = {0};
//
// // 0 1 2 3 4 5 6 7 8 9 0A 0B 0C 0D 0E 0F 10
// // 0x00 0x00 0x00 0x10 0x1E 0x3F 0x24 0x00 0x00 0x06 0x33 0x00 0x4A 0x00 0x00 0x00 0x8A
// // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// I2C_Out[0] = 0x03; //Address
// I2C_Out[1] = 0x10; //0x03 System Clock
// I2C_Out[2] = 0x10; //0x04 Stereo Audio Clock / Control High
// I2C_Out[3] = 0x62; //0x05 Stereo Audio Clock / Control Low
// I2C_Out[4] = 0x40; //0x06 Interface
// I2C_Out[5] = 0x00; //0x07 Interface
// I2C_Out[6] = 0x00; //0x08 Voice Filter
// I2C_Out[7] = 0x08; //0x09 DAC Attenuation DAC Level Adjust -10:0x1A
// I2C_Out[8] = 0x33; //0x0A ADC Output Levels DA Level 4:[left -10:0xD][right -10:0xD]
// I2C_Out[9] = 0x00; //0x0B DAC Gain and Sidetone 0 2:[DVG 00] 5:[DVST -10:0x00]
// I2C_Out[10] = 0x4A; //0x0C Microphone Gain -- 0 2:[MicPreAmp 00] 5:[Mic PGA 0x14]
// I2C_Out[11] = 0x00; //0x0D Reserved
// I2C_Out[12] = 0x00; //0x0E Microphone AGC
// I2C_Out[13] = 0x00; //0x0F Noise Gate, Microphone AGC
// I2C_Out[14] = 0x8A; //0x10 System Shutdown
//
// error = HAL_I2C_Master_Transmit(env->audioI2c, 0x20, I2C_Out, 15, 500);
//
// I2C_Out[0] = 0x00;
// error = HAL_I2C_Master_Receive(env->audioI2c, 0x21, I2C_In, 17, 500);
//}

17
modular.json Normal file
View File

@ -0,0 +1,17 @@
{
"dep": [
{
"type": "git",
"provider": "NAVIGATOR_UVEOS_NATION_TELIT",
"repo": "I2cPortInterface"
}
],
"cmake": {
"inc_dirs": [
"Inc"
],
"srcs": [
"Src/**.c"
]
}
}