add some code

This commit is contained in:
2025-09-05 13:25:11 +08:00
parent 9ff0a99e7a
commit 3cf1229a85
8911 changed files with 2535396 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
MIT License
Copyright 2018 Microsemi Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,36 @@
The Source code for the Timberwolf device driver is partitioned into 4 folders.
\api_lib\
There are 5 files in this folder
The VprocTwolf_access.c/h -
is the user's space OS independent API to read/write specific register of the device to
reset the device into one of the 5 supported reset modes and to boot load a firmware/configuration record into the device.
The API must be used in conjunction with a low level device driver such as microsemi_spis_tw.c/h, VprocGal_HAL.c/h
vproc_common.c/h -
includes functions and variable declarations that are common to all Microsemi Voice processing devices.
These functions include the Vproc_msDelay(), VprocWait(). The Variables declarations include
the device status codes, and device reset modes enums. As well as multiple macros to enable debug mode.
the specific user_space hardware abstraction layer code for the ZL38040/05x/06x/08x Timberwolf devices.
\firmware\
This folder contains the firmware image , configuration record files and header file.
NOTE: The firmware of the development board and its corresponding configuration have been encapsulated into a static library.
\example_apps\
This folder contains example host applications for the zl38040/050/060/080 Microsemi devices.
zl38063.c/h -
a series of operations for zl38063, such as initialize, adjust the volume, and so on.
NOTE: You can get the latest firmware and related technical support by registering SDS account.
http://sds.microsemi.com/software.php.
ZLS38063 GUI software(MiTuner Lite GUI Software), ZLS38063 and ZLS38508LITE
http://sds.microsemi.com/software.php?view_type=listrev&id=103386.
firmware of ZL38063
http://sds.microsemi.com/software.php?view_type=listrev&id=104598.

View File

@@ -0,0 +1,10 @@
#ifndef TW_SPI_ACCESS_H
#define TW_SPI_ACCESS_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int tw_upload_dsp_firmware(int mode);
#endif

View File

@@ -0,0 +1,74 @@
/****************************************************************************
*
* vprocTwolf_access.h - Voice Processor devices high level access module function
* prototypes, variables
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#ifndef VPROC_TWOLFACCESS_H
#define VPROC_TWOLFACCESS_H
#include "vproc_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TWOLF_MAILBOX_SPINWAIT 1000 /*at least a 1000 to avoid mailbox busy */
/*device HBI command structure*/
typedef struct hbiCmdInfo {
unsigned char page;
unsigned char offset;
unsigned char numwords;
} hbiCmdInfo;
/* external function prototypes */
VprocStatusType VprocTwolfHbiInit(void); /*Use this function to initialize the HBI bus*/
VprocStatusType VprocTwolfHbiRead(unsigned short cmd, /*the 16-bit register to read from*/
unsigned char numwords, /* The number of 16-bit words to read*/
unsigned short *pData); /* Pointer to the read data buffer*/
VprocStatusType VprocTwolfHbiWrite(unsigned short cmd, /*the 16-bit register to write to*/
unsigned char numwords, /* The number of 16-bit words to write*/
unsigned short *pData); /*the words (0-255) to write*/
VprocStatusType TwolfHbiNoOp( /*send no-op command to the device*/
unsigned char numWords); /* The number of no-op (0-255) to write*/
/*An alternative method to loading the firmware into the device
* USe this method if you have used the provided tool to convert the *.s3 into
* c code that can be compiled with the application
*/
VprocStatusType
VprocTwolfHbiBoot_alt(/*use this function to boot load the firmware (*.c) from the host to the device RAM*/
twFirmware *st_firmware); /*Pointer to the firmware image in host RAM*/
VprocStatusType VprocTwolfLoadConfig(dataArr *pCr2Buf, unsigned short numElements);
VprocStatusType VprocTwolfHbiCleanup(void);
VprocStatusType VprocTwolfHbiBootPrepare(void);
VprocStatusType VprocTwolfHbiBootMoreData(char *dataBlock);
VprocStatusType VprocTwolfHbiBootConclude(void);
VprocStatusType VprocTwolfFirmwareStop(void); /*Use this function to halt the currently running firmware*/
VprocStatusType VprocTwolfFirmwareStart(void); /*Use this function to start/restart the firmware currently in RAM*/
VprocStatusType VprocTwolfSaveImgToFlash(void); /*Save current loaded firmware from device RAM to FLASH*/
VprocStatusType VprocTwolfSaveCfgToFlash(void); /*Save current device config from device RAM to FLASH*/
VprocStatusType VprocTwolfReset(VprocResetMode mode);
VprocStatusType VprocTwolfEraseFlash(void);
VprocStatusType VprocTwolfLoadFwrCfgFromFlash(uint16 image_number);
VprocStatusType VprocTwolfSetVolume(uint8 vol);
VprocStatusType VprocTwolfGetVolume(int8_t *vol);
VprocStatusType VprocTwolfGetAppStatus(uint16 *status);
#ifdef __cplusplus
}
#endif
#endif /* VPROCTWOLFACCESS_H */

View File

@@ -0,0 +1,85 @@
/****************************************************************************
* vproc_common.c - Hal functions for the VPROC API
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#include "vproc_common.h"
#include "esp_codec_dev_os.h"
#include "audio_codec_ctrl_if.h"
/*Note - These functions are PLATFORM SPECIFIC- They must be modified
* accordingly
**********************************************************************/
static audio_codec_ctrl_if_t *vproc_ctrl_if;
void VprocSetCtrlIf(void *ctrl_if)
{
vproc_ctrl_if = (audio_codec_ctrl_if_t *) ctrl_if;
}
static uint16_t convert_edian(uint16_t v)
{
return (v >> 8) | ((v & 0xFF) << 8);
}
void VprocHALcleanup(void)
{
}
int VprocHALInit(void)
{
if (vproc_ctrl_if) {
return 0;
}
return -1;
}
void Vproc_msDelay(unsigned short time)
{
esp_codec_dev_sleep(time);
}
/* VprocWait(): use this function to
* force a delay of specified time in resolution of 125 micro-Seconds
*
* Input Argument: time in unsigned 32-bit
* Return: none
*/
void VprocWait(unsigned long int time)
{
esp_codec_dev_sleep(time);
}
/* This is the platform dependent low level spi
* function to write 16-bit data to the ZL380xx device
*/
int VprocHALWrite(unsigned short val)
{
int ret = 0;
if (vproc_ctrl_if) {
val = convert_edian(val);
ret = vproc_ctrl_if->write_reg(vproc_ctrl_if, 0, 0, &val, sizeof(val));
}
return ret;
}
/* This is the platform dependent low level spi
* function to read 16-bit data from the ZL380xx device
*/
int VprocHALRead(unsigned short *pVal)
{
unsigned short data = 0;
int ret = 0;
if (vproc_ctrl_if) {
ret = vproc_ctrl_if->read_reg(vproc_ctrl_if, 0, 0, &data, sizeof(data));
*pVal = convert_edian(data);
}
return ret;
}

View File

@@ -0,0 +1,124 @@
/****************************************************************************
* vproc_common.h - Hal functions prototypes, macros and variables for the VPROC API
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#ifndef VPROC_COMMON_H
#define VPROC_COMMON_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DEBUG_LOGD ESP_LOGD
#define DEBUG_LOGE ESP_LOGE
#define DEBUG_LOGI ESP_LOGI
/*This header includes some platform dependent data types*/
#include "vproc_data_types.h"
//#define RETRY_COUNT 100
#define VPROC_TIMEOUT 500
#define TAG_SPI "SPI"
/* external defines */
#undef VPROC_DEBUG
/*create a 16-bit word out of two bytes*/
#define MAKE16(a, b) (unsigned short) (((unsigned short) (b) << 8) | (unsigned short) (a))
/*create a 32-bit word out of 4 bytes*/
#define MAKE32(a, b, c, d) \
(unsigned long) (((unsigned long) d << 24) | ((unsigned long) c << 16) | ((unsigned long) b << 8) | \
((unsigned long) a))
/*
* debug - print the function name and line number for the source of the error
* the line number count start at 1 and not 0
*/
/*
*Define this macro to report mode debug info
*/
#undef VPROC_API_DBG_INFO
#ifdef VPROC_API_DBG_INFO
#define VPROG_DBG_INFO(s, args...) printf(""s, ##args);
#else
#define VPROG_DBG_INFO(s, args...)
#endif
#define VPROC_API_DBG_ERROR
#ifdef VPROC_API_DBG_ERROR
#define VPROG_DBG_ERROR(s, args...) printf("---%s %d: "s, __func__, __LINE__, ##args);
#else
#define VPROG_DBG_ERROR(s, args...)
#endif
/*unsigned char deviceType;*/
/*device/access Status codes*/
typedef enum VprocStatusType {
VPROC_STATUS_SUCCESS = 0,
VPROC_STATUS_FAILURE,
VPROC_STATUS_INIT_FAILED,
VPROC_STATUS_WR_FAILED,
VPROC_STATUS_RD_FAILED,
VPROC_STATUS_FW_LOAD_FAILED,
VPROC_STATUS_CFG_LOAD_FAILED,
VPROC_STATUS_CLOSE_FAILED,
VPROC_STATUS_FW_SAVE_FAILED,
VPROC_STATUS_GFG_SAVE_FAILED,
VPROC_STATUS_MAU_NOT_READY,
VPROC_STATUS_CHK_FAILED,
VPROC_STATUS_FUNC_NOT_SUPPORTED,
VPROC_STATUS_INVALID_ARG,
VPROC_STATUS_ERR_VTD_CODE,
VPROC_STATUS_ERR_VERIFY,
VPROC_STATUS_DEVICE_BUSY,
VPROC_STATUS_ERR_HBI,
VPROC_STATUS_ERR_IMAGE,
VPROC_STATUS_MAILBOX_BUSY,
VPROC_STATUS_CMDREG_BUSY,
VPROC_STATUS_IN_CRTCL_SECTN,
VPROC_STATUS_BOOT_LOADING_MORE_DATA,
VPROC_STATUS_BOOT_LOADING_CMP,
VPROC_STATUS_DEV_NOT_INITIALIZED,
} VprocStatusType;
/* Device Reset modes*/
typedef enum VprocResetMode {
VPROC_RST_HARDWARE_ROM = 0, /*hardware reset -reset the device and reload the firmware from flash*/
VPROC_RST_HARDWARE_RAM = 1, /*hardware reset -reset the device and reload the firmware from RAM*/
VPROC_RST_SOFTWARE = 2,
VPROC_RST_AEC = 3, /*software reset -reset and runs the firmware from RAM*/
VPROC_RST_BOOT = 4
} VprocResetMode;
typedef enum vProcDeviceType {
VPROC_DEV_GALILEO = 1, /*Galileo devices: ZL38004, ZL38012, ZL38005*/
VPROC_DEV_TIMBERWOLF = 2 /*Timberwolf: ZL38040*/
} VprocDeviceType;
extern void VprocSetCtrlIf(void *ctrl_if);
extern void VprocHALcleanup(void);
extern int VprocHALInit(void);
extern void Vproc_msDelay(unsigned short time);
extern void VprocWait(unsigned long int time);
extern int VprocHALWrite(unsigned short val);
extern int VprocHALRead(unsigned short *pVal);
#ifdef __cplusplus
}
#endif
#endif /* VPROC_COMMON_H */

View File

@@ -0,0 +1,121 @@
/** \file vproc_data_types.h
* vproc_data_types.h
*
* This file is the header for all standard types used in the API code.
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#ifndef VP_API_TYPES_H
#define VP_API_TYPES_H
/* For maximum that can be stored in an int - if file exists in library */
#include "limits.h"
#include "esp_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef NULL
#define NULL (0)
#endif
#ifdef EXTERN
#undef EXTERN
#error EXTERN was redefined!
#endif /* undef EXTERN */
#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN extern
#endif /* __cplusplus */
/********************* DECLARATIONS ***************************/
/* Constants */
#define FALSE (0) /* Boolean constant */
#define TRUE (1) /* Boolean constant */
#ifndef __cplusplus
/* C++ language provides a boolean data type; So no need to define
* one more data type; Make use of it
* NOTE: The 'C' potions of the VP-API assume C++ "bool" to be of the
* same size as that of "char". Please make sure this assumption is correct.
*/
// typedef unsigned char bool;
#endif /* __cplusplus */
/****************** typedefs ***********************************/
/* These are the basic number types used */
/* for uint8, uint16, uint32, int8, int16, int32, bool */
// PLATFORM SPECIFIC DEFINITIONS
typedef unsigned char uchar;
typedef signed char int8;
typedef unsigned char UCharT; // 8 bits unsigned - PLATFORM SPECIFIC
typedef unsigned char UInt8T; // 8 bits unsigned - PLATFORM SPECIFIC
typedef unsigned short UInt16T; // 16 bits unsigned - PLATFORM SPECIFIC
typedef unsigned long UInt32T; // 32 bits unsigned - PLATFORM SPECIFIC
typedef signed long Int32T; // 32 bits signed - PLATFORM SPECIFIC
typedef unsigned char uint8; // 8 bits unsigned - PLATFORM SPECIFIC
typedef unsigned short uint16; // 16 bits unsigned - PLATFORM SPECIFIC
typedef uint8 *uint8p; // pointer to 8 bits unsigned - PLATFORM SPECIFIC
typedef uint16 *uint16p; // pointer to 16 bits unsigned - PLATFORM SPECIFIC
typedef uint32_t uint32; // 32 bits unsigned - PLATFORM SPECIFIC
typedef signed short int16; // 32 bits unsigned - PLATFORM SPECIFIC
typedef uint32 *uint32p;
typedef int8 *int8p;
typedef int16 *int16p;
typedef Int32T *int32p;
/* external types */
/* Some compilers optimize the size of enumeration data types based on
* the maximum data value assigned to the members of that data type.
* 'Standard C' requires enumeration data types to be of the same size
* as that of native 'int' implementation.
* The VP-API from a portability persepective adds a 'dummy' member to
* all enumeration data types that force the compilers to allocate the size
* of enumeration data types to be equal to that of native 'int'
* implementation */
#define FORCE_STANDARD_C_ENUM_SIZE (INT_MAX)
/* Eliminate error messages that occur when comparing an enumeration constant
< 0 */
#define FORCE_SIGNED_ENUM (INT_MIN)
/* Define any API specific basic data type ranges (that are necessary) */
#define VP_INT16_MAX (SHRT_MAX)
#define VP_INT16_MIN (SHRT_MIN)
#define VP_INT32_MAX (LONG_MAX)
#define VP_INT32_MIN (LONG_MIN)
/*firmware data structures*/
typedef struct {
uint16 buf[16]; /*the firmware data block to send to the device*/
uint16 numWords; /*the number of words within the block of data stored in buf[]*/
uint32 targetAddr; /*the target base address to write to register 0x00c of the device*/
uint8 useTargetAddr; /*this value is either 0 or 1. When 1 the tarGetAddr must be written to the device*/
} twFwr;
typedef struct {
twFwr *st_Fwr;
uint32 byteCount; /*The total number of bytes within the firmware - NOT USED*/
uint8 havePrgmBase;
uint32 prgmBase;
uint32 execAddr; /*The execution start address of the firmware in RAM*/
uint16 twFirmwareStreamLen; /*The number of blocks within the firmware*/
} twFirmware;
/*config record structures*/
typedef struct {
uint16 reg; /*the register */
uint16 value; /*the value to write into reg */
} dataArr;
#ifdef __cplusplus
}
#endif
#endif /* VP_API_TYPES_H */

View File

@@ -0,0 +1,299 @@
/****************************************************************************
* tw_hal_verify.c - Read/write registers of the device and verify whether the
* device is accessed properly
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#include <stdio.h>
#include <stdlib.h> /* malloc, free, rand */
#include "esp_log.h"
#include "vproc_common.h"
#include "zl38063_config.h"
#include "vprocTwolf_access.h"
#include "zl38063_firmware.h"
/*NOTE: notice that the *.c code are included in the apps-
* This is because the compiler I'm using requires that
* But if your makefile is such that compiler knows where to find these files
* then remove the #include *.c below
*/
#undef SAVE_IMAGE_TO_FLASH /*define this macro to save the firmware from RAM to flash*/
#undef SAVE_CFG_TO_FLASH /*define this macro to save the cfg from RAM to flash*/
/*quick test*/
#define TW_HAL_VERIFY_DEBUG
#define MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST 125
static const char *TAG = "TW_HAL_VERIFY";
/*LoadFwrConfig_Alt - to load a converted *s3, *cr2 to c code into the device.
* Basically instead of loading the *.s3, *cr2 directly,
* use the tw_convert tool to convert the ascii hex fwr mage into code and compile
* with the application
*
* input arg: mode: 0 - load both firmware and confing
* 1 - load firmware only
* 2 - load config only
*/
VprocStatusType LoadFwrConfig_Alt(uint8 mode)
{
VprocStatusType status = VPROC_STATUS_SUCCESS;
if ((mode == 0) || (mode == 1)) {
twFirmware st_Firmware;
st_Firmware.st_Fwr = (twFwr *) st_twFirmware;
st_Firmware.twFirmwareStreamLen = (uint16) firmwareStreamLen;
st_Firmware.execAddr = (uint32) executionAddress;
st_Firmware.havePrgmBase = (uint8) haveProgramBaseAddress;
st_Firmware.prgmBase = (uint32) programBaseAddress;
ESP_LOGD(TAG, "Firmware boot loading started ....");
status = VprocTwolfHbiBoot_alt(&st_Firmware);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiBoot()", status);
return -1;
}
ESP_LOGD(TAG, "Loading the image to RAM....done");
#ifdef SAVE_IMAGE_TO_FLASH
ESP_LOGD(TAG, "Saving firmware to flash....");
status = VprocTwolfSaveImgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfSaveImgToFlash()", status);
return status;
}
ESP_LOGD(TAG, "Saving firmware to flash....done");
#endif
status = VprocTwolfFirmwareStart();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfFirmwareStart()", status);
return status;
}
}
if ((mode == 0) || (mode == 2)) {
ESP_LOGD(TAG, "Loading the config file into the device RAM....");
status = VprocTwolfLoadConfig((dataArr *) st_twConfig, (uint16) configStreamLen);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfLoadConfig()", status);
return status;
}
#ifdef SAVE_CFG_TO_FLASH
ESP_LOGD(TAG, "Saving config to flash....");
status = VprocTwolfSaveCfgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfSaveCfgToFlash()", status);
return status;
}
ESP_LOGD(TAG, "Saving config to flash....done");
#endif
}
{ /*Verify that the boot loading PASS or Fail*/
uint16 val = 0;
status = VprocTwolfHbiRead(0x0022, 1, &val);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiRead()", status);
VprocTwolfHbiCleanup();
return -1;
}
if ((val == 38040) || (val == 38050) || (val == 38060) || (val == 38080) || (val == 38051) || (val == 38041)) {
ESP_LOGD(TAG, "Device boot loading completed successfully...");
} else {
ESP_LOGD(TAG, "Device boot loading failed!!!...");
return VPROC_STATUS_FAILURE;
}
}
/*Firmware reset - in order for the configuration to take effect
* NOTE: The ZL38040 needs a soft reset for the uploaded configuration
* to take effect. This soft-reset is sent below
* if the ZL38040 is an I2S slave, if the I2S master is not stable
* at the time of this reset, then that reset will not take effect.
* In that case the host has to to simply resend the reset
* command once the I2S master
* is up and running and is at a stable state.
*/
status = VprocTwolfReset(VPROC_RST_SOFTWARE);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfReset()", status);
return status;
}
ESP_LOGD(TAG, "Device boot loading completed successfully...");
return status;
}
int test_zl38063(void *arg)
{
int status = 0;
uint16 cmdword = 0;
uint16 val[MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST];
uint8 numwords = 0;
uint16 tempbuf[MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST];
uint16 i = 0;
#ifdef TW_HAL_VERIFY_DEBUG
uint16 j = 0;
#endif
status = VprocTwolfHbiInit();
if (status < 0) {
perror("tw_spi_access open");
return -1;
}
if ((MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST > 125) || (MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST < 2)) {
ESP_LOGD(TAG, "MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST must between 2 and 126");
}
memset(val, 0, sizeof(val));
memset(tempbuf, 0, sizeof(tempbuf));
ESP_LOGD(TAG, "Test 1 - Verifying that the device is present and working ....");
cmdword = 0x00C;
numwords = 2;
val[0] = 0x1234;
val[1] = 0x5678;
status = VprocTwolfHbiWrite(cmdword, numwords, val);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiWrite()\n", status);
VprocHALcleanup();
return -1;
}
#ifdef TW_HAL_VERIFY_DEBUG
j = 0;
for (i = 0; i < numwords; i++) {
ESP_LOGD(TAG, "wr: addr 0x%04x = 0x%04x", (cmdword + j), val[i]);
j = j + 2;
}
#endif
status = VprocTwolfHbiRead(cmdword, numwords, tempbuf);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiRead()", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef TW_HAL_VERIFY_DEBUG
j = 0;
for (i = 0; i < numwords; i++) {
ESP_LOGD(TAG, "RD: addr 0x%04x = 0x%04x", (cmdword + j), tempbuf[i]);
j = j + 2;
}
#endif
if ((tempbuf[0] != 0x1234) && (tempbuf[1] != 0x5600)) {
ESP_LOGD(TAG, "Test 1 - completed - FAIL!!!");
return -1;
}
ESP_LOGD(TAG, "Test 1 - completed - PASS\n\n");
status = VprocTwolfReset(0);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiRead()", status);
VprocTwolfHbiCleanup();
return -1;
}
ESP_LOGD(TAG, "Device reset completed successfully...");
ESP_LOGD(TAG, "Test 2 - Verifying single word write/read access ....");
cmdword = 0x0300;
val[0] = 0x4008;
numwords = 1;
status = VprocTwolfHbiWrite(cmdword, numwords, val);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiWrite()", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef TW_HAL_VERIFY_DEBUG
j = 0;
for (i = 0; i < numwords; i++) {
ESP_LOGD(TAG, "wr: addr 0x%04x = 0x%04x", (cmdword + j), val[i]);
j = j + 2;
}
#endif
status = VprocTwolfHbiRead(cmdword, numwords, val);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiRead()", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef TW_HAL_VERIFY_DEBUG
j = 0;
for (i = 0; i < numwords; i++) {
ESP_LOGD(TAG, "RD: addr 0x%04x = 0x%04x\n", (cmdword + j), val[i]);
j = j + 2;
}
#endif
if ((val[0] != 0x4008)) {
ESP_LOGD(TAG, "Test 2 - completed - FAIL!!!");
return -1;
}
ESP_LOGD(TAG, "Test 2 - completed - PASS");
ESP_LOGD(TAG, "Test 3 - Verifying multiple words write/read access ....");
/* Fill the data buffer with unique data values. */
for (i = 0; i < MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST; i++) {
val[i] = i | ((0xFF - i) << 8);
}
cmdword = 0x0300;
numwords = MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST;
status = VprocTwolfHbiWrite(cmdword, numwords, val);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiWrite()", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef TW_HAL_VERIFY_DEBUG
j = 0;
for (i = 0; i < numwords; i++) {
ESP_LOGD(TAG, "twr: addr 0x%04x = 0x%04x", (cmdword + j), val[i]);
j = j + 2;
}
#endif
status = VprocTwolfHbiRead(cmdword, numwords, tempbuf);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiRead()", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef TW_HAL_VERIFY_DEBUG
j = 0;
for (i = 0; i < numwords; i++) {
ESP_LOGD(TAG, "RD: addr 0x%04x = 0x%04x =? 0x%04x", (cmdword + j), tempbuf[i], val[i]);
j = j + 2;
}
#endif
j = 0;
for (i = 0; i < MAX_WORDS_FOR_MULTIWORD_ACCESS_TEST; i++) {
if (tempbuf[i] != val[i]) {
ESP_LOGD(TAG, "RD: addr 0x%04x = 0x%04x =? 0x%04x", (cmdword + j), tempbuf[i], val[i]);
ESP_LOGD(TAG, "Test 3 - completed - FAIL!!!");
return -1;
}
j = j + 2;
}
ESP_LOGD(TAG, "Test 3 - completed - PASS");
ESP_LOGD(TAG, "Test 4 - Verifying the firmware/config boot loading ....");
if (LoadFwrConfig_Alt(0) != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Device boot loading failed.....");
ESP_LOGD(TAG, "Test 4 - completed - FAIL!!!");
} else
ESP_LOGD(TAG, "Test 4 - completed - PASS");
VprocTwolfHbiCleanup();
return 0;
}

View File

@@ -0,0 +1,161 @@
/****************************************************************************
* tw_ldfwcfg.c - To load a *.s3 firmware and/or a *.cr2 into the device
* and optionally save the loaded image to flash
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#include <stdio.h>
#include <stdlib.h> /* malloc, free, rand */
#include "esp_log.h"
#include "vproc_common.h"
#include "vprocTwolf_access.h"
/*NOTE: notice that the *.c code are included in the apps-
* This is because the compiler I'm using requires that
* But if your makefile is such that compiler knows where to find these files
* then remove the #include *.c below
*/
#undef SAVE_CFG_TO_FLASH /*define this macro to save the cfg from RAM to flash*/
static const char *TAG = "TW_LDCFG";
uint16 numElements;
dataArr *pCr2Buf;
/* fseekNunlines() -- The firmware file is an ascii text file.
* the information from fseek will not be useful.
* this is our own fseek equivalent
*/
static unsigned long fseekNunlines(FILE *BOOT_FD)
{
uint32 line_count = 0;
int c;
while ((c = fgetc(BOOT_FD)) != EOF) {
if (c == '\n')
line_count++;
}
return line_count;
}
/* readCfgFile() use this function to
* Read the Voice processing cr2 config file into RAM
* filepath -- pointer to the location where to find the file
* pCr2Buf -- the actual firmware data array will be pointed to this buffer
*/
static int readCfgFile(char *filepath)
{
unsigned int reg[2], val[2], len;
uint8 done = 0;
uint16 index = 0;
FILE *BOOT_FD;
char *s;
char line[512] = "";
BOOT_FD = fopen(filepath, "rb");
if (BOOT_FD != NULL) {
len = fseekNunlines(BOOT_FD);
if (len <= 0) {
ESP_LOGD(TAG, "Error: file is not of the correct format...");
return -1;
}
ESP_LOGD(TAG, "fileLength = %u", len);
/*start at the beginning of the file*/
// fseek(BOOT_FD, 0, SEEK_SET);
/* allocate memory to contain the reg and val:*/
pCr2Buf = (dataArr *) malloc(len * sizeof(dataArr));
if (pCr2Buf == NULL) {
ESP_LOGD(TAG, "not enough memory to allocate %u bytes.. ", len * sizeof(dataArr));
return -1;
}
rewind(BOOT_FD);
/*read and format the data accordingly*/
numElements = 0;
do {
s = fgets(line, 512, BOOT_FD);
if (line[0] == ';') {
continue;
} else if (s != NULL) {
numElements++;
sscanf(line, "%x %c %x", reg, s, val);
pCr2Buf[index].reg = reg[0];
pCr2Buf[index].value = val[0];
// ESP_LOGD(TAG,"pCr2Buf[%d].reg pCr2Buf[%d].value = 0x%04x\t0x%04x\n", index, index,
// pCr2Buf[index].reg, pCr2Buf[index].value);
index++;
} else {
done = 1;
}
} while (done == 0);
fclose(BOOT_FD);
ESP_LOGD(TAG, "size of pCr2Buf = %u bytes.. ", sizeof(pCr2Buf));
} else {
ESP_LOGD(TAG, "Error: can't open file");
}
return 0;
}
/*This example host app load the *.s3 firmware to the device RAM. Optionally save it to flash
* Then start the firmware from the execution address in RAM
* It then stops the firmware - Load the cr2 file into RAM. Optionally save it to flash
* Then restarts the firmware
*/
int main(int argc, char **argv)
{
VprocStatusType status = VPROC_STATUS_SUCCESS;
if (argc != 2) {
ESP_LOGD(TAG, "Error: argc = %d - missing %d arg(s)... ", argc, 3 - (argc - 1));
ESP_LOGD(TAG, "command Usage:%s ConfigPath", argv[0]);
exit(1);
}
ESP_LOGD(TAG, ":%s %s %s", argv[0], argv[1], argv[2]);
/*global file handle*/
status = VprocTwolfHbiInit();
if (status < 0) {
perror("tw_spi_access open");
return -1;
}
if (readCfgFile(argv[1]) < 0) {
ESP_LOGD(TAG, "Error:read %s file", argv[1]);
}
ESP_LOGD(TAG, "a- Reading config file to host RAM - done....");
ESP_LOGD(TAG, "c- Loading the config file into the device RAM");
status = VprocTwolfLoadConfig(pCr2Buf, numElements);
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfLoadConfig()", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef SAVE_CONFIG_TO_FLASH
status = VprocTwolfSaveCfgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfSaveCfgToFlash()", status);
VprocTwolfHbiCleanup();
return -1;
}
ESP_LOGD(TAG, "d- Saving config to flash- done....");
#endif
ESP_LOGD(TAG, "e- Loading config record - done....");
free(pCr2Buf);
pCr2Buf = NULL;
VprocTwolfHbiCleanup();
return 0;
}

View File

@@ -0,0 +1,117 @@
/****************************************************************************
* tw_ldfw.c - To load a *.s3 firmware into the device
* and optionally save the loaded image to flash
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#include "vproc_common.h"
#include "vprocTwolf_access.h"
#include "esp_log.h"
/*NOTE: notice that the *.c code are included in the apps-
* This is because the compiler I'm using requires that
* But if your makefile is such that compiler knows where to find these files
* then remove the #include *.c below
*/
//#undef SAVE_IMAGE_TO_FLASH /*define this macro to save the firmware from RAM to flash*/
static const char *TAG = "TW_LDFW";
/*quick test*/
/*This example host app load the *.s3 firmware to the device RAM. Optionally save it to flash
* Then start the firmware from the execution address in RAM
*/
int main(int argc, char **argv)
{
VprocStatusType status = VPROC_STATUS_SUCCESS;
FILE *BOOT_FD;
char line[256] = "";
if (argc != 2) {
ESP_LOGD(TAG, "Error: argc = %d - missing %d arg(s)... ", argc, 3 - (argc - 1));
ESP_LOGD(TAG, "command Usage:%s firmwarePath", argv[0]);
exit(1);
}
ESP_LOGD(TAG, ":%s %s %s", argv[0], argv[1], argv[2]);
BOOT_FD = fopen(argv[1], "rb");
if (BOOT_FD == NULL) {
ESP_LOGD(TAG, "Error: can't open file %s", argv[1]);
return -1;
}
/*global file handle*/
status = VprocTwolfHbiInit();
if (status < 0) {
perror("tw_spi_access open");
fclose(BOOT_FD);
return -1;
}
ESP_LOGD(TAG, "1- Opening firmware file - done....");
status = VprocTwolfHbiBootPrepare();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiBootPrepare()", status);
fclose(BOOT_FD);
VprocHALcleanup();
return -1;
}
ESP_LOGD(TAG, "-- Boot prepare - done....");
while (fgets(line, 256, BOOT_FD) != NULL) {
status = VprocTwolfHbiBootMoreData(line);
if (status == VPROC_STATUS_BOOT_LOADING_MORE_DATA) {
continue;
} else if (status == VPROC_STATUS_BOOT_LOADING_CMP) {
break;
} else if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiBootMoreData()", status);
fclose(BOOT_FD);
VprocHALcleanup();
return -1;
}
}
ESP_LOGD(TAG, "-- Firmware data transfer - done....");
fclose(BOOT_FD);
/*clean up and verify that the boodloading completed correctly*/
status = VprocTwolfHbiBootConclude();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfHbiBootConclude()", status);
VprocHALcleanup();
return -1;
}
ESP_LOGD(TAG, "2- Loading firmware - done....");
#ifdef SAVE_IMAGE_TO_FLASH
ESP_LOGD(TAG, "-- Saving firmware to flash....");
status = VprocTwolfSaveImgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfSaveImgToFlash()", status);
VprocHALcleanup();
return -1;
}
ESP_LOGD(TAG, "-- Saving firmware to flash....done");
#endif
status = VprocTwolfFirmwareStart();
if (status != VPROC_STATUS_SUCCESS) {
ESP_LOGD(TAG, "Error %d:VprocTwolfFirmwareStart()", status);
VprocHALcleanup();
return -1;
}
ESP_LOGD(TAG, "Device boot loading completed successfully...");
VprocHALcleanup();
return 0;
}

View File

@@ -0,0 +1,223 @@
/****************************************************************************
* tw_ldfwcfg.c - To load a *.s3 firmware and/or a *.cr2 into the device
* and optionally save the loaded image to flash
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#include <stdio.h>
#include <stdlib.h> /* malloc, free, rand */
#include "vproc_common.h"
#include "vprocTwolf_access.h"
/*NOTE: notice that the *.c code are included in the apps-
* This is because the compiler I'm using requires that
* But if your makefile is such that compiler knows where to find these files
* then remove the #include *.c below
*/
#undef SAVE_IMAGE_TO_FLASH /*define this macro to save the firmware from RAM to flash*/
#undef SAVE_CFG_TO_FLASH /*define this macro to save the cfg from RAM to flash*/
/*quick test*/
uint16 numElements;
dataArr *pCr2Buf;
/* fseekNunlines() -- The firmware file is an ascii text file.
* the information from fseek will not be useful.
* this is our own fseek equivalent.
*/
static unsigned long fseekNunlines(FILE *BOOT_FD)
{
uint32 line_count = 0;
int c;
while ((c = fgetc(BOOT_FD)) != EOF) {
if (c == '\n')
line_count++;
}
return line_count;
}
/* readCfgFile() use this function to
* Read the Voice processing cr2 config file into RAM
* filepath -- pointer to the location where to find the file
* pCr2Buf -- the actual firmware data array will be pointed to this buffer
*/
static int readCfgFile(char *filepath)
{
unsigned int reg[2], val[2], len;
uint8 done = 0;
uint16 index = 0;
FILE *BOOT_FD;
char *s;
char line[512] = "";
BOOT_FD = fopen(filepath, "rb");
if (BOOT_FD != NULL) {
len = fseekNunlines(BOOT_FD);
if (len <= 0) {
printf("Error: file is not of the correct format...\n");
return -1;
}
// printf("fileLength = %u\n", len);
/*start at the beginning of the file*/
// fseek(BOOT_FD, 0, SEEK_SET);
/* allocate memory to contain the reg and val:*/
pCr2Buf = (dataArr *) malloc(len * sizeof(dataArr));
if (pCr2Buf == NULL) {
printf("not enough memory to allocate %u bytes.. ", len * sizeof(dataArr));
return -1;
}
rewind(BOOT_FD);
/*read and format the data accordingly*/
numElements = 0;
do {
s = fgets(line, 512, BOOT_FD);
if (line[0] == ';') {
continue;
} else if (s != NULL) {
numElements++;
sscanf(line, "%x %c %x", reg, s, val);
pCr2Buf[index].reg = reg[0];
pCr2Buf[index].value = val[0];
// printf("pCr2Buf[%d].reg pCr2Buf[%d].value = 0x%04x\t0x%04x\n", index, index, pCr2Buf[index].reg,
// pCr2Buf[index].value);
index++;
} else {
done = 1;
}
} while (done == 0);
fclose(BOOT_FD);
// printf ("size of pCr2Buf = %u bytes.. \n", len*sizeof(pCr2Buf));
} else {
printf("Error: can't open file\n");
}
return 0;
}
/*This example host app load the *.s3 firmware to the device RAM. Optionally save it to flash
* Then start the firmware from the execution address in RAM
* It then stops the firmware - Load the cr2 file into RAM. Optionally save it to flash
* Then resstarts the firmware
*/
int main(int argc, char **argv)
{
VprocStatusType status = VPROC_STATUS_SUCCESS;
FILE *BOOT_FD;
char line[256] = "";
if (argc < 3) {
printf("Error: argc = %d - missing %d arg(s)... \n", argc, 3 - (argc - 1));
printf("command Usage:%s firmwarePath ConfigPath\n", argv[0]);
exit(1);
}
printf(":%s %s %s\n", argv[0], argv[1], argv[2]);
BOOT_FD = fopen(argv[1], "rb");
if (BOOT_FD == NULL) {
printf("Error: can't open file %s\n", argv[1]);
return -1;
}
/*global file handle*/
status = VprocTwolfHbiInit();
// gTwolf_fd = open(file_name, O_RDWR);
if (status < 0) {
perror("tw_spi_access open");
fclose(BOOT_FD);
return -1;
}
printf("1- Opening firmware file - done....\n");
status = VprocTwolfHbiBootPrepare();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfHbiBootPrepare()\n", status);
fclose(BOOT_FD);
VprocTwolfHbiCleanup();
return -1;
}
printf("-- Boot prepare - done....\n");
while (fgets(line, 256, BOOT_FD) != NULL) {
status = VprocTwolfHbiBootMoreData(line);
if (status == VPROC_STATUS_BOOT_LOADING_MORE_DATA) {
continue;
} else if (status == VPROC_STATUS_BOOT_LOADING_CMP) {
break;
} else if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfHbiBootMoreData()\n", status);
fclose(BOOT_FD);
VprocTwolfHbiCleanup();
return -1;
}
}
printf("-- Firmware data transfer - done....\n");
fclose(BOOT_FD);
status = VprocTwolfHbiBootConclude();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfHbiBootConclude()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef SAVE_IMAGE_TO_FLASH
printf("-- Saving firmware to flash....\n");
status = VprocTwolfSaveImgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfSaveImgToFlash()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("-- Saving firmware to flash....done\n");
#endif
status = VprocTwolfFirmwareStart();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfFirmwareStart()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("3- Loading the config file into the device RAM\n");
if (readCfgFile(argv[2]) < 0) {
printf("Error:read %s file\n", argv[2]);
}
printf("a- Reading config file to host RAM - done....\n");
status = VprocTwolfLoadConfig(pCr2Buf, numElements);
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfLoadConfig()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
#ifdef SAVE_CFG_TO_FLASH
printf("-- Saving config to flash....\n");
status = VprocTwolfSaveCfgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfSaveCfgToFlash()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("-- Saving config to flash....done\n");
#endif
printf("Device boot loading completed successfully...\n");
VprocTwolfHbiCleanup();
return 0;
}

View File

@@ -0,0 +1,431 @@
/****************************************************************************
* tw_spi_access.c - Demo apps demonstrating how to access registers of the
* device over spi or I2C. Loading a firmware and or config into the device
*
*
****************************************************************************
* Copyright Microsemi Inc, 2018. All rights reserved.
* Licensed under the MIT License. See LICENSE.txt in the project
* root for license information.
*
***************************************************************************/
#include "vproc_common.h"
#include "vprocTwolf_access.h"
/*NOTE: notice that the *.c code are included in the apps-
* This is because the compiler I'm using requires that
* But if your makefile is such that compiler knows where to find these files
* then remove the #include *.c below
*/
#include "zl38063_config.h"
#include "zl38063_firmware.h"
#include "esp_codec_dev_os.h"
#undef SAVE_IMAGE_TO_FLASH /*define this macro to save the firmware from RAM to flash*/
#undef SAVE_CFG_TO_FLASH /*define this macro to save the cfg from RAM to flash*/
#define SAVE_IMAGE_TO_FLASH
#define SAVE_CFG_TO_FLASH
/*quick test*/
/*LoadFwrConfig_Alt - to load a converted *s3, *cr2 to c code into the device.
* Basically instead of loading the *.s3, *cr2 directly,
* use the tw_convert tool to convert the ascii hex fwr mage into code and compile
* with the application
*
* input arg: mode: 0 - load both firmware and confing
* 1 - load firmware only
* 2 - load config only
* -1 - Force loading
*/
int tw_upload_dsp_firmware(int mode)
{
union {
short a;
char b;
} test_bigendian;
if (mode >= 0) {
uint16 vol = 0;
esp_codec_dev_sleep(1000);
int ret = VprocTwolfGetAppStatus(&vol);
if (vol) {
ESP_LOGW(TAG_SPI, "MCS ret:%d,Status:%d", ret, vol);
return 0;
}
ESP_LOGI(TAG_SPI, "** Loading DSP firmware ret:%d,Status:%d **", ret, vol);
} else {
mode = 0;
}
test_bigendian.a = 1;
ESP_LOGI(TAG_SPI, "b=%d", test_bigendian.b);
int status = VprocTwolfHbiInit();
if (status < 0) {
DEBUG_LOGE(TAG_SPI, "tw_spi_access open");
return -1;
}
if ((mode == 0) || (mode == 1)) {
twFirmware st_Firmware;
st_Firmware.st_Fwr = (twFwr *) st_twFirmware;
st_Firmware.twFirmwareStreamLen = (uint16) firmwareStreamLen;
st_Firmware.execAddr = (uint32) executionAddress;
st_Firmware.havePrgmBase = (uint8) haveProgramBaseAddress;
st_Firmware.prgmBase = (uint32) programBaseAddress;
ESP_LOGI(TAG_SPI, "1- Firmware boot loading started ....");
status = VprocTwolfHbiBoot_alt(&st_Firmware);
if (status != VPROC_STATUS_SUCCESS) {
DEBUG_LOGE(TAG_SPI, "Error %d:VprocTwolfHbiBoot()", status);
// VprocTwolfHbiCleanup();
return -1;
}
ESP_LOGI(TAG_SPI, "2- Loading the image to RAM....done");
#ifdef SAVE_IMAGE_TO_FLASH
ESP_LOGI(TAG_SPI, "-- Saving firmware to flash....");
status = VprocTwolfSaveImgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
DEBUG_LOGE(TAG_SPI, "Error %d:VprocTwolfSaveImgToFlash()", status);
// VprocTwolfHbiCleanup();
return status;
}
ESP_LOGI(TAG_SPI, "-- Saving firmware to flash....done");
#endif
status = VprocTwolfFirmwareStart();
if (status != VPROC_STATUS_SUCCESS) {
DEBUG_LOGE(TAG_SPI, "Error %d:VprocTwolfFirmwareStart()", status);
// VprocTwolfHbiCleanup();
return status;
}
}
#if 1
if ((mode == 0) || (mode == 2)) {
ESP_LOGI(TAG_SPI, "3- Loading the config file into the device RAM....");
status = VprocTwolfLoadConfig((dataArr *) st_twConfig, (uint16) configStreamLen);
if (status != VPROC_STATUS_SUCCESS) {
DEBUG_LOGE(TAG_SPI, "Error %d:VprocTwolfLoadConfig()", status);
// VprocTwolfHbiCleanup();
return status;
}
#ifdef SAVE_CFG_TO_FLASH
ESP_LOGI(TAG_SPI, "-- Saving config to flash....");
status = VprocTwolfSaveCfgToFlash();
if (status != VPROC_STATUS_SUCCESS) {
DEBUG_LOGE(TAG_SPI, "Error %d:VprocTwolfSaveCfgToFlash()", status);
// VprocTwolfHbiCleanup();
return status;
}
ESP_LOGI(TAG_SPI, "-- Saving config to flash....done");
#endif
}
/*Firmware reset - in order for the configuration to take effect*/
status = VprocTwolfReset(VPROC_RST_SOFTWARE);
if (status != VPROC_STATUS_SUCCESS) {
DEBUG_LOGE(TAG_SPI, "Error %d:VprocTwolfReset()", status);
ESP_LOGI(TAG_SPI, "Error");
// VprocTwolfHbiCleanup();
return status;
}
#endif
ESP_LOGI(TAG_SPI, "Device boot loading completed successfully...");
return status;
}
int zl38063_comm(int argc, char **argv)
{
VprocStatusType status = VPROC_STATUS_SUCCESS;
if (argc == 1) {
printf("Usage: for help type:%s -h", argv[0]);
exit(1);
}
if (strcmp(argv[1], "-h") == 0) {
printf("\nUsage:\n\t%s [-cmd mode] [options...] see supported"
" command modes below\n\n",
argv[0]);
printf("\t-wr : to write one or more 16-bit words to the device\n"
"\t-rd : to read one or more 16-bit words from the device\n"
"\t-rst : to reset the device in one of these"
" supported reset modes:\n"
"\t\t - [0: RAM | 1: ROM | 2: SOFT | 3: AEC | 4: BOOT]\n");
printf("\t-lfcff : to load a specific firmware and related"
" config from flash - arg: 1 to 14\n");
printf("\t-lfcfh-a : to load a pre-compiled firmware and related config"
" from host via SPI\n");
printf("\t-lffh-a: to load a pre-compiled firmware from host via SPI\n");
printf("\t-lcfh-a: to load a pre-compiled config from host via SPI\n");
printf("\t-fclr : to erase the content of the ZL380xx slave flash\n");
printf("\t-sto : to reset the device into boot mode\n");
printf("\t-sta : to start execution of firmware found at "
"exec address in RAM\n");
printf("\t-apla : to configure the ZL380xx x-point for "
"audio playback mode\n");
printf("\t-arec : to configure the ZL380xx x-point for audio "
"recording mode\n");
printf("Example:\n");
printf("\tEx to write 0x8004 into register 0x0300:"
"\n\t%s -wr 0x0300 0x8004\n\n",
argv[0]);
printf("\tEx to read 12 words starting from register 0x020:"
"\n\t%s -rd 0x0020 12\n\n",
argv[0]);
printf("\tEx to reset the device in boot mode:"
"\n\t%s -rst n 'where n:[1-4]\n\n",
argv[0]);
printf("\tEx to load to RAM a firmware and config previously"
" saved to flash at index 1:\n\t%s -lfcff 1\n\n",
argv[0]);
printf("\tEx to load to RAM a firmware previously"
" saved to flash at index 1:\n\t%s -lfff 1\n\n",
argv[0]);
printf("\tEx to load to RAM the pre-compiled (in)firmware "
"from teh host "
"HBI (SPI):\n\t%s -lffh-a\n\n",
argv[0]);
printf("\tEx to load to RAM the pre-compiled (in)config "
"from teh host "
"HBI (SPI):\n\t%s -lcfh-a\n\n",
argv[0]);
printf("\tEx to load to RAM the pre-compiled (in)firmware and config "
"from teh host "
"HBI (SPI):\n\t%s -lfcfh-a\n\n",
argv[0]);
printf("\tEx to stop the firmware currently running and clear "
"the RAM:\n\t%s -sto\n\n",
argv[0]);
printf("\tEx to start a firmware previously loaded into "
"RAM:\n\t%s -sta\n\n",
argv[0]);
printf("\tEx to mute SOUT :\n\t%s -mute_s [1 | 0]\n\n", argv[0]);
printf("\tEx to mute ROUT :\n\t%s -mute_r [1 | 0]\n\n", argv[0]);
printf("\tEx to erase the slave flash device controlled by "
"the ZL380xx :\n\t%s -fclr\n\n",
argv[0]);
printf("\tEx to configure the device for recording mode at a "
"desired clock and sample rates"
" with AEC off[0] or on [1]:\n\t%s -arec clkrate "
"fsrate n 'where n:[0 | 1]'\n\n",
argv[0]);
printf("\tEx to configure the device for playback mode at a "
"desired clock and sample rates"
" with AEC off[0] or on [1]:\n\t%s -apla clkrate "
"fsrate n 'where n:[0 | 1]'\n\n",
argv[0]);
return -1;
}
if ((argc < 3) && (strcmp(argv[1], "-wr") == 0)) {
printf("Usage:%s -wr register value0 value1....value124 \n", argv[0]);
return -1;
}
if ((argc < 3) && (strcmp(argv[1], "-rd") == 0)) {
printf("Usage:%s -rd register n 'where n:[1-127]'\n", argv[0]);
return -1;
}
if ((argc < 3) && (strcmp(argv[1], "-rst") == 0)) {
printf("Usage:%s -rst n 'where n:[0-4]'\n", argv[0]);
return -1;
}
if ((argc < 3) && (strcmp(argv[1], "-apla") == 0)) {
printf("Usage:%s -apla <clkrate in KHz> <fsrate in Hz> n"
" 'where n:[0 | 1]'\n",
argv[0]);
return -1;
}
if ((argc < 3) && (strcmp(argv[1], "-arec") == 0)) {
printf("Usage:%s -arec <clkrate in KHz> <fsrate in Hz> n"
" 'where n:[0 | 1]'\n",
argv[0]);
return -1;
}
if ((argc < 3) && (strcmp(argv[1], "-lfcff") == 0)) {
printf("Usage:%s -lfcfh 1\n", argv[0]);
return -1;
}
/*global file handle*/
status = VprocTwolfHbiInit();
if (status < 0) {
perror("tw_spi_access open");
return -1;
}
if ((strcmp(argv[1], "-wr") == 0) || (strcmp(argv[1], "-rd") == 0)) {
int i = 0, j = 0;
unsigned short val[128];
unsigned short cmdword = (unsigned short) strtoul(argv[2], NULL, 0);
unsigned char numwords = 0;
memset(val, 0, sizeof(val));
if (strcmp(argv[1], "-wr") == 0) { /*for WRITING 1 or more ZL380xx registers*/
unsigned short val[128];
numwords = argc - 3; /*calculate the number of words to write*/
;
for (i = 0; i < numwords; i++) {
val[i] = (unsigned short) strtoul(argv[3 + i], NULL, 0);
}
status = VprocTwolfHbiWrite(cmdword, numwords, val);
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfHbiWrite()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
for (i = 0; i < numwords; i++) {
printf("wr: addr 0x%04x = 0x%04x\n", (cmdword + j), val[i]);
j = j + 2;
}
} else { /*for READING 1 or more ZL380xx registers**/
numwords = (unsigned char) strtoul(argv[3], NULL, 0);
if ((numwords == 0) || (numwords > 128)) {
printf("number of words is out of range. Maximum is 128\n");
VprocTwolfHbiCleanup();
return -1;
}
status = VprocTwolfHbiRead(cmdword, numwords, val);
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfHbiRead()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
for (i = 0; i < numwords; i++) {
printf("RD: addr 0x%04x = 0x%04x\n", (cmdword + j), val[i]);
j = j + 2;
}
}
} else if (strcmp(argv[1], "-rst") == 0) { /*for RESETTING ZL380xx*/
unsigned char rstMode = (unsigned char) strtoul(argv[2], NULL, 0);
status = VprocTwolfReset((uint16) rstMode);
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfHbiRead()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("Device reset completed successfully...\n");
} else if (strcmp(argv[1], "-lfcff") == 0) {
/*Load ZL380x0 firmware + related config record from flash*/
unsigned short image_num = (unsigned short) strtoul(argv[2], NULL, 0);
status = VprocTwolfFirmwareStop();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfFirmwareStop()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
status = VprocTwolfLoadFwrCfgFromFlash(image_num);
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfLoadFwrCfgFromFlash()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
status = VprocTwolfReset(VPROC_RST_HARDWARE_RAM);
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfReset()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("Device boot loading from flash completed successfully...\n");
} else if (strcmp(argv[1], "-lfff") == 0) {
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfLoadFwrFromFlash()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("Device boot loading from flash completed successfully...\n");
} else if (strcmp(argv[1], "-lfcfh-a") == 0) { /*for LOADING FWR/CFG via SPI*/
if (tw_upload_dsp_firmware(0) != VPROC_STATUS_SUCCESS)
printf("Device boot loading failed.....\n");
} else if (strcmp(argv[1], "-lcfh-a") == 0) { /*for LOADING CFG via SPI*/
if (tw_upload_dsp_firmware(2) != VPROC_STATUS_SUCCESS)
printf("Device boot loading failed.....\n");
} else if (strcmp(argv[1], "-lffh-a") == 0) { /*for LOADING FWR via SPI*/
if (tw_upload_dsp_firmware(1) != VPROC_STATUS_SUCCESS)
printf("Device boot loading failed.....\n");
} else if (strcmp(argv[1], "-sto") == 0) { /*for resetting into boot mode*/
if (VprocTwolfFirmwareStop() != 0)
VprocTwolfHbiCleanup();
else
printf("Firmware stopped to boot mode completed"
" successfully...\n");
} else if (strcmp(argv[1], "-sta") == 0) { /*start executing FWR/CFG */
if (VprocTwolfFirmwareStart() != 0)
VprocTwolfHbiCleanup();
else
printf("Firmware is now running successfully...\n");
} else if (strcmp(argv[1], "-mute_r") == 0) { /*start executing FWR/CFG */
uint8 mute = (uint8) strtoul(argv[2], NULL, 0);
// to do need fix
// if(VprocTwolfMute(VPROC_ROUT, mute) != 0)
if (1) {
VprocTwolfHbiCleanup();
} else {
if (mute)
printf("ROUT Port muted sucessfully...\n");
else
printf("ROUT Port unmuted sucessfully...\n");
}
} else if (strcmp(argv[1], "-mute_s") == 0) { /*start executing FWR/CFG */
uint8 mute = (uint8) strtoul(argv[2], NULL, 0);
// to do need fix
// if(VprocTwolfMute(VPROC_SOUT, mute) != 0)
if (1)
VprocTwolfHbiCleanup();
else {
if (mute)
printf("SOUT Port muted sucessfully...\n");
else
printf("SOUT Port unmuted sucessfully...\n");
}
} else if ((strcmp(argv[1], "-arec") == 0) || (strcmp(argv[1], "-apla") == 0))
/* configure the ZL380x0 for either audio recording or playback
* Over an I2S link
*/
{
unsigned short pclkrate = (unsigned short) strtoul(argv[2], NULL, 0);
unsigned short fsrate = (unsigned short) strtoul(argv[3], NULL, 0);
unsigned short aecState = (unsigned char) strtoul(argv[4], NULL, 0);
printf("pclkrate = %u KHz, fsrate = %u Hz, AEC state = %d\n", pclkrate, fsrate, aecState);
// to do need fix
#if 0
if (strcmp(argv[1], "-arec") == 0) {
if (VprocTwolfUpstreamConfigure(pclkrate, fsrate, aecState) != 0)
VprocTwolfHbiCleanup();
else
printf("Device configured for audio recording...\n");
} else if (strcmp(argv[1], "-apla") == 0) {
if (VprocTwolfDownstreamConfigure(pclkrate, fsrate, aecState) != 0)
VprocTwolfHbiCleanup();
else
printf("Device configured for audio playback...\n");
}
#endif
} else if (strcmp(argv[1], "-fclr") == 0) {
/*Erase the full content of the ZL380x0 controlled slave flash*/
status = VprocTwolfEraseFlash();
if (status != VPROC_STATUS_SUCCESS) {
printf("Error %d:VprocTwolfEraseFlash()\n", status);
VprocTwolfHbiCleanup();
return -1;
}
printf("flash erasing completed successfully...\n");
} else {
printf("Usage: for help type:\n%s -h\n", argv[0]);
}
printf("\n");
return 0;
}

View File

@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*Configuration file version: Microsemi_ZLS38063_1_P1_4_0_Config.cr2, modified: Tue Sep 18 20:48:31 2018*/
#ifndef _ZL38063_CONFIG_H_
#define _ZL38063_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
extern const unsigned short configStreamLen;
extern const dataArr st_twConfig[];
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*Firmware Version : Microsemi_ZLS38063_1_P1_4_0_Firmware.s3, modified: Tue Sep 18 20:50:24 2018 */
#ifndef _ZL38063_FIRMWARE_H_
#define _ZL38063_FIRMWARE_H_
#ifdef __cplusplus
extern "C" {
#endif
extern const twFwr st_twFirmware[];
extern const unsigned short firmwareStreamLen;
extern const unsigned long programBaseAddress;
extern const unsigned long executionAddress;
extern const unsigned char haveProgramBaseAddress;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,312 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_log.h"
#include "zl38063_codec.h"
#include "esp_codec_dev_vol.h"
#include "tw_spi_access.h"
#include "vproc_common.h"
#define TAG "zl38063"
#define HBI_PAGED_READ(offset, length) ((uint16_t) (((uint16_t) (offset) << 8) | (length)))
#define HBI_PAGED_WRITE(offset, length) ((uint16_t) (HBI_PAGED_READ(offset, length) | 0x0080))
#define HBI_SELECT_PAGE(page) ((uint16_t) (0xFE00 | (page)))
#define HBI_DIRECT_READ(offset, length) ((uint16_t) (0x8000 | ((uint16_t) (offset) << 8) | (length)))
#define HBI_DIRECT_WRITE(offset, length) ((uint16_t) (HBI_DIRECT_READ(offset, length) | 0x0080))
typedef struct {
audio_codec_if_t base;
const audio_codec_ctrl_if_t *ctrl_if;
const audio_codec_gpio_if_t *gpio_if;
bool is_open;
bool enabled;
bool pa_reverted;
int16_t pa_pin;
int16_t reset_pin;
float hw_gain;
} audio_codec_zl38063_t;
static uint16_t convert_edian(uint16_t v)
{
return (v >> 8) | ((v & 0xFF) << 8);
}
static void get_write_cmd(uint16_t addr, int size, uint16_t *dst, int *n)
{
uint8_t page;
uint8_t offset;
page = addr >> 8;
offset = (addr & 0xFF) / 2;
if (page == 0) {
dst[(*n)++] = convert_edian(HBI_DIRECT_WRITE(offset, size - 1));
}
if (page) {
/*indirect page access*/
if (page != 0xFF) {
page -= 1;
}
dst[(*n)++] = convert_edian(HBI_SELECT_PAGE(page));
dst[(*n)++] = convert_edian(HBI_PAGED_WRITE(offset, size - 1));
}
}
static void get_read_cmd(uint16_t addr, int size, uint16_t *dst, int *n)
{
uint8_t page;
uint8_t offset;
page = addr >> 8;
offset = (addr & 0xFF) / 2;
if (page == 0) {
dst[(*n)++] = convert_edian(HBI_DIRECT_READ(offset, size - 1));
}
if (page) {
// Indirect page access
if (page != 0xFF) {
page -= 1;
}
dst[(*n)++] = convert_edian(HBI_SELECT_PAGE(page));
dst[(*n)++] = convert_edian(HBI_PAGED_READ(offset, size - 1));
}
}
static int read_addr(audio_codec_zl38063_t *codec, uint16_t addr, int words, uint16_t *data)
{
int total_addr = 0;
int n = 0;
get_read_cmd(addr, words, (uint16_t *) &total_addr, &n);
if (codec->ctrl_if->read_reg) {
int ret =
codec->ctrl_if->read_reg(codec->ctrl_if, total_addr, n * sizeof(uint16_t), data, words * sizeof(uint16_t));
for (int i = 0; i < words; i++) {
data[i] = convert_edian(data[i]);
}
return ret;
}
return ESP_CODEC_DEV_NOT_SUPPORT;
}
static int write_addr(audio_codec_zl38063_t *codec, uint16_t addr, int words, uint16_t *data)
{
int total_addr = 0;
int n = 0;
get_write_cmd(addr, words, (uint16_t *) &total_addr, &n);
if (codec->ctrl_if->write_reg) {
for (int i = 0; i < words; i++) {
data[i] = convert_edian(data[i]);
}
return codec->ctrl_if->write_reg(codec->ctrl_if, total_addr, n * sizeof(uint16_t), data,
words * sizeof(uint16_t));
}
return ESP_CODEC_DEV_NOT_SUPPORT;
}
static int get_status(audio_codec_zl38063_t *codec, uint16_t *status)
{
return read_addr(codec, 0x030, 1, status);
}
static int zl38063_pa_power(audio_codec_zl38063_t *codec, bool on)
{
int16_t pa_pin = codec->pa_pin;
if (pa_pin != -1 && codec->gpio_if != NULL) {
codec->gpio_if->setup(pa_pin, AUDIO_GPIO_DIR_OUT, AUDIO_GPIO_MODE_FLOAT);
codec->gpio_if->set(pa_pin, codec->pa_reverted ? !on: on);
}
return ESP_CODEC_DEV_OK;
}
static int zl38063_reset(audio_codec_zl38063_t *codec, bool on)
{
int16_t reset_pin = codec->reset_pin;
if (reset_pin != -1 && codec->gpio_if != NULL) {
codec->gpio_if->setup(reset_pin, AUDIO_GPIO_DIR_OUT, AUDIO_GPIO_MODE_FLOAT);
codec->gpio_if->set(reset_pin, !on);
}
return ESP_CODEC_DEV_OK;
}
static int _set_vol(audio_codec_zl38063_t *codec, uint8_t vol)
{
uint16_t reg = vol + (vol << 8);
int ret = write_addr(codec, 0x238, 1, &reg);
ret |= write_addr(codec, 0x23A, 1, &reg);
return ret == 0 ? ESP_CODEC_DEV_OK : ESP_CODEC_DEV_WRITE_FAIL;
}
int zl38063_get_vol(audio_codec_zl38063_t *codec, float *vol)
{
uint16_t reg = 0;
int ret = read_addr(codec, 0x238, 1, &reg);
*vol = (int8_t) (reg >> 8);
return ret;
}
static int zl38063_open(const audio_codec_if_t *h, void *cfg, int cfg_size)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
zl38063_codec_cfg_t *codec_cfg = (zl38063_codec_cfg_t *) cfg;
if (codec == NULL || codec_cfg->ctrl_if == NULL || cfg_size != sizeof(zl38063_codec_cfg_t)) {
return ESP_CODEC_DEV_INVALID_ARG;
}
codec->ctrl_if = codec_cfg->ctrl_if;
codec->gpio_if = codec_cfg->gpio_if;
codec->pa_pin = codec_cfg->pa_pin;
codec->reset_pin = codec_cfg->reset_pin;
codec->pa_reverted = codec_cfg->pa_reverted;
uint16_t status = 0;
VprocSetCtrlIf((void *) codec_cfg->ctrl_if);
zl38063_reset(codec, true);
int ret = get_status(codec, &status);
if (ret != 0) {
ESP_LOGE(TAG, "Fail to write register");
return ESP_CODEC_DEV_WRITE_FAIL;
}
if (status == 0) {
ESP_LOGI(TAG, "Start upload firmware");
ret = tw_upload_dsp_firmware(0);
if (ret != 0) {
ESP_LOGE(TAG, "Fail to upload firmware");
return ESP_CODEC_DEV_WRITE_FAIL;
}
}
codec->is_open = true;
return ESP_CODEC_DEV_OK;
}
static int zl38063_enable(const audio_codec_if_t *h, bool enable)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
if (codec == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
if (codec->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
if (codec->enabled == enable) {
return ESP_CODEC_DEV_OK;
}
zl38063_pa_power(codec, enable);
codec->enabled = enable;
ESP_LOGD(TAG, "Codec is %s", enable ? "enabled" : "disabled");
return ESP_CODEC_DEV_OK;
}
static int zl38063_set_vol(const audio_codec_if_t *h, float db_vol)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
if (codec == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
if (codec->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
db_vol -= codec->hw_gain;
if (db_vol < -90.0) {
db_vol = -90.0;
} else if (db_vol > 6.0) {
db_vol = 6.0;
}
int8_t reg = (int8_t) db_vol;
int ret = _set_vol(codec, reg);
ESP_LOGD(TAG, "Set vol reg:%d", reg);
return ret;
}
static int zl38063_close(const audio_codec_if_t *h)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
if (codec == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
if (codec->is_open) {
zl38063_pa_power(codec, false);
codec->is_open = false;
}
zl38063_reset(codec, false);
VprocSetCtrlIf(NULL);
return ESP_CODEC_DEV_OK;
}
static int zl38063_set_reg(const audio_codec_if_t *h, int reg, int value)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
if (codec == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
if (codec->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
return write_addr(codec, (uint16_t) reg, 1, (uint16_t *) &value);
}
static int zl38063_get_reg(const audio_codec_if_t *h, int reg, int *value)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
if (codec == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
if (codec->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
*value = 0;
return read_addr(codec, reg, 1, (uint16_t *) value);
}
static int zl38063_set_fs(const audio_codec_if_t *h, esp_codec_dev_sample_info_t *fs)
{
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) h;
if (codec == NULL) {
return ESP_CODEC_DEV_INVALID_ARG;
}
if (codec->is_open == false) {
return ESP_CODEC_DEV_WRONG_STATE;
}
if (fs->channel != 2 || fs->sample_rate != 48000 || fs->bits_per_sample != 16) {
ESP_LOGE(TAG, "Firmware only support 48k 2channel 16 bits");
return ESP_CODEC_DEV_NOT_SUPPORT;
}
return ESP_CODEC_DEV_OK;
}
const audio_codec_if_t *zl38063_codec_new(zl38063_codec_cfg_t *codec_cfg)
{
// verify param
if (codec_cfg == NULL || codec_cfg->ctrl_if == NULL) {
ESP_LOGE(TAG, "Wrong codec config");
return NULL;
}
if (codec_cfg->ctrl_if->is_open(codec_cfg->ctrl_if) == false) {
ESP_LOGE(TAG, "Control interface not open yet");
return NULL;
}
audio_codec_zl38063_t *codec = (audio_codec_zl38063_t *) calloc(1, sizeof(audio_codec_zl38063_t));
if (codec == NULL) {
ESP_LOGE(TAG, "No memory for instance");
return NULL;
}
codec->ctrl_if = codec_cfg->ctrl_if;
codec->base.open = zl38063_open;
codec->base.enable = zl38063_enable;
codec->base.set_vol = zl38063_set_vol;
codec->base.set_reg = zl38063_set_reg;
codec->base.get_reg = zl38063_get_reg;
codec->base.set_fs = zl38063_set_fs;
codec->base.close = zl38063_close;
codec->hw_gain = esp_codec_dev_col_calc_hw_gain(&codec_cfg->hw_gain);
do {
int ret = codec->base.open(&codec->base, codec_cfg, sizeof(zl38063_codec_cfg_t));
if (ret != 0) {
ESP_LOGE(TAG, "Open fail");
break;
}
return &codec->base;
} while (0);
if (codec) {
free(codec);
}
return NULL;
}