component/bt: remove source codes from esp-audio modules;
This commit is contained in:
parent
d7c1c0b1f6
commit
fa72a98635
61 changed files with 6 additions and 222906 deletions
|
@ -1 +0,0 @@
|
|||
*.o
|
|
@ -1,30 +0,0 @@
|
|||
menu "EspAudio"
|
||||
|
||||
config AUDIO_PLAYER_EN
|
||||
bool "Enable ESP player"
|
||||
default y
|
||||
config AUDIO_RECORDER_EN
|
||||
bool "Enable ESP recorder"
|
||||
default y
|
||||
config AUDIO_LOG_ERROR_EN
|
||||
bool "Enable Audio error message"
|
||||
default y
|
||||
help
|
||||
Disable it will redurce error information and run faster
|
||||
config AUDIO_LOG_WARN_EN
|
||||
bool "Enable Audio warning message"
|
||||
default y
|
||||
help
|
||||
Disable it will redurce warning information and run faster
|
||||
config AUDIO_LOG_INFO_EN
|
||||
bool "Enable Audio normal message"
|
||||
default y
|
||||
help
|
||||
Disable it will redurce normal information and run faster
|
||||
config AUDIO_LOG_DEBUG_EN
|
||||
bool "Enable Audio debug message"
|
||||
default n
|
||||
help
|
||||
Disable it will redurce debug information and run faster
|
||||
|
||||
endmenu
|
|
@ -1,4 +0,0 @@
|
|||
#This is Espressif Audio Platform
|
||||
|
||||
# Setting Up ESP-IDF
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
COMPONENT_ADD_INCLUDEDIRS := include player/inc recorder/inc \
|
||||
../media_hal/include \
|
||||
../misc/include
|
||||
|
||||
COMPONENT_SRCDIRS := player recorder
|
||||
|
||||
include $(IDF_PATH)/make/component_common.mk
|
||||
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ESP_AUDIO
|
||||
#define ESP_AUDIO
|
||||
#include "esp_types.h"
|
||||
#include "EspAudioCom.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Maximum size of the URI, including null character.
|
||||
*/
|
||||
//#define MAX_URI_SIZE 1024
|
||||
|
||||
/*
|
||||
* Defines various states that the ESP player can be.
|
||||
*/
|
||||
enum EspAudioState
|
||||
{
|
||||
AUDIOSTATE_UNINITIALIZED = 0, /* player is not initialized */
|
||||
AUDIOSTATE_IDLE, /* player is idle */
|
||||
AUDIOSTATE_STOPPED, /* player is stopled */
|
||||
AUDIOSTATE_TRANSIT, /* player is busy in a transition */
|
||||
AUDIOSTATE_PLAYING, /* player is currently playing */
|
||||
AUDIOSTATE_PAUSED, /* player is in the paused state for playback */
|
||||
AUDIOSTATE_ENDED, /* player finished decoding player, without user request. */
|
||||
AUDIOSTATE_ERROR, /* player was given a URI that could not be played */
|
||||
|
||||
AUDIOSTATE_UNKNOWN /* unknown playstate */
|
||||
};
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
InputSrcType_NetSpec = 0, ///< Specify audio file from internet.
|
||||
InputSrcType_NetLiving = 1, ///< Living audio stream from internet,e.g.m3u8
|
||||
InputSrcType_LocalFile = 2, ///< Local file which store in the SD card
|
||||
InputSrcType_Stream = 3, ///< Only audio stream,e.g.PCM
|
||||
InputSrcType_Max
|
||||
} InputSrcType;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EspAudioErr_NoErr =0, ///< No error
|
||||
EspAudioErr_InvalidPara, ///< Invalid parameters
|
||||
EspAudioErr_NoMem, ///< Malloc failed
|
||||
EspAudioErr_HardwareErr, ///< Hardware error
|
||||
EspAudioErr_OutOfRange, ///< length of URI is too long.
|
||||
EspAudioErr_NotSupport, ///< Not support the
|
||||
|
||||
} EspAudioErr;
|
||||
|
||||
|
||||
/*
|
||||
* Initializes the ESP player library.
|
||||
*/
|
||||
void EspAudio_Init(void);
|
||||
|
||||
/*
|
||||
* Cleans up the ESP player library.
|
||||
*/
|
||||
void EspAudio_UnInit(void);
|
||||
|
||||
/*
|
||||
* Play, stop, pause the streaming and output of player
|
||||
* EspAudio_Init must be called before these methods work.
|
||||
*/
|
||||
int EspAudio_SetupStream(const char* URI, InputSrcType UriType);
|
||||
/*
|
||||
* Call this method to transition to playing state.
|
||||
*
|
||||
* Returns nonzero if an error occurred.
|
||||
*/
|
||||
int EspAudio_Play(void);
|
||||
|
||||
/*
|
||||
* Call this method to stop playing ESP player.
|
||||
*
|
||||
* Returns nonzero if an error occurred.
|
||||
*/
|
||||
int EspAudio_Stop(void);
|
||||
|
||||
/*
|
||||
* Call this method to pause the playing ESP player.
|
||||
*
|
||||
* Returns nonzero if an error occurred.
|
||||
*/
|
||||
int EspAudio_Pause(void);
|
||||
|
||||
/*
|
||||
* Returns the playstate of the ESP player library.
|
||||
* Returns MEDIA_UNKNOWN if the stream could not be found.
|
||||
*/
|
||||
enum EspAudioState EspAudio_GetPlayState(void);
|
||||
|
||||
/*
|
||||
* Get the player volume level . Volume level is from 0 to 100.
|
||||
* Returns a negative value if the stream could not be found or the value is unknown.
|
||||
*/
|
||||
int EspAudio_GetVolume(int *level);
|
||||
|
||||
/*
|
||||
* Set the player volume level . Volume level is from 0 to 100.
|
||||
* Returns a negative value if the stream could not be found or the value is unknown.
|
||||
*/
|
||||
int EspAudio_SetVolume(int level);
|
||||
|
||||
/*
|
||||
* Call this method to configrate stream information.
|
||||
*
|
||||
* Returns nonzero if an error occurred.
|
||||
*/
|
||||
EspAudioErr EspAudioPlayerStreamCfg(uint32_t rate, uint32_t channel,uint32_t bitLen);
|
||||
|
||||
/*
|
||||
* Call this method to flush stream data to driver.
|
||||
*
|
||||
* Returns nonzero if an error occurred.
|
||||
*
|
||||
* Note:Timeout portMAX_DELAY-block; others,unblock.
|
||||
*/
|
||||
EspAudioErr EspAudioPlayerStreamWrite(uint8_t *inData, uint32_t inSize, uint32_t timeout);
|
||||
|
||||
/*
|
||||
* Call this method to stop once stream write.
|
||||
*
|
||||
* Returns nonzero if an error occurred.
|
||||
*
|
||||
*/
|
||||
EspAudioErr EspAudioPlayerStreamWriteEnd(void);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESPAUDIOCOM_H
|
||||
#define _ESPAUDIOCOM_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "audio_log.h"
|
||||
#include "EspAudioCom.h"
|
||||
|
||||
#define ESP_AUDIO_RELEASE_MAJOR (0000)
|
||||
#define ESP_AUDIO_RELEASE_MINOR (52)
|
||||
#define ESP_AUDIO_RELEASE_VER "0.52"
|
||||
|
||||
// Specified audio buffer address
|
||||
#define AUDIO_BUFFER_ADDR (0x3f800000) // For external RAM
|
||||
|
||||
// Specified aduio buffer size
|
||||
#ifdef AUDIO_BUFFER_ADDR
|
||||
#define AUDIO_BUFFER_SIZE (1024*1024)
|
||||
#else
|
||||
#define AUDIO_BUFFER_SIZE (25000)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type;
|
||||
char str[1024];
|
||||
} UrlInfo;
|
||||
|
||||
|
||||
typedef enum {
|
||||
StreamType_Opus,
|
||||
StreamType_Pcm, // it will be support
|
||||
StreamType_Max,
|
||||
} StreamType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
StreamSampleRate_8k = 8000,
|
||||
StreamSampleRate_16k = 16000, // This is support
|
||||
StreamSampleRate_22K = 22050,
|
||||
StreamSampleRate_32K = 32000,
|
||||
StreamSampleRate_44k = 44100,
|
||||
StreamSampleRate_48k = 48000,
|
||||
StreamSampleRate_Max,
|
||||
} StreamSampleRate;
|
||||
|
||||
|
||||
typedef enum {
|
||||
StreamBitLen_8BIT = 8,
|
||||
StreamBitLen_16BIT = 16,
|
||||
StreamBitLen_24BIT = 24,
|
||||
StreamBitLen_32BIT = 32,
|
||||
StreamBitLen_Max,
|
||||
} StreamBitLen;
|
||||
|
||||
|
||||
typedef enum {
|
||||
StreamChannel_One, // it will be support
|
||||
StreamChannel_Two,
|
||||
StreamChannel_Max,
|
||||
} StreamChannel;
|
||||
|
||||
#endif /* _ESPAUDIOCOM_H */
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESPAUDIORECORDER_H__
|
||||
#define __ESPAUDIORECORDER_H__
|
||||
#include "esp_types.h"
|
||||
#include "EspAudio.h"
|
||||
|
||||
|
||||
//Type Definitions
|
||||
typedef void (*Callback_RecordData)(void *recBuf, uint32_t *recLen);
|
||||
|
||||
typedef enum {
|
||||
RecorderState_Unknown = 0,
|
||||
RecorderState_Init,
|
||||
RecorderState_Stoped,
|
||||
RecorderState_Recording,
|
||||
RecorderState_Paused,
|
||||
} RecorderState;
|
||||
|
||||
typedef enum {
|
||||
EncodeType_Opus = 1,
|
||||
EncodeType_Pcm,
|
||||
EncodeType_Max,
|
||||
} EncodeType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
RecorderSampleRate_8k = 8000, // it will be support
|
||||
RecorderSampleRate_16k = 16000,
|
||||
RecorderSampleRate_Max,
|
||||
} RecorderSampleRate;
|
||||
|
||||
|
||||
typedef enum {
|
||||
RecorderChannel_One = 1,
|
||||
RecorderChannel_Two, // it will be support
|
||||
RecorderChannel_Max,
|
||||
} RecorderChannel;
|
||||
|
||||
|
||||
typedef struct {
|
||||
RecorderSampleRate rate;
|
||||
RecorderChannel channel;
|
||||
EncodeType encodeType;
|
||||
Callback_RecordData func;
|
||||
} RecorderAttr;
|
||||
|
||||
|
||||
EspAudioErr EspAudioRecorderStart(RecorderAttr *recorderAttr);
|
||||
EspAudioErr EspAudioRecorderStop(void);
|
||||
EspAudioErr EspAudioRecorderPause(void);
|
||||
EspAudioErr EspAudioRecorderResume(void);
|
||||
EspAudioErr EspAudioRecorderStateGet(RecorderState *state);
|
||||
EspAudioErr EspAudioRecorderInit(void);
|
||||
EspAudioErr EspAudioRecorderUninit(void);
|
||||
|
||||
|
||||
#endif //__ESPAUDIORECORDER_H__
|
|
@ -1,855 +0,0 @@
|
|||
#include <string.h>
|
||||
#include "esp_types.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "errno.h"
|
||||
#include "audio_log.h"
|
||||
#include "inc/DownloadTask.h"
|
||||
#include "inc/M3u8.h"
|
||||
#include "EspAudioCom.h"
|
||||
#include "EspAudio.h"
|
||||
|
||||
#include "inc/MediaDecoderTask.h"
|
||||
#include "Storage.h"
|
||||
#include "MediaHal.h"
|
||||
#include "Utility.h"
|
||||
|
||||
#define PRIO_DOWNLOAD 19
|
||||
#define DEFAULT_AAC_SEQ 0xFFFFFFFF
|
||||
#define REQUEST_BUF_LEN 1024
|
||||
#define RECV_BUF_LEN 1500
|
||||
|
||||
|
||||
#if 1
|
||||
#define DEBUGHTTP printf
|
||||
#else
|
||||
#define DEBUGHTTP
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t fileTaskState = 0;
|
||||
uint32_t m3u8TaskState = 0;
|
||||
void m3u8DownloadTask(void *pvParameters);
|
||||
void fileDownloadTask(void *pvParameters);
|
||||
|
||||
typedef struct {
|
||||
int status; // 1:downloading; 2:finished
|
||||
char *reqBuf;
|
||||
char *recvBuf;
|
||||
int blockQuit;
|
||||
int receivedSize;
|
||||
uint32_t remaindSize;
|
||||
uint32_t downloadedSize;
|
||||
uint32_t contentTotalSize;
|
||||
UriSrcAttr uri;
|
||||
} HttpObj;
|
||||
|
||||
|
||||
typedef struct {
|
||||
TaskState state;
|
||||
pthread_t thread;
|
||||
int threadQuit;
|
||||
} DownloadInstance;
|
||||
|
||||
|
||||
static HttpObj localHttp;
|
||||
//static mutex_t downloadMutex;
|
||||
static UrlInfo actLiveUrl;
|
||||
|
||||
DownloadInstance dlInstance = { 0 };
|
||||
|
||||
typedef void (*Callback_Recv)(HttpObj *obj);
|
||||
|
||||
int checkIsReqOk(char *buf)
|
||||
{
|
||||
char *l = strstr(buf, "HTTP/1.1 2");
|
||||
if (NULL == l) {
|
||||
l = strstr(buf, "HTTP/1.0 2");
|
||||
if (NULL == l) {
|
||||
l = strstr(buf, "HTTP/1.0 3");
|
||||
if (NULL == l) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int getLocation (const char *buf, char* dest)
|
||||
{
|
||||
// Location: http://119.90.25.49/live.xmcdn.com/192.168.3.134/live/38/24/161118_174054_588.aac
|
||||
char *l = strstr(buf, "Location:");
|
||||
if (NULL == l) {
|
||||
LOGE("Can't find Location:%s", buf);
|
||||
return -1;
|
||||
}
|
||||
l += 10;
|
||||
int i1 = 0;
|
||||
if (l != NULL) {
|
||||
while (*l != '\r') {
|
||||
dest[i1++] = *(l++);
|
||||
if (i1 > ESP_URI_LEN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGE("Can't find Location:%s", buf);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getFileLength(char *buf)
|
||||
{
|
||||
char *l = strstr(buf, "Content-Length:");
|
||||
if (NULL == l) {
|
||||
LOGE("Can't find length:%s", buf);
|
||||
return 0;
|
||||
}
|
||||
l += 16;
|
||||
char len[32] = {0};
|
||||
int i1 = 0;
|
||||
if (l != NULL) {
|
||||
while (*l != '\r') {
|
||||
len[i1++] = *(l++);
|
||||
}
|
||||
} else {
|
||||
LOGE("Can't find length:%s", buf);
|
||||
return 0;
|
||||
}
|
||||
return atoi(len);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ReqHead(char* outReqBuf, const char *url, char* host)
|
||||
{
|
||||
LOGD("http HEAD requst\r\n");
|
||||
sprintf(outReqBuf, "HEAD %s HTTP/1.1\r\n"
|
||||
"Accept:*/*\r\n"
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Connection:Keep-Alive\r\n"
|
||||
"Cache-Control: no-cache\r\n"
|
||||
"\r\n\r\n", url, host);
|
||||
DEBUGHTTP(outReqBuf);
|
||||
}
|
||||
|
||||
|
||||
void ReqGetM3u8(char* outReqBuf, const char *url, char* host)
|
||||
{
|
||||
LOGD("http GET requst:");
|
||||
if ((NULL == url) || (NULL == host)) {
|
||||
LOGE("NULL = url or NULL = host");
|
||||
return;
|
||||
}
|
||||
sprintf(outReqBuf, "GET %s HTTP/1.1\r\n"
|
||||
"Accept:*/*\r\n"
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Connection: Close\r\n" // Keep-Alive
|
||||
"Cache-Control: no-cache\r\n"
|
||||
"\r\n\r\n", url, host);
|
||||
DEBUGHTTP(outReqBuf);
|
||||
}
|
||||
|
||||
|
||||
void ReqDataPre(char* outReqBuf, const char *url, char* host, uint32_t startLen, uint32_t endLen)
|
||||
{
|
||||
if (0 != endLen) {
|
||||
sprintf(outReqBuf, "GET %s HTTP/1.1\r\n"
|
||||
"Accept:*/*\r\n"
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Proxy-Connection: Keep-Alive\r\n"
|
||||
"Cache-Control: no-cache\r\n"
|
||||
"Range: bytes=%d-%d\r\n\r\n", url, host, startLen, endLen - 1);
|
||||
} else {
|
||||
sprintf(outReqBuf, "GET %s HTTP/1.1\r\n"
|
||||
"Accept:*/*\r\n"
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Proxy-Connection: Keep-Alive\r\n"
|
||||
"Cache-Control: no-cache\r\n\r\n", url, host);
|
||||
}
|
||||
|
||||
LOGD("http GET requst-%d:", strlen(outReqBuf));
|
||||
//DEBUGHTTP(outReqBuf);
|
||||
}
|
||||
|
||||
int getIpForHost(const char *host, struct sockaddr_in *ip)
|
||||
{
|
||||
struct hostent *he;
|
||||
struct in_addr **addr_list;
|
||||
char str[200] ;
|
||||
|
||||
he = gethostbyname(host);
|
||||
if (he == NULL) return 0;
|
||||
addr_list = (struct in_addr **)he->h_addr_list;
|
||||
if (addr_list[0] == NULL) return 0;
|
||||
ip->sin_family = AF_INET;
|
||||
memcpy(&ip->sin_addr, addr_list[0], sizeof(ip->sin_addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int splitHostUrl(const char* url, char* host, uint16_t *port, char **path)
|
||||
{
|
||||
if ((NULL == url) || (NULL == host)) {
|
||||
LOGE("ERR:url=NULL or Host=NULL\n");
|
||||
return -1;
|
||||
}
|
||||
char* temp1;
|
||||
char* source = (char*)url;
|
||||
char portBuf[10] = {0};
|
||||
while (url) {
|
||||
source = strstr(source, "//");
|
||||
if (url == NULL) {
|
||||
LOGE("ERR:strchr=NULL\n");
|
||||
return -1;
|
||||
}
|
||||
source += 2;
|
||||
temp1 = strchr(source, ':');
|
||||
if (temp1 != NULL) {
|
||||
// try to find '/'
|
||||
strncpy(host, source, temp1 - source);
|
||||
temp1 += 1;
|
||||
source = strchr(source, '/');
|
||||
if (source == NULL) {
|
||||
LOGE("ERR:strchr=NULL\n");
|
||||
return 0;
|
||||
}
|
||||
strncpy(portBuf, temp1, source - temp1);
|
||||
*port = strtoul(portBuf, 0, 10);
|
||||
*path = source;
|
||||
LOGD("\nUsed Host[%s] Port[%d],Path:%s\n", host, *port, *path);
|
||||
} else {
|
||||
// try to find port
|
||||
temp1 = strchr(source, '/');
|
||||
if (temp1 == NULL) {
|
||||
LOGE("ERR:strchr=NULL\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(host, source, temp1 - source);
|
||||
*port = 80;
|
||||
*path = temp1;
|
||||
LOGD("\nUsed Host[%s] Port[%d],Path:%s\n", host, *port, *path);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int connectToServer(const char* actUrl, const char* hostName, uint16_t port, int timeOut)
|
||||
{
|
||||
struct sockaddr_in remote_ip;
|
||||
int sock = -1;
|
||||
int nNetTimeout = timeOut; // socket timeout 1 Sec
|
||||
int retryCnt = 3;
|
||||
while (retryCnt--) {
|
||||
bzero(&remote_ip, sizeof(struct sockaddr_in));
|
||||
if (1 != inet_aton(hostName, &remote_ip.sin_addr)) {
|
||||
if (!getIpForHost(hostName, &remote_ip)) {
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
LOGE("getIpForHost failed");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
remote_ip.sin_family = AF_INET;
|
||||
int sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1) {
|
||||
LOGE("socket failed errno=%d", errno);
|
||||
continue;
|
||||
}
|
||||
// setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
|
||||
struct timeval tv_out;
|
||||
tv_out.tv_sec = 20; //Wait 20 seconds.
|
||||
tv_out.tv_usec = 0;
|
||||
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&tv_out, sizeof(tv_out));
|
||||
|
||||
remote_ip.sin_port = htons(port);
|
||||
LOGD("[sock=%d],connecting to server IP:%s,Port:%d...",
|
||||
sock, ipaddr_ntoa((const ip_addr_t*)&remote_ip.sin_addr.s_addr), port);
|
||||
if (connect(sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 0) {
|
||||
close(sock);
|
||||
LOGE("Conn err.\n");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
continue;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
LOGE("Lost host,connect and getIpForHost timeout");
|
||||
return -2;
|
||||
}
|
||||
|
||||
void resetDownloadAttr(char *src, uint32_t *type)
|
||||
{
|
||||
localHttp.status = 0;
|
||||
if (localHttp.blockQuit < 0) {
|
||||
localHttp.blockQuit = 0;
|
||||
}
|
||||
localHttp.receivedSize = 0;
|
||||
localHttp.remaindSize = 0;
|
||||
localHttp.downloadedSize = 0;
|
||||
localHttp.uri.srcType = *type;
|
||||
localHttp.contentTotalSize = 0;
|
||||
memset(localHttp.uri.str, 0, ESP_URI_LEN);
|
||||
strncpy(localHttp.uri.str, src, strlen(src));
|
||||
}
|
||||
|
||||
void OnFileDataCB(HttpObj *obj)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = audioBufWrite(obj->reqBuf, obj->receivedSize, 100);
|
||||
if (ret) {
|
||||
obj->remaindSize -= obj->receivedSize;
|
||||
obj->downloadedSize += obj->receivedSize;
|
||||
// uint32_t rd, wr;
|
||||
// audioBufPosGet(&rd, &wr);
|
||||
// LOGD("rd:%x,wr:%x,downloaded=%d, remaind=%d, total=%d, recvSize=%d",
|
||||
// rd,wr,obj->downloadedSize, obj->remaindSize, obj->contentTotalSize, obj->receivedSize);
|
||||
break;
|
||||
} else {
|
||||
LOGE("audioBufWrite failed ret=%d. rcev=%d,remaind=%d, d=%d", ret,
|
||||
obj->receivedSize, obj->remaindSize, obj->downloadedSize);
|
||||
break;
|
||||
}
|
||||
} while (0 == obj->blockQuit);
|
||||
}
|
||||
|
||||
void OnM3u8DataCB(HttpObj *obj)
|
||||
{
|
||||
obj->remaindSize -= obj->receivedSize;
|
||||
obj->downloadedSize += obj->receivedSize;
|
||||
// LOGD(":\n%s", obj->reqBuf);
|
||||
}
|
||||
|
||||
char *GetValidUrl(M3u8Info *pActM3u8, M3u8Seq *actSeq)
|
||||
{
|
||||
char *retUrl = NULL;
|
||||
if ((NULL == actSeq)
|
||||
|| (NULL == pActM3u8)) {
|
||||
LOGE("pActM3u8 or actSeq is NULL");
|
||||
return retUrl;
|
||||
}
|
||||
int validM3u8 = -1;
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
// LOGD("M3u8 AAC URL,%dth,%s\n", i, pActM3u8->segList[i].url);
|
||||
if ((actSeq->sub == DEFAULT_AAC_SEQ)
|
||||
|| (1 == m3u8CheckValid(&pActM3u8->segList[i].seq, (const M3u8Seq*)actSeq))) {
|
||||
validM3u8 = 1;
|
||||
retUrl = pActM3u8->segList[i].url;
|
||||
memcpy(actSeq, &pActM3u8->segList[i].seq, sizeof(pActM3u8->segList[i].seq));
|
||||
pActM3u8->segList[i].seq.sub = 0;
|
||||
LOGD("Get one valid AAC URL,%dth,seq=%x,%s\n", i, actSeq->sub, retUrl);
|
||||
if ((0 == actSeq->sub)
|
||||
|| (retUrl[0] == '\0')) {
|
||||
retUrl = NULL;
|
||||
}
|
||||
return retUrl;
|
||||
} else {
|
||||
// LOGD("Get one valid AAC URL,%dth,seq=%x,%s\n", i, pActM3u8->segList[i].seq.sub, pActM3u8->segList[i].url);
|
||||
pActM3u8->segList[i].seq.sub = 0;
|
||||
}
|
||||
}
|
||||
if (validM3u8 != 1) {
|
||||
LOGD("Can not found valid aac url, curtAacSeq=%x", actSeq->sub);
|
||||
}
|
||||
return retUrl;
|
||||
|
||||
}
|
||||
|
||||
int httpDownloading(HttpObj *obj, Callback_Recv recvCB)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (NULL == obj->uri.str)
|
||||
|| (NULL == obj->reqBuf)
|
||||
|| (NULL == obj->recvBuf)
|
||||
|| (0 == strlen(obj->uri.str))) {
|
||||
LOGE("Pointer is NULL,obj:%x,URL:%x reqbuf:%x recvBuf:%x,len:%d,blockQuit:%d",
|
||||
obj, obj->uri.str, obj->reqBuf, obj->recvBuf, strlen(obj->uri.str), obj->blockQuit);
|
||||
return -1;
|
||||
}
|
||||
char hostName[32] = { 0 };
|
||||
int actSocket = -1;
|
||||
uint32_t contrlDat = 0;
|
||||
uint8_t modifyProFlag = 0;
|
||||
int cnt = 0;
|
||||
int n = 0;
|
||||
LOGD("\n>>>>>Downloading start:%s,0x%x,remaind=%d,downloaded=%d,total=%d,fill=%d",
|
||||
obj->uri.str, obj->uri.str, obj->remaindSize, obj->downloadedSize, obj->contentTotalSize, audioBufFillGet());
|
||||
obj->status = 1;
|
||||
uint16_t ipPort = 80;
|
||||
char *uriPath = NULL;
|
||||
do {
|
||||
// Here will check exit event;
|
||||
|
||||
Retry: LOGD("retry new url size=%d", obj->remaindSize);
|
||||
memset(hostName, 0, sizeof(hostName));
|
||||
if (0 != splitHostUrl(obj->uri.str, hostName, &ipPort, &uriPath)) {
|
||||
LOGE("splitHostUrl failed:%s", obj->uri.str);
|
||||
continue;
|
||||
}
|
||||
LOGD("Hostname:%s", hostName);
|
||||
if ((actSocket = connectToServer((const char*)obj->uri.str, hostName, ipPort, 10000)) >= 0) {
|
||||
char * datPos = NULL;
|
||||
bzero(obj->reqBuf, REQUEST_BUF_LEN);
|
||||
ReqDataPre(obj->reqBuf, uriPath, hostName, obj->downloadedSize, obj->contentTotalSize);
|
||||
LOGD("Hostname:%s++++++++", hostName);
|
||||
write(actSocket, obj->reqBuf, strlen(obj->reqBuf));
|
||||
LOGD("Hostname:%s--------", hostName);
|
||||
bzero(obj->recvBuf, RECV_BUF_LEN);
|
||||
datPos = NULL;
|
||||
cnt = 0;
|
||||
do {
|
||||
bzero(obj->reqBuf, REQUEST_BUF_LEN);
|
||||
n = read(actSocket, obj->reqBuf, REQUEST_BUF_LEN);
|
||||
if ((n > 0) && (cnt <= RECV_BUF_LEN)) {
|
||||
// DEBUGHTTP("Head is: %s", obj->reqBuf);
|
||||
memcpy(obj->recvBuf + cnt, obj->reqBuf, n);
|
||||
datPos = strstr(obj->recvBuf, "\r\n""""\r\n");
|
||||
if (datPos) {
|
||||
//DEBUGHTTP("Find CRLF CRLF ok");
|
||||
// LOGD("Head is: %s", obj->recvBuf);
|
||||
} else {
|
||||
LOGE("Find CRLF CRLF failed,wait more data");
|
||||
}
|
||||
}
|
||||
cnt += n;
|
||||
} while ((datPos == NULL) && (n > 0) && (cnt < RECV_BUF_LEN));
|
||||
if (n < 0) {
|
||||
close(actSocket);
|
||||
continue;
|
||||
}
|
||||
if (NULL == datPos) {
|
||||
// datPos == strstr(obj->recvBuf, "\r\n""""\r\n");
|
||||
LOGD("Head is: %s", obj->recvBuf);
|
||||
|
||||
if (NULL == datPos) {
|
||||
close(actSocket);
|
||||
LOGE("Can't Find CRLF CRLF,it's bad response,try again");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int ret = checkIsReqOk(obj->recvBuf);
|
||||
if (ret < 0) {
|
||||
close(actSocket);
|
||||
LOGE("Recv a bad resp:%s", obj->recvBuf);
|
||||
continue;
|
||||
} else if (ret == 1) {
|
||||
close(actSocket);
|
||||
LOGW("Recv a 3xx resp:%s", obj->recvBuf);
|
||||
memset(obj->uri.str, 0, ESP_URI_LEN);
|
||||
if (getLocation((const char*)obj->recvBuf, obj->uri.str) < 0) {
|
||||
LOGE("Find 3xx URL error");
|
||||
} else {
|
||||
LOGW("Recv a 3xx resp:%s", obj->uri.str);
|
||||
}
|
||||
goto Retry;
|
||||
}
|
||||
if (0 == obj->contentTotalSize) obj->contentTotalSize = getFileLength(obj->recvBuf);
|
||||
datPos += 4;
|
||||
cnt = cnt - (datPos - obj->recvBuf);
|
||||
if (0 == obj->remaindSize) {
|
||||
obj->remaindSize = obj->contentTotalSize;
|
||||
}
|
||||
// Save the tail data
|
||||
bzero(obj->reqBuf, REQUEST_BUF_LEN);
|
||||
memcpy(obj->reqBuf, datPos, cnt);
|
||||
|
||||
LOGD("downloaded=%d, remaind=%d, total=%d, cnt=%d",
|
||||
obj->downloadedSize, obj->remaindSize, obj->contentTotalSize, cnt);
|
||||
int writeComplete = 0;
|
||||
do {
|
||||
if (writeComplete) {
|
||||
bzero(obj->reqBuf, REQUEST_BUF_LEN);
|
||||
n = read(actSocket, obj->reqBuf, REQUEST_BUF_LEN);
|
||||
cnt = n;
|
||||
// DEBUGHTTP("recv,cnt:%d\n", cnt);
|
||||
}
|
||||
if (n > 0) {
|
||||
if (cnt > 0) {
|
||||
obj->receivedSize = cnt;
|
||||
recvCB(obj);
|
||||
}
|
||||
cnt = 0;
|
||||
writeComplete = 1;
|
||||
}
|
||||
} while ((n > 0) && (obj->remaindSize > 0) && (0 == obj->blockQuit));
|
||||
close(actSocket);
|
||||
LOGD("Sock[%d] has closed,n=%d,blockQuit=%d", actSocket, n, obj->blockQuit);
|
||||
} else {
|
||||
LOGE("Connect is error.");
|
||||
}
|
||||
LOGD("Connect closed,file size remaind=%d", obj->remaindSize);
|
||||
|
||||
} while ((obj->remaindSize != 0) && (0 == obj->blockQuit));
|
||||
if (0 == obj->remaindSize) {
|
||||
obj->status = 2;
|
||||
} else {
|
||||
obj->status = 3;
|
||||
}
|
||||
LOGD("\n<<<<<Downloading finish:%s,remaind=%d,downloaded=%d,total=%d fill=%d status=%d\n",
|
||||
obj->uri.str, obj->remaindSize, obj->downloadedSize, obj->contentTotalSize,
|
||||
audioBufFillGet(), obj->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fileDownloadTask(void *pvParameters)
|
||||
{
|
||||
int n, cnt;
|
||||
DownloadInstance *downloadObj = (DownloadInstance *)pvParameters;
|
||||
LOGI("%s is running.%x %x", __func__, pvParameters, downloadObj->threadQuit);
|
||||
|
||||
/////////////////////////////
|
||||
M3u8Seq runningAacSeq = {0, 0, DEFAULT_AAC_SEQ};
|
||||
M3u8Info *pUsingM3u8 = NULL;
|
||||
uint32_t mediaSeq = DEFAULT_AAC_SEQ;
|
||||
|
||||
downloadObj->threadQuit = 0;
|
||||
while (downloadObj->threadQuit == 0) {
|
||||
switch (downloadObj->state) {
|
||||
case TaskState_Ready:
|
||||
if ((NULL == actLiveUrl.str)
|
||||
|| (actLiveUrl.str[0] == '\0')
|
||||
|| (NULL == localHttp.uri.str )) {
|
||||
downloadObj->state = TaskState_Idle;
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
LOGI("Downloading URL is NULL,downloading task paused");
|
||||
break;
|
||||
} else {
|
||||
LOGI("Download task is ready.%s type:%d", actLiveUrl.str, actLiveUrl.type);
|
||||
}
|
||||
if (InputSrcType_NetSpec == actLiveUrl.type) {
|
||||
resetDownloadAttr(actLiveUrl.str, &actLiveUrl.type);
|
||||
downloadObj->state = TaskState_Running;
|
||||
audioBufWrRest();
|
||||
} else if (InputSrcType_NetLiving == actLiveUrl.type) {
|
||||
resetDownloadAttr(actLiveUrl.str, &actLiveUrl.type);
|
||||
|
||||
audioBufWrRest();
|
||||
mediaSeq = DEFAULT_AAC_SEQ;
|
||||
downloadObj->state = TaskState_Running;
|
||||
runningAacSeq.sub = DEFAULT_AAC_SEQ;
|
||||
if (pUsingM3u8) {
|
||||
free(pUsingM3u8);
|
||||
pUsingM3u8 = NULL;
|
||||
}
|
||||
pUsingM3u8 = calloc(1, sizeof(M3u8Info));
|
||||
if (pUsingM3u8 == NULL) {
|
||||
LOGE("recvBuf malloc error");
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
LOGE("Http uri.srcType is not supported[%d]", localHttp.uri.srcType);
|
||||
downloadObj->state = TaskState_Idle;
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
}
|
||||
break;
|
||||
case TaskState_Pause:
|
||||
LOGI("TaskState_Pause,Total=%d, downloaded=%d,remaind=%d", localHttp.contentTotalSize,
|
||||
localHttp.downloadedSize,
|
||||
localHttp.remaindSize);
|
||||
downloadObj->state = TaskState_Idle;
|
||||
break;
|
||||
case TaskState_Resume:
|
||||
downloadObj->state = TaskState_Running;
|
||||
LOGI("TaskState_Resume,Total=%d, downloaded=%d,remaind=%d", localHttp.contentTotalSize,
|
||||
localHttp.downloadedSize,
|
||||
localHttp.remaindSize);
|
||||
break;
|
||||
case TaskState_Running:
|
||||
if (InputSrcType_NetSpec == localHttp.uri.srcType) {
|
||||
LOGI("Excute URL:%s", localHttp.uri.str);
|
||||
httpDownloading(&localHttp, OnFileDataCB);
|
||||
if (2 == localHttp.status) {
|
||||
downloadObj->state = TaskState_Idle;
|
||||
LOGI("Excute URL over, task will be idle.remind[%d]", localHttp.remaindSize);
|
||||
}
|
||||
} else if (InputSrcType_NetLiving == localHttp.uri.srcType) {
|
||||
resetDownloadAttr(actLiveUrl.str, &actLiveUrl.type);
|
||||
memset(localHttp.recvBuf, 0, RECV_BUF_LEN);
|
||||
memset(localHttp.reqBuf, 0, REQUEST_BUF_LEN);
|
||||
|
||||
LOGD("Excute URL:%s, actLiveUrl.str=%x", localHttp.uri.str, actLiveUrl.str);
|
||||
httpDownloading(&localHttp, OnM3u8DataCB);
|
||||
|
||||
M3u8Info *pActM3u8 = m3u8Parser(localHttp.reqBuf, pUsingM3u8);
|
||||
if (NULL == pActM3u8) {
|
||||
LOGE("Parser m3u8 is error");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
break;
|
||||
}
|
||||
if ((pActM3u8->mediaSeq <= mediaSeq) && (mediaSeq != DEFAULT_AAC_SEQ)) {
|
||||
LOGD("mediaSeq has not update,used=%d,new=%d", mediaSeq, pActM3u8->mediaSeq);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
break;
|
||||
}
|
||||
char *validUrl = GetValidUrl(pActM3u8, &runningAacSeq);
|
||||
|
||||
LOGD("AAC URL,runningAacSeq:%x,%x,%x\n",
|
||||
runningAacSeq.sub, runningAacSeq.main, runningAacSeq.date);
|
||||
if (NULL == validUrl) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
LOGE("uri.str is NULL,state=%d", downloadObj->state);
|
||||
break;
|
||||
}
|
||||
DecoderObj decoder;
|
||||
mediaDecoderTaskInfoGet(&decoder);
|
||||
decoder.musicType = checkMediaType(validUrl);
|
||||
if (decoder.musicType >= EspAudioMeidaType_M3u) {
|
||||
LOGE("%s,Music type[%d] is error", validUrl, decoder.musicType);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
break;
|
||||
} else {
|
||||
mediaDecoderTaskInfoSet(&decoder);
|
||||
}
|
||||
do {
|
||||
resetDownloadAttr(validUrl, &actLiveUrl.type);
|
||||
memset(localHttp.recvBuf, 0, RECV_BUF_LEN);
|
||||
memset(localHttp.reqBuf, 0, REQUEST_BUF_LEN);
|
||||
|
||||
httpDownloading(&localHttp, OnFileDataCB);
|
||||
validUrl = GetValidUrl(pActM3u8, &runningAacSeq);
|
||||
|
||||
LOGD("AAC URL,runningAacSeq:%x,%x,%x\n", runningAacSeq.sub, runningAacSeq.main, runningAacSeq.date);
|
||||
if (NULL == validUrl) {
|
||||
LOGD("uri.str is NULL,state=%d", downloadObj->state);
|
||||
break;
|
||||
}
|
||||
} while (validUrl != NULL);
|
||||
mediaSeq = pActM3u8->mediaSeq;
|
||||
} else {
|
||||
LOGE("Http uri.srcType is not supported[%d]", localHttp.uri.srcType);
|
||||
downloadObj->state = TaskState_Idle;
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
}
|
||||
|
||||
break;
|
||||
case TaskState_Stoped:
|
||||
downloadObj->state = TaskState_Idle;
|
||||
break;
|
||||
case TaskState_Idle:
|
||||
default:
|
||||
vTaskDelay(250 / portTICK_RATE_MS);
|
||||
// LOGD("blockQuit[%d] state[%d]", localHttp.blockQuit, downloadObj->state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
downloadObj->threadQuit = -1;
|
||||
downloadObj->thread = NULL;
|
||||
downloadObj->state = TaskState_Stoped;
|
||||
if (pUsingM3u8) {
|
||||
free(pUsingM3u8);
|
||||
pUsingM3u8 = NULL;
|
||||
}
|
||||
LOGD("%s is ended...", __func__);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TaskState downloadTaskStateGet()
|
||||
{
|
||||
return dlInstance.state;
|
||||
}
|
||||
|
||||
int downloadTaskHTTPStateGet()
|
||||
{
|
||||
return localHttp.status;
|
||||
}
|
||||
|
||||
void downloadTaskDownloadSizeSet(int *size)
|
||||
{
|
||||
if (NULL == size) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
// localHttp.blockQuit = 1;
|
||||
localHttp.downloadedSize = *size;
|
||||
downloadTaskResume();
|
||||
}
|
||||
|
||||
void downloadTaskContentSizeGet(uint32_t *size)
|
||||
{
|
||||
if (NULL == size) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
*size = localHttp.contentTotalSize;
|
||||
}
|
||||
|
||||
void downloadTaskInfoSet(UriSrcAttr *uri)
|
||||
{
|
||||
if (NULL == uri) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
actLiveUrl.type = uri->srcType;
|
||||
memset(actLiveUrl.str, 0 , ESP_URI_LEN);
|
||||
strncpy(actLiveUrl.str, uri->str, strlen(uri->str));
|
||||
localHttp.blockQuit = 0;
|
||||
LOGD("Set url ok:%s", actLiveUrl.str);
|
||||
}
|
||||
|
||||
void downloadTaskPause()
|
||||
{
|
||||
if (0 == dlInstance.thread) {
|
||||
dlInstance.state = TaskState_Unknown;
|
||||
LOGE("dlInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
if (TaskState_Running == dlInstance.state) {
|
||||
localHttp.blockQuit = -1;
|
||||
}
|
||||
dlInstance.state = TaskState_Pause;
|
||||
|
||||
LOGD("download task state=%d", dlInstance.state);
|
||||
}
|
||||
|
||||
void downloadTaskResume()
|
||||
{
|
||||
if (0 == dlInstance.thread) {
|
||||
dlInstance.state = TaskState_Unknown;
|
||||
LOGE("dlInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
if (TaskState_Pause == dlInstance.state) {
|
||||
localHttp.blockQuit = 0;
|
||||
}
|
||||
dlInstance.state = TaskState_Resume;
|
||||
LOGD("download task state=%d", dlInstance.state);
|
||||
}
|
||||
|
||||
void downloadTaskCreate(int taskType)
|
||||
{
|
||||
if (localHttp.reqBuf) {
|
||||
free(localHttp.reqBuf);
|
||||
}
|
||||
if (localHttp.recvBuf) {
|
||||
free(localHttp.recvBuf);
|
||||
}
|
||||
if (localHttp.uri.str) {
|
||||
free(localHttp.uri.str);
|
||||
}
|
||||
localHttp.reqBuf = calloc(1, REQUEST_BUF_LEN);
|
||||
if (NULL == localHttp.reqBuf) {
|
||||
LOGE("reqBuf malloc error");
|
||||
return;
|
||||
}
|
||||
localHttp.recvBuf = calloc(1, RECV_BUF_LEN);
|
||||
if (NULL == localHttp.recvBuf) {
|
||||
LOGE("recvBuf malloc error");
|
||||
free(localHttp.reqBuf);
|
||||
return;
|
||||
}
|
||||
localHttp.uri.str = calloc(1, ESP_URI_LEN);
|
||||
if (NULL == localHttp.uri.str) {
|
||||
LOGE("uri.str malloc error");
|
||||
free(localHttp.reqBuf);
|
||||
free(localHttp.recvBuf);
|
||||
return;
|
||||
}
|
||||
// mutex_init(&downloadMutex);
|
||||
// configASSERT(downloadMutex);
|
||||
xTaskCreate(fileDownloadTask, "fileDownloadTask", (6 * 1024), &dlInstance, PRIO_DOWNLOAD, &dlInstance.thread);
|
||||
configASSERT(dlInstance.thread);
|
||||
LOGD("download task state=%d", dlInstance.state);
|
||||
}
|
||||
|
||||
int downloadTaskStart()
|
||||
{
|
||||
if (0 == dlInstance.thread) {
|
||||
dlInstance.state = TaskState_Unknown;
|
||||
LOGE("dlInstance.thread is NULL");
|
||||
return -1;
|
||||
}
|
||||
if ((actLiveUrl.str == NULL)
|
||||
|| (actLiveUrl.str[0] == '\0')) {
|
||||
dlInstance.state = TaskState_Idle;
|
||||
LOGE("uri.str task is NULL");
|
||||
return -1;
|
||||
}
|
||||
dlInstance.state = TaskState_Ready;
|
||||
LOGD("download task state=%d, %s, %d", dlInstance.state, actLiveUrl.str, localHttp.blockQuit);
|
||||
audioBufWrRest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void downloadTaskStop(void *que)
|
||||
{
|
||||
if (0 == dlInstance.thread) {
|
||||
dlInstance.state = TaskState_Unknown;
|
||||
LOGE("dlInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
if (dlInstance.state == TaskState_Unknown) {
|
||||
LOGW("dlInstance.state is TaskState_Unknown");
|
||||
return;
|
||||
}
|
||||
localHttp.blockQuit = 1;
|
||||
dlInstance.state = TaskState_Stoped;
|
||||
configASSERT(que);
|
||||
xQueueSend(que, &localHttp.blockQuit, 0);
|
||||
|
||||
LOGD("download task +++++ blockQuit=%d, state=%d", localHttp.blockQuit, dlInstance.state);
|
||||
while ((TaskState_Finished != dlInstance.state)
|
||||
&& (TaskState_Idle != dlInstance.state)) {
|
||||
if ((TaskState_Idle == dlInstance.state)) {
|
||||
localHttp.blockQuit = 0;
|
||||
break;
|
||||
}
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
}
|
||||
audioBufWrRest();
|
||||
xQueueReset(que);
|
||||
LOGD("download task ------ blockQuit=%d, state=%d", localHttp.blockQuit, dlInstance.state);
|
||||
}
|
||||
|
||||
void downloadTaskDestroy()
|
||||
{
|
||||
if (0 == dlInstance.thread) {
|
||||
dlInstance.state = TaskState_Unknown;
|
||||
LOGE("dlInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGD("download task +++++ blockQuit=%d, state=%d", localHttp.blockQuit, dlInstance.state);
|
||||
if (0 == dlInstance.threadQuit) {
|
||||
localHttp.blockQuit = 1;
|
||||
dlInstance.threadQuit = 1;
|
||||
dlInstance.state = TaskState_Stoped;
|
||||
while (1) {
|
||||
if ((dlInstance.threadQuit == -1)) {
|
||||
localHttp.blockQuit = 0;
|
||||
break;
|
||||
}
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
if (localHttp.reqBuf) free(localHttp.reqBuf);
|
||||
if (localHttp.recvBuf) free(localHttp.recvBuf);
|
||||
if (localHttp.uri.str) free(localHttp.uri.str);
|
||||
|
||||
memset(&localHttp, 0, sizeof(localHttp));
|
||||
localHttp.reqBuf = NULL;
|
||||
localHttp.recvBuf = NULL;
|
||||
localHttp.uri.str = NULL;
|
||||
dlInstance.state = TaskState_Unknown;
|
||||
dlInstance.thread = NULL;
|
||||
// mutex_destroy(&downloadMutex);
|
||||
// downloadMutex = NULL;
|
||||
LOGD("download task ------ blockQuit=%d, state=%d", localHttp.blockQuit, dlInstance.state);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,318 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "inc/M3u8.h"
|
||||
|
||||
static int read_line_from_m3u8_info(char *m3u8_info, char *line_buffer, int buffer_size);
|
||||
static int m3u8_info_eof();
|
||||
static int parseSegFromUrl(M3u8Segment* tsp);
|
||||
static char * strdupmy(const char *s);
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
char* trim_str(char *str)
|
||||
{
|
||||
char* tmp = str;
|
||||
|
||||
while (*str++ != '\r') {
|
||||
if (*str == '\0' || *str == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*str = '\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Must to be free memory
|
||||
static char * strdupmy(const char *s)
|
||||
{
|
||||
size_t len = strlen(s) + 1;
|
||||
void *new = malloc(len);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
return (char *)memcpy(new, s, len);
|
||||
}
|
||||
|
||||
char* split_url(char* url, char* seg_path, char* seg_name)
|
||||
{
|
||||
char* temp1;
|
||||
char rateStr[10] = {0};
|
||||
int len = strlen(url);
|
||||
while (url) {
|
||||
temp1 = strrchr(url, '/');
|
||||
if (temp1 == NULL) {
|
||||
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
temp1 += 1;
|
||||
strncpy(seg_path, url, temp1 - url);
|
||||
strncpy(seg_name, temp1, len - (temp1 - url));
|
||||
return seg_path;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int is_blank(char *str)
|
||||
{
|
||||
if (0 == strlen(str))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_line_from_m3u8_info(char *m3u8_info, char *line_buffer, int buffer_size)
|
||||
{
|
||||
int start;
|
||||
int end = -1;
|
||||
char cur_char = '\0';
|
||||
int copy_size;
|
||||
|
||||
start = offset;
|
||||
while (offset < length) {
|
||||
cur_char = m3u8_info[offset];
|
||||
if (cur_char == '\r' || cur_char == '\n') {
|
||||
end = offset;
|
||||
offset++;
|
||||
break;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
if (end == -1) {
|
||||
end = length;
|
||||
}
|
||||
if (cur_char == '\r') {
|
||||
offset++;
|
||||
}
|
||||
memset(line_buffer, 0, buffer_size);
|
||||
copy_size = end - start;
|
||||
if (copy_size > buffer_size - 1) {
|
||||
copy_size = buffer_size - 1;
|
||||
}
|
||||
strncpy(line_buffer, m3u8_info + start, copy_size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int m3u8_info_eof()
|
||||
{
|
||||
if (offset >= length) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int parseSegFromUrl(M3u8Segment* tsp)
|
||||
{
|
||||
int len = strlen(tsp->url);
|
||||
int ret = -1;
|
||||
char *segment_path = (char*)malloc(len);
|
||||
char *segment_name = (char*)malloc(len);
|
||||
if ((segment_path == NULL) | (segment_name == NULL)) {
|
||||
goto SAVEEXIT;
|
||||
}
|
||||
memset(segment_path, 0, len);
|
||||
memset(segment_name, 0, len);
|
||||
split_url(tsp->url, segment_path, segment_name);
|
||||
//http://live.xmcdn.com/192.168.3.134/live/12/24/160411_000003_15f9.ts
|
||||
//http://live.xmcdn.com/192.168.3.134/live/75/24/160413_082919_12b0.aac
|
||||
char* temp1 = strchr(segment_name, '.');
|
||||
char* temp2 = strrchr(segment_name, '_');
|
||||
if ((temp1 == NULL) | (temp2 == NULL)) {
|
||||
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
|
||||
goto SAVEEXIT;
|
||||
}
|
||||
*temp1 = '\0';
|
||||
temp1++;
|
||||
if (strncmp(temp1, "aac", 3) == 0) {
|
||||
tsp->fmt = AUDIOFMT_AAC;
|
||||
} else if (strncmp(temp1, "ts", 3) == 0) {
|
||||
tsp->fmt = AUDIOFMT_TS;
|
||||
} else {
|
||||
tsp->fmt = AUDIOFMT_UNKNOWN;
|
||||
}
|
||||
///subSeq
|
||||
temp2++;
|
||||
tsp->seq.sub = strtoul(temp2, 0, 16);
|
||||
////mainSeq
|
||||
temp2--;
|
||||
*temp2 = '\0';
|
||||
temp1 = strrchr(segment_name, '_');
|
||||
if (temp1 == NULL) {
|
||||
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
|
||||
goto SAVEEXIT;
|
||||
}
|
||||
temp1++;
|
||||
tsp->seq.main = strtoul(temp1, 0, 16);
|
||||
///
|
||||
temp2 = strchr(segment_name, '_');
|
||||
if (temp2 == NULL) {
|
||||
printf("ERR:strchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
|
||||
goto SAVEEXIT;
|
||||
}
|
||||
*temp2 = '\0';
|
||||
tsp->seq.date = strtoul(segment_name, 0, 16);
|
||||
|
||||
temp1 = strrchr(segment_path, '/');
|
||||
if (temp1 == NULL) {
|
||||
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
|
||||
goto SAVEEXIT;
|
||||
}
|
||||
*temp1 = '\0';
|
||||
temp1 = strrchr(segment_path, '/');
|
||||
if (temp1 == NULL) {
|
||||
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
|
||||
goto SAVEEXIT;
|
||||
}
|
||||
temp1++;
|
||||
tsp->rate = atoi(temp1);
|
||||
ret = 0;
|
||||
SAVEEXIT:
|
||||
if (segment_path) {
|
||||
free(segment_path);
|
||||
}
|
||||
if (segment_name) {
|
||||
free(segment_name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#define ONE_LINE_SIZE 1024
|
||||
M3u8Info *m3u8Parser(char *m3u8Str, M3u8Info* m3u8)
|
||||
{
|
||||
int has_segment = 0;
|
||||
if (NULL == m3u8) {
|
||||
printf("malloc for M3u8Info failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *line = malloc(ONE_LINE_SIZE);
|
||||
if (NULL == line) {
|
||||
printf("zalloc for line failed.");
|
||||
return NULL;
|
||||
}
|
||||
memset(line, 0, ONE_LINE_SIZE);
|
||||
memset(m3u8, 0, sizeof(M3u8Info));
|
||||
length = strlen(m3u8Str);
|
||||
offset = 0;
|
||||
|
||||
while (!m3u8_info_eof()) {
|
||||
int result = 0;
|
||||
char *str = NULL;
|
||||
if (m3u8->segCount >= MAX_SEGMENT_COUNT) {
|
||||
printf("segCount >= MAX_SEGMENT_COUNT[%d].", MAX_SEGMENT_COUNT);
|
||||
break;
|
||||
}
|
||||
result = read_line_from_m3u8_info(m3u8Str, line, ONE_LINE_SIZE);
|
||||
if (!result) {
|
||||
printf("ERR:read line error from m3u8 info.");
|
||||
if (line) free(line);
|
||||
return NULL;
|
||||
}
|
||||
if (is_blank(line)) {
|
||||
continue;
|
||||
}
|
||||
str = trim_str(line);
|
||||
if (has_segment) {
|
||||
int size = strlen(str) + 1;
|
||||
m3u8->segList[m3u8->segCount].seq.sub = m3u8->mediaSeq + m3u8->segCount;
|
||||
// m3u8->segList[m3u8->segCount - 1].url = (char *)malloc(size);
|
||||
memset(m3u8->segList[m3u8->segCount].url, 0, size);
|
||||
strcpy(m3u8->segList[m3u8->segCount].url, str);
|
||||
parseSegFromUrl(&m3u8->segList[m3u8->segCount]);
|
||||
has_segment = 0;
|
||||
m3u8->segCount++;
|
||||
} else {
|
||||
if (0 == strncmp(str, "#EXTM3U", strlen("#EXTM3U"))) {
|
||||
|
||||
} else if (0 == strncmp(str, "#EXT-X-VERSION:", strlen("#EXT-X-VERSION:"))) {
|
||||
|
||||
} else if (0 == strncmp(str, "#EXT-X-ALLOW-CACHE:", strlen("#EXT-X-ALLOW-CACHE:"))) {
|
||||
|
||||
} else if (0 == strncmp(str, "#EXT-X-TARGETDURATION:", strlen("#EXT-X-TARGETDURATION:"))) {
|
||||
char *str_duration = str + strlen("#EXT-X-TARGETDURATION:");
|
||||
m3u8->targetDuration = atoi(trim_str(str_duration));
|
||||
// printf("Get the TARGETDURATION=%d\n", m3u8->targetDuration);
|
||||
} else if (0 == strncmp(str, "#EXT-X-MEDIA-SEQUENCE:", strlen("#EXT-X-MEDIA-SEQUENCE:"))) {
|
||||
char *str_sequence = str + strlen("#EXT-X-MEDIA-SEQUENCE:");
|
||||
m3u8->mediaSeq = atol(trim_str(str_sequence));
|
||||
// printf("Get the MEDIA-SEQUENCE=%d\n", m3u8->mediaSeq);
|
||||
} else if (0 == strncmp(str, "#EXTINF:", strlen("#EXTINF:"))) {
|
||||
char *str_segment_duration = NULL;
|
||||
int i = 0;
|
||||
has_segment = 1;
|
||||
str_segment_duration = str + strlen("#EXTINF:");
|
||||
while (str_segment_duration[i] != 0) {
|
||||
if ((str_segment_duration[i] < '0') || (str_segment_duration[i] > '9')) {
|
||||
str_segment_duration[i] = 0;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
m3u8->segList[m3u8->segCount].duration = atoi(str_segment_duration);
|
||||
} else if (0 == strncmp(str, "#EXT-X-DISCONTINUITY", strlen("#EXT-X-DISCONTINUITY"))) {
|
||||
|
||||
} else if (0 == strncmp(str, "#EXT-X-ENDLIST", strlen("#EXT-X-ENDLIST"))) {
|
||||
|
||||
} else {
|
||||
printf("unknown line: %s.", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (line) free(line);
|
||||
return m3u8;
|
||||
}
|
||||
|
||||
uint8_t m3u8CheckValid(const M3u8Seq* new, const M3u8Seq* pre)
|
||||
{
|
||||
if (pre->date < new->date) {
|
||||
return 1;
|
||||
} else if (pre->date == new->date) {
|
||||
if (pre->main < new->main) {
|
||||
return 1;
|
||||
} else if (pre->main == new->main) {
|
||||
if ((pre->sub & 0x0000FFFF) < (new->sub & 0x0000FFFF)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void m3u8Destroy(M3u8Info *m3u8)
|
||||
{
|
||||
int i = 0;
|
||||
if (m3u8 == NULL) {
|
||||
return;
|
||||
}
|
||||
free(m3u8);
|
||||
}
|
||||
|
||||
int m3u8_test(char* pStr)
|
||||
{
|
||||
//char *m3u8Str = "#EXTM3U\n"
|
||||
// "#EXT-X-TARGETDURATION:8\n"
|
||||
// "#EXT-X-MEDIA-SEQUENCE:92595\n"
|
||||
// "#EXTINF:8,\n"
|
||||
// "20121120T182851-04-92595.ts\n"
|
||||
// "#EXTINF:8,\n"
|
||||
// "20121120T182851-04-92596.ts\n"
|
||||
// "#EXTINF:8,\n"
|
||||
// "20121120T182851-04-92597.ts\n"
|
||||
// "#EXTINF:8,\n"
|
||||
// "20121120T182851-04-92598.ts\n";
|
||||
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
// M3u8Info *m3u8 = m3u8Parser(pStr, m3u8);
|
||||
// m3u8Destroy(m3u8);
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,370 +0,0 @@
|
|||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "audio_log.h"
|
||||
|
||||
#include "inc/DecoderCom.h"
|
||||
#include "EspAudioCom.h"
|
||||
#include "Storage.h"
|
||||
#include "Utility.h"
|
||||
#include "inc/MediaDecoderTask.h"
|
||||
|
||||
|
||||
#define DECODER_TSK_PRIO 8
|
||||
#define DATA_PKG_SIZE (512*2)
|
||||
|
||||
#if 0
|
||||
#define DEBUGPLY printf
|
||||
#else
|
||||
#define DEBUGPLY
|
||||
#endif
|
||||
|
||||
static xQueueHandle rdQue;
|
||||
|
||||
void mediaDecoderTask(void *pvParameters);
|
||||
|
||||
typedef struct {
|
||||
TaskState state;
|
||||
pthread_t thread;
|
||||
int threadQuit;
|
||||
TaskState lastState;
|
||||
DecoderObj player;
|
||||
} MediaPlayerInstance;
|
||||
extern uint32_t rdpos;
|
||||
extern uint32_t wrpos;
|
||||
|
||||
|
||||
MediaPlayerInstance decoderInstance = { 0 };
|
||||
static StreamInfo streamInfo;
|
||||
|
||||
typedef void (*mediaTaskCallback)(uint32_t *state);
|
||||
static mediaTaskCallback stateCB;
|
||||
|
||||
|
||||
void mediaDecoderTask(void *pvParameters)
|
||||
{
|
||||
MediaPlayerInstance *MPI = (MediaPlayerInstance *)pvParameters;
|
||||
LOGI("%s is running.%x %x", __func__, pvParameters, MPI->threadQuit);
|
||||
|
||||
/////////////////////////////
|
||||
MPI->threadQuit = 0;
|
||||
int newPos = 0;
|
||||
uint32_t wrPos, rdPos;
|
||||
int isLoopNum = 0;
|
||||
int readSize = DATA_PKG_SIZE;
|
||||
int writeDataFinished = 0;
|
||||
while (MPI->threadQuit == 0) {
|
||||
switch (MPI->state) {
|
||||
case TaskState_Ready:
|
||||
if (MPI->player.musicType == EspAudioMeidaType_Unknown) {
|
||||
vTaskDelay(100);
|
||||
continue;
|
||||
}
|
||||
LOGD("MPI is here,rate=%d,channel=%d,bitLen=%x",
|
||||
streamInfo.rate,
|
||||
streamInfo.ch,
|
||||
streamInfo.bitLen);
|
||||
MusicInfo setInfo;
|
||||
setInfo.num_channels = streamInfo.ch;
|
||||
setInfo.sampling_rate = streamInfo.rate;
|
||||
mediaHalModeSet(MediaMode_Decode, &setInfo);
|
||||
mediaHalPlay(MPI->player.musicType);
|
||||
audioBufPosGet(&rdPos, &wrPos);
|
||||
if ((InputSrcType_NetSpec == MPI->player.srcType)
|
||||
|| (InputSrcType_LocalFile == MPI->player.srcType)
|
||||
|| ((InputSrcType_Stream == MPI->player.srcType) && (MPI->player.totalByteLength != 0))) {
|
||||
if ((MPI->player.totalByteLength - MPI->player.bytePosition) < DATA_PKG_SIZE) {
|
||||
readSize = MPI->player.totalByteLength - MPI->player.bytePosition;
|
||||
} else {
|
||||
readSize = DATA_PKG_SIZE;
|
||||
}
|
||||
} else {
|
||||
readSize = DATA_PKG_SIZE;
|
||||
}
|
||||
LOGD("rdPos=%x,wrPos=%x,readSize=%d, type=%d\r\n", rdPos, wrPos, readSize, MPI->player.srcType);
|
||||
MPI->state = TaskState_Running;
|
||||
writeDataFinished = 0;
|
||||
isLoopNum = 0;
|
||||
|
||||
MPI->lastState = TaskState_Ready;
|
||||
break;
|
||||
case TaskState_Pause:
|
||||
mediaHalPause();
|
||||
LOGI("Pause playing music....");
|
||||
MPI->state = TaskState_Idle;
|
||||
MPI->lastState = TaskState_Pause;
|
||||
break;
|
||||
case TaskState_Resume:
|
||||
mediaHalPlay(MPI->player.musicType);
|
||||
MPI->state = TaskState_Running;
|
||||
MPI->lastState = TaskState_Resume;
|
||||
LOGI("Resume playing music....");
|
||||
break;
|
||||
case TaskState_Running: {
|
||||
if (1 == writeDataFinished) {
|
||||
MusicInfo info;
|
||||
mediaHalMusicInfoGet(&info);
|
||||
if (1 == info.bufEmpty) {
|
||||
MPI->state = TaskState_Stoped;
|
||||
LOGI("Set state TaskState_Stoped");
|
||||
} else {
|
||||
LOGI("Waiting for decoder empty...");
|
||||
}
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
break;
|
||||
}
|
||||
int res = audioBufRead(MPI->player.dat, readSize, 100);
|
||||
if (res == 0) {
|
||||
MPI->state = TaskState_Stoped;
|
||||
LOGD("audio buffer read quit");
|
||||
break;
|
||||
}
|
||||
MediaErr ret = mediaHalDataWrite((uint8_t*)MPI->player.dat, readSize);
|
||||
if (ret == MediaErr_NoError) {
|
||||
MPI->player.bytePosition += readSize;
|
||||
if ((InputSrcType_NetSpec == MPI->player.srcType)
|
||||
|| (InputSrcType_LocalFile == MPI->player.srcType)
|
||||
|| ((InputSrcType_Stream == MPI->player.srcType) && (MPI->player.totalByteLength != 0))) {
|
||||
newPos = MPI->player.bytePosition + DATA_PKG_SIZE;
|
||||
if (MPI->player.totalByteLength <= newPos) {
|
||||
writeDataFinished = 1;
|
||||
readSize = MPI->player.totalByteLength - MPI->player.bytePosition;
|
||||
|
||||
MPI->player.bytePosition = MPI->player.totalByteLength;
|
||||
LOGD("Last byte Pos=%d total=%d", MPI->player.bytePosition, MPI->player.totalByteLength);
|
||||
break;
|
||||
} else {
|
||||
readSize = DATA_PKG_SIZE;
|
||||
}
|
||||
}
|
||||
} else if (MediaErr_CodecError == ret) {
|
||||
uint32_t rdPOS, wrPOS;
|
||||
audioBufPosGet(&rdPOS, &wrPOS);
|
||||
LOGI("ap8048 init failed ret=%x.Try again.rdPOS=%x,wrPOS=%x", ret, rdPOS, wrPOS);
|
||||
audioBufRdPosSet(&rdPos);
|
||||
mediaHalStop();
|
||||
MPI->state = TaskState_Ready;
|
||||
} else {
|
||||
LOGE("ap8048 ret error[%x]", ret);
|
||||
}
|
||||
MPI->lastState = TaskState_Running;
|
||||
}
|
||||
|
||||
break;
|
||||
case TaskState_Stoped: {
|
||||
mediaHalStop();
|
||||
newPos = 0;
|
||||
if (MPI->player.bytePosition == MPI->player.totalByteLength) {
|
||||
MPI->state = TaskState_Finished;
|
||||
MPI->player.bytePosition = 0;
|
||||
MPI->player.totalByteLength = 0;
|
||||
} else {
|
||||
MPI->state = TaskState_Idle;
|
||||
}
|
||||
LOGI("Stop playing music....state[%d]", MPI->state);
|
||||
MPI->lastState = TaskState_Stoped;
|
||||
if (stateCB) stateCB(&MPI->state);
|
||||
break;
|
||||
}
|
||||
case TaskState_Finished:
|
||||
case TaskState_Idle:
|
||||
default:
|
||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||
// LOGD("MPI->state[%d]", MPI->state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MPI->threadQuit = -1;
|
||||
MPI->thread = NULL;
|
||||
MPI->state = TaskState_Unknown;
|
||||
MPI->lastState = TaskState_Unknown;
|
||||
|
||||
LOGD("%s is ended...", __func__);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void mediaDecoderTaskCb(void *func)
|
||||
{
|
||||
stateCB = func;
|
||||
}
|
||||
TaskState mediaDecoderTaskStateGet()
|
||||
{
|
||||
return decoderInstance.lastState;
|
||||
}
|
||||
|
||||
void mediaDecoderTaskInfoGet(DecoderObj *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
memcpy(obj, &decoderInstance.player, sizeof(*obj));
|
||||
}
|
||||
|
||||
void mediaDecoderStreamInfoSet(StreamInfo *info)
|
||||
{
|
||||
if (NULL == info) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
memcpy(&streamInfo, info, sizeof(streamInfo));
|
||||
decoderInstance.player.totalByteLength = 0;
|
||||
LOGD("Set Stream info ok,rate=%d,channel=%d,bitLen=%x",
|
||||
streamInfo.rate,
|
||||
streamInfo.ch,
|
||||
streamInfo.bitLen);
|
||||
}
|
||||
|
||||
void mediaDecoderStreamSizeUpdate(uint32_t *size)
|
||||
{
|
||||
if (NULL == *size) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
decoderInstance.player.totalByteLength = *size;
|
||||
LOGD("Stream total size=%d", decoderInstance.player.totalByteLength);
|
||||
}
|
||||
|
||||
|
||||
void mediaDecoderTaskInfoSet(DecoderObj *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
LOGE("Invalid para");
|
||||
return ;
|
||||
}
|
||||
memcpy(&decoderInstance.player, obj, sizeof(*obj));
|
||||
|
||||
LOGD("Set DecoderObj ok,total=%d,type=%d,dat=%x music=%d",
|
||||
decoderInstance.player.totalByteLength,
|
||||
decoderInstance.player.srcType,
|
||||
decoderInstance.player.dat,
|
||||
decoderInstance.player.musicType);
|
||||
}
|
||||
|
||||
void mediaDecoderTaskPause()
|
||||
{
|
||||
if (0 == decoderInstance.thread) {
|
||||
decoderInstance.state = TaskState_Unknown;
|
||||
LOGE("decoderInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
if (TaskState_Running == decoderInstance.state) {
|
||||
decoderInstance.state = TaskState_Pause;
|
||||
}
|
||||
LOGD("Task state=%d", decoderInstance.state);
|
||||
}
|
||||
|
||||
void mediaDecoderTaskResume()
|
||||
{
|
||||
if (0 == decoderInstance.thread) {
|
||||
decoderInstance.state = TaskState_Unknown;
|
||||
LOGE("decoderInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
decoderInstance.state = TaskState_Resume;
|
||||
LOGD("Task state=%d", decoderInstance.state);
|
||||
}
|
||||
|
||||
void mediaDecoderTaskCreate()
|
||||
{
|
||||
if (NULL != decoderInstance.player.dat) {
|
||||
free(decoderInstance.player.dat);
|
||||
}
|
||||
memset(&decoderInstance, 0, sizeof(decoderInstance));
|
||||
memset(&streamInfo, 0, sizeof(streamInfo));
|
||||
decoderInstance.player.dat = calloc(1, DATA_PKG_SIZE);
|
||||
if (NULL == decoderInstance.player.dat) {
|
||||
LOGE("decoderInstance.player.dat malloc error");
|
||||
return;
|
||||
}
|
||||
xTaskCreate(mediaDecoderTask, "mediaDecoderTask", (5 * 1024), &decoderInstance, DECODER_TSK_PRIO, &decoderInstance.thread);
|
||||
configASSERT(decoderInstance.thread);
|
||||
LOGD("Task state=%d,dat:%x", decoderInstance.state, decoderInstance.player.dat);
|
||||
rdQue = xQueueCreate(2, 1);
|
||||
configASSERT(rdQue);
|
||||
audioBufRdQuitCfg(rdQue);
|
||||
}
|
||||
|
||||
|
||||
int mediaDecoderTaskStart()
|
||||
{
|
||||
if (0 == decoderInstance.thread) {
|
||||
decoderInstance.state = TaskState_Unknown;
|
||||
LOGE("decoderInstance.thread is NULL");
|
||||
return -1;
|
||||
}
|
||||
if ((decoderInstance.player.srcType == InputSrcType_NetSpec)
|
||||
|| (decoderInstance.player.srcType == InputSrcType_LocalFile)) {
|
||||
if (decoderInstance.player.totalByteLength == 0) {
|
||||
LOGE("Player parameter is not ready");
|
||||
decoderInstance.state = TaskState_Idle;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
decoderInstance.state = TaskState_Ready;
|
||||
LOGD("Task state=%d", decoderInstance.state);
|
||||
audioBufRdRest();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mediaDecoderTaskStop()
|
||||
{
|
||||
if (0 == decoderInstance.thread) {
|
||||
decoderInstance.state = TaskState_Unknown;
|
||||
LOGE("decoderInstance.thread is NULL");
|
||||
return;
|
||||
}
|
||||
if ((decoderInstance.lastState == TaskState_Unknown)
|
||||
|| (decoderInstance.lastState == TaskState_Stoped)) {
|
||||
LOGW("dlInstance.state is [%d]", decoderInstance.state);
|
||||
return;
|
||||
}
|
||||
decoderInstance.state = TaskState_Stoped;
|
||||
configASSERT(rdQue);
|
||||
xQueueSend(rdQue, &decoderInstance.state, 0);
|
||||
LOGD("Task state=%d", decoderInstance.state);
|
||||
while ((TaskState_Finished != decoderInstance.state)
|
||||
&& (TaskState_Idle != decoderInstance.state)) {
|
||||
if ((TaskState_Idle == decoderInstance.state)) {
|
||||
break;
|
||||
}
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
}
|
||||
audioBufRdRest();
|
||||
int flag;
|
||||
xQueueReceive(rdQue, &flag, 0);
|
||||
LOGD("Task state=%d", decoderInstance.state);
|
||||
}
|
||||
|
||||
void mediaDecoderTaskDestroy()
|
||||
{
|
||||
if (0 == decoderInstance.threadQuit) {
|
||||
decoderInstance.state = TaskState_Stoped;
|
||||
decoderInstance.threadQuit = 1;
|
||||
while (1) {
|
||||
if ((decoderInstance.threadQuit == -1)) {
|
||||
break;
|
||||
}
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != decoderInstance.player.dat) {
|
||||
free(decoderInstance.player.dat);
|
||||
}
|
||||
memset(&decoderInstance.player, 0, sizeof(decoderInstance.player));
|
||||
memset(&streamInfo, 0, sizeof(streamInfo));
|
||||
decoderInstance.player.dat = NULL;
|
||||
decoderInstance.state = TaskState_Unknown;
|
||||
vQueueDelete(rdQue);
|
||||
rdQue = NULL;
|
||||
LOGD("Task state=%d", decoderInstance.state);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* File Name : wm_http_client.h
|
||||
*
|
||||
* Description: Http client header file.
|
||||
*
|
||||
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author : wanghf
|
||||
*
|
||||
* Date : 2014-6-6
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __DECODER_COM_H__
|
||||
#define __DECODER_COM_H__
|
||||
#include "esp_types.h"
|
||||
|
||||
|
||||
|
||||
// HTTP Type Definitions
|
||||
|
||||
//#define pthread_t sys_thread_t
|
||||
|
||||
|
||||
typedef enum {
|
||||
TaskState_Unknown = 0,
|
||||
TaskState_Idle = 1, // running state
|
||||
TaskState_Running = 2,
|
||||
TaskState_Stoped = 3,
|
||||
TaskState_Finished = 4,
|
||||
|
||||
TaskState_Ready = 10, //control state
|
||||
TaskState_Resume = 11,
|
||||
TaskState_Pause = 12,
|
||||
|
||||
} TaskState;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__DECODER_COM_H__
|
|
@ -1,46 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* File Name : wm_http_client.h
|
||||
*
|
||||
* Description: Http client header file.
|
||||
*
|
||||
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author : wanghf
|
||||
*
|
||||
* Date : 2014-6-6
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef HTTP_CLIENT_H
|
||||
#define HTTP_CLIENT_H
|
||||
#include "esp_types.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "DecoderCom.h"
|
||||
|
||||
#define ESP_URI_LEN 1024
|
||||
|
||||
typedef struct {
|
||||
char *str;
|
||||
int srcType; // 0:specific net audio; 1:m3u8 files; 2:audio data files
|
||||
// int setStartBytePos;
|
||||
} UriSrcAttr;
|
||||
|
||||
TaskState downloadTaskStateGet();
|
||||
|
||||
void downloadTaskContentSizeGet(uint32_t *size);
|
||||
|
||||
void downloadTaskInfoSet(UriSrcAttr *obj);
|
||||
int downloadTaskHTTPStateGet();
|
||||
|
||||
void downloadTaskPause();
|
||||
|
||||
void downloadTaskResume();
|
||||
|
||||
int downloadTaskStart();
|
||||
void downloadTaskStop();
|
||||
|
||||
void downloadTaskCreate(int taskType);
|
||||
void downloadTaskDestroy();
|
||||
|
||||
#endif //
|
|
@ -1,79 +0,0 @@
|
|||
#ifndef _M3U8_H_
|
||||
#define _M3U8_H_
|
||||
#include "esp_types.h"
|
||||
|
||||
#define MAX_SEGMENT_COUNT 3
|
||||
|
||||
|
||||
//
|
||||
typedef enum {
|
||||
AUDIOFMT_UNKNOWN = 0,
|
||||
AUDIOFMT_AAC = 1,
|
||||
AUDIOFMT_TS = 2,
|
||||
} AUDIOFMT;
|
||||
|
||||
typedef struct {
|
||||
size_t date;
|
||||
size_t main;
|
||||
size_t sub;
|
||||
} M3u8Seq;
|
||||
//
|
||||
typedef struct {
|
||||
int duration;
|
||||
int rate;
|
||||
AUDIOFMT fmt;
|
||||
char url[128];
|
||||
char name[256];
|
||||
M3u8Seq seq;
|
||||
} M3u8Segment;
|
||||
|
||||
//
|
||||
typedef struct _M3u8Info {
|
||||
int targetDuration;
|
||||
size_t mediaSeq;
|
||||
int segCount;
|
||||
M3u8Segment segList[MAX_SEGMENT_COUNT];
|
||||
} M3u8Info;
|
||||
|
||||
|
||||
typedef struct _audioUrlObj {
|
||||
AUDIOFMT fmt;
|
||||
uint32_t uflag; // 0-empty;1-ready;2-using;3-used;
|
||||
uint32_t idx; // stream sequence
|
||||
// uint32_t totalTime; // time of music,live:0
|
||||
char *url;
|
||||
char *radioName;
|
||||
char *musicName;
|
||||
struct _audioUrlObj *next;
|
||||
} audioUrlObj;
|
||||
|
||||
|
||||
uint8_t m3u8CheckValid(const M3u8Seq* new, const M3u8Seq* pre);
|
||||
|
||||
|
||||
/**
|
||||
* [m3u8_parser Parser the m3u8 string]
|
||||
* @param m3u8_string [To be parser string]
|
||||
* @return [m3u8 object, NULL->failed]
|
||||
*/
|
||||
M3u8Info *m3u8Parser(char *m3u8Str, M3u8Info* m3u8);
|
||||
|
||||
/**
|
||||
* [m3u8_destroy Destroy the m3u8 struct]
|
||||
* @param m3u8 [m3u8 struct]
|
||||
*/
|
||||
void m3u8Destroy(M3u8Info *m3u8);
|
||||
|
||||
/**
|
||||
* [m3u8_save description]
|
||||
* @param m3u8 [m3u8 struct]
|
||||
* @param m3u8_path [file path]
|
||||
* @param ts_segment_url_prefix [prefix will be fill]
|
||||
* @return [0->failed;1->successed]
|
||||
*/
|
||||
//int m3u8_save(M3u8Info *m3u8, char *m3u8_path, char *ts_segment_url_prefix);
|
||||
|
||||
|
||||
int m3u8_test(char* pStr);
|
||||
|
||||
#endif
|
|
@ -1,66 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* File Name : wm_http_client.h
|
||||
*
|
||||
* Description: Http client header file.
|
||||
*
|
||||
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author : wanghf
|
||||
*
|
||||
* Date : 2014-6-6
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __PLAYERTASK_H__
|
||||
#define __PLAYERTASK_H__
|
||||
#include "esp_types.h"
|
||||
#include "EspAudioCom.h"
|
||||
#include "EspAudio.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "MediaHal.h"
|
||||
|
||||
//Type Definitions
|
||||
|
||||
typedef struct {
|
||||
char *dat;
|
||||
InputSrcType srcType;
|
||||
EspAudioMeidaType musicType;
|
||||
uint32_t totalByteLength;
|
||||
uint32_t bytePosition;
|
||||
int codecVer;
|
||||
int codecType; // 0:hardware; 1:software
|
||||
} DecoderObj;
|
||||
|
||||
typedef struct {
|
||||
uint32_t rate;
|
||||
uint32_t ch;
|
||||
uint32_t bitLen;
|
||||
uint32_t size; // 0xFFFFFFFF stream length is infinite
|
||||
} StreamInfo;
|
||||
|
||||
TaskState mediaDecoderTaskStateGet();
|
||||
void mediaDecoderStreamInfoSet(StreamInfo *info);
|
||||
|
||||
void mediaDecoderTaskInfoGet(DecoderObj *obj);
|
||||
void mediaDecoderTaskInfoSet(DecoderObj *obj);
|
||||
void mediaDecoderTaskPause();
|
||||
void mediaDecoderTaskResume();
|
||||
|
||||
int mediaDecoderTaskStart();
|
||||
void mediaDecoderTaskStop();
|
||||
|
||||
void mediaDecoderTaskCreate();
|
||||
void mediaDecoderTaskDestroy();
|
||||
|
||||
void mediaDecoderVolSet();
|
||||
void mediaDecoderVolGet();
|
||||
void mediaDecoderMusicInfoGet();
|
||||
void mediaDecoderDecodeTimeGet();
|
||||
void mediaDecoderModeSet();
|
||||
void mediaDecoderStreamSizeUpdate(uint32_t *size);
|
||||
void mediaDecoderTaskCb(void *func);
|
||||
|
||||
|
||||
|
||||
#endif //__PLAYERTASK_H__
|
|
@ -1,300 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "DecoderCom.h"
|
||||
#include "EspAudioCom.h"
|
||||
#include "MediaHal.h"
|
||||
#include "EspAudioRecorder.h"
|
||||
#include "Ap80xx.h"
|
||||
|
||||
#define RECORD_TSK_PRIO 6
|
||||
#define RECORDER_PKG_SIZE 1024
|
||||
|
||||
typedef enum {
|
||||
RecorderEventType_Unknown,
|
||||
RecorderEventType_Start,
|
||||
RecorderEventType_Stop,
|
||||
RecorderEventType_Pause,
|
||||
RecorderEventType_Resume,
|
||||
RecorderEventType_Quit,
|
||||
} RecorderEventType;
|
||||
|
||||
typedef struct {
|
||||
RecorderEventType type;
|
||||
void *value;
|
||||
} RecorderEventInfo;
|
||||
|
||||
static xTaskHandle recorderThread;
|
||||
static xQueueHandle recorderEventQue;
|
||||
static RecorderState recTaskState;
|
||||
static MusicInfo streamInfo;
|
||||
|
||||
void MediaEncoderTask(void *pvParameters)
|
||||
{
|
||||
LOGI("%s is running.%x %x", __func__);
|
||||
/////////////////////////////
|
||||
RecorderEventInfo eventInfo ;
|
||||
static RecorderAttr s_attr;
|
||||
static int recordStartFlag = 0;
|
||||
eventInfo.type = RecorderEventType_Unknown;
|
||||
eventInfo.value = NULL;
|
||||
uint8_t *recvData = malloc(RECORDER_PKG_SIZE);
|
||||
if (NULL == recvData) {
|
||||
LOGE("malloc failed");
|
||||
return ;
|
||||
}
|
||||
memset(recvData, 0, RECORDER_PKG_SIZE);
|
||||
|
||||
while (1) {
|
||||
if (xQueueReceive(recorderEventQue, &eventInfo, 10)) {
|
||||
switch (eventInfo.type) {
|
||||
case RecorderEventType_Start: {
|
||||
MediaState mediaState;
|
||||
mediaHalStatusGet(&mediaState);
|
||||
LOGD("Start recording ...%d", mediaState);
|
||||
if (MediaState_Initialized > mediaState) {
|
||||
mediaHalInit();
|
||||
LOGD("Need to init codec driver...[%d]", mediaState);
|
||||
}
|
||||
if (eventInfo.value) {
|
||||
memcpy(&s_attr, eventInfo.value, sizeof(s_attr));
|
||||
free(eventInfo.value);
|
||||
eventInfo.value = NULL;
|
||||
LOGI("recv:channel=%d, rate=%d, encodeType=%d, func=%p",
|
||||
s_attr.channel, s_attr.rate, s_attr.encodeType, s_attr.func);
|
||||
streamInfo.sampling_rate =s_attr.rate;
|
||||
streamInfo.num_channels = s_attr.channel;
|
||||
streamInfo.stream_type = s_attr.encodeType;
|
||||
|
||||
mediaHalModeSet(MediaMode_Encode, &streamInfo);
|
||||
recordStartFlag = 1;
|
||||
recTaskState = RecorderState_Recording;
|
||||
LOGI("Start recording ....");
|
||||
} else {
|
||||
LOGE("eventInfo.value = NULL");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RecorderEventType_Pause: {
|
||||
if (RecorderState_Recording == recTaskState) {
|
||||
recordStartFlag = 0;
|
||||
recTaskState = RecorderState_Paused;
|
||||
LOGI("Pause recording");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RecorderEventType_Resume: {
|
||||
if (RecorderState_Paused == recTaskState) {
|
||||
recordStartFlag = 1;
|
||||
recTaskState = RecorderState_Recording;
|
||||
LOGI("Resume recording");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RecorderEventType_Stop: {
|
||||
recordStartFlag = 0;
|
||||
recTaskState = RecorderState_Stoped;
|
||||
|
||||
apSetDecodeMode();
|
||||
memset(&streamInfo, 0, sizeof(streamInfo));
|
||||
LOGI("Stop recording");
|
||||
break;
|
||||
}
|
||||
case RecorderEventType_Quit: {
|
||||
recordStartFlag = 0;
|
||||
recTaskState = RecorderState_Unknown;
|
||||
LOGI("MediaEncoderTask will be quit");
|
||||
goto encoderTaskQuit;
|
||||
}
|
||||
default:
|
||||
vTaskDelay(250 / portTICK_RATE_MS);
|
||||
LOGE("Event type does not support[%d]", eventInfo.type);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LOGD("stack left %d byte\n", uxTaskGetStackHighWaterMark(NULL));
|
||||
if (recordStartFlag) {
|
||||
int len = 0;
|
||||
int ret = mediaHalDataRead(recvData, &len);
|
||||
if ((ret != 0) || (len == 1)) {
|
||||
LOGE("mediaHalDataRead failed,ret=%d len=%d", ret, len);
|
||||
continue;
|
||||
} else {
|
||||
// LOGD("mediaHalDataRead ok,ret=%d len=%d", ret, len);
|
||||
if (len>0) {
|
||||
s_attr.func(recvData, (uint32_t*)&len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
encoderTaskQuit:
|
||||
free(recvData);
|
||||
recvData = NULL;
|
||||
configASSERT(recorderEventQue);
|
||||
vQueueDelete(recorderEventQue);
|
||||
recorderEventQue = NULL;
|
||||
recorderThread = NULL;
|
||||
LOGI("%s is ended...", __func__);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderStateGet(RecorderState *state)
|
||||
{
|
||||
if (NULL == state) {
|
||||
LOGE("Invalid para,%p", state);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
*state = recTaskState;
|
||||
|
||||
return EspAudioErr_NoErr;
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderInit(void)
|
||||
{
|
||||
if (NULL == recorderThread) {
|
||||
xTaskCreate(MediaEncoderTask, "MediaEncoderTask", (5*1024), NULL, RECORD_TSK_PRIO, &recorderThread);
|
||||
configASSERT(recorderThread);
|
||||
}
|
||||
if (NULL == recorderEventQue) {
|
||||
recorderEventQue = xQueueCreate(4, sizeof(RecorderEventInfo));
|
||||
configASSERT(recorderEventQue);
|
||||
}
|
||||
|
||||
LOGD("recorder has been created, %p,%p", recorderThread, recorderEventQue);
|
||||
recTaskState = RecorderState_Init;
|
||||
return EspAudioErr_NoErr;
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderStart(RecorderAttr *recorderAttr)
|
||||
{
|
||||
if ((NULL == recorderAttr)
|
||||
|| (NULL == recorderThread)
|
||||
|| (NULL == recorderEventQue)) {
|
||||
LOGE("Invalid para, %p,%p,%p", recorderAttr, recorderThread, recorderEventQue);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
if (NULL == recorderAttr->func) {
|
||||
LOGE("Invalid para, %p", recorderAttr->func);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
RecorderAttr *attr = malloc(sizeof(RecorderAttr));
|
||||
if (NULL == attr) {
|
||||
LOGE("Malloc failed");
|
||||
return EspAudioErr_NoMem;
|
||||
}
|
||||
attr->channel = recorderAttr->channel;
|
||||
attr->rate = recorderAttr->rate;
|
||||
attr->encodeType = recorderAttr->encodeType;
|
||||
attr->func = recorderAttr->func;
|
||||
|
||||
RecorderEventInfo eventInfo ;
|
||||
eventInfo.type = RecorderEventType_Start;
|
||||
eventInfo.value = attr;
|
||||
LOGD("channel=%d, rate=%d, encodeType=%d, func=%p",
|
||||
attr->channel, attr->rate, attr->encodeType, attr->func);
|
||||
configASSERT(recorderEventQue);
|
||||
if (pdTRUE != xQueueSend(recorderEventQue, &eventInfo, 0)) {
|
||||
LOGE("EspAudioRecorderStart, queue send failed");
|
||||
} else {
|
||||
LOGD("EspAudioRecorderStart, send sucessed");
|
||||
}
|
||||
return EspAudioErr_NoErr;
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderPause(void)
|
||||
{
|
||||
if ((NULL == recorderThread)
|
||||
|| (NULL == recorderEventQue)) {
|
||||
LOGE("Invalid para, %p,%p", recorderThread, recorderEventQue);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
RecorderEventInfo eventInfo ;
|
||||
eventInfo.type = RecorderEventType_Pause;
|
||||
eventInfo.value = NULL;
|
||||
configASSERT(recorderEventQue);
|
||||
if (pdTRUE != xQueueSend(recorderEventQue, &eventInfo, 0)) {
|
||||
LOGE("RecorderEventType_Pause, queue send failed");
|
||||
} else {
|
||||
LOGD("RecorderEventType_Pause, send sucessed");
|
||||
}
|
||||
return EspAudioErr_NoErr;
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderResume(void)
|
||||
{
|
||||
if ((NULL == recorderThread)
|
||||
|| (NULL == recorderEventQue)) {
|
||||
LOGE("Invalid para, %p,%p", recorderThread, recorderEventQue);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
RecorderEventInfo eventInfo ;
|
||||
eventInfo.type = RecorderEventType_Resume;
|
||||
eventInfo.value = NULL;
|
||||
configASSERT(recorderEventQue);
|
||||
if (pdTRUE != xQueueSend(recorderEventQue, &eventInfo, 0)) {
|
||||
LOGE("RecorderEventType_Resume, queue send failed");
|
||||
} else {
|
||||
LOGD("RecorderEventType_Resume, send sucessed");
|
||||
}
|
||||
return EspAudioErr_NoErr;
|
||||
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderStop(void)
|
||||
{
|
||||
if ((NULL == recorderThread)
|
||||
|| (NULL == recorderEventQue)) {
|
||||
LOGE("Invalid para, %p,%p", recorderThread, recorderEventQue);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
RecorderEventInfo eventInfo ;
|
||||
eventInfo.type = RecorderEventType_Stop;
|
||||
eventInfo.value = NULL;
|
||||
configASSERT(recorderEventQue);
|
||||
if (pdTRUE != xQueueSend(recorderEventQue, &eventInfo, 0)) {
|
||||
LOGE("RecorderEventType_Stop, queue send failed");
|
||||
} else {
|
||||
LOGD("RecorderEventType_Stop, send sucessed");
|
||||
}
|
||||
return EspAudioErr_NoErr;
|
||||
}
|
||||
|
||||
EspAudioErr EspAudioRecorderUninit(void)
|
||||
{
|
||||
if ((NULL == recorderThread)
|
||||
|| (NULL == recorderEventQue)) {
|
||||
LOGE("recorderThread=%p, recorderEventQue=%p", recorderThread, recorderEventQue);
|
||||
return EspAudioErr_InvalidPara;
|
||||
}
|
||||
RecorderEventInfo eventInfo ;
|
||||
eventInfo.type = RecorderEventType_Quit;
|
||||
eventInfo.value = NULL;
|
||||
configASSERT(recorderEventQue);
|
||||
if (pdTRUE != xQueueSend(recorderEventQue, &eventInfo, 0)) {
|
||||
LOGE("RecorderEventType_Quit, queue send failed");
|
||||
} else {
|
||||
LOGD("RecorderEventType_Quit, send sucessed");
|
||||
}
|
||||
return EspAudioErr_NoErr;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,53 +0,0 @@
|
|||
#include <stdint.h>
|
||||
|
||||
static const uint16_t gCRC16TableNBS[256] =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
|
||||
uint16_t GetCRC16NBS(uint8_t* data, uint32_t length)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint8_t temp;
|
||||
|
||||
while(length--)
|
||||
{
|
||||
temp = (unsigned char)(crc >> 8); // get high byte
|
||||
crc <<= 8; // get low byte
|
||||
crc ^= gCRC16TableNBS[*data ^ temp];
|
||||
data++;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
|
@ -1,387 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dma.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#define QUEUE_BLOCK_LENGTH (4096L)
|
||||
|
||||
|
||||
#define DMA_DBG_WARING_ENABLE (0)
|
||||
#define DMA_DBG_ERROR_ENABLE (0)
|
||||
#define DMA_INFO_ENABLE (0)
|
||||
#define DMA_DBG_ENABLE (0)
|
||||
|
||||
//DBG INFOR
|
||||
#if DMA_DBG_ENABLE
|
||||
#define DMA_DBG(format,...) do{\
|
||||
ets_printf("[dbg][%s#%u]",__FUNCTION__,__LINE__);\
|
||||
ets_printf(format,##__VA_ARGS__);\
|
||||
}while(0)
|
||||
#else
|
||||
#define DMA_DBG(...)
|
||||
#endif
|
||||
#if DMA_INFO_ENABLE
|
||||
#define DMA_INFO(format,...) do{\
|
||||
ets_printf("[info][%s#%u]",__FUNCTION__,__LINE__);\
|
||||
ets_printf(format,##__VA_ARGS__);\
|
||||
}while(0)
|
||||
#else
|
||||
#define DMA_INFO(...)
|
||||
#endif
|
||||
|
||||
#if DMA_DBG_WARNING_ENABLE
|
||||
#define DMA_WARNING(format,...) do{\
|
||||
ets_printf("[waring][%s#%u]",__FUNCTION__,__LINE__);\
|
||||
ets_printf(format,##__VA_ARGS__);\
|
||||
}while(0)
|
||||
#else
|
||||
#define DMA_WARNING(...)
|
||||
#endif
|
||||
#if DMA_DBG_ERROR_ENABLE
|
||||
#define DMA_ERROR(format,...) do{\
|
||||
ets_printf("[error][%s#%u]",__FUNCTION__,__LINE__);\
|
||||
ets_printf(format,##__VA_ARGS__);\
|
||||
}while(0)
|
||||
#else
|
||||
#define DMA_ERROR(...)
|
||||
#endif
|
||||
|
||||
void dma_show_queue(ping_pong_buf_t *pcfg)
|
||||
{
|
||||
uint32_t i;
|
||||
DMA_INFO("obj=%x \r\n", pcfg);
|
||||
DMA_INFO("ping bck que=%x buf=%x,next_link_ptr=%x\r\n", pcfg->ping->backup_queue, pcfg->ping->buffer_addr, pcfg->ping->backup_queue.next_link_ptr);
|
||||
DMA_INFO("ping first_que=%x, %08x, buf=%x\r\n", pcfg->ping->first_queue,*pcfg->ping->first_queue, pcfg->ping->buffer_addr);
|
||||
DMA_INFO("ping last_que=%x, %08x, buf=%x\r\n", pcfg->ping->last_queue, *pcfg->ping->last_queue, pcfg->ping->buffer_addr);
|
||||
|
||||
DMA_INFO("pong bck que=%x buf=%x,next_link_ptr=%x\r\n", pcfg->pong->backup_queue, pcfg->pong->buffer_addr, pcfg->pong->backup_queue.next_link_ptr);
|
||||
DMA_INFO("pong first_que=%x, %08x, buf=%x\r\n", pcfg->pong->first_queue, *pcfg->pong->first_queue, pcfg->pong->buffer_addr);
|
||||
DMA_INFO("pong last_que=%x, %08x, buf=%x\r\n", pcfg->pong->last_queue, *pcfg->pong->last_queue, pcfg->pong->buffer_addr);
|
||||
|
||||
dma_queue_t *addr = (dma_queue_t*)pcfg->ping->first_queue;
|
||||
dma_queue_t *addr1 = (dma_queue_t*)pcfg->pong->first_queue;
|
||||
for (i = 0; i < pcfg->queue_cnt; ++i) {
|
||||
DMA_INFO("ping queue%d buf:%08x,len=%d,size=%d,cur_link:%08x,next_link:%08x\r\n", i,
|
||||
addr->buf_ptr,addr->data_length, addr->block_size, addr, addr->next_link_ptr);
|
||||
addr = (dma_queue_t*)addr->next_link_ptr;
|
||||
}
|
||||
for (i = 0; i < pcfg->queue_cnt; ++i) {
|
||||
DMA_INFO("pong queue%d buf:%08x,len=%d,size=%d,cur_link:%08x,next_link:%08x\r\n", i,
|
||||
addr1->buf_ptr,addr1->data_length, addr1->block_size, addr1, addr1->next_link_ptr);
|
||||
addr1 = (dma_queue_t*)addr1->next_link_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill a link
|
||||
*
|
||||
*/
|
||||
static void fill_one_link(uint8_t own, uint8_t eof, uint8_t sub_sof, uint16_t size, uint16_t length,
|
||||
uint32_t *buf_ptr, dma_queue_t *nxt_ptr, dma_queue_t *i2s_queue)
|
||||
{
|
||||
i2s_queue->owner = own;
|
||||
i2s_queue->eof = eof;
|
||||
i2s_queue->sub_sof = sub_sof;
|
||||
i2s_queue->data_length = 0x0FFF & length;
|
||||
i2s_queue->block_size = size ;
|
||||
i2s_queue->buf_ptr = (uint32_t)buf_ptr;
|
||||
i2s_queue->next_link_ptr = (uint32_t)nxt_ptr;
|
||||
i2s_queue->unused = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill the queue
|
||||
*
|
||||
*/
|
||||
static int dma_queue_fill(uint32_t cnt, uint32_t len, ping_pong_buf_t *cfg)
|
||||
{
|
||||
if (0 == cnt) {
|
||||
return -1;
|
||||
}
|
||||
// ping queue list
|
||||
dma_queue_t *pingAry[cnt];
|
||||
// pong queue list
|
||||
dma_queue_t *pongAry[cnt];
|
||||
uint32_t i, j;
|
||||
memset(&pingAry, 0, sizeof(pingAry));
|
||||
memset(&pongAry, 0, sizeof(pongAry));
|
||||
cnt = 1;
|
||||
for (i = 0; i < cnt; ++i) {
|
||||
pingAry[i] = (dma_queue_t*)malloc(sizeof(dma_queue_t));
|
||||
if (pingAry[i] == NULL) {
|
||||
for (j = 0; j < i; ++j) {
|
||||
free(pingAry[j]);
|
||||
pingAry[j] = NULL;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < cnt; ++i) {
|
||||
pongAry[i] = (dma_queue_t*)malloc(sizeof(dma_queue_t));
|
||||
if (NULL == pongAry[i]) {
|
||||
for (j = 0; j < cnt; ++j) {
|
||||
free(pingAry[j]);
|
||||
pingAry[j] = NULL;
|
||||
}
|
||||
for (j = 0; j < i; ++j) {
|
||||
free(pongAry[j]);
|
||||
pongAry[j] = NULL;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
cfg->ping->first_queue = pingAry[0];
|
||||
cfg->pong->first_queue = pongAry[0];
|
||||
if (1 == cnt) {
|
||||
cfg->ping->last_queue = pingAry[0];
|
||||
cfg->pong->last_queue = pongAry[0];
|
||||
} else {
|
||||
cfg->ping->last_queue = pingAry[cnt - 1];
|
||||
cfg->pong->last_queue = pongAry[cnt - 1];
|
||||
}
|
||||
uint32_t remainSize = len;
|
||||
uint32_t bufSize = QUEUE_BLOCK_LENGTH;
|
||||
for (i = 0; i < cnt; ++i) {
|
||||
if (1 == cnt) {
|
||||
// Queue list include only one link, and set up eof bit.
|
||||
if (QUEUE_BLOCK_LENGTH == len) {
|
||||
bufSize = len - 1;
|
||||
} else {
|
||||
bufSize = len;
|
||||
}
|
||||
fill_one_link(1, 1, 0, bufSize, bufSize, cfg->ping->buffer_addr, pongAry[i], pingAry[i]);
|
||||
fill_one_link(1, 1, 0, bufSize, bufSize, cfg->pong->buffer_addr, pingAry[i], pongAry[i]);
|
||||
} else {
|
||||
if (i == (cnt - 1)) {
|
||||
// ping/pong queue list last link connect to the pong/ping first link, and set up eof bit.
|
||||
bufSize = remainSize;
|
||||
fill_one_link(1, 1, 0, bufSize, bufSize, cfg->ping->buffer_addr + ((QUEUE_BLOCK_LENGTH / sizeof(uint32_t)) * i),
|
||||
pongAry[0], pingAry[i]);
|
||||
fill_one_link(1, 1, 0, bufSize, bufSize, cfg->pong->buffer_addr + ((QUEUE_BLOCK_LENGTH / sizeof(uint32_t)) * i),
|
||||
pingAry[0], pongAry[i]);
|
||||
} else {
|
||||
// Conncet the next link.
|
||||
fill_one_link(1, 0, 0, bufSize - 1, bufSize - 1, cfg->ping->buffer_addr + ((QUEUE_BLOCK_LENGTH / sizeof(uint32_t)) * i), pingAry[i + 1], pingAry[i]);
|
||||
fill_one_link(1, 0, 0, bufSize - 1, bufSize - 1, cfg->pong->buffer_addr + ((QUEUE_BLOCK_LENGTH / sizeof(uint32_t)) * i), pongAry[i + 1], pongAry[i]);
|
||||
}
|
||||
}
|
||||
remainSize -= bufSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a ping-pong buffer object used by DMA.
|
||||
*
|
||||
*/
|
||||
ping_pong_buf_t* dma_buf_create(uint32_t bufLen)
|
||||
{
|
||||
if (0 == bufLen) {
|
||||
return NULL;
|
||||
}
|
||||
uint32_t i, j;
|
||||
uint32_t queue_cnt ;
|
||||
uint8_t * pBuf = NULL;
|
||||
i = bufLen / QUEUE_BLOCK_LENGTH;
|
||||
j = bufLen % QUEUE_BLOCK_LENGTH;
|
||||
if (0 == j) {
|
||||
queue_cnt = i;
|
||||
} else {
|
||||
queue_cnt = i + 1;
|
||||
}
|
||||
DMA_INFO("\r\nbufLen=%d queue_cnt=%d\r\n", bufLen, queue_cnt);
|
||||
|
||||
ping_pong_buf_t* pcfg;
|
||||
pcfg = (ping_pong_buf_t*)malloc(sizeof(ping_pong_buf_t));
|
||||
if (NULL == pcfg) {
|
||||
return NULL;
|
||||
}
|
||||
pBuf = ((uint8_t*)malloc(bufLen * 2)); // buflen is number of bytes buffer.malloc ping and pong buffer.
|
||||
pcfg->ping = (dma_element_t*)malloc(sizeof(dma_element_t));
|
||||
pcfg->pong = (dma_element_t*)malloc(sizeof(dma_element_t));
|
||||
if ((NULL == pBuf)
|
||||
|| (NULL == pcfg->pong)
|
||||
|| (NULL == pcfg->ping)) {
|
||||
free(pBuf);
|
||||
pBuf = NULL;
|
||||
free(pcfg->pong);
|
||||
pcfg->pong = NULL;
|
||||
free(pcfg->ping);
|
||||
pcfg->ping = NULL;
|
||||
free(pcfg);
|
||||
pcfg = NULL;
|
||||
DMA_INFO("Malloc ping->buffer_addr failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(pBuf, 0, (bufLen * 2));
|
||||
memset(pcfg->ping, 0, sizeof(dma_element_t));
|
||||
memset(pcfg->pong, 0, sizeof(dma_element_t));
|
||||
pcfg->ping->buffer_addr = (uint32_t*)pBuf;
|
||||
pcfg->pong->buffer_addr = (uint32_t*)(pBuf + bufLen);
|
||||
pcfg->queue_cnt = queue_cnt; // Number of queue
|
||||
if (dma_queue_fill(queue_cnt, bufLen, pcfg) < 0) {
|
||||
free(pcfg->ping->buffer_addr);
|
||||
pcfg->ping->buffer_addr = NULL;
|
||||
free(pcfg->pong->buffer_addr);
|
||||
pcfg->pong->buffer_addr = NULL;
|
||||
free(pBuf);
|
||||
pBuf = NULL;
|
||||
free(pcfg->pong);
|
||||
pcfg->pong = NULL;
|
||||
free(pcfg->ping);
|
||||
pcfg->ping = NULL;
|
||||
free(pcfg);
|
||||
pcfg = NULL;
|
||||
return NULL;
|
||||
}
|
||||
pcfg->len = bufLen; // Buffer length
|
||||
dma_show_queue(pcfg);
|
||||
return pcfg;
|
||||
}
|
||||
static esp_err_t dma_queue_reset(int32_t que_size, dma_element_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// No need reset;
|
||||
if (0 == obj->backup_queue.next_link_ptr) {
|
||||
return ESP_OK;
|
||||
}
|
||||
dma_queue_t *dmaQueCur = obj->first_queue;
|
||||
dma_queue_t *dmaQueNext = NULL;
|
||||
if (que_size > 1) {
|
||||
while (dmaQueNext != obj->first_queue) {
|
||||
dmaQueNext = (dma_queue_t*)dmaQueCur->next_link_ptr;
|
||||
if ((dma_queue_t*)obj->backup_queue.next_link_ptr == dmaQueNext) {
|
||||
DMA_INFO("find next_link_ptr=%x \r\n", dmaQueNext);
|
||||
break;
|
||||
}
|
||||
dmaQueCur = dmaQueNext;
|
||||
}
|
||||
}
|
||||
memcpy(dmaQueCur, &obj->backup_queue, sizeof(obj->backup_queue));
|
||||
memset(&obj->backup_queue, 0, sizeof(obj->backup_queue));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the dma buffer length.
|
||||
*
|
||||
*/
|
||||
esp_err_t dma_buf_len_reset(ping_pong_buf_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
dma_queue_t *dmaQueCur = obj->ping->first_queue;
|
||||
dma_queue_t *dmaQueNext = NULL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
DMA_INFO("next_link_ptr=%x lenght=%d\r\n", obj->ping->backup_queue.next_link_ptr, obj->ping->first_queue->data_length);
|
||||
|
||||
obj->ping->first_queue->owner = 1;
|
||||
obj->ping->last_queue->owner = 1;
|
||||
obj->pong->first_queue->owner = 1;
|
||||
obj->pong->last_queue->owner = 1;
|
||||
|
||||
obj->pong->first_queue->data_length = 32;
|
||||
obj->pong->last_queue->data_length = 32;
|
||||
obj->ping->first_queue->data_length = 32;
|
||||
obj->ping->last_queue->data_length = 32;
|
||||
|
||||
ret = dma_queue_reset(obj->queue_cnt, obj->ping);
|
||||
ret += dma_queue_reset(obj->queue_cnt, obj->pong);
|
||||
|
||||
//dma_show_queue(obj);
|
||||
DMA_INFO("[%s # %u lenght=%d]\r\n",__FUNCTION__,__LINE__, obj->ping->first_queue->data_length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the buffer length before the start.
|
||||
*
|
||||
*/
|
||||
esp_err_t dma_buf_len_set(ping_pong_buf_t *obj, dma_element_t *element, uint32_t len)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (len < obj->len) {
|
||||
int i, k, cnt;
|
||||
i = len / QUEUE_BLOCK_LENGTH;
|
||||
k = len % QUEUE_BLOCK_LENGTH;
|
||||
if (0 == k) {
|
||||
cnt = i;
|
||||
} else {
|
||||
cnt = i + 1;
|
||||
}
|
||||
dma_queue_t *dmaQueCur = element->first_queue;
|
||||
dma_queue_t *dmaQueNext = NULL;
|
||||
while (--cnt) {
|
||||
dmaQueNext = (dma_queue_t*)dmaQueCur->next_link_ptr;
|
||||
dmaQueCur = dmaQueNext;
|
||||
}
|
||||
memcpy(&element->backup_queue, (dma_queue_t*)dmaQueCur, sizeof(element->backup_queue));
|
||||
|
||||
dmaQueCur->next_link_ptr = 0;
|
||||
dmaQueCur->data_length = k;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the ping-pong buffer instance.
|
||||
*
|
||||
*/
|
||||
void dma_buf_destroy(ping_pong_buf_t *obj)
|
||||
{
|
||||
ping_pong_buf_t *temp = obj;
|
||||
dma_show_queue(temp);
|
||||
if (NULL != temp) {
|
||||
// Free the link list
|
||||
uint32_t i = 0;
|
||||
dma_queue_t *curtCfg = temp->ping->first_queue;
|
||||
dma_queue_t *nextCfg = NULL;
|
||||
for (i = 0; i < temp->queue_cnt; ++i) {
|
||||
nextCfg = (dma_queue_t*)curtCfg->next_link_ptr;
|
||||
free(curtCfg);
|
||||
curtCfg = NULL;
|
||||
curtCfg = nextCfg;
|
||||
}
|
||||
curtCfg = temp->pong->first_queue;
|
||||
nextCfg = NULL;
|
||||
for (i = 0; i < temp->queue_cnt; ++i) {
|
||||
nextCfg = (dma_queue_t*)curtCfg->next_link_ptr;
|
||||
free(curtCfg);
|
||||
curtCfg = NULL;
|
||||
curtCfg = nextCfg;
|
||||
}
|
||||
// Free the buffer
|
||||
free(temp->ping->buffer_addr);
|
||||
temp->ping->buffer_addr = NULL;
|
||||
free(temp->ping);
|
||||
temp->ping = NULL;
|
||||
free(temp->pong);
|
||||
temp->pong = NULL;
|
||||
free(temp);
|
||||
temp = NULL;
|
||||
}
|
||||
}
|
|
@ -1,350 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#include "rom/ets_sys.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "i2c_soft.h"
|
||||
|
||||
static uint8_t m_nLastSDA;
|
||||
static uint8_t m_nLastSCL;
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_setDC
|
||||
* Description : Internal used function -
|
||||
* set i2c SDA and SCL bit value for half clk cycle
|
||||
* Parameters : uint8_t SDA
|
||||
* uint8_t SCL
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
static void i2c_master_setDC(uint8_t SDA, uint8_t SCL)
|
||||
{
|
||||
SDA &= 0x01;
|
||||
SCL &= 0x01;
|
||||
m_nLastSDA = SDA;
|
||||
m_nLastSCL = SCL;
|
||||
//ETS_INTR_LOCK();
|
||||
if ((0 == SDA) && (0 == SCL)) {
|
||||
I2C_MASTER_SDA_LOW_SCL_LOW();
|
||||
} else if ((0 == SDA) && (1 == SCL)) {
|
||||
I2C_MASTER_SDA_LOW_SCL_HIGH();
|
||||
} else if ((1 == SDA) && (0 == SCL)) {
|
||||
I2C_MASTER_SDA_HIGH_SCL_LOW();
|
||||
} else {
|
||||
I2C_MASTER_SDA_HIGH_SCL_HIGH();
|
||||
}
|
||||
//ETS_INTR_UNLOCK();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_getDC
|
||||
* Description : Internal used function -
|
||||
* get i2c SDA bit value
|
||||
* Parameters : NONE
|
||||
* Returns : uint8_t - SDA bit value
|
||||
*******************************************************************************/
|
||||
static uint8_t i2c_master_getDC(void)
|
||||
{
|
||||
uint8_t sda_out;
|
||||
//ETS_INTR_LOCK();
|
||||
//sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
|
||||
sda_out = gpio_get_level(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
|
||||
//ETS_INTR_UNLOCK();
|
||||
return sda_out;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_init
|
||||
* Description : initilize I2C bus to enable i2c operations
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_init(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5);
|
||||
|
||||
// when SCL = 0, toggle SDA to clear up
|
||||
i2c_master_setDC(0, 0) ;
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(1, 0) ;
|
||||
i2c_master_wait(5);
|
||||
|
||||
// set data_cnt to max value
|
||||
for (i = 0; i < 28; i++) {
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5); // sda 1, scl 0
|
||||
i2c_master_setDC(1, 1);
|
||||
i2c_master_wait(5); // sda 1, scl 1
|
||||
}
|
||||
|
||||
// reset all
|
||||
i2c_master_stop();
|
||||
//return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_gpio_init
|
||||
* Description : config SDA and SCL gpio to open-drain output mode,
|
||||
* mux and gpio num defined in i2c_master.h
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_gpio_init(void)
|
||||
{
|
||||
|
||||
gpio_config_t io_config;
|
||||
io_config.pin_bit_mask= (I2C_MASTER_SDA_PIN) | (I2C_MASTER_SCL_PIN);
|
||||
io_config.mode= GPIO_MODE_INPUT_OUTPUT_OD;
|
||||
io_config.pull_up_en= GPIO_PULLUP_ENABLE;
|
||||
io_config.pull_down_en= GPIO_PULLDOWN_DISABLE;
|
||||
io_config.intr_type = GPIO_PIN_INTR_DISABLE;
|
||||
|
||||
gpio_config(&io_config);
|
||||
#if 0
|
||||
io_config.gpio_intry_type_sel = GPIO_PIN_INTR_DISABLE;
|
||||
io_config.gpio_mode_sel = GPIO_MODE_OUTPUT_OD;
|
||||
io_config.gpio_pin_sel = I2C_MASTER_SCL_PIN;
|
||||
io_config.gpio_pulldown_sel = GPIO_PULLDOWN_DISABLE;
|
||||
io_config.gpio_pullup_sel = GPIO_PULLUP_ENABLE;
|
||||
|
||||
gpio_config(&io_config);
|
||||
#endif
|
||||
#if 0
|
||||
ETS_INTR_UNLOCK();
|
||||
// Set to GPIO function
|
||||
PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC);
|
||||
PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC);
|
||||
// Enable input
|
||||
SET_PERI_REG_MASK(I2C_MASTER_SDA_MUX, FUN_IE);
|
||||
|
||||
GPIO_REG_WRITE(GPIO_PIN_ADDR(I2C_MASTER_SDA_GPIO),
|
||||
GPIO_REG_READ(GPIO_PIN_ADDR(I2C_MASTER_SDA_GPIO)) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
|
||||
GPIO_REG_WRITE(GPIO_ENABLE, GPIO_REG_READ(GPIO_ENABLE) | (1 << I2C_MASTER_SDA_GPIO));
|
||||
|
||||
GPIO_REG_WRITE(GPIO_PIN_ADDR(I2C_MASTER_SCL_GPIO),
|
||||
GPIO_PIN_ADDR(I2C_MASTER_SCL_GPIO) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
|
||||
GPIO_REG_WRITE(GPIO_ENABLE, GPIO_REG_READ(GPIO_ENABLE) | (1 << I2C_MASTER_SCL_GPIO));
|
||||
I2C_MASTER_SDA_HIGH_SCL_HIGH();
|
||||
PIN_PULLUP_EN(I2C_MASTER_SDA_MUX);
|
||||
PIN_PULLUP_EN(I2C_MASTER_SCL_MUX);
|
||||
ETS_INTR_UNLOCK();
|
||||
#endif
|
||||
|
||||
i2c_master_init();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_start
|
||||
* Description : set i2c to send state
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_start(void)
|
||||
{
|
||||
// ETS_INTR_UNLOCK();
|
||||
i2c_master_setDC(1, m_nLastSCL);
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(1, 1);
|
||||
i2c_master_wait(5); // sda 1, scl 1
|
||||
i2c_master_setDC(0, 1);
|
||||
i2c_master_wait(5); // sda 0, scl 1
|
||||
// ETS_INTR_UNLOCK();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_stop
|
||||
* Description : set i2c to stop sending state
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_stop(void)
|
||||
{
|
||||
// ETS_INTR_UNLOCK();
|
||||
i2c_master_wait(5);
|
||||
|
||||
i2c_master_setDC(0, m_nLastSCL);
|
||||
i2c_master_wait(5); // sda 0
|
||||
i2c_master_setDC(0, 1);
|
||||
i2c_master_wait(5); // sda 0, scl 1
|
||||
i2c_master_setDC(1, 1);
|
||||
i2c_master_wait(5); // sda 1, scl 1
|
||||
// ETS_INTR_UNLOCK();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_setAck
|
||||
* Description : set ack to i2c bus as level value
|
||||
* Parameters : uint8_t level - 0 or 1
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_setAck(uint8_t level)
|
||||
{
|
||||
// ETS_INTR_UNLOCK();
|
||||
|
||||
i2c_master_setDC(m_nLastSDA, 0);
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(level, 0);
|
||||
i2c_master_wait(5); // sda level, scl 0
|
||||
i2c_master_setDC(level, 1);
|
||||
i2c_master_wait(8); // sda level, scl 1
|
||||
i2c_master_setDC(level, 0);
|
||||
i2c_master_wait(5); // sda level, scl 0
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5);
|
||||
// ETS_INTR_UNLOCK();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_getAck
|
||||
* Description : confirm if peer send ack
|
||||
* Parameters : NONE
|
||||
* Returns : uint8_t - ack value, 0 or 1
|
||||
*******************************************************************************/
|
||||
uint8_t i2c_master_getAck(void)
|
||||
{
|
||||
uint8_t retVal;
|
||||
// ETS_INTR_UNLOCK();
|
||||
i2c_master_setDC(m_nLastSDA, 0);
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(1, 1);
|
||||
i2c_master_wait(5);
|
||||
|
||||
retVal = i2c_master_getDC();
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5);
|
||||
// ETS_INTR_UNLOCK();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_checkAck
|
||||
* Description : get dev response
|
||||
* Parameters : NONE
|
||||
* Returns : true : get ack ; false : get nack
|
||||
*******************************************************************************/
|
||||
bool i2c_master_checkAck(void)
|
||||
{
|
||||
if(i2c_master_getAck()){
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_send_ack
|
||||
* Description : response ack
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_send_ack(void)
|
||||
{
|
||||
i2c_master_setAck(0x0);
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_send_nack
|
||||
* Description : response nack
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_send_nack(void)
|
||||
{
|
||||
i2c_master_setAck(0x1);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_readByte
|
||||
* Description : read Byte from i2c bus
|
||||
* Parameters : NONE
|
||||
* Returns : uint8_t - readed value
|
||||
*******************************************************************************/
|
||||
uint8_t i2c_master_readByte(void)
|
||||
{
|
||||
uint8_t retVal = 0;
|
||||
uint8_t k, i;
|
||||
// ETS_INTR_UNLOCK();
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(m_nLastSDA, 0);
|
||||
i2c_master_wait(5); // sda 1, scl 0
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5); // sda 1, scl 0
|
||||
i2c_master_setDC(1, 1);
|
||||
i2c_master_wait(5); // sda 1, scl 1
|
||||
|
||||
k = i2c_master_getDC();
|
||||
i2c_master_wait(5);
|
||||
|
||||
if (i == 7) {
|
||||
i2c_master_wait(3); ////
|
||||
}
|
||||
|
||||
k <<= (7 - i);
|
||||
retVal |= k;
|
||||
}
|
||||
|
||||
i2c_master_setDC(1, 0);
|
||||
i2c_master_wait(5); // sda 1, scl 0
|
||||
// ETS_INTR_UNLOCK();
|
||||
return retVal;
|
||||
}
|
||||
#define DBG_TONY ets_printf
|
||||
/******************************************************************************
|
||||
* FunctionName : i2c_master_writeByte
|
||||
* Description : write wrdata value(one byte) into i2c
|
||||
* Parameters : uint8_t wrdata - write value
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void i2c_master_writeByte(uint8_t wrdata)
|
||||
{
|
||||
uint8_t dat;
|
||||
int8_t i;
|
||||
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(m_nLastSDA, 0);
|
||||
i2c_master_wait(5);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
dat = wrdata >> i;
|
||||
i2c_master_setDC(dat, 0);
|
||||
i2c_master_wait(5);
|
||||
i2c_master_setDC(dat, 1);
|
||||
i2c_master_wait(5);
|
||||
|
||||
if (i == 0) {
|
||||
i2c_master_wait(3); ////
|
||||
}
|
||||
|
||||
i2c_master_setDC(dat, 0);
|
||||
i2c_master_wait(5);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,615 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "i2s.h"
|
||||
#include <string.h>
|
||||
#include "rom/ets_sys.h"
|
||||
#include "esp_intr.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "stdio.h"
|
||||
|
||||
|
||||
#define I2S_BASE_CLK (80000000L)
|
||||
#define ABS(x) (((x)>0)?(x):(-(x)))
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the interrupt function.
|
||||
*
|
||||
*/
|
||||
static void i2s_intr_func_set(void * isr, i2s_num_t i2sNum)
|
||||
{
|
||||
if (I2S_NUM_I2S0 == i2sNum) {
|
||||
intr_matrix_set(0, ETS_I2S0_INTR_SOURCE, ETS_I2S0_INUM);
|
||||
ESP_I2S0_INTR_ATTACH(isr, NULL);
|
||||
// enable intr in cpu
|
||||
ESP_I2S0_INTR_ENABLE();
|
||||
} else if (I2S_NUM_I2S1 == i2sNum) {
|
||||
intr_matrix_set(0, ETS_I2S1_INTR_SOURCE, ETS_I2S1_INUM);
|
||||
ESP_I2S1_INTR_ATTACH(isr, NULL);
|
||||
// enable intr in cpu
|
||||
ESP_I2S1_INTR_ENABLE();
|
||||
} else {
|
||||
// To do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S ping buffer address.
|
||||
*
|
||||
*/
|
||||
uint32_t* i2s_dma_ping_buf_get(i2s_dma_attr_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return NULL;
|
||||
}
|
||||
return obj->buf->ping->buffer_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2S pong buffer address.
|
||||
*
|
||||
*/
|
||||
uint32_t* i2s_dma_pong_buf_get(i2s_dma_attr_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return NULL;
|
||||
}
|
||||
return obj->buf->pong->buffer_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get not working ping-pong buffer address.
|
||||
*
|
||||
*/
|
||||
uint32_t* i2s_dma_status_get(i2s_num_t i2sNum, i2s_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (i2sNum > I2S_NUM_MAX)) {
|
||||
return NULL;
|
||||
}
|
||||
if ((I2S_MODE_MASTER_RX == obj->mode)
|
||||
|| (I2S_MODE_SLAVE_RX == obj->mode)) {
|
||||
// Data stream receive
|
||||
if (READ_PERI_REG(I2S_IN_EOF_DES_ADDR_REG(i2sNum)) == ((uint32_t)obj->buf->ping->last_queue)) {
|
||||
return obj->buf->ping->buffer_addr;
|
||||
} else if (READ_PERI_REG(I2S_IN_EOF_DES_ADDR_REG(i2sNum)) == ((uint32_t)obj->buf->pong->last_queue)) {
|
||||
return obj->buf->pong->buffer_addr;
|
||||
}
|
||||
} else if ((I2S_MODE_MASTER_TX == obj->mode)
|
||||
|| (I2S_MODE_SLAVE_TX == obj->mode)) {
|
||||
// Data stream send
|
||||
if (READ_PERI_REG(I2S_OUT_EOF_DES_ADDR_REG(i2sNum)) == ((uint32_t)obj->buf->ping->last_queue)) {
|
||||
return obj->buf->ping->buffer_addr;
|
||||
} else if (READ_PERI_REG(I2S_OUT_EOF_DES_ADDR_REG(i2sNum)) == ((uint32_t)obj->buf->pong->last_queue)) {
|
||||
return obj->buf->pong->buffer_addr;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Ping-Pong buffer to the destination
|
||||
*
|
||||
*/
|
||||
void i2s_dma_dest_add_set(i2s_num_t i2sNum, i2s_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (i2sNum > I2S_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
if ((I2S_MODE_MASTER_RX == obj->mode)
|
||||
|| (I2S_MODE_SLAVE_RX == obj->mode)) {
|
||||
SET_PERI_REG_BITS(I2S_IN_LINK_REG(i2sNum), I2S_INLINK_ADDR, ((uint32_t)(obj->buf->ping->first_queue)), I2S_INLINK_ADDR_S);
|
||||
} else if ((I2S_MODE_MASTER_TX == obj->mode)
|
||||
|| (I2S_MODE_SLAVE_TX == obj->mode)) {
|
||||
SET_PERI_REG_BITS(I2S_OUT_LINK_REG(i2sNum), I2S_OUTLINK_ADDR, ((uint32_t)(obj->buf->ping->first_queue)), I2S_OUTLINK_ADDR_S);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA and create a I2S DMA instance
|
||||
*
|
||||
*/
|
||||
int i2s_dma_init(i2s_num_t i2sNum, i2s_dma_attr_t *obj, void *isr)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (i2sNum > I2S_NUM_MAX)) {
|
||||
return -1;
|
||||
}
|
||||
obj->buf = dma_buf_create(obj->buf_size);
|
||||
if (NULL == obj->buf) {
|
||||
return -2;
|
||||
}
|
||||
if ((I2S_MODE_MASTER_TX == obj->mode)
|
||||
|| (I2S_MODE_SLAVE_TX == obj->mode)) {
|
||||
//Reset DMA
|
||||
SET_PERI_REG_MASK(I2S_LC_CONF_REG(i2sNum), I2S_OUT_RST);
|
||||
CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(i2sNum), I2S_OUT_RST);
|
||||
// enable send intr
|
||||
i2s_int_enable(i2sNum, I2S_INT_SRC_ONE_BUF_SEND_DONE);
|
||||
} else if ((I2S_MODE_MASTER_RX == obj->mode)
|
||||
|| (I2S_MODE_SLAVE_RX == obj->mode)) {
|
||||
//Reset DMA
|
||||
SET_PERI_REG_MASK(I2S_LC_CONF_REG(i2sNum), I2S_IN_RST);
|
||||
CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(i2sNum), I2S_IN_RST);
|
||||
SET_PERI_REG_BITS(I2S_RXEOF_NUM_REG(i2sNum), I2S_RX_EOF_NUM, (obj->buf_size / 4), I2S_RX_EOF_NUM_S);
|
||||
// enable receive intr
|
||||
i2s_int_enable(i2sNum, I2S_INT_SRC_ONE_BUF_RECV_DONE /*| I2sIntSrc_RxHalfFull |I2sIntSrc_RxFull*/);
|
||||
}
|
||||
|
||||
//Enable and configure DMA
|
||||
SET_PERI_REG_MASK(I2S_LC_CONF_REG(i2sNum), I2S_CHECK_OWNER | I2S_OUT_EOF_MODE |
|
||||
I2S_OUT_LOOP_TEST | I2S_IN_LOOP_TEST);
|
||||
i2s_intr_func_set(isr, i2sNum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the I2S DMA instance
|
||||
*
|
||||
*/
|
||||
esp_err_t i2s_dma_uninit(i2s_dma_attr_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
dma_buf_destroy(obj->buf);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the I2S DMA work mode.
|
||||
*
|
||||
*/
|
||||
void i2s_dma_enable(i2s_num_t i2sNum, i2s_mode_t mode)
|
||||
{
|
||||
if (i2sNum > I2S_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
if ((I2S_MODE_MASTER_RX == mode)
|
||||
|| (I2S_MODE_SLAVE_RX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_IN_LINK_REG(i2sNum), I2S_INLINK_START);
|
||||
} else if ((I2S_MODE_MASTER_TX == mode)
|
||||
|| (I2S_MODE_SLAVE_TX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(i2sNum), I2S_OUTLINK_START);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the I2S DMA work mode.
|
||||
*
|
||||
*/
|
||||
void i2s_dma_disable(i2s_num_t i2sNum, i2s_mode_t mode)
|
||||
{
|
||||
if (i2sNum > I2S_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
if ((I2S_MODE_MASTER_RX == mode)
|
||||
|| (I2S_MODE_SLAVE_RX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_IN_LINK_REG(i2sNum), I2S_INLINK_STOP);
|
||||
} else if ((I2S_MODE_MASTER_TX == mode)
|
||||
|| (I2S_MODE_SLAVE_TX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(i2sNum), I2S_OUTLINK_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the I2S sample rate, in HZ
|
||||
*
|
||||
*/
|
||||
void i2s_clk_set(int rate, int bits)
|
||||
{
|
||||
uint32_t i2sNum = 0 ;
|
||||
int bckdiv, factor = 32;
|
||||
int clkmInteger, clkmDecimals;
|
||||
float denom = (float)1 / 16;
|
||||
// BCLK = Fs * bits * 2;
|
||||
// MCLK = factor * BCLK; m = 2;
|
||||
// clkm = 160MHz / MCLK;
|
||||
ets_printf("rate=%d, bits=%d \r\n", rate, bits);
|
||||
float clkmdiv = (float)I2S_BASE_CLK / (rate * factor * bits * 2);
|
||||
ets_printf("clkmdiv=%f\r\n", clkmdiv);
|
||||
if (clkmdiv > 256) {
|
||||
factor++;
|
||||
clkmdiv = (float)I2S_BASE_CLK / (rate * factor * bits * 2);
|
||||
}
|
||||
ets_printf("clkmdiv=%f\r\n", clkmdiv);
|
||||
clkmInteger = clkmdiv;
|
||||
ets_printf("clkmInteger=%d\r\n", clkmInteger);
|
||||
clkmDecimals = (clkmdiv - clkmInteger) / denom;
|
||||
ets_printf("clkmDecimals=%d\r\n", clkmDecimals);
|
||||
float mclk = clkmInteger + denom * clkmDecimals;
|
||||
ets_printf("MCLK=%f\r\n", (float)I2S_BASE_CLK / mclk);
|
||||
rtc_plla_ena(1,10,2);
|
||||
#if 0
|
||||
CLEAR_PERI_REG_MASK(I2S_CLKM_CONF_REG, (I2S_CLKM_DIV_NUM_M
|
||||
| I2S_CLKM_DIV_A_M
|
||||
| I2S_CLKM_DIV_B_M));
|
||||
SET_PERI_REG_MASK(I2S_CLKM_CONF_REG, I2S_CLK_EN | ((0 & I2S_CLKM_DIV_A_V) << I2S_CLKM_DIV_A_S)
|
||||
| ((0) << I2S_CLKM_DIV_B_S) | (20 & I2S_CLKM_DIV_NUM_V));
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_SAMPLE_RATE_CONF_REG, I2S_RX_BCK_DIV_NUM_M | I2S_TX_BCK_DIV_NUM_M);
|
||||
SET_PERI_REG_MASK(I2S_SAMPLE_RATE_CONF_REG, ((4 & I2S_RX_BCK_DIV_NUM_V) << I2S_RX_BCK_DIV_NUM_S)
|
||||
| ((4 & I2S_TX_BCK_DIV_NUM_V) << I2S_TX_BCK_DIV_NUM_S));
|
||||
|
||||
#else
|
||||
#if 0 // Fs= 48kHz
|
||||
CLEAR_PERI_REG_MASK(I2S_CLKM_CONF_REG, (I2S_CLKM_DIV_NUM_M
|
||||
| I2S_CLKM_DIV_A_M
|
||||
| I2S_CLKM_DIV_B_M));
|
||||
I2S_SET_CLKA_ENA(1);
|
||||
I2S_SET_CLKM_DIV_A(63);
|
||||
I2S_SET_CLKM_DIV_B(32);
|
||||
I2S_SET_CLKM_DIV_NUM(6);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_SAMPLE_RATE_CONF_REG, I2S_RX_BCK_DIV_NUM_M | I2S_TX_BCK_DIV_NUM_M);
|
||||
I2S_SET_RX_BCK_DIV_NUM(4);
|
||||
I2S_SET_TX_BCK_DIV_NUM(2);
|
||||
I2S_SET_TX_PDM_FS(480);
|
||||
#else
|
||||
// Fs = 44.1kHz
|
||||
CLEAR_PERI_REG_MASK(I2S_CLKM_CONF_REG(i2sNum), (I2S_CLKM_DIV_NUM_M | I2S_CLKM_DIV_A_M | I2S_CLKM_DIV_B_M));
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(i2sNum), I2S_CLKM_DIV_A_V, 64, I2S_CLKM_DIV_A_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(i2sNum), I2S_CLKM_DIV_B_V,8, I2S_CLKM_DIV_B_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(i2sNum), I2S_CLKM_DIV_NUM_V, 78, I2S_CLKM_DIV_NUM_S);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_SAMPLE_RATE_CONF_REG(i2sNum), I2S_RX_BCK_DIV_NUM_M | I2S_TX_BCK_DIV_NUM_M);
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(i2sNum), I2S_RX_BCK_DIV_NUM_V, 4, I2S_RX_BCK_DIV_NUM_S);
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(i2sNum), I2S_TX_BCK_DIV_NUM_V, 2, I2S_TX_BCK_DIV_NUM_S);
|
||||
SET_PERI_REG_BITS(I2S_PDM_FREQ_CONF_REG(i2sNum), I2S_TX_PDM_FS_V, 441, I2S_TX_PDM_FS_S);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
CLEAR_PERI_REG_MASK(0x60009000, (0xf));
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), 0x0f);
|
||||
|
||||
|
||||
#if 0 // Fs= 48kHz
|
||||
CLEAR_PERI_REG_MASK(I2S_CLKM_CONF_REG, (I2S_CLKM_DIV_NUM_M
|
||||
|I2S_CLKM_DIV_A_M
|
||||
|I2S_CLKM_DIV_B_M));
|
||||
I2S_SET_CLKA_ENA(1);
|
||||
I2S_SET_CLKM_DIV_A(63);
|
||||
I2S_SET_CLKM_DIV_B(32);
|
||||
I2S_SET_CLKM_DIV_NUM(6);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_SAMPLE_RATE_CONF_REG, I2S_RX_BCK_DIV_NUM_M |I2S_TX_BCK_DIV_NUM_M);
|
||||
I2S_SET_RX_BCK_DIV_NUM(4);
|
||||
I2S_SET_TX_BCK_DIV_NUM(2);
|
||||
I2S_SET_TX_PDM_FS(480);
|
||||
#else
|
||||
// Fs = 44.1kHz
|
||||
CLEAR_PERI_REG_MASK(I2S_CLKM_CONF_REG(i2sNum), (I2S_CLKM_DIV_NUM_M
|
||||
|I2S_CLKM_DIV_A_M
|
||||
|I2S_CLKM_DIV_B_M));
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(i2sNum),I2S_CLKM_DIV_A_V,64,I2S_CLKM_DIV_A_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(i2sNum),I2S_CLKM_DIV_B_V,8,I2S_CLKM_DIV_B_S);
|
||||
SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(i2sNum),I2S_CLKM_DIV_NUM_V,78,I2S_CLKM_DIV_NUM_S);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_SAMPLE_RATE_CONF_REG(i2sNum), I2S_RX_BCK_DIV_NUM_M |I2S_TX_BCK_DIV_NUM_M);
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(i2sNum),I2S_RX_BCK_DIV_NUM_V,4,I2S_RX_BCK_DIV_NUM_S);
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(i2sNum),I2S_TX_BCK_DIV_NUM_V,8,I2S_TX_BCK_DIV_NUM_S);
|
||||
SET_PERI_REG_BITS(I2S_PDM_FREQ_CONF_REG(i2sNum),I2S_TX_PDM_FS_V,441,I2S_TX_PDM_FS_S);
|
||||
|
||||
#endif
|
||||
CLEAR_PERI_REG_MASK(0x60009000,(0xf));
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum),0x0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2s with a given module.
|
||||
*
|
||||
*/
|
||||
void i2s_reset(i2s_num_t i2sNum)
|
||||
{
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_RESET_M);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_RESET_M);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_FIFO_RESET_M);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_FIFO_RESET_M);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_RESET_M);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_RESET_M);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_FIFO_RESET_M);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_FIFO_RESET_M);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the I2S module
|
||||
*
|
||||
*/
|
||||
void i2s_init(i2s_num_t i2sNum, i2s_attr_t *pAttr)
|
||||
{
|
||||
if ((i2sNum > I2S_NUM_MAX)
|
||||
|| (NULL == pAttr)) {
|
||||
return ;
|
||||
}
|
||||
if (i2sNum == I2S_NUM_I2S0) {
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
} else if (i2sNum == I2S_NUM_I2S1) {
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
|
||||
}
|
||||
|
||||
// configure I2S data port interface.
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(i2sNum), I2S_LCD_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_PCM2PDM_CONV_EN | I2S_PDM2PCM_CONV_EN);
|
||||
SET_PERI_REG_BITS(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, 0x1, RTC_CNTL_SOC_CLK_SEL_S);
|
||||
|
||||
if (0 != pAttr->rx_mode.mode) {
|
||||
if (I2S_IFACE_TYPE_DMA == pAttr->rx_mode.iface) {
|
||||
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(i2sNum), I2S_DSCR_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(I2S_FIFO_CONF_REG(i2sNum), I2S_DSCR_EN);
|
||||
}
|
||||
// Working mode
|
||||
if (I2S_MODE_MASTER_RX == pAttr->rx_mode.mode) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_SLAVE_MOD);
|
||||
// configure I2S communication standard format
|
||||
i2s_clk_set(pAttr->rx_mode.rate, pAttr->rx_mode.bits);
|
||||
} else if (I2S_MODE_SLAVE_RX == pAttr->rx_mode.mode) {
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_SLAVE_MOD);
|
||||
} else {
|
||||
// To do nothing.
|
||||
}
|
||||
// configure I2S communication standard format
|
||||
if (I2S_STD_FORMAT_I2S == pAttr->rx_mode.std) {
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_MSB_SHIFT);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF1_REG(i2sNum), I2S_RX_SHORT_SYNC);
|
||||
} else if (I2S_STD_FORMAT_MSB == pAttr->rx_mode.std) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_MSB_SHIFT);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_SHORT_SYNC);
|
||||
} else if (I2S_STD_FORMAT_LSB == pAttr->rx_mode.std) {
|
||||
|
||||
} else if (I2S_STD_FORMAT_PCM_SHORT == pAttr->rx_mode.std) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_MSB_SHIFT);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_SHORT_SYNC);
|
||||
} else if (I2S_STD_FORMAT_PCM_LONG == pAttr->rx_mode.std) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_MSB_SHIFT);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_SHORT_SYNC);
|
||||
} else {
|
||||
// To do nothing.
|
||||
}
|
||||
// configure bit width format.
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(i2sNum), I2S_RX_BITS_MOD, pAttr->rx_mode.bits, I2S_RX_BITS_MOD_S);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(i2sNum), I2S_RX_FIFO_MOD_FORCE_EN);
|
||||
// setting channel mode.
|
||||
if (I2S_CHANNEL_FMT_RIGHT_LEFT == pAttr->rx_mode.channel) {
|
||||
// set rx,tx channel mode, both are "two channel" here
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_RX_FIFO_MOD_V, 0, I2S_RX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_RX_CHAN_MOD, I2S_CHANNEL_FMT_RIGHT_LEFT, I2S_RX_CHAN_MOD_S);// 0-two channel;1-right;2-left
|
||||
} else if (I2S_CHANNEL_FMT_ALL_RIGHT == pAttr->rx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_RX_FIFO_MOD_V, 0, I2S_RX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_RX_CHAN_MOD, I2S_CHANNEL_FMT_ALL_RIGHT, I2S_RX_CHAN_MOD_S);
|
||||
} else if (I2S_CHANNEL_FMT_ALL_LEFT == pAttr->rx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_RX_FIFO_MOD_V, 0, I2S_RX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_RX_CHAN_MOD, I2S_CHANNEL_FMT_ALL_LEFT, I2S_RX_CHAN_MOD_S);
|
||||
} else if (I2S_CHANNEL_FMT_ONLY_RIGHT == pAttr->rx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_RX_FIFO_MOD_V, 1, I2S_RX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_RX_CHAN_MOD, 1, I2S_RX_CHAN_MOD_S);
|
||||
} else if (I2S_CHANNEL_FMT_ONLY_LEFT == pAttr->rx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_RX_FIFO_MOD_V, 1, I2S_RX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_RX_CHAN_MOD, 2, I2S_RX_CHAN_MOD_S);
|
||||
} else {
|
||||
// To do nothing.
|
||||
}
|
||||
|
||||
if (I2S_MODULE_WORK_TYPE_PDM == pAttr->rx_mode.type) {
|
||||
if (PDM_SAMPLE_RATE_RATIO_64 == pAttr->rx_mode.ratio) {
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_RX_PDM_SINC_DSR_16_EN); // Clear:64*fs;set:128*fs
|
||||
} else if (PDM_SAMPLE_RATE_RATIO_128 == pAttr->rx_mode.ratio) {
|
||||
SET_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_RX_PDM_SINC_DSR_16_EN); // Clear:64*fs;set:128*fs
|
||||
}
|
||||
if (PDM_PCM_CONV_ENABLE == pAttr->rx_mode.conv) {
|
||||
SET_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_PDM2PCM_CONV_EN);
|
||||
} else if (PDM_PCM_CONV_DISABLE == pAttr->rx_mode.conv) {
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_PDM2PCM_CONV_EN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != pAttr->tx_mode.mode) {
|
||||
if (I2S_IFACE_TYPE_DMA == pAttr->tx_mode.iface) {
|
||||
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(i2sNum), I2S_DSCR_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(I2S_FIFO_CONF_REG(i2sNum), I2S_DSCR_EN);
|
||||
}
|
||||
|
||||
if (I2S_MODE_MASTER_TX == pAttr->tx_mode.mode) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_SLAVE_MOD);
|
||||
// configure I2S communication standard format
|
||||
i2s_clk_set(pAttr->tx_mode.rate, pAttr->tx_mode.bits);
|
||||
// rtc_plla_ena(1, 621, 14);
|
||||
// SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(i2sNum), I2S_CLKA_ENA);
|
||||
printf("rtc_plla_ena is ok\r\n");
|
||||
} else if (I2S_MODE_SLAVE_RX == pAttr->tx_mode.mode) {
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_SLAVE_MOD);
|
||||
} else {
|
||||
// To do nothing.
|
||||
}
|
||||
// configure I2S communication standard format
|
||||
if (I2S_STD_FORMAT_I2S == pAttr->tx_mode.std) {
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_MSB_SHIFT);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_SHORT_SYNC);
|
||||
} else if (I2S_STD_FORMAT_MSB == pAttr->tx_mode.std) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_MSB_SHIFT);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_SHORT_SYNC);
|
||||
} else if (I2S_STD_FORMAT_LSB == pAttr->tx_mode.std) {
|
||||
|
||||
} else if (I2S_STD_FORMAT_PCM_SHORT == pAttr->tx_mode.std) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_MSB_SHIFT);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_SHORT_SYNC);
|
||||
} else if (I2S_STD_FORMAT_PCM_LONG == pAttr->tx_mode.std) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_MSB_SHIFT);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_SHORT_SYNC);
|
||||
} else {
|
||||
// To do nothing.
|
||||
}
|
||||
// configure bit width format.
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(i2sNum), I2S_TX_BITS_MOD, pAttr->tx_mode.bits, I2S_TX_BITS_MOD_S);
|
||||
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(i2sNum), I2S_TX_FIFO_MOD_FORCE_EN);
|
||||
|
||||
if (I2S_CHANNEL_FMT_RIGHT_LEFT == pAttr->tx_mode.channel) {
|
||||
// set rx,tx channel mode, both are "two channel" here
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_TX_FIFO_MOD_V, 0, I2S_TX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_TX_CHAN_MOD, I2S_CHANNEL_FMT_RIGHT_LEFT, I2S_TX_CHAN_MOD_S);// 0-two channel;1-right;2-left
|
||||
} else if (I2S_CHANNEL_FMT_ALL_RIGHT == pAttr->tx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_TX_FIFO_MOD_V, 0, I2S_TX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_TX_CHAN_MOD, I2S_CHANNEL_FMT_ALL_RIGHT, I2S_TX_CHAN_MOD_S);
|
||||
} else if (I2S_CHANNEL_FMT_ALL_LEFT == pAttr->tx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_TX_FIFO_MOD_V, 0, I2S_TX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_TX_CHAN_MOD, I2S_CHANNEL_FMT_ALL_LEFT, I2S_TX_CHAN_MOD_S);
|
||||
} else if (I2S_CHANNEL_FMT_ONLY_RIGHT == pAttr->tx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_TX_FIFO_MOD_V, 1, I2S_TX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_TX_CHAN_MOD, 1, I2S_TX_CHAN_MOD_S);
|
||||
} else if (I2S_CHANNEL_FMT_ONLY_LEFT == pAttr->tx_mode.channel) {
|
||||
SET_PERI_REG_BITS(I2S_FIFO_CONF_REG(i2sNum), I2S_TX_FIFO_MOD_V, 1, I2S_TX_FIFO_MOD_S); // 0-right&left channel;1-one channel
|
||||
SET_PERI_REG_BITS(I2S_CONF_CHAN_REG(i2sNum), I2S_TX_CHAN_MOD, 2, I2S_TX_CHAN_MOD_S);
|
||||
} else {
|
||||
// To do nothing.
|
||||
}
|
||||
if (I2S_MODULE_WORK_TYPE_PDM == pAttr->tx_mode.type) {
|
||||
if (PDM_SAMPLE_RATE_RATIO_64 == pAttr->tx_mode.ratio) {
|
||||
SET_PERI_REG_BITS(I2S_PDM_CONF_REG(i2sNum), I2S_TX_PDM_SINC_OSR2_M, 1, I2S_TX_PDM_SINC_OSR2_S); // TX: 2---128*fs;1---64*fs
|
||||
} else if (PDM_SAMPLE_RATE_RATIO_128 == pAttr->tx_mode.ratio) {
|
||||
SET_PERI_REG_BITS(I2S_PDM_CONF_REG(i2sNum), I2S_TX_PDM_SINC_OSR2_M, 2, I2S_TX_PDM_SINC_OSR2_S); // TX: 2---128*fs;1---64*fs
|
||||
}
|
||||
if (PDM_PCM_CONV_ENABLE == pAttr->rx_mode.conv) {
|
||||
SET_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_PDM2PCM_CONV_EN);
|
||||
} else if (PDM_PCM_CONV_DISABLE == pAttr->rx_mode.conv) {
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_PDM2PCM_CONV_EN);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clear all of the interrupt sources.
|
||||
WRITE_PERI_REG(I2S_INT_CLR_REG(i2sNum), 0xffffffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the interrupt source.
|
||||
*
|
||||
*/
|
||||
void i2s_int_enable(i2s_num_t i2sNum, i2s_int_src_t intSrc)
|
||||
{
|
||||
SET_PERI_REG_MASK(I2S_INT_ENA_REG(i2sNum), intSrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the interrupt source.
|
||||
*
|
||||
*/
|
||||
void i2s_int_disable(i2s_num_t i2sNum, i2s_int_src_t intSrc)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(I2S_INT_ENA_REG(i2sNum), intSrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the interrupt source.
|
||||
*
|
||||
*/
|
||||
void i2s_int_clear(i2s_num_t i2sNum, i2s_int_src_t intSrc)
|
||||
{
|
||||
SET_PERI_REG_MASK(I2S_INT_CLR_REG(i2sNum), intSrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the I2S interrupt status
|
||||
*/
|
||||
uint32_t i2s_int_status_get(i2s_num_t i2sNum)
|
||||
{
|
||||
return READ_PERI_REG(I2S_INT_ST_REG(i2sNum));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start I2S work
|
||||
*
|
||||
*/
|
||||
void i2s_start(i2s_module_work_type_t type, i2s_num_t i2sNum, i2s_mode_t mode)
|
||||
{
|
||||
if (i2sNum > I2S_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
if (I2S_MODULE_WORK_TYPE_I2S == type) {
|
||||
if ((I2S_MODE_MASTER_RX == mode)
|
||||
|| (I2S_MODE_SLAVE_RX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_START);
|
||||
SET_PERI_REG_MASK(GPIO_ENABLE_REG, BIT(0));
|
||||
} else if ((I2S_MODE_MASTER_TX == mode)
|
||||
|| (I2S_MODE_SLAVE_TX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_START);
|
||||
SET_PERI_REG_MASK(GPIO_ENABLE_REG, BIT(0));
|
||||
}
|
||||
} else if (I2S_MODULE_WORK_TYPE_PDM == type) {
|
||||
if ((I2S_MODE_MASTER_RX == mode)
|
||||
|| (I2S_MODE_SLAVE_RX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_RX_PDM_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_START);
|
||||
} else if ((I2S_MODE_MASTER_TX == mode)
|
||||
|| (I2S_MODE_SLAVE_TX == mode)) {
|
||||
SET_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_TX_PDM_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_START);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop I2S work
|
||||
*
|
||||
*/
|
||||
void i2s_stop(i2s_module_work_type_t type, i2s_num_t i2sNum, i2s_mode_t mode)
|
||||
{
|
||||
if (i2sNum > I2S_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
if (I2S_MODULE_WORK_TYPE_I2S == type) {
|
||||
if ((I2S_MODE_MASTER_RX == mode)
|
||||
|| (I2S_MODE_SLAVE_RX == mode)) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_START);
|
||||
SET_PERI_REG_MASK(GPIO_ENABLE_REG, BIT(0));
|
||||
} else if ((I2S_MODE_MASTER_TX == mode)
|
||||
|| (I2S_MODE_SLAVE_TX == mode)) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_START);
|
||||
}
|
||||
} else if (I2S_MODULE_WORK_TYPE_PDM == type) {
|
||||
if ((I2S_MODE_MASTER_RX == mode)
|
||||
|| (I2S_MODE_SLAVE_RX == mode)) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_RX_START);
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_RX_PDM_EN);
|
||||
} else if ((I2S_MODE_MASTER_TX == mode)
|
||||
|| (I2S_MODE_SLAVE_TX == mode)) {
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(i2sNum), I2S_TX_START);
|
||||
CLEAR_PERI_REG_MASK(I2S_PDM_CONF_REG(i2sNum), I2S_TX_PDM_EN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,827 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "spi.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "esp_intr.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Defines slave commands.Default value based on slave ESP8266 & ESP32.
|
||||
*/
|
||||
#define MASTER_WRITE_DATA_TO_SLAVE_CMD 2
|
||||
#define MASTER_READ_DATA_FROM_SLAVE_CMD 3
|
||||
#define MASTER_WRITE_STATUS_TO_SLAVE_CMD 1
|
||||
#define MASTER_READ_STATUS_FROM_SLAVE_CMD 4
|
||||
|
||||
|
||||
static void spi_intr_func_set(void * isr, spi_num_t spiNum)
|
||||
{
|
||||
if (SPI_NUM_SPI1 == spiNum) {
|
||||
intr_matrix_set(0, ETS_SPI1_DMA_INTR_SOURCE, ETS_SPI1_INUM);
|
||||
ESP_SPI1_INTR_ATTACH(isr, NULL);
|
||||
// enable intr in cpu
|
||||
ESP_SPI1_INTR_ENABLE();
|
||||
} else if (SPI_NUM_SPI2 == spiNum) {
|
||||
intr_matrix_set(0, ETS_SPI2_DMA_INTR_SOURCE, ETS_SPI2_INUM);
|
||||
ESP_SPI2_INTR_ATTACH(isr, NULL);
|
||||
// enable intr in cpu
|
||||
ESP_SPI2_INTR_ENABLE();
|
||||
} else if (SPI_NUM_SPI3 == spiNum) {
|
||||
intr_matrix_set(0, ETS_SPI3_DMA_INTR_SOURCE, ETS_SPI3_INUM);
|
||||
ESP_SPI3_INTR_ATTACH(isr, NULL);
|
||||
// enable intr in cpu
|
||||
ESP_SPI3_INTR_ENABLE();
|
||||
} else {
|
||||
// To do nothing
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
|
||||
/**
|
||||
* @brief Get SPI ping buffer address.
|
||||
*
|
||||
*/
|
||||
uint32_t* spi_dma_ping_buf_get(spi_dma_attr_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return NULL;
|
||||
}
|
||||
return obj->buf->ping->buffer_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get SPI ping buffer address.
|
||||
*
|
||||
*/
|
||||
uint32_t* spi_dma_pong_buf_get(spi_dma_attr_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return NULL;
|
||||
}
|
||||
return obj->buf->pong->buffer_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get without work ping-pong buffer address.
|
||||
*
|
||||
*/
|
||||
uint32_t* spi_dma_status_get(spi_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return NULL;
|
||||
}
|
||||
switch (obj->dir) {
|
||||
case SPI_DMA_DIR_OUT:
|
||||
if (READ_PERI_REG(SPI_OUT_EOF_DES_ADDR_REG(obj->spi_num)) == ((uint32_t)obj->buf->ping->last_queue)) {
|
||||
return obj->buf->ping->buffer_addr;
|
||||
} else if (READ_PERI_REG(SPI_OUT_EOF_DES_ADDR_REG(obj->spi_num)) == ((uint32_t)obj->buf->pong->last_queue)) {
|
||||
return obj->buf->pong->buffer_addr;
|
||||
}
|
||||
break;
|
||||
case SPI_DMA_DIR_IN:
|
||||
if (READ_PERI_REG(SPI_IN_SUC_EOF_DES_ADDR_REG(obj->spi_num)) == ((uint32_t)obj->buf->ping->last_queue)) {
|
||||
return obj->buf->ping->buffer_addr;
|
||||
} else if (READ_PERI_REG(SPI_IN_SUC_EOF_DES_ADDR_REG(obj->spi_num)) == ((uint32_t)obj->buf->pong->last_queue)) {
|
||||
return obj->buf->pong->buffer_addr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
*/
|
||||
void spi_dma_dest_add_set(spi_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
if (SPI_DMA_DIR_IN == obj->dir) {
|
||||
SET_PERI_REG_BITS(SPI_DMA_IN_LINK_REG(obj->spi_num), SPI_INLINK_ADDR, ((uint32_t)(obj->buf->ping->first_queue)), SPI_INLINK_ADDR_S);
|
||||
} else if (SPI_DMA_DIR_OUT == obj->dir) {
|
||||
SET_PERI_REG_BITS(SPI_DMA_OUT_LINK_REG(obj->spi_num), SPI_OUTLINK_ADDR, ((uint32_t)(obj->buf->ping->first_queue)), SPI_OUTLINK_ADDR_S);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset SPI ping buffer address.
|
||||
*
|
||||
*/
|
||||
void spi_dma_rest(spi_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
dma_buf_len_reset(obj->buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA and create a SPI DMA instance.
|
||||
*
|
||||
*/
|
||||
int spi_dma_init(spi_dma_attr_t *obj, void *isr)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return -1;
|
||||
}
|
||||
obj->buf = dma_buf_create(obj->buf_size);
|
||||
if (NULL == obj->buf) {
|
||||
return -2;
|
||||
}
|
||||
// Reset DMA
|
||||
SET_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_OUT_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_OUT_LINK_REG(obj->spi_num), SPI_OUTLINK_START);
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_IN_LINK_REG(obj->spi_num), SPI_INLINK_START);
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_OUT_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST);
|
||||
|
||||
// Select DMA channel.
|
||||
SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, obj->channel, ((obj->spi_num - 1) * 2));
|
||||
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(obj->spi_num), SPI_USR_MOSI);//////add
|
||||
if ((SPI_MODE_MASTER == obj->mode)) {
|
||||
// enable send intr
|
||||
SET_PERI_REG_MASK(SPI_DMA_INT_ENA_REG(obj->spi_num ), SPI_INT_SRC_ONE_BUF_SEND_DONE);
|
||||
SET_PERI_REG_MASK(SPI_DMA_INT_ENA_REG(obj->spi_num ), SPI_INT_SRC_ONE_BUF_RECV_DONE);
|
||||
|
||||
} else if ((SPI_MODE_SLAVE == obj->mode)) {
|
||||
SET_PERI_REG_MASK(SPI_SLV_RDBUF_DLEN_REG(obj->spi_num), ((obj->buf_size << 3) - 1));
|
||||
SET_PERI_REG_MASK(SPI_SLV_WRBUF_DLEN_REG(obj->spi_num), ((obj->buf_size << 3) - 1));
|
||||
// enable receive intr
|
||||
SET_PERI_REG_MASK(SPI_DMA_INT_ENA_REG(obj->spi_num), SPI_INT_SRC_ONE_BUF_RECV_DONE);
|
||||
}
|
||||
// Clear all of interrupt source
|
||||
spi_int_clear(obj->spi_num);
|
||||
|
||||
spi_intr_func_set(isr, obj->spi_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroy the SPI DMA instance
|
||||
*
|
||||
*/
|
||||
int spi_dma_uninit(spi_dma_attr_t *obj)
|
||||
{
|
||||
if (NULL == obj) {
|
||||
return -1;
|
||||
}
|
||||
dma_buf_destroy(obj->buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the SPI DMA work mode.
|
||||
*
|
||||
*/
|
||||
static void spi_dma_enable(spi_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SPI_DMA_DIR_IN == obj->dir) {
|
||||
WRITE_PERI_REG(0x3ff000c4,1<<22);
|
||||
WRITE_PERI_REG(0x3ff000c4,0);
|
||||
SET_PERI_REG_MASK(SPI_DMA_OUT_LINK_REG(obj->spi_num), SPI_OUTLINK_START);
|
||||
SET_PERI_REG_MASK(SPI_DMA_IN_LINK_REG(obj->spi_num), SPI_INLINK_START);
|
||||
// LOGD("recv-01:length=%x",READ_PERI_REG(SPI_DMA_TSTATUS_REG(obj->spi_num))>>18);
|
||||
// while (((READ_PERI_REG(SPI_DMA_TSTATUS_REG(obj->spi_num))>>18)&0x3)!=0x3){
|
||||
//LOGD("recv-01:length=%x",READ_PERI_REG(SPI_DMA_TSTATUS_REG(obj->spi_num))>>18);
|
||||
// }
|
||||
} else if (SPI_DMA_DIR_OUT == obj->dir) {
|
||||
SET_PERI_REG_MASK(SPI_DMA_IN_LINK_REG(obj->spi_num), SPI_INLINK_START);
|
||||
SET_PERI_REG_MASK(SPI_DMA_OUT_LINK_REG(obj->spi_num), SPI_OUTLINK_START);
|
||||
// Waiting DMA controller fill TX FIFO
|
||||
while ((READ_PERI_REG(SPI_DMA_RSTATUS_REG(obj->spi_num))&0x80000000));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the SPI DMA work mode.
|
||||
*
|
||||
*/
|
||||
static void spi_dma_disable(spi_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
if (SPI_DMA_DIR_IN == obj->dir) {
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_IN_LINK_REG(obj->spi_num), SPI_INLINK_STOP);
|
||||
} else if (SPI_DMA_DIR_OUT == obj->dir) {
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_OUT_LINK_REG(obj->spi_num), SPI_OUTLINK_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable SPI DMA interrupt source.
|
||||
*
|
||||
*/
|
||||
void spi_dma_int_enable(spi_num_t spiNum, spi_int_src_t intSrc)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_DMA_INT_ENA_REG(spiNum), intSrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable SPI DMA interrupt source.
|
||||
*
|
||||
*/
|
||||
void spi_dma_int_disable(spi_num_t spiNum, spi_int_src_t intSrc)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_DMA_INT_ENA_REG(spiNum), intSrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear all of SPI DMA interrupt source.
|
||||
*
|
||||
*/
|
||||
void spi_dma_int_clear(spi_num_t spiNum)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_DMA_INT_CLR_REG(spiNum), 0x1FF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the SPI DMA interrupt status.
|
||||
*
|
||||
*/
|
||||
int32_t spi_dma_int_status_get(spi_num_t spiNum)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return -1;
|
||||
}
|
||||
return READ_PERI_REG(SPI_DMA_INT_ST_REG(spiNum));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start SPI work by DMA
|
||||
*
|
||||
*/
|
||||
void spi_dma_start(spi_dma_attr_t *obj, uint32_t len)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
// Reset DMA controller
|
||||
|
||||
SET_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_OUT_RST | SPI_IN_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_OUT_RST | SPI_IN_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST);
|
||||
|
||||
if (SPI_MODE_MASTER == obj->mode) {
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_DMA_CONTINUE);
|
||||
if (obj->dir == SPI_DMA_DIR_IN) {
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(obj->spi_num), SPI_USR_MISO_DBITLEN, ((len << 3) - 1), SPI_USR_MISO_DBITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(obj->spi_num), SPI_USR_MOSI_DBITLEN, ((len << 3) - 1), SPI_USR_MOSI_DBITLEN_S);
|
||||
}else{
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(obj->spi_num), SPI_USR_MISO_DBITLEN, ((len << 3) - 1), SPI_USR_MISO_DBITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(obj->spi_num), SPI_USR_MOSI_DBITLEN, ((len << 3) - 1), SPI_USR_MOSI_DBITLEN_S);
|
||||
}
|
||||
} else if (SPI_MODE_SLAVE == obj->mode) {
|
||||
if (0 == len) {
|
||||
SET_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_DMA_CONTINUE);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_DMA_CONTINUE);
|
||||
}
|
||||
}
|
||||
// 1.Enable DMA
|
||||
|
||||
|
||||
spi_dma_enable(obj);
|
||||
//LOGD("recv start before:%08x\n",obj->buf->ping->first_queue->data_length);
|
||||
|
||||
// LOGD("SPI_DMA_STATUS_REG=%x",READ_PERI_REG(SPI_DMA_STATUS_REG(obj->spi_num)));
|
||||
|
||||
// 2.Start SPI
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(obj->spi_num), SPI_USR);
|
||||
//LOGD("recv start after:%08x\n",obj->buf->ping->first_queue->data_length);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop SPI work by DMA
|
||||
*
|
||||
*/
|
||||
void spi_dma_stop(spi_dma_attr_t *obj)
|
||||
{
|
||||
if ((NULL == obj)
|
||||
|| (obj->spi_num > SPI_NUM_MAX)) {
|
||||
return;
|
||||
}
|
||||
if (SPI_MODE_MASTER == obj->mode) {
|
||||
SET_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_DMA_TX_STOP);
|
||||
} else if (SPI_MODE_SLAVE == obj->mode) {
|
||||
SET_PERI_REG_MASK(SPI_DMA_CONF_REG(obj->spi_num), SPI_DMA_RX_STOP);
|
||||
}
|
||||
spi_dma_disable(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Based on pAttr initialize SPI module.
|
||||
*
|
||||
*/
|
||||
void spi_init(spi_num_t spiNum, spi_attr_t* pAttr)
|
||||
{
|
||||
if ((spiNum > SPI_NUM_MAX)
|
||||
|| (NULL == pAttr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1);
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), SPI_TRANS_DONE << 5);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CS_SETUP);
|
||||
// By default clear command
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_COMMAND);
|
||||
|
||||
// SPI_CPOL & SPI_CPHA
|
||||
switch (pAttr->sub_mode) {
|
||||
case SPI_SUBMODE_1:
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(spiNum), SPI_CK_IDLE_EDGE);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CK_OUT_EDGE); // CHPA_FALLING_EDGE_SAMPLE
|
||||
break;
|
||||
case SPI_SUBMODE_2:
|
||||
SET_PERI_REG_MASK(SPI_PIN_REG(spiNum), SPI_CK_IDLE_EDGE);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CK_OUT_EDGE); // CHPA_FALLING_EDGE_SAMPLE
|
||||
break;
|
||||
case SPI_SUBMODE_3:
|
||||
SET_PERI_REG_MASK(SPI_PIN_REG(spiNum), SPI_CK_IDLE_EDGE);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CK_OUT_EDGE);
|
||||
break;
|
||||
case SPI_SUBMODE_0:
|
||||
default:
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(spiNum), SPI_CK_IDLE_EDGE);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CK_OUT_EDGE);
|
||||
// To do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
// SPI bit order
|
||||
if (SPI_BIT_ORDER_MSB_FIRST == pAttr->bit_order) {
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spiNum), SPI_WR_BIT_ORDER);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spiNum), SPI_RD_BIT_ORDER);
|
||||
} else if (SPI_BIT_ORDER_LSB_FIRST == pAttr->bit_order) {
|
||||
SET_PERI_REG_MASK(SPI_CTRL_REG(spiNum), SPI_WR_BIT_ORDER);
|
||||
SET_PERI_REG_MASK(SPI_CTRL_REG(spiNum), SPI_RD_BIT_ORDER);
|
||||
} else {
|
||||
// To do nothing
|
||||
}
|
||||
|
||||
// SPI bit order
|
||||
if (SPI_WORK_MODE_HALF == pAttr->half_mode) {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_DOUTDIN);
|
||||
} else if (SPI_WORK_MODE_FULL == pAttr->half_mode) {
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_DOUTDIN);
|
||||
}
|
||||
// May be not must to do.
|
||||
WRITE_PERI_REG(SPI_USER1_REG(spiNum), 0);
|
||||
// SPI mode type
|
||||
if (SPI_MODE_MASTER == pAttr->mode) {
|
||||
// SPI mode type
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(spiNum), SPI_MISO_DELAY_MODE, 0, SPI_MISO_DELAY_MODE_S); ////??????
|
||||
// SPI_SET_MISO_DELAY_NUM(spiNum,0);////???????
|
||||
//SET_PERI_REG_BITS(SPI_CTRL2_REG(spiNum), SPI_MISO_DELAY_NUM,0,SPI_MISO_DELAY_NUM_S);////??????
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), SPI_SLAVE_MODE);
|
||||
// SPI Send buffer
|
||||
// CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO_HIGHPART );// By default slave send buffer C0-C7
|
||||
// SPI Speed
|
||||
if (1 < (pAttr->speed)) {
|
||||
uint8_t i, k;
|
||||
i = (pAttr->speed / 40) ? (pAttr->speed / 40) : 1;
|
||||
|
||||
k = pAttr->speed / i;
|
||||
CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(spiNum), SPI_CLK_EQU_SYSCLK);
|
||||
WRITE_PERI_REG(SPI_CLOCK_REG(spiNum),
|
||||
(((i - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
|
||||
(((k - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
|
||||
((((k + 1) / 2 - 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
|
||||
(((k - 1) & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
|
||||
} else {
|
||||
WRITE_PERI_REG(SPI_CLOCK_REG(spiNum), SPI_CLK_EQU_SYSCLK); // 80Mhz speed
|
||||
}
|
||||
// Enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_MOSI);
|
||||
|
||||
// CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CS_HOLD);/////////////add
|
||||
SET_PERI_REG_MASK(SPI_CTRL2_REG(spiNum), ((0x4 & SPI_MISO_DELAY_NUM) << SPI_MISO_DELAY_NUM_S)); //delay num
|
||||
|
||||
} else if (SPI_MODE_SLAVE == pAttr->mode) {
|
||||
|
||||
// SPI mode type
|
||||
SET_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), SPI_SLAVE_MODE);
|
||||
// SPI mode type
|
||||
SET_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), SPI_SLV_WR_RD_BUF_EN);
|
||||
// SPI Send buffer
|
||||
// SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO_HIGHPART);// By default slave send buffer C8-C15
|
||||
|
||||
// If do not set delay cycles, slave not working,master cann't get the data.
|
||||
SET_PERI_REG_MASK(SPI_CTRL2_REG(spiNum), ((0x2 & SPI_MOSI_DELAY_NUM) << SPI_MOSI_DELAY_NUM_S)); //delay num
|
||||
// SPI Speed
|
||||
WRITE_PERI_REG(SPI_CLOCK_REG(spiNum), 0);
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_CS_SETUP);/////////////add
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI);
|
||||
|
||||
// By default format::CMD(8bits)+ADDR(8bits)+DATA(32bytes)
|
||||
// set pAttr->cmd_len bit slave recieve command length
|
||||
// set 1 bytes status buffer length
|
||||
// set pAttr->addr_len bit slave recieve read address length
|
||||
// set pAttr->addr_len bit slave recieve write address length
|
||||
// set 32 bytes slave recieve buffer length
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spiNum), SPI_USR_COMMAND_BITLEN,
|
||||
(7), SPI_USR_COMMAND_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SLAVE1_REG(spiNum), SPI_SLV_STATUS_BITLEN,
|
||||
(7), SPI_SLV_STATUS_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SLAVE1_REG(spiNum), SPI_SLV_WR_ADDR_BITLEN,
|
||||
(7), SPI_SLV_WR_ADDR_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SLAVE1_REG(spiNum), SPI_SLV_RD_ADDR_BITLEN,
|
||||
(7), SPI_SLV_RD_ADDR_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SLV_WRBUF_DLEN_REG(spiNum), SPI_SLV_WRBUF_DBITLEN,
|
||||
(32 * 8 - 1), SPI_SLV_WRBUF_DBITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SLV_RDBUF_DLEN_REG(spiNum), SPI_SLV_RDBUF_DBITLEN,
|
||||
(32 * 8 - 1), SPI_SLV_RDBUF_DBITLEN_S);
|
||||
} else {
|
||||
// To do nothing
|
||||
}
|
||||
|
||||
char i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
WRITE_PERI_REG((SPI_W0_REG(spiNum) + (i << 2)), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set address value by master mode.
|
||||
*
|
||||
*/
|
||||
void spi_master_cfg_addr(spi_num_t spiNum, uint32_t addr)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
// Set address
|
||||
SET_PERI_REG_BITS(SPI_ADDR_REG(spiNum), SPI_USR_ADDR_VALUE, addr, SPI_USR_ADDR_VALUE_S);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set command value by master mode.
|
||||
*
|
||||
*/
|
||||
void spi_master_cfg_cmd(spi_num_t spiNum, uint32_t cmd)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
// SPI_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
|
||||
// bit15-0 is cmd value.
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spiNum), SPI_USR_COMMAND_VALUE, cmd, SPI_USR_COMMAND_VALUE_S);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send data to slave.
|
||||
*
|
||||
*/
|
||||
int spi_master_send_data(spi_num_t spiNum, spi_data_t* pInData)
|
||||
{
|
||||
char idx = 0;
|
||||
if ((spiNum > SPI_NUM_MAX)
|
||||
|| (NULL == pInData)
|
||||
|| (64 < pInData->tx_data_len)) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t *value = pInData->tx_data;
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spiNum))&SPI_USR);
|
||||
// Set command by user.
|
||||
if (pInData->cmd_len != 0) {
|
||||
// Max command length 16 bits.
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spiNum), SPI_USR_COMMAND_BITLEN,
|
||||
((pInData->cmd_len << 3) - 1), SPI_USR_COMMAND_BITLEN_S);
|
||||
// Enable command
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_COMMAND);
|
||||
// Load command
|
||||
spi_master_cfg_cmd(spiNum, pInData->cmd);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_COMMAND);
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spiNum), SPI_USR_COMMAND_BITLEN,
|
||||
0, SPI_USR_COMMAND_BITLEN_S);
|
||||
}
|
||||
// Set Address by user.
|
||||
if (pInData->addr_len == 0) {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_ADDR);
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(spiNum), SPI_USR_ADDR_BITLEN,
|
||||
0, SPI_USR_ADDR_BITLEN_S);
|
||||
} else {
|
||||
if (NULL == pInData->addr) {
|
||||
return -1;
|
||||
}
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(spiNum), SPI_USR_ADDR_BITLEN,
|
||||
((pInData->addr_len << 3) - 1), SPI_USR_ADDR_BITLEN_S);
|
||||
// Enable address
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_ADDR);
|
||||
// Load address
|
||||
spi_master_cfg_addr(spiNum, *pInData->addr);
|
||||
}
|
||||
// Set data by user.
|
||||
if (pInData->tx_data_len != 0) {
|
||||
if (NULL == value) {
|
||||
return -1;
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO);
|
||||
// Enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI);
|
||||
// Load send buffer
|
||||
do {
|
||||
WRITE_PERI_REG((SPI_W0_REG(spiNum) + (idx << 2)), *value++);
|
||||
} while (++idx < ((pInData->tx_data_len / 4) + ((pInData->tx_data_len % 4) ? 1 : 0)));
|
||||
|
||||
// Set data send buffer length.Max data length 64 bytes.
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, ((pInData->tx_data_len << 3) - 1), SPI_USR_MOSI_DBITLEN_S);
|
||||
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, ((pInData->rx_data_len << 3) - 1), SPI_USR_MISO_DBITLEN_S);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO);
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN,
|
||||
0, SPI_USR_MOSI_DBITLEN_S);
|
||||
|
||||
}
|
||||
// Start send data
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
|
||||
while (!(READ_PERI_REG(SPI_SLAVE_REG(spiNum))&SPI_TRANS_DONE));
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), SPI_TRANS_DONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive data from slave.
|
||||
*
|
||||
*/
|
||||
int spi_master_recv_data(spi_num_t spiNum, spi_data_t* pData)
|
||||
{
|
||||
char idx = 0;
|
||||
if ((spiNum > SPI_NUM_MAX)
|
||||
|| (NULL == pData)) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t *value = pData->rx_data;
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spiNum))&SPI_USR);
|
||||
// Set command by user.
|
||||
if (pData->cmd_len != 0) {
|
||||
// Max command length 16 bits.
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spiNum), SPI_USR_COMMAND_BITLEN,
|
||||
((pData->cmd_len << 3) - 1), SPI_USR_COMMAND_BITLEN_S);
|
||||
// Enable command
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_COMMAND);
|
||||
// Load command
|
||||
spi_master_cfg_cmd(spiNum, pData->cmd);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_COMMAND);
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spiNum), SPI_USR_COMMAND_BITLEN,
|
||||
0, SPI_USR_COMMAND_BITLEN_S);
|
||||
}
|
||||
// Set Address by user.
|
||||
if (pData->addr_len == 0) {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_ADDR);
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(spiNum), SPI_USR_ADDR_BITLEN,
|
||||
0, SPI_USR_ADDR_BITLEN_S);
|
||||
} else {
|
||||
if (NULL == pData->addr) {
|
||||
return -1;
|
||||
}
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(spiNum), SPI_USR_ADDR_BITLEN,
|
||||
((pData->addr_len << 3) - 1), SPI_USR_ADDR_BITLEN_S);
|
||||
// Enable address
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_ADDR);
|
||||
// Load address
|
||||
spi_master_cfg_addr(spiNum, *pData->addr);
|
||||
}
|
||||
// Set data by user.
|
||||
if (pData->rx_data_len != 0) {
|
||||
if (NULL == value) {
|
||||
return -1;
|
||||
}
|
||||
// Clear MOSI enable
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI);
|
||||
// Enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO);
|
||||
// Set data send buffer length.Max data length 64 bytes.
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, ((pData->rx_data_len << 3) - 1), SPI_USR_MISO_DBITLEN_S);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO);
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 0, SPI_USR_MISO_DBITLEN_S);
|
||||
}
|
||||
// Start send data
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
|
||||
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spiNum))&SPI_USR);
|
||||
// Read data out
|
||||
do {
|
||||
*value++ = READ_PERI_REG(SPI_W0_REG(spiNum) + (idx << 2));
|
||||
} while (++idx < ((pData->rx_data_len / 4) + ((pData->rx_data_len % 4) ? 1 : 0)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load data to send buffer by slave mode.
|
||||
|
||||
*
|
||||
*/
|
||||
int spi_slave_send_data(spi_num_t spiNum, uint32_t *pOutData, uint8_t outLen)
|
||||
{
|
||||
if (NULL == pOutData) {
|
||||
return -1;
|
||||
}
|
||||
char i;
|
||||
uint32_t *value = pOutData;
|
||||
for (i = 0; i < outLen; ++i) {
|
||||
WRITE_PERI_REG((SPI_W0_REG(spiNum) + (i << 2)), *value++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configurate slave prepare for receive data.
|
||||
*
|
||||
*/
|
||||
int spi_slave_recv_data(spi_num_t spiNum, void(*isrFunc)(void*))
|
||||
{
|
||||
char idx = 0;
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
spi_int_enable(spiNum, SPI_INT_SRC_WR_STA_DONE
|
||||
| SPI_INT_SRC_RD_STA_DONE | SPI_INT_SRC_WR_BUF_DONE | SPI_INT_SRC_RD_BUF_DONE);
|
||||
spi_int_disable(spiNum, SPI_INT_SRC_TRANS_DONE);
|
||||
|
||||
spi_intr_func_set(isrFunc, spiNum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send data to slave(ESP32,RD_STATUS or WR_STATUS).
|
||||
*
|
||||
*/
|
||||
void spi_master_send_status(spi_num_t spiNum, uint8_t data)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spiNum))&SPI_USR);
|
||||
// enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
|
||||
|
||||
// 8bits cmd, 0x04 is eps32 slave write cmd value
|
||||
WRITE_PERI_REG(SPI_USER2_REG(spiNum),
|
||||
((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S)
|
||||
| MASTER_WRITE_STATUS_TO_SLAVE_CMD);
|
||||
// Set data send buffer length.
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN,
|
||||
((sizeof(data) << 3) - 1), SPI_USR_MOSI_DBITLEN_S);
|
||||
|
||||
WRITE_PERI_REG(SPI_W0_REG(spiNum), (uint32_t)(data));
|
||||
// start SPI
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive data from slave(ESP32).
|
||||
*
|
||||
*/
|
||||
int spi_master_recv_status(spi_num_t spiNum)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spiNum))&SPI_USR);
|
||||
// enable MISO
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MISO);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spiNum), SPI_USR_MOSI | SPI_USR_DUMMY | SPI_USR_ADDR);
|
||||
|
||||
// 8bits cmd, 0x06 is eps32 slave read cmd value
|
||||
WRITE_PERI_REG(SPI_USER2_REG(spiNum),
|
||||
((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S)
|
||||
| MASTER_READ_STATUS_FROM_SLAVE_CMD);
|
||||
// Set revcive buffer length.
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN,
|
||||
7, SPI_USR_MISO_DBITLEN_S);
|
||||
|
||||
// start spi module.
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
|
||||
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spiNum))&SPI_USR);
|
||||
|
||||
uint8_t data = (uint8_t)(READ_PERI_REG(SPI_W0_REG(spiNum)) & 0xff);
|
||||
return (uint8_t)(READ_PERI_REG(SPI_W0_REG(spiNum)) & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable SPI interrupt source.
|
||||
*
|
||||
*/
|
||||
void spi_int_enable(spi_num_t spiNum, spi_int_src_t intSrc)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), intSrc << 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable SPI interrupt source.
|
||||
*
|
||||
*/
|
||||
void spi_int_disable(spi_num_t spiNum, spi_int_src_t intSrc)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), intSrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear all of SPI interrupt source.
|
||||
*
|
||||
*/
|
||||
void spi_int_clear(spi_num_t spiNum)
|
||||
{
|
||||
if (spiNum > SPI_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spiNum), SPI_INT_SRC_TRANS_DONE
|
||||
| SPI_INT_SRC_WR_STA_DONE
|
||||
| SPI_INT_SRC_RD_STA_DONE
|
||||
| SPI_INT_SRC_WR_BUF_DONE
|
||||
| SPI_INT_SRC_RD_BUF_DONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the SPI interrupt status.
|
||||
*
|
||||
*/
|
||||
int32_t spi_int_status_get(spi_num_t i2sNum)
|
||||
{
|
||||
if (i2sNum > SPI_NUM_MAX) {
|
||||
return -1;
|
||||
}
|
||||
return READ_PERI_REG(SPI_SLAVE_REG(i2sNum));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,469 +0,0 @@
|
|||
#include "driver/i2c.h"
|
||||
#include "esp_types.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/i2c_soft.h"
|
||||
#include "ES7242.h"
|
||||
#include "driver/gpio.h"
|
||||
//#include "driver/gpio_sig_map.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
|
||||
|
||||
#define I2C_FREQ 100000 //HZ
|
||||
#define I2C_SLAVE_DEV_ADDR 0x60
|
||||
|
||||
#define I2C_SDA_OUT_IO_NUM 21
|
||||
#define I2C_SDA_OUT_IO_SIG I2CEXT0_SDA_OUT_IDX
|
||||
#define I2C_SDA_OUT_IO_PIN GPIO_SEL_21
|
||||
|
||||
#define I2C_SCL_OUT_IO_NUM 19
|
||||
#define I2C_SCL_OUT_IO_SIG I2CEXT0_SCL_OUT_IDX
|
||||
#define I2C_SCL_OUT_IO_PIN GPIO_SEL_19
|
||||
|
||||
#define I2C_SDA_IN_IO_SIG I2CEXT0_SDA_IN_IDX
|
||||
#define I2C_SCL_IN_IO_SIG I2CEXT0_SCL_IN_IDX
|
||||
|
||||
#define ES8388_ADDR 0x20
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
void I2C_GpioInit()
|
||||
{
|
||||
#if 1
|
||||
ets_printf("Configuring GPIO...........\n");
|
||||
gpio_config_t gpio_conf;
|
||||
gpio_conf.gpio_pin_sel = I2C_SDA_OUT_IO_PIN | I2C_SCL_OUT_IO_PIN ;
|
||||
gpio_conf.gpio_mode_sel = GPIO_MODE_INPUT_OUTPUT_OD;
|
||||
gpio_conf.gpio_pulldown_sel = GPIO_PULLDOWN_DISABLE;
|
||||
gpio_conf.gpio_pullup_sel = GPIO_PULLUP_ENABLE;
|
||||
gpio_conf.gpio_intry_type_sel = GPIO_PIN_INTR_DISABLE;
|
||||
gpio_config(&gpio_conf);
|
||||
#if 0
|
||||
SET_PERI_REG_BITS(GPIO_PIN_REG_19, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_REG_23, FUN_DRV, 3, FUN_DRV_S);
|
||||
CLEAR_PERI_REG_MASK(GPIO_PIN_REG_19, FUN_PD);
|
||||
CLEAR_PERI_REG_MASK(GPIO_PIN_REG_23, FUN_PD);
|
||||
#endif
|
||||
|
||||
gpio_matrix_out(I2C_SDA_OUT_IO_NUM, I2C_SDA_OUT_IO_SIG, 0, 0);
|
||||
gpio_matrix_out(I2C_SCL_OUT_IO_NUM, I2C_SCL_OUT_IO_SIG, 0, 0);
|
||||
gpio_matrix_in(I2C_SDA_OUT_IO_NUM, I2C_SDA_IN_IO_SIG, 0);
|
||||
gpio_matrix_in(I2C_SCL_OUT_IO_NUM, I2C_SCL_IN_IO_SIG, 0);
|
||||
#else
|
||||
// SDA OUT
|
||||
gpio_matrix_out(19, I2C_SDA_OUT_IO_SIG, 0, 0);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_GPIO19);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO19_U, FUN_IE | FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO19_U, FUN_PD);
|
||||
|
||||
SET_PERI_REG_MASK(GPIO_PIN19_REG, GPIO_PIN19_PAD_DRIVER);
|
||||
//====debug====
|
||||
gpio_matrix_out(23, I2C_SCL_OUT_IO_SIG, 0, 0);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO23_U, FUNC_GPIO23_GPIO23);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO23_U, FUN_IE | FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO23_U, FUN_PD);
|
||||
SET_PERI_REG_MASK(GPIO_PIN23_REG, GPIO_PIN23_PAD_DRIVER);
|
||||
//============================
|
||||
//SDA IN
|
||||
gpio_matrix_in(19, I2C_SDA_IN_IO_SIG, 0);
|
||||
//SCL IN
|
||||
gpio_matrix_in(23, I2C_SCL_IN_IO_SIG, 0);
|
||||
|
||||
#endif
|
||||
|
||||
ets_printf("GPIO Configured! ! ! ! ! ! ! ! ! !\n");
|
||||
}
|
||||
|
||||
|
||||
void disp_cmd(uint8_t i2c_no, uint8_t idx)
|
||||
{
|
||||
// ets_printf("---cmd %d ---\n",idx);
|
||||
|
||||
// ets_printf("opcode: %d \n",I2C_GET_COMMAND_OP_CODE(i2c_no,idx));
|
||||
// ets_printf("acken: %d \n",I2C_GET_COMMAND_ACK_EN(i2c_no,idx));
|
||||
// ets_printf("ackexp: %d \n",I2C_GET_COMMAND_ACK_EXP(i2c_no,idx));
|
||||
// ets_printf("ack val: %d \n",I2C_GET_COMMAND_ACK_VALUE(i2c_no,idx));
|
||||
// ets_printf("byte num: %d \n",I2C_GET_COMMAND_BYTE_NUM(i2c_no,idx));
|
||||
// ets_printf("done: %d \n",I2C_GET_COMMAND_DONE(i2c_no,idx));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void i2c_master_read_test()
|
||||
|
||||
{
|
||||
uint8_t i2c_no = 0;
|
||||
uint8_t idx = 0;
|
||||
|
||||
uint8_t data_buf[] = {I2C_SLAVE_DEV_ADDR, //addr
|
||||
0x10,
|
||||
0x01,
|
||||
0x12,
|
||||
0x13,
|
||||
0x14,
|
||||
};
|
||||
uint8_t byte_num = 3;//sizeof(data_buf);
|
||||
|
||||
I2C_SET_TX_FIFO_RST(0, 1);
|
||||
I2C_SET_TX_FIFO_RST(0, 0);
|
||||
|
||||
//command0 : sending restart signal
|
||||
idx = 0;
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no, idx, 0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no, idx, 0);
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no, 0, 1);
|
||||
disp_cmd( i2c_no, 0);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
idx = 1;
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no, idx, 0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no, idx, 1); //WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no, idx, byte_num); //BYTE NUMBER
|
||||
disp_cmd( i2c_no, 1);
|
||||
|
||||
//command2 : master generating stop
|
||||
idx = 2;
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no, idx, 0x3); //STOP
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no, idx, 0); //NO ACK
|
||||
disp_cmd( i2c_no, 2);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < byte_num; i++) {
|
||||
WRITE_PERI_REG(I2C_DATA_REG(i2c_no), data_buf[i]);
|
||||
}
|
||||
|
||||
//start sending
|
||||
I2C_SET_TRANS_START(i2c_no, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void I2C_MasterInit(uint8_t init_num)
|
||||
{
|
||||
|
||||
//step 1: gpio init
|
||||
I2C_GpioInit();
|
||||
#if 1
|
||||
ets_delay_us(500000);
|
||||
//step 2: i2c init
|
||||
ets_printf("Initializing I2C Master.............\r\n");
|
||||
I2C_InitTypeDef i2c_master;
|
||||
i2c_master.mode = I2C_MASTER_MODE; //master mode
|
||||
i2c_master.addr_10bit_en = 0; //not used
|
||||
i2c_master.clk_speed = 100000; //clk set
|
||||
i2c_master.slave_addr = 0x0; //no slave addr for master mode
|
||||
I2C_Init(init_num, &i2c_master);
|
||||
#else
|
||||
uint8_t i2c_no = init_num;
|
||||
if (i2c_no > 1) {
|
||||
ets_printf("invalid i2c number...\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//set master mode
|
||||
//I2C_SET_RX_LSB_FIRST(i2c_no,0); //MSB FIRST
|
||||
//I2C_SET_TX_LSB_FIRST(i2c_no,0); //MSB FIRST
|
||||
I2C_SET_MS_MODE(i2c_no, 1); //MASTER MODE
|
||||
//I2C_SET_SCL_FORCE_OUT(i2c_no,1); //out put practical level
|
||||
//I2C_SET_SDA_FORCE_OUT(i2c_no,1); //out put practical level
|
||||
|
||||
//SET FREQ/DUTY
|
||||
I2C_SET_SCL_LOW_PERIOD(i2c_no, (APB_CLK_FREQ / I2C_FREQ) / 2);
|
||||
I2C_SET_SCL_HIGH_PERIOD(i2c_no, (APB_CLK_FREQ / I2C_FREQ) / 2);
|
||||
|
||||
//SET CLK RE/START HOLD/SETUP
|
||||
I2C_SET_SCL_START_HOLD_TIME(i2c_no, 50); //400);
|
||||
I2C_SET_SCL_RSTART_SETUP_TIME(i2c_no, 50); //400);
|
||||
|
||||
//SET CLK STOP HOLD/SETUP
|
||||
I2C_SET_SCL_STOP_HOLD_TIME(i2c_no, 50); //400);
|
||||
I2C_SET_SCL_STOP_SETUP_TIME(i2c_no, 50); //400);
|
||||
|
||||
//SET DATA I/O HOLD/SAMPLE
|
||||
I2C_SET_SDA_HOLD_TIME(i2c_no, 40);
|
||||
I2C_SET_SDA_SAMPLE_TIME(i2c_no, 40);
|
||||
|
||||
//SET CLK TIME OUT
|
||||
//I2C_SET_TIME_OUT_THRSH(i2c_no,2000);
|
||||
I2C_SET_TIME_OUT_REG(i2c_no, 2000);
|
||||
|
||||
//SET FIFO MODE
|
||||
//I2C_SET_NONFIFO_EN(i2c_no,0);
|
||||
//SET SCL FILTER
|
||||
//I2C_SET_SCL_FILTER_EN(i2c_no,1);
|
||||
//SET SDA FILTER
|
||||
//I2C_SET_SDA_FILTER_EN(i2c_no,0);
|
||||
|
||||
//i2c_intr_config();
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void i2c_send_data_test(uint8_t i2c_num, uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
|
||||
|
||||
//struct I2C_DEV * I2Cx = I2C(i2c_num);
|
||||
uint8_t data_buf[] = {
|
||||
slave_addr,
|
||||
reg_addr,
|
||||
data
|
||||
};
|
||||
|
||||
uint8_t byte_num = sizeof(data_buf);
|
||||
struct I2C_CmdDef cmd;
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
//reset tx fifo
|
||||
I2C_ResetTxFifo(i2c_num);
|
||||
|
||||
//setup command 0
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.ack_en = 0;
|
||||
cmd.ack_exp = 0;
|
||||
cmd.ack_val = 0;
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_RESTART;
|
||||
|
||||
I2C_ConfigCmd(i2c_num, 0, &cmd);
|
||||
|
||||
disp_cmd( i2c_num, 0);
|
||||
|
||||
//setup command 1
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.ack_en = 0;
|
||||
cmd.ack_exp = 0;
|
||||
cmd.ack_val = 0;
|
||||
cmd.byte_num = byte_num;
|
||||
cmd.op_code = I2C_CMD_WRITE;
|
||||
I2C_ConfigCmd(i2c_num, 1, &cmd);
|
||||
disp_cmd( i2c_num, 1);
|
||||
|
||||
//setup command 2
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_STOP;
|
||||
I2C_ConfigCmd(i2c_num, 2, &cmd);
|
||||
disp_cmd( i2c_num, 2);
|
||||
|
||||
//push the sending data to tx fifo
|
||||
I2C_TxFifoPush(i2c_num, data_buf , byte_num);
|
||||
|
||||
//I2C start sending
|
||||
I2C_Start(i2c_num);
|
||||
|
||||
I2C_WaitTxDone(i2c_num, 2);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void ES8388_PowerOn_Init1(void)
|
||||
{
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x08, 0x00); //CODEC IN I2S SLAVE MODE -
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x00, 0x07); //PLAY BACK,ENREFR=0 //changed
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2d, 0x00); //vroi=0
|
||||
|
||||
ets_delay_us(10000);
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x01, 0x40); //pdn_ana=1,ibiasgen_pdn=0,lpvrefbuf=1
|
||||
|
||||
ets_delay_us(10000);
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x02, 0xf3); //Reset STM and DLL
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x03, 0xFF); //Reset STM and DLL
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x04, 0xC0); //power up L/R DAC,Enable LO1/RO1,LO2/RO2,OUT3/MONO
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x0A, 0x00); //LIN1/RIN1 as ADC Input
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x0C, 0x0C); //I2S-16BIT,LADC=Left data,RADC=right data W
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x0d, 0x02); //SINGLE SPEED,RATIO=256
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x10, 0x00); //ADC Left Volume=0db
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x11, 0x00); //ADC Right Volume=0db
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x17, 0x18); //I2S-16BIT 0x18 //PCM 16BIT 0x5E
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x18, 0x02); //SINGLE SPEED,RATIO=256
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x19, 0x36); //SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x1A, 0x00); //LDAC volume=0db,RDAC Volume=0db
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x1B, 0x00);
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x19, 0x32); //SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x27, 0xB8); //Left DAC TO Left MIXER
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x28, 0x38);
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x29, 0x38);
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2A, 0xB8); //RIGHT DAC TO RIGHT MIXER
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x04, 0x30); //Enable DAC and Enable Lout/Rout
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2e, 0X10); //LOUT/ROUT volume
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2f, 0X10);
|
||||
|
||||
ets_delay_us(50000);
|
||||
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2e, 0x1A); //LOUT/ROUT volume
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2f, 0x1A);
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x04, 0xc0); //Disable DAC and Lout/Rout
|
||||
}
|
||||
|
||||
void ES8388_DAC_Play1(void)
|
||||
{
|
||||
int Vol = 0x1f;
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x02, 0xAA); //START DAC DLL and State Machine
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2d, 0X00); //vroi=0 DelayT0(10); //Delay 10mS
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x04, 0x3C); //Enable DAC and Enable Lout/Rout
|
||||
|
||||
ets_delay_us(10000);
|
||||
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2e, Vol); //LOUT2/ROUT2
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x2f, Vol);
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x30, Vol); //LOUT1/ROUT1
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x31, Vol);
|
||||
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x19, 0xF2); //DAC un-Mute
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x01, 0x40); //LPVrefBuf=0,Pdn_ana=0
|
||||
ES7242_WriteReg(ES8388_ADDR, 0x00, 0x07); //Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
|
||||
}
|
||||
|
||||
|
||||
void ES7242_Poweron_Init(void)
|
||||
{
|
||||
ets_printf("Writing Data to Registers\n");
|
||||
#if 0
|
||||
ES7242_WriteReg(ES7242_Address1, 0x00, 0x01);
|
||||
ets_delay_us(10000);
|
||||
ES7242_WriteReg(ES7242_Address1, 0x01, 0x00);
|
||||
ets_delay_us(10000);
|
||||
ES7242_WriteReg(ES7242_Address2, 0x00, 0x01);
|
||||
ets_delay_us(10000);
|
||||
ES7242_WriteReg(ES7242_Address2, 0x01, 0x00);
|
||||
ets_delay_us(10000);
|
||||
#endif
|
||||
#if 1
|
||||
ES7242_WriteReg(ES7242_Address3, 0x00, 0x01);
|
||||
ets_delay_us(10000);
|
||||
ES7242_WriteReg(ES7242_Address3, 0x01, 0x00);
|
||||
ets_delay_us(10000);
|
||||
ES7242_WriteReg(ES7242_Address4, 0x00, 0x01);
|
||||
ets_delay_us(10000);
|
||||
ES7242_WriteReg(ES7242_Address4, 0x01, 0x00);
|
||||
ets_delay_us(10000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ES7242_ADC_Record()
|
||||
{
|
||||
|
||||
#if 0
|
||||
ES7242_WriteReg(ES7242_Address1, 0x01, 0x0F);
|
||||
ES7242_WriteReg(ES7242_Address1, 0x07, 0x00);
|
||||
ES7242_WriteReg(ES7242_Address1, 0x08, 0x11);
|
||||
ES7242_WriteReg(ES7242_Address1, 0x09, 0x00);
|
||||
|
||||
ES7242_WriteReg(ES7242_Address2, 0x01, 0x8F);
|
||||
ES7242_WriteReg(ES7242_Address2, 0x07, 0x00);
|
||||
ES7242_WriteReg(ES7242_Address2, 0x08, 0x11);
|
||||
ES7242_WriteReg(ES7242_Address2, 0x09, 0x00);
|
||||
#endif
|
||||
#if 1
|
||||
ES7242_WriteReg(ES7242_Address3, 0x01, 0x0F);
|
||||
ES7242_WriteReg(ES7242_Address3, 0x07, 0x00);
|
||||
ES7242_WriteReg(ES7242_Address3, 0x08, 0x11);
|
||||
ES7242_WriteReg(ES7242_Address3, 0x09, 0x00);
|
||||
#endif
|
||||
#if 1
|
||||
ES7242_WriteReg(ES7242_Address4, 0x01, 0x8F);
|
||||
ES7242_WriteReg(ES7242_Address4, 0x07, 0x00);
|
||||
ES7242_WriteReg(ES7242_Address4, 0x08, 0x11);
|
||||
ES7242_WriteReg(ES7242_Address4, 0x09, 0x00);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ES7242_ADC_StandBy()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
void ES7242_init(void)
|
||||
{
|
||||
//I2C_MasterInit(0x0);
|
||||
i2c_master_gpio_init();
|
||||
ES8388_PowerOn_Init1();
|
||||
ES8388_DAC_Play1();
|
||||
//ES7242_Poweron_Init();
|
||||
// ES7242_ADC_Record();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool I2C_Write_Byte(uint8_t data, uint8_t iter)
|
||||
{
|
||||
if (iter == 0) {
|
||||
iter = 1;
|
||||
}
|
||||
|
||||
while (iter--) {
|
||||
i2c_master_writeByte(data);
|
||||
|
||||
if (i2c_master_getAck()) {
|
||||
i2c_master_stop();
|
||||
i2c_master_wait(500); // Wait 500us and retry.
|
||||
i2c_master_start();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i2c_master_stop();
|
||||
return false;
|
||||
}
|
||||
#if 1
|
||||
void ES7242_WriteReg(uint8_t slave_add, uint8_t reg_add, uint8_t data)
|
||||
{
|
||||
i2c_master_start();
|
||||
if (false == I2C_Write_Byte(slave_add, 10)) {
|
||||
ets_printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
if (false == I2C_Write_Byte(reg_add, 10)) {
|
||||
ets_printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
if (false == I2C_Write_Byte(data, 10)) {
|
||||
ets_printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
i2c_master_stop();
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
void ES7242_WriteReg(uint8_t slave_add, uint8_t reg_add, uint8_t data)
|
||||
{
|
||||
i2c_send_data_test(0x0, slave_add, reg_add, data);
|
||||
//ets_delay_us(10000);
|
||||
}
|
||||
#endif
|
||||
uint8_t ES7242_ReadReg(uint8_t slave_add, uint8_t reg_add, uint8_t dat)
|
||||
{
|
||||
i2c_master_start();
|
||||
if (false == I2C_Write_Byte(slave_add, 0)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
if (false == I2C_Write_Byte(reg_add, 0)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
i2c_master_start();
|
||||
i2c_master_writeByte(0x21);
|
||||
uint8_t ack = i2c_master_getAck();
|
||||
uint8_t Reve = i2c_master_readByte();
|
||||
i2c_master_setAck(1);
|
||||
i2c_master_stop();
|
||||
return Reve;
|
||||
}
|
|
@ -1,273 +0,0 @@
|
|||
#include "i2c_soft.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <stdio.h>
|
||||
#include "ES8388.h"
|
||||
|
||||
#define ES8388_ADDR 0x22 // 0x22:CE=1;0x20:CE=0
|
||||
|
||||
static bool I2C_Write_Byte(uint8_t data, uint8_t iter);
|
||||
void ES8388_WriteReg(uint8_t slave_add, uint8_t reg_add, uint8_t data);
|
||||
uint8_t ES8388_ReadReg(uint8_t slave_add, uint8_t reg_add, uint8_t dat);
|
||||
|
||||
|
||||
void ES8388_Init(uint32_t mode, uint32_t channel, uint32_t bits, uint32_t rate)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_Stop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_Pause()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_Resume()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_SetVolume()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_SetDacChannel(int32_t channel, int32_t value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_SetMute(int32_t channel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ES8388_SetMicGain()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ES8388_PowerOn_Init(void)
|
||||
{
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x08, 0x00); //CODEC IN I2S SLAVE MODE -
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x00, 0x07); //PLAY BACK,ENREFR=0 //changed
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2d, 0x00); //vroi=0
|
||||
|
||||
vTaskDelay(1);
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x40); //pdn_ana=1,ibiasgen_pdn=0,lpvrefbuf=1
|
||||
|
||||
vTaskDelay(1);
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0xf3); //Reset STM and DLL
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x03, 0xFF); //Reset STM and DLL
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0xC0); //power up L/R DAC,Enable LO1/RO1,LO2/RO2,OUT3/MONO
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0A, 0x00); //LIN1/RIN1 as ADC Input
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0C, 0x0C); //I2S-16BIT,LADC=Left data,RADC=right data W
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0d, 0x02); //SINGLE SPEED,RATIO=256
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x10, 0x00); //ADC Left Volume=0db
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x11, 0x00); //ADC Right Volume=0db
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x17, 0x18); //I2S-16BIT
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x18, 0x02); //SINGLE SPEED,RATIO=256
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x19, 0x36); //SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x1A, 0x00); //LDAC volume=0db,RDAC Volume=0db
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x1B, 0x00);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x19, 0x32); //SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x27, 0xB8); //Left DAC TO Left MIXER
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x28, 0x38);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x29, 0x38);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2A, 0xB8); //RIGHT DAC TO RIGHT MIXER
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0x30); //Enable DAC and Enable Lout/Rout
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2e, 0X10); //LOUT/ROUT volume
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2f, 0X10);
|
||||
|
||||
vTaskDelay(5);
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2e, 0x1A); //LOUT/ROUT volume
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2f, 0x1A);
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0xc0); //Disable DAC and Lout/Rout
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ES8388_DAC_Play()
|
||||
{
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0x00); //START DAC DLL and State Machine
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2d, 0X00); //vroi=0 DelayT0(10); //Delay 10mS
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0x3C); //Enable DAC and Enable Lout/Rout
|
||||
|
||||
vTaskDelay(1);
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2e, Vol); //LOUT2/ROUT2
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2f, Vol);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x30, Vol); //LOUT1/ROUT1
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x31, Vol);
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x19, 0xF2); //DAC un-Mute
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x40); //LPVrefBuf=0,Pdn_ana=0
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x00, 0x07); //Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
|
||||
}
|
||||
void ES8388_ALC()
|
||||
{
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x12, 0xf2); //ALC for Microphone
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x13, 0xb0);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x14, 0x05);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x15, 0x06);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x16, 0x7b);
|
||||
|
||||
}
|
||||
void ES8388_ADC_Record()
|
||||
{
|
||||
|
||||
/*
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x08, 0x00); //Codec in I2S slave mode
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0xF3); //ADC Power-up
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x00, 0x05); //DAC Power-DN,LOUT/ROUT disable
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x40); //DAC Power-DN,LOUT/ROUT disable
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x03, 0x00); //ADC Power-up
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0xC0); //DAC Power-DN,LOUT/ROUT disable
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x09, 0x77); //Analog In PGA=24db
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0A, 0x00); //MIC INPUT FROM LIN1/RIN1
|
||||
// ES8388_WriteReg(0x0A,0x50); //MIC INPUT FROM LIN2/RIN2
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0C, 0x0C); //I2S-16BIT, leftADC-Left Channel, RightADC-Right Channel
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0D, 0x02); //MCLK/LRCK=256
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x10, 0x00); //ADC VOLUME = 0dB
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x10, 0x00); //ADC VOLUME = 0dB
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0x55);
|
||||
|
||||
vTaskDelay(1); //Delay 10mS
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x40); //pdn_ana=0,ibiasgen_pdn=0
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x00, 0x05); //置ES8350于PLAYBACK & RECORD 模式,且EnRefr=1
|
||||
ES8388_ALC();
|
||||
ES8388_ADC_StandBy();
|
||||
*/
|
||||
//unsigned int i;
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x36); //Power down whole chip analog
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x72); //power up whole chip analog
|
||||
//ES8388_WriteReg(ES8388_ADDR, 0x02, 0xF3); //stop STM and DLL, power down DAC&ADC vref
|
||||
//ES8388_WriteReg(ES8388_ADDR, 0x02, 0xF0); //power up DAC&ADC vref
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x2B, 0x80); //set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0xF3); //ADC clock is same as DAC. Use ADC MCLK as internal MCLK
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x08, 0x00); //CODEC IN I2S SLAVE MODE-0x00;master-0x80
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0xC0); //power down DAC, Disable LOUT&ROUT
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x05, 0x00); //low power setting
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x06, 0xC3);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0A, 0x00); //select LIN1&RIN1 as Microphone
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0B, 0x00);
|
||||
// ES8388_WriteReg(ES8388_ADDR, 0x0C, 0x6F); //ADC 16BIT PCM & right=left
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0C, 0x0C); //ADC I2S-16BIT
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x0D, 0x02); //ADCLRCK = MCLK/256
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x10, 0x00); //ADC VOLUME = 0DB
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x11, 0x00);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x09, 0x88); //MIC PGA =24DB
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x12, 0xE2); //MIC ALC SETTING
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x13, 0xC0);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x14, 0x12);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x15, 0x06);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x16, 0xC3);
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0x00); //startup FSM and DLL
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x03, 0x00); //Power up ADC, Enable LIN&RIN, Power down MICBIAS, set int1lp to low power mode
|
||||
vTaskDelay(1);
|
||||
//ES8388_WriteReg(ES8388_ADDR, 0x01, 0x40); //pdn_ana=0,ibiasgen_pdn=0
|
||||
//ES8388_WriteReg(ES8388_ADDR, 0x00, 0x05); //置ES8350于PLAYBACK & RECORD 模式,且EnRefr=1
|
||||
|
||||
}
|
||||
void ES8388_ADC_StandBy()
|
||||
{
|
||||
|
||||
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x00, 0x01); //置ES8350于PLAYBACK & RECORD 模式,且EnRefr=1
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x01, 0x58); //pdn_ana=0,ibiasgen_pdn=0
|
||||
vTaskDelay(1); //Delay 10mS
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x03, 0xFF); //ADC Power-Down
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x04, 0xC0); //DAC Power-DN,LOUT/ROUT disable
|
||||
ES8388_WriteReg(ES8388_ADDR, 0x02, 0xf3); //关闭录音
|
||||
|
||||
}
|
||||
void ES8388_init(void)
|
||||
{
|
||||
i2c_master_gpio_init();
|
||||
ES8388_PowerOn_Init();
|
||||
// ES8388_ADC_Record();
|
||||
//ES8388_DAC_Play();
|
||||
|
||||
}
|
||||
|
||||
static bool I2C_Write_Byte(uint8_t data, uint8_t iter)
|
||||
{
|
||||
if (iter == 0) {
|
||||
iter = 1;
|
||||
}
|
||||
|
||||
while (iter--) {
|
||||
i2c_master_writeByte(data);
|
||||
|
||||
if (i2c_master_getAck()) {
|
||||
i2c_master_stop();
|
||||
ets_delay_us(500); // Wait 500us and retry.
|
||||
i2c_master_start();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i2c_master_stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ES8388_WriteReg(uint8_t slave_add, uint8_t reg_add, uint8_t data)
|
||||
{
|
||||
i2c_master_start();
|
||||
if (false == I2C_Write_Byte(slave_add, 30)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
if (false == I2C_Write_Byte(reg_add, 30)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
if (false == I2C_Write_Byte(data, 30)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
i2c_master_stop();
|
||||
}
|
||||
|
||||
uint8_t ES8388_ReadReg(uint8_t slave_add, uint8_t reg_add, uint8_t dat)
|
||||
{
|
||||
i2c_master_start();
|
||||
if (false == I2C_Write_Byte(slave_add, 10)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
if (false == I2C_Write_Byte(reg_add, 10)) {
|
||||
printf("Slave is busy, TIME OUT");
|
||||
}
|
||||
i2c_master_start();
|
||||
i2c_master_writeByte(0x21);
|
||||
uint8_t ack = i2c_master_getAck();
|
||||
uint8_t Reve = i2c_master_readByte();
|
||||
i2c_master_setAck(1);
|
||||
i2c_master_stop();
|
||||
return Reve;
|
||||
}
|
|
@ -1,388 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MediaHal.h"
|
||||
#include "audio_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_types.h"
|
||||
//#include "inc/Vs10xx.h"
|
||||
#include "AP80/Ap80xx.h"
|
||||
#include "EspAudioCom.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "MyString.h"
|
||||
#include "ES8388.h"
|
||||
|
||||
// 2---ES8388
|
||||
// 1---AP8048
|
||||
// 0---VS1053
|
||||
|
||||
#define PA_POINT_PWR 25 // GPIO25
|
||||
#define AP_POINT_PWR 26 // GPIO26
|
||||
|
||||
#define CODECTYPE 1
|
||||
static char* LOGPRE = "[mediaHal Err]";
|
||||
static char* LOGPRD = "[mediaHal Info]";
|
||||
|
||||
|
||||
static MediaState mediaStatus = 0;
|
||||
static uint32_t mediaVol = 50;
|
||||
|
||||
void mediaHalInit(void)
|
||||
{
|
||||
#if CODECTYPE==0
|
||||
VS_Init();
|
||||
VS_Sine_Test();
|
||||
VS_HD_Reset();
|
||||
VS_Soft_Reset();
|
||||
VS_Set_All();
|
||||
#elif CODECTYPE==1
|
||||
// AP8048 PWRKEY
|
||||
gpio_config_t io_conf;
|
||||
memset(&io_conf, 0, sizeof(io_conf));
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_GPIO26);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO26_U, FUN_PU);
|
||||
|
||||
io_conf.pin_bit_mask = GPIO_SEL_26;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.intr_type = GPIO_PIN_INTR_DISABLE ;
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(AP_POINT_PWR, 0x01); // Enable the AP80 powerkey
|
||||
|
||||
// PA PWR
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_GPIO25);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO25_U, FUN_PU);
|
||||
gpio_set_level(PA_POINT_PWR, 0x01);
|
||||
|
||||
apInit();
|
||||
#elif CODECTYPE==2
|
||||
ES8388_init();
|
||||
|
||||
#endif
|
||||
mediaStatus = MediaState_Initialized;
|
||||
LOGI("mediaHalInit ok");
|
||||
}
|
||||
|
||||
MediaErr mediaHalDataRead(uint8_t *dat, int *len)
|
||||
{
|
||||
if ((NULL == dat)
|
||||
/*|| (MediaState_Playing != mediaStatus)*/) {
|
||||
printf("%s,[func]%s,MediaState is not playing[%x]\r\n", LOGPRE, __func__, mediaStatus);
|
||||
return MediaErr_ParaError;
|
||||
}
|
||||
uint32_t ret = 0;
|
||||
#if CODECTYPE==0
|
||||
ret = VS_Send_MusicData(dat);
|
||||
#elif CODECTYPE==1
|
||||
ret = apMicReadData(dat, (uint16_t*)len);
|
||||
#endif
|
||||
if (ret != MediaErr_NoError) {
|
||||
printf("%s,[func]%s,Send data to codec failed,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
return MediaErr_CodecError;
|
||||
} else {
|
||||
return MediaErr_NoError;
|
||||
}
|
||||
}
|
||||
|
||||
MediaErr mediaHalDataWrite(uint8_t *dat, int len)
|
||||
{
|
||||
if ((NULL == dat)
|
||||
|| (MediaState_Playing != mediaStatus)) {
|
||||
printf("%s,[func]%s,MediaState is not playing[%x]\r\n", LOGPRE, __func__, mediaStatus);
|
||||
return MediaErr_ParaError;
|
||||
}
|
||||
uint32_t ret = 0;
|
||||
#if CODECTYPE==0
|
||||
ret = VS_Send_MusicData(dat);
|
||||
#elif CODECTYPE==1
|
||||
ret = apSendData(dat, len);
|
||||
#endif
|
||||
if (ret != MediaErr_NoError) {
|
||||
printf("%s,[func]%s,Send data to codec failed,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
return MediaErr_CodecError;
|
||||
} else {
|
||||
return MediaErr_NoError;
|
||||
}
|
||||
}
|
||||
|
||||
void mediaHalReset(void)
|
||||
{
|
||||
// VS_HD_Reset();
|
||||
//VS_Soft_Reset();
|
||||
}
|
||||
|
||||
MediaErr mediaHalPlay(EspAudioMeidaType type)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
#if CODECTYPE==0
|
||||
VS_Restart_Play(); //
|
||||
VS_Reset_DecodeTime(); //
|
||||
VS_SPI_SpeedHigh();
|
||||
#else
|
||||
if ((MediaState_Initialized == mediaStatus)
|
||||
|| (MediaState_Stoped == mediaStatus)) {
|
||||
if (EspAudioMeidaType_Aac == type) {
|
||||
ret = apPlayStart("radio", sizeof("radio"), AAC_DECODER);
|
||||
} else if (EspAudioMeidaType_Mp3 == type) {
|
||||
ret = apPlayStart("radio", sizeof("radio"), MP3_DECODER);
|
||||
} else if (EspAudioMeidaType_Wav == type) {
|
||||
ret = apPlayStart("radio", sizeof("radio"), WAV_DECODER);
|
||||
} else if (EspAudioMeidaType_Flac == type) {
|
||||
ret = apPlayStart("radio", sizeof("radio"), FLAC_DECODER);
|
||||
} else if (EspAudioMeidaType_Opus == type) {
|
||||
ret = apPlayStart("radio", sizeof("radio"), OPUS_DECODER);
|
||||
} else if (EspAudioMeidaType_Pcm == type) {
|
||||
ret = apPlayStart("radio", sizeof("radio"), PCM_DECODER);
|
||||
}
|
||||
else {
|
||||
printf("%s,[func]%s,Music type[%d] does not support\r\n", LOGPRE, __func__, type);
|
||||
}
|
||||
} else {
|
||||
apPlayResume();
|
||||
}
|
||||
|
||||
printf("%s,[func]%s, mediaStatus=%d\r\n", LOGPRD, __func__, mediaStatus);
|
||||
#endif
|
||||
mediaStatus = MediaState_Playing;
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
MediaErr mediaHalPause(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
if (MediaState_Playing == mediaStatus) {
|
||||
apPlayPause();
|
||||
mediaStatus = MediaState_Paused;
|
||||
}
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
printf("%s,[func]%s,mediaStatus=%d\r\n", LOGPRD, __func__, mediaStatus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalStop(void)
|
||||
{
|
||||
|
||||
uint32_t ret = 0;
|
||||
#if CODECTYPE==0
|
||||
VS_Cancel();
|
||||
#elif CODECTYPE==1
|
||||
|
||||
apPlayStop();
|
||||
#endif
|
||||
mediaStatus = MediaState_Stoped;
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalVolumeSet(uint8_t value)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
uint32_t tmp = value;
|
||||
LOGD("volmue=%d", tmp);
|
||||
|
||||
#if CODECTYPE==0
|
||||
vsset.mvol = value;
|
||||
mediaVol = vsset.mvol;
|
||||
tmp = (value * 200) / 100 + 50;
|
||||
mediaVol = tmp;
|
||||
VS_Set_Vol(tmp); // when vs1053 does not init,this call will be hang.
|
||||
#elif CODECTYPE==1
|
||||
|
||||
ret = apVolSet(tmp);
|
||||
#endif
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalMute(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
#if CODECTYPE==0
|
||||
VS_Set_Vol(0);
|
||||
#elif CODECTYPE==1
|
||||
|
||||
ret = apVolMuteEnable();
|
||||
#endif
|
||||
mediaVol = 0;
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalStatusGet(MediaState *staus)
|
||||
{
|
||||
if (NULL == staus) {
|
||||
return MediaErr_ParaError;
|
||||
}
|
||||
*staus = mediaStatus;
|
||||
return MediaErr_NoError;
|
||||
}
|
||||
|
||||
void mediaHalSleep(void)
|
||||
{
|
||||
// GPIO_OUTPUT_SET(PA_POINT_PWR, 0);
|
||||
// GPIO_OUTPUT_SET(AP_POINT_PWR, 0);
|
||||
printf("%s mediaHal sleep\r\n", LOGPRE);
|
||||
}
|
||||
|
||||
void mediaHalWakeup(void)
|
||||
{
|
||||
// GPIO_OUTPUT_SET(PA_POINT_PWR, 1);
|
||||
// GPIO_OUTPUT_SET(AP_POINT_PWR, 1);
|
||||
printf("%s Codec wakeup\r\n", LOGPRE);
|
||||
}
|
||||
|
||||
MediaErr mediaHalDecodeTimeRest()
|
||||
{
|
||||
uint32_t ret = apRestDecodeTime();
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalDecodeTimeGet(uint32_t *time)
|
||||
{
|
||||
if (NULL == time) {
|
||||
return MediaErr_ParaError;
|
||||
}
|
||||
uint32_t ret = apGetDecodeTime((DecodeTime*)time);
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalMusicInfoGet(MusicInfo *info)
|
||||
{
|
||||
if (NULL == info) {
|
||||
return MediaErr_ParaError;
|
||||
}
|
||||
uint32_t ret = apGetInfo((SongInformation*)info);
|
||||
if (ret != OK_RESPONSE) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
ret = MediaErr_CodecError;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MediaErr mediaHalModeSet(MediaMode mode, MusicInfo* info)
|
||||
{
|
||||
MediaErr err = MediaErr_NoError;
|
||||
uint8_t ret = OK_RESPONSE;
|
||||
|
||||
|
||||
switch (mode) {
|
||||
case MediaMode_Encode:
|
||||
{
|
||||
setEnccodeInfo tmpInfo;
|
||||
memset(&tmpInfo, 0, sizeof(tmpInfo));
|
||||
ret = apSetEncodeMode();
|
||||
tmpInfo.streamDirection = 1;
|
||||
tmpInfo.numChannels = info->num_channels;
|
||||
tmpInfo.sampleRate = info->sampling_rate;
|
||||
tmpInfo.encoderType = info->stream_type; //OPUS_ENCODER;
|
||||
ret = apEncodeStart();
|
||||
ret += apSetEncodeInfo(&tmpInfo);
|
||||
LOGD("apSetEncodeInfo ret = %d %d\n", ret, tmpInfo.encoderType,
|
||||
tmpInfo.sampleRate, tmpInfo.numChannels);
|
||||
break;
|
||||
}
|
||||
case MediaMode_Decode:
|
||||
{
|
||||
setDecodeInfo tmpInfo;
|
||||
memset(&tmpInfo, 0, sizeof(tmpInfo));
|
||||
ret = apSetDecodeMode();
|
||||
tmpInfo.streamDirection = 0;
|
||||
tmpInfo.numChannels = info->num_channels;
|
||||
tmpInfo.sampleRate = info->sampling_rate;
|
||||
|
||||
ret += apSetDecodeInfo(&tmpInfo);
|
||||
LOGD("apSetDecodeInfo ret=%d\n", ret);
|
||||
|
||||
break;
|
||||
}
|
||||
case MediaMode_AuxIn:
|
||||
ret = apSetDecodeMode();
|
||||
break;
|
||||
default:
|
||||
err = MediaErr_NotSuport;
|
||||
break;
|
||||
}
|
||||
if ((ret != OK_RESPONSE) && (ERROR_OTHER!= ret)) {
|
||||
printf("%s,[func]%s,ret=%d\r\n", LOGPRE, __func__, ret);
|
||||
err = MediaErr_CodecError;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
EspAudioMeidaType checkMediaType(const char* targetUri)
|
||||
{
|
||||
EspAudioMeidaType type;
|
||||
if (EndsWith(targetUri, ".wav", 1) != 0) {
|
||||
type = EspAudioMeidaType_Wav;
|
||||
} else if (EndsWith(targetUri, ".aac", 1) != 0) {
|
||||
type = EspAudioMeidaType_Aac;
|
||||
} else if (EndsWith(targetUri, ".mp3", 1) != 0) {
|
||||
type = EspAudioMeidaType_Mp3;
|
||||
} else if (EndsWith(targetUri, ".amr", 1) != 0) {
|
||||
type = EspAudioMeidaType_Amr;
|
||||
} else if (EndsWith(targetUri, ".alac", 1) != 0) {
|
||||
type = EspAudioMeidaType_Alac;
|
||||
} else if (EndsWith(targetUri, ".flac", 1) != 0) {
|
||||
type = EspAudioMeidaType_Flac;
|
||||
} else if (EndsWith(targetUri, ".ape", 1) != 0) {
|
||||
type = EspAudioMeidaType_Ape;
|
||||
} else if (EndsWith(targetUri, ".m3u8", 1) != 0) {
|
||||
type = EspAudioMeidaType_M3u;
|
||||
} else if (EndsWith(targetUri, ".opu", 1) != 0) {
|
||||
type = EspAudioMeidaType_Opus;
|
||||
} else if (EndsWith(targetUri, ".pcm", 1) != 0) {
|
||||
type = EspAudioMeidaType_Pcm;
|
||||
} else {
|
||||
type = EspAudioMeidaType_Unknown;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// end
|
|
@ -1,15 +0,0 @@
|
|||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := include include/AP80 include/ES8388 include/driver \
|
||||
../misc/include
|
||||
|
||||
COMPONENT_SRCDIRS := AP80 ES8388 Driver test .
|
||||
|
||||
include $(IDF_PATH)/make/component_common.mk
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __AP80XX_H__
|
||||
#define __AP80XX_H__
|
||||
#include <stdint.h>
|
||||
#pragma pack (1)
|
||||
|
||||
#define CHIPTYPE 32
|
||||
|
||||
#if CHIPTYPE == 32
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
#define SPIMasterSendData spi_master_send_data
|
||||
|
||||
#define HSPICLK_OUT_MUX_IDX HSPICLK_OUT_IDX
|
||||
#define SpiNum_HSPI SPI_NUM_SPI2
|
||||
|
||||
#define AP80XXENABLEDMA 1
|
||||
#define AP80XXENABLEINT 1
|
||||
#define CALLPLAYOBJ_EN 1
|
||||
|
||||
#define SPIM_STREAM_CONTROL_GET_STATUS() (gpio_get_level(GPIO_NUM_22))
|
||||
|
||||
#elif CHIPTYPE == 31
|
||||
#define SPIM_STREAM_CONTROL_GET_STATUS() (GPIO_INPUT_GET(22))
|
||||
#endif
|
||||
|
||||
#define EAU_SYNC_BYTE 'S'
|
||||
|
||||
#define EAU_COMMAND_LENGTH (1)
|
||||
#define EAU_SYNC_WORD_LENGTH (1)
|
||||
#define EAU_CRC_VALUE_LENGTH (2)
|
||||
#define EAU_RESEND_IF_CRC_ERROR (1)
|
||||
|
||||
#define EAU_SEND_DATA_LENGTH (32 * 48)
|
||||
#define EAU_SEND_FARMA_LENGTH (32)
|
||||
#define EAU_RECV_FARMA_LENGTH (32)
|
||||
|
||||
#define OK_RESPONSE (0x00)
|
||||
//Òì³£¶¨Òå
|
||||
#define ERROR_TIME_OUT (0x01)
|
||||
#define ERROR_STREAM_FULL (0x02)
|
||||
#define ERROR_CRC (0x03)
|
||||
#define ERROR_RESPONSE (0x04)
|
||||
#define ERROR_CMD (0x05)
|
||||
#define ERROR_PARAMETER (0x06)
|
||||
#define ERROR_INIT (0x07)
|
||||
#define ERROR_OTHER (0x08)
|
||||
#define ERROR_PROMODE (0x09)
|
||||
#define ERROR_DEVICE_TIME_OUT (0x0A)
|
||||
#define ERROR_START (0x0B)
|
||||
#define ERROR_DMABUSY (0x0C)
|
||||
|
||||
#define SPIDATABUFMAXLEN (64)
|
||||
|
||||
typedef uint32_t DecodeTime;
|
||||
|
||||
typedef enum _SSPP_CMD
|
||||
{
|
||||
EAU_CMD_UNKOWN = 0,
|
||||
EAU_CMD_START,
|
||||
EAU_CMD_PAUSE,
|
||||
EAU_CMD_RESUME,
|
||||
EAU_CMD_STOP,
|
||||
EAU_CMD_MUTE,
|
||||
EAU_CMD_UNMUTE,
|
||||
EAU_CMD_DATA,
|
||||
EAU_CMD_WRITE_DATA = EAU_CMD_DATA,
|
||||
EAU_CMD_VOL_SET,
|
||||
EAU_CMD_VOL_ADD,
|
||||
EAU_CMD_VOL_SUB,
|
||||
EAU_CMD_INFO_GET,
|
||||
EAU_CMD_INFO_SET,
|
||||
EAU_CMD_TIME_REST,
|
||||
EAU_CMD_TIME_GET,
|
||||
EAU_CMD_VERSION_GET,
|
||||
EAU_CMD_ENCODE_MODE,
|
||||
EAU_CMD_DECODE_MODE,
|
||||
EAU_CMD_READ_DATA,
|
||||
EAU_CMD_LIN_SWITCH,
|
||||
EAU_CMD_MIC_SWITCH,
|
||||
EAU_CMD_ENCODE_START,
|
||||
}SSPP_CMD;
|
||||
|
||||
typedef struct _MASTERCmdContext
|
||||
{
|
||||
uint8_t SyncWord;
|
||||
uint8_t Command;
|
||||
uint16_t Content;
|
||||
uint16_t CrcValue;
|
||||
}MASTERCmdContext,EAUCmdContext;
|
||||
|
||||
typedef struct _EAUCmdResponseContext
|
||||
{
|
||||
uint8_t SyncWord;
|
||||
uint8_t Command;
|
||||
uint16_t Response;
|
||||
uint16_t CrcValue;
|
||||
}EAUCmdResponseContext;
|
||||
|
||||
|
||||
typedef struct _DataContext
|
||||
{
|
||||
uint8_t SyncWord;
|
||||
uint8_t data[EAU_SEND_DATA_LENGTH+EAU_CRC_VALUE_LENGTH];
|
||||
}EAUDataContext;
|
||||
|
||||
typedef enum __EAU_CMD_RESPONSE
|
||||
{
|
||||
EAU_CMD_RESP_UNKOWN = 0,
|
||||
EAU_CMD_RESP_OKCMD,
|
||||
EAU_CMD_RESP_ERCMD,
|
||||
EAU_CMD_RESP_OKSEND,
|
||||
EAU_CMD_RESP_RESEND,
|
||||
EAU_CMD_RESP_NEXTSEND,
|
||||
EAU_CMD_RESP_INITERROR,
|
||||
EAU_CMD_RESP_STATEERROR,
|
||||
}EAU_CMD_RESPONSE;
|
||||
|
||||
/**
|
||||
* @ly Audio encoder type Ex
|
||||
*/
|
||||
typedef enum _EncoderTypeEx
|
||||
{
|
||||
OPUS_ENCODER_EX = 1, /**< OPUS encoder */
|
||||
PCM_ENCODER_EX, /**< PCM encoder */
|
||||
} EncoderTypeEx;
|
||||
|
||||
/**
|
||||
* @ly Audio Decoder Type Set
|
||||
*/
|
||||
typedef enum _DecoderType
|
||||
{
|
||||
UNKOWN_DECODER = 0, /**< Unknown decoder */
|
||||
PURE_SOFTWARE_DECODERS = 1, /**< Pure software decoders as follows */
|
||||
WAV_DECODER, /**< WAV decoder */
|
||||
FLAC_DECODER, /**< FLAC decoder */
|
||||
AAC_DECODER, /**< AAC decoder */
|
||||
AIF_DECODER, /**< AIFF and AIFC decoder */
|
||||
ALAC_DECODER, /**< ALAC and AIFC decoder */
|
||||
OPUS_DECODER, /**< OPUS decoder */
|
||||
PCM_DECODER, /**< PCM decoder */
|
||||
WITH_HARDWARE_DECODERS = 128, /**< Decoders with hardware as follows */
|
||||
MP3_DECODER, /**< MP3 decoder */
|
||||
WMA_DECODER, /**< WAM decoder */
|
||||
SBC_DECODER, /**< SBC decoder */
|
||||
} DecoderType;
|
||||
|
||||
/**
|
||||
* @ly Song Information
|
||||
*/
|
||||
typedef struct _SongInformation
|
||||
{
|
||||
int32_t stream_type; /**< Stream type, must be in @code StreamTypeSet */
|
||||
uint32_t num_channels; /**< Number of channels */
|
||||
uint32_t sampling_rate; /**< Sampling rate, unit: Hz */
|
||||
uint32_t bitrate; /**< Bit rate, unit:bps */
|
||||
uint32_t duration; /**< Total play time, unit:ms */
|
||||
uint32_t file_size; /**< Song file size in bytes . */
|
||||
uint16_t firmware_ver; /**< AP80xx firmware version . */
|
||||
uint16_t firmware_num; /**< AP80xx firmware number . */
|
||||
uint8_t Stream_buf_is_Empty; /**< Stream_buf_is_Empty . */
|
||||
uint8_t RFU; /**< RFU . */
|
||||
} SongInformation;
|
||||
|
||||
/**
|
||||
* @ly code Information
|
||||
*/
|
||||
typedef struct _setdeccodeInfo
|
||||
{
|
||||
int32_t streamDirection; /**< Stream direction */
|
||||
uint32_t numChannels; /**< Number of channels */
|
||||
uint32_t sampleRate; /**< Bit rate, unit:bps */
|
||||
uint32_t decoderType; /**< Decoder Type:OPUS,PCM */
|
||||
uint32_t frameSize; /**< opus and pcm */
|
||||
uint32_t RFU2; /**< RFU */
|
||||
uint32_t RFU3; /**< RFU */
|
||||
uint32_t RFU4; /**< RFU */
|
||||
uint32_t RFU5; /**< RFU */
|
||||
uint32_t RFU6; /**< RFU */
|
||||
uint32_t RFU7; /**< RFU */
|
||||
} setDecodeInfo;
|
||||
|
||||
/**
|
||||
* @ly encode Information
|
||||
*/
|
||||
typedef struct _set_enccode_info
|
||||
{
|
||||
int32_t streamDirection; /**< Stream direction */
|
||||
uint32_t numChannels; /**< Number of channels */
|
||||
uint32_t sampleRate; /**< Sample rate, unit:bps */
|
||||
uint32_t encoderType; /**< Encoder Type:OPUS,PCM */
|
||||
uint32_t frameSize; /**< RFU */
|
||||
uint32_t RFU2; /**< RFU */
|
||||
uint32_t RFU3; /**< RFU */
|
||||
uint32_t RFU4; /**< RFU */
|
||||
uint32_t RFU5; /**< RFU */
|
||||
uint32_t RFU6; /**< RFU */
|
||||
uint32_t RFU7; /**< RFU */
|
||||
}setEnccodeInfo;
|
||||
|
||||
//public function
|
||||
void apInit();
|
||||
uint8_t apPlayStop(void);
|
||||
uint8_t apPlayPause(void);
|
||||
uint8_t apLinSwitch(void);
|
||||
uint8_t apMicSwitch(void);
|
||||
uint8_t apPlayResume(void);
|
||||
uint8_t apEncodeStart(void);
|
||||
uint8_t apVolSet(uint16_t vol);
|
||||
uint8_t apSetEncodeMode(void);
|
||||
uint8_t apSetDecodeMode(void);
|
||||
uint8_t apVolMuteEnable(void);
|
||||
uint8_t apVolMuteDisable(void);
|
||||
uint8_t apRestDecodeTime(void);
|
||||
uint8_t apSetWaitTime(uint32_t waitTime);
|
||||
uint8_t apGetDecodeTime(DecodeTime *time);
|
||||
uint8_t apGetInfo(SongInformation *songInfo);
|
||||
uint8_t apSetDecodeInfo(setDecodeInfo *decodeInfo);
|
||||
uint8_t apSetEncodeInfo(setEnccodeInfo *encodeInfo);
|
||||
uint8_t apSendData(uint8_t *sendData, uint16_t sendLen);
|
||||
uint8_t apMicReadData(uint8_t *readData, uint16_t *readLen);
|
||||
uint8_t apPlayStart(const char *songFileName, uint8_t len, DecoderType decType);
|
||||
|
||||
//private function
|
||||
void audio_test_main();
|
||||
void mic_test();
|
||||
void audio_test_main();
|
||||
void apSetResponse(bool responseEnable);
|
||||
void printfByteS(uint8_t *indata, uint16_t len);
|
||||
|
||||
#endif // __AP80XX_H__
|
|
@ -1,28 +0,0 @@
|
|||
/**
|
||||
**************************************************************************************
|
||||
* @file crc.h
|
||||
* @brief Calculate CRC Value
|
||||
*
|
||||
* @author Aissen Li
|
||||
* @version V1.0.0
|
||||
*
|
||||
* © Shanghai Mountain View Silicon Technology Co.,Ltd. All rights reserved.
|
||||
**************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __CRC_H__
|
||||
#define __CRC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif//__cplusplus
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint16_t GetCRC16NBS(uint8_t* data, uint32_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif//__cplusplus
|
||||
|
||||
#endif//__CRC_H__
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef __ES8388_H
|
||||
#define __ES8388_H
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#define ES7154_Address 0x00
|
||||
#define ES7242_Address1 0x20
|
||||
#define ES7242_Address2 0x22
|
||||
#define ES7242_Address3 0x24
|
||||
#define ES7242_Address4 0x26
|
||||
|
||||
void ES7242_init(void);
|
||||
void ES7242_Poweron_Init(void);
|
||||
//void ES8388_DAC_Play(void);
|
||||
//void ES8388_ALC(void);
|
||||
void ES7242_ADC_Record(void);
|
||||
void ES7242_ADC_StandBy(void);
|
||||
static bool I2C_Write_Byte(uint8_t data, uint8_t iter);
|
||||
void ES7242_WriteReg(uint8_t slave_add, uint8_t reg_add, uint8_t data);
|
||||
uint8_t ES7242_ReadReg(uint8_t slave_add, uint8_t reg_add, uint8_t dat);
|
||||
void I2C_MasterInit(uint8_t init_num);
|
||||
void i2c_master_read_test();
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
#ifndef __ES8388_H
|
||||
#define __ES8388_H
|
||||
#include "esp_types.h"
|
||||
|
||||
#define ES8388_CONTROL1 0x00
|
||||
#define ES8388_CONTROL2 0x01
|
||||
|
||||
#define ES8388_CHIPPOWER 0x02
|
||||
|
||||
#define ES8388_ADCPOWER 0x03
|
||||
#define ES8388_DACPOWER 0x04
|
||||
|
||||
#define ES8388_CHIPLOPOW1 0x05
|
||||
#define ES8388_CHIPLOPOW2 0x06
|
||||
|
||||
#define ES8388_ANAVOLMANAG 0x07
|
||||
|
||||
#define ES8388_MASTERMODE 0x08
|
||||
|
||||
#define ES8388_ADCCONTROL1 0x09
|
||||
#define ES8388_ADCCONTROL2 0x0a
|
||||
#define ES8388_ADCCONTROL3 0x0b
|
||||
#define ES8388_ADCCONTROL4 0x0c
|
||||
#define ES8388_ADCCONTROL5 0x0d
|
||||
#define ES8388_ADCCONTROL6 0x0e
|
||||
#define ES8388_ADCCONTROL7 0x0f
|
||||
#define ES8388_ADCCONTROL8 0x10
|
||||
#define ES8388_ADCCONTROL9 0x11
|
||||
#define ES8388_ADCCONTROL10 0x12
|
||||
#define ES8388_ADCCONTROL11 0x13
|
||||
#define ES8388_ADCCONTROL12 0x14
|
||||
#define ES8388_ADCCONTROL13 0x15
|
||||
#define ES8388_ADCCONTROL14 0x16
|
||||
|
||||
#define ES8388_DACCONTROL1 0x17
|
||||
#define ES8388_DACCONTROL2 0x18
|
||||
#define ES8388_DACCONTROL3 0x19
|
||||
#define ES8388_DACCONTROL4 0x1a
|
||||
#define ES8388_DACCONTROL5 0x1b
|
||||
#define ES8388_DACCONTROL6 0x1c
|
||||
#define ES8388_DACCONTROL7 0x1d
|
||||
#define ES8388_DACCONTROL8 0x1e
|
||||
#define ES8388_DACCONTROL9 0x1f
|
||||
#define ES8388_DACCONTROL10 0x20
|
||||
#define ES8388_DACCONTROL11 0x21
|
||||
#define ES8388_DACCONTROL12 0x22
|
||||
#define ES8388_DACCONTROL13 0x23
|
||||
#define ES8388_DACCONTROL14 0x24
|
||||
#define ES8388_DACCONTROL15 0x25
|
||||
#define ES8388_DACCONTROL16 0x26
|
||||
#define ES8388_DACCONTROL17 0x27
|
||||
#define ES8388_DACCONTROL18 0x28
|
||||
#define ES8388_DACCONTROL19 0x29
|
||||
#define ES8388_DACCONTROL20 0x2a
|
||||
#define ES8388_DACCONTROL21 0x2b
|
||||
#define ES8388_DACCONTROL22 0x2c
|
||||
#define ES8388_DACCONTROL23 0x2d
|
||||
#define ES8388_DACCONTROL24 0x2e
|
||||
#define ES8388_DACCONTROL25 0x2f
|
||||
#define ES8388_DACCONTROL26 0x30
|
||||
#define ES8388_DACCONTROL27 0x31
|
||||
#define ES8388_DACCONTROL28 0x32
|
||||
#define ES8388_DACCONTROL29 0x33
|
||||
#define ES8388_DACCONTROL30 0x34
|
||||
|
||||
#define Vol 0x0F
|
||||
|
||||
|
||||
void ES8388_init(void);
|
||||
void ES8388_PowerOn_Init(void);
|
||||
void ES8388_DAC_Play(void);
|
||||
void ES8388_ALC(void);
|
||||
void ES8388_ADC_Record(void);
|
||||
void ES8388_ADC_StandBy(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __MEDIAHAL_H__
|
||||
#define __MEDIAHAL_H__
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define AP_POINT_PWR 26 // GPIO26 AP8048
|
||||
#define PA_POINT_PWR 25 // GPIO25
|
||||
|
||||
typedef enum {
|
||||
MediaState_Initialized = 0, /* codec is initialized */
|
||||
MediaState_Stoped, /* codec is stoped */
|
||||
MediaState_Transit, /* codec is busy in a transition */
|
||||
MediaState_Playing, /* codec is currently playing */
|
||||
MediaState_Paused, /* codec is in the paused state for playback */
|
||||
MediaState_Ended, /* codec finished decoding media, media has stopped without user request. */
|
||||
MediaState_Error, /* codec was given a URI that could not be played */
|
||||
|
||||
MediaState_Unknow /* unknown playstate */
|
||||
}MediaState;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EspAudioMeidaType_Unknown = 0,
|
||||
EspAudioMeidaType_Wav,
|
||||
EspAudioMeidaType_Aac,
|
||||
EspAudioMeidaType_Mp3,
|
||||
EspAudioMeidaType_Amr,
|
||||
EspAudioMeidaType_Alac,
|
||||
EspAudioMeidaType_Flac,
|
||||
EspAudioMeidaType_Ape,
|
||||
EspAudioMeidaType_M3u,
|
||||
EspAudioMeidaType_Opus,
|
||||
EspAudioMeidaType_Pcm,
|
||||
EspAudioMeidaType_Max,
|
||||
}EspAudioMeidaType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
MediaErr_NoError = 0,
|
||||
MediaErr_ParaError,
|
||||
MediaErr_CodecInitFailed,
|
||||
MediaErr_CodecError,
|
||||
MediaErr_NotSuport,
|
||||
} MediaErr;
|
||||
|
||||
typedef enum {
|
||||
MediaMode_Decode = 0,
|
||||
MediaMode_Encode = 1,
|
||||
MediaMode_AuxIn = 2,
|
||||
MediaMode_Max = 3,
|
||||
} MediaMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t stream_type; /**< Stream type, must be in @code StreamTypeSet */
|
||||
uint32_t num_channels; /**< Number of channels */
|
||||
uint32_t sampling_rate; /**< Sampling rate, unit: Hz */
|
||||
uint32_t bitrate; /**< Bit rate, unit:bps */
|
||||
uint32_t duration; /**< Total play time, unit:ms */
|
||||
uint32_t file_size; /**< Song file size in bytes . */
|
||||
uint16_t firmware_ver; /**< AP80xx firmware version . */
|
||||
uint16_t firmware_num; /**< AP80xx firmware number . */
|
||||
uint8_t bufEmpty; /**< Stream_buf_is_Empty . */
|
||||
uint8_t RFU; /**< RFU . */
|
||||
|
||||
} MusicInfo;
|
||||
|
||||
void mediaHalInit();
|
||||
MediaErr mediaHalDataWrite(uint8_t *dat, int len);
|
||||
MediaErr mediaHalDataRead(uint8_t *dat, int *len);
|
||||
|
||||
MediaErr mediaHalPlay(EspAudioMeidaType type);
|
||||
MediaErr mediaHalPause(void);
|
||||
MediaErr mediaHalStop(void);
|
||||
void mediaHalReset(void);
|
||||
MediaErr mediaHalVolumeSet(uint8_t value);
|
||||
MediaErr mediaHalMute(void);
|
||||
MediaErr mediaHalStatusGet(MediaState *staus);
|
||||
void mediaHalSleep(void);
|
||||
void mediaHalWakeup(void);
|
||||
MediaErr mediaHalModeSet(MediaMode mode, MusicInfo* info);
|
||||
|
||||
|
||||
MediaErr mediaHalDecodeTimeRest(void);
|
||||
MediaErr mediaHalDecodeTimeGet(uint32_t *time);
|
||||
MediaErr mediaHalMusicInfoGet(MusicInfo *info);
|
||||
|
||||
EspAudioMeidaType checkMediaType(const char* targetUri);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MEDIAHAL_H__
|
|
@ -1,127 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _DRIVER_DMA_H_
|
||||
#define _DRIVER_DMA_H__
|
||||
#include <esp_types.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup Driver_APIs Driver APIs
|
||||
* @brief Driver APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup Driver_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA queue description.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t block_size: 12;
|
||||
uint32_t data_length: 12;
|
||||
uint32_t unused: 5;
|
||||
uint32_t sub_sof: 1;
|
||||
uint32_t eof: 1;
|
||||
uint32_t owner: 1;
|
||||
uint32_t buf_ptr;
|
||||
uint32_t next_link_ptr;
|
||||
} dma_queue_t;
|
||||
|
||||
/**
|
||||
* @brief DMA element description
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t *buffer_addr;
|
||||
dma_queue_t *first_queue;
|
||||
dma_queue_t *last_queue;
|
||||
dma_queue_t backup_queue;
|
||||
} dma_element_t;
|
||||
|
||||
/**
|
||||
* @brief DMA ping-pong buffer object description
|
||||
*/
|
||||
typedef struct {
|
||||
dma_element_t *ping;
|
||||
dma_element_t *pong;
|
||||
uint32_t len;
|
||||
uint32_t queue_cnt;
|
||||
} ping_pong_buf_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a ping-pong buffer object used by DMA.
|
||||
*
|
||||
* @param [in] bufLen
|
||||
* Set the buffer length.
|
||||
* --------------------
|
||||
* | ping | Pong |
|
||||
* --------------------
|
||||
* | bufLen | bufLen |
|
||||
* --------------------
|
||||
*
|
||||
* @return uint32*, NULL:indicates parameter error, others indicates ping-pong buffer address.
|
||||
*/
|
||||
ping_pong_buf_t* dma_buf_create(uint32_t bufLen);
|
||||
|
||||
/**
|
||||
* @brief Reset the dma buffer length.
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct ping_pong_buf_t that indicates the object length to be reset to bufLen.
|
||||
*
|
||||
* @return uint32*, ESP_FAIL:indicates parameter error, ESP_OK :indicates success.
|
||||
*/
|
||||
esp_err_t dma_buf_len_reset(ping_pong_buf_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Set the buffer length before the start.
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t.
|
||||
* @param [in] len
|
||||
* Set the transmit length .
|
||||
*
|
||||
* @return uint32*, ESP_FAIL:indicates parameter error, ESP_OK: indicates success.
|
||||
*/
|
||||
esp_err_t dma_buf_len_set(ping_pong_buf_t *obj, dma_element_t *element, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Destroy the ping-pong buffer instance.
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct ping_pong_buf_t that indicates the object to be destroy.
|
||||
*
|
||||
* @return NULL
|
||||
*/
|
||||
void dma_buf_destroy(ping_pong_buf_t *obj);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __DMA_H__
|
|
@ -1,166 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _DRIVER_I2C_H_
|
||||
#define _DRIVER_I2C_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "soc/i2c_reg.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
||||
#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
|
||||
#define I2C_APB_CLK_FREQ APB_CLK_FREQ
|
||||
#define I2C_COMD_REG(i2c_no, cmd_no) (I2C_COMD0_REG(i2c_no)+ (cmd_no)*4 )
|
||||
#define I2C_COMMAND_DONE (BIT(31))
|
||||
#define I2C_COMMAND_DONE_M (BIT(31))
|
||||
#define I2C_COMMAND_DONE_V 0x1
|
||||
#define I2C_COMMAND_DONE_S 31
|
||||
#define I2C_COMMAND_OP_CODE 0x7
|
||||
#define I2C_COMMAND_OP_CODE_M ((I2C_COMMAND_OP_CODE_V)<<(I2C_COMMAND_OP_CODE_S))
|
||||
#define I2C_COMMAND_OP_CODE_V 0x7
|
||||
#define I2C_COMMAND_OP_CODE_S 11
|
||||
#define I2C_COMMAND_ACK_VALUE (BIT(10))
|
||||
#define I2C_COMMAND_ACK_VALUE_M (BIT(10))
|
||||
#define I2C_COMMAND_ACK_VALUE_V 0x1
|
||||
#define I2C_COMMAND_ACK_VALUE_S 10
|
||||
#define I2C_COMMAND_ACK_EXP (BIT(9))
|
||||
#define I2C_COMMAND_ACK_EXP_M (BIT(9))
|
||||
#define I2C_COMMAND_ACK_EXP_V 0x1
|
||||
#define I2C_COMMAND_ACK_EXP_S 9
|
||||
#define I2C_COMMAND_ACK_EN (BIT(8))
|
||||
#define I2C_COMMAND_ACK_EN_M (BIT(8))
|
||||
#define I2C_COMMAND_ACK_EN_V 0x1
|
||||
#define I2C_COMMAND_ACK_EN_S 8
|
||||
#define I2C_COMMAND_BYTE_NUM 0xff
|
||||
#define I2C_COMMAND_BYTE_NUM_M 0xff
|
||||
#define I2C_COMMAND_BYTE_NUM_V 0xff
|
||||
#define I2C_COMMAND_BYTE_NUM_S 0
|
||||
|
||||
typedef enum{
|
||||
I2C_SLAVE_MODE = 0,
|
||||
I2C_MASTER_MODE,
|
||||
}enum_i2c_mode_t;
|
||||
|
||||
typedef enum{
|
||||
I2C_CMD_RESTART = 0,
|
||||
I2C_CMD_WRITE,
|
||||
I2C_CMD_READ,
|
||||
I2C_CMD_STOP,
|
||||
I2C_CMD_END
|
||||
}enum_cmd_opcode_t;
|
||||
|
||||
typedef enum{
|
||||
I2C0 = 0, // 0x3ff53000
|
||||
I2C1 , // 0x3ff67000
|
||||
I2C_MAX
|
||||
} enum_i2c_port_t;
|
||||
|
||||
typedef struct{
|
||||
enum_i2c_mode_t mode;
|
||||
uint8_t addr_10bit_en;
|
||||
uint16_t slave_addr;
|
||||
uint32_t clk_speed;
|
||||
}i2c_config_t;
|
||||
|
||||
typedef struct{
|
||||
uint8_t byte_num;
|
||||
uint8_t ack_en;
|
||||
uint8_t ack_exp;
|
||||
uint8_t ack_val;
|
||||
enum_cmd_opcode_t op_code;
|
||||
}i2c_cmd_def_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset I2C tx fifo, flush the data in tx fifo.
|
||||
*
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_reset_tx_fifo(enum_i2c_port_t i2c_no );
|
||||
|
||||
/**
|
||||
* @brief Fill the tx fifo with the given data bytes
|
||||
*
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
* @param uint8_t *data : pointer to the data buffer
|
||||
* @param uint8_t len : data length of the data
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_tx_fifo_push(enum_i2c_port_t i2c_no,uint8_t *data , uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Reset I2C rx fifo, flush the data in rx fifo.
|
||||
*
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_reset_rx_fifo(enum_i2c_port_t i2c_no);
|
||||
|
||||
/**
|
||||
* @brief Fill the tx fifo with the given data bytes
|
||||
*
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
* @param uint8_t cmd_idx : i2c command index(at most 16 commands one time)
|
||||
* @param i2c_cmd_def_t* cmd : command definition.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_config_cmd(enum_i2c_port_t i2c_no,uint8_t cmd_idx, i2c_cmd_def_t* cmd);
|
||||
|
||||
/**
|
||||
* @brief Start sending data to i2c bus.The data is defined in the command registers.Stop when there is a "STOP" command
|
||||
*
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_start(enum_i2c_port_t i2c_no);
|
||||
|
||||
/**
|
||||
* @brief Set and initialize i2c params
|
||||
*
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
* @param i2c_config_t* i2c_conf : i2c setting param struct
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_init( enum_i2c_port_t i2c_no, i2c_config_t* i2c_conf);
|
||||
|
||||
/**
|
||||
* @brief Set and initialize i2c interruption handler
|
||||
*
|
||||
* @param uint8_t cpu_num : CPU number (PRO_CPU_NUM or APP_CPU_NUM)
|
||||
* @param enum_i2c_port_t i2c_no : I2C port num (I2C0 or I2C1)
|
||||
* @param uint8_t i2c_intr_num : i2c interrupt number, set this value according to interrupt cpu using table, Please see the core-isa.h
|
||||
* @param void (* fn)(void* ) : i2c interrupt handler
|
||||
* @param void * arg : param pointer of i2c interrupt handler
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_intr_register(uint8_t cpu_num,enum_i2c_port_t i2c_no,uint8_t i2c_intr_num,void (* fn)(void* ),void * arg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_DRIVER_I2C_H_*/
|
|
@ -1,193 +0,0 @@
|
|||
#ifndef __I2C_MASTER_H__
|
||||
#define __I2C_MASTER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_types.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#if 0
|
||||
#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_MTMS_U
|
||||
#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_MTDO_U
|
||||
#define I2C_MASTER_SDA_GPIO 14
|
||||
#define I2C_MASTER_SCL_GPIO 15
|
||||
#define I2C_MASTER_SDA_FUNC FUNC_MTMS_GPIO14
|
||||
#define I2C_MASTER_SCL_FUNC FUNC_MTDO_GPIO15
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO26_U
|
||||
#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_GPIO27_U
|
||||
#define I2C_MASTER_SDA_GPIO 26
|
||||
#define I2C_MASTER_SDA_PIN GPIO_Pin_26
|
||||
|
||||
#define I2C_MASTER_SCL_PIN GPIO_Pin_27
|
||||
#define I2C_MASTER_SCL_GPIO 27
|
||||
#define I2C_MASTER_SDA_FUNC FUNC_GPIO26_GPIO26
|
||||
#define I2C_MASTER_SCL_FUNC FUNC_GPIO27_GPIO27
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
|
||||
#define I2C_MASTER_SDA_GPIO 21
|
||||
#define I2C_MASTER_SDA_PIN GPIO_SEL_21
|
||||
|
||||
#define I2C_MASTER_SCL_PIN GPIO_SEL_19
|
||||
#define I2C_MASTER_SCL_GPIO 19
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO23_U
|
||||
#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_GPIO5_U
|
||||
#define I2C_MASTER_SDA_GPIO 23
|
||||
#define I2C_MASTER_SDA_PIN GPIO_Pin_23
|
||||
|
||||
#define I2C_MASTER_SCL_PIN GPIO_Pin_5
|
||||
#define I2C_MASTER_SCL_GPIO 5
|
||||
#define I2C_MASTER_SDA_FUNC FUNC_GPIO23_GPIO23
|
||||
#define I2C_MASTER_SCL_FUNC FUNC_GPIO5_GPIO5
|
||||
#endif
|
||||
|
||||
#define I2C_MASTER_SDA_HIGH_SCL_HIGH() \
|
||||
gpio_set_level(I2C_MASTER_SDA_GPIO,1);\
|
||||
gpio_set_level(I2C_MASTER_SCL_GPIO,1);
|
||||
|
||||
#define I2C_MASTER_SDA_HIGH_SCL_LOW() \
|
||||
gpio_set_level(I2C_MASTER_SDA_GPIO,1);\
|
||||
gpio_set_level(I2C_MASTER_SCL_GPIO,0);
|
||||
|
||||
#define I2C_MASTER_SDA_LOW_SCL_HIGH() \
|
||||
gpio_set_level(I2C_MASTER_SDA_GPIO,0);\
|
||||
gpio_set_level(I2C_MASTER_SCL_GPIO,1);
|
||||
|
||||
#define I2C_MASTER_SDA_LOW_SCL_LOW() \
|
||||
gpio_set_level(I2C_MASTER_SDA_GPIO,0);\
|
||||
gpio_set_level(I2C_MASTER_SCL_GPIO,0);
|
||||
|
||||
/** \defgroup Driver_APIs Driver APIs
|
||||
* @brief Driver APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup Driver_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \defgroup I2C_Driver_APIs I2C_MASTER Driver APIs
|
||||
* @brief UART driver APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_MASTER_Driver_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief i2c_master_gpio_init,config SDA and SCL gpio to open-drain output mode.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_gpio_init(void);
|
||||
|
||||
/**
|
||||
* @brief i2c_master_gpio_init,config SDA and SCL gpio to open-drain output mode.
|
||||
*
|
||||
* @param initilize I2C bus to enable i2c operations.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_init(void);
|
||||
|
||||
#define i2c_master_wait ets_delay_us
|
||||
|
||||
|
||||
/**
|
||||
* @brief i2c_master_gpio_init,config SDA and SCL gpio to open-drain output mode.
|
||||
*
|
||||
* @param set i2c to stop sending state.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_stop(void);
|
||||
|
||||
/**
|
||||
* @brief i2c_master_gpio_init,config SDA and SCL gpio to open-drain output mode.
|
||||
*
|
||||
* @param set i2c to start sending state.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_start(void);
|
||||
|
||||
/**
|
||||
* @brief i2c_master_gpio_init,config SDA and SCL gpio to open-drain output mode.
|
||||
*
|
||||
* @param set ack to i2c bus as level value.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_setAck(uint8_t level);
|
||||
|
||||
/**
|
||||
* @brief confirm if peer send ack.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
uint8_t i2c_master_getAck(void);
|
||||
|
||||
/**
|
||||
* @brief read Byte from i2c bus.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return the byte which read from i2c bus.
|
||||
*/
|
||||
uint8_t i2c_master_readByte(void);
|
||||
|
||||
/**
|
||||
* @brief write wrdata value(one byte) into i2c.
|
||||
*
|
||||
* @param uint8_t wrdata:write value
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_writeByte(uint8_t wrdata);
|
||||
|
||||
/**
|
||||
* @brief i2c_master_checkAck.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return the result of check ack
|
||||
*/
|
||||
bool i2c_master_checkAck(void);
|
||||
|
||||
/**
|
||||
* @brief i2c master send Ack.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_send_ack(void);
|
||||
|
||||
/**
|
||||
* @brief i2c master send Nack.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void i2c_master_send_nack(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -1,419 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _DRIVER_II2C_STRUCT_H_
|
||||
#define _DRIVER_II2C_STRUCT_H_
|
||||
|
||||
|
||||
typedef struct I2C_DEV{
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_low_period: 14;
|
||||
unsigned int reserved14: 18;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_LOW_PERIOD;
|
||||
union {
|
||||
struct {
|
||||
unsigned int sda_force_out: 1;
|
||||
unsigned int scl_force_out: 1;
|
||||
unsigned int sample_scl_level: 1;
|
||||
unsigned int reserved3: 1;
|
||||
unsigned int ms_mode: 1;
|
||||
unsigned int trans_start: 1;
|
||||
unsigned int tx_lsb_first: 1;
|
||||
unsigned int rx_lsb_first: 1;
|
||||
unsigned int clk_en: 1;
|
||||
unsigned int reserved9: 23;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} CTR;
|
||||
union {
|
||||
struct {
|
||||
unsigned int ack_rec: 1;
|
||||
unsigned int slave_rw: 1;
|
||||
unsigned int time_out: 1;
|
||||
unsigned int arb_lost: 1;
|
||||
unsigned int bus_busy: 1;
|
||||
unsigned int slave_addressed: 1;
|
||||
unsigned int byte_trans: 1;
|
||||
unsigned int reserved7: 1;
|
||||
unsigned int rxfifo_cnt: 6;
|
||||
unsigned int reserved14: 4;
|
||||
unsigned int txfifo_cnt: 6;
|
||||
unsigned int scl_main_state_last: 3;
|
||||
unsigned int reserved27: 1;
|
||||
unsigned int scl_state_last: 3;
|
||||
unsigned int reserved31: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SR;
|
||||
union {
|
||||
struct {
|
||||
unsigned int time_out_reg: 20;
|
||||
unsigned int reserved20: 12;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} TO;
|
||||
union {
|
||||
struct {
|
||||
unsigned int slave_addr: 15;
|
||||
unsigned int reserved15: 16;
|
||||
unsigned int addr_10bit_en: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SLAVE_ADDR;
|
||||
union {
|
||||
struct {
|
||||
unsigned int rxfifo_start_addr: 5;
|
||||
unsigned int rxfifo_end_addr: 5;
|
||||
unsigned int txfifo_start_addr: 5;
|
||||
unsigned int txfifo_end_addr: 5;
|
||||
unsigned int reserved20: 12;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} RXFIFO_ST;
|
||||
union {
|
||||
struct {
|
||||
unsigned int rxfifo_full_thrhd: 5;
|
||||
unsigned int txfifo_empty_thrhd: 5;
|
||||
unsigned int nonfifo_en: 1;
|
||||
unsigned int fifo_addr_cfg_en: 1;
|
||||
unsigned int rx_fifo_rst: 1;
|
||||
unsigned int tx_fifo_rst: 1;
|
||||
unsigned int nonfifo_rx_thres: 6;
|
||||
unsigned int nonfifo_tx_thres: 6;
|
||||
unsigned int reserved26: 6;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_FIFO_CONF;
|
||||
union {
|
||||
struct {
|
||||
unsigned int fifo_data: 8;
|
||||
unsigned int reserved8: 24;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_DATA;
|
||||
union {
|
||||
struct {
|
||||
unsigned int rxfifo_full_int_raw: 1;
|
||||
unsigned int txfifo_empty_int_raw: 1;
|
||||
unsigned int rxfifo_ovf_int_raw: 1;
|
||||
unsigned int end_detect_int_raw: 1;
|
||||
unsigned int slave_tran_comp_int_raw: 1;
|
||||
unsigned int arbitration_lost_int_raw: 1;
|
||||
unsigned int master_tran_comp_int_raw: 1;
|
||||
unsigned int trans_complete_int_raw: 1;
|
||||
unsigned int time_out_int_raw: 1;
|
||||
unsigned int trans_start_int_raw: 1;
|
||||
unsigned int ack_err_int_raw: 1;
|
||||
unsigned int rx_rec_full_int_raw: 1;
|
||||
unsigned int tx_send_empty_int_raw: 1;
|
||||
unsigned int reserved13: 19;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_INT_RAW;
|
||||
union {
|
||||
struct {
|
||||
unsigned int rxfifo_full_int_clr: 1;
|
||||
unsigned int txfifo_empty_int_clr: 1;
|
||||
unsigned int rxfifo_ovf_int_clr: 1;
|
||||
unsigned int end_detect_int_clr: 1;
|
||||
unsigned int slave_tran_comp_int_clr: 1;
|
||||
unsigned int arbitration_lost_int_clr: 1;
|
||||
unsigned int master_tran_comp_int_clr: 1;
|
||||
unsigned int trans_complete_int_clr: 1;
|
||||
unsigned int time_out_int_clr: 1;
|
||||
unsigned int trans_start_int_clr: 1;
|
||||
unsigned int ack_err_int_clr: 1;
|
||||
unsigned int rx_rec_full_int_clr: 1;
|
||||
unsigned int tx_send_empty_int_clr: 1;
|
||||
unsigned int reserved13: 19;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_INT_CLR;
|
||||
union {
|
||||
struct {
|
||||
unsigned int rxfifo_full_int_ena: 1;
|
||||
unsigned int txfifo_empty_int_ena: 1;
|
||||
unsigned int rxfifo_ovf_int_ena: 1;
|
||||
unsigned int end_detect_int_ena: 1;
|
||||
unsigned int slave_tran_comp_int_ena: 1;
|
||||
unsigned int arbitration_lost_int_ena: 1;
|
||||
unsigned int master_tran_comp_int_ena: 1;
|
||||
unsigned int trans_complete_int_ena: 1;
|
||||
unsigned int time_out_int_ena: 1;
|
||||
unsigned int trans_start_int_ena: 1;
|
||||
unsigned int ack_err_int_ena: 1;
|
||||
unsigned int rx_rec_full_int_ena: 1;
|
||||
unsigned int tx_send_empty_int_ena: 1;
|
||||
unsigned int reserved13: 19;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_INT_ENA;
|
||||
union {
|
||||
struct {
|
||||
unsigned int rxfifo_full_int_st: 1;
|
||||
unsigned int txfifo_empty_int_st: 1;
|
||||
unsigned int rxfifo_ovf_int_st: 1;
|
||||
unsigned int end_detect_int_st: 1;
|
||||
unsigned int slave_tran_comp_int_st: 1;
|
||||
unsigned int arbitration_lost_int_st: 1;
|
||||
unsigned int master_tran_comp_int_st: 1;
|
||||
unsigned int trans_complete_int_st: 1;
|
||||
unsigned int time_out_int_st: 1;
|
||||
unsigned int trans_start_int_st: 1;
|
||||
unsigned int ack_err_int_st: 1;
|
||||
unsigned int rx_rec_full_int_st: 1;
|
||||
unsigned int tx_send_empty_int_st: 1;
|
||||
unsigned int reserved13: 19;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_INT_STATUS;
|
||||
union {
|
||||
struct {
|
||||
unsigned int sda_hold_time: 10;
|
||||
unsigned int reserved10: 22;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SDA_HOLD;
|
||||
union {
|
||||
struct {
|
||||
unsigned int sda_sample_time: 10;
|
||||
unsigned int reserved10: 22;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SDA_SAMPLE;
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_high_period: 14;
|
||||
unsigned int reserved14: 18;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_HIGH_PERIOD;
|
||||
uint32_t reserved_3c;
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_start_hold_time: 10;
|
||||
unsigned int reserved10: 22;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_START_HOLD;
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_rstart_setup_time: 10;
|
||||
unsigned int reserved10: 22;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_RSTART_SETUP;
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_stop_hold_time: 14;
|
||||
unsigned int reserved14: 18;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_STOP_HOLD;
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_stop_setup_time: 10;
|
||||
unsigned int reserved10: 22;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_STOP_SETUP;
|
||||
union {
|
||||
struct {
|
||||
unsigned int scl_filter_thres: 3;
|
||||
unsigned int scl_filter_en: 1;
|
||||
unsigned int reserved4: 28;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SCL_FILTER_CFG;
|
||||
union {
|
||||
struct {
|
||||
unsigned int sda_filter_thres: 3;
|
||||
unsigned int sda_filter_en: 1;
|
||||
unsigned int reserved4: 28;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} SDA_FILTER_CFG;
|
||||
union {
|
||||
struct {
|
||||
//unsigned int command: 14;
|
||||
unsigned int command_byte_num: 8;
|
||||
unsigned int command_ack_en: 1;
|
||||
unsigned int command_ack_exp: 1;
|
||||
unsigned int command_ack_val: 1;
|
||||
unsigned int command_op_code: 3;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD[16];
|
||||
#if 0
|
||||
union {
|
||||
struct {
|
||||
unsigned int command1: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command1_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD1;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command2: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command2_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD2;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command3: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command3_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD3;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command4: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command4_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD4;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command5: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command5_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD5;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command6: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command6_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD6;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command7: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command7_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD7;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command8: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command8_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD8;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command9: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command9_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD9;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command10: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command10_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD10;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command11: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command11_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD11;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command12: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command12_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD12;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command13: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command13_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD13;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command14: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command14_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD14;
|
||||
union {
|
||||
struct {
|
||||
unsigned int command15: 14;
|
||||
unsigned int reserved14: 17;
|
||||
unsigned int command15_done: 1;
|
||||
} fld;
|
||||
uint32_t val;
|
||||
} I2C_COMD15;
|
||||
#endif
|
||||
uint32_t reserved_98;
|
||||
uint32_t reserved_9c;
|
||||
uint32_t reserved_a0;
|
||||
uint32_t reserved_a4;
|
||||
uint32_t reserved_a8;
|
||||
uint32_t reserved_ac;
|
||||
uint32_t reserved_b0;
|
||||
uint32_t reserved_b4;
|
||||
uint32_t reserved_b8;
|
||||
uint32_t reserved_bc;
|
||||
uint32_t reserved_c0;
|
||||
uint32_t reserved_c4;
|
||||
uint32_t reserved_c8;
|
||||
uint32_t reserved_cc;
|
||||
uint32_t reserved_d0;
|
||||
uint32_t reserved_d4;
|
||||
uint32_t reserved_d8;
|
||||
uint32_t reserved_dc;
|
||||
uint32_t reserved_e0;
|
||||
uint32_t reserved_e4;
|
||||
uint32_t reserved_e8;
|
||||
uint32_t reserved_ec;
|
||||
uint32_t reserved_f0;
|
||||
uint32_t reserved_f4;
|
||||
//struct {
|
||||
// uint32_t val;
|
||||
//}I2C_DATE;
|
||||
uint32_t reserved_fc;
|
||||
//struct {
|
||||
// uint32_t val;
|
||||
//}I2C_FIFO_START_ADDR;
|
||||
}I2C_TypeDef;
|
||||
|
||||
|
||||
#endif
|
|
@ -1,443 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef _DRIVER_I2S_H_
|
||||
#define _DRIVER_I2S_H_
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include <stdint.h>
|
||||
#include "dma.h"
|
||||
#include "soc/soc.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#define ETS_I2S0_INUM 17
|
||||
#define ETS_I2S1_INUM 17
|
||||
|
||||
#define ESP_I2S1_INTR_ATTACH(func, arg) \
|
||||
xt_set_interrupt_handler(ETS_I2S1_INUM, (func), (void *)(arg))
|
||||
|
||||
#define ESP_I2S0_INTR_ENABLE() \
|
||||
ESP_INTR_ENABLE(ETS_I2S0_INUM)
|
||||
|
||||
#define ESP_I2S0_INTR_DISABLE() \
|
||||
ESP_INTR_DISABLE(ETS_I2S0_INUM)
|
||||
|
||||
#define ESP_I2S1_INTR_ENABLE() \
|
||||
ESP_INTR_ENABLE(ETS_I2S1_INUM)
|
||||
|
||||
#define ESP_I2S1_INTR_DISABLE() \
|
||||
ESP_INTR_DISABLE(ETS_I2S1_INUM)
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup Driver_APIs Driver APIs
|
||||
* @brief Driver APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup Driver_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \defgroup I2S_Driver_APIs I2S Driver APIs
|
||||
* @brief I2S driver APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_Driver_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
// ena:1 enable audio pll;
|
||||
// 0 disable audio pll;
|
||||
// freq = (xtal * (sdm2 + 4))/((o_div+2)*2)
|
||||
// xtal is 40M/26M
|
||||
// (xtal * (sdm2 + 4)):240 ~ 600MHz
|
||||
// o_div : 0 ~ 31
|
||||
void rtc_plla_ena(uint8_t ena, uint32_t sdm2, uint32_t o_div);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Two I2S module.I2S0 has support pdm.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_NUM_I2S0 = 0x0,
|
||||
I2S_NUM_I2S1 = 0x1,
|
||||
I2S_NUM_MAX = I2S_NUM_I2S1,
|
||||
} i2s_num_t;
|
||||
|
||||
/**
|
||||
* @brief I2S module working mode.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_MODE_MASTER_TX = 1,
|
||||
I2S_MODE_MASTER_RX = 2,
|
||||
I2S_MODE_SLAVE_TX = 3,
|
||||
I2S_MODE_SLAVE_RX = 4,
|
||||
} i2s_mode_t;
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per sample.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_SAMPLE_8BIT = 8,
|
||||
I2S_BITS_PER_SAMPLE_16BIT = 16,
|
||||
I2S_BITS_PER_SAMPLE_24BIT = 24,
|
||||
I2S_BITS_PER_SAMPLE_32BIT = 32,
|
||||
} i2s_sample_bits_t;
|
||||
|
||||
/**
|
||||
* @brief I2S audio data formats.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_STD_FORMAT_I2S,
|
||||
I2S_STD_FORMAT_MSB,
|
||||
I2S_STD_FORMAT_LSB,
|
||||
I2S_STD_FORMAT_PCM_SHORT,
|
||||
I2S_STD_FORMAT_PCM_LONG,
|
||||
} i2s_std_format_t;
|
||||
|
||||
/**
|
||||
* @brief I2S data port interface type
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_IFACE_TYPE_DMA,
|
||||
I2S_IFACE_TYPE_CPU,
|
||||
} i2s_interface_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S channel format type
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
I2S_CHANNEL_FMT_ALL_RIGHT,
|
||||
I2S_CHANNEL_FMT_ALL_LEFT,
|
||||
I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||
I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
} i2s_channel_fmt_t;
|
||||
|
||||
/**
|
||||
* @brief I2S audio sample rate per second, measured in Hz.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_SAMPLE_RATE_96K = 96000,
|
||||
I2S_SAMPLE_RATE_48K = 48000,
|
||||
I2S_SAMPLE_RATE_44K = 44100,
|
||||
I2S_SAMPLE_RATE_32K = 32000,
|
||||
I2S_SAMPLE_RATE_22K = 22050,
|
||||
I2S_SAMPLE_RATE_16K = 16000,
|
||||
I2S_SAMPLE_RATE_11K = 11025,
|
||||
I2S_SAMPLE_RATE_8K = 8000,
|
||||
} i2s_sample_rate_t;
|
||||
|
||||
/**
|
||||
* @brief PDM sample rate ratio, measured in Hz.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PDM_SAMPLE_RATE_RATIO_64,
|
||||
PDM_SAMPLE_RATE_RATIO_128,
|
||||
} pdm_sample_rate_ratio_t;
|
||||
|
||||
/**
|
||||
* @brief PDM PCM convter enable/disable.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PDM_PCM_CONV_ENABLE,
|
||||
PDM_PCM_CONV_DISABLE,
|
||||
} pdm_pcm_conv_t;
|
||||
|
||||
/**
|
||||
* @brief I2s module work type.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_MODULE_WORK_TYPE_I2S,
|
||||
I2S_MODULE_WORK_TYPE_PDM,
|
||||
} i2s_module_work_type_t;
|
||||
|
||||
|
||||
// @brief I2S interrupt source defined.
|
||||
typedef enum {
|
||||
I2S_INT_SRC_ONE_BUF_SEND_DONE = I2S_OUT_EOF_INT_ENA, //BIT(12) One package buffer has been sent.
|
||||
I2S_INT_SRC_ONE_BUF_RECV_DONE = I2S_IN_SUC_EOF_INT_ENA, //BIT(9) Received one package buffer
|
||||
|
||||
I2S_INT_SRC_TX_EMPTY = I2S_TX_REMPTY_INT_ENA, //BIT(5) Tx buffer is empty
|
||||
I2S_INT_SRC_RX_FULL = I2S_RX_WFULL_INT_ENA, //BIT(2) Rx buffer is full
|
||||
I2S_INT_SRC_TX_HALF_EMPTY = I2S_TX_PUT_DATA_INT_ENA, //BIT(1) Tx buffer is half empty
|
||||
I2S_INT_SRC_RX_HALF_FULL = I2S_RX_TAKE_DATA_INT_ENA, //BIT(0) Rx buffer is half full
|
||||
} i2s_int_src_t;
|
||||
|
||||
/**
|
||||
* @brief I2S attribute
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_module_work_type_t type;
|
||||
i2s_mode_t mode;
|
||||
i2s_sample_rate_t rate;
|
||||
i2s_sample_bits_t bits;
|
||||
i2s_std_format_t std;
|
||||
i2s_interface_t iface;
|
||||
i2s_channel_fmt_t channel;
|
||||
pdm_sample_rate_ratio_t ratio;
|
||||
pdm_pcm_conv_t conv;
|
||||
} i2s_module_info_t;
|
||||
|
||||
/**
|
||||
* @brief I2S attribute
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_module_info_t tx_mode;
|
||||
i2s_module_info_t rx_mode;
|
||||
} i2s_attr_t;
|
||||
|
||||
// I2S DMA attribite
|
||||
typedef struct {
|
||||
uint32_t mode;
|
||||
uint32_t buf_size;
|
||||
ping_pong_buf_t *buf;
|
||||
} i2s_dma_attr_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize I2s with a given module.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] pAttr Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_init(i2s_num_t i2sNum, i2s_attr_t *pAttr);
|
||||
|
||||
/**
|
||||
* @brief Reset I2s with a given module.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_reset(i2s_num_t i2sNum);
|
||||
|
||||
/**
|
||||
* @brief Start I2s module
|
||||
*
|
||||
* @param[in] type Indicates I2s module which mode will be working.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] mode Indicates I2S working mode.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_start(i2s_module_work_type_t type, i2s_num_t i2sNum, i2s_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Stop I2s module.
|
||||
*
|
||||
* @param[in] type Indicates I2s module which mode will be stop.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module.
|
||||
*
|
||||
* @param[in] mode Indicates I2S working mode.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_stop(i2s_module_work_type_t type, i2s_num_t i2sNum, i2s_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Set i2s module clock.
|
||||
*
|
||||
* @param[in] rate bit clock.
|
||||
*
|
||||
* @param[in] bits bit length.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_clk_set(int rate, int bits);
|
||||
|
||||
/**
|
||||
* @brief Enable I2s DMA mode.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] mode Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_dma_enable(i2s_num_t i2sNum, i2s_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Disable I2s DMA mode.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] mode Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_dma_disable(i2s_num_t i2sNum, i2s_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get ping buffer address.
|
||||
*
|
||||
* @param[in] obj Number of i2s module
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
uint32_t* i2s_dma_ping_buf_get(i2s_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Get pong buffer address.
|
||||
*
|
||||
* @param[in] obj Number of i2s module
|
||||
*
|
||||
* @param[in] pAttr Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
uint32_t* i2s_dma_pong_buf_get(i2s_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Get without working ping-pong buffer address.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] obj Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
uint32_t* i2s_dma_status_get(i2s_num_t i2sNum, i2s_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Set the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] obj Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_dma_dest_add_set(i2s_num_t i2sNum, i2s_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA and create a I2S DMA instance.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] obj Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @param[in] isr Pointer to a function that will be called
|
||||
*
|
||||
* @return -1:indicates parameter error, -2: DMA buffer init failure, others indicates success.
|
||||
*
|
||||
*/
|
||||
int i2s_dma_init(i2s_num_t i2sNum, i2s_dma_attr_t* obj, void *isr);
|
||||
|
||||
/**
|
||||
* @brief Destroy the I2S DMA instance.
|
||||
*
|
||||
* @param[in] obj Pointer to a struct i2s_attr_t that indicates I2S working attribution.
|
||||
*
|
||||
* @return ESP_FAIL:indicates parameter error, ESP_OK :indicates success.
|
||||
*
|
||||
*/
|
||||
esp_err_t i2s_dma_uninit(i2s_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Enable the I2s module interrupt source.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] intSrc Indicates which interrupt source to be enable.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_int_enable(i2s_num_t i2sNum, i2s_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Disable the I2s module interrupt source.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] intSrc Indicates which interrupt source to be disable.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_int_disable(i2s_num_t i2sNum, i2s_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Clear the I2s module interrupt source.
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @param[in] intSrc Indicates which interrupt source to be clear.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
void i2s_int_clear(i2s_num_t i2sNum, i2s_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Get the I2s module interrupt source
|
||||
*
|
||||
* @param[in] i2sNum Number of i2s module
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*/
|
||||
uint32_t i2s_int_status_get(i2s_num_t i2sNum);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __I2S_H__
|
|
@ -1,33 +0,0 @@
|
|||
#ifndef _PSRAM_H
|
||||
#define _PSRAM_H
|
||||
#include "soc/spi_reg.h"
|
||||
#include "esp_err.h"
|
||||
#define PSRAM_READ 0x03
|
||||
#define PSRAM_FAST_READ 0x0B
|
||||
#define PSRAM_FAST_READ_QUAD 0xEB
|
||||
#define PSRAM_WRITE 0x02
|
||||
#define PSRAM_QUAD_WRITE 0x38
|
||||
#define PSRAM_ENTER_QMODE 0x35
|
||||
#define PSRAM_EXIT_QMODE 0xF5
|
||||
#define PSRAM_RESET_EN 0x66
|
||||
#define PSRAM_RESET 0x99
|
||||
#define PSRAM_SET_BURST_LEN 0xC0
|
||||
#define PSRAM_DEVICE_ID 0x9F
|
||||
|
||||
typedef enum {
|
||||
PSRAM_SPI_1 = 0x1,
|
||||
PSRAM_SPI_2,
|
||||
PSRAM_SPI_3,
|
||||
PSRAM_SPI_MAX ,
|
||||
} psram_spi_num_t;
|
||||
|
||||
typedef enum {
|
||||
PSRAM_CACHE_F80M_S40M = 0,//DO NOT USE FOR NOW
|
||||
PSRAM_CACHE_F40M_S40M, //SUPPORTED
|
||||
PSRAM_CACHE_F80M_S80M, //DO NOT USE FOR NOW
|
||||
PSRAM_CACHE_MAX,
|
||||
} psram_cache_mode_t;
|
||||
|
||||
esp_err_t psram_enable(psram_cache_mode_t mode);
|
||||
|
||||
#endif
|
|
@ -1,512 +0,0 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _DRIVER_SPI_H_
|
||||
#define _DRIVER_SPI_H_
|
||||
#include "soc/dport_reg.h"
|
||||
#include "spi.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include <esp_types.h>
|
||||
#include "dma.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#define ETS_SPI_INUM 8
|
||||
#define ETS_HSIP_INUM 8
|
||||
#define ETS_I2S_INUM 9
|
||||
#define ETS_RTC_INUM 9
|
||||
#define ETS_RMT_CTRL_INUM 9
|
||||
#define ETS_GPIO_INUM 18
|
||||
#define ETS_MAX_INUM 16
|
||||
#define ETS_I2C0_INUM 17
|
||||
//#define ETS_I2S0_INUM 17
|
||||
#define ETS_SPI1_INUM 17
|
||||
#define ETS_SPI2_INUM 17
|
||||
#define ETS_SPI3_INUM 17
|
||||
#define ETS_PCNT_INUM 17
|
||||
#define ETS_LEDC_INUM 18
|
||||
|
||||
|
||||
#define ESP_SPI1_INTR_ENABLE() \
|
||||
ESP_INTR_ENABLE(ETS_SPI1_INUM)
|
||||
|
||||
#define ESP_SPI1_INTR_DISABLE() \
|
||||
ESP_INTR_DISABLE(ETS_SPI1_INUM)
|
||||
|
||||
#define ESP_SPI2_INTR_ENABLE() \
|
||||
ESP_INTR_ENABLE(ETS_SPI2_INUM)
|
||||
|
||||
#define ESP_SPI2_INTR_DISABLE() \
|
||||
ESP_INTR_DISABLE(ETS_SPI2_INUM)
|
||||
|
||||
#define ESP_SPI3_INTR_ENABLE() \
|
||||
ESP_INTR_ENABLE(ETS_SPI3_INUM)
|
||||
|
||||
#define ESP_SPI3_INTR_DISABLE() \
|
||||
ESP_INTR_DISABLE(ETS_SPI3_INUM)
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Support SPI1/SPI2/SPI3 module.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_NUM_SPI1 = 0x1,
|
||||
SPI_NUM_SPI2 = 0x2,
|
||||
SPI_NUM_SPI3 = 0x3,
|
||||
SPI_NUM_MAX = SPI_NUM_SPI3,
|
||||
} spi_num_t;
|
||||
|
||||
/**
|
||||
* @brief The SPI module can work in either master or slave mode.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_MODE_MASTER = 0,
|
||||
SPI_MODE_SLAVE = 1,
|
||||
} spi_mode_t;
|
||||
|
||||
/**
|
||||
* @brief SPI sub mode
|
||||
*
|
||||
* Support 4 sub modes based on SPI clock polarity and phase.
|
||||
* SPI_CPOL SPI_CPHA SubMode
|
||||
* 0 0 0
|
||||
* 0 1 1
|
||||
* 1 0 2
|
||||
* 1 1 3
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_SUBMODE_0 = 0,
|
||||
SPI_SUBMODE_1 = 1,
|
||||
SPI_SUBMODE_2 = 2,
|
||||
SPI_SUBMODE_3 = 3,
|
||||
} spi_sub_mode_t;
|
||||
|
||||
/**
|
||||
* @brief The SPI module working speed.
|
||||
*
|
||||
* @attention Max speed 80MHz
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_SPEED_2MHZ = 40,
|
||||
SPI_SPEED_5MHZ = 16,
|
||||
SPI_SPEED_8MHZ = 10,
|
||||
SPI_SPEED_10MHZ = 8,
|
||||
SPI_SPEED_16MHZ = 5,
|
||||
SPI_SPEED_20MHZ = 4,
|
||||
} spi_speed_t;
|
||||
|
||||
/**
|
||||
* @brief The SPI mode working speed.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_BIT_ORDER_MSB_FIRST = 0,
|
||||
SPI_BIT_ORDER_LSB_FIRST = 1,
|
||||
} spi_bit_order_t;
|
||||
|
||||
// @brief SPI interrupt source defined.
|
||||
typedef enum {
|
||||
SPI_INT_SRC_TRANS_DONE = SPI_TRANS_DONE,
|
||||
SPI_INT_SRC_WR_STA_DONE = SPI_SLV_WR_STA_DONE,
|
||||
SPI_INT_SRC_RD_STA_DONE = SPI_SLV_RD_STA_DONE,
|
||||
SPI_INT_SRC_WR_BUF_DONE = SPI_SLV_WR_BUF_DONE,
|
||||
SPI_INT_SRC_RD_BUF_DONE = SPI_SLV_RD_BUF_DONE,
|
||||
SPI_INT_SRC_ONE_BUF_RECV_DONE = SPI_IN_SUC_EOF_INT_ENA,
|
||||
SPI_INT_SRC_ONE_BUF_SEND_DONE = SPI_OUT_EOF_INT_ENA,
|
||||
} spi_int_src_t;
|
||||
|
||||
/**
|
||||
* @brief The SPI mode working speed.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_WORK_MODE_HALF = 0,
|
||||
SPI_WORK_MODE_FULL = 1,
|
||||
} spi_work_mode_t;
|
||||
|
||||
/**
|
||||
* @brief The SPI DMA channels.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_DMA_CHANNEL_0 = 1,
|
||||
SPI_DMA_CHANNEL_1 = 2,
|
||||
} spi_dma_channel_t;
|
||||
|
||||
/**
|
||||
* @brief The SPI dma direction.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SPI_DMA_DIR_IN = 1,
|
||||
SPI_DMA_DIR_OUT = 2,
|
||||
} spi_dma_dir_t;
|
||||
|
||||
#pragma pack(1)
|
||||
/**
|
||||
* @brief SPI attribute
|
||||
*/
|
||||
typedef struct {
|
||||
spi_mode_t mode; ///< Master or slave mode
|
||||
spi_sub_mode_t sub_mode; ///< SPI SPI_CPOL SPI_CPHA mode
|
||||
spi_speed_t speed; ///< SPI Clock
|
||||
spi_bit_order_t bit_order; ///< SPI bit order
|
||||
spi_work_mode_t half_mode; ///< Half or Full work mode
|
||||
} spi_attr_t;
|
||||
|
||||
/**
|
||||
* @brief SPI attribute
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t cmd; ///< Command value
|
||||
uint8_t cmd_len; ///< Command byte length
|
||||
uint32_t *addr; ///< Point to address value
|
||||
uint8_t addr_len; ///< Address byte length
|
||||
uint32_t *tx_data; ///< Point to send data buffer
|
||||
uint8_t tx_data_len; ///< Send data byte length.
|
||||
uint32_t *rx_data; ///< Point to recevie data buffer
|
||||
uint8_t rx_data_len; ///< Recevie Data byte length.
|
||||
} spi_data_t;
|
||||
|
||||
// SPI DMA attribite
|
||||
typedef struct {
|
||||
spi_num_t spi_num; ///< Spi number
|
||||
uint32_t mode; ///< Spi work mode
|
||||
uint32_t buf_size; ///< Size of buffer
|
||||
spi_dma_dir_t dir; ///< Direction of data,in or out.
|
||||
spi_dma_channel_t channel; ///< Channel of DMA
|
||||
ping_pong_buf_t *buf; ///< Buffer address
|
||||
} spi_dma_attr_t;
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
* @brief Get SPI ping buffer address.
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return uint32_t*, NULL:indicates parameter error, others indicates ping buffer address.
|
||||
*/
|
||||
uint32_t* spi_dma_ping_buf_get(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Get SPI pong buffer address.
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return uint32_t*, NULL:indicates parameter error, others indicates pong buffer address.
|
||||
*/
|
||||
uint32_t* spi_dma_pong_buf_get(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Get without working ping-pong buffer address.
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return uint32_t*, NULL:indicates parameter error, others indicates not working buffer address.
|
||||
*/
|
||||
uint32_t* spi_dma_status_get(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
int32_t spi_dma_memcpy(spi_dma_attr_t *obj, void *src, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_dest_add_set(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Reset the SPI DMA instance
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
* @param [in] isr
|
||||
* Indicates which function to be called, when interrupt hanpened.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_rest(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA and create a SPI DMA instance
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
* @param [in] isr
|
||||
* Indicates which function to be called, when interrupt hanpened.
|
||||
*
|
||||
* @return -1:indicates parameter error, -2: DMA buffer init failure, others indicates success.
|
||||
*/
|
||||
int spi_dma_init(spi_dma_attr_t *obj, void *isr);
|
||||
|
||||
/**
|
||||
* @brief Destroy the SPI DMA instance
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return int, -1:indicates parameter error, others indicates success.
|
||||
*/
|
||||
int spi_dma_uninit(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_int_enable(spi_num_t spiNum, spi_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_int_disable(spi_num_t spiNum, spi_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_int_clear(spi_num_t spiNum);
|
||||
|
||||
/**
|
||||
* @brief Configrate the Ping-Pong buffer to the destination
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
int32_t spi_dma_int_status_get(spi_num_t spiNum);
|
||||
|
||||
/**
|
||||
* @brief Start e SPI DMA instance
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
* @param [in] len
|
||||
* Indicates how many data to be called.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_start(spi_dma_attr_t *obj, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Stop the SPI DMA transmit
|
||||
*
|
||||
* @param [in] obj
|
||||
* Pointer to a struct spi_dma_attr_t that indicates SPI DMA working attribution.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void spi_dma_stop(spi_dma_attr_t *obj);
|
||||
|
||||
/**
|
||||
* @brief Initialize SPI module.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] pAttr
|
||||
* Pointer to a struct spi_attr_t that indicates SPI working attribution.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_init(spi_num_t spiNum, spi_attr_t* pAttr);
|
||||
|
||||
/**
|
||||
* @brief Set slave address value by master.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] addr
|
||||
* Slave address to be set.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_master_cfg_addr(spi_num_t spiNum, uint32_t addr);
|
||||
|
||||
/**
|
||||
* @brief Set command value by master.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] cmd
|
||||
* Command will be send to slave.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_master_cfg_cmd(spi_num_t spiNum, uint32_t cmd);
|
||||
|
||||
/**
|
||||
* @brief Send data to slave from master.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] pInData
|
||||
* Pointer to a spi_data_t strcuture that indicates data, address and command will be send.
|
||||
*
|
||||
* @return int, -1:indicates failure,others indicates success.
|
||||
*/
|
||||
int spi_master_send_data(spi_num_t spiNum, spi_data_t* pInData);
|
||||
|
||||
/**
|
||||
* @brief Receive data from slave by master.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] pOutData
|
||||
* Point to data buffer.
|
||||
*
|
||||
* @return int, -1:indicates failure,others indicates success.
|
||||
*
|
||||
*/
|
||||
int spi_master_recv_data(spi_num_t spiNum, spi_data_t* pData);
|
||||
|
||||
/**
|
||||
* @brief Load data to slave send buffer.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] pOutData
|
||||
* Point to data buffer.
|
||||
* @param [in] outLen
|
||||
* The number of bytes to be set.
|
||||
*
|
||||
* @return int, -1:indicates failure,others indicates success.
|
||||
*/
|
||||
int spi_slave_send_data(spi_num_t spiNum, uint32_t *pOutData, uint8_t outLen);
|
||||
|
||||
/**
|
||||
* @brief Receive data by slave.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
* @param [in] isrFunc
|
||||
* isrFunc is a pointer to the function to be called when the SPI interrupt occurs.
|
||||
*
|
||||
* @return int, -1:indicates failure,others indicates success.
|
||||
*/
|
||||
int spi_slave_recv_data(spi_num_t spiNum, void(*isrFunc)(void*));
|
||||
|
||||
/**
|
||||
* @brief Set slave status by master.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
*
|
||||
* @param [in] data
|
||||
* Data will be write to slave SPI_WR_STATUS.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_master_send_status(spi_num_t spiNum, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief Get salve status by master.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
*
|
||||
* @return int, -1: indicates failure; other value in slave status.
|
||||
*/
|
||||
int spi_master_recv_status(spi_num_t spiNum);
|
||||
|
||||
/**
|
||||
* @brief Enable SPI module interrupt source.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
*
|
||||
* @param [in] intSrc
|
||||
* Indicates which interrupt source to enable.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_int_enable(spi_num_t spiNum, spi_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Disable SPI module interrupt source.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
*
|
||||
* @param [in] intSrc
|
||||
* Indicates which interrupt source to disable.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_int_disable(spi_num_t spiNum, spi_int_src_t intSrc);
|
||||
|
||||
/**
|
||||
* @brief Clear all of spi interrupt.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void spi_int_clear(spi_num_t spiNum);
|
||||
|
||||
/**
|
||||
* @brief Get the spi interrupt status.
|
||||
*
|
||||
* @param [in] spiNum
|
||||
* Indicates which submode to be used.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
int32_t spi_int_status_get(spi_num_t spiNum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SPI_H__
|
File diff suppressed because it is too large
Load diff
|
@ -1,932 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
//#include "esp_common.h"
|
||||
//#include "i2c_test.h"
|
||||
//#include "i2c_register.h"
|
||||
#include "../gpio/gpio.h"
|
||||
//#include "../test_code/peripheral_test.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#define FIELD_MODE 1
|
||||
|
||||
#define I2C_FREQ 100000 //HZ
|
||||
#define I2C_SLAVE_DEV_ADDR 0x60
|
||||
|
||||
#define I2C_SDA_OUT_IO_NUM 19
|
||||
#define I2C_SDA_OUT_IO_SIG I2CEXT0_SDA_OUT_IDX
|
||||
#define I2C_SDA_OUT_IO_PIN GPIO_Pin_19
|
||||
|
||||
#define I2C_SCL_OUT_IO_NUM 23
|
||||
#define I2C_SCL_OUT_IO_SIG I2CEXT0_SCL_OUT_IDX
|
||||
#define I2C_SCL_OUT_IO_PIN GPIO_Pin_23
|
||||
|
||||
#define I2C_SDA_IN_IO_SIG I2CEXT0_SDA_IN_IDX
|
||||
#define I2C_SCL_IN_IO_SIG I2CEXT0_SCL_IN_IDX
|
||||
|
||||
void I2C_GpioInit()
|
||||
{
|
||||
gpio_config_t gpio_conf;
|
||||
gpio_conf.GPIO_Mode = GPIO_Mode_Input_OutOD;
|
||||
gpio_conf.GPIO_Pin = I2C_SDA_OUT_IO_PIN | I2C_SCL_OUT_IO_PIN ;
|
||||
gpio_conf.GPIO_Pulldown = GPIO_PullDown_DIS;
|
||||
gpio_conf.GPIO_Pullup = GPIO_PullUp_EN;
|
||||
gpio_conf.GPIO_IntrType = GPIO_PIN_INTR_DISABLE;
|
||||
gpio_config(&gpio_conf);
|
||||
|
||||
gpio_matrix_out(I2C_SDA_OUT_IO_NUM,I2C_SDA_OUT_IO_SIG,0,0);
|
||||
gpio_matrix_out(I2C_SCL_OUT_IO_NUM, I2C_SCL_OUT_IO_SIG,0,0);
|
||||
gpio_matrix_in(I2C_SDA_OUT_IO_NUM, I2C_SDA_IN_IO_SIG,0);
|
||||
gpio_matrix_in(I2C_SCL_OUT_IO_NUM, I2C_SCL_IN_IO_SIG,0);
|
||||
}
|
||||
#if 0
|
||||
// SDA OUT
|
||||
uint32 i2c_sda_io_mux_reg = GPIO_PIN_MUX_REG[I2C_SDA_OUT_IO_NUM];
|
||||
gpio_matrix_out(I2C_SDA_OUT_IO_NUM,I2C_SDA_OUT_IO_SIG);
|
||||
PIN_FUNC_SELECT(i2c_sda_io_mux_reg, I2C_GPIO_FUNC);
|
||||
SET_PERI_REG_MASK(i2c_sda_io_mux_reg,FUN_IE|FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(i2c_sda_io_mux_reg,FUN_PD);
|
||||
SET_PERI_REG_MASK(i2c_sda_io_mux_reg,GPIO_PIN_PAD_DRIVER);
|
||||
//SDL OUT
|
||||
uint32 i2c_scl_io_mux_reg = GPIO_PIN_MUX_REG[I2C_SCL_OUT_IO_NUM];
|
||||
gpio_matrix_out(I2C_SCL_OUT_IO_NUM, I2C_SCL_OUT_IO_SIG);
|
||||
PIN_FUNC_SELECT(i2c_scl_io_mux_reg, I2C_GPIO_FUNC);
|
||||
SET_PERI_REG_MASK(i2c_scl_io_mux_reg,FUN_IE|FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(i2c_scl_io_mux_reg,FUN_PD);
|
||||
SET_PERI_REG_MASK(i2c_scl_io_mux_reg,GPIO_PIN_PAD_DRIVER);
|
||||
//SDA IN
|
||||
gpio_matrix_in(I2C_SDA_OUT_IO_NUM, I2C_SDA_IN_IO_SIG);
|
||||
//SCL IN
|
||||
gpio_matrix_in(I2C_SCL_OUT_IO_NUM, I2C_SCL_IN_IO_SIG);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void i2c_send_data_test(uint8 i2c_no,uint8 mask1,uint8 mask2, uint8 mask3)
|
||||
{
|
||||
uint8 data_buf[] = {0xa8, //slave addr
|
||||
0x13, //reg addr
|
||||
mask1, //val1
|
||||
mask2, //val2
|
||||
mask3, //val3
|
||||
0 //val4
|
||||
};
|
||||
|
||||
uint8 byte_num = sizeof(data_buf);
|
||||
struct I2C_CmdDef cmd;
|
||||
os_memset(&cmd,0,sizeof(cmd));
|
||||
|
||||
//reset tx fifo
|
||||
I2C_ResetTxFifo(I2C(i2c_no));
|
||||
|
||||
//setup command 0
|
||||
cmd.ack_en = 0;
|
||||
cmd.ack_exp = 1;
|
||||
cmd.ack_val = 1;
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_RESTART;
|
||||
I2C_ConfigCmd(i2c_no,0, &cmd);
|
||||
|
||||
//setup command 1
|
||||
cmd.byte_num = byte_num;
|
||||
cmd.op_code = I2C_CMD_WRITE;
|
||||
I2C_ConfigCmd(i2c_no,1, &cmd);
|
||||
|
||||
//setup command 2
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_STOP;
|
||||
I2C_ConfigCmd(i2c_no,2, &cmd);
|
||||
|
||||
//push the sending data to tx fifo
|
||||
I2C_TxFifoPush(i2c_no,data_buf ,byte_num);
|
||||
|
||||
//I2C start sending
|
||||
I2C_Start(i2c_no);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i2c_intr_handler(void)
|
||||
{
|
||||
uint8 i2c_no = 0; //UART1
|
||||
|
||||
I2C_TypeDef* I2Cx = I2C(i2c_no);
|
||||
// uint32 i2c_intr_status = READ_PERI_REG(I2C_I2C_INT_STATUS_REG(i2c_no));
|
||||
uint32 i2c_intr_status = I2Cx->I2C_INT_STATUS.val;
|
||||
|
||||
//uint16 fifo_len = I2C_GET_RXFIFO_CNT(i2c_no);
|
||||
uint16 rx_fifo_len = I2Cx->SR.fld.rxfifo_cnt;
|
||||
//uint16 tx_fifo_len = I2C_GET_TXFIFO_CNT(i2c_no);
|
||||
uint16 tx_fifo_len = I2Cx->SR.fld.txfifo_cnt;
|
||||
|
||||
uint16 i = 0;
|
||||
os_printf("====================================================\n");
|
||||
os_printf("IN I2C RX INTR !!!!!!!!\r\n");
|
||||
os_printf("i2c_intr_status: 0x%08x \r\n",i2c_intr_status);
|
||||
|
||||
|
||||
|
||||
if( (i2c_intr_status >> I2C_RXFIFO_FULL_INT_ST_S)&I2C_RXFIFO_FULL_INT_ST_V){
|
||||
os_printf("I2C_RXFIFO_FULL_INT, rx_fifo_len: %d\r\n",rx_fifo_len);
|
||||
for(i=0;i<rx_fifo_len;i++){
|
||||
//os_printf("%c",I2C_GET_FIFO_RDATA(i2c_no));
|
||||
os_printf("%c",I2Cx->I2C_DATA.fld.fifo_data);
|
||||
}
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TXFIFO_EMPTY_INT_ST_S)&I2C_TXFIFO_EMPTY_INT_ST_V){
|
||||
os_printf("I2C_TXFIFO_EMPTY_INT, TX_fifo_len: %d\r\n",tx_fifo_len);
|
||||
// I2C_SET_TXFIFO_EMPTY_INT_ENA(i2c_no,0);
|
||||
I2Cx->I2C_INT_ENA.fld.tx_send_empty_int_ena = 0;
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_RXFIFO_OVF_INT_ST_S)&I2C_RXFIFO_OVF_INT_ST_V){
|
||||
os_printf("I2C_RXFIFO_OVF_INT, tx_fifo_len: %d\r\n",tx_fifo_len);
|
||||
for(i=0;i<rx_fifo_len;i++){
|
||||
os_printf("%c",I2Cx->I2C_DATA.fld.fifo_data);
|
||||
}
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_SLAVE_TRAN_COMP_INT_ST_S)&I2C_SLAVE_TRAN_COMP_INT_ST_V){
|
||||
os_printf("I2C_SLAVE_TRAN_COMP_INT_ST, tx_fifo_len: %d\r\n",tx_fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_ARBITRATION_LOST_INT_ST_S)&I2C_ARBITRATION_LOST_INT_ST_V){
|
||||
os_printf("I2C_ARBITRATION_LOST_INT_ST, tx_fifo_len: %d\r\n",tx_fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_MASTER_TRAN_COMP_INT_ST_S)&I2C_MASTER_TRAN_COMP_INT_ST_V){
|
||||
os_printf("I2C_MASTER_TRAN_COMP_INT_ST, tx_fifo_len: %d\r\n",tx_fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TRANS_COMPLETE_INT_ST_S)&I2C_TRANS_COMPLETE_INT_ST_V){
|
||||
os_printf("I2C_TRANS_COMPLETE_INT_ST, tx_fifo_len: %d\r\n",tx_fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TIME_OUT_INT_ST_S)&I2C_TIME_OUT_INT_ST_V){
|
||||
os_printf("I2C_TIME_OUT_INT_ST, tx_fifo_len: %d\r\n",tx_fifo_len);
|
||||
os_printf("DISABLE TOUT INT...time out status: %d \r\n",I2Cx->SR.fld.time_out);
|
||||
// I2C_SET_TIME_OUT_INT_ENA(i2c_no,0);
|
||||
I2Cx->I2C_INT_ENA.fld.time_out_int_ena = 0;
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TRANS_START_INT_ST_S)&I2C_TRANS_START_INT_ST_V){
|
||||
os_printf("I2C_TRANS_START_INT_ST, fifo_len: %d\r\n",tx_fifo_len);
|
||||
}
|
||||
//uart_intr_status = READ_PERI_REG(UART_INT_ST_REG(uart_no)) ;
|
||||
// SET_PERI_REG_MASK(I2C_I2C_INT_CLR_REG(i2c_no),i2c_intr_status);
|
||||
I2Cx->I2C_INT_CLR.val = i2c_intr_status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void I2C_IntrConfig(uint8 i2c_no)
|
||||
{
|
||||
I2C_TypeDef* I2Cx = I2C(i2c_no);
|
||||
os_printf("===========================\r\n");
|
||||
os_printf("I2C0 TEST INTR CONFIG: %d\r\n",i2c_no);
|
||||
os_printf("===========================\r\n");
|
||||
I2Cx->I2C_INT_CLR.val = 0xffffffff;
|
||||
ETS_INTR_DISABLE(ETS_I2C0_INUM);
|
||||
//REG_SET_FIELD(PRO_UART1_INTR_MAP_REG,DPORT_PRO_UART1_INTR_MAP,ETS_UART1_INUM);
|
||||
//REG_SET_FIELD(PRO_UART1_INTR_MAP_REG,DPORT_PRO_UART1_INTR_MAP,ETS_UART1_INUM);
|
||||
//ETS_INTR_ATTACH(i2c_rx_intr_handler, NULL,ETS_I2C0_INUM);
|
||||
//ETS_INTR_ENABLE(ETS_I2C0_INUM);
|
||||
|
||||
os_printf("EN INTR.\n");
|
||||
I2C_IntrRegister(i2c_intr_handler,NULL);
|
||||
I2Cx->I2C_INT_ENA.val = 0;
|
||||
os_printf("I2C INT EN0: 0X%08x\n",READ_PERI_REG(0x60013028));
|
||||
//I2Cx->I2C_INT_ENA.fld.master_tran_comp_int_ena = 1;
|
||||
I2Cx->I2C_INT_ENA.fld.time_out_int_ena =1;
|
||||
I2Cx->I2C_INT_ENA.fld.trans_complete_int_ena=1;
|
||||
I2Cx->I2C_INT_ENA.fld.trans_start_int_ena=1;
|
||||
//WRITE_PERI_REG(0x60013028,0x3c0);
|
||||
os_printf("I2C INT EN01: 0X%08x\n",READ_PERI_REG(0x60013028));
|
||||
ETS_INTR_ENABLE(ETS_I2C0_INUM);
|
||||
}
|
||||
|
||||
void I2C_MasterTest(uint8 i2c_no)
|
||||
{
|
||||
os_printf("test i2c master...\r\n");
|
||||
os_printf("gpio init");
|
||||
//step 1: gpio init
|
||||
I2C_GpioInit();
|
||||
|
||||
//step 2: i2c init
|
||||
//master init
|
||||
I2C_InitTypeDef I2C_Init_t;
|
||||
I2C_Init_t.addr_10bit_en = 0; //not used
|
||||
I2C_Init_t.clk_speed = 100000; //clk set
|
||||
I2C_Init_t.mode = I2C_MASTER_MODE; //master mode
|
||||
I2C_Init_t.slave_addr = 0x0; //no slave addr for master mode
|
||||
I2C_Init(i2c_no,&I2C_Init_t);
|
||||
//I2C_IntrConfig(i2c_no);
|
||||
#if 0
|
||||
int i =1;
|
||||
uint32 m_tmp = (1<<(i%18));
|
||||
uint8 mask1 = (m_tmp>>0) &0x3f ;
|
||||
uint8 mask2 = (m_tmp>>6) &0x3f ;
|
||||
uint8 mask3 = (m_tmp>>12) &0x3f ;
|
||||
i2c_send_data_test(0,mask1, mask2, mask3);
|
||||
os_printf("finish sending..\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void i2c_send_long_data_test()
|
||||
{
|
||||
os_printf("send long data\n");
|
||||
uint8 i2c_no = 0;
|
||||
uint8 cmd_idx = 0;
|
||||
I2C_TypeDef* I2Cx = I2C(i2c_no);
|
||||
|
||||
int i =1;
|
||||
uint8 data_buf[256];
|
||||
for(i=0;i< sizeof(data_buf);i++) data_buf[i]=i;
|
||||
|
||||
struct I2C_CmdDef cmd;
|
||||
os_memset(&cmd,0,sizeof(cmd));
|
||||
|
||||
//reset tx fifo
|
||||
I2C_ResetTxFifo(i2c_no);
|
||||
|
||||
//setup command 0: start
|
||||
cmd_idx = 0;
|
||||
cmd.ack_en = 0;
|
||||
cmd.ack_exp = 1;
|
||||
cmd.ack_val = 1;
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_RESTART;
|
||||
I2C_ConfigCmd(i2c_no,cmd_idx, &cmd);
|
||||
|
||||
//setup command 1: write
|
||||
cmd_idx = 1;
|
||||
cmd.byte_num = 31;
|
||||
cmd.op_code = I2C_CMD_WRITE;
|
||||
I2C_ConfigCmd(i2c_no,cmd_idx, &cmd);
|
||||
|
||||
//setup command 2: end
|
||||
cmd_idx = 2;
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_END;
|
||||
I2C_ConfigCmd(i2c_no,cmd_idx,&cmd);
|
||||
I2C_TxFifoPush(i2c_no,data_buf ,31);
|
||||
|
||||
// os_printf("tcmd1.done:%d\n",I2Cx->I2C_COMD[1].fld.command_done);
|
||||
// os_printf("tcmd2.done:%d\n",I2Cx->I2C_COMD[2].fld.command_done);
|
||||
I2C_Start(i2c_no);
|
||||
os_printf("2");
|
||||
uint8 val;
|
||||
while(1){
|
||||
if(I2Cx->I2C_COMD[1].fld.command_done == 1) break;
|
||||
//os_printf("dne:%d\n",I2Cx->I2C_COMD[1].fld.command_done);
|
||||
//if(I2C_GET_COMMAND_DONE(0,1) == 1) break;
|
||||
ets_delay_us(1);
|
||||
}
|
||||
// os_printf("send 1st\n");
|
||||
// ets_delay_us(50000);
|
||||
// os_printf("cmd1.done2:%d\n",I2Cx->I2C_COMD[1].fld.command_done);
|
||||
// os_printf("cmd2.done2:%d\n",I2Cx->I2C_COMD[2].fld.command_done);
|
||||
// os_printf("send 2nd\n");
|
||||
|
||||
cmd_idx = 0;
|
||||
cmd.byte_num = 31;
|
||||
cmd.op_code = I2C_CMD_WRITE;
|
||||
I2C_ConfigCmd(i2c_no,cmd_idx, &cmd);
|
||||
I2C_TxFifoPush(i2c_no,data_buf+31 ,31);
|
||||
|
||||
|
||||
//setup command 0: stop
|
||||
cmd_idx = 1;
|
||||
cmd.byte_num = 0;
|
||||
cmd.op_code = I2C_CMD_STOP;
|
||||
I2C_ConfigCmd(i2c_no,cmd_idx, &cmd);
|
||||
|
||||
//push the sending data to tx fifo
|
||||
//I2C_TxFifoPush(i2c_no,data_buf ,byte_num);
|
||||
|
||||
//I2C start sending
|
||||
I2C_Start(i2c_no);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void I2C1_GPIO_Init()
|
||||
{
|
||||
#if 1
|
||||
// SDA OUT
|
||||
gpio_matrix_out(21, I2C1_SDA_OUT_IO_SIG);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_GPIO21);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO21_U,FUN_IE|FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO21_U,FUN_PD);
|
||||
SET_PERI_REG_MASK(GPIO_PIN21_REG,GPIO_PIN21_PAD_DRIVER);
|
||||
//====debug====
|
||||
gpio_matrix_out(22, I2C1_SCL_OUT_IO_SIG);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_GPIO22);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO22_U,FUN_IE|FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO22_U,FUN_PD);
|
||||
SET_PERI_REG_MASK(GPIO_PIN22_REG,GPIO_PIN22_PAD_DRIVER);
|
||||
//============================
|
||||
//SDA IN
|
||||
gpio_matrix_in(21, I2C1_SDA_IN_IO_SIG);
|
||||
//SCL IN
|
||||
gpio_matrix_in(22, I2C1_SCL_IN_IO_SIG);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void I2C_GPIO_Init_ori()
|
||||
{
|
||||
#if 1
|
||||
// SDA OUT
|
||||
gpio_matrix_out(19, I2C_SDA_OUT_IO_SIG);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_GPIO19);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO19_U,FUN_IE|FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO19_U,FUN_PD);
|
||||
SET_PERI_REG_MASK(GPIO_PIN19_REG,GPIO_PIN19_PAD_DRIVER);
|
||||
//====debug====
|
||||
gpio_matrix_out(20, I2C_SCL_OUT_IO_SIG);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, FUNC_GPIO20_GPIO20);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO20_U,FUN_IE|FUN_PU);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO20_U,FUN_PD);
|
||||
SET_PERI_REG_MASK(GPIO_PIN20_REG,GPIO_PIN20_PAD_DRIVER);
|
||||
//============================
|
||||
//SDA IN
|
||||
gpio_matrix_in(19, I2C_SDA_IN_IO_SIG);
|
||||
//SCL IN
|
||||
gpio_matrix_in(20, I2C_SCL_IN_IO_SIG);
|
||||
#endif
|
||||
|
||||
//init I2C1 GPIO
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i2c_slave_init(uint8 i2c_no)
|
||||
{
|
||||
if(i2c_no>1){
|
||||
os_printf("invalid i2c number...\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
I2C1_GPIO_Init();
|
||||
|
||||
|
||||
//set master mode
|
||||
//I2C_SET_RX_LSB_FIRST(i2c_no,0); //MSB FIRST
|
||||
//I2C_SET_TX_LSB_FIRST(i2c_no,0); //MSB FIRST
|
||||
|
||||
I2C_SET_MS_MODE(i2c_no,0); //SLAVE MODE
|
||||
//I2C_SET_SCL_FORCE_OUT(i2c_no,1); //out put practical level
|
||||
//I2C_SET_SDA_FORCE_OUT(i2c_no,1); //out put practical level
|
||||
|
||||
I2C_SET_SLAVE_ADDR(i2c_no,I2C_SLAVE_DEV_ADDR);
|
||||
I2C_SET_ADDR_10BIT_EN(i2c_no,0);
|
||||
|
||||
|
||||
//SET FREQ/DUTY
|
||||
I2C_SET_SCL_LOW_PERIOD(i2c_no, (APB_CLK_FREQ/I2C_FREQ)/2);
|
||||
I2C_SET_SCL_HIGH_PERIOD(i2c_no, (APB_CLK_FREQ/I2C_FREQ)/2);
|
||||
|
||||
//SET CLK RE/START HOLD/SETUP
|
||||
I2C_SET_SCL_START_HOLD_TIME(i2c_no,50);//400);
|
||||
I2C_SET_SCL_RSTART_SETUP_TIME(i2c_no,50);//400);
|
||||
|
||||
//SET CLK STOP HOLD/SETUP
|
||||
I2C_SET_SCL_STOP_HOLD_TIME(i2c_no,50);//400);
|
||||
I2C_SET_SCL_STOP_SETUP_TIME(i2c_no,50);//400);
|
||||
|
||||
//SET DATA I/O HOLD/SAMPLE
|
||||
I2C_SET_SDA_HOLD_TIME(i2c_no,40);
|
||||
I2C_SET_SDA_SAMPLE_TIME(i2c_no,40);
|
||||
|
||||
//SET CLK TIME OUT
|
||||
I2C_SET_TIME_OUT_THRSH(i2c_no,2000);
|
||||
|
||||
//SET FIFO MODE
|
||||
//I2C_SET_NONFIFO_EN(i2c_no,0);
|
||||
//SET SCL FILTER
|
||||
//I2C_SET_SCL_FILTER_EN(i2c_no,1);
|
||||
//SET SDA FILTER
|
||||
//I2C_SET_SDA_FILTER_EN(i2c_no,0);
|
||||
|
||||
os_printf("===========================\r\n");
|
||||
os_printf("I2C1 SLAVE TRANS START\r\n");
|
||||
os_printf("===========================\r\n");
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
|
||||
|
||||
|
||||
os_printf("===========================\r\n");
|
||||
os_printf("I2C1 TEST INTR CONFIG\r\n");
|
||||
os_printf("===========================\r\n");
|
||||
ETS_INTR_DISABLE(ETS_I2C1_INUM);
|
||||
//REG_SET_FIELD(PRO_UART1_INTR_MAP_REG,DPORT_PRO_UART1_INTR_MAP,ETS_UART1_INUM);
|
||||
intr_matrix_set(ETS_I2C1_SOURCE, ETS_I2C1_INUM);
|
||||
ETS_INTR_ATTACH(i2c1_rx_intr_handler, NULL,ETS_I2C1_INUM);
|
||||
ETS_INTR_ENABLE(ETS_I2C1_INUM);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void i2c_master_init(uint8 i2c_no)
|
||||
{
|
||||
if(i2c_no>1){
|
||||
os_printf("invalid i2c number...\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//set master mode
|
||||
//I2C_SET_RX_LSB_FIRST(i2c_no,0); //MSB FIRST
|
||||
//I2C_SET_TX_LSB_FIRST(i2c_no,0); //MSB FIRST
|
||||
I2C_SET_MS_MODE(i2c_no,1); //MASTER MODE
|
||||
//I2C_SET_SCL_FORCE_OUT(i2c_no,1); //out put practical level
|
||||
//I2C_SET_SDA_FORCE_OUT(i2c_no,1); //out put practical level
|
||||
|
||||
//SET FREQ/DUTY
|
||||
I2C_SET_SCL_LOW_PERIOD(i2c_no, (APB_CLK_FREQ/I2C_FREQ)/2);
|
||||
I2C_SET_SCL_HIGH_PERIOD(i2c_no, (APB_CLK_FREQ/I2C_FREQ)/2);
|
||||
|
||||
//SET CLK RE/START HOLD/SETUP
|
||||
I2C_SET_SCL_START_HOLD_TIME(i2c_no,50);//400);
|
||||
I2C_SET_SCL_RSTART_SETUP_TIME(i2c_no,50);//400);
|
||||
|
||||
//SET CLK STOP HOLD/SETUP
|
||||
I2C_SET_SCL_STOP_HOLD_TIME(i2c_no,50);//400);
|
||||
I2C_SET_SCL_STOP_SETUP_TIME(i2c_no,50);//400);
|
||||
|
||||
//SET DATA I/O HOLD/SAMPLE
|
||||
I2C_SET_SDA_HOLD_TIME(i2c_no,40);
|
||||
I2C_SET_SDA_SAMPLE_TIME(i2c_no,40);
|
||||
|
||||
//SET CLK TIME OUT
|
||||
I2C_SET_TIME_OUT_THRSH(i2c_no,2000);
|
||||
|
||||
//SET FIFO MODE
|
||||
//I2C_SET_NONFIFO_EN(i2c_no,0);
|
||||
//SET SCL FILTER
|
||||
//I2C_SET_SCL_FILTER_EN(i2c_no,1);
|
||||
//SET SDA FILTER
|
||||
//I2C_SET_SDA_FILTER_EN(i2c_no,0);
|
||||
|
||||
i2c_intr_config();
|
||||
}
|
||||
|
||||
|
||||
void i2c_master_read_test()
|
||||
{
|
||||
uint8 i2c_no = 0;
|
||||
uint8 idx = 0;
|
||||
|
||||
uint8 data_buf[] = {I2C_SLAVE_DEV_ADDR, //addr
|
||||
0x10,
|
||||
0x01,
|
||||
0x12,
|
||||
0x13,
|
||||
0x14,
|
||||
};
|
||||
uint8 byte_num = sizeof(data_buf);
|
||||
|
||||
I2C_SET_TX_FIFO_RST(0,1);
|
||||
I2C_SET_TX_FIFO_RST(0,0);
|
||||
|
||||
//command0 : sending restart signal
|
||||
idx = 0;
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,0,1);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
idx = 1;
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,1);//WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,idx,byte_num); //BYTE NUMBER
|
||||
|
||||
//command2 : master generating stop
|
||||
idx = 2;
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,0x3); //STOP
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0); //NO ACK
|
||||
|
||||
int i = 0;
|
||||
for(i=0;i<byte_num;i++){
|
||||
WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),data_buf[i]);
|
||||
}
|
||||
|
||||
//start sending
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i2c_master_write_long_data(uint8 i2c_no)
|
||||
{
|
||||
uint8 idx,idx2 = 0;
|
||||
uint8 data_buf[] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0};
|
||||
uint8 byte_num = sizeof(data_buf);
|
||||
|
||||
//command0 : sending restart signal
|
||||
idx = 0;
|
||||
os_printf("IDX 0: %d \r\n",idx);
|
||||
I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,idx,1);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
idx = 1;
|
||||
|
||||
os_printf("IDX 1: %d \r\n",idx);
|
||||
I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,1);//WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,idx,byte_num); //BYTE NUMBER
|
||||
|
||||
//command2 : master generating END
|
||||
idx = 2;
|
||||
os_printf("IDX 2: %d \r\n",idx);
|
||||
I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,0x4); //END
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0); //NO ACK
|
||||
|
||||
int i = 0;
|
||||
for(i=0;i<byte_num;i++){
|
||||
WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),data_buf[i]);
|
||||
}
|
||||
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
|
||||
//os_printf("trans check...\r\n");
|
||||
while( I2C_GET_COMMAND_DONE(i2c_no,1) == 0);
|
||||
//os_printf("trans check ok...\r\n");
|
||||
|
||||
//command0 : sending restart signal
|
||||
//idx=0;
|
||||
//I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
//I2C_SET_COMMAND_OP_CODE(i2c_no,idx,0);
|
||||
//I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
//I2C_SET_COMMAND_BYTE_NUM(i2c_no,idx,1);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
idx = 0;
|
||||
//os_printf("IDX2 0: %d \r\n",idx);
|
||||
I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
|
||||
I2C_SET_COMMAND_ACK_EXP(i2c_no,idx,1);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,1);//WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,idx,2); //BYTE NUMBER
|
||||
//os_printf("******************\r\n");
|
||||
//os_printf("command %d : 0x%08x 0x%08x\r\n",idx,READ_PERI_REG(I2C_I2C_COMD0_REG(i2c_no)),I2C_GET_COMMAND_OP_CODE(i2c_no,idx));
|
||||
|
||||
idx = 1;
|
||||
//os_printf("IDX2 1: %d \r\n",idx);
|
||||
I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
|
||||
I2C_SET_COMMAND_ACK_EXP(i2c_no,idx,1);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0);
|
||||
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,1);//WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,idx,2); //BYTE NUMBER
|
||||
|
||||
//command2 : master generating stop
|
||||
//idx = 2;
|
||||
idx = 2; //why ??? if no this line, idx is last value not 2
|
||||
//os_printf("IDX2 2: %d \r\n",idx);
|
||||
|
||||
|
||||
I2C_SET_COMMAND_DONE(i2c_no,idx,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,idx,0x3); //STOP
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,idx,0); //NO ACK
|
||||
//os_printf("******************\r\n");
|
||||
//os_printf("command %d : 0x%08x 0x%08x\r\n",idx,READ_PERI_REG(I2C_I2C_COMD1_REG(i2c_no)),I2C_GET_COMMAND_OP_CODE(i2c_no,idx));
|
||||
|
||||
for(i=0;i<byte_num;i++){
|
||||
WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),data_buf[i]);
|
||||
}
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i2c_write_led_test(uint8 i2c_no,uint8 mask1,uint8 mask2, uint8 mask3)
|
||||
{
|
||||
uint8 data_buf[] = {0xa8,
|
||||
0x13, //addr
|
||||
mask1,
|
||||
mask2,
|
||||
mask3,
|
||||
0 //update
|
||||
};
|
||||
uint8 byte_num = sizeof(data_buf);
|
||||
|
||||
I2C_SET_TX_FIFO_RST(0,1);
|
||||
I2C_SET_TX_FIFO_RST(0,0);
|
||||
|
||||
//command0 : sending restart signal
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,0,0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,0,0);
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,0,1);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,1,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,1,1);//WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,1,byte_num); //BYTE NUMBER
|
||||
|
||||
//command2 : master generating stop
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,2,0x3); //STOP
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,2,0); //NO ACK
|
||||
|
||||
|
||||
int i = 0;
|
||||
for(i=0;i<byte_num;i++){
|
||||
WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),data_buf[i]);
|
||||
}
|
||||
|
||||
//start sending
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
|
||||
}
|
||||
|
||||
#if 1
|
||||
void i2c_master_tx_cfg(uint8 i2c_no)
|
||||
{
|
||||
//SET CMD & ACK
|
||||
//I2C_SET_COMMAND0(i2c_no,)
|
||||
|
||||
uint8 data_buf[] = {0xa8,
|
||||
0x0, //addr
|
||||
0x1, //normal mode
|
||||
0XFF,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, //data
|
||||
0x3f,0x0,0x3f,0x01};
|
||||
int byte_num = sizeof(data_buf);
|
||||
|
||||
I2C_SET_TX_FIFO_RST(i2c_no,1);
|
||||
I2C_SET_TX_FIFO_RST(i2c_no,0);
|
||||
|
||||
//I2C_SET_SLAVE_ADDR(i2c_no,0xa8);
|
||||
//I2C_SET_ADDR_10BIT_EN(i2c_no,0);
|
||||
|
||||
//command0 : sending restart signal
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,0,0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,0,0);
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,0,1);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,1,0);
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,1,1);//WRITE COMMAND
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,1,byte_num); //BYTE NUMBER
|
||||
|
||||
//command2 : master generating stop
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,2,0x3); //STOP
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,2,0); //NO ACK
|
||||
|
||||
//command3: start
|
||||
//I2C_SET_COMMAND_OP_CODE(i2c_no,2,0);
|
||||
//I2C_SET_COMMAND_ACK_EN(i2c_no,2,0);
|
||||
//I2C_SET_COMMAND_BYTE_NUM(i2c_no,2,1);
|
||||
//command4: stop
|
||||
//I2C_SET_COMMAND_OP_CODE(i2c_no,3,0x3); //STOP
|
||||
//I2C_SET_COMMAND_ACK_EN(i2c_no,3,0); //NO ACK
|
||||
|
||||
|
||||
//write fifo
|
||||
int i = 0;
|
||||
for(i=0;i<byte_num;i++){
|
||||
WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),data_buf[i]);
|
||||
}
|
||||
|
||||
//start sending
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
for(i = 0;i<50;i++){
|
||||
|
||||
//while(I2C_GET_TRANS_COMPLETE_INT_RAW(0)==0);
|
||||
while(I2C_GET_COMMAND2_DONE(0) == 0);
|
||||
//I2C_SET_TRANS_COMPLETE_INT_CLR(0,1);
|
||||
|
||||
ets_delay_us(5000);
|
||||
ets_delay_us(5000);
|
||||
ets_delay_us(5000);
|
||||
ets_delay_us(5000);
|
||||
|
||||
uint32 m_tmp = (1<<(i%18));
|
||||
uint8 mask1 = (m_tmp>>0) &0x3f ;
|
||||
uint8 mask2 = (m_tmp>>6) &0x3f ;
|
||||
uint8 mask3 = (m_tmp>>12) &0x3f ;
|
||||
i2c_write_led_test(i2c_no,mask1,mask2, mask3);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
void i2c_master_tx_cfg(uint8 i2c_no)
|
||||
{
|
||||
//SET CMD & ACK
|
||||
//I2C_SET_COMMAND0(i2c_no,)
|
||||
|
||||
uint8 data_buf[] = {0x0, //addr
|
||||
0x1, //normal mode
|
||||
0XFF,0x1f,0xff,0x1f,0xff,0x1f,0xff,0x1f,0xff,0x1f,0xff,0x1f,0xff,0xff,0xff,0xff,0xff,0xff, //data
|
||||
0x3f,0x0,0x3f,0x01};
|
||||
int byte_num = sizeof(data_buf);
|
||||
|
||||
I2C_SET_TX_FIFO_RST(i2c_no,1);
|
||||
I2C_SET_TX_FIFO_RST(i2c_no,0);
|
||||
|
||||
//I2C_SET_SLAVE_ADDR(i2c_no,0xa8);
|
||||
//I2C_SET_ADDR_10BIT_EN(i2c_no,0);
|
||||
|
||||
//command0 : sending restart signal
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,0,0);
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,0,0);
|
||||
I2C_SET_COMMAND_BYTE_NUM(i2c_no,0,1);
|
||||
|
||||
//command1 : picking slave and sending data
|
||||
//I2C_SET_COMMAND_ACK_EN(i2c_no,1,0);
|
||||
//I2C_SET_COMMAND_OP_CODE(i2c_no,1,1);//WRITE COMMAND
|
||||
//I2C_SET_COMMAND_BYTE_NUM(i2c_no,1,byte_num+1); //BYTE NUMBER
|
||||
|
||||
//command2 : master generating stop
|
||||
I2C_SET_COMMAND_OP_CODE(i2c_no,1,0x3); //STOP
|
||||
I2C_SET_COMMAND_ACK_EN(i2c_no,1,0); //NO ACK
|
||||
|
||||
//command3: start
|
||||
//I2C_SET_COMMAND_OP_CODE(i2c_no,2,0);
|
||||
//I2C_SET_COMMAND_ACK_EN(i2c_no,2,0);
|
||||
//I2C_SET_COMMAND_BYTE_NUM(i2c_no,2,1);
|
||||
//command4: stop
|
||||
//I2C_SET_COMMAND_OP_CODE(i2c_no,3,0x3); //STOP
|
||||
//I2C_SET_COMMAND_ACK_EN(i2c_no,3,0); //NO ACK
|
||||
|
||||
//write fifo
|
||||
WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),0xa8); //SLAVE ADDRESS: 7BIT ADDR + R/W BIT
|
||||
int i = 0;
|
||||
for(i=0;i<byte_num;i++){
|
||||
//WRITE_PERI_REG(I2C_I2C_DATA_REG(i2c_no),data_buf[i]);
|
||||
}
|
||||
|
||||
//start sending
|
||||
I2C_SET_TRANS_START(i2c_no,1);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define I2C_INT_STR "I2C0 INTR:"
|
||||
void i2c_rx_intr_handler()
|
||||
{
|
||||
uint8 i2c_no = 0; //UART1
|
||||
uint32 i2c_intr_status = READ_PERI_REG(I2C_I2C_INT_STATUS_REG(i2c_no));
|
||||
|
||||
uint16 fifo_len = I2C_GET_RXFIFO_CNT(i2c_no);
|
||||
uint16 tx_fifo_len = I2C_GET_TXFIFO_CNT(i2c_no);
|
||||
uint16 i = 0;
|
||||
os_printf("====================================================");
|
||||
os_printf("IN I2C RX INTR !!!!!!!!\r\n");
|
||||
os_printf("\n\n\n\n===================================================");
|
||||
|
||||
os_printf("i2c_intr_status: 0x%08x \r\n",i2c_intr_status);
|
||||
if( (i2c_intr_status >> I2C_RXFIFO_FULL_INT_ST_S)&I2C_RXFIFO_FULL_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_RXFIFO_FULL_INT, fifo_len: %d\r\n",fifo_len);
|
||||
for(i=0;i<fifo_len;i++){
|
||||
os_printf("%c",I2C_GET_FIFO_RDATA(i2c_no));
|
||||
}
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TXFIFO_EMPTY_INT_ST_S)&I2C_TXFIFO_EMPTY_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_TXFIFO_EMPTY_INT, TX_fifo_len: %d\r\n",tx_fifo_len);
|
||||
I2C_SET_TXFIFO_EMPTY_INT_ENA(i2c_no,0);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_RXFIFO_OVF_INT_ST_S)&I2C_RXFIFO_OVF_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_RXFIFO_OVF_INT, fifo_len: %d\r\n",fifo_len);
|
||||
for(i=0;i<fifo_len;i++){
|
||||
os_printf("%c",I2C_GET_FIFO_RDATA(i2c_no));
|
||||
}
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_SLAVE_TRAN_COMP_INT_ST_S)&I2C_SLAVE_TRAN_COMP_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_SLAVE_TRAN_COMP_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_ARBITRATION_LOST_INT_ST_S)&I2C_ARBITRATION_LOST_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_ARBITRATION_LOST_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_MASTER_TRAN_COMP_INT_ST_S)&I2C_MASTER_TRAN_COMP_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_MASTER_TRAN_COMP_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TRANS_COMPLETE_INT_ST_S)&I2C_TRANS_COMPLETE_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_TRANS_COMPLETE_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TIME_OUT_INT_ST_S)&I2C_TIME_OUT_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_TIME_OUT_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
os_printf("DISABLE TOUT INT...time out status: %d \r\n",I2C_GET_TIME_OUT(0));
|
||||
I2C_SET_TIME_OUT_INT_ENA(i2c_no,0);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TRANS_START_INT_ST_S)&I2C_TRANS_START_INT_ST_V){
|
||||
os_printf(I2C_INT_STR"I2C_TRANS_START_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
|
||||
//uart_intr_status = READ_PERI_REG(UART_INT_ST_REG(uart_no)) ;
|
||||
SET_PERI_REG_MASK(I2C_I2C_INT_CLR_REG(i2c_no),i2c_intr_status);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#define I2C1_INT_STR "I2C0 INTR:"
|
||||
|
||||
void i2c1_rx_intr_handler()
|
||||
{
|
||||
uint8 i2c_no = 1; //UART1
|
||||
uint32 i2c_intr_status = READ_PERI_REG(I2C_I2C_INT_STATUS_REG(i2c_no));
|
||||
|
||||
uint16 fifo_len = I2C_GET_RXFIFO_CNT(i2c_no);
|
||||
uint16 tx_fifo_len = I2C_GET_TXFIFO_CNT(i2c_no);
|
||||
uint16 i = 0;
|
||||
os_printf("====================================================");
|
||||
os_printf("IN I2C RX INTR !!!!!!!!\r\n");
|
||||
os_printf("\n\n\n\n===================================================");
|
||||
|
||||
os_printf("i2c_intr_status: 0x%08x \r\n",i2c_intr_status);
|
||||
if( (i2c_intr_status >> I2C_RXFIFO_FULL_INT_ST_S)&I2C_RXFIFO_FULL_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_RXFIFO_FULL_INT, fifo_len: %d\r\n",fifo_len);
|
||||
for(i=0;i<fifo_len;i++){
|
||||
os_printf("%c",I2C_GET_FIFO_RDATA(i2c_no));
|
||||
}
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TXFIFO_EMPTY_INT_ST_S)&I2C_TXFIFO_EMPTY_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_TXFIFO_EMPTY_INT, TX_fifo_len: %d\r\n",tx_fifo_len);
|
||||
I2C_SET_TXFIFO_EMPTY_INT_ENA(i2c_no,0);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_RXFIFO_OVF_INT_ST_S)&I2C_RXFIFO_OVF_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_RXFIFO_OVF_INT, fifo_len: %d\r\n",fifo_len);
|
||||
for(i=0;i<fifo_len;i++){
|
||||
os_printf("%c",I2C_GET_FIFO_RDATA(i2c_no));
|
||||
}
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_SLAVE_TRAN_COMP_INT_ST_S)&I2C_SLAVE_TRAN_COMP_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_SLAVE_TRAN_COMP_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_ARBITRATION_LOST_INT_ST_S)&I2C_ARBITRATION_LOST_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_ARBITRATION_LOST_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_MASTER_TRAN_COMP_INT_ST_S)&I2C_MASTER_TRAN_COMP_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_MASTER_TRAN_COMP_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TRANS_COMPLETE_INT_ST_S)&I2C_TRANS_COMPLETE_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_TRANS_COMPLETE_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TIME_OUT_INT_ST_S)&I2C_TIME_OUT_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_TIME_OUT_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
os_printf("DISABLE TOUT INT...time out status: %d \r\n",I2C_GET_TIME_OUT(0));
|
||||
I2C_SET_TIME_OUT_INT_ENA(i2c_no,0);
|
||||
}
|
||||
else if( (i2c_intr_status >> I2C_TRANS_START_INT_ST_S)&I2C_TRANS_START_INT_ST_V){
|
||||
os_printf(I2C1_INT_STR"I2C_TRANS_START_INT_ST, fifo_len: %d\r\n",fifo_len);
|
||||
}
|
||||
|
||||
//uart_intr_status = READ_PERI_REG(UART_INT_ST_REG(uart_no)) ;
|
||||
SET_PERI_REG_MASK(I2C_I2C_INT_CLR_REG(i2c_no),i2c_intr_status);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void i2c_intr_config()
|
||||
{
|
||||
os_printf("===========================\r\n");
|
||||
os_printf("I2C0 TEST INTR CONFIG\r\n");
|
||||
os_printf("===========================\r\n");
|
||||
|
||||
ETS_INTR_DISABLE(ETS_I2C0_INUM);
|
||||
//REG_SET_FIELD(PRO_UART1_INTR_MAP_REG,DPORT_PRO_UART1_INTR_MAP,ETS_UART1_INUM);
|
||||
intr_matrix_set(ETS_I2C0_SOURCE, ETS_I2C0_INUM);
|
||||
ETS_INTR_ATTACH(i2c_rx_intr_handler, NULL,ETS_I2C0_INUM);
|
||||
ETS_INTR_ENABLE(ETS_I2C0_INUM);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
|
@ -1,466 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "stdarg.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "audio_log.h"
|
||||
#include "ES8388.h"
|
||||
#include "i2c_soft.h"
|
||||
//#if 0
|
||||
|
||||
// I2STest: 1 -> I2S moudle test slef,Tx->Rx
|
||||
// I2STest: 2 -> I2S moudle read wave data to decoder(WM8960/WM8978)
|
||||
// I2STest: others -> Reverse.
|
||||
#define I2STest 2
|
||||
#define I2SBUFSZ (81920)
|
||||
char *I2sBuf=(char*)0x3ffa8000; //0x3FFBC000
|
||||
char *bufWrPos;
|
||||
char *bufRdPos;
|
||||
|
||||
|
||||
static i2s_dma_attr_t i2sDmaTxObj, i2sDmaRxObj;
|
||||
static uint32_t recvCnt =0;
|
||||
static uint32_t setBufLen = (1024*3); // buffer length bytes
|
||||
|
||||
extern uint8_t musicTable[];
|
||||
extern uint32_t tabSize;
|
||||
|
||||
static uint32_t loadSize = 0;
|
||||
static uint32_t initVlaue = 0;
|
||||
|
||||
SemaphoreHandle_t xSemPlayEnd;
|
||||
xQueueHandle uartQueue;
|
||||
extern SemaphoreHandle_t xSemUartCmd;
|
||||
|
||||
extern void __ShowI2S_REGValue();
|
||||
#define SHOWI2SREG() __ShowI2S_REGValue()
|
||||
|
||||
|
||||
int BufFill()
|
||||
{
|
||||
int fill = bufWrPos - bufRdPos;
|
||||
if (fill < 0) fill += I2SBUFSZ;
|
||||
return fill;
|
||||
}
|
||||
|
||||
void BufRead(char *dest, int n) {
|
||||
|
||||
while (n--) {
|
||||
*dest++ = *bufRdPos++;
|
||||
if (bufRdPos==I2sBuf+I2SBUFSZ) {
|
||||
bufRdPos=I2sBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BufWrite(char *src, int n) {
|
||||
while (n--) {
|
||||
*bufWrPos++ = initVlaue++;//*src++;
|
||||
if (bufWrPos==I2sBuf+I2SBUFSZ) {
|
||||
bufWrPos=I2sBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
int32_t flag =0;
|
||||
|
||||
|
||||
// @brief Fill test data to buffer
|
||||
static void set_buffer2Zero(uint32_t *buffer, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t *pbuff = (uint8_t *)buffer;
|
||||
for (i = 0; i < (len); i++) {
|
||||
*pbuff++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @brief Read receive ping-pong buffer to buffer
|
||||
void readToRecvBuf_es8388(uint32_t *buffer, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t *pbuff = (uint8_t*)buffer;
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
printf("buffer=%x,recvCnt=%d, bufWrPos=%x\r\n", (uint32_t)buffer,recvCnt, (uint32_t)bufWrPos);
|
||||
|
||||
|
||||
for (i = 0; i < len ; i++) {
|
||||
*bufWrPos++ = *pbuff++;
|
||||
//printf("%08x",*buffer++);
|
||||
recvCnt++;
|
||||
if (recvCnt > (I2SBUFSZ)) {
|
||||
printf("receive buffer,full, bufWrPos=%x recvCnt=%d\r\n", (uint32_t)bufWrPos, recvCnt);
|
||||
bufWrPos=I2sBuf;
|
||||
recvCnt = 0;
|
||||
i2s_stop(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_RX);
|
||||
xSemaphoreGiveFromISR(xSemPlayEnd, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @brief Configrate the I2S pin.
|
||||
void i2s_pin_init(i2s_mode_t mode)
|
||||
{
|
||||
if (mode == I2S_MODE_MASTER_TX) {
|
||||
// MCLK
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); //);
|
||||
SET_PERI_REG_BITS(PIN_CTRL, CLK_OUT1, 0, CLK_OUT1_S);
|
||||
|
||||
gpio_matrix_out(25, I2S0O_WS_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(26, I2S0O_BCK_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(22, I2S0O_DATA_OUT23_IDX, 0, 0);
|
||||
|
||||
ets_printf("I2SPinInit Master_Tx \r\n");
|
||||
|
||||
} else if (mode == I2S_MODE_SLAVE_TX) {
|
||||
|
||||
// signal select
|
||||
gpio_matrix_in(21, I2S0I_WS_IN_IDX, 0);
|
||||
gpio_matrix_in(22, I2S0I_BCK_IN_IDX, 0);
|
||||
gpio_matrix_out(23, I2S0O_DATA_OUT23_IDX, 0, 0);
|
||||
// MCLK
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
// Select gpio function
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_GPIO21);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_GPIO22);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO23_U, FUNC_GPIO23_GPIO23);
|
||||
// pull up or pull down
|
||||
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO21_U, FUN_IE | FUN_PU);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO22_U, FUN_IE | FUN_PU);
|
||||
PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO23_U);
|
||||
} else if (mode == I2S_MODE_MASTER_RX) {
|
||||
// signal select
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); //);
|
||||
SET_PERI_REG_BITS(PIN_CTRL, CLK_OUT1, 0, CLK_OUT1_S);
|
||||
|
||||
gpio_matrix_out(26, I2S0O_WS_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(25, I2S0O_BCK_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(22, I2S0I_DATA_IN15_IDX, 0);
|
||||
|
||||
} else if (mode == I2S_MODE_SLAVE_RX) {
|
||||
// signal select
|
||||
gpio_matrix_in(16, I2S0I_WS_IN_IDX, 0);
|
||||
gpio_matrix_in(17, I2S0I_BCK_IN_IDX, 0);
|
||||
gpio_matrix_in(18, I2S0I_DATA_IN15_IDX, 0);
|
||||
// Select gpio function
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_GPIO16);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_GPIO17);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, FUNC_GPIO18_GPIO18);
|
||||
// pull up or pull down
|
||||
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO16_U, FUN_IE | FUN_PU);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO17_U, FUN_IE | FUN_PU);
|
||||
SET_PERI_REG_MASK(PERIPHS_IO_MUX_GPIO18_U, FUN_IE | FUN_PU);
|
||||
}
|
||||
}
|
||||
|
||||
// @brief Fill test data to buffer
|
||||
void loadMusicData_es8388(uint32_t *buffer, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t *pbuff = (uint8_t*)buffer;
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
printf("bufAddr=%x, bufRdPos=%x\r\n", (uint32_t)pbuff, (uint32_t)bufRdPos);
|
||||
for (i = 0; i < len; i++) {
|
||||
*pbuff++ = *bufRdPos++;
|
||||
loadSize++;
|
||||
if (loadSize>tabSize) {
|
||||
printf("Music play finished. musicTable=%x bufRdPos=%x,loadSize=%x\r\n", (uint32_t)musicTable,
|
||||
(uint32_t)bufRdPos, loadSize);
|
||||
bufRdPos= (char*)musicTable;
|
||||
loadSize = 0;
|
||||
i2s_stop(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
xSemaphoreGiveFromISR(xSemPlayEnd, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
}
|
||||
// @brief I2S interrupt service routine.
|
||||
void I2SDmaIsr_es8388(void *para)
|
||||
{
|
||||
portBASE_TYPE HPTaskAwoken=0;
|
||||
int dummy;
|
||||
uint32_t intrStatus = i2s_int_status_get(I2S_NUM_I2S0);
|
||||
i2s_int_clear(I2S_NUM_I2S0, 0xffffffff);
|
||||
printf("intrStatus12=%x\r\n",intrStatus);
|
||||
if (0 == intrStatus) {
|
||||
//No interested interrupts pending
|
||||
return;
|
||||
}
|
||||
//clear all intrs
|
||||
//process every intr
|
||||
if (intrStatus & I2S_INT_SRC_ONE_BUF_SEND_DONE) {
|
||||
////find the DMA which sends the interrupt signal
|
||||
uint32_t *bufAddr = NULL;
|
||||
bufAddr = i2s_dma_status_get(I2S_NUM_I2S0, &i2sDmaTxObj);
|
||||
if (NULL == bufAddr) {
|
||||
printf("bufAddr is null\r\n");
|
||||
}
|
||||
loadMusicData_es8388(bufAddr, setBufLen);
|
||||
}
|
||||
|
||||
//Receiver data record
|
||||
if (intrStatus & I2S_INT_SRC_ONE_BUF_RECV_DONE) {
|
||||
uint32_t *recvBuf = NULL;
|
||||
// recvBuf = i2s_dma_status_get(I2S_NUM_I2S0, &i2sDmaRxObj);
|
||||
// readToRecvBuf_es8388(recvBuf, setBufLen);
|
||||
}
|
||||
}
|
||||
|
||||
void i2sDmaBufInit_es8388()
|
||||
{
|
||||
int dmaRegt;
|
||||
// Tx DMA buffer init
|
||||
memset(&i2sDmaTxObj, 0, sizeof(i2sDmaTxObj));
|
||||
i2sDmaTxObj.buf = NULL;
|
||||
i2sDmaTxObj.buf_size = setBufLen;
|
||||
i2sDmaTxObj.mode = I2S_MODE_MASTER_TX;
|
||||
dmaRegt = i2s_dma_init(I2S_NUM_I2S0, &i2sDmaTxObj, I2SDmaIsr_es8388);
|
||||
if (dmaRegt) {
|
||||
LOGE("I2SDmaInit init failed ret=%d", dmaRegt);
|
||||
return;
|
||||
}
|
||||
LOGD("i2sDmaTx buf=%x dataPing=%x pongAddr=%x\r\n", i2sDmaTxObj.buf,
|
||||
i2s_dma_ping_buf_get(&i2sDmaTxObj), i2s_dma_pong_buf_get(&i2sDmaTxObj));
|
||||
i2s_dma_dest_add_set(I2S_NUM_I2S0, &i2sDmaTxObj);
|
||||
i2s_dma_enable(I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
|
||||
// Rx DMA buffer init
|
||||
memset(&i2sDmaRxObj, 0, sizeof(i2sDmaRxObj));
|
||||
i2sDmaRxObj.buf = NULL;
|
||||
i2sDmaRxObj.buf_size = setBufLen;
|
||||
i2sDmaRxObj.mode = I2S_MODE_MASTER_RX;
|
||||
dmaRegt = i2s_dma_init(I2S_NUM_I2S0, &i2sDmaRxObj, I2SDmaIsr_es8388);
|
||||
if (dmaRegt) {
|
||||
LOGE("I2SDmaInit init failed ret=%d", dmaRegt);
|
||||
return;
|
||||
}
|
||||
LOGD("i2sDmaRx buf=%x dataPing=%x pongAddr=%x\r\n", i2sDmaRxObj.buf,
|
||||
i2s_dma_ping_buf_get(&i2sDmaRxObj), i2s_dma_pong_buf_get(&i2sDmaRxObj));
|
||||
i2s_dma_dest_add_set(I2S_NUM_I2S0, &i2sDmaRxObj);
|
||||
i2s_dma_enable(I2S_NUM_I2S0, I2S_MODE_MASTER_RX);
|
||||
|
||||
}
|
||||
|
||||
void i2sTxModeInit_es8388()
|
||||
{
|
||||
i2s_attr_t i2sAttr;
|
||||
i2s_reset(I2S_NUM_I2S0);
|
||||
memset(&i2sAttr, 0, sizeof(i2sAttr));
|
||||
// int x,y,z;
|
||||
// int F,M;
|
||||
// F= 40000000;
|
||||
// M = 2048000;
|
||||
|
||||
// printf("Freq read\r\n");
|
||||
// int ret = 0;
|
||||
// int pre_ret = 0;
|
||||
// for (z=0; z<256;z++) {
|
||||
// for (y=0; y<32;y++) {
|
||||
// for (x=2; x<=10;x++) {
|
||||
// ret = (F*x+4*F) - ((4*M*z)+(2*z*M*y));
|
||||
// if (ret < pre_ret) {
|
||||
// printf("Found beter freq,x:%d,y:%d,z:%d\r\n", z, y, x);
|
||||
// break;
|
||||
// }
|
||||
// else {
|
||||
// pre_ret = ret;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// printf("Freq,x:%d,y:%d,z:%d\r\n", z, y, x);
|
||||
i2sAttr.tx_mode.type = I2S_MODULE_WORK_TYPE_I2S;
|
||||
i2sAttr.tx_mode.mode = I2S_MODE_MASTER_TX;
|
||||
i2sAttr.tx_mode.rate = I2S_SAMPLE_RATE_8K;
|
||||
i2sAttr.tx_mode.bits = I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2sAttr.tx_mode.std = I2S_STD_FORMAT_I2S;
|
||||
i2sAttr.tx_mode.iface = I2S_IFACE_TYPE_DMA;
|
||||
i2sAttr.tx_mode.channel = I2S_CHANNEL_FMT_RIGHT_LEFT;
|
||||
i2s_init(I2S_NUM_I2S0, &i2sAttr);
|
||||
|
||||
i2sDmaBufInit_es8388();
|
||||
|
||||
SHOWI2SREG();
|
||||
}
|
||||
|
||||
void i2sRxModeInit_es8388()
|
||||
{
|
||||
i2s_attr_t i2sAttr;
|
||||
memset(&i2sAttr, 0, sizeof(i2sAttr));
|
||||
i2sAttr.rx_mode.type = I2S_MODULE_WORK_TYPE_I2S;
|
||||
i2sAttr.rx_mode.mode = I2S_MODE_MASTER_RX;
|
||||
i2sAttr.rx_mode.rate = I2S_SAMPLE_RATE_8K;
|
||||
i2sAttr.rx_mode.bits = I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2sAttr.rx_mode.std = I2S_STD_FORMAT_I2S;
|
||||
i2sAttr.rx_mode.iface = I2S_IFACE_TYPE_DMA;
|
||||
i2sAttr.rx_mode.channel = I2S_CHANNEL_FMT_RIGHT_LEFT;
|
||||
i2s_init(I2S_NUM_I2S0, &i2sAttr);
|
||||
SHOWI2SREG();
|
||||
}
|
||||
//½øÈëPCM ·ÅÒôģʽ
|
||||
void recorder_enter_play_mode_es8388(void)
|
||||
{ // ES8388_ADC_StandBy();
|
||||
//ES8388_PowerOn_Init();
|
||||
ES8388_DAC_Play();
|
||||
vTaskDelay(5);
|
||||
LOGD("Playback the recorder...");
|
||||
i2s_stop(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_RX);
|
||||
int i;
|
||||
// Set data buffer
|
||||
bufRdPos = I2sBuf;
|
||||
bufWrPos = I2sBuf;
|
||||
// BufRead("agc", 81920);
|
||||
uint8_t *recvBuf = (uint8_t*)I2sBuf;
|
||||
|
||||
#if 0
|
||||
|
||||
for(i = 0; i < (I2SBUFSZ); i++) {
|
||||
os_printf("%02x ",*recvBuf++);
|
||||
}
|
||||
|
||||
os_printf("\r\n\r\n");
|
||||
#endif
|
||||
|
||||
tabSize = I2SBUFSZ;
|
||||
uint32_t *dataPing = i2s_dma_ping_buf_get(&i2sDmaTxObj);
|
||||
uint32_t *dataPong = i2s_dma_pong_buf_get(&i2sDmaTxObj);
|
||||
loadMusicData_es8388(dataPing, setBufLen);
|
||||
loadMusicData_es8388(dataPong, setBufLen);
|
||||
i2sTxModeInit_es8388();
|
||||
|
||||
i2s_start(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
}
|
||||
|
||||
|
||||
void recorder_enter_rec_mode_es8388(void)
|
||||
{
|
||||
LOGD("start to recorder...");
|
||||
i2s_stop(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
i2c_master_gpio_init();
|
||||
ES8388_PowerOn_Init();
|
||||
ES8388_ADC_Record();
|
||||
i2sRxModeInit_es8388();
|
||||
|
||||
i2sDmaBufInit_es8388();
|
||||
|
||||
i2s_pin_init(I2S_MODE_MASTER_RX);
|
||||
|
||||
i2s_start(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_RX);
|
||||
}
|
||||
|
||||
void PlayWavMusic_es8388()
|
||||
{
|
||||
// i2c_master_gpio_init();
|
||||
// ES8388_PowerOn_Init();
|
||||
// ES8388_DAC_Play();
|
||||
vTaskDelay(100);
|
||||
LOGD("Enter play music...");
|
||||
i2sTxModeInit_es8388();
|
||||
i2s_pin_init(I2S_MODE_MASTER_TX);
|
||||
uint32_t *dataPing = i2s_dma_ping_buf_get(&i2sDmaTxObj);
|
||||
uint32_t *dataPong = i2s_dma_pong_buf_get(&i2sDmaTxObj);
|
||||
|
||||
// Test wav music
|
||||
bufRdPos = (char*)musicTable;
|
||||
tabSize = 196174;
|
||||
set_buffer2Zero(dataPing, setBufLen);
|
||||
set_buffer2Zero(dataPong, setBufLen);
|
||||
// loadMusicData_es8388(dataPing, setBufLen);
|
||||
// loadMusicData_es8388(dataPong, setBufLen);
|
||||
vTaskDelay(3000);
|
||||
|
||||
i2s_start(I2S_MODULE_WORK_TYPE_I2S, I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
SHOWI2SREG();
|
||||
}
|
||||
void rec_play_mode_es8388()
|
||||
{
|
||||
// Both of recorder and paly mode
|
||||
LOGD("start to rec_play_mode...");
|
||||
i2s_stop(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
ES8388_ADC_Record();
|
||||
i2sRxModeInit_es8388();
|
||||
i2s_start(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_RX);
|
||||
//i2s_stop(I2S_MODULE_WORK_TYPE_I2S,I2S_NUM_I2S0, I2S_MODE_MASTER_TX);
|
||||
ES8388_DAC_Play();
|
||||
}
|
||||
|
||||
|
||||
void i2s_test_es8388_interface(void* para)
|
||||
{
|
||||
LOGD("I2S module init ok");
|
||||
uint32_t recvDat = 0;
|
||||
|
||||
PlayWavMusic_es8388();
|
||||
// recorder_enter_rec_mode_es8388();
|
||||
for(;;)
|
||||
{
|
||||
// if(xSemaphoreTake(xSemUartCmd, portMAX_DELAY) == pdTRUE )
|
||||
// {
|
||||
// printf("xSemaphoreTake received\r\n");
|
||||
// PlayWavMusic();
|
||||
// }
|
||||
xQueueReceive(uartQueue, &recvDat, portMAX_DELAY);
|
||||
LOGD("recvDat=%x", recvDat);
|
||||
switch (recvDat)
|
||||
{
|
||||
case '1':
|
||||
PlayWavMusic_es8388();
|
||||
break;
|
||||
case '2':
|
||||
recorder_enter_rec_mode_es8388();
|
||||
break;
|
||||
case '3':
|
||||
recorder_enter_play_mode_es8388();
|
||||
break;
|
||||
case '4':
|
||||
rec_play_mode_es8388();
|
||||
break;
|
||||
default:
|
||||
LOGD("Cmd does not support.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void i2s_test_es8388_init(void)
|
||||
{
|
||||
|
||||
LOGD("i2s_test_es8388_init task creating\r\n");
|
||||
xSemPlayEnd = xSemaphoreCreateBinary();
|
||||
xTaskCreate(i2s_test_es8388_interface, "i2s_test_es8388_interface", 4096, NULL, 4, NULL);
|
||||
uartQueue = xQueueCreate(1, sizeof(uint32_t*));
|
||||
|
||||
LOGD("i2s_test_es8388_init task create ok\r\n");
|
||||
}
|
||||
//#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
Copyright 2006 - 2011 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Implements additional string functionality.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "MyString.h"
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define strnicmp _strnicmp
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX
|
||||
#define strnicmp strncasecmp
|
||||
#endif
|
||||
|
||||
int EndsWith(const char* str, const char* endsWith, int ignoreCase)
|
||||
{
|
||||
int strLen, ewLen, offset;
|
||||
int cmp = 0;
|
||||
|
||||
strLen = (int)strlen(str);
|
||||
ewLen = (int)strlen(endsWith);
|
||||
if (ewLen > strLen) return 0;
|
||||
offset = strLen - ewLen;
|
||||
|
||||
if (ignoreCase != 0) {
|
||||
cmp = strncmp(str + offset, endsWith, ewLen);
|
||||
} else {
|
||||
cmp = strncmp(str + offset, endsWith, ewLen);
|
||||
}
|
||||
|
||||
return cmp == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
int IndexOf(const char* str, const char* findThis)
|
||||
{
|
||||
int i, j, strLen, ftLen;
|
||||
|
||||
strLen = (int)strlen(str);
|
||||
ftLen = (int)strlen(findThis);
|
||||
|
||||
if (ftLen <= strLen) {
|
||||
for (i = 0; i < strLen; i++) {
|
||||
for (j = 0; j < ftLen; j++) {
|
||||
if (str[i + j] != findThis[j]) break;
|
||||
}
|
||||
if (j == ftLen) return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LastIndexOf(const char* str, const char* findThis)
|
||||
{
|
||||
int i, j, strLen, ftLen;
|
||||
|
||||
strLen = (int)strlen(str);
|
||||
ftLen = (int)strlen(findThis);
|
||||
|
||||
if (ftLen <= strLen) {
|
||||
for (i = strLen - ftLen; i >= 0; i--) {
|
||||
for (j = 0; j < ftLen; j++) {
|
||||
if (str[i + j] != findThis[j]) break;
|
||||
}
|
||||
if (j == ftLen) return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int StartsWith(const char* str, const char* startsWith, int ignoreCase)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
if (ignoreCase != 0) {
|
||||
cmp = strncmp(str, startsWith, (int)strlen(startsWith));
|
||||
} else {
|
||||
cmp = strncmp(str, startsWith, (int)strlen(startsWith));
|
||||
}
|
||||
|
||||
return cmp == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
void debug_func3()
|
||||
{
|
||||
printf("debug_func3...\r\n");
|
||||
}
|
||||
|
|
@ -1,321 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "audio_log.h"
|
||||
#include "EspAudioCom.h"
|
||||
#include "Storage.h"
|
||||
#include "Utility.h"
|
||||
#include "string.h"
|
||||
#include "psramApi.h"
|
||||
|
||||
static char *audioBuf;
|
||||
static char *audioBufWrPos;
|
||||
static char *audioBufRdPos;
|
||||
|
||||
mutex_t audioBufMutex;
|
||||
#ifdef AUDIO_BUFFER_ADDR
|
||||
#define ISMALLOC 0
|
||||
#else
|
||||
#define ISMALLOC 1
|
||||
#endif
|
||||
|
||||
uint32_t rdpos,wrpos;
|
||||
|
||||
static QueueHandle_t queWrQuit;
|
||||
static QueueHandle_t queRdQuit;
|
||||
|
||||
/**
|
||||
* @brief Initialize buffer
|
||||
*
|
||||
*/
|
||||
int audioBufInit()
|
||||
{
|
||||
int ret = 0;
|
||||
#if (ISMALLOC == 1)
|
||||
audioBuf = malloc(AUDIO_BUFFER_SIZE);
|
||||
if (NULL == audioBuf) {
|
||||
LOGE("malloc is failed.");
|
||||
}
|
||||
|
||||
LOGD("Audio buffer malloc is ok,%x.", audioBuf);
|
||||
#else
|
||||
audioBuf = (char*)AUDIO_BUFFER_ADDR;
|
||||
LOGD("Audio buffer address is%x, size %d bytes.", audioBuf,AUDIO_BUFFER_SIZE);
|
||||
#endif
|
||||
|
||||
if (NULL == audioBuf) {
|
||||
LOGE("[audioBufInit]malloc failed!\r\n");
|
||||
ret = -1;
|
||||
}
|
||||
audioBufRdPos = audioBuf;
|
||||
audioBufWrPos = audioBuf;
|
||||
mutex_init(&audioBufMutex);
|
||||
rdpos = 0;
|
||||
wrpos = 0;
|
||||
LOGI("[%08x]%s++++%d\r\n", (uint32_t)audioBufMutex, __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize buffer
|
||||
*
|
||||
*/
|
||||
void audioBufUninit()
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
mutex_lock(&audioBufMutex);
|
||||
audioBufRdPos = NULL;
|
||||
audioBufWrPos = NULL;
|
||||
if (audioBuf) {
|
||||
#if (ISMALLOC == 1)
|
||||
free(audioBuf);
|
||||
#endif
|
||||
audioBuf = NULL;
|
||||
}
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the size of the specified buffer, in bytes.
|
||||
*
|
||||
*/
|
||||
void audioBufRdQuitCfg(void * que)
|
||||
{
|
||||
configASSERT(que);
|
||||
mutex_lock(&audioBufMutex);
|
||||
LOGD("que=%p",que);
|
||||
queRdQuit = (QueueHandle_t)que;
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the size of the specified buffer, in bytes.
|
||||
*
|
||||
*/
|
||||
void audioBufWrQuitCfg(void * que)
|
||||
{
|
||||
configASSERT(que);
|
||||
mutex_lock(&audioBufMutex);
|
||||
LOGD("que=%p",que);
|
||||
queWrQuit = (QueueHandle_t)que;
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieves the size of the specified buffer, in bytes.
|
||||
*
|
||||
*/
|
||||
int audioBufFillGet()
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
mutex_lock(&audioBufMutex);
|
||||
int fill = audioBufWrPos - audioBufRdPos;
|
||||
if (fill < 0) {
|
||||
fill += AUDIO_BUFFER_SIZE;
|
||||
}
|
||||
mutex_unlock(&audioBufMutex);
|
||||
return fill;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reads data from the specified buffer.
|
||||
*
|
||||
*/
|
||||
int audioBufRead(char *dest, int n, uint32_t t)
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
int ret = 0;
|
||||
char *outDest = dest;
|
||||
if (NULL == outDest) {
|
||||
LOGE(">>>>> audioBufRead dest is NULL\r\n");
|
||||
return -1;
|
||||
}
|
||||
retryR:
|
||||
ret = audioBufFillGet();
|
||||
if (ret < n) {
|
||||
int flag = 0;
|
||||
LOGD("Waiting readable semaphore,wanted[%d] fill[%d] timeout[%d]",n, ret, t);
|
||||
if (xQueueReceive(queRdQuit, &flag, t)) {
|
||||
LOGE("receive a read quit queue\r\n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
goto retryR;
|
||||
}
|
||||
}
|
||||
ret = n;
|
||||
mutex_lock(&audioBufMutex);
|
||||
#if (ISMALLOC == 1)
|
||||
while (n--) {
|
||||
*outDest++ = *audioBufRdPos++;
|
||||
rdpos++;
|
||||
if (audioBufRdPos == (audioBuf + AUDIO_BUFFER_SIZE)) {
|
||||
audioBufRdPos = audioBuf;
|
||||
// LOGD(">>>>> audioBuf+ ReadPos + AUDIO_BUFFER_SIZE\r\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(n + audioBufRdPos <= (audioBuf + AUDIO_BUFFER_SIZE))
|
||||
{
|
||||
psram_cache_memcpy((uint8_t*) outDest, (uint8_t*) audioBufRdPos, n);
|
||||
audioBufRdPos += n;
|
||||
} else {
|
||||
uint32_t len = audioBuf + AUDIO_BUFFER_SIZE - audioBufRdPos;
|
||||
psram_cache_memcpy((uint8_t*) outDest, (uint8_t*) audioBufRdPos, len);
|
||||
|
||||
outDest += len;
|
||||
len = n - len;
|
||||
psram_cache_memcpy((uint8_t*) outDest, (uint8_t*) audioBuf, len);
|
||||
audioBufRdPos = audioBuf + len;
|
||||
}
|
||||
rdpos += n;
|
||||
#endif
|
||||
|
||||
mutex_unlock(&audioBufMutex);
|
||||
// LOGD("r:%p w:%p,rdpos=%d,wrpos=%d,dlt=%d f=%d",audioBufRdPos,audioBufWrPos,rdpos,wrpos,(wrpos-rdpos),audioBufFillGet());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes data to the specified buffer.
|
||||
*
|
||||
*/
|
||||
int audioBufWrite(char *src, int n, uint32_t t)
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
char *inSrc = src;
|
||||
int ret = n;
|
||||
if (NULL == inSrc) {
|
||||
ret = -1;
|
||||
LOGE("Source is NULL\r\n");
|
||||
return ret;
|
||||
}
|
||||
int empty;
|
||||
retryW:
|
||||
empty = (AUDIO_BUFFER_SIZE - audioBufFillGet());
|
||||
if (empty < n) {
|
||||
int flag = 0;
|
||||
LOGD("Waiting writeable semaphore,wanted[%d] empty[%d] timeout[%d]",n, empty, t);
|
||||
if (xQueueReceive(queWrQuit, &flag, t)) {
|
||||
LOGE("receive a write quit queue\r\n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
goto retryW;
|
||||
}
|
||||
}
|
||||
mutex_lock(&audioBufMutex);
|
||||
#if (ISMALLOC == 1)
|
||||
while (n--) {
|
||||
*audioBufWrPos++ = *inSrc++;
|
||||
wrpos++;
|
||||
if (audioBufWrPos == (audioBuf + AUDIO_BUFFER_SIZE)) {
|
||||
audioBufWrPos = audioBuf;
|
||||
//LOGD(">>>>> audioBuf+ WritePos + AUDIO_BUFFER_SIZE\r\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(n + audioBufWrPos <= (audioBuf + AUDIO_BUFFER_SIZE))
|
||||
{
|
||||
psram_cache_memcpy((uint8_t*) audioBufWrPos, (uint8_t*) src, n);
|
||||
audioBufWrPos += n;
|
||||
} else {
|
||||
uint32_t len = audioBuf + AUDIO_BUFFER_SIZE - audioBufWrPos;
|
||||
psram_cache_memcpy((uint8_t*) audioBufWrPos, (uint8_t*) inSrc, len);
|
||||
inSrc += len;
|
||||
len = n - len;
|
||||
psram_cache_memcpy((uint8_t*) audioBuf, (uint8_t*) inSrc, len);
|
||||
audioBufWrPos = audioBuf + len;
|
||||
}
|
||||
wrpos += n;
|
||||
#endif
|
||||
mutex_unlock(&audioBufMutex);
|
||||
// LOGD("r:%p w:%p,rdpos=%d,wrpos=%d,dlt=%d f=%d",audioBufRdPos,audioBufWrPos,rdpos,wrpos,(wrpos-rdpos),audioBufFillGet());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the write and read buffer pointer.
|
||||
*
|
||||
*/
|
||||
void audioBufRestAll()
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
mutex_lock(&audioBufMutex);
|
||||
|
||||
audioBufWrPos = audioBuf;
|
||||
audioBufRdPos = audioBuf;
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the read buffer address.
|
||||
*
|
||||
*/
|
||||
void audioBufRdRest()
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
mutex_lock(&audioBufMutex);
|
||||
audioBufRdPos = audioBuf;
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the write buffer address.
|
||||
*
|
||||
*/
|
||||
void audioBufWrRest()
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
mutex_lock(&audioBufMutex);
|
||||
audioBufWrPos = audioBuf;
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the buffer read and write position.
|
||||
*
|
||||
*/
|
||||
void audioBufPosGet(uint32_t *rdPos, uint32_t *wrPos)
|
||||
{
|
||||
configASSERT(audioBufMutex);
|
||||
mutex_lock(&audioBufMutex);
|
||||
*wrPos = (uint32_t)audioBufWrPos;
|
||||
*rdPos = (uint32_t)audioBufRdPos;
|
||||
mutex_unlock(&audioBufMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the buffer read and write position.
|
||||
*
|
||||
*/
|
||||
void audioBufRdPosSet(uint32_t *rdPos)
|
||||
{
|
||||
audioBufRdPos = (char*)*rdPos;
|
||||
}
|
||||
|
||||
|
||||
// end
|
|
@ -1,346 +0,0 @@
|
|||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "Utility.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "MyString.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define UTL_MALLOC malloc
|
||||
#define UTL_FREE free
|
||||
|
||||
int utl_malloc_counter = 0;
|
||||
void* utl_malloc (int size)
|
||||
{
|
||||
++utl_malloc_counter;
|
||||
#ifdef TRACK_MALLOC_VERBOSE
|
||||
printf("utl_malloc_counter=%d\r\n", utl_malloc_counter);
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void utl_free (void *ptr)
|
||||
{
|
||||
--utl_malloc_counter;
|
||||
#ifdef TRACK_MALLOC_VERBOSE
|
||||
printf("utl_malloc_counter=%d\r\n", utl_malloc_counter);
|
||||
#endif
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _DEBUG
|
||||
#define UTL_MALLOC malloc
|
||||
#define UTL_FREE free
|
||||
#endif
|
||||
|
||||
void* EspCopyArray(int elementSize, int numElements, const void* data)
|
||||
{
|
||||
int size;
|
||||
void* dataCopy = NULL;
|
||||
|
||||
size = elementSize * numElements;
|
||||
dataCopy = (void*) UTL_MALLOC (size);
|
||||
memcpy(dataCopy, data, size);
|
||||
|
||||
return dataCopy;
|
||||
}
|
||||
|
||||
void _SafeFree1 (void* freeThis)
|
||||
{
|
||||
if (freeThis != NULL) {
|
||||
UTL_FREE (freeThis);
|
||||
}
|
||||
}
|
||||
|
||||
void SafeFree1 (void** freeThis)
|
||||
{
|
||||
_SafeFree1(*freeThis);
|
||||
|
||||
*freeThis = NULL;
|
||||
}
|
||||
|
||||
char* SafeStringCopy1 (char* storeHere, const char* str)
|
||||
{
|
||||
char* retVal = storeHere;
|
||||
int size = 1;
|
||||
|
||||
if (str != NULL) {
|
||||
if (storeHere == NULL) {
|
||||
size = (int) strlen(str) + 1;
|
||||
retVal = EspCopyArray(1, size, str);
|
||||
} else {
|
||||
strcpy(retVal, str);
|
||||
}
|
||||
} else {
|
||||
if (storeHere == NULL) {
|
||||
retVal = (char*) UTL_MALLOC(1);
|
||||
}
|
||||
retVal[0] = '\0';
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef WIN32
|
||||
/*
|
||||
if (!HeapValidate(GetProcessHeap(), 0, NULL))
|
||||
{
|
||||
foo = 3;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/** Create a new mutex
|
||||
* @param mutex pointer to the mutex to create
|
||||
* @return 0: successed;1:failed;
|
||||
*/
|
||||
int mutex_init(mutex_t *pxMutex)
|
||||
{
|
||||
int xReturn = -1;
|
||||
*pxMutex = xSemaphoreCreateMutex();
|
||||
if (*pxMutex != NULL) {
|
||||
xReturn = 0;
|
||||
|
||||
} else {
|
||||
;
|
||||
}
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/** Lock a mutex
|
||||
* @param mutex the mutex to lock
|
||||
*/
|
||||
void mutex_lock(mutex_t *pxMutex)
|
||||
{
|
||||
while (xSemaphoreTake(*pxMutex, portMAX_DELAY) != pdPASS);
|
||||
// printf("[%08x]%s\r\n",pxMutex,__func__);
|
||||
}
|
||||
|
||||
/** Unlock a mutex
|
||||
* @param mutex the mutex to unlock
|
||||
*/
|
||||
void mutex_unlock(mutex_t *pxMutex)
|
||||
{
|
||||
xSemaphoreGive(*pxMutex);
|
||||
// printf("[%08x]%s\r\n",pxMutex,__func__);
|
||||
}
|
||||
|
||||
/** Delete a semaphore
|
||||
* @param mutex the mutex to delete
|
||||
*/
|
||||
void mutex_destroy(mutex_t *pxMutex)
|
||||
{
|
||||
vQueueDelete(*pxMutex);
|
||||
}
|
||||
|
||||
/////-----------------------------------
|
||||
//int sem_init_t (sem_t* sem, int pshared, unsigned int value)
|
||||
//{
|
||||
// xSemaphoreHandle xSemaphore;
|
||||
// xSemaphore = xSemaphoreCreateCounting(10, value);
|
||||
// //printf("xSemaphore: 0x%08x\r\n",xSemaphore);
|
||||
// if (xSemaphore) {
|
||||
// *sem = (int)xSemaphore;
|
||||
// return 0;
|
||||
// } else {
|
||||
// return 1;
|
||||
// }
|
||||
//}
|
||||
|
||||
//int sem_wait_t(sem_t *sem)
|
||||
//{
|
||||
|
||||
// xSemaphoreHandle xSemaphore = (xSemaphoreHandle)(*sem);
|
||||
// if (xSemaphore) {
|
||||
// while (1) {
|
||||
// if (pdTRUE == xSemaphoreTake(xSemaphore, 10)) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return 0;
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
|
||||
//int sem_post_t(sem_t *sem)
|
||||
//{
|
||||
// xSemaphoreHandle xSemaphore = (xSemaphoreHandle)(*sem);
|
||||
// if (xSemaphore) {
|
||||
// xSemaphoreGive(xSemaphore);
|
||||
// return 0;
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
|
||||
//int sem_destroy_t(sem_t* sem)
|
||||
//{
|
||||
// xSemaphoreHandle xSemaphore = (xSemaphoreHandle)(*sem);
|
||||
// if (xSemaphore) {
|
||||
// vSemaphoreDelete(xSemaphore);
|
||||
// *sem = 0;
|
||||
// return 0;
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
|
||||
//int sem_trywait_t(sem_t* sem)
|
||||
//{
|
||||
// xSemaphoreHandle xSemaphore = (xSemaphoreHandle)(*sem);
|
||||
// if (xSemaphore) {
|
||||
// if (pdTRUE == xSemaphoreTake(xSemaphore, 0)) return 0;
|
||||
// else return -1;
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
uint32 task_cnt = 0;
|
||||
//int pthread_task_create(pthread_t *thread,pthread_attr_t *attr,void* function,void* param)
|
||||
int pthread_task_create(xTaskHandle *thread_handle, void *attr, void* function, void* param)
|
||||
{
|
||||
printf("task num: %d \r\n", ++task_cnt);
|
||||
xTaskCreate(function, "test", 512, param, 18, thread_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_task_detach(xTaskHandle *thread_handle)
|
||||
{
|
||||
printf("task num: %d \r\n", --task_cnt);
|
||||
vTaskDelete(thread_handle);
|
||||
}
|
||||
|
||||
void gettimeofday_tt(struct timeval* t, void* timezone)
|
||||
{
|
||||
/* wujg : pass compile first */
|
||||
if (timezone != NULL)
|
||||
t->tv_sec = *(time_t*)timezone + system_get_time() / 1000000;
|
||||
else
|
||||
t->tv_sec = system_get_time() / 1000000;
|
||||
//t->tv_sec = system_get_time() + system_get_time()/1000000;
|
||||
t->tv_usec = 0; /* 1ms precision */
|
||||
}
|
||||
|
||||
#define MAX_LEN 1460
|
||||
#define RETRY_NUM 3
|
||||
int IRAM_ATTR send_t(int s, const void *data, int size, int flags)
|
||||
{
|
||||
#if 1
|
||||
int send_len = 0;
|
||||
int retry = 0;
|
||||
int res;
|
||||
printf("send_t ...,retry num: %d; send_len: %d;size:%d\r\n", retry, send_len, size);
|
||||
|
||||
while (retry < RETRY_NUM && send_len < size) {
|
||||
printf("in while\r\n");
|
||||
if ((size - send_len) <= MAX_LEN) {
|
||||
res = write(s, (uint8*)data + send_len, size - send_len);
|
||||
send_len += res > 0 ? res : 0;
|
||||
|
||||
} else {
|
||||
res = write(s, (uint8*)data + send_len, MAX_LEN);
|
||||
send_len += res > 0 ? res : 0;
|
||||
}
|
||||
printf("send data len: %d\r\n", send_len);
|
||||
res <= 0 ? (retry++) : (retry);
|
||||
}
|
||||
return send_len;
|
||||
|
||||
#else
|
||||
if (size <= 1460) {
|
||||
return lwip_send(s, data, size, flags);
|
||||
} else {
|
||||
int total_num = (size % MAX_LEN == 0) ? (size / MAX_LEN) : (size / MAX_LEN + 1);
|
||||
int i;
|
||||
for (i = 0; i < total_num; i++) {
|
||||
if (i == total_num - 1)
|
||||
lwip_send(s, (uint8*)data + MAX_LEN * i, size - MAX_LEN * i, flags);
|
||||
else
|
||||
lwip_send(s, (uint8*)data + MAX_LEN * i, MAX_LEN, flags);
|
||||
vTaskDelay(2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return size;
|
||||
#endif
|
||||
}
|
||||
|
||||
int IRAM_ATTR sendto_t(int s, const void *data, int size, int flags, const struct sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
printf("s1\r\n");
|
||||
if (size <= 1460) {
|
||||
printf("s2\r\n");
|
||||
return lwip_sendto(s, data, size, flags, to, tolen);
|
||||
} else {
|
||||
printf("s3\r\n");
|
||||
int total_num = (size % MAX_LEN == 0) ? (size / MAX_LEN) : (size / MAX_LEN + 1);
|
||||
int i;
|
||||
for (i = 0; i < total_num; i++) {
|
||||
if (i == total_num - 1) {
|
||||
printf("s4\r\n");
|
||||
lwip_sendto(s, (uint8*)data + MAX_LEN * i, size - MAX_LEN * i, flags, to, tolen);
|
||||
printf("s5\r\n");
|
||||
} else {
|
||||
printf("s6\r\n");
|
||||
lwip_sendto(s, (uint8*)data + MAX_LEN * i, MAX_LEN, flags, to, tolen);
|
||||
printf("s7\r\n");
|
||||
}
|
||||
vTaskDelay(2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
printf("s8\r\n");
|
||||
return size;
|
||||
}
|
||||
|
||||
int fd_rec = 0;
|
||||
void update_fd_rec(int fd_num)
|
||||
{
|
||||
if (fd_num > fd_rec) fd_rec = fd_num;
|
||||
}
|
||||
int get_fd_rec()
|
||||
{
|
||||
return fd_rec;
|
||||
}
|
||||
|
||||
int socket_t(int domain, int type, int protocol)
|
||||
{
|
||||
int fd_num = lwip_socket(domain, type, protocol);
|
||||
printf("!!!!!!!!\r\n");
|
||||
printf("socket fd: %d\r\n", fd_num);
|
||||
printf("!!!!!!!!\r\n");
|
||||
update_fd_rec(fd_num);
|
||||
printf("fd rec::: %d\r\n", get_fd_rec());
|
||||
|
||||
return fd_num;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
//============================================
|
||||
|
||||
void debug_func()
|
||||
{
|
||||
printf("debug_func...\r\n");
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "audio_log.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "soc/spi_reg.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
char tmp[1500] = {0};
|
||||
/**
|
||||
* @brief print out log information.
|
||||
*
|
||||
*/
|
||||
void __log(const char *level, const char * func, uint32_t line, const char * restrict format, ...)
|
||||
{
|
||||
if (level != NULL) {
|
||||
//memset(tmp, 0, sizeof(tmp));
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
(void)vsnprintf(tmp, sizeof(tmp), format, ap);
|
||||
tmp[1500-1] = '\0';
|
||||
va_end(ap);
|
||||
printf("[%s]%s(%d):%s\r\n", level, func, line,tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
||||
|
||||
include $(IDF_PATH)/make/component_common.mk
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
Copyright 2006 - 2011 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implements additional string functionality.
|
||||
*/
|
||||
|
||||
#ifndef MY_STRING_H
|
||||
|
||||
/*
|
||||
* EndsWith()
|
||||
* str : the string to analyze
|
||||
* endsWith : the token to find at the end of str
|
||||
* ignoreCase : nonzero indicates case insensitive search
|
||||
*
|
||||
* If "str" ends with "endsWith", then we return nonzero.
|
||||
*/
|
||||
int EndsWith(const char* str, const char* endsWith, int ignoreCase);
|
||||
|
||||
/*
|
||||
* IndexOf()
|
||||
* str : the string to analyze
|
||||
* findThis : the token to find
|
||||
* ignoreCase : nonzero indicates case insensitive search
|
||||
*
|
||||
* Returns the first index where findThis can be found in str.
|
||||
* Returns -1 if not found.
|
||||
*/
|
||||
int IndexOf(const char* str, const char* findThis);
|
||||
|
||||
/*
|
||||
* IndexOf()
|
||||
* str : the string to analyze
|
||||
* findThis : the token to find
|
||||
* ignoreCase : nonzero indicates case insensitive search
|
||||
*
|
||||
* Returns the last index where findThis can be found in str.
|
||||
* Returns -1 if not found.
|
||||
*/
|
||||
int LastIndexOf(const char* str, const char* findThis);
|
||||
|
||||
/*
|
||||
* IndexOf()
|
||||
* str : the string to analyze
|
||||
* startsWith : the token to find
|
||||
* ignoreCase : nonzero indicates case insensitive search
|
||||
*
|
||||
* Returns nonzero value if the string starts with 'startsWith'.
|
||||
*/
|
||||
int StartsWith(const char* str, const char* startsWith, int ignoreCase);
|
||||
|
||||
#endif
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __STORAGE_H__
|
||||
#define __STORAGE_H__
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the specified buffer
|
||||
*
|
||||
* @attention : The specified buffer is cyclic.
|
||||
*
|
||||
* @return 0:Successed; others:failed.
|
||||
*/
|
||||
|
||||
int audioBufInit();
|
||||
|
||||
/**
|
||||
* @brief Uninitialize buffer
|
||||
*
|
||||
* @return 0:Successed; others:failed.
|
||||
*/
|
||||
void audioBufUninit();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieves the size of the specified buffer, in bytes.
|
||||
*
|
||||
* @return > 0: Size of the buffer was filled.
|
||||
*/
|
||||
int audioBufFillGet();
|
||||
|
||||
/**
|
||||
* @brief Reads data from the specified buffer.
|
||||
*
|
||||
* @para [out] dest: A pointer to the buffer that receives the data read from specified buffer.
|
||||
* [in ] n : The maximum number of bytes to be read.
|
||||
* [in] t : Timeout portMAX_DELAY-block; others,unblock.
|
||||
*
|
||||
* @attention : The specified buffer is cyclic.
|
||||
*
|
||||
* @return > 0: Actually number of bytes has read. 0: buffer is too low,failed.
|
||||
*/
|
||||
int audioBufRead(char *dest, int n, uint32_t t);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Writes data to the specified buffer.
|
||||
*
|
||||
* @para [in] src : A pointer to the buffer containing the data to be written to the specified buffer.
|
||||
* [in] n : The number of bytes to be written to the buffer.
|
||||
* [in] t : Timeout portMAX_DELAY-block; others,unblock.
|
||||
*
|
||||
* @attention : The specified buffer is cyclic.
|
||||
*
|
||||
* @return 0:Failed,no more spaces for store; > 0:Actually number of bytes has write.
|
||||
*/
|
||||
int audioBufWrite(char *src, int n, uint32_t t);
|
||||
|
||||
/**
|
||||
* @brief Reset the write and read buffer pointer.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufRestAll();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset the read buffer address.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufRdRest();
|
||||
|
||||
/**
|
||||
* @brief Reset the read buffer address.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufWrRest();
|
||||
|
||||
/**
|
||||
* @brief Get the buffer read and write position.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufPosGet(uint32_t *rdPos, uint32_t *wrPos);
|
||||
|
||||
/**
|
||||
* @brief Set the buffer read and write position.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufRdPosSet(uint32_t *rdPos);
|
||||
|
||||
/**
|
||||
* @brief Set quit queue for read block.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufRdQuitCfg(void * que);
|
||||
|
||||
/**
|
||||
* @brief Set quit queue for write block.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void audioBufWrQuitCfg(void * que);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __STORAGE_H__
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
Copyright 2006 - 2011 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTILITY_H
|
||||
#define UTILITY_H
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/igmp.h"
|
||||
|
||||
/*
|
||||
* Defines an empty string.
|
||||
*/
|
||||
#define EMPTY_STRING ""
|
||||
|
||||
/*
|
||||
* Used to prevent warnings on assinign NULL
|
||||
* to a char*
|
||||
*/
|
||||
#define NULL_CHAR '\0'
|
||||
|
||||
/*
|
||||
* Copies memory from one location to a new location
|
||||
* and returns the pointer.
|
||||
*/
|
||||
void* CopyArray(int elementSize, int numElements, const void* data);
|
||||
|
||||
/*
|
||||
* Does a normal free on freeThis, except
|
||||
* that it checks for non-NULL value first.
|
||||
*/
|
||||
void _SafeFree1 (void* freeThis);
|
||||
|
||||
/*
|
||||
* This macro calls _SafeFree and then assigns
|
||||
* the pointer to NULL, for extra safety.
|
||||
*/
|
||||
//#define SafeFree(x) _SafeFree(x); x = NULL;
|
||||
void SafeFree1(void** freeThis);
|
||||
|
||||
/*
|
||||
* Copies a string safely.
|
||||
* If str is NULL returned value is an empty string.
|
||||
*
|
||||
* If storeHere is NULL, then memory is allocated
|
||||
* by the method. Use SafeFree() to deallocate
|
||||
* that memory.
|
||||
*
|
||||
* Returns the copy of str.
|
||||
*/
|
||||
char* SafeStringCopy1 (char* storeHere, const char* str);
|
||||
|
||||
/*
|
||||
* Spawns a normal thread that is detached
|
||||
* from the calling thread.
|
||||
*/
|
||||
void SpawnDetachedThread(void* method, void* arg);
|
||||
|
||||
|
||||
#define mutex_t xSemaphoreHandle
|
||||
|
||||
/** Create a new mutex
|
||||
* @param mutex pointer to the mutex to create
|
||||
* @return 0: successed;1:failed;
|
||||
*/
|
||||
int mutex_init(mutex_t *pxMutex);
|
||||
|
||||
/** Lock a mutex
|
||||
* @param mutex the mutex to lock
|
||||
*/
|
||||
void mutex_lock(mutex_t *pxMutex);
|
||||
|
||||
/** Unlock a mutex
|
||||
* @param mutex the mutex to unlock
|
||||
*/
|
||||
void mutex_unlock(mutex_t *pxMutex);
|
||||
|
||||
/** Delete a semaphore
|
||||
* @param mutex the mutex to delete
|
||||
*/
|
||||
void mutex_destroy(mutex_t *pxMutex);
|
||||
|
||||
|
||||
#define TEST_OS_MODE 1
|
||||
|
||||
typedef int sem_t_t;
|
||||
#if 1 //TEST_OS_MODE
|
||||
|
||||
//int sem_init_t (sem_t_t *sem, int pshared, unsigned int value);
|
||||
//int sem_wait_t(sem_t_t *sem);
|
||||
//int sem_post_t(sem_t_t *sem);
|
||||
//int sem_destroy_t(sem_t_t* sem);
|
||||
//int sem_trywait_t(sem_t_t* sem);
|
||||
|
||||
int pthread_task_create();
|
||||
void gettimeofday_tt(struct timeval* t, void* timezone);
|
||||
|
||||
int send_t(int s, const void *data, int size, int flags);
|
||||
int sendto_t(int s, const void *data, int size, int flags,const struct sockaddr *to, socklen_t tolen);
|
||||
int get_fd_rec();
|
||||
void update_fd_rec(int fd_num);
|
||||
int socket_t(int domain, int type, int protocol);
|
||||
|
||||
|
||||
#define pthread_t xTaskHandle
|
||||
#define pthread_create pthread_task_create
|
||||
//#define pthread_detach //pthread_task_detach
|
||||
|
||||
|
||||
#if 0
|
||||
#define pthread_t xTaskHandle
|
||||
#define pthread_create pthread_task_create
|
||||
#define pthread_detach //pthread_task_detach
|
||||
#define gettimeofday gettimeofday_tt
|
||||
#define send(a,b,c,d) lwip_send(a,b,c,d)//send_t(a,b,c,d)//write(a,b,c)//lwip_send(a,b,c,d) //send_t(a,b,c,d)
|
||||
#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) // sendto_t(a,b,c,d,e,f)
|
||||
#define socket(a,b,c) lwip_socket(a,b,c) //socket_t(a,b,c)
|
||||
|
||||
|
||||
|
||||
|
||||
//#define printf os_printf
|
||||
//#define printf(fmt,...) os_printf(fmt, ##__VA_ARGS__)
|
||||
//#define ioctl ioctlsocket
|
||||
#define ASSERT(exp) do{ \
|
||||
if(!(exp)) {os_printf("ERROR IN RESERT IN %s:%d",__func__,__LINE__);} \
|
||||
}while(0)
|
||||
|
||||
#endif
|
||||
//typedef int sem_t;
|
||||
//#define sem_init(x,y,z) sem_init_t(x,y,z)
|
||||
//#define sem_destroy(x) sem_destroy_t(x)
|
||||
//#define sem_wait(x) sem_wait_t(x)
|
||||
//#define sem_trywait(x) sem_trywait_t(x)
|
||||
//#define sem_post(x) sem_post_t(x)
|
||||
|
||||
|
||||
|
||||
void debug_func();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __AUDIO_LOG_H__
|
||||
#define __AUDIO_LOG_H__
|
||||
#include "esp_types.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Make sure all of the definitions in this header have a C binding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void __log(const char *level, const char * func, uint32_t line, const char * restrict format, ...);
|
||||
|
||||
|
||||
#ifdef CONFIG_AUDIO_LOG_INFO_EN
|
||||
#define LOGI(format, ...) __log("I", __func__, __LINE__, format, ##__VA_ARGS__);
|
||||
#else
|
||||
#define LOGI(format, ...)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_LOG_DEBUG_EN
|
||||
#define LOGD(format, ...) __log("D", __func__, __LINE__, format, ##__VA_ARGS__);
|
||||
#else
|
||||
#define LOGD(format, ...)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_LOG_WARN_EN
|
||||
#define LOGW(format, ...) __log("W", __func__, __LINE__, format, ##__VA_ARGS__);
|
||||
#else
|
||||
#define LOGW(format, ...)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_LOG_ERROR_EN
|
||||
#define LOGE(format, ...) __log("E", __func__, __LINE__, format, ##__VA_ARGS__);
|
||||
#else
|
||||
#define LOGE(format, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __AUDIO_LOG_H__
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* ESPRSSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP32 only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ESP_TIMER_H__
|
||||
#define __ESP_TIMER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "esp_types.h"
|
||||
/* timer related */
|
||||
typedef void os_timer_func_t(void *timer_arg);
|
||||
|
||||
typedef struct _os_timer_t {
|
||||
struct _os_timer_t *timer_next;
|
||||
void *timer_handle;
|
||||
uint32_t timer_expire;
|
||||
uint32_t timer_period;
|
||||
os_timer_func_t *timer_func;
|
||||
bool timer_repeat_flag;
|
||||
void *timer_arg;
|
||||
} os_timer_t;
|
||||
|
||||
/** \defgroup Timer_APIs Software timer APIs
|
||||
* @brief Software timer APIs
|
||||
*
|
||||
* Timers of the following interfaces are software timers. Functions of the timers are executed during the tasks.
|
||||
* Since a task can be stopped, or be delayed because there are other tasks with higher priorities, the following os_timer interfaces cannot guarantee the precise execution of the timers.
|
||||
* - For the same timer, os_timer_arm (or os_timer_arm_us) cannot be invoked repeatedly. os_timer_disarm should be invoked first.
|
||||
* - os_timer_setfn can only be invoked when the timer is not enabled, i.e., after os_timer_disarm or before os_timer_arm (or os_timer_arm_us).
|
||||
*
|
||||
*/
|
||||
|
||||
/** @addtogroup Timer_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set the timer callback function.
|
||||
*
|
||||
* @attention 1. The callback function must be set in order to enable the timer.
|
||||
* @attention 2. Operating system scheduling is disabled in timer callback.
|
||||
*
|
||||
* @param os_timer_t *ptimer : Timer structure
|
||||
* @param os_timer_func_t *pfunction : timer callback function
|
||||
* @param void *parg : callback function parameter
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void os_timer_setfn(os_timer_t *ptimer, os_timer_func_t *pfunction, void *parg);
|
||||
|
||||
/**
|
||||
* @brief Enable the millisecond timer.
|
||||
*
|
||||
* @param os_timer_t *ptimer : timer structure
|
||||
* @param uint32_t milliseconds : Timing, unit: millisecond, the maximum value allowed is 0x41893
|
||||
* @param bool repeat_flag : Whether the timer will be invoked repeatedly or not
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void os_timer_arm(os_timer_t *ptimer, uint32_t msec, bool repeat_flag);
|
||||
|
||||
/**
|
||||
* @brief Disarm the timer
|
||||
*
|
||||
* @param os_timer_t *ptimer : Timer structure
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void os_timer_disarm(os_timer_t *ptimer);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -13,7 +13,7 @@
|
|||
#include "bt_app_common.h"
|
||||
#include "esp_bt_stack_manager.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "bta_api.h"
|
||||
// #include "bta_api.h"
|
||||
#include "esp_a2dp_api.h"
|
||||
|
||||
typedef enum {
|
||||
|
@ -25,7 +25,7 @@ typedef union {
|
|||
esp_a2d_cb_param_t a2d;
|
||||
} bt_app_evt_arg;
|
||||
|
||||
static void bt_app_handle_evt(UINT16 event, void *p_param);
|
||||
static void bt_app_handle_evt(uint16_t event, void *p_param);
|
||||
|
||||
static void bt_app_a2d_cb(uint32_t event, void *param)
|
||||
{
|
||||
|
@ -43,20 +43,18 @@ static void bt_app_a2d_cb(uint32_t event, void *param)
|
|||
}
|
||||
}
|
||||
|
||||
static void bt_app_a2d_data_cb(uint8_t *data, uint32_t len)
|
||||
static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
// EspAudioPlayerStreamWrite(data, len, 10);
|
||||
return;
|
||||
// EspAudioPlayerStreamWrite((uint8_t *)data, len, 10);
|
||||
}
|
||||
|
||||
static void bt_app_handle_evt(UINT16 event, void *p_param)
|
||||
static void bt_app_handle_evt(uint16_t event, void *p_param)
|
||||
{
|
||||
BT_APP_TRACE_DEBUG("bt_app_handle_evt 0x%x\n", event);
|
||||
esp_a2d_cb_param_t *a2d = NULL;
|
||||
switch (event) {
|
||||
case BT_APP_EVT_STACK_ON: {
|
||||
char *dev_name = "ESP_SPEAKER";
|
||||
// BTM_SetTraceLevel(BT_TRACE_LEVEL_WARNING);
|
||||
esp_bt_gap_set_device_name(dev_name);
|
||||
|
||||
esp_a2d_register_callback(bt_app_a2d_cb);
|
||||
|
@ -97,7 +95,7 @@ static void bt_app_handle_evt(UINT16 event, void *p_param)
|
|||
|
||||
void app_main_entry(void)
|
||||
{
|
||||
bt_status_t init, enable;
|
||||
esp_err_t init, enable;
|
||||
init = esp_bt_init_stack();
|
||||
if (init != ESP_OK) {
|
||||
return;
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
|
||||
COMPONENT_SRCDIRS := .
|
||||
|
||||
include $(IDF_PATH)/make/component_common.mk
|
|
@ -1,259 +0,0 @@
|
|||
/*
|
||||
ESP8266 web server - platform-dependent routines, FreeRTOS version
|
||||
|
||||
|
||||
Thanks to my collague at Espressif for writing the foundations of this code.
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
#include "httpd-com.h"
|
||||
#include "httpd-platform.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "string.h"
|
||||
|
||||
static int httpPort;
|
||||
static int httpMaxConnCt;
|
||||
|
||||
struct RtosConnType {
|
||||
int fd;
|
||||
int needWriteDoneNotif;
|
||||
int needsClose;
|
||||
int port;
|
||||
char ip[4];
|
||||
};
|
||||
|
||||
static RtosConnType rconn[HTTPD_MAX_CONNECTIONS];
|
||||
static xQueueHandle queWebServerStop = NULL;
|
||||
|
||||
int httpdPlatSendData(ConnTypePtr conn, char *buff, int len) {
|
||||
int ret = 0;
|
||||
char *cipher = buff;
|
||||
unsigned short clen = len;
|
||||
conn->needWriteDoneNotif = 1;
|
||||
if (!cipher || clen == 0)
|
||||
return false;
|
||||
ret = write(conn->fd, cipher, clen);
|
||||
cipher != buff ? free(cipher) : 0;
|
||||
return ret >= 0;
|
||||
}
|
||||
|
||||
void httpdPlatDisconnect(ConnTypePtr conn) {
|
||||
conn->needsClose = 1;
|
||||
conn->needWriteDoneNotif = 1; //because the real close is done in the writable select code
|
||||
}
|
||||
|
||||
void httpdPlatDisableTimeout(ConnTypePtr conn) {
|
||||
//Unimplemented for FreeRTOS
|
||||
}
|
||||
|
||||
|
||||
#define RECV_BUF_SIZE 1460
|
||||
static void platHttpServerTask(void *pvParameters) {
|
||||
int32_t listenfd;
|
||||
int32_t remotefd;
|
||||
int32_t len;
|
||||
int32_t ret;
|
||||
int x;
|
||||
int maxfdp = 0;
|
||||
fd_set readset, writeset;
|
||||
struct sockaddr name;
|
||||
struct timeval timeout;
|
||||
struct sockaddr_in server_addr;
|
||||
struct sockaddr_in remote_addr;
|
||||
|
||||
portBASE_TYPE xStatus;
|
||||
bool ValueFromReceive = false;
|
||||
for (x = 0; x < HTTPD_MAX_CONNECTIONS; x++) {
|
||||
rconn[x].fd = -1;
|
||||
}
|
||||
|
||||
/* Construct local address structure */
|
||||
memset(&server_addr, 0, sizeof(server_addr)); /* Zero out structure */
|
||||
server_addr.sin_family = AF_INET; /* Internet address family */
|
||||
server_addr.sin_addr.s_addr = INADDR_ANY; /* Any incoming interface */
|
||||
server_addr.sin_len = sizeof(server_addr);
|
||||
server_addr.sin_port = htons(httpPort); /* Local port */
|
||||
|
||||
/* Create socket for incoming connections */
|
||||
do {
|
||||
listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listenfd == -1) {
|
||||
httpd_printf("platHttpServerTask: failed to create sock!\n");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
} while (listenfd == -1);
|
||||
/* Bind to the local port */
|
||||
do {
|
||||
ret = bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
||||
if (ret != 0) {
|
||||
httpd_printf("platHttpServerTask: failed to bind!\n");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
} while (ret != 0);
|
||||
do {
|
||||
/* Listen to the local connection */
|
||||
ret = listen(listenfd, HTTPD_MAX_CONNECTIONS);
|
||||
if (ret != 0) {
|
||||
httpd_printf("platHttpServerTask: failed to listen!\n");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
|
||||
} while (ret != 0);
|
||||
|
||||
// httpd_printf("esphttpd: active and listening to connections.\n");
|
||||
while (1) {
|
||||
// clear fdset, and set the select function wait time
|
||||
int socketsFull = 1;
|
||||
maxfdp = 0;
|
||||
FD_ZERO(&readset);
|
||||
FD_ZERO(&writeset);
|
||||
timeout.tv_sec = 2;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
for (x = 0; x < HTTPD_MAX_CONNECTIONS; x++) {
|
||||
if (rconn[x].fd != -1) {
|
||||
FD_SET(rconn[x].fd, &readset);
|
||||
if (rconn[x].needWriteDoneNotif) FD_SET(rconn[x].fd, &writeset);
|
||||
if (rconn[x].fd > maxfdp) maxfdp = rconn[x].fd;
|
||||
} else {
|
||||
socketsFull = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!socketsFull) {
|
||||
FD_SET(listenfd, &readset);
|
||||
if (listenfd > maxfdp) maxfdp = listenfd;
|
||||
}
|
||||
xStatus = xQueueReceive(queWebServerStop, &ValueFromReceive, 0);
|
||||
if ( pdPASS == xStatus && true == ValueFromReceive) {
|
||||
httpd_printf("user_webserver_task rcv exit signal!\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
//polling all exist client handle,wait until readable/writable
|
||||
ret = select(maxfdp + 1, &readset, &writeset, NULL, &timeout); //&timeout
|
||||
if (ret > 0) {
|
||||
//See if we need to accept a new connection
|
||||
if (FD_ISSET(listenfd, &readset)) {
|
||||
len = sizeof(struct sockaddr_in);
|
||||
remotefd = accept(listenfd, (struct sockaddr *)&remote_addr, (socklen_t *)&len);
|
||||
if (remotefd < 0) {
|
||||
httpd_printf("platHttpServerTask: Huh? Accept failed.\n");
|
||||
continue;
|
||||
}
|
||||
for (x = 0; x < HTTPD_MAX_CONNECTIONS; x++) if (rconn[x].fd == -1) break;
|
||||
if (x == HTTPD_MAX_CONNECTIONS) {
|
||||
httpd_printf("platHttpServerTask: Huh? Got accept with all slots full.\n");
|
||||
continue;
|
||||
}
|
||||
int keepAlive = 1; //enable keepalive
|
||||
int keepIdle = 60; //60s
|
||||
int keepInterval = 5; //5s
|
||||
int keepCount = 3; //retry times
|
||||
|
||||
setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
|
||||
setsockopt(remotefd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
|
||||
setsockopt(remotefd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
|
||||
setsockopt(remotefd, IPPROTO_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
|
||||
|
||||
rconn[x].fd = remotefd;
|
||||
rconn[x].needWriteDoneNotif = 0;
|
||||
rconn[x].needsClose = 0;
|
||||
|
||||
len = sizeof(name);
|
||||
getpeername(remotefd, &name, (socklen_t *)&len);
|
||||
struct sockaddr_in *piname = (struct sockaddr_in *)&name;
|
||||
|
||||
rconn[x].port = piname->sin_port;
|
||||
memcpy(&rconn[x].ip, &piname->sin_addr.s_addr, sizeof(rconn[x].ip));
|
||||
|
||||
httpdConnectCb(&rconn[x], rconn[x].ip, rconn[x].port);
|
||||
//ets_timer_disarm(&connData[x].conn->stop_watch);
|
||||
//ets_timer_setfn(&connData[x].conn->stop_watch, (ETSTimerFunc *)httpserver_conn_watcher, connData[x].conn);
|
||||
//ets_timer_arm(&connData[x].conn->stop_watch, STOP_TIMER, 0);
|
||||
}
|
||||
|
||||
//See if anything happened on the existing connections.
|
||||
for (x = 0; x < HTTPD_MAX_CONNECTIONS; x++) {
|
||||
//Skip empty slots
|
||||
if (rconn[x].fd == -1) continue;
|
||||
|
||||
//Check for write availability first: the read routines may write needWriteDoneNotif while
|
||||
//the select didn't check for that.
|
||||
if (rconn[x].needWriteDoneNotif && FD_ISSET(rconn[x].fd, &writeset)) {
|
||||
rconn[x].needWriteDoneNotif = 0; //Do this first, httpdSentCb may write something making this 1 again.
|
||||
if (rconn[x].needsClose) {
|
||||
//Do callback and close fd.
|
||||
|
||||
httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port);
|
||||
close(rconn[x].fd);
|
||||
rconn[x].fd = -1;
|
||||
} else {
|
||||
httpdSentCb(&rconn[x], rconn[x].ip, rconn[x].port);
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(rconn[x].fd, &readset)) {
|
||||
char *precvbuf = (char*)malloc(RECV_BUF_SIZE + 1);
|
||||
if (precvbuf==NULL) httpd_printf("platHttpServerTask: memory exhausted!\n");
|
||||
memset(precvbuf, 0, RECV_BUF_SIZE + 1);
|
||||
ret = recv(rconn[x].fd, precvbuf, RECV_BUF_SIZE, 0);
|
||||
if (ret > 0) {
|
||||
//Data received. Pass to httpd.
|
||||
char *plain = NULL;
|
||||
unsigned short plen = strlen(precvbuf);
|
||||
if (precvbuf && plen > 0)
|
||||
httpdRecvCb(&rconn[x], rconn[x].ip, rconn[x].port, precvbuf, plen);
|
||||
}
|
||||
// else
|
||||
{
|
||||
//recv error,connection close
|
||||
httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port);
|
||||
close(rconn[x].fd);
|
||||
rconn[x].fd = -1;
|
||||
}
|
||||
if (precvbuf) free(precvbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(listenfd);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
int httpdPlatUninit(void)
|
||||
{
|
||||
bool ValueToSend = true;
|
||||
portBASE_TYPE xStatus;
|
||||
|
||||
configASSERT(queWebServerStop);
|
||||
if (queWebServerStop == NULL) {
|
||||
return -1;
|
||||
}
|
||||
xStatus = xQueueSend(queWebServerStop, &ValueToSend, 0);
|
||||
if (xStatus != pdPASS) {
|
||||
httpd_printf("Web server can not send to the queue!\r\n");
|
||||
return -1;
|
||||
} else {
|
||||
httpd_printf("queWebServerStop send ok\r\n");
|
||||
return pdPASS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Initialize listening socket, do general initialization
|
||||
void httpdPlatInit(int port, int maxConnCt) {
|
||||
httpPort = port;
|
||||
httpMaxConnCt = maxConnCt;
|
||||
if (queWebServerStop == NULL)
|
||||
queWebServerStop = xQueueCreate(1, 1);
|
||||
configASSERT(queWebServerStop);
|
||||
httpd_printf ("user_webserver_task start\r\n");
|
||||
|
||||
xTaskCreate(platHttpServerTask, "esphttpd", HTTPD_STACKSIZE, NULL, WEB_SERVER_TASK_PRIO, NULL);
|
||||
}
|
|
@ -1,841 +0,0 @@
|
|||
/*
|
||||
Esp8266 http server - core routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
#include "httpd-platform.h"
|
||||
#include "string.h"
|
||||
#include "esp_types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
#if 0
|
||||
//Max amount of simultaneous connections
|
||||
#define MAX_CONN 8
|
||||
//Max length of request head. This is statically allocated for each connection.
|
||||
#define MAX_HEAD_LEN 1024
|
||||
//Max post buffer len. This is dynamically malloc'ed if needed.
|
||||
#define MAX_POST 1024
|
||||
//Max send buffer len. This is allocated on the stack.
|
||||
#define MAX_SENDBUFF_LEN 2048
|
||||
//If some data can't be sent because the underlaying socket doesn't accept the data (like the nonos
|
||||
//layer is prone to do), we put it in a backlog that is dynamically malloc'ed. This defines the max
|
||||
//size of the backlog.
|
||||
#define MAX_BACKLOG_SIZE (4*1024)
|
||||
|
||||
typedef struct HttpSendBacklogItem HttpSendBacklogItem;
|
||||
|
||||
struct HttpSendBacklogItem {
|
||||
int len;
|
||||
HttpSendBacklogItem *next;
|
||||
char data[];
|
||||
};
|
||||
|
||||
//Flags
|
||||
#define HFL_HTTP11 (1<<0)
|
||||
#define HFL_CHUNKED (1<<1)
|
||||
#define HFL_SENDINGBODY (1<<2)
|
||||
#define HFL_DISCONAFTERSENT (1<<3)
|
||||
|
||||
//Private data for http connection
|
||||
struct HttpdPriv {
|
||||
char head[MAX_HEAD_LEN];
|
||||
int headPos;
|
||||
char *sendBuff;
|
||||
int sendBuffLen;
|
||||
char *chunkHdr;
|
||||
HttpSendBacklogItem *sendBacklog;
|
||||
int sendBacklogSize;
|
||||
int flags;
|
||||
};
|
||||
#endif
|
||||
|
||||
//Connection pool
|
||||
static HttpdConnData *connData[HTTPD_MAX_CONNECTIONS];
|
||||
//This gets set at init time.
|
||||
static HttpdBuiltInUrl *builtInUrls;
|
||||
|
||||
#if 0
|
||||
//Struct to keep extension->mime data in
|
||||
typedef struct {
|
||||
const char *ext;
|
||||
const char *mimetype;
|
||||
} MimeMap;
|
||||
|
||||
//#define RSTR(a) ((const char)(a))
|
||||
|
||||
//The mappings from file extensions to mime types. If you need an extra mime type,
|
||||
//add it here.
|
||||
static const ICACHE_RODATA_ATTR MimeMap mimeTypes[] = {
|
||||
{"htm", "text/htm"},
|
||||
{"html", "text/html"},
|
||||
{"css", "text/css"},
|
||||
{"js", "text/javascript"},
|
||||
{"txt", "text/plain"},
|
||||
{"jpg", "image/jpeg"},
|
||||
{"jpeg", "image/jpeg"},
|
||||
{"png", "image/png"},
|
||||
{"svg", "image/svg+xml"},
|
||||
{NULL, "text/html"}, //default value
|
||||
};
|
||||
|
||||
//Returns a static char* to a mime type for a given url to a file.
|
||||
const char *httpdGetMimetype(char *url) {
|
||||
int i = 0;
|
||||
//Go find the extension
|
||||
char *ext = url + (strlen(url) - 1);
|
||||
while (ext != url && *ext != '.') ext--;
|
||||
if (*ext == '.') ext++;
|
||||
|
||||
//ToDo: strcmp is case sensitive; we may want to do case-intensive matching here...
|
||||
while (mimeTypes[i].ext != NULL && strcmp(ext, mimeTypes[i].ext) != 0) i++;
|
||||
return mimeTypes[i].mimetype;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
void __attribute__((weak))
|
||||
httpd_encrypt(ConnTypePtr conn, char *plain, unsigned short plen, char **cipher, unsigned short *clen)
|
||||
{
|
||||
*cipher = plain;
|
||||
*clen = plen;
|
||||
}
|
||||
|
||||
void __attribute__((weak))
|
||||
httpd_decrypt(ConnTypePtr conn, char *cipher, unsigned short clen, char **plain, unsigned short *plen)
|
||||
{
|
||||
*plain = cipher;
|
||||
*plen = clen;
|
||||
}
|
||||
|
||||
#endif
|
||||
//Looks up the connData info for a specific connection
|
||||
static HttpdConnData *httpdFindConnData(ConnTypePtr conn, char *remIp, int remPort) {
|
||||
int i = 0;
|
||||
for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {
|
||||
if (connData[i] && connData[i]->remote_port == remPort &&
|
||||
memcmp(connData[i]->remote_ip, remIp, 4) == 0) {
|
||||
connData[i]->conn = conn;
|
||||
return connData[i];
|
||||
}
|
||||
}
|
||||
//Shouldn't happen.
|
||||
httpd_printf("*** Unknown connection %d.%d.%d.%d:%d\n", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort);
|
||||
httpdPlatDisconnect(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Retires a connection for re-use
|
||||
static void httpdRetireConn(HttpdConnData *conn) {
|
||||
if (conn->priv->sendBacklog != NULL) {
|
||||
HttpSendBacklogItem *i, *j;
|
||||
i = conn->priv->sendBacklog;
|
||||
do {
|
||||
j = i;
|
||||
i = i->next;
|
||||
free(j);
|
||||
} while (i != NULL);
|
||||
}
|
||||
if (conn->post->buff != NULL) free(conn->post->buff);
|
||||
if (conn->post != NULL) free(conn->post);
|
||||
if (conn->priv != NULL) free(conn->priv);
|
||||
if (conn) free(conn);
|
||||
int i = 0;
|
||||
for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {
|
||||
if (connData[i] == conn) connData[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//Stupid li'l helper function that returns the value of a hex char.
|
||||
static int httpdHexVal(char c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Decode a percent-encoded value.
|
||||
//Takes the valLen bytes stored in val, and converts it into at most retLen bytes that
|
||||
//are stored in the ret buffer. Returns the actual amount of bytes used in ret. Also
|
||||
//zero-terminates the ret buffer.
|
||||
int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
|
||||
int s = 0, d = 0;
|
||||
int esced = 0, escVal = 0;
|
||||
while (s < valLen && d < retLen) {
|
||||
if (esced == 1) {
|
||||
escVal = httpdHexVal(val[s]) << 4;
|
||||
esced = 2;
|
||||
} else if (esced == 2) {
|
||||
escVal += httpdHexVal(val[s]);
|
||||
ret[d++] = escVal;
|
||||
esced = 0;
|
||||
} else if (val[s] == '%') {
|
||||
esced = 1;
|
||||
} else if (val[s] == '+') {
|
||||
ret[d++] = ' ';
|
||||
} else {
|
||||
ret[d++] = val[s];
|
||||
}
|
||||
s++;
|
||||
}
|
||||
if (d < retLen) ret[d] = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
//Find a specific arg in a string of get- or post-data.
|
||||
//Line is the string of post/get-data, arg is the name of the value to find. The
|
||||
//zero-terminated result is written in buff, with at most buffLen bytes used. The
|
||||
//function returns the length of the result, or -1 if the value wasn't found. The
|
||||
//returned string will be urldecoded already.
|
||||
int httpdFindArg(char *line, char *arg, char *buff, int buffLen) {
|
||||
char *p, *e;
|
||||
if (line == NULL) return -1;
|
||||
p = line;
|
||||
while (p != NULL && *p != '\n' && *p != '\r' && *p != 0) {
|
||||
// httpd_printf("findArg: %s\n", p);
|
||||
if (strncmp(p, arg, strlen(arg)) == 0 && p[strlen(arg)] == '=') {
|
||||
p += strlen(arg) + 1; //move p to start of value
|
||||
e = (char*)strstr(p, "&");
|
||||
if (e == NULL) e = p + strlen(p);
|
||||
// httpd_printf("findArg: val %s len %d\n", p, (e-p));
|
||||
return httpdUrlDecode(p, (e - p), buff, buffLen);
|
||||
}
|
||||
p = (char*)strstr(p, "&");
|
||||
if (p != NULL) p += 1;
|
||||
}
|
||||
//httpd_printf("Finding %s in %s: Not found :/\n", arg, line);
|
||||
return -1; //not found
|
||||
}
|
||||
|
||||
//Get the value of a certain header in the HTTP client head
|
||||
//Returns true when found, false when not found.
|
||||
int httpdGetHeader(HttpdConnData *conn, char *header, char *ret, int retLen) {
|
||||
char *p = conn->priv->head;
|
||||
p = p + strlen(p) + 1; //skip GET/POST part
|
||||
p = p + strlen(p) + 1; //skip HTTP part
|
||||
while (p < (conn->priv->head + conn->priv->headPos)) {
|
||||
while (*p <= 32 && *p != 0) p++; //skip crap at start
|
||||
//See if this is the header
|
||||
if (strncmp(p, header, strlen(header)) == 0 && p[strlen(header)] == ':') {
|
||||
//Skip 'key:' bit of header line
|
||||
p = p + strlen(header) + 1;
|
||||
//Skip past spaces after the colon
|
||||
while (*p == ' ') p++;
|
||||
//Copy from p to end
|
||||
while (*p != 0 && *p != '\r' && *p != '\n' && retLen > 1) {
|
||||
*ret++ = *p++;
|
||||
retLen--;
|
||||
}
|
||||
//Zero-terminate string
|
||||
*ret = 0;
|
||||
//All done :)
|
||||
return 1;
|
||||
}
|
||||
p += strlen(p) + 1; //Skip past end of string and \0 terminator
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Call before calling httpdStartResponse to disable automatically-chosen transfer
|
||||
//encodings (specifically, for now, chunking) and fall back on Connection: Close.
|
||||
void httpdDisableTransferEncoding(HttpdConnData *conn) {
|
||||
conn->priv->flags &= ~HFL_CHUNKED;
|
||||
}
|
||||
|
||||
//Start the response headers.
|
||||
void httpdStartResponse(HttpdConnData *conn, int code) {
|
||||
char buff[256];
|
||||
int l;
|
||||
l = sprintf(buff, "HTTP/1.%d %d OK\r\nServer: esp32-httpd/"HTTPDVER"\r\n%s\r\n",
|
||||
(conn->priv->flags & HFL_HTTP11) ? 1 : 0,
|
||||
code,
|
||||
(conn->priv->flags & HFL_CHUNKED) ? "Transfer-Encoding: chunked" : "Connection: close");
|
||||
httpdSend(conn, buff, l);
|
||||
}
|
||||
|
||||
//Send a http header.
|
||||
void httpdHeader(HttpdConnData *conn, const char *field, const char *val) {
|
||||
httpdSend(conn, field, -1);
|
||||
httpdSend(conn, ": ", -1);
|
||||
httpdSend(conn, val, -1);
|
||||
httpdSend(conn, "\r\n", -1);
|
||||
}
|
||||
|
||||
//Finish the headers.
|
||||
void httpdEndHeaders(HttpdConnData *conn) {
|
||||
httpdSend(conn, "\r\n", -1);
|
||||
conn->priv->flags |= HFL_SENDINGBODY;
|
||||
}
|
||||
|
||||
//Redirect to the given URL.
|
||||
void httpdRedirect(HttpdConnData *conn, char *newUrl) {
|
||||
httpdStartResponse(conn, 302);
|
||||
httpdHeader(conn, "Location", newUrl);
|
||||
httpdEndHeaders(conn);
|
||||
httpdSend(conn, "Moved to ", -1);
|
||||
httpdSend(conn, newUrl, -1);
|
||||
}
|
||||
|
||||
//Use this as a cgi function to redirect one url to another.
|
||||
int cgiRedirect(HttpdConnData *connData) {
|
||||
if (connData->conn == NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
httpdRedirect(connData, (char*)connData->cgiArg);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
//Used to spit out a 404 error
|
||||
static int cgiNotFound(HttpdConnData *connData) {
|
||||
if (connData->conn == NULL) return HTTPD_CGI_DONE;
|
||||
httpdStartResponse(connData, 404);
|
||||
httpdEndHeaders(connData);
|
||||
httpdSend(connData, "404 File not found.", -1);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
//This CGI function redirects to a fixed url of http://[hostname]/ if hostname field of request isn't
|
||||
//already that hostname. Use this in combination with a DNS server that redirects everything to the
|
||||
//ESP in order to load a HTML page as soon as a phone, tablet etc connects to the ESP. Watch out:
|
||||
//this will also redirect connections when the ESP is in STA mode, potentially to a hostname that is not
|
||||
//in the 'official' DNS and so will fail.
|
||||
int cgiRedirectToHostname(HttpdConnData *connData) {
|
||||
static const char hostFmt[] = "http://%s/";
|
||||
char *buff;
|
||||
int isIP = 0;
|
||||
int x;
|
||||
if (connData->conn == NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
if (connData->hostName == NULL) {
|
||||
//httpd_printf("Huh? No hostname.\n");
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
|
||||
//Quick and dirty code to see if host is an IP
|
||||
if (strlen(connData->hostName) > 8) {
|
||||
isIP = 1;
|
||||
for (x = 0; x < strlen(connData->hostName); x++) {
|
||||
if (connData->hostName[x] != '.' && (connData->hostName[x] < '0' || connData->hostName[x] > '9')) isIP = 0;
|
||||
}
|
||||
}
|
||||
if (isIP) return HTTPD_CGI_NOTFOUND;
|
||||
//Check hostname; pass on if the same
|
||||
if (strcmp(connData->hostName, (char*)connData->cgiArg) == 0) return HTTPD_CGI_NOTFOUND;
|
||||
//Not the same. Redirect to real hostname.
|
||||
buff = malloc(strlen((char*)connData->cgiArg) + sizeof(hostFmt));
|
||||
sprintf(buff, hostFmt, (char*)connData->cgiArg);
|
||||
//httpd_printf("Redirecting to hostname url %s\n", buff);
|
||||
httpdRedirect(connData, buff);
|
||||
free(buff);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
|
||||
//Same as above, but will only redirect clients with an IP that is in the range of
|
||||
//the SoftAP interface. This should preclude clients connected to the STA interface
|
||||
//to be redirected to nowhere.
|
||||
int cgiRedirectApClientToHostname(HttpdConnData *connData) {
|
||||
#ifndef FREERTOS
|
||||
uint32_t *remadr;
|
||||
tcpip_adapter_ip_info_t apip;
|
||||
|
||||
wifi_mode_t x;
|
||||
esp_wifi_get_mode(&x);
|
||||
//Check if we have an softap interface; bail out if not
|
||||
if (x != 2 && x != 3) return HTTPD_CGI_NOTFOUND;
|
||||
remadr = (uint32_t *)connData->remote_ip;
|
||||
/// not used. wifi_get_ip_info(WIFI_IF_AP, &apip);
|
||||
if ((*remadr & apip.netmask.addr) == (apip.ip.addr & apip.netmask.addr)) {
|
||||
return cgiRedirectToHostname(connData);
|
||||
} else {
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
#else
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//Add data to the send buffer. len is the length of the data. If len is -1
|
||||
//the data is seen as a C-string.
|
||||
//Returns 1 for success, 0 for out-of-memory.
|
||||
int httpdSend(HttpdConnData *conn, const char *data, int len) {
|
||||
if (conn->conn == NULL) return 0;
|
||||
if (len < 0) len = strlen(data);
|
||||
if (len == 0) return 0;
|
||||
if (conn->priv->flags & HFL_CHUNKED && conn->priv->flags & HFL_SENDINGBODY && conn->priv->chunkHdr == NULL) {
|
||||
if (conn->priv->sendBuffLen + len + 6 > MAX_SENDBUFF_LEN) return 0;
|
||||
//Prefix with chunk header
|
||||
conn->priv->chunkHdr = &conn->priv->sendBuff[conn->priv->sendBuffLen];
|
||||
strcpy(conn->priv->chunkHdr, "0000\r\n");
|
||||
conn->priv->sendBuffLen += 6;
|
||||
}
|
||||
if (conn->priv->sendBuffLen + len > MAX_SENDBUFF_LEN) return 0;
|
||||
memcpy(conn->priv->sendBuff + conn->priv->sendBuffLen, data, len);
|
||||
conn->priv->sendBuffLen += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char httpdHexNibble(int val) {
|
||||
val &= 0xf;
|
||||
if (val < 10) return '0' + val;
|
||||
return 'A' + (val - 10);
|
||||
}
|
||||
|
||||
//Function to send any data in conn->priv->sendBuff. Do not use in CGIs unless you know what you
|
||||
//are doing! Also, if you do set conn->cgi to NULL to indicate the connection is closed, do it BEFORE
|
||||
//calling this.
|
||||
void httpdFlushSendBuffer(HttpdConnData *conn) {
|
||||
int r, len;
|
||||
|
||||
if (conn->conn == NULL) return;
|
||||
if (conn->priv->chunkHdr != NULL) {
|
||||
//We're sending chunked data, and the chunk needs fixing up.
|
||||
//Finish chunk with cr/lf
|
||||
httpdSend(conn, "\r\n", 2);
|
||||
//Calculate length of chunk
|
||||
len = ((&conn->priv->sendBuff[conn->priv->sendBuffLen]) - conn->priv->chunkHdr) - 8;
|
||||
//Fix up chunk header to correct value
|
||||
conn->priv->chunkHdr[0] = httpdHexNibble(len >> 12);
|
||||
conn->priv->chunkHdr[1] = httpdHexNibble(len >> 8);
|
||||
conn->priv->chunkHdr[2] = httpdHexNibble(len >> 4);
|
||||
conn->priv->chunkHdr[3] = httpdHexNibble(len >> 0);
|
||||
//Reset chunk hdr for next call
|
||||
conn->priv->chunkHdr = NULL;
|
||||
}
|
||||
|
||||
if (conn->priv->flags & HFL_CHUNKED && conn->priv->flags & HFL_SENDINGBODY && conn->cgi == NULL) {
|
||||
//End chunk
|
||||
strcpy(&conn->priv->sendBuff[conn->priv->sendBuffLen], "0\r\n\r\n");
|
||||
conn->priv->sendBuffLen += 5;
|
||||
}
|
||||
|
||||
// httpd_printf("Server.line %d %x %p\n", __LINE__, conn->priv->flags & HFL_ONLYRESPONSEOK, conn->cgi);
|
||||
if (conn->priv->flags & HFL_ONLYRESPONSEOK && conn->cgi == NULL) {
|
||||
//End chunk
|
||||
strcpy(&conn->priv->sendBuff[0], "HTTP/1.0 200 OK\r\nContent-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
|
||||
conn->priv->sendBuffLen = strlen(conn->priv->sendBuff);
|
||||
}
|
||||
|
||||
httpd_printf("httpd.line %d %x %p\n", __LINE__, conn->priv->flags & HFL_ONLYRESPONSEOK, conn->cgi);
|
||||
if (conn->priv->flags & HFL_ONLYRESPONSEOK && conn->cgi == NULL) {
|
||||
//End chunk
|
||||
strcpy(&conn->priv->sendBuff[0], "HTTP/1.0 200 OK\r\nContent-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
|
||||
conn->priv->sendBuffLen = strlen(conn->priv->sendBuff);
|
||||
}
|
||||
|
||||
if (conn->priv->sendBuffLen != 0) {
|
||||
r = httpdPlatSendData(conn->conn, conn->priv->sendBuff, conn->priv->sendBuffLen);
|
||||
if (!r) {
|
||||
//Can't send this for some reason. Dump packet in backlog, we can send it later.
|
||||
if (conn->priv->sendBacklogSize + conn->priv->sendBuffLen > MAX_BACKLOG_SIZE) {
|
||||
//httpd_printf("Httpd: Backlog: Exceeded max backlog size, dropped %d bytes instead of sending them.\n", conn->priv->sendBuffLen);
|
||||
conn->priv->sendBuffLen = 0;
|
||||
return;
|
||||
}
|
||||
HttpSendBacklogItem *i = malloc(sizeof(HttpSendBacklogItem) + conn->priv->sendBuffLen);
|
||||
if (i == NULL) {
|
||||
//httpd_printf("Httpd: Backlog: malloc failed, out of memory!\n");
|
||||
return;
|
||||
}
|
||||
memcpy(i->data, conn->priv->sendBuff, conn->priv->sendBuffLen);
|
||||
i->len = conn->priv->sendBuffLen;
|
||||
i->next = NULL;
|
||||
if (conn->priv->sendBacklog == NULL) {
|
||||
conn->priv->sendBacklog = i;
|
||||
} else {
|
||||
HttpSendBacklogItem *e = conn->priv->sendBacklog;
|
||||
while (e->next != NULL) e = e->next;
|
||||
e->next = i;
|
||||
}
|
||||
conn->priv->sendBacklogSize += conn->priv->sendBuffLen;
|
||||
}
|
||||
conn->priv->sendBuffLen = 0;
|
||||
conn->priv->flags = (conn->priv->flags & (~HFL_ONLYRESPONSEOK));
|
||||
}
|
||||
}
|
||||
|
||||
void httpdCgiIsDone(HttpdConnData *conn) {
|
||||
conn->cgi = NULL; //no need to call this anymore
|
||||
if ((conn->priv->flags & HFL_CHUNKED)
|
||||
/*|| (conn->priv->flags &HFL_ONLYRESPONSEOK)*/) {
|
||||
//httpd_printf("Pool slot %d is done. Cleaning up for next req\n", conn->slot);
|
||||
httpdFlushSendBuffer(conn);
|
||||
//Note: Do not clean up sendBacklog, it may still contain data at this point.
|
||||
conn->priv->headPos = 0;
|
||||
conn->post->len = -1;
|
||||
conn->priv->flags = 0;
|
||||
if (conn->post->buff) free(conn->post->buff);
|
||||
conn->post->buff = NULL;
|
||||
conn->post->buffLen = 0;
|
||||
conn->post->received = 0;
|
||||
conn->hostName = NULL;
|
||||
} else if (HFL_ONLYRESPONSEOK != (conn->priv->flags & HFL_ONLYRESPONSEOK)) {
|
||||
//Cannot re-use this connection. Mark to get it killed after all data is sent.
|
||||
conn->priv->flags |= HFL_DISCONAFTERSENT;
|
||||
}
|
||||
}
|
||||
|
||||
//Callback called when the data on a socket has been successfully
|
||||
//sent.
|
||||
void httpdSentCb(ConnTypePtr rconn, char *remIp, int remPort) {
|
||||
int r;
|
||||
HttpdConnData *conn = httpdFindConnData(rconn, remIp, remPort);
|
||||
char *sendBuff;
|
||||
|
||||
if (conn == NULL) return;
|
||||
|
||||
if (conn->priv->sendBacklog != NULL) {
|
||||
//We have some backlog to send first.
|
||||
HttpSendBacklogItem *next = conn->priv->sendBacklog->next;
|
||||
httpdPlatSendData(conn->conn, conn->priv->sendBacklog->data, conn->priv->sendBacklog->len);
|
||||
conn->priv->sendBacklogSize -= conn->priv->sendBacklog->len;
|
||||
free(conn->priv->sendBacklog);
|
||||
conn->priv->sendBacklog = next;
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->priv->flags & HFL_DISCONAFTERSENT) { //Marked for destruction?
|
||||
//httpd_printf("Pool slot %d is done. Closing.\n", conn->slot);
|
||||
httpdPlatDisconnect(conn->conn);
|
||||
return; //No need to call httpdFlushSendBuffer.
|
||||
}
|
||||
|
||||
//If we don't have a CGI function, there's nothing to do but wait for something from the client.
|
||||
if (conn->cgi == NULL) return;
|
||||
|
||||
sendBuff = malloc(MAX_SENDBUFF_LEN);
|
||||
conn->priv->sendBuff = sendBuff;
|
||||
conn->priv->sendBuffLen = 0;
|
||||
r = conn->cgi(conn); //Execute cgi fn.
|
||||
if (r == HTTPD_CGI_DONE) {
|
||||
httpdCgiIsDone(conn);
|
||||
}
|
||||
if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) {
|
||||
//httpd_printf("ERROR! CGI fn returns code %d after sending data! Bad CGI!\n", r);
|
||||
httpdCgiIsDone(conn);
|
||||
}
|
||||
httpdFlushSendBuffer(conn);
|
||||
free(sendBuff);
|
||||
}
|
||||
|
||||
//This is called when the headers have been received and the connection is ready to send
|
||||
//the result headers and data.
|
||||
//We need to find the CGI function to call, call it, and dependent on what it returns either
|
||||
//find the next cgi function, wait till the cgi data is sent or close up the connection.
|
||||
static void httpdProcessRequest(HttpdConnData *conn) {
|
||||
int r;
|
||||
int i = 0;
|
||||
if (conn->url == NULL) {
|
||||
//httpd_printf("WtF? url = NULL\n");
|
||||
return; //Shouldn't happen
|
||||
}
|
||||
//See if we can find a CGI that's happy to handle the request.
|
||||
while (1) {
|
||||
//Look up URL in the built-in URL table.
|
||||
while (builtInUrls[i].url != NULL) {
|
||||
int match = 0;
|
||||
//See if there's a literal match
|
||||
if (strcmp(builtInUrls[i].url, conn->url) == 0) match = 1;
|
||||
//See if there's a wildcard match
|
||||
if (builtInUrls[i].url[strlen(builtInUrls[i].url) - 1] == '*' &&
|
||||
strncmp(builtInUrls[i].url, conn->url, strlen(builtInUrls[i].url) - 1) == 0) match = 1;
|
||||
if (match) {
|
||||
if (strcmp(conn->getArgs, "command=soundbox") == 0) {
|
||||
conn->cgiData = NULL;
|
||||
conn->cgi = builtInUrls[i].cgiCb;
|
||||
conn->cgiArg = builtInUrls[i].cgiArg;
|
||||
conn->priv->flags |= HFL_ONLYRESPONSEOK;
|
||||
|
||||
httpd_printf("Soundbox request is right.%d\n", __LINE__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (builtInUrls[i].url == NULL) {
|
||||
//Drat, we're at the end of the URL table. This usually shouldn't happen. Well, just
|
||||
//generate a built-in 404 to handle this.
|
||||
httpd_printf("%s not found. 404!\n", conn->url);
|
||||
conn->cgi = cgiNotFound;
|
||||
}
|
||||
|
||||
//Okay, we have a CGI function that matches the URL. See if it wants to handle the
|
||||
//particular URL we're supposed to handle.
|
||||
|
||||
r = conn->cgi(conn);
|
||||
if (r == HTTPD_CGI_MORE) {
|
||||
//Yep, it's happy to do so and has more data to send.
|
||||
if (conn->recvHdl) {
|
||||
//Seems the CGI is planning to do some long-term communications with the socket.
|
||||
//Disable the timeout on it, so we won't run into that.
|
||||
httpdPlatDisableTimeout(conn->conn);
|
||||
}
|
||||
httpdFlushSendBuffer(conn);
|
||||
return;
|
||||
} else if (r == HTTPD_CGI_DONE) {
|
||||
//Yep, it's happy to do so and already is done sending data.
|
||||
httpdCgiIsDone(conn);
|
||||
return;
|
||||
} else if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) {
|
||||
//URL doesn't want to handle the request: either the data isn't found or there's no
|
||||
//need to generate a login screen.
|
||||
i++; //look at next url the next iteration of the loop.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Parse a line of header data and modify the connection data accordingly.
|
||||
static void httpdParseHeader(char *h, HttpdConnData *conn) {
|
||||
int i;
|
||||
char firstLine = 0;
|
||||
|
||||
if (strncmp(h, "GET ", 4) == 0) {
|
||||
conn->requestType = HTTPD_METHOD_GET;
|
||||
firstLine = 1;
|
||||
} else if (strncmp(h, "PUT ", 4) == 0) {
|
||||
conn->requestType = HTTPD_METHOD_PUT;
|
||||
firstLine = 1;
|
||||
} else if (strncmp(h, "Host:", 5) == 0) {
|
||||
i = 5;
|
||||
while (h[i] == ' ') i++;
|
||||
conn->hostName = &h[i];
|
||||
} else if (strncmp(h, "POST ", 5) == 0) {
|
||||
conn->requestType = HTTPD_METHOD_POST;
|
||||
firstLine = 1;
|
||||
}
|
||||
|
||||
if (firstLine) {
|
||||
char *e;
|
||||
|
||||
//Skip past the space after POST/GET
|
||||
i = 0;
|
||||
while (h[i] != ' ') i++;
|
||||
conn->url = h + i + 1;
|
||||
|
||||
//Figure out end of url.
|
||||
e = (char*)strstr(conn->url, " ");
|
||||
if (e == NULL) return; //wtf?
|
||||
*e = 0; //terminate url part
|
||||
e++; //Skip to protocol indicator
|
||||
while (*e == ' ') e++; //Skip spaces.
|
||||
//If HTTP/1.1, note that and set chunked encoding
|
||||
if (strcasecmp(e, "HTTP/1.1") == 0) conn->priv->flags |= HFL_HTTP11 | HFL_CHUNKED;
|
||||
|
||||
// httpd_printf("URL = %s\n", conn->url);
|
||||
//Parse out the URL part before the GET parameters.
|
||||
conn->getArgs = (char*)strstr(conn->url, "?");
|
||||
if (conn->getArgs != 0) {
|
||||
*conn->getArgs = 0;
|
||||
conn->getArgs++;
|
||||
//httpd_printf("GET args = %s\n", conn->getArgs);
|
||||
} else {
|
||||
conn->getArgs = NULL;
|
||||
}
|
||||
} else if (strncmp(h, "Connection:", 11) == 0) {
|
||||
i = 11;
|
||||
//Skip trailing spaces
|
||||
while (h[i] == ' ') i++;
|
||||
if (strncmp(&h[i], "close", 5) == 0) conn->priv->flags &= ~HFL_CHUNKED; //Don't use chunked conn
|
||||
} else if (strncmp(h, "Content-Length:", 15) == 0) {
|
||||
i = 15;
|
||||
//Skip trailing spaces
|
||||
while (h[i] == ' ') i++;
|
||||
//Get POST data length
|
||||
conn->post->len = atoi(h + i);
|
||||
|
||||
// Allocate the buffer
|
||||
if (conn->post->len > MAX_POST) {
|
||||
// we'll stream this in in chunks
|
||||
conn->post->buffSize = MAX_POST;
|
||||
} else {
|
||||
conn->post->buffSize = conn->post->len;
|
||||
}
|
||||
//httpd_printf("Mallocced buffer for %d + 1 bytes of post data.\n", conn->post->buffSize);
|
||||
conn->post->buff = (char*)malloc(conn->post->buffSize + 1);
|
||||
conn->post->buffLen = 0;
|
||||
} else if (strncmp(h, "Content-Type: ", 14) == 0) {
|
||||
if (strstr(h, "multipart/form-data")) {
|
||||
// It's multipart form data so let's pull out the boundary for future use
|
||||
char *b;
|
||||
if ((b = strstr(h, "boundary=")) != NULL) {
|
||||
conn->post->multipartBoundary = b + 7; // move the pointer 2 chars before boundary then fill them with dashes
|
||||
conn->post->multipartBoundary[0] = '-';
|
||||
conn->post->multipartBoundary[1] = '-';
|
||||
//httpd_printf("boundary = %s\n", conn->post->multipartBoundary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Callback called when there's data available on a socket.
|
||||
void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsigned short len) {
|
||||
int x, r;
|
||||
char *p, *e;
|
||||
char *sendBuff = NULL;
|
||||
HttpdConnData *conn = httpdFindConnData(rconn, remIp, remPort);
|
||||
if (conn == NULL) return;
|
||||
if (conn->priv->sendBuff) return; // the connection is busy
|
||||
|
||||
sendBuff = (char *)malloc(MAX_SENDBUFF_LEN);
|
||||
if (!sendBuff)
|
||||
return;
|
||||
// ENTER_CRITICAL();
|
||||
memset(sendBuff, 0, MAX_SENDBUFF_LEN);
|
||||
conn->priv->sendBuff = sendBuff;
|
||||
conn->priv->sendBuffLen = 0;
|
||||
// ESP_MFI_EXIT_CRITICAL();
|
||||
|
||||
//This is slightly evil/dirty: we abuse conn->post->len as a state variable for where in the http communications we are:
|
||||
//<0 (-1): Post len unknown because we're still receiving headers
|
||||
//==0: No post data
|
||||
//>0: Need to receive post data
|
||||
//ToDo: See if we can use something more elegant for this.
|
||||
for (x = 0; x < len; x++) {
|
||||
if (conn->post->len < 0) {
|
||||
//This byte is a header byte.
|
||||
if (data[x] == '\n') {
|
||||
//Compatibility with clients that send \n only: fake a \r in front of this.
|
||||
if (conn->priv->headPos != 0 && conn->priv->head[conn->priv->headPos - 1] != '\r') {
|
||||
conn->priv->head[conn->priv->headPos++] = '\r';
|
||||
}
|
||||
}
|
||||
if (conn->priv->headPos != MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++] = data[x];
|
||||
conn->priv->head[conn->priv->headPos] = 0;
|
||||
//Scan for /r/n/r/n. Receiving this indicate the headers end.
|
||||
if (data[x] == '\n' && (char *)strstr(conn->priv->head, "\r\n\r\n") != NULL) {
|
||||
//Indicate we're done with the headers.
|
||||
conn->post->len = 0;
|
||||
//Reset url data
|
||||
conn->url = NULL;
|
||||
//Iterate over all received headers and parse them.
|
||||
p = conn->priv->head;
|
||||
while (p < (&conn->priv->head[conn->priv->headPos - 4])) {
|
||||
e = (char *)strstr(p, "\r\n"); //Find end of header line
|
||||
if (e == NULL) break; //Shouldn't happen.
|
||||
e[0] = 0; //Zero-terminate header
|
||||
httpdParseHeader(p, conn); //and parse it.
|
||||
p = e + 2; //Skip /r/n (now /0/n)
|
||||
}
|
||||
|
||||
// httpd_printf("find head ok.line %d\n", __LINE__);
|
||||
//If we don't need to receive post data, we can send the response now.
|
||||
if (conn->post->len == 0) {
|
||||
httpdProcessRequest(conn);
|
||||
}
|
||||
}
|
||||
} else if (conn->post->len != 0) {
|
||||
//This byte is a POST byte.
|
||||
|
||||
conn->post->buff[conn->post->buffLen++] = data[x];
|
||||
conn->post->received++;
|
||||
conn->hostName = NULL;
|
||||
|
||||
if (conn->post->buffLen >= conn->post->buffSize || conn->post->received == conn->post->len) {
|
||||
//Received a chunk of post data
|
||||
conn->post->buff[conn->post->buffLen] = 0; //zero-terminate, in case the cgi handler knows it can use strings
|
||||
//Send the response.
|
||||
|
||||
if (conn->cgi) {
|
||||
r = conn->cgi(conn);
|
||||
if (r == HTTPD_CGI_DONE) {
|
||||
httpdCgiIsDone(conn);
|
||||
}
|
||||
} else {
|
||||
//No CGI fn set yet: probably first call. Allow httpdProcessRequest to choose CGI and
|
||||
//call it the first time.
|
||||
httpdProcessRequest(conn);
|
||||
}
|
||||
conn->post->buffLen = 0;
|
||||
}
|
||||
} else {
|
||||
//Let cgi handle data if it registered a recvHdl callback. If not, ignore.
|
||||
if (conn->recvHdl) {
|
||||
r = conn->recvHdl(conn, data + x, len - x);
|
||||
if (r == HTTPD_CGI_DONE) {
|
||||
// httpd_printf("Recvhdl returned DONE\n");
|
||||
httpdCgiIsDone(conn);
|
||||
//We assume the recvhdlr has sent something; we'll kill the sock in the sent callback.
|
||||
}
|
||||
break; //ignore rest of data, recvhdl has parsed it.
|
||||
} else {
|
||||
httpd_printf("Eh? Got unexpected data from client. %s\n", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (conn->conn) httpdFlushSendBuffer(conn);
|
||||
// ESP_MFI_ENTER_CRITICAL();
|
||||
conn->priv->sendBuff = NULL;
|
||||
conn->priv->sendBuffLen = 0;
|
||||
// ESP_MFI_EXIT_CRITICAL();
|
||||
free(sendBuff);
|
||||
}
|
||||
|
||||
//The platform layer should ALWAYS call this function, regardless if the connection is closed by the server
|
||||
//or by the client.
|
||||
void httpdDisconCb(ConnTypePtr rconn, char *remIp, int remPort) {
|
||||
HttpdConnData *hconn = httpdFindConnData(rconn, remIp, remPort);
|
||||
if (hconn == NULL) return;
|
||||
httpd_printf("Pool slot %d: socket closed.\n", hconn->slot);
|
||||
hconn->conn = NULL; //indicate cgi the connection is gone
|
||||
if (hconn->cgi) hconn->cgi(hconn); //Execute cgi fn if needed
|
||||
httpdRetireConn(hconn);
|
||||
}
|
||||
|
||||
|
||||
int httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort) {
|
||||
int i;
|
||||
//Find empty conndata in pool
|
||||
for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) if (connData[i] == NULL) break;
|
||||
//httpd_printf("Conn req from %d.%d.%d.%d:%d, using pool slot %d\n", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort, i);
|
||||
if (i == HTTPD_MAX_CONNECTIONS) {
|
||||
//httpd_printf("Aiee, conn pool overflow!\n");
|
||||
return 0;
|
||||
}
|
||||
connData[i] = malloc(sizeof(HttpdConnData));
|
||||
memset(connData[i], 0, sizeof(HttpdConnData));
|
||||
connData[i]->priv = malloc(sizeof(HttpdPriv));
|
||||
memset(connData[i]->priv, 0, sizeof(HttpdPriv));
|
||||
connData[i]->conn = conn;
|
||||
connData[i]->slot = i;
|
||||
connData[i]->priv->headPos = 0;
|
||||
connData[i]->post = malloc(sizeof(HttpdPostData));
|
||||
memset(connData[i]->post, 0, sizeof(HttpdPostData));
|
||||
connData[i]->post->buff = NULL;
|
||||
connData[i]->post->buffLen = 0;
|
||||
connData[i]->post->received = 0;
|
||||
connData[i]->post->len = -1;
|
||||
connData[i]->hostName = NULL;
|
||||
connData[i]->remote_port = remPort;
|
||||
connData[i]->priv->sendBacklog = NULL;
|
||||
connData[i]->priv->sendBacklogSize = 0;
|
||||
memcpy(connData[i]->remote_ip, remIp, 4);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Httpd initialization routine. Call this to kick off webserver functionality.
|
||||
void httpdInit(HttpdBuiltInUrl *fixedUrls, int port) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HTTPD_MAX_CONNECTIONS; i++) {
|
||||
connData[i] = NULL;
|
||||
}
|
||||
builtInUrls = fixedUrls;
|
||||
|
||||
httpdPlatInit(port, HTTPD_MAX_CONNECTIONS);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef HTTPD_COM_H
|
||||
#define HTTPD_COM_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "httpd-com.h"
|
||||
|
||||
typedef struct RtosConnType RtosConnType;
|
||||
typedef RtosConnType* ConnTypePtr;
|
||||
#define httpd_printf(fmt, ...) do { \
|
||||
ets_printf(fmt, ##__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef HTTPD_PLATFORM_H
|
||||
#define HTTPD_PLATFORM_H
|
||||
#include "httpd-com.h"
|
||||
|
||||
#define WEB_SERVER_TASK_PRIO 6
|
||||
int httpdPlatSendData(ConnTypePtr conn, char *buff, int len);
|
||||
void httpdPlatDisconnect(ConnTypePtr conn);
|
||||
void httpdPlatDisableTimeout(ConnTypePtr conn);
|
||||
void httpdPlatInit(int port, int maxConnCt);
|
||||
int httpdPlatUninit(void) ;
|
||||
|
||||
|
||||
#endif
|
|
@ -1,132 +0,0 @@
|
|||
#ifndef HTTPD_H
|
||||
#define HTTPD_H
|
||||
|
||||
#include "httpd-com.h"
|
||||
#include "esp_types.h"
|
||||
|
||||
#define HTTPDVER "0.4"
|
||||
|
||||
#define HTTPD_CGI_MORE 0
|
||||
#define HTTPD_CGI_DONE 1
|
||||
#define HTTPD_CGI_NOTFOUND 2
|
||||
#define HTTPD_CGI_AUTHENTICATED 3
|
||||
|
||||
#define HTTPD_METHOD_GET 1
|
||||
#define HTTPD_METHOD_POST 2
|
||||
#define HTTPD_METHOD_PUT 3
|
||||
|
||||
|
||||
#define HTTPD_MAX_CONNECTIONS 2
|
||||
#define HTTPD_STACKSIZE (4*1024)
|
||||
#define ESP32
|
||||
|
||||
|
||||
typedef struct HttpdPriv HttpdPriv;
|
||||
typedef struct HttpdConnData HttpdConnData;
|
||||
typedef struct HttpdPostData HttpdPostData;
|
||||
|
||||
typedef int (* cgiSendCallback)(HttpdConnData *connData);
|
||||
typedef int (* cgiRecvHandler)(HttpdConnData *connData, char *data, int len);
|
||||
|
||||
//Max amount of simultaneous connections
|
||||
#define MAX_CONN 8
|
||||
//Max length of request head. This is statically allocated for each connection.
|
||||
#define MAX_HEAD_LEN 1024
|
||||
//Max post buffer len. This is dynamically malloc'ed if needed.
|
||||
#define MAX_POST 1024
|
||||
//Max send buffer len. This is allocated on the stack.
|
||||
#define MAX_SENDBUFF_LEN 1460
|
||||
//If some data can't be sent because the underlaying socket doesn't accept the data (like the nonos
|
||||
//layer is prone to do), we put it in a backlog that is dynamically malloc'ed. This defines the max
|
||||
//size of the backlog.
|
||||
#define MAX_BACKLOG_SIZE (4*1024)
|
||||
|
||||
typedef struct HttpSendBacklogItem HttpSendBacklogItem;
|
||||
|
||||
struct HttpSendBacklogItem {
|
||||
int len;
|
||||
HttpSendBacklogItem *next;
|
||||
char data[];
|
||||
};
|
||||
|
||||
//Flags
|
||||
#define HFL_HTTP11 (1<<0)
|
||||
#define HFL_CHUNKED (0<<1)
|
||||
#define HFL_SENDINGBODY (1<<2)
|
||||
#define HFL_DISCONAFTERSENT (1<<3)
|
||||
#define HFL_ONLYRESPONSEOK (1<<4)
|
||||
|
||||
|
||||
//Private data for http connection
|
||||
struct HttpdPriv {
|
||||
char head[MAX_HEAD_LEN];
|
||||
int headPos;
|
||||
char *sendBuff;
|
||||
int sendBuffLen;
|
||||
char *chunkHdr;
|
||||
HttpSendBacklogItem *sendBacklog;
|
||||
int sendBacklogSize;
|
||||
int flags;
|
||||
};
|
||||
|
||||
//A struct describing a http connection. This gets passed to cgi functions.
|
||||
struct HttpdConnData {
|
||||
ConnTypePtr conn; // The TCP connection. Exact type depends on the platform.
|
||||
char requestType; // One of the HTTPD_METHOD_* values
|
||||
char *url; // The URL requested, without hostname or GET arguments
|
||||
char *getArgs; // The GET arguments for this request, if any.
|
||||
const void *cgiArg; // Argument to the CGI function, as stated as the 3rd argument of
|
||||
// the builtInUrls entry that referred to the CGI function.
|
||||
void *cgiData; // Opaque data pointer for the CGI function
|
||||
char *hostName; // Host name field of request
|
||||
HttpdPriv *priv; // Opaque pointer to data for internal httpd housekeeping
|
||||
cgiSendCallback cgi; // CGI function pointer
|
||||
cgiRecvHandler recvHdl; // Handler for data received after headers, if any
|
||||
HttpdPostData *post; // POST data structure
|
||||
int remote_port; // Remote TCP port
|
||||
uint8_t remote_ip[4]; // IP address of client
|
||||
uint8_t slot; // Slot ID
|
||||
};
|
||||
|
||||
//A struct describing the POST data sent inside the http connection. This is used by the CGI functions
|
||||
struct HttpdPostData {
|
||||
int len; // POST Content-Length
|
||||
int buffSize; // The maximum length of the post buffer
|
||||
int buffLen; // The amount of bytes in the current post buffer
|
||||
int received; // The total amount of bytes received so far
|
||||
char *buff; // Actual POST data buffer
|
||||
char *multipartBoundary;
|
||||
};
|
||||
|
||||
//A struct describing an url. This is the main struct that's used to send different URL requests to
|
||||
//different routines.
|
||||
typedef struct {
|
||||
const char *url;
|
||||
cgiSendCallback cgiCb;
|
||||
const void *cgiArg;
|
||||
} HttpdBuiltInUrl;
|
||||
|
||||
int cgiRedirect(HttpdConnData *connData);
|
||||
int cgiRedirectToHostname(HttpdConnData *connData);
|
||||
int cgiRedirectApClientToHostname(HttpdConnData *connData);
|
||||
void httpdRedirect(HttpdConnData *conn, char *newUrl);
|
||||
int httpdUrlDecode(char *val, int valLen, char *ret, int retLen);
|
||||
int httpdFindArg(char *line, char *arg, char *buff, int buffLen);
|
||||
void httpdInit(HttpdBuiltInUrl *fixedUrls, int port);
|
||||
const char *httpdGetMimetype(char *url);
|
||||
void httpdDisableTransferEncoding(HttpdConnData *conn);
|
||||
void httpdStartResponse(HttpdConnData *conn, int code);
|
||||
void httpdHeader(HttpdConnData *conn, const char *field, const char *val);
|
||||
void httpdEndHeaders(HttpdConnData *conn);
|
||||
int httpdGetHeader(HttpdConnData *conn, char *header, char *ret, int retLen);
|
||||
int httpdSend(HttpdConnData *conn, const char *data, int len);
|
||||
void httpdFlushSendBuffer(HttpdConnData *conn);
|
||||
|
||||
//Platform dependent code should call these.
|
||||
void httpdSentCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
void httpdRecvCb(ConnTypePtr conn, char *remIp, int remPort, char *data, unsigned short len);
|
||||
void httpdDisconCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
int httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "Utility.h"
|
||||
#include "psram.h"
|
||||
|
||||
#define mutex_t xSemaphoreHandle
|
||||
mutex_t psram_mem_mutex = NULL;
|
||||
|
||||
void psram_cache_enable(void)
|
||||
{
|
||||
psram_enable(PSRAM_CACHE_F40M_S40M);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memcpy with a cache, atomic protected, speaking, reading and writing
|
||||
*/
|
||||
void psram_cache_memcpy(uint8_t *dst, uint8_t *src, uint16_t len)
|
||||
{
|
||||
uint16_t temp = 0;
|
||||
uint8_t *dest = dst;
|
||||
uint8_t *source = src;
|
||||
uint16_t n = len;
|
||||
if (psram_mem_mutex == NULL) {
|
||||
mutex_init(&psram_mem_mutex);
|
||||
}
|
||||
mutex_lock(&psram_mem_mutex);
|
||||
while (n--) {
|
||||
temp = *source++;
|
||||
*dest++ = temp;
|
||||
}
|
||||
mutex_unlock(&psram_mem_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memset with a cache, atomic protected, speaking, reading and writing
|
||||
*/
|
||||
void psram_cache_memset(uint8_t *addr, uint8_t c, uint32_t len)
|
||||
{
|
||||
if (psram_mem_mutex == NULL) {
|
||||
mutex_init(&psram_mem_mutex);
|
||||
}
|
||||
mutex_lock(&psram_mem_mutex);
|
||||
memset(addr, c, len);
|
||||
mutex_unlock(&psram_mem_mutex);
|
||||
}
|
Loading…
Reference in a new issue