Kestrel Interface
Loading...
Searching...
No Matches
kest_sgtl5000.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdint.h>
3#include <stdbool.h>
4#include "esp_err.h"
5#include "esp_check.h"
6#include "esp_log.h"
7
8#include "kest_error_codes.h"
9#include "kest_printf.h"
10
11#include "driver/spi_master.h"
12#include "driver/i2c_master.h"
13#include "driver/pulse_cnt.h"
14#include "driver/gpio.h"
15
16#include "kest_sgtl5000.h"
17
18#define SGTL5000_SDA 15
19#define SGTL5000_SCL 16
20
21static const char *TAG = "sgtl5000";
22
24
25static uint16_t ana_ctrl;
26static uint8_t i2c_addr = 0x0A;
27
28static bool muted;
29static bool semi_automated;
30
31static i2c_master_bus_handle_t bus;
32static i2c_master_dev_handle_t dev;
33
34typedef struct {
38 uint32_t i2c_hz;
40
42{
43 if (!cfg) return ESP_ERR_INVALID_ARG;
44
45 i2c_master_bus_config_t bus_cfg = {
46 .i2c_port = -1,
47 .sda_io_num = cfg->sda_gpio,
48 .scl_io_num = cfg->scl_gpio,
49 .clk_source = I2C_CLK_SRC_DEFAULT,
50 .glitch_ignore_cnt = 7,
51 .intr_priority = 0,
52 .trans_queue_depth = 0,
53 .flags.enable_internal_pullup = false,
54 };
55
56 esp_err_t err = i2c_new_master_bus(&bus_cfg, &bus);
57 if (err != ESP_OK) return err;
58
59 i2c_device_config_t dev_cfg = {
60 .dev_addr_length = I2C_ADDR_BIT_LEN_7,
61 .device_address = i2c_addr,
62 .scl_speed_hz = cfg->i2c_hz,
63 };
64
65 err = i2c_master_bus_add_device(bus, &dev_cfg, &dev);
66
67 return (err == ESP_OK) ? NO_ERROR : ERR_I2C_FAIL;
68}
69
70int sgtl5000_set_address_level(int cs_level_high)
71{
72 uint8_t new_addr = cs_level_high ? SGTL5000_I2C_ADDR_CS_HIGH : SGTL5000_I2C_ADDR_CS_LOW;
73 i2c_addr = new_addr;
74
75 if (!bus) return ERR_BAD_ARGS;
76
77 if (dev) {
78 i2c_master_bus_rm_device(dev);
79 dev = NULL;
80 }
81
82 i2c_device_config_t dev_cfg = {
83 .dev_addr_length = I2C_ADDR_BIT_LEN_7,
84 .device_address = i2c_addr,
85 .scl_speed_hz = 400000,
86 };
87
88 esp_err_t err = i2c_master_bus_add_device(bus, &dev_cfg, &dev);
89
90 return (err == ESP_OK) ? NO_ERROR : ERR_I2C_FAIL;
91}
92
93int sgtl5000_read_reg(uint16_t reg, uint16_t *out_val)
94{
95 if (!dev || !out_val) return ESP_ERR_INVALID_STATE;
96
97 uint8_t addr_be[2] = { (uint8_t)(reg >> 8), (uint8_t)(reg & 0xFF) };
98 uint8_t data[2] = {0, 0};
99
100 esp_err_t err = i2c_master_transmit_receive(dev, addr_be, sizeof(addr_be), data, sizeof(data), -1);
101 if (err != ESP_OK) return ERR_I2C_FAIL;
102
103 vTaskDelay(pdMS_TO_TICKS(2));
104
105 *out_val = ((uint16_t)data[0] << 8) | (uint16_t)data[1];
106 return NO_ERROR;
107}
108
109int sgtl5000_write_reg(uint16_t reg, uint16_t val)
110{
111 if (!dev) return ESP_ERR_INVALID_STATE;
112
113 if (reg == CHIP_ANA_CTRL) ana_ctrl = val;
114
115 uint8_t pkt[4] = {
116 (uint8_t)(reg >> 8), (uint8_t)(reg & 0xFF),
117 (uint8_t)(val >> 8), (uint8_t)(val & 0xFF)
118 };
119
120 esp_err_t err = i2c_master_transmit(dev, pkt, sizeof(pkt), -1);
121
122 if (err != ESP_OK)
123 return ERR_I2C_FAIL;
124
125 return NO_ERROR;
126}
127
128int sgtl5000_modify_reg(uint16_t reg, uint16_t val, uint16_t mask, uint16_t *out_newval)
129{
130 uint16_t cur;
131 int ret_val = sgtl5000_read_reg(reg, &cur);
132 if (ret_val != NO_ERROR) return ret_val;
133
134 uint16_t newv = (cur & ~mask) | (val & mask);
135 ret_val = sgtl5000_write_reg(reg, newv);
136 if (ret_val != NO_ERROR) return ret_val;
137
138 if (out_newval) *out_newval = newv;
139 return NO_ERROR;
140}
141
143{
144 if (!dev) return ESP_ERR_INVALID_STATE;
145
146 muted = true;
147
148 kest_printf("Send power sequence...\n");
149
150 int ret_val;
151
152 if ((ret_val = sgtl5000_write_reg(CHIP_LINREG_CTRL, 0x006C)) != NO_ERROR) return ret_val;
153 if ((ret_val = sgtl5000_write_reg(CHIP_REF_CTRL, 0x01F2)) != NO_ERROR) return ret_val;
154 if ((ret_val = sgtl5000_write_reg(CHIP_LINE_OUT_CTRL, 0x0F22)) != NO_ERROR) return ret_val;
155 if ((ret_val = sgtl5000_write_reg(CHIP_SHORT_CTRL, 0x4446)) != NO_ERROR) return ret_val;
156 if ((ret_val = sgtl5000_write_reg(CHIP_ANA_CTRL, 0x0137)) != NO_ERROR) return ret_val;
157
158 if ((ret_val = sgtl5000_write_reg(CHIP_ANA_POWER, 0x40FF)) != NO_ERROR) return ret_val;
159 if ((ret_val = sgtl5000_write_reg(CHIP_DIG_POWER, 0x0073)) != NO_ERROR) return ret_val;
160
161 // delay(400);
162 vTaskDelay(pdMS_TO_TICKS(400));
163
164 if ((ret_val = sgtl5000_write_reg(CHIP_LINE_OUT_VOL, 0x1D1D)) != NO_ERROR) return ret_val;
165
166 if ((ret_val = sgtl5000_write_reg(CHIP_CLK_CTRL, 0x0004)) != NO_ERROR) return ret_val;
167 if ((ret_val = sgtl5000_write_reg(CHIP_I2S_CTRL, 0x0030)) != NO_ERROR) return ret_val;
168
169 if ((ret_val = sgtl5000_write_reg(CHIP_SSS_CTRL, 0x0010)) != NO_ERROR) return ret_val;
170 if ((ret_val = sgtl5000_write_reg(CHIP_ADCDAC_CTRL, 0x0000)) != NO_ERROR) return ret_val;
171 if ((ret_val = sgtl5000_write_reg(CHIP_DAC_VOL, 0x3C3C)) != NO_ERROR) return ret_val;
172 if ((ret_val = sgtl5000_write_reg(CHIP_ANA_HP_CTRL, 0x7F7F)) != NO_ERROR) return ret_val;
173 if ((ret_val = sgtl5000_write_reg(CHIP_ANA_CTRL, 0x0036)) != NO_ERROR) return ret_val;
174
175 semi_automated = true;
176
177 // Set input as line in
178 if ((ret_val = sgtl5000_write_reg(0x0020, 0x0055)) != NO_ERROR) return ret_val;
179 if ((ret_val = sgtl5000_write_reg(0x0024, ana_ctrl | (1u<<2))) != NO_ERROR) return ret_val;
180
181 if ((ret_val = sgtl5000_modify_reg(CHIP_ADCDAC_CTRL, 0, 0x0300, NULL)) != NO_ERROR)
182 return ret_val;
183
184 kest_printf("Done.\n");
185
186 return NO_ERROR;
187}
188
190{
191 if (n > 15) n = 15;
192 return sgtl5000_write_reg(CHIP_ANA_ADC_CTRL, (n << 4) | n);
193}
194
196{
197 if (n > 31) n = 31;
198 else if (n < 13) n = 13;
199 return sgtl5000_modify_reg(CHIP_LINE_OUT_VOL,(n<<8)|n, (31<<8)|31, NULL);
200}
201
203{
204 gpio_config_t cfg = {
205 .pin_bit_mask = 1ULL << 2,
206 .mode = GPIO_MODE_INPUT,
207 .pull_up_en = GPIO_PULLUP_DISABLE,
208 .pull_down_en = GPIO_PULLDOWN_DISABLE,
209 .intr_type = GPIO_INTR_DISABLE,
210 };
211
212 gpio_config(&cfg);
213}
214
215static void read_and_print(uint16_t reg, const char *name)
216{
217 uint16_t v = 0xFFFF;
218 int ret_val = sgtl5000_read_reg(reg, &v);
219 if (ret_val != NO_ERROR)
220 {
221 kest_printf("RD %-18s (0x%04X): ERROR\n", name, reg);
222 return;
223 }
224 kest_printf("RD %-18s (0x%04X): 0x%04X\n", name, reg, v);
225}
226
227typedef struct {
228 uint16_t reg;
229 const char *name;
231
233{
234 static const sgtl_reg_desc_t reads[] = {
235 { CHIP_ID, "CHIP_ID" },
236 { CHIP_DIG_POWER, "CHIP_DIG_POWER" },
237 { CHIP_ANA_POWER, "CHIP_ANA_POWER" },
238 { CHIP_CLK_CTRL, "CHIP_CLK_CTRL" },
239 { CHIP_I2S_CTRL, "CHIP_I2S_CTRL" },
240 { CHIP_ADCDAC_CTRL, "CHIP_ADCDAC_CTRL" },
241 { CHIP_DAC_VOL, "CHIP_DAC_VOL" },
242 { CHIP_PAD_STRENGTH, "CHIP_PAD_STRENGTH" },
243 { CHIP_ANA_ADC_CTRL, "CHIP_ANA_ADC_CTRL" },
244 { CHIP_ANA_HP_CTRL, "CHIP_ANA_HP_CTRL" },
245 { CHIP_ANA_CTRL, "CHIP_ANA_CTRL" },
246 { CHIP_LINREG_CTRL, "CHIP_LINREG_CTRL" },
247 { CHIP_REF_CTRL, "CHIP_REF_CTRL" },
248 { CHIP_MIC_CTRL, "CHIP_MIC_CTRL" },
249 { CHIP_LINE_OUT_CTRL, "CHIP_LINE_OUT_CTRL" },
250 { CHIP_LINE_OUT_VOL, "CHIP_LINE_OUT_VOL" },
251 { CHIP_ANA_POWER, "CHIP_ANA_POWER" },
252 { CHIP_PLL_CTRL, "CHIP_PLL_CTRL" },
253 { CHIP_CLK_TOP_CTRL, "CHIP_CLK_TOP_CTRL" },
254 { CHIP_ANA_STATUS, "CHIP_ANA_STATUS" },
255 { CHIP_ANA_TEST1, "CHIP_ANA_TEST1" },
256 { CHIP_ANA_TEST2, "CHIP_ANA_TEST2" },
257 { CHIP_SHORT_CTRL, "CHIP_SHORT_CTRL" },
258 { CHIP_SSS_CTRL, "CHIP_SSS_CTRL" },
259 };
260
261 kest_printf("\n=== SGTL5000 READ DUMP ===\n");
262 for (size_t i = 0; i < sizeof(reads)/sizeof(reads[0]); i++) {
263 (void)read_and_print(reads[i].reg, reads[i].name);
264 }
265}
266
267void kest_sgtl5000_init(void *param)
268{
270
271 sgtl5000_i2c_cfg_t sgtl_i2c_cfg = {
272 .i2c_port = -1,
273 .sda_gpio = SGTL5000_SDA,
274 .scl_gpio = SGTL5000_SCL,
275 .i2c_hz = 400000,
276 };
277
278
279
280 vTaskDelay(pdMS_TO_TICKS(3000));
281
282 int ret_val;
283
284 kest_printf("Initialise I2C bus with SGTL5000...\n");
285 if ((ret_val = sgtl5000_i2c_init(&sgtl_i2c_cfg)) != NO_ERROR)
286 {
287 kest_printf("Error initialising I2C bus with SGTL5000...\n");
288 return;
289 }
290
291 if ((ret_val = sgtl5000_set_address_level(0)) != NO_ERROR)
292 return;
293
294 kest_printf("Initialising SGTL5000...\n");
295 if ((ret_val = sgtl5000_enable()) != NO_ERROR)
296 {
297 kest_printf("Error initialising SGTL5000...\n");
298 return;
299 }
300
303
304 sgtl5000_status = 1;
305
306 kest_printf("SGTL5000 Initialised\n");
307
308 //sgtl5000_readout_registers();
309
310 vTaskDelete(NULL);
311}
#define ERR_BAD_ARGS
#define NO_ERROR
#define ERR_I2C_FAIL
void kest_printf(const char *fmt,...)
Definition kest_printf.c:21
int sgtl5000_set_address_level(int cs_level_high)
int sgtl5000_read_reg(uint16_t reg, uint16_t *out_val)
void sgtl_power_gpio_init(void)
int sgtl5000_status
int sgtl5000_write_reg(uint16_t reg, uint16_t val)
int sgtl5000_line_in_level(uint8_t n)
void kest_sgtl5000_init(void *param)
int sgtl5000_line_out_level(uint8_t n)
#define SGTL5000_SCL
void sgtl5000_readout_registers()
int sgtl5000_enable(void)
int sgtl5000_i2c_init(const sgtl5000_i2c_cfg_t *cfg)
#define SGTL5000_SDA
int sgtl5000_modify_reg(uint16_t reg, uint16_t val, uint16_t mask, uint16_t *out_newval)
#define CHIP_ANA_CTRL
#define SGTL5000_I2C_ADDR_CS_LOW
#define CHIP_MIC_CTRL
#define CHIP_ANA_POWER
#define CHIP_I2S_CTRL
#define CHIP_PAD_STRENGTH
#define CHIP_ANA_ADC_CTRL
#define CHIP_ANA_STATUS
#define CHIP_SHORT_CTRL
#define CHIP_CLK_TOP_CTRL
#define CHIP_LINE_OUT_CTRL
#define CHIP_ADCDAC_CTRL
#define CHIP_PLL_CTRL
#define CHIP_ANA_TEST1
#define CHIP_ID
#define CHIP_LINE_OUT_VOL
#define CHIP_CLK_CTRL
#define CHIP_SSS_CTRL
#define CHIP_DIG_POWER
#define CHIP_DAC_VOL
#define CHIP_ANA_TEST2
#define SGTL5000_I2C_ADDR_CS_HIGH
#define CHIP_ANA_HP_CTRL
#define CHIP_LINREG_CTRL
#define CHIP_REF_CTRL
const char * name