summaryrefslogtreecommitdiff
path: root/Core/Src/cs4272.c
blob: e7b639eb7d7109c4d432ebdea60dfd547b55b82d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * cs4272.c
 *
 *  Created on: Aug 16, 2026
 *      Author: ozpv
 */

#include "i2c.h"
#include "cs4272.h"

volatile int32_t rx_buffer[BUFFER_SIZE] __attribute__((section(".audio_buffers")));
volatile int32_t tx_buffer[BUFFER_SIZE] __attribute__((section(".audio_buffers")));

const uint8_t CS4272_CONFIG[7] = {
        // MODE CONTROL 1
        // single speed i2s slave
        0b00000001,
        // DAC CONTROL
        // no auto mute steep roll off interpolation 48 kHz de-emphasis
        // Soft Ramp Up and Down and no polarity flipping
        0b00001100,
        // DAC Volume & Mixing Control
        // Channel B Volume = Channel A Volume Soft Ramp and Zero Cross
        // a = L b = R
        0b01111001,
        // Channel A volume
        // 0 dB
        // Binary Code Decimal Value Volume Setting
        // 0000000 0 0 dB
        // 0010100 20 -20 dB
        // 0101000 40 -40 dB
        // 0111100 60 -60 dB
        // 1011010 90 -90 dB
        0b00000000,
        // Channel B volume
        0b00000000,
        // ADC control
        // I2S up to 24-bit data High Pass filter on
        // bits 3:2 adc channel mute
        0b00010000,
        // MODE CONTROL 2
        // power down OFF
        0b00000010,
};

HAL_StatusTypeDef CS4272_ReadRegister(uint8_t addr, uint8_t *data) {
    return HAL_I2C_Mem_Read(&hi2c4, CS4272_I2C_ADDR, addr, I2C_MEMADD_SIZE_8BIT,
            data, 1, HAL_MAX_DELAY);
}

HAL_StatusTypeDef CS4272_WriteRegister(uint8_t addr, uint8_t data) {
    return HAL_I2C_Mem_Write(&hi2c4, CS4272_I2C_ADDR, addr,
    I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}

void CS4272_Reset() {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);

    HAL_Delay(10);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);

    HAL_Delay(10);
}

uint8_t CS4272_Init() {
    CS4272_Reset();

    if (HAL_I2C_IsDeviceReady(&hi2c4, CS4272_I2C_ADDR, 3, 1000) != HAL_OK) {
        return HAL_ERROR;
    }

    // 5.2.1 Recommended Power-Up Sequence
    // power down mode and control port enable
    if (CS4272_WriteRegister(MODE_CONTROL_2, 0x03) != HAL_OK) {
        return HAL_ERROR;
    }

    // check if device ID is correct
    uint8_t id = 0;
    if (CS4272_ReadRegister(CHIP_ID, &id) != HAL_OK) {
        return HAL_ERROR;
    }

    if ((id >> 4) != CS4272_CHIP_ID) {
        return 2;
    }

    // Configure
    uint8_t cfg = 0;
    for (uint8_t i = MODE_CONTROL_1; i < MODE_CONTROL_2; ++i) {
        if (CS4272_WriteRegister(i, CS4272_CONFIG[i - 1]) != HAL_OK) {
            return HAL_ERROR;
        }

        if (CS4272_ReadRegister(i, &cfg) != HAL_OK) {
            return HAL_ERROR;
        }

        if (cfg != CS4272_CONFIG[i - 1]) {
            return 2;
        }
    }

    if (CS4272_WriteRegister(MODE_CONTROL_2, 0x02) != HAL_OK) {
        return HAL_ERROR;
    }

    if (CS4272_ReadRegister(MODE_CONTROL_2, &cfg) != HAL_OK || cfg != 0x02) {
        return 2;
    }

    return HAL_OK;
}

void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) {
    for(int i = 0; i < BUFFER_SIZE / 2; i++) {
        tx_buffer[i] = rx_buffer[i];
    }
}

void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) {
    for(int i = BUFFER_SIZE / 2; i < BUFFER_SIZE; i++) {
        tx_buffer[i] = rx_buffer[i];
    }
}