MAX_CARLINK_A270S/MXC_A27-PCB4.5-270S/app/main_lvgl.c

1561 lines
41 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file main
*
*/
#if !defined(VG_ONLY) && !defined(AWTK)
/*********************
* INCLUDES
*********************/
#include <stdlib.h>
#include <unistd.h>
#include "lvgl/lvgl.h"
#include "lv_drivers/display/arklcd.h"
#include "lv_examples/src/lv_demo_widgets/lv_demo_widgets.h"
#include "lv_examples/src/lv_demo_printer/lv_demo_printer.h"
#include "xinbas/xinbas_demo.h"
#include "haoke/haoke_demo.h"
#include "lv_lib_png/lv_png.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "board.h"
#include "chip.h"
#include "animation.h"
#include "sfud.h"
#include "romfile.h"
#include "updatefile.h"
#include "sysinfo.h"
#include "mmcsd_core.h"
#include "ff_stdio.h"
#ifdef WIFI_SUPPORT
#include "carlink_ey.h"
#include "carlink_ec.h"
#include "ark_network.h"
#endif
#ifdef OTA_UPDATE_SUPPORT
#include "ota_update.h"
#endif
#ifdef USE_ULOG
#ifdef ULOG_BACKEND_USING_CONSOLE
extern int ulog_console_backend_init(void);
#endif
#ifdef ULOG_EASYFLASH_BACKEND_ENABLE
#include "easyflash.h"
#include "ulog_easyflash.h"
#endif
#ifdef ULOG_FILE_BACKEND_ENABLE
#include "ulog_file.h"
#endif
#endif
#define WIFI_TEST 0
#define BT_TEST 0
#define SDMMC_TEST 0
#undef TASK_STATUS_MONITOR
#define USB_DEV_PLUGED 0
#define USB_DEV_UNPLUGED 1
extern int usb_wait_stor_dev_pluged(uint32_t timeout);
extern void hub_usb_dev_reset(void);
static void hal_init(void);
#if !LV_TICK_CUSTOM
static void tick_thread(void *data);
#endif
#ifdef VG_DRIVER
#pragma data_alignment=1024
#ifdef REVERSE_TRACK
#define VG_HEAP_SIZE 0x600000
#else
#define VG_HEAP_SIZE 0xa00000
#endif
__no_init static uint8_t vgHeap[VG_HEAP_SIZE];
extern int xm_vg_init (unsigned int heap_addr, unsigned int size);
#endif
#define INPUT_QUEUE_LEN 64
static QueueHandle_t touch_input_mq;
static QueueHandle_t keypad_input_mq;
void SendTouchInputEvent(lv_indev_data_t *indata)
{
xQueueSend(touch_input_mq, indata, 0);
}
void SendTouchInputEventFromISR(lv_indev_data_t *indata)
{
xQueueSendFromISR(touch_input_mq, indata, 0);
}
void SendKeypadInputEvent(lv_indev_data_t *indata)
{
xQueueSend(keypad_input_mq, indata, 0);
}
void SendKeypadInputEventFromISR(lv_indev_data_t *indata)
{
xQueueSendFromISR(keypad_input_mq, indata, 0);
}
#ifdef SDMMC_SUPPORT
#if SDMMC_TEST
static void sdcard_read_thread(void *para)
{
unsigned int status;
for (;;) {
status = mmcsd_wait_cd_changed(portMAX_DELAY);
if (status == MMCSD_HOST_PLUGED) {
printf("card inserted.\n");
#ifdef OTA_UPDATE_SUPPORT
FF_FILE *fp = ff_fopen("/sd/update.bin", "rb");
if (fp) {
ff_fclose(fp);
update_from_media("/sd", UPFILE_TYPE_WHOLE);
}
#if DEVICE_TYPE_SELECT == EMMC_FLASH
fp = ff_fopen("/sd/emmcldr.bin", "rb");
#else
fp = ff_fopen("/sd/spildr.bin", "rb");
#endif
if (fp) {
ff_fclose(fp);
update_from_media("/sd", UPFILE_TYPE_FIRSTLDR);
}
fp = ff_fopen("/sd/stepldr.bin", "rb");
if (fp) {
ff_fclose(fp);
update_from_media("/sd", UPFILE_TYPE_STEPLDR);
}
fp = ff_fopen("/sd/lnchemmc.bin", "rb");
if (fp) {
ff_fclose(fp);
update_from_media("/sd", UPFILE_TYPE_LNCHEMMC);
}
#else
FF_FILE *fp = ff_fopen("/sd/update.bin", "rb");
if (fp) {
UpFileHeader header;
SysInfo *sysinfo = GetSysInfo();
if (ff_fread(&header, 1, sizeof(header), fp) == sizeof(header)) {
if(header.magic != MKTAG('U', 'P', 'D', 'F')){
printf("Wrong update file, don't update.\n");
} else {
if (header.checksum != sysinfo->app_checksum) {
printf("found different update file(0x%x-0x%x), update...\n",
header.checksum, sysinfo->app_checksum);
sysinfo->update_media_type = UPDATE_MEDIA_SD;
sysinfo->update_status = UPDATE_STATUS_START;
SaveSysInfo();
wdt_cpu_reboot();
} else {
printf("the update file version is same, don't update.\n");
}
}
};
ff_fclose(fp);
} else {
printf("open update.bin fail.\n");
}
#endif
} else if (status == MMCSD_HOST_UNPLUGED) {
printf("card removed.\n");
}
}
}
static void sdcard_read_demo(void)
{
if (xTaskCreate(sdcard_read_thread, "sdread", configMINIMAL_STACK_SIZE, NULL,
1, NULL) != pdPASS) {
printf("create sdread task fail.\n");
}
}
#endif
#endif
#ifdef USB_SUPPORT
static void usb_read_thread(void *para)
{
unsigned int status;
for (;;) {
status = usb_wait_stor_dev_pluged(portMAX_DELAY);
if (status == USB_DEV_PLUGED) {
printf("usb dev inserted.\n");
#ifdef OTA_UPDATE_SUPPORT
FF_FILE *fp = ff_fopen("/usb/update.bin", "rb");
if (fp) {
ff_fclose(fp);
update_from_media("/usb", UPFILE_TYPE_WHOLE);
}
#if DEVICE_TYPE_SELECT == EMMC_FLASH
fp = ff_fopen("/usb/emmcldr.bin", "rb");
#else
fp = ff_fopen("/usb/spildr.bin", "rb");
#endif
if (fp) {
ff_fclose(fp);
update_from_media("/usb", UPFILE_TYPE_FIRSTLDR);
}
fp = ff_fopen("/usb/stepldr.bin", "rb");
if (fp) {
ff_fclose(fp);
update_from_media("/usb", UPFILE_TYPE_STEPLDR);
}
fp = ff_fopen("/usb/lnchemmc.bin", "rb");
if (fp) {
ff_fclose(fp);
update_from_media("/usb", UPFILE_TYPE_LNCHEMMC);
}
#else
FF_FILE *fp = ff_fopen("/usb/update.bin", "rb");
if (fp) {
UpFileHeader header;
SysInfo *sysinfo = GetSysInfo();
if (ff_fread(&header, 1, sizeof(header), fp) == sizeof(header)) {
if (header.magic != MKTAG('U', 'P', 'D', 'F')) {
printf("Wrong update file, don't update.\n");
} else {
if (header.checksum != sysinfo->app_checksum) {
printf("found different update file(0x%x-0x%x), update...\n",
header.checksum, sysinfo->app_checksum);
sysinfo->update_media_type = UPDATE_MEDIA_USB;
sysinfo->update_status = UPDATE_STATUS_START;
SaveSysInfo();
hub_usb_dev_reset();
vTaskDelay(500);
wdt_cpu_reboot();
} else {
printf("the update file version is same, don't update.\n");
}
}
};
ff_fclose(fp);
} else {
printf("open update.bin fail.\n");
}
#endif
} else if (status == USB_DEV_UNPLUGED) {
printf("usb removed.\n");
}
}
}
static void usb_read_demo(void)
{
if (xTaskCreate(usb_read_thread, "usbread", configMINIMAL_STACK_SIZE * 16, NULL,
1, NULL) != pdPASS) {
printf("create usbread task fail.\n");
}
}
#endif
#ifdef WIFI_SUPPORT
#if WIFI_TEST
//#define RELTECK_WIFI_AP_MODE
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_DHCP.h"
#include "carlink_ey.h"
#include "carlink_ey_video.h"
#include "iperf_task.h"
#include "iot_wifi.h"
#include "FreeRTOS_DHCP_Server.h"
#ifdef RELTECK_WIFI_AP_MODE
static const uint8_t ucIPAddress[4] = {192, 168, 13, 1};
#else
static const uint8_t ucIPAddress[4] = {192, 168, 13, 37};
#endif
static const uint8_t ucNetMask[4] = {255, 255, 255, 0};
//static const uint8_t ucGatewayAddress[4] = {192, 168, 13, 1};
static const uint8_t ucGatewayAddress[4] = {192, 168, 13, 1};
static const uint8_t ucDNSServerAddress[4] = {8, 8, 8, 8};
//static const uint8_t ucMACAddress[6] = {0x00, 0x0c, 0x29, 0x5d, 0x2e, 0x03};
//static const uint8_t ucMACAddress[6] = {0x68, 0xb9, 0xd3, 0xc1, 0x28, 0x03};
static const uint8_t ucMACAddress[6] = {0x30, 0x4a, 0x26, 0x78, 0xfd, 0x12};
uint8_t wifi_data_buffer[65536] = {0};
void ark_test_h264_dec();
struct test_header
{
uint16_t id;
uint16_t payload_len;
};
#if 0
static int vCreateTCPServerSocket( void )
{
SocketSet_t xFD_Set;
struct freertos_sockaddr xAddress, xRemoteAddr;
Socket_t xSockets = FREERTOS_INVALID_SOCKET, xClientSocket = FREERTOS_INVALID_SOCKET;
socklen_t xClientLength = sizeof( xAddress );
static const TickType_t xNoTimeOut = portMAX_DELAY;
BaseType_t ret = -1;
BaseType_t xResult;
struct test_header header;
uint8_t header_buf[4];
uint8_t* header_buf_ptr;
const int header_len = sizeof(struct test_header);
int header_buf_len = 0;
uint8_t *h264SrcBuf = NULL;
uint8_t *h264SrcBufPtr = NULL;
int32_t h264SrcSize = 0, h264SrcSizePos = 0;
uint8_t err_flag = 0;int i;
video_frame_s* frame = NULL;
xFD_Set = FreeRTOS_CreateSocketSet();
xSockets = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( xSockets != FREERTOS_INVALID_SOCKET );
FreeRTOS_setsockopt( xSockets,
0,
FREERTOS_SO_RCVTIMEO,
&xNoTimeOut,
sizeof( xNoTimeOut ) );
xAddress.sin_port = ( uint16_t ) 11111;
xAddress.sin_port = FreeRTOS_htons( xAddress.sin_port );
FreeRTOS_bind( xSockets, &xAddress, sizeof( xAddress ) );
FreeRTOS_listen( xSockets, 1 );
//ark_test_h264_dec();
carlink_ey_video_init();
while (1) {
FreeRTOS_FD_CLR(xSockets, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET(xSockets, xFD_Set, eSELECT_READ);
if (xClientSocket && xClientSocket != FREERTOS_INVALID_SOCKET) {
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET( xClientSocket, xFD_Set, eSELECT_READ );
}
xResult = FreeRTOS_select( xFD_Set, portMAX_DELAY );
if (xResult < 0) {
break;
}
if( FreeRTOS_FD_ISSET ( xSockets, xFD_Set ) ) {
xClientSocket = FreeRTOS_accept( xSockets, &xRemoteAddr, &xClientLength);
if( ( xClientSocket != NULL ) && ( xClientSocket != FREERTOS_INVALID_SOCKET ) ) {
uint8_t pucBuffer[32] = {0};
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_GetRemoteAddress( xClientSocket, ( struct freertos_sockaddr * ) &xRemoteAddr );
FreeRTOS_inet_ntoa(xRemoteAddr.sin_addr, pucBuffer );
printf("Carlink: Received a connection from %s:%u\n", pucBuffer, FreeRTOS_ntohs(xRemoteAddr.sin_port));
}
continue;
} else if( FreeRTOS_FD_ISSET ( xClientSocket, xFD_Set ) ) {
header_buf_ptr = header_buf;
header_buf_len = header_len;
err_flag = 0;
while (header_buf_len > 0) {
err_flag = 0;
ret = FreeRTOS_recv(xClientSocket, (void*)header_buf_ptr, header_buf_len, 0);
if (ret < 0) {
err_flag = 1;
printf("FreeRTOS_recv header err:%d\r\n", ret);
break;
}
header_buf_ptr += ret;
header_buf_len -= ret;
}
if (err_flag) {
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_closesocket(xClientSocket);
xClientSocket = FREERTOS_INVALID_SOCKET;
video_frame_s* dummy = NULL;
notify_h264_frame_ready(&dummy);
continue;
}
/*printf("##header:");
for (i = 0; i < header_len; i++) {
printf("%02x ", header_buf[i]);
}printf("\r\n");*/
//READ_LE16(header_buf, header.id);
//READ_LE16(header_buf + 2, header.payload_len);
header.id = (header_buf[0] | (header_buf[1] << 8));
header.payload_len = (header_buf[2] | (header_buf[3] << 8));
printf("recv id:%d len:%d\r\n", header.id, header.payload_len);
int retry_cnt = 0;
h264SrcSize = header.payload_len;
get_retry:
frame = get_h264_frame_buf();
if (NULL == frame) {
printf("h264 frame is empty\r\n");
vTaskDelay(pdMS_TO_TICKS(10));
goto get_retry;
//continue;
}
h264SrcSizePos = h264SrcSize;
h264SrcBufPtr = frame->cur;
h264SrcBuf = frame->cur;
frame->len = h264SrcSize;
err_flag = 0;
while (h264SrcSizePos > 0) {
//printf("h264SrcSizePos:%d\r\n", h264SrcSizePos);
ret = FreeRTOS_recv( xClientSocket, (void *)h264SrcBufPtr, h264SrcSizePos, 0);
//printf("lBytes:%d h264SrcSizePos:%d\r\n", lBytes, h264SrcSizePos);
if (ret < 0) {
printf("FreeRTOS_recv err:%d\r\n", ret);
err_flag = 1;
break;
}
h264SrcBufPtr += ret;
h264SrcSizePos -= ret;
}/*printf("read finished\r\n");
printf("payload:");
for (i = 0; i < 16; i++) {
printf("%02x ", h264SrcBuf[i]);
}printf("\r\n");*/
if (err_flag) {
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_closesocket(xClientSocket);
xClientSocket = FREERTOS_INVALID_SOCKET;
video_frame_s* dummy = NULL;
notify_h264_frame_ready(&dummy);
continue;
}
notify_h264_frame_ready(&frame);
}
}
FreeRTOS_closesocket(xClientSocket);
FreeRTOS_closesocket(xSockets);
}
#else
static int vCreateTCPServerSocket( void )
{
SocketSet_t xFD_Set;
struct freertos_sockaddr xAddress, xRemoteAddr;
Socket_t xSockets = FREERTOS_INVALID_SOCKET, xClientSocket = FREERTOS_INVALID_SOCKET;
socklen_t xClientLength = sizeof( xAddress );
static const TickType_t xNoTimeOut = portMAX_DELAY;
BaseType_t ret = -1;
BaseType_t xResult;
xFD_Set = FreeRTOS_CreateSocketSet();
xSockets = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( xSockets != FREERTOS_INVALID_SOCKET );
FreeRTOS_setsockopt( xSockets,
0,
FREERTOS_SO_RCVTIMEO,
&xNoTimeOut,
sizeof( xNoTimeOut ) );
xAddress.sin_port = ( uint16_t ) 11111;
xAddress.sin_port = FreeRTOS_htons( xAddress.sin_port );
FreeRTOS_bind( xSockets, &xAddress, sizeof( xAddress ) );
FreeRTOS_listen( xSockets, 1 );
//ark_test_h264_dec();
carlink_ey_video_init();
while (1) {
FreeRTOS_FD_CLR(xSockets, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET(xSockets, xFD_Set, eSELECT_READ);
if (xClientSocket && xClientSocket != FREERTOS_INVALID_SOCKET) {
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET( xClientSocket, xFD_Set, eSELECT_READ );
}
xResult = FreeRTOS_select( xFD_Set, portMAX_DELAY );
if (xResult < 0) {
break;
}
if( FreeRTOS_FD_ISSET ( xSockets, xFD_Set ) ) {
xClientSocket = FreeRTOS_accept( xSockets, &xRemoteAddr, &xClientLength);
if( ( xClientSocket != NULL ) && ( xClientSocket != FREERTOS_INVALID_SOCKET ) ) {
char pucBuffer[32] = {0};
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_FD_SET(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_GetRemoteAddress( xClientSocket, ( struct freertos_sockaddr * ) &xRemoteAddr );
FreeRTOS_inet_ntoa(xRemoteAddr.sin_addr, pucBuffer );
printf("Carlink: Received a connection from %s:%u\n", pucBuffer, FreeRTOS_ntohs(xRemoteAddr.sin_port));
}
continue;
} else if( FreeRTOS_FD_ISSET ( xClientSocket, xFD_Set ) ) {
ret = FreeRTOS_recv(xClientSocket, wifi_data_buffer, sizeof wifi_data_buffer, 0);
if (ret > 0) {
printf("recv buf size:%d\r\n", ret);
} else {
printf("FreeRTOS_recv err:%d\r\n", ret);
FreeRTOS_FD_CLR(xClientSocket, xFD_Set, eSELECT_READ);
FreeRTOS_closesocket(xClientSocket);
xClientSocket = FREERTOS_INVALID_SOCKET;
continue;
}
}
}
FreeRTOS_closesocket(xClientSocket);
FreeRTOS_closesocket(xSockets);
return 0;
}
#endif
#if ( ipconfigUSE_DHCP_HOOK != 0 )
eDHCPCallbackAnswer_t xApplicationDHCPHook2( eDHCPCallbackPhase_t eDHCPPhase,
uint32_t ulIPAddress )
{
eDHCPCallbackAnswer_t eReturn;
//uint32_t ulStaticIPAddress, ulStaticNetMask;
char ip_str[20] = {0};
sprintf(ip_str, "%d.%d.%d.%d\r\n", (ulIPAddress >> 0) & 0xFF,
(ulIPAddress >> 8) & 0xFF, (ulIPAddress >> 16) & 0xFF, (ulIPAddress >> 24) & 0xFF);
printf("\r\n eDHCPPhase:%d ulIPAddress:%s state:%d \r\n", eDHCPPhase, ip_str, getDhcpClientState());
if (getDhcpClientState() == 0)
return eDHCPStopNoChanges;
switch( eDHCPPhase )
{
case eDHCPPhasePreDiscover :
eReturn = eDHCPContinue;
break;
case eDHCPPhasePreRequest :
#if 0
ulStaticIPAddress = FreeRTOS_inet_addr_quick( ucIPAddress[0],
ucIPAddress[1],
ucIPAddress[2],
ucIPAddress[3] );
ulStaticNetMask = FreeRTOS_inet_addr_quick( ucNetMask[0],
ucNetMask[1],
ucNetMask[2],
ucNetMask[3] );
ulStaticIPAddress &= ulStaticNetMask;
ulIPAddress &= ulStaticNetMask;
if( ulStaticIPAddress == ulIPAddress ) {
eReturn = eDHCPUseDefaults;
} else {
eReturn = eDHCPContinue;
}
#else
eReturn = eDHCPContinue;
#endif
break;
default :
eReturn = eDHCPContinue;
break;
}
return eReturn;
}
#endif
void wifi_test_event_handler( WIFIEvent_t * xEvent )
{
WIFIEventType_t xEventType = xEvent->xEventType;
if (0) {
} else if (eWiFiEventConnected == xEventType) {// meter is sta
printf("\r\n The meter is connected to ap \r\n");
} else if (eWiFiEventDisconnected == xEventType) {// meter is sta
printf("\r\n The meter is disconnected from ap \r\n");
} else if (eWiFiEventAPStationConnected == xEventType) {// meter is ap
printf("\r\n The meter in AP is connected by a sta \r\n");
} else if (eWiFiEventAPStationDisconnected == xEventType) {// meter is ap
printf("\r\n The sta is disconnected from the meter \r\n");
}
}
int wifi_sta_test_proc();
int wifi_ap_test_proc();
static void wifi_demo_test(void)
{
BaseType_t ret = 0;
unsigned int status;
uint32_t IPAddress = (32 << 24) | (13 << 16) | (168 << 8) | (192 << 0);
for (;;) {
status = mmcsd_wait_sdio_ready((int32_t)portMAX_DELAY);
if (status == MMCSD_HOST_PLUGED) {
printf("detect sdio device\r\n");
break;
}
}
#ifndef RELTECK_WIFI_AP_MODE
setDhcpClientState(1);
#endif
ret = ret;
//vTaskDelay(pdMS_TO_TICKS(5000));//wait connect
ret = FreeRTOS_IPInit(ucIPAddress, ucNetMask, ucGatewayAddress,ucDNSServerAddress, ucMACAddress);
//ark_wlan_init();
#ifdef RELTECK_WIFI_AP_MODE
wifi_ap_test_proc();
#else
WIFI_RegisterEvent(eWiFiEventMax, wifi_test_event_handler);
wifi_sta_test_proc();
#endif
//vTaskDelay(pdMS_TO_TICKS(8000));
while(0) {
//printf("send ping\r\n");
FreeRTOS_SendPingRequest(IPAddress, 8, 1000);
vTaskDelay(pdMS_TO_TICKS(1000));
}
vTaskDelay(pdMS_TO_TICKS(1000));
#ifdef RELTECK_WIFI_AP_MODE
setDhcpClientState(0);
IPAddress = (20 << 24) | (13 << 16) | (168 << 8) | (192 << 0);
dhcpserver_start(ucIPAddress, IPAddress, 10);
#else
setDhcpClientState(1);
#endif
//vCreateTCPServerSocket();
vIPerfInstall();
}
#endif
#endif
#ifdef AUDIO_REPLAY
#include "audio.h"
#define BUFSZ 4096
struct RIFF_HEADER_DEF
{
char riff_id[4]; // 'R','I','F','F'
uint32_t riff_size;
char riff_format[4]; // 'W','A','V','E'
};
struct WAVE_FORMAT_DEF
{
uint16_t FormatTag;
uint16_t Channels;
uint32_t SamplesPerSec;
uint32_t AvgBytesPerSec;
uint16_t BlockAlign;
uint16_t BitsPerSample;
};
struct FMT_BLOCK_DEF
{
char fmt_id[4]; // 'f','m','t',' '
uint32_t fmt_size;
struct WAVE_FORMAT_DEF wav_format;
};
struct DATA_BLOCK_DEF
{
char data_id[4]; // 'R','I','F','F'
uint32_t data_size;
};
struct wav_info
{
struct RIFF_HEADER_DEF header;
struct FMT_BLOCK_DEF fmt_block;
struct DATA_BLOCK_DEF data_block;
};
#if 0
static void pcmplay_thread(void *param)
{
#define PCM_BUF_SIZE 0x100000
u32 *pcmBuf = pvPortMalloc(PCM_BUF_SIZE);
if (pcmBuf) {
struct audio_caps caps = {0};
struct audio_device *audio;
/* 打开 Audio 播放设备 */
audio = audio_dev_open(AUDIO_FLAG_REPLAY);
if (!audio) {
printf("Open audio device fail.\n");
return;
}
/* 设置采样率、通道、采样位数等音频参数信息 */
caps.main_type = AUDIO_TYPE_OUTPUT; /* 输出类型(播放设备 */
caps.sub_type = AUDIO_DSP_PARAM; /* 设置所有音频参数信息 */
caps.udata.config.samplerate = 44100; /* 采样率 */
caps.udata.config.channels = 2; /* 采样通道 */
caps.udata.config.samplebits = 16; /* 采样位数 */
audio_dev_configure(audio, &caps);
/* Load external pcm file to waveBuf */
printf("### pcmBuf:0x%x\n", (u32)pcmBuf);
//get pcm file from SD card or use jlink to download pcm file to pcmBuf.
//...
CP15_clean_dcache_for_dma((uint32_t)pcmBuf, (uint32_t)pcmBuf + PCM_BUF_SIZE);
/* play */
while(1) {
int i;
char *buf = (char *)pcmBuf;
for(i=0; i<PCM_BUF_SIZE/BUFSZ; i++) {
audio_dev_write(audio, buf, BUFSZ);
buf += BUFSZ;
}
}
/* 关闭 Audio 设备 */
audio_dev_close(audio);
vPortFree(pcmBuf);
}
}
#endif
#define ROMFILE_ADUIO
/* Parse wav file header info */
static int wavplay_parse_header(void *file, struct wav_info *info)
{
int max_sub_chunk = 8;
#ifdef ROMFILE_ADUIO
if (RomFileRead((RomFile *)file, &(info->header), sizeof(struct RIFF_HEADER_DEF)) <= 0)
goto __exit;
/* seek to fmt sub-chunk(Drop other sub-chunk in front of fmt chunk) */
while(1)
{
if (RomFileRead((RomFile *)file, &(info->fmt_block), sizeof(struct FMT_BLOCK_DEF)) <= 0)
goto __exit;
if(memcmp(info->fmt_block.fmt_id, "fmt ", 4) == 0)
break; /* "fmt " sub-chunk fond */
/* sub-chunk "fmt " not fond, seek to the next sub-chunk */
RomFileSeek((RomFile *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), SEEK_CUR);
/* timeout */
if(max_sub_chunk-- <= 0)
goto __exit;
};
if (info->fmt_block.fmt_size > sizeof(struct WAVE_FORMAT_DEF))
RomFileSeek((RomFile *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), SEEK_CUR);
if (RomFileRead((RomFile *)file, &(info->data_block), sizeof(struct DATA_BLOCK_DEF)) <= 0)
goto __exit;
#else
if (ff_fread(&(info->header), sizeof(struct RIFF_HEADER_DEF), 1, (FF_FILE *)file) <= 0)
goto __exit;
/* seek to fmt sub-chunk(Drop other sub-chunk in front of fmt chunk) */
while(1)
{
if (ff_fread(&(info->fmt_block), sizeof(struct FMT_BLOCK_DEF), 1, (FF_FILE *)file) <= 0)
goto __exit;
if(memcmp(info->fmt_block.fmt_id, "fmt ", 4) == 0)
break; // "fmt " sub-chunk fond.
/* sub-chunk "fmt " not fond, seek to the next sub-chunk */
ff_fseek((FF_FILE *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), FF_SEEK_CUR);
/* timeout */
if(max_sub_chunk-- <= 0)
goto __exit;
};
if (info->fmt_block.fmt_size > sizeof(struct WAVE_FORMAT_DEF))
ff_fseek((FF_FILE *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), FF_SEEK_CUR);
if (ff_fread(&(info->data_block), sizeof(struct DATA_BLOCK_DEF), 1, (FF_FILE *)file) <= 0)
goto __exit;
#endif
return 0;
__exit:
printf("%s fail.\n", __func__);
return -1;
}
static void wavplay_thread(void *param)
{
#ifdef ROMFILE_ADUIO
RomFile *file = NULL;
#else
FF_FILE *file = NULL;
#endif
uint8_t *buffer = NULL;
struct wav_info *info = NULL;
struct audio_caps caps = {0};
struct audio_device *audio;
int data_size;
#ifdef ROMFILE_ADUIO
file = RomFileOpen("audio/sin1K.wav");
#else
file = ff_fopen("/sd/audio/sin1K", "rb");
#endif
if (!file)
{
printf("open file failed!\n");
goto __exit;
}
buffer = pvPortMalloc(BUFSZ);
if (buffer == NULL)
goto __exit;
info = (struct wav_info *) pvPortMalloc(sizeof(*info));
if (info == NULL)
goto __exit;
/* 解析文件头信息 */
if(wavplay_parse_header((void *)file, info) < 0)
goto __exit;
printf("wav information:\n");
printf("samplerate %d\n", info->fmt_block.wav_format.SamplesPerSec);
printf("channel %d\n", info->fmt_block.wav_format.Channels);
/* 打开 Audio 播放设备 */
audio = audio_dev_open(AUDIO_FLAG_REPLAY);
if (!audio)
{
printf("Open audio device fail.\n");
goto __exit;
}
/* 设置采样率、通道、采样位数等音频参数信息 */
caps.main_type = AUDIO_TYPE_OUTPUT; /* 输出类型(播放设备 */
caps.sub_type = AUDIO_DSP_PARAM; /* 设置所有音频参数信息 */
caps.udata.config.samplerate = info->fmt_block.wav_format.SamplesPerSec; /* 采样率 */
caps.udata.config.channels = info->fmt_block.wav_format.Channels; /* 采样通道 */
caps.udata.config.samplebits = 16; /* 采样位数 */
audio_dev_configure(audio, &caps);
data_size = info->data_block.data_size;
while (data_size > 0)
{
int length;
/* 从文件系统读取 wav 文件的音频数据 */
#ifdef ROMFILE_ADUIO
length = RomFileRead(file, buffer, BUFSZ);
#else
length = ff_fread(buffer, 1, BUFSZ, file);
#endif
if(length > data_size)
length = data_size;
if (length <= 0)
break;
/* 向 Audio 设备写入音频数据 */
audio_dev_write(audio, buffer, length);
data_size -= length;
}
/* 关闭 Audio 设备 */
audio_dev_close(audio, AUDIO_FLAG_REPLAY);
__exit:
if (file)
#ifdef ROMFILE_ADUIO
RomFileClose(file);
#else
ff_fclose(file);
#endif
if (buffer)
vPortFree(buffer);
if (info)
vPortFree(info);
while(1)
vTaskDelay(portMAX_DELAY);
}
static void wavplay_demo(void)
{
if (xTaskCreate(wavplay_thread, "wavplay", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES - 3, NULL) != pdPASS) {
printf("create wavplay task fail.\n");
}
}
#endif
#ifdef AUDIO_RECORD
#include "audio.h"
#define RECORD_BUF_SIZE 1024*1024
#define RECORD_REQ_SIZE 1024
static uint8_t *wavrecord_buffer = NULL;
static uint8_t *waverecord_get_a_new_buffer(int size)
{
static int waverecord_index = 0;
uint8_t *buffer = NULL;
if(!wavrecord_buffer)
{
wavrecord_buffer = pvPortMalloc(RECORD_BUF_SIZE);
if(!wavrecord_buffer)
return NULL;
waverecord_index = 0;
}
if(waverecord_index + size < RECORD_BUF_SIZE)
{
buffer = wavrecord_buffer + waverecord_index;
waverecord_index += size;
}
else
{
printf("record done, start_addr:0x%x, size:0x%x\n", (u32)wavrecord_buffer, RECORD_BUF_SIZE);
//CP15_clean_dcache_for_dma((uint32_t)wavrecord_buffer, (uint32_t)wavrecord_buffer + RECORD_BUF_SIZE);
buffer = wavrecord_buffer;
waverecord_index = 0;
}
return buffer;
}
static int wavrecord_callback(struct audio_device *audio)
{
int ret = -1;
/* save record data */
if(audio && audio->record)
{
int size = audio->record->buf_info.total_size;
if(size == RECORD_REQ_SIZE)
{
uint8_t *buffer = waverecord_get_a_new_buffer(size);
if(buffer)
{
/* clear buffer */
//memset(buffer, 0, size);
#if 1 /* method 1: use dynamic buffer to receive record data(without copy data). [Recommend this method] */
audio_dev_record_set_param(audio, buffer, size); //Set a new buffer to receive the next frame.
#else /* method 2: use one buffer to receive record data(should copy data) */
if(audio->record->buf_info.buffer)
memcpy(buffer, audio->record->buf_info.buffer, size); //Copy the record data to a destnation buffer.
#endif
ret = 0;
}
}
else
{
printf("%s() Invalid size:%d\n", __func__, size);
}
}
return ret;
}
static void wavrecord_thread(void *param)
{
uint8_t *buffer = NULL;
struct audio_device *audio;
int ret;
audio = audio_dev_open(AUDIO_FLAG_RECORD);
if(audio)
{
/* set record sample information */
struct audio_caps caps = {0};
caps.main_type = AUDIO_TYPE_INPUT; /* 输入类型(录音设备 */
caps.sub_type = AUDIO_DSP_PARAM; /* 设置所有音频参数信息 */
caps.udata.config.samplerate = 16000; /* 采样率 */
caps.udata.config.channels = 2; /* 采样通道 */
caps.udata.config.samplebits = 16; /* 采样位数 */
audio_dev_configure(audio, &caps);
/* register record complete callback */
audio_dev_register_record_callback(audio, wavrecord_callback);
/* set record buffer and size */
buffer = waverecord_get_a_new_buffer(RECORD_REQ_SIZE);
ret = audio_dev_record_set_param(audio, buffer, RECORD_REQ_SIZE);
if(ret)
{
printf("%s() audio_dev_record_set_param failed \n", __func__);
goto exit;
}
/* start recording */
audio_dev_record_start(audio);
printf("wav record information:\n");
printf("samplerate %d\n", caps.udata.config.samplerate);
printf("channel %d\n", caps.udata.config.channels);
printf("samplebits %d\n", caps.udata.config.samplebits);
}
while(1)
vTaskDelay(portMAX_DELAY);
exit:
if(audio)
{
/* stop record */
audio_dev_record_stop(audio);
/* 关闭 Audio 设备 */
audio_dev_close(audio, AUDIO_FLAG_REPLAY);
}
if (wavrecord_buffer)
vPortFree(wavrecord_buffer);
}
static void wavrecord_demo(void)
{
if (xTaskCreate(wavrecord_thread, "wavrecord", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES - 3, NULL) != pdPASS) {
printf("create waverecord task fail.\n");
}
}
#endif
#ifdef I2C_EEPROM_MASTER_DEMO
#define I2C_EEPROM_24C02_ADDR 0x50
#define I2C_EEPROM_WR_SIZE 8
static void eeprom_thread(void *param)
{
struct i2c_adapter *adap = NULL;
struct i2c_msg msg[2];
unsigned char send_buf[I2C_EEPROM_WR_SIZE + 1];
unsigned char rev_buf[I2C_EEPROM_WR_SIZE];
int ret;
u8 retries = 0;
int i;
if (!(adap = i2c_open("i2c0"))) {
printf("open i2c0 fail.\n");
return;
}
while(1) {
/* write data */
send_buf[0] = 0; /* word addr */
printf("write data: ");
for (i = 0; i < I2C_EEPROM_WR_SIZE; i++) {
send_buf[1 + i] = rand() & 0xff;
printf("%02x, ", send_buf[1 + i]);
}
printf("\n");
msg[0].flags = !I2C_M_RD;
msg[0].addr = I2C_EEPROM_24C02_ADDR;
msg[0].len = I2C_EEPROM_WR_SIZE + 1;
msg[0].buf = send_buf;
while (retries++ < 3) {
ret = i2c_transfer(adap, msg, 1);
if (ret == 1)
break;
else
printf("i2c_transfer error %d.\n", ret);
}
memset(rev_buf, 0, sizeof(rev_buf));
/* read data */
msg[0].flags = !I2C_M_RD;
msg[0].addr = I2C_EEPROM_24C02_ADDR;
msg[0].len = 1;
msg[0].buf = send_buf;
msg[1].flags = I2C_M_RD;
msg[1].addr = I2C_EEPROM_24C02_ADDR;
msg[1].len = I2C_EEPROM_WR_SIZE;
msg[1].buf = rev_buf;
retries = 0;
while (retries++ < 3) {
ret = i2c_transfer(adap, msg, 2);
if (ret == 2)
break;
else
printf("i2c_transfer read error %d.\n", ret);
}
printf("read data: ");
for (i = 0; i < I2C_EEPROM_WR_SIZE; i++)
printf("%02x, ", rev_buf[i]);
printf("\n");
for (i = 0; i < I2C_EEPROM_WR_SIZE; i++) {
if (send_buf[1 + i] != rev_buf[i])
printf("i2c_transfer data[%d] err, 0x%02x, 0x%02x.\n", i, send_buf[1 + i], rev_buf[i]);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static void i2c_eeprom_demo(void)
{
if (xTaskCreate(eeprom_thread, "eeprom", configMINIMAL_STACK_SIZE, NULL,
configMAX_PRIORITIES - 4, NULL) != pdPASS) {
printf("create eeprom task fail.\n");
}
}
#endif
void lvgl_thread(void *data)
{
printf("lvgl thread start.\n");
#if DEVICE_TYPE_SELECT != EMMC_FLASH
/* initialize the spi flash */
sfud_init();
#ifdef SPI0_QSPI_MODE
sfud_qspi_fast_read_enable(sfud_get_device(0), 4);
#endif
#else
mmcsd_wait_mmc_ready(portMAX_DELAY);
#endif
#ifdef USE_ULOG
ulog_init();
#ifdef ULOG_BACKEND_USING_CONSOLE
ulog_console_backend_init();
#endif
#ifdef ULOG_EASYFLASH_BACKEND_ENABLE
easyflash_init();
ulog_ef_backend_init();
#endif
#ifdef ULOG_FILE_BACKEND_ENABLE
usb_wait_stor_dev_pluged(portMAX_DELAY);
ulog_file_backend_init();
#endif
TRACE_INFO("use ulog.\n");
//read_all_flash_log();
#endif
/* read sysinfo */
ReadSysInfo();
GetUpFileInfo();
/* initialize carback */
#ifdef CARBACK_DETECT
carback_init();
#endif
/* play animation */
#if ANIMATION_POLICY != ANIMATION_NONE
animation_init();
animation_start();
#endif
/* uart rx demo */
//uart_rx_demo();
#if BT_TEST
fsc_bt_main();//feiyitong bt module
#endif
/* can demo */
//can_demo();
/* read sd card demo */
#ifdef SDMMC_SUPPORT
#if SDMMC_TEST
sdcard_read_demo();
#endif
#endif
#ifdef USB_SUPPORT
extern int get_usb_mode();
extern int ark_network_init(void);
extern void ncm_update_demo();
extern void ncm_log_demo();
extern void wifi_update_demo(void);
if (get_usb_mode()) {
ark_network_init();
#ifdef NCM_UPDATE_SUPPORT
ncm_update_demo();
#endif
#ifdef NCM_LOG_SUPPORT
ncm_log_demo();
#endif
} else {
#ifdef WIFI_UPDATE_SUPPORT
wifi_update_demo();
#else
usb_read_demo();
#endif
}
#endif
#ifdef WIFI_SUPPORT
#if WIFI_TEST
wifi_demo_test();
#else
#if CARLINK_EY
set_carlink_display_info(0, 0, LCD_WIDTH, LCD_HEIGHT); //设置屏幕显示区域(起始坐标和分辨率)
set_carlink_video_info(LCD_WIDTH, LCD_HEIGHT, 30); //设置请求H264视频流参数
carlink_ey_init();
#endif
#if CARLINK_EC
set_carlink_display_info(0, 0, LCD_WIDTH, LCD_HEIGHT);
set_carlink_video_info(LCD_WIDTH, LCD_HEIGHT, 30);
carlink_ec_init(0, NULL);
#else
ark_network_init();
#endif
#endif
#endif
/* read romfile */
ReadRomFile();
#ifdef AUDIO_REPLAY
wavplay_demo();
#endif
#ifdef AUDIO_RECORD
wavrecord_demo();
#endif
#if defined(I2C_EEPROM_SLAVE_DEMO) && (defined(I2C0_SLAVE_MODE) || defined(I2C1_SLAVE_MODE))
extern int i2c_slave_eeprom_init(void);
i2c_slave_eeprom_init();
#endif
#ifdef I2C_EEPROM_MASTER_DEMO
i2c_eeprom_demo();
#endif
#ifdef TP_SUPPORT
extern int tp_init(void);
tp_init();
#endif
/*Initialize LittlevGL*/
lv_init();
/*Initialize the HAL for LittlevGL*/
hal_init();
#if defined(VG_DRIVER) && !defined(LVGL_VG_GPU)
xm_vg_init((unsigned int)vgHeap, VG_HEAP_SIZE);
#endif
lv_png_init();
//lv_cpr_init();
/*Check the themes too*/
//lv_disp_set_default(lv_windows_disp);
/*Run the v7 demo*/
//lv_demo_widgets();
#if LV_USE_DEMO_PRINTER
lv_demo_printer();
#else
#ifdef VG_DRIVER
#if defined(REVERSE_TRACK) || defined(LVGL_VG_GPU)
haoke_demo();
#else
xinbas_demo();
#endif
#else
haoke_demo();
#endif
#endif
while(1) {
#ifdef TASK_STATUS_MONITOR
static uint32_t idletick = 0;
uint8_t CPU_RunInfo[1024];
if (xTaskGetTickCount() - idletick > configTICK_RATE_HZ * 10) {
memset(CPU_RunInfo,0,1024);
vTaskList((char *)&CPU_RunInfo); //获取任务运行时间信息
printf("---------------------------------------------\r\n");
printf("Task State Priority Stack #\r\n");
printf("%s", CPU_RunInfo);
printf("---------------------------------------------\r\n");
memset(CPU_RunInfo,0,1024);
vTaskGetRunTimeStats((char *)&CPU_RunInfo);
printf("Task Abs Time % Time\r\n");
printf("%s", CPU_RunInfo);
printf("---------------------------------------------\r\n\n");
idletick = xTaskGetTickCount();
}
#endif
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
vTaskDelay(pdMS_TO_TICKS(1)); /*Just to let the system breath*/
}
}
#if LV_USE_DEMO_PRINTER
#if !(defined(ADC_TOUCH) || defined(TP_SUPPORT))
static inline void input_click(int x, int y)
{
lv_indev_data_t indata;
indata.point.x = x;
indata.point.y = y;
indata.state = LV_INDEV_STATE_PR;
xQueueSend(touch_input_mq, &indata, 0);
vTaskDelay(pdMS_TO_TICKS(10));
xQueueSend(touch_input_mq, &indata, 0);
vTaskDelay(pdMS_TO_TICKS(100));
indata.state = LV_INDEV_STATE_REL;
xQueueSend(touch_input_mq, &indata, 0);
}
void lvgl_input_thread(void *data)
{
lv_indev_data_t indata;
int i;
loop:
/* click copy icon */
vTaskDelay(pdMS_TO_TICKS(1000));
input_click(250 * LCD_WIDTH / 1024, 250 * LCD_HEIGHT / 600);
/* move brightness slider */
vTaskDelay(pdMS_TO_TICKS(3000));
indata.point.x = 648;
indata.point.y = 240;
indata.state = LV_INDEV_STATE_PR;
xQueueSend(touch_input_mq, &indata, 0);
vTaskDelay(pdMS_TO_TICKS(10));
xQueueSend(touch_input_mq, &indata, 0);
for (i = 1; i <= 16; i++) {
indata.point.y = 240 - i * 2;
xQueueSend(touch_input_mq, &indata, 0);
}
indata.state = LV_INDEV_STATE_REL;
xQueueSend(touch_input_mq, &indata, 0);
/* move hue slider */
indata.point.x = 720;
indata.point.y = 240;
indata.state = LV_INDEV_STATE_PR;
xQueueSend(touch_input_mq, &indata, 0);
vTaskDelay(pdMS_TO_TICKS(10));
xQueueSend(touch_input_mq, &indata, 0);
for (i = 1; i <= 16; i++) {
indata.point.y = 240 + i * 2;
xQueueSend(touch_input_mq, &indata, 0);
}
indata.state = LV_INDEV_STATE_REL;
xQueueSend(touch_input_mq, &indata, 0);
/* click next icon */
vTaskDelay(pdMS_TO_TICKS(4000));
input_click(680, 408);
/* click copies up button */
vTaskDelay(pdMS_TO_TICKS(1000));
indata.point.x = 940 * LCD_WIDTH / 1024;
indata.point.y = 200 * LCD_HEIGHT / 600;
for (i = 0; i < 8; i++) {
indata.state = LV_INDEV_STATE_PR;
xQueueSend(touch_input_mq, &indata, 0);
vTaskDelay(pdMS_TO_TICKS(100));
indata.state = LV_INDEV_STATE_REL;
xQueueSend(touch_input_mq, &indata, 0);
vTaskDelay(pdMS_TO_TICKS(100));
}
/* press color switch */
vTaskDelay(pdMS_TO_TICKS(1000));
input_click(870 * LCD_WIDTH / 1024 - 100, 360 * LCD_HEIGHT / 600);
/* press vertical switch */
vTaskDelay(pdMS_TO_TICKS(1000));
input_click(1176 * LCD_WIDTH / 1024 - 200, 360 * LCD_HEIGHT / 600);
/* click dpi dropdown */
vTaskDelay(pdMS_TO_TICKS(1000));
input_click(400 * LCD_WIDTH / 1024, 520 * LCD_HEIGHT / 600);
vTaskDelay(pdMS_TO_TICKS(1000));
input_click(318 * LCD_WIDTH / 1024, 420 * LCD_HEIGHT / 600);
/* click print icon */
vTaskDelay(pdMS_TO_TICKS(1000));
input_click(848 * LCD_WIDTH / 1024, 500 * LCD_HEIGHT / 600);
/* click continue icon */
vTaskDelay(pdMS_TO_TICKS(3500));
input_click(512 * LCD_WIDTH / 1024, 268 * LCD_HEIGHT / 600 + 200);
vTaskDelay(pdMS_TO_TICKS(1000));
goto loop;
}
#endif
#endif
#ifdef LVGL_VG_GPU
static void vg_init_thread(void *para)
{
xm_vg_init((unsigned int)vgHeap, VG_HEAP_SIZE);
for (;;)
vTaskDelay(portMAX_DELAY);
}
#endif
void vRegisterSampleCLICommands( void );
void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority );
void main_lvgl(void)
{
/* Start the task that manages the command console for FreeRTOS+CLI. */
vUARTCommandConsoleStart( ( configMINIMAL_STACK_SIZE * 3 ), tskIDLE_PRIORITY );
/* Register the standard CLI commands. */
vRegisterSampleCLICommands();
/* Create a task to test driver */
#ifndef LVGL_VG_GPU
xTaskCreate(lvgl_thread, "lvgl", 2048, NULL,
tskIDLE_PRIORITY + 1, NULL);
#else
xTaskCreate(vg_init_thread, "vginit", 2048, NULL,
tskIDLE_PRIORITY + 1, NULL);
#endif
touch_input_mq = xQueueCreate(INPUT_QUEUE_LEN, sizeof(lv_indev_data_t));
if (touch_input_mq == NULL) {
printf("create touch input message queue fail.\n");
return;
}
keypad_input_mq = xQueueCreate(INPUT_QUEUE_LEN, sizeof(lv_indev_data_t));
if (keypad_input_mq == NULL) {
printf("create keypad input message queue fail.\n");
return;
}
#if LV_USE_DEMO_PRINTER
#if !(defined(ADC_TOUCH) || defined(TP_SUPPORT))
xTaskCreate(lvgl_input_thread, "lvglinput", 1024, NULL, 8, NULL);
#endif
#endif
return;
}
/**********************
* STATIC FUNCTIONS
**********************/
static bool touch_input_read(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
xQueueReceive(touch_input_mq, data, 0);
if (uxQueueSpacesAvailable(touch_input_mq) < INPUT_QUEUE_LEN)
return true;
else
return false;
}
static bool keypad_input_read(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
if (xQueueReceive(keypad_input_mq, data, 0) == pdPASS) {
printf("keypad_input_read %d %s.\n", data->key, data->state ? "press" : "release");
}
if (uxQueueSpacesAvailable(keypad_input_mq) < INPUT_QUEUE_LEN)
return true;
else
return false;
}
/**
* Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
*/
static void hal_init(void)
{
/* Add a display
* Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/
arklcd_init();
#if !ARKLCD_DOUBLE_BUFFERED
static lv_disp_buf_t disp_buf;
/*static lv_color_t buf1[LV_HOR_RES_MAX * LV_VER_RES_MAX / 10];
lv_disp_buf_init(&disp_buf, buf1, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX / 10);*/
static lv_color_t buf1[LV_HOR_RES_MAX * LV_VER_RES_MAX / 10];
static lv_color_t buf2[LV_HOR_RES_MAX * LV_VER_RES_MAX / 10];
lv_disp_buf_init(&disp_buf, buf1, buf2, LV_HOR_RES_MAX * LV_VER_RES_MAX / 10);
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.buffer = &disp_buf;
disp_drv.flush_cb = arklcd_flush;
lv_disp_drv_register(&disp_drv);
#endif
/* Add the virtual input device */
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv); /*Basic initialization*/
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = touch_input_read; /*This function will be called periodically (by the library) to get the mouse position and state*/
/*Set cursor. For simplicity set a HOME symbol now.*/
/* LV_IMG_DECLARE(mouse_cursor_icon);
lv_indev_t * indev_mouse;
indev_mouse = lv_indev_drv_register(&indev_drv);
lv_obj_t * mouse_cursor = lv_img_create(lv_disp_get_scr_act(NULL), NULL);
lv_img_set_src(mouse_cursor, &mouse_cursor_icon);
lv_indev_set_cursor(indev_mouse, mouse_cursor); */
lv_indev_drv_register(&indev_drv);
/* Add the key input device */
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = keypad_input_read;
lv_indev_drv_register(&indev_drv);
#if !LV_TICK_CUSTOM
{
rt_thread_t tid;
/* Tick init.
* You have to call 'lv_tick_handler()' in every milliseconds
* Create an thread to do this*/
tid = rt_thread_create("lvgltick", tick_thread, RT_NULL, 1024,
RT_THREAD_PRIORITY_MAX/2, 10);
if (tid != RT_NULL) rt_thread_startup(tid);
}
#endif
}
#if !LV_TICK_CUSTOM
/**
* A task to measure the elapsed time for LittlevGL
* @param data unused
* @return never return
*/
static void tick_thread(void *data)
{
while(1) {
lv_tick_inc(1);
vTaskDelay(pdMS_TO_TICKS(1)); /*Sleep for 1 millisecond*/
}
}
#endif
#endif