component/bt: remove source codes from esp-audio modules;

This commit is contained in:
wangmengyang 2017-01-02 14:20:28 +08:00
parent d7c1c0b1f6
commit fa72a98635
61 changed files with 6 additions and 222906 deletions

View file

@ -1 +0,0 @@
*.o

View file

@ -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

View file

@ -1,4 +0,0 @@
#This is Espressif Audio Platform
# Setting Up ESP-IDF

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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__

View file

@ -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

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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__

View file

@ -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 //

View file

@ -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

View file

@ -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__

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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__

View file

@ -1,28 +0,0 @@
/**
**************************************************************************************
* @file crc.h
* @brief Calculate CRC Value
*
* @author Aissen Li
* @version V1.0.0
*
* &copy; 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__

View file

@ -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

View file

@ -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

View file

@ -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__

View file

@ -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__

View file

@ -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_*/

View file

@ -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

View file

@ -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

View file

@ -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__

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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");
}

View file

@ -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

View file

@ -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");
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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__

View file

@ -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

View file

@ -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__

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}