Skip to content

Commit

Permalink
Merge pull request #89 from wizmo2/wm8978
Browse files Browse the repository at this point in the history
Add support for WM8978 i2c dac
  • Loading branch information
philippe44 committed Apr 10, 2021
2 parents 1b39a4f + 5075878 commit 68db286
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 7 deletions.
4 changes: 2 additions & 2 deletions components/platform_console/cmd_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ typedef enum {
} parse_state_t;
static const char *TAG = "cmd_config";
extern struct arg_end *getParmsEnd(struct arg_hdr * * argtable);
//bck=<gpio>,ws=<gpio>,do=<gpio>[,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|AC101|I2S][,sda=<gpio>,scl=gpio[,i2c=<addr>]]
//bck=<gpio>,ws=<gpio>,do=<gpio>[,mute=<gpio>[:0|1][,model=TAS57xx|TAS5713|AC101|WM8978|I2S][,sda=<gpio>,scl=gpio[,i2c=<addr>]]
static struct {
struct arg_str *model_name;
struct arg_int *clock;
Expand Down Expand Up @@ -774,7 +774,7 @@ static char * get_log_level_options(const char * longname){
return options;
}
static void register_i2s_config(void){
i2s_args.model_name = arg_str1(NULL,"model_name","TAS57xx|TAS5713|AC101|I2S","DAC Model Name");
i2s_args.model_name = arg_str1(NULL,"model_name","TAS57xx|TAS5713|AC101|WM8978|I2S","DAC Model Name");
i2s_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
i2s_args.clock = arg_int1(NULL,"clock","<n>","Clock GPIO. e.g. 33");
i2s_args.wordselect = arg_int1(NULL,"wordselect","<n>","Word Select GPIO. e.g. 25");
Expand Down
2 changes: 1 addition & 1 deletion components/squeezelite/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
idf_component_register( SRC_DIRS . external ac101 tas57xx
idf_component_register( SRC_DIRS . external ac101 tas57xx wm8978
INCLUDE_DIRS . ac101
PRIV_REQUIRES
codecs
Expand Down
1 change: 1 addition & 0 deletions components/squeezelite/adac.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct adac_s {
extern const struct adac_s dac_tas57xx;
extern const struct adac_s dac_tas5713;
extern const struct adac_s dac_ac101;
extern const struct adac_s dac_wm8978;
extern const struct adac_s dac_external;

int adac_init(char *config, int i2c_port);
Expand Down
2 changes: 1 addition & 1 deletion components/squeezelite/component.mk
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ CFLAGS += -O3 -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ON

# -I$(COMPONENT_PATH)/../codecs/inc/faad2

COMPONENT_SRCDIRS := . tas57xx ac101 external
COMPONENT_SRCDIRS := . tas57xx ac101 external wm8978
COMPONENT_ADD_INCLUDEDIRS := . ./tas57xx ./ac101
COMPONENT_EMBED_FILES := vu.data

2 changes: 1 addition & 1 deletion components/squeezelite/output_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ extern struct buffer *streambuf;
extern struct buffer *outputbuf;
extern u8_t *silencebuf;

const struct adac_s *dac_set[] = { &dac_tas57xx, &dac_tas5713, &dac_ac101, NULL };
const struct adac_s *dac_set[] = { &dac_tas57xx, &dac_tas5713, &dac_ac101, &dac_wm8978, NULL };
const struct adac_s *adac = &dac_external;

static log_level loglevel;
Expand Down
98 changes: 98 additions & 0 deletions components/squeezelite/wm8978/wm8978.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Squeezelite for esp32
*
* (c) Wizmo 2021
* Sebastien 2019
* Philippe G. 2019, philippe_44@outlook.com
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*
*/

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/i2s.h>
#include "driver/i2c.h"
#include "esp_log.h"
#include "adac.h"

#define WM8978 0x1A // for TTGO TAudio

static const char TAG[] = "WM8978";

static void speaker(bool active) { }
static void headset(bool active) { }
static bool volume(unsigned left, unsigned right) { return false; }
static void power(adac_power_e mode);
static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config);

static esp_err_t i2c_write_shadow(uint8_t reg, uint16_t val);
static uint16_t i2c_read_shadow(uint8_t reg);

const struct adac_s dac_wm8978 = { "WM8978", init, adac_deinit, power, speaker, headset, volume };

// initiation table for non-readbale 9-bit i2c registers
static uint16_t WM8978_REGVAL_TBL[58] = {
0X0000, 0X0000, 0X0000, 0X0000, 0X0050, 0X0000, 0X0140, 0X0000,
0X0000, 0X0000, 0X0000, 0X00FF, 0X00FF, 0X0000, 0X0100, 0X00FF,
0X00FF, 0X0000, 0X012C, 0X002C, 0X002C, 0X002C, 0X002C, 0X0000,
0X0032, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000,
0X0038, 0X000B, 0X0032, 0X0000, 0X0008, 0X000C, 0X0093, 0X00E9,
0X0000, 0X0000, 0X0000, 0X0000, 0X0003, 0X0010, 0X0010, 0X0100,
0X0100, 0X0002, 0X0001, 0X0001, 0X0039, 0X0039, 0X0039, 0X0039,
0X0001, 0X0001
};

/****************************************************************************************
* init
*/
static bool init(char *config, int i2c_port, i2s_config_t *i2s_config) {
// TODO: maybe add something here to confirm it is actually detected?
adac_init(config, i2c_port);

ESP_LOGI(TAG, "WM8978 detected");

// init sequence
i2c_write_shadow(0, 0);
i2c_write_shadow(4, 16);
i2c_write_shadow(6, 0);
i2c_write_shadow(10, 8);
i2c_write_shadow(43, 16);
i2c_write_shadow(49, 102);

// Configure system clk to GPIO0 for DAC MCLK input
ESP_LOGI(TAG, "Configuring MCLK on pin:%d", 0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
REG_WRITE(PIN_CTRL, 0xFFFFFFF0);

return true;
}

/****************************************************************************************
* power
*/
static void power(adac_power_e mode) {
uint16_t *data, off[] = {0, 0, 0}, on[] = {11, 384, 111};
data = (mode == ADAC_STANDBY || mode == ADAC_OFF) ? off : on;
i2c_write_shadow(1, data[0]);
i2c_write_shadow(2, data[1]);
i2c_write_shadow(3, data[2]);
}

/****************************************************************************************
* Write with custom reg/value structure
*/
static esp_err_t i2c_write_shadow(uint8_t reg, uint16_t val) {
WM8978_REGVAL_TBL[reg] = val;
reg = (reg << 1) | ((val >> 8) & 0x01);
val &= 0xff;
return adac_write_byte(WM8978, reg, val);
}

/****************************************************************************************
* Return local register value
*/
static uint16_t i2c_read_shadow(uint8_t reg) {
return WM8978_REGVAL_TBL[reg];
}
4 changes: 2 additions & 2 deletions components/wifi-manager/webapp/mock/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"help": "DAC Options",
"hascb": true,
"argtable": [{
"datatype": "TAS57xx|TAS5713|AC101|I2S",
"datatype": "TAS57xx|TAS5713|AC101|WM8978|I2S",
"glossary": "DAC Model Name",
"longopts": "model_name",
"checkbox": false,
Expand Down Expand Up @@ -202,7 +202,7 @@
"mincount": 0,
"maxcount": 1
}],
"hint": " --model_name=TAS57xx|TAS5713|AC101|I2S --clock=<n> --wordselect=<n> --data=<n> [--mute_gpio=<n>] [--mute_level] [--dac_sda=<n>] [--dac_scl=<n>] [--dac_i2c=<n>] [--clear]",
"hint": " --model_name=TAS57xx|TAS5713|AC101|WM8978|I2S --clock=<n> --wordselect=<n> --data=<n> [--mute_gpio=<n>] [--mute_level] [--dac_sda=<n>] [--dac_scl=<n>] [--dac_i2c=<n>] [--clear]",
"name": "cfg-hw-dac"
}, {
"help": "SPDIF Options",
Expand Down

0 comments on commit 68db286

Please sign in to comment.