summaryrefslogtreecommitdiff
path: root/Core/Src/cs4272.c
blob: 8ba98856a308b712d3eafb4b492df9bb4e7a82c0 (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
127
/*
 * cs4272.c
 *
 *  Created on: Aug 16, 2026
 *      Author: ozpv
 */

#include "i2c.h"
#include "cs4272.h"
#include "ringmod.h"
#include "retain.h"

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

const uint8_t CS4272_CONFIG[7] = {
        /* MODE CONTROL 1
           single speed i2s slave */
        0b00000001,
        /* DAC CONTROL
          Steep Interpolation Filter
          48 kHz de-emphasis
          Soft Ramp Up and Down and no polarity flip */
        0b01101100,
        /* DAC Volume & Mixing Control
          Channel B Volume = Channel A Volume
          Soft Ramp and Zero Cross
          a = L b = R
          stereo 0b01111001 */
        0b01111000,
        /* 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
           Muted for mono */
        0b10000000,
        /* ADC control
           I2S up to 24-bit data High Pass filter on
           bits 3:2 active high adc channel mute
           Channel B muted */
        0b00010100,
        /* MODE CONTROL 2
           power down OFF */
        0b00000010,
};

//const struct RingModParams params = {
//    0.40f,
//    156.0f,
//    16.90f,
//    0.18f,
//    false,
//};

void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) {
    retain(rx_buffer, tx_buffer, 0, BUFFER_SIZE / 2, MONO);
}

void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) {
    retain(rx_buffer, tx_buffer, BUFFER_SIZE / 2, BUFFER_SIZE, MONO);
}

HAL_StatusTypeDef CS4272_ReadRegister(const 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(const 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(void) {
    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(void) {
    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 (size_t i = MODE_CONTROL_1; i < CHIP_ID; ++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;
        }
    }

    return HAL_OK;
}