【OKT507】迪文屏事件

前言

本章介绍如何实现迪文屏与飞凌OKT507的uart事件通信。

代码

从上到下是uart_example.c、dwin.c、dwin.h、makefile

#include "dwin.h"

#include     <stdio.h>      
#include     <stdlib.h>     
#include     <unistd.h>     
#include     <sys/types.h>  
#include     <sys/stat.h>   
#include     <fcntl.h>      
#include     <termios.h>    
#include     <errno.h>      
#include	 <sys/time.h>
#include     <string.h>
#include     <getopt.h>
#include    "stdbool.h"

// #include "dwin.h"
// #include "//delay.h"
#define uint8_t u_int8_t
#define bool _Bool


extern void u8_to_char(uint8_t * , char ** );
extern int judge_dwin_cmd(uint8_t ** );
extern int get_len(uint8_t *cmd_u8);
extern dwin_event_flag uart_judge_dwin_event(i_dwin_cmd * cmd);
extern i_dwin_cmd temp_cmd_recv;
extern dwin_event_key event_key_list[EVENT_KEY_NUM_MAX];
extern dwin_event_key_spec event_key_spec[EVENT_KEY_SPEC_NUM_MAX];

// extern char* u8_to_char(uint8_t * );

extern c_dwin_cmd cmd_recv_char; // from dwin
extern c_dwin_cmd cmd_send_char; // send to dwin
extern dwin_event_flag c_judge_dwin_event(c_dwin_cmd * cmd);
extern void c_dwin_cmd_analysis(char * in,c_dwin_cmd *cmd);
extern void c_print_cmd(c_dwin_cmd *cmd);
// extern void print_uint8(uint8_t * in);
// #define false FALSE
// #define true TRUE

/* E53模块中
 * UART0_RX_M0 -> GPIO0_B6
 * UART0_TX_M0 -> GPIO0_B7
 */
#define UART_ID                 0

#define UART_RECV_LEN           1024
#define BUF_RX_MAX 512
#define LEN_CHAR_TEMP 17

c_dwin_cmd cmd_char;


int search_str_end(uint8_t *str_z, int count)
{
    int temp_zero = 1;
    int temp_count = count -1;  // 有效字符11个,12个是0x00
    printf("init count = %d, temp_count = %d\n",count,temp_count);
    uint8_t *str_temp1 = str_z;

    while(1)
    {
        printf("str = [%02X], temp_zero = [%d], temp_count = [%d]\n",*str_temp1,temp_zero,temp_count);
        // if find 10 zero, will return count
        if(*str_temp1 != 0x00)
        {
            printf("value = %02X, %ld\n",*str_temp1,str_temp1-str_z);
            temp_count += temp_zero;
		    str_temp1++;
            temp_zero = 1;
        }
        else
        {
            temp_zero++;
            printf("value = %02X, %ld\n",*str_temp1,str_temp1-str_z);
        }
            
        
        if(temp_zero > 10)
            break;
    }
    printf("init count = %d, temp_count = %d\n",count,temp_count);
    return temp_count;
}

int my_strlen(uint8_t *str)
{
    printf("enter my_strlen");
    uint8_t *str_temp = str;
	// assert(str);
	int count = 0;

    // while (*str != '\0') // this will ignore 0x00
	while (*str_temp != '\0')
	{
        printf("value = %02X, %ld\n",*str_temp,str_temp-str);
		count++;
		str_temp++;
	}
    // has found 0x00, str end. but uart data may contents 0x00 .. 0x00
    // so, need to judge next value

    count = search_str_end(str_temp-1,count);

    // int temp_count = count;
    // for(int i=0;i<10;i++)
    // {
    //     if(*str_temp =='\0')
    //     {
    //         temp_count++;
    //         str_temp++;
    //         // printf("temp_count = %d\n",temp_count);
    //     }
    //     else
    //         break;
    // }
    // // printf("temp_count = %d,count=%d\n",temp_count,count);
    // if(temp_count == count+10)
    //     printf("search 10 0x00 \n");
    // else
    // {
    //     printf("has find 0x00 \n");
    //     printf("end1 temp_count = %d,count=%d\n",temp_count,count);
    //     return temp_count;
    // }

    // printf("end 2 temp_count = %d,count=%d\n",temp_count,count);
	return count;
}


int judge_char(uint8_t * str)
{
    if (str != NULL){
        // not empty
        printf("enter judge_char");
        if (my_strlen(str) != 0) {
            // not '\0'
            return 1;            
        }
        else
            return 0;
    }
    else
        return -1;
}


// unsigned int uart_init(void)
// {
//     unsigned int ret;
//     UartAttribute attr;

//     LzUartDeinit(UART_ID);

//     attr.baudRate = 115200;
//     attr.dataBits = UART_DATA_BIT_8;
//     attr.pad = FLOW_CTRL_NONE;
//     attr.parity = UART_PARITY_NONE;
//     attr.rxBlock = UART_BLOCK_STATE_NONE_BLOCK;
//     attr.stopBits = UART_STOP_BIT_1;
//     attr.txBlock = UART_BLOCK_STATE_NONE_BLOCK;

//     // 使用UART0
//     PinctrlSet(GPIO0_PB6, MUX_FUNC2, PULL_KEEP, DRIVE_LEVEL2);
//     PinctrlSet(GPIO0_PB7, MUX_FUNC2, PULL_KEEP, DRIVE_LEVEL2);
    
//     ret = LzUartInit(UART_ID, &attr);
//     if (ret <0)
//     {
//         printf("%s, %d: LzUartInit(%d) failed!\n", __FILE__, __LINE__, ret);
//         return 1;
//     }

//     return 0;
// }



void func_uart_write(uint8_t * str, int fd)
{
    printf("enter func_uart_write");
    unsigned int ret;
    // printf("Youkai : %s, %d: uart write!\n", __FILE__, __LINE__);

    // plus 3 due to dwin has head1/2/len
    ret = write(fd, str, *(str+2));
    if (ret <0)
    {
        printf("%s, %d: LzUartInit(%d) failed!\n", __FILE__, __LINE__, ret);
        return;
    }

    //delay(100);
}

// void print_uint8(uint8_t * in)
// {
//     printf("----temp: len[%d]\t[",*(in+2));
//     for(int i =0;i< 8;i++)
//     {
//         printf("%02X",*(in+i));
//     }
//     printf("]\n");
// }

void uint8_2_char(uint8_t * in,char * out, int cp_len)
{
    // printf("----temp: len[%d]\t[",*(in+2));
    printf("raw uint8_t data[");
    int cmd_len=*(in+2)+3;
    char tmp[3];
    memset(tmp,0x00,3);
    for(int i =0;i< cp_len;i++)
    {
        printf("%02X",*(in+i));
        sprintf(tmp,"%02X",*(in+i));
        strcat(out,tmp);

        memset(tmp,0x00,3);
    }
    printf("]\n");
}

void main(void)
{
    int fd;
    int nread;
    char buf_rx[BUF_RX_MAX+1];
    int n=0,i=0;
    // char* dev  = NULL;
    char dev[]  = "/dev/ttyS5";
    struct termios oldtio,newtio;
	speed_t speed = B115200;
    int next_option,havearg = 0,flow = 0;

    /*  打开串口 */
    fd = open(dev, O_RDWR | O_NONBLOCK| O_NOCTTY | O_NDELAY); 
    if (fd < 0)	{
        printf("Can't Open Serial Port!\n");
        exit(0);	
    }
	
	printf("Welcome to uart buf_tx\n");
	
    //save to oldtio
    tcgetattr(fd,&oldtio);
    bzero(&newtio,sizeof(newtio));
    newtio.c_cflag = speed|CS8|CLOCAL|CREAD;
    newtio.c_cflag &= ~CSTOPB;
    newtio.c_cflag &= ~PARENB;
    newtio.c_iflag = IGNPAR;  
    newtio.c_oflag = 0;
    // newtio.c_cc[VTIME]=10;
    tcflush(fd,TCIFLUSH);  
    tcsetattr(fd,TCSANOW,&newtio);  
    tcgetattr(fd,&oldtio);
	
    memset(buf_rx,0,BUF_RX_MAX+1);

    char buf_tx[100]="forlinx_uart_test.1234567890...";

    printf("Send buf_tx data:\n[%s] [%ld]\n",buf_tx,strlen(buf_tx));
	write(fd, buf_tx, strlen(buf_tx));
	fd_set rd;

    int flag_rx=0;
    bool flag_rx1= false;
    bool flag_rx2 = false;

    bool flag_print=true;
    int cmd_len=0;


    uint8_t str_send[UART_RECV_LEN] = "HelloWorld!\n";
    char str_send_char[513] = "";
    uint8_t recv_int8[UART_RECV_LEN];
    char recv_char[UART_RECV_LEN];
    uint8_t recv_int8_t[9];
    char recv_char_t[LEN_CHAR_TEMP];

    char *recv_char_p=NULL;

    // char **recv_char_addr=&recv_char;

    // status set true, will allow to send uart msg from xiaolinpai to dwin
    
    bool status_uart_send = false;

    init_dwin_status();
    // dwin_cmd_init_send();

    // i_dwin_cmd * p_cmd_send = &cmd_send;
    // dwin_cmd_init_send(p_cmd_send);

    // ------------------- test uint8 to char -------------------
    uint8_t xxx[]={0X5A,0XA5,0X05,0X82,0X10,0X00,0X00,0X01};
    // u8_2_char(xxx);
    char *yyy=(char *)malloc(get_len(recv_int8));
    u8_to_char(xxx,&yyy);
    // yyy = (char *)u8_to_char(xxx);
    printf("yyy = %s\n",yyy);
    // ------------------- test uint8 to char -------------------

    printf("enter while\n");

    printf("youkai\n");

    while (1)
    {
        // ----------------- uart write -----------------
        // if(status_uart_send == true)
        // {
        //     printf("enter send uart\n");
        //     // judge if str_send is empty
        //     // int temp = -1;
        //     // temp = judge_char(str_send);

        //     // if(temp == 1)
        //     if(*str_send != 0x00)
        //     {
        //         printf("func_uart_write before\n");
        //         func_uart_write(str_send,fd);
        //         printf("func_uart_write end\n");
        //     }

        //     memset(str_send,0x00,259);

        //     // if send ok, 
        //     // status_uart_send = false;
        // }


        //delay(100);


        // // printf("Youkai : %s, %d: uart write!\n", __FILE__, __LINE__);
        // ret = write(UART_ID, str_send, my_strlen(str_send));
        // if (ret <0)
        // {
        //     printf("%s, %d: LzUartInit(%d) failed!\n", __FILE__, __LINE__, ret);
        //     return;
        // }

        
        // ----------------- uart read -----------------
        memset(recv_int8_t,0x00,UART_RECV_LEN);
        int nread = read(fd, recv_int8_t, UART_RECV_LEN);
        if (nread >  0)
        {
            
            // 接收到的是字符串 "5AA5" 4
            // printf("temp: len[%ld]\t[%s]\n",strlen(recv_int8_t),recv_int8_t);

            // 接收到的是十六进制数 0x5AA5 2
            // printf(">>>>%d,,%d\n",*recv_int8_t,*(recv_int8_t+1));
            if(*recv_int8_t==0x5a && *(recv_int8_t+1)==0xa5)
            {
                cmd_len=*(recv_int8_t+2)+3;
                cmd_len=2*cmd_len ;
                printf("\ncmd len = %d\n",cmd_len);
                // if(recv_char_p == NULL)
                // {  
                //     recv_char_p=(char*)malloc(cmd_len+1);
                // }
            }

            // printf("uart read= %d\n",nread);

            // sprintf(recv_char_t,"%02X",recv_int8_t);
            memset(recv_char_t,0x00,LEN_CHAR_TEMP);
            uint8_2_char(recv_int8_t,recv_char_t, nread);
            // u8_to_char(recv_int8_t,&recv_char_t);
            // printf("recv_char_t = [%s]\n",recv_char_t);

            strcat(recv_char,recv_char_t);
            // strcat(recv_char_p,recv_char_t);
            printf("recv_char = [%s]\n",recv_char);

            // // 获取长度,16进制传输
            // int temp_len_i=get_len(recv_int8);
            // printf("temp_len=%d\n",temp_len_i);
            // printf("temp: len[%02x]\t[",*(recv_int8_t+2),recv_int8_t);

            // 收到数据设置状态
            flag_rx1=true;
            flag_rx2=true;

        }
        else if(nread < 0 )
        {
            printf("%s, %d: LzUartInit(%d) failed!\n", __FILE__, __LINE__, nread);
            return;
        }
        if(nread == 0)
        {
           // 判断传输停止
            if(flag_rx1==true&&flag_rx2==true)
            {
                flag_rx2=false;
            }
            else if(flag_rx1==true&&flag_rx2==false)
            {
                flag_rx1=false;

                printf("judge 1\n");

                if(strlen(recv_char)>0)
                {
                    printf("strlen = %ld _ cmd_len=%d\n",strlen(recv_char),cmd_len);

                    if(strlen(recv_char)==cmd_len)
                    // if(strlen(recv_char_p)==cmd_len)
                    {
                        printf(">>>recv_cmd_char = [%s]\n",recv_char);
                        // printf(">>>recv_cmd_char = [%s]\n",recv_char_p);

                        // c_judge_dwin_event(&cmd_recv_char);
                        // c_dwin_cmd_analysis(&recv_char_p,&cmd_recv_char);
                        c_dwin_cmd_analysis(recv_char,&cmd_recv_char);
                        // c_print_cmd(&cmd_recv_char);
                        
                        // free(recv_char_p);
                        tcflush(fd, TCIOFLUSH);
                    }
                    memset(recv_char,0x00,UART_RECV_LEN);
                }
            }
        }
    }
    close(fd);
    
    return;
}


#include "dwin.h"


// DATA FORMAT: head  + date len + write/read + addr + read_len / write_value
//              5A A5 +          +    82/83   + 3000 +    01    /     3132
// ps: date_len = write/read(1) + addr(2) + read_len / write_value(1/2)     
// date_len is the number bytes of end date_len  
#define DWIN_CMD_HEAD_1  0x5A//{0x5A,0XA5}//"\x5A\xA5"
#define DWIN_CMD_HEAD_2  0xA5
#define DWIN_CMD_WRITE   0x82
#define DWIN_CMD_READ    0x83

#define DWIN_CMD_OK "5AA503824F4B\0"

#define DWIN_CMD_POINT_HEAD1 0
#define DWIN_CMD_POINT_HEAD2 1
#define DWIN_CMD_POINT_LEN 2
#define DWIN_CMD_POINT_WR 3
#define DWIN_CMD_POINT_ADDR1 4
#define DWIN_CMD_POINT_ADDR2 5
#define DWIN_CMD_POINT_VALUE 6


// -------------------- data --------------------
// case 1
// malloc char menber to save dwincmd by char format
// char * dwin_cmd_char_temp;

// case 2 
char dwin_cmd_char_temp[DWIN_CMD_CHAR_MAX];
uint8_t dwin_cmd_u8_temp[DWIN_CMD_U8_MAX];
char * dwin_cmd_char_value;
char temp_c[3];



i_dwin_cmd temp_cmd_recv; // from dwin
i_dwin_cmd temp_cmd_send; // send to dwin

c_dwin_cmd cmd_recv_char; // from dwin
c_dwin_cmd cmd_send_char; // send to dwin

dwin_event_key event_key_list[EVENT_KEY_NUM_MAX]={
    // {
    //     event_flag, event_name,
    //     event_status,
    //     event_addr, event_flag_name,
    //     event_ops1, enent_ops1
    // },

    {
        EVENT_FLAG_AUDIO_RECORD, "record",
        EVENT_FLAG_STATUS_STOP,
        "1503", "EVENT_FLAG_AUDIO_RECORD",
        func_open_record,   func_close_record
    },

    {
        EVENT_FLAG_CAM_SCAN,    "cam",
        EVENT_FLAG_STATUS_STOP,
        "1504", "EVENT_FLAG_CAM_SCAN",
        func_open_cam,      func_close_cam
    },

    {
        EVENT_FLAG_NFC_SCAN,    "nfc",
        EVENT_FLAG_STATUS_STOP, 
        "1505", "EVENT_FLAG_NFC_SCAN",
        func_open_nfc,      func_close_nfc
    },

    {
        EVENT_FLAG_UNKOWN,  "unknow",
        EVENT_FLAG_STATUS_STOP,
        "0000" , "EVENT_FLAG_UNKOWN"
    }
};

dwin_event_key_spec event_key_spec[EVENT_KEY_SPEC_NUM_MAX]=
{
    // special event, just one ops
    // {
    //     event_key, event_name,
    //     event_ops
    // },

    {
        "1502010012",  "search",
        func_search
    },
    // ...

    {EVENT_KEY_SPEC_VALUE,  "end", 
        func_spec_end
    }
};


// -------------------- event func --------------------

// function 
void func_open_record()
{
    printf("--- func_record_open\n");
    return;
}

void func_close_record()
{
    printf("--- func_close_record\n");
    return;
}

// function 
void func_open_cam()
{
    printf("--- func_cam_open\n");
    return;
}

void func_close_cam()
{
    printf("--- func_close_cam\n");
    return;
}

// function 
void func_open_nfc()
{
    printf("--- func_nfc_open\n");
    return;
}

void func_close_nfc()
{
    printf("--- func_close_nfc\n");
    return;
}


void func_search()
{
    printf("--- func_search\n");
    return;
}

void func_spec_end()
{
    printf("--- func_spec_end\n");
    return;
}
// void (*func)();



// -------------------- dwin func --------------------

void init_dwin_status()
{
    printf("set all status stop\n");
    dwin_event_key  * temp_key;
    temp_key = &event_key_list[0];
    for(int i =0; temp_key->flag != EVENT_FLAG_UNKOWN; i++)
    {
        temp_key = &event_key_list[i];
        temp_key->status = EVENT_FLAG_STATUS_STOP;
    }
    return;
}

//---------------------------------------------------------
//  FOR uint8_t data  0x5AA5..
//
//
//
//---------------------------------------------------------

// cmd save as uint_8
void i_dwin_cmd_clear(i_dwin_cmd * cmd)
{
    cmd->head[0]=DWIN_CMD_HEAD_1;
    cmd->head[1]=DWIN_CMD_HEAD_2;
    cmd->len = 0x00;
    cmd->wr = 0x00;
    cmd->addr[0] = 0x00;
    cmd->addr[1] = 0x00;
    cmd->value = NULL;


    if(cmd->cmd_u8 != NULL)
    {
        free(cmd->cmd_u8);
        cmd->cmd_u8 = NULL;
    }

    if(cmd->cmd_char != NULL)
    {
        free(cmd->cmd_char);
        cmd->cmd_char = NULL;
    }

    // memset(cmd->cmd_u8,0x00,DWIN_CMD_LEN_U8_MAX);
    // cmd->cmd_char = NULL;
    return;
}

void dwin_cmd_init_send()
{
    i_dwin_cmd_clear(&temp_cmd_recv);

    temp_cmd_recv.wr = DWIN_CMD_WRITE;

    temp_cmd_recv.cmd_char = NULL;
    temp_cmd_recv.cmd_u8 = NULL;

    // memset(temp_cmd_recv.cmd_char,0x00,DWIN_CMD_CHAR_MAX);
    // memset(temp_cmd_recv.cmd_u8,0x00,DWIN_CMD_LEN_U8_MAX);
    return;
}




// TOTO
// analysis u8 cmd to save in cmd
void uart_dwin_cmd_analysis(uint8_t *in_u8_raw)
{
    // 1. judge cmd is dwin head
    uint8_t *cmd_temp = in_u8_raw;
    if(*(cmd_temp+DWIN_CMD_POINT_HEAD1) == DWIN_CMD_HEAD_1 
        && *(cmd_temp+DWIN_CMD_POINT_HEAD2)== DWIN_CMD_HEAD_2)
    {
        printf("this is dwin cmd\n");

        i_dwin_cmd_clear(&temp_cmd_recv);
        
        // 1. save cmd msg
        temp_cmd_recv.len = *(cmd_temp + DWIN_CMD_POINT_LEN);
        temp_cmd_recv.wr = *(cmd_temp + DWIN_CMD_POINT_WR);
        temp_cmd_recv.addr[0] = *(cmd_temp + DWIN_CMD_POINT_ADDR1);
        temp_cmd_recv.addr[1] = *(cmd_temp + DWIN_CMD_POINT_ADDR2);
        temp_cmd_recv.value = cmd_temp + DWIN_CMD_POINT_VALUE;
        // temp_cmd_recv.cmd_u8 = dwin_cmd_u8_temp;
        
        // case1:
        // copy_u8_2_u8(cmd_temp);

        //case2:
        temp_cmd_recv.cmd_u8 = u8_to_u8(in_u8_raw);

        // print_dwin_cmd(temp_cmd_recv);

        // uint8_t to char , save in cmd struct
        
        // case1:
        // temp_cmd_recv.cmd_char = dwin_cmd_char_temp;
        // memset(temp_cmd_recv.cmd_char,0x00,DWIN_CMD_CHAR_MAX);


        //case2:
        char *temp_c=NULL;

        u8_to_char(in_u8_raw,&temp_c);

        if(temp_c!= NULL)
            temp_cmd_recv.cmd_char = temp_c;
        else
            printf("temp_c is null");

        printf("temp_cmd_recv.cmd_char");
        // dwin_cmd_uint8_t2char(temp_cmd_recv);
        // printf("dwin cmd char = %s\n",temp_cmd_recv.cmd_char);

        // 2. event judge
        uart_judge_dwin_event(&temp_cmd_recv);

        printf("uart_judge_dwin_event");
    }
    return;
}



// TOTO
dwin_event_flag uart_judge_dwin_event(i_dwin_cmd * cmd)
{
    printf("\nenter uart_judge_dwin_event\n");

    // print_dwin_cmd(*cmd);
    printf("cmd str = %s\n",cmd->cmd_char);

    // 1. judge ok
    if(strcmp(cmd->cmd_char,DWIN_CMD_OK) == 0)
    {
        printf("recv ok\n");

        // get ok, stop send
        // status_uart_send = false;
        return EVENT_FLAG_OK;
    } 

    // 2. judge event

    printf("\nenter uart_judge_dwin_event\n");

    dwin_event_key * temp_value ;
    temp_value = &event_key_list[0];

    for(int i = 0; temp_value->flag != EVENT_FLAG_UNKOWN ; i++)
    {
        // +8 choose add
        // printf("search=%s,key=%s\n",cmd->cmd_char + DWIN_CMD_CHAR_ADDR_VALUE ,temp_value.key);

        // can't use strcmp, due to uart data may have double 0x00
        if(strstr(cmd->cmd_char + DWIN_CMD_CHAR_ADDR_VALUE, temp_value->key) != NULL)
        {
            printf("searched key= %s, value=%d, name=%s\n",temp_value->key,temp_value->flag,temp_value->flag_name);

            if(strstr(cmd->cmd_char + DWIN_CMD_CHAR_VALUE_VALUE, "010001") != NULL)
            {
                printf("status set open\n");
                if(temp_value->open != NULL )
                {
                    temp_value->open();
                    temp_value->status = EVENT_FLAG_STATUS_ING;
                    printf("%s status change: stop -> ing\n",temp_value->event_name);
                }
            }

            if(strstr(cmd->cmd_char + DWIN_CMD_CHAR_VALUE_VALUE, "010000") != NULL)
            {
                printf("status set close\n");
                if(temp_value->close != NULL )
                {
                    temp_value->close();
                    temp_value->status = EVENT_FLAG_STATUS_STOP;
                    printf("%s status change: ing -> stop\n",temp_value->event_name);
                }
            }

            // change_dwin_status(temp_value->flag);
            // change_dwin_status_key(temp_value);

            printf("has find match key, event = [%s]\n\n",temp_value->event_name);

            return temp_value->flag;
        }
        temp_value = &event_key_list[i];
    }

    printf("hasn't find match key\n");

    searc_spec_event(cmd);

    return EVENT_FLAG_UNKOWN;
}

void searc_spec_event(i_dwin_cmd * cmd)
{
    printf("search spec event\n");
    dwin_event_key_spec * temp_value ;
    temp_value = &event_key_spec[0];

    // printf("spec event key = %s\n",temp_value->key);

    for(int i = 0; strcmp(temp_value->key,EVENT_KEY_SPEC_VALUE) != 0 && i<EVENT_KEY_SPEC_NUM_MAX ; i++)
    {
        // printf("spec event key = %s\n",temp_value->key);
        // printf("spec event value = %s\n",cmd->cmd_char + DWIN_CMD_CHAR_ADDR_VALUE);
        if(strstr(cmd->cmd_char + DWIN_CMD_CHAR_ADDR_VALUE, temp_value->key ) != NULL)
        {
            temp_value->func();
            printf("find spec event: {value = %s,\tname = %s,\ttemp_value}\n",temp_value->key,temp_value->event_name);
            return;
        }

        temp_value = &event_key_spec[i];

    }

    printf("unfind spec key\n");
    return;
}





// -------------------- basic func  --------------------


char * uint8_t2char(uint8_t value)
{
    memset(temp_c,0x00,3);
    sprintf(temp_c, "%02X", value);
    // printf("temp_c = [%s]\n",temp_c);
    return temp_c;
}

void print_dwin_cmd(i_dwin_cmd cmd)
{
    printf("len=%02X\n",cmd.len);
    printf("wr=%02X\n",cmd.wr);
    printf("addr=%02x_%02X\n",cmd.addr[0],cmd.addr[1]);
    printf("value=%s\n",cmd.cmd_char);
    return;
}


// 串口数据从uint8转换位char,例如0x5AA5,转换为字符串”5AA5“,由2字节转换为4字节
// malloc buffer and return buffer addr

void u8_to_char(uint8_t * in_u8, char ** out)
{
    uint8_t * temp_cmd_u8 = in_u8;

    int len_u8 = *(in_u8 + DWIN_CMD_POINT_LEN ) + 3; // +3 head12/len
    int len_char = 2*len_u8 +1;     // +1 '\0'
    printf("cmd_u8 len_u8=%d,len_char=%d\n",len_u8,len_char);

    // printf("0\n");
    // *out = (char *)malloc(len_char);
    // printf("1\n");
    memset(*out,0x00,len_char);
    // printf("2\n");

    for(int i=0;i<len_u8;i++)
    {
        // printf("i=%d\n",i);
        uint8_t temp_int8=*(in_u8+i);
        // printf("temp_int8 = %02x\n",temp_int8);
        uint8_t2char( temp_int8 );
        // printf("before strcat\n");
        strcat(*out,temp_c);
        // printf(">>end strcat\n");
        // temp_cmd_u8++;
    }
    // strcat(cmd_char_t,'\0');
    // *(temp_char + len_char -1) = '\0';

    printf("u8_to_char out = [%s] \n",*out);

    // printf("temp_char end\n");
    return;

}


uint8_t * u8_to_u8(uint8_t * in_u8)
{
    uint8_t * temp_in_u8 = in_u8;

    int len_u8 = *(in_u8 + DWIN_CMD_POINT_LEN) + 3;
    printf("cmd_u8 len_u8=%d\n",len_u8);

    uint8_t * temp_out_u8 = (uint8_t *)malloc(len_u8);

    for(int i=0;i<len_u8;i++)
    {
        *(temp_out_u8 +i) = *(temp_in_u8 +i);
    }

    return temp_out_u8;
}
















// -------------------- delete func  --------------------

void change_dwin_status_key(dwin_event_key *in_key)
{
    printf("change status \n");

    if(in_key->status == EVENT_FLAG_STATUS_ING)
    {
        in_key->status = EVENT_FLAG_STATUS_STOP;
        printf("%s status change: ing -> stop\n",in_key->event_name);

        return;
    }
    else if(in_key->status == EVENT_FLAG_STATUS_STOP){
        in_key->status = EVENT_FLAG_STATUS_ING;
        printf("%s status change: stop -> ing\n",in_key->event_name);

        return;
    }
    else
        printf("error event_flag for %s\n",in_key->event_name);

    printf("unknown event\n");
    return;
}


void save_cmd_u8(i_dwin_cmd * cmd)
{
    uint8_t * p = cmd->cmd_u8;
    *(p+DWIN_CMD_POINT_HEAD1) = cmd->head[0];
    *(p+DWIN_CMD_POINT_HEAD2 ) = cmd->head[1];
    *(p+DWIN_CMD_POINT_LEN ) = cmd->len;
    *(p+DWIN_CMD_POINT_WR ) = cmd->wr;
    *(p+DWIN_CMD_POINT_ADDR1 ) = cmd->addr[0];
    *(p+DWIN_CMD_POINT_ADDR2 ) = cmd->addr[1];

    return;
    // *(p+2)
}

char * uint8_t2char_list(uint8_t * p_dwin_u8_value,int len)
{
    char * p_dwin_char_value = dwin_cmd_char_value;

    for(int i=0; i<len; i++)
    {
        strcat(p_dwin_char_value,uint8_t2char(*p_dwin_u8_value));
        p_dwin_u8_value++;
        p_dwin_char_value = p_dwin_char_value + 2;
    }

    *(p_dwin_char_value +1 )= '\0';
    
    return dwin_cmd_char_value;
}


int dwin_event_cmp(uint8_t * value ,uint8_t *match)
{
    uint8_t * p_value = value;
    uint8_t * p_match = match;
    for(int i=0;i<4;i++)
    {
        if(*p_value == *p_match)
        {
            p_value++;
            p_match++;
        }
        else
        {
            printf("dont match\n");
            return 0;
        }
        printf(" matched \n");
        return 1;
    }
    return 0;
}

/*
    func1: uint8_t change to char
        0x5A A5 04 83 10 00 01
        "5AA50483100001"

    func2: judge uint8_t
        if(str[X] == 0x5A)
*/
char * dwin_cmd_uint8_t2char(i_dwin_cmd cmd)
{
    print_dwin_cmd(cmd);

    // case1: malloc
    // int cmd_len = cmd.len;
    // int malloc_len = (cmd_len + 3) *2 +1;
    // printf("malloc %d\n",malloc_len);
    // dwin_cmd_char_temp = (char*)malloc( malloc_len);

    // case2: char array
    memset(dwin_cmd_char_temp,0x00,DWIN_CMD_CHAR_MAX);

    // point to char value pos
    dwin_cmd_char_value = dwin_cmd_char_temp + 2*DWIN_CMD_POINT_VALUE;

    // 1. head 
    strcat(dwin_cmd_char_temp,"5AA5");
    // printf("dwin_cmd_char_temp = %s\n",dwin_cmd_char_temp);

    // 2. len
    uint8_t2char(cmd.len);
    strcat(dwin_cmd_char_temp,temp_c);

    // 3. wr
    uint8_t2char(cmd.wr);
    strcat(dwin_cmd_char_temp,temp_c);

    // 4. addr
    uint8_t2char(cmd.addr[0]);
    strcat(dwin_cmd_char_temp,temp_c);
    uint8_t2char(cmd.addr[1]);
    strcat(dwin_cmd_char_temp,temp_c);

    // printf("dwin_cmd_char_temp = %s\n",dwin_cmd_char_temp);

    // 5. addr
    uint8_t2char_list(cmd.value,cmd.len - 3);   // 3 due to addr(2) + wr(1)

    printf("dwin_cmd_char_temp = %s\n",dwin_cmd_char_temp);

    return dwin_cmd_char_temp;
}




/*
    func1: uint8_t change to char
        0x5A A5 04 83 10 00 01
        "5AA50483100001"

    func2: judge uint8_t
        if(str[X] == 0x5A)
*/
void uart_recv_value_cut(uint8_t * recv_all)
{
    // dwin_cmd_sizeof = sizeof(recv_all);
    int dwin_cmd_sizeof = strlen(recv_all);
    //ERROR may: my_strlen
    printf("dwin_cmd_sizeof = %d\n",dwin_cmd_sizeof);

    //p = (int*)malloc(sizeof(int) * n);
    char * dwin_cmd_charlist;
    dwin_cmd_charlist = (char*)malloc( dwin_cmd_sizeof *2 +1);
    
    memset(dwin_cmd_charlist,0x00,dwin_cmd_sizeof);

    for(int i = 0;i<dwin_cmd_sizeof;i++)
    {
        printf("i = [ %d ]\n",i);
        uint8_t temp_uc = recv_all[i];
        char temp_c[3] = "00";
        //ERROR, may set 2 

        if(temp_uc != 0x00)
            sprintf(temp_c, "%02X", temp_uc);
        else
        {
            printf("uc is 0x00\n");
            // temp_c[0] = '0';
            // temp_c[1] = '0';
            // temp_c = "00";
        }

        printf("temp_c = [ %s ]\n",temp_c);
        strcat(dwin_cmd_charlist,temp_c);
        //strcat(dwin_cmd_charlist,'\0');
        
    }
    printf("dwin_cmd_charlist %s \n",dwin_cmd_charlist);

    printf("end display");




    // if(recv_all[0]==DWIN_CMD_HEAD_1 && recv_all[1]==DWIN_CMD_HEAD_2)
    // {
    //     printf("this is dwin cmd %s\n",(char)recv_all);

    //     dwin_cmd_len = recv_all[2];
    //     dwin_cmd_wr = recv_all[3];
    //     dwin_cmd_addr[0] = recv_all[4];
    //     dwin_cmd_addr[1] = recv_all[5];
    //     dwin_cmd_data_len = recv_all[6];
    //     dwin_cmd_data_value = recv_all+7;

    //     printf("dwin_cmd_len %02X\n",dwin_cmd_len);
    //     printf("dwin_cmd_wr %02X\n",dwin_cmd_wr);
    //     printf("dwin_cmd_addr[0] %02X\n",dwin_cmd_addr[0]);
    //     printf("dwin_cmd_addr[1] %02X\n",dwin_cmd_addr[1]);
    //     printf("dwin_cmd_data_len %02X\n",dwin_cmd_data_len);


    //     sprintf(dwin_cmd_charlist, "%02X", dwin_cmd_len);
    //     printf("dwin_cmd_charlist %s\n",dwin_cmd_charlist);
    //     // printf(" %x\n",);
    //     // printf(" %x\n",);

    //     // if(recv_all[0]==0x5A)
    // }

    free(dwin_cmd_charlist);

    printf("end func");
    return ;
}


void copy_u8_2_u8(uint8_t * u8_raw)
{
    memset(dwin_cmd_u8_temp,0x00,DWIN_CMD_CHAR_MAX);
    uint8_t * p_raw = u8_raw;
    uint8_t * p_end = dwin_cmd_u8_temp;
    int len = *(u8_raw + DWIN_CMD_POINT_LEN) + 3;
    for(int i=0;i<len;i++)
    {
        *(p_end +i) = *(p_raw +i);
        // p_raw++;
        // p_end++;
    }

    return;
}


//---------------------------------------------------------
//  FOR char: "5AA5.."
//
//
//
//---------------------------------------------------------

// ADD FOR LINUX DIWN
int judge_dwin_cmd(uint8_t **in_u8_raw)
{
    // 1. judge cmd is dwin head
    printf("judge_dwin_cmd=[%s]\n",*in_u8_raw);
    uint8_t *cmd_temp = *in_u8_raw;
    if(*(cmd_temp+DWIN_CMD_POINT_HEAD1) == DWIN_CMD_HEAD_1 
        && *(cmd_temp+DWIN_CMD_POINT_HEAD2)== DWIN_CMD_HEAD_2)
    {
        printf("this is dwin cmd\n");
        return 1;
    }
    else
        return 0;
}

int get_len(uint8_t *cmd_u8)
{
    int len = *(cmd_u8  + 2);
    // printf("len = %d\n",len);
    return len;
}

// cmd save with char
void c_dwin_cmd_clear(c_dwin_cmd * cmd)
{
    printf("clear cmd value\n");
    strncpy(cmd->head,"5AA5",4);
    strncpy(cmd->len,"00",2);
    strncpy(cmd->wr,"83",2);
    strncpy(cmd->addr,"0000",4);
    cmd->value = NULL;
    cmd->cmd_char = NULL;

    // memset(cmd->cmd_u8,0x00,DWIN_CMD_LEN_U8_MAX);
    // cmd->cmd_char = NULL;
    return;
}

void print_uint8(uint8_t * in)
{
    printf("----temp: len[%d]\t[",*(in+2));
    for(int i =0;i< 8;i++)
    {
        printf("%02X",*(in+i));
    }
    printf("]\n");
}

void c_print_cmd(c_dwin_cmd *cmd)
{
    printf("print cmd value\n");
    printf("head | len | wr | addr | value  | all\n");
    printf("%s | %s  | %s | %s | %s | %s\n",cmd->head,cmd->len,cmd->wr,cmd->addr,cmd->value,cmd->cmd_char);
    return;

}

void c_dwin_cmd_analysis(char * in,c_dwin_cmd *cmd)
{
    // 1. judge cmd is dwin head
    char *cmd_temp = in;

    printf("this is dwin cmd\n");

    c_dwin_cmd_clear(cmd);
    
    // 1. save cmd msg
    printf("save cmd value\n");
    // printf("len=%s\n",(in+C_CMD_POINT_LEN));
    strncpy(cmd->len,in+C_CMD_POINT_LEN,2);
    strncpy(cmd->wr,in+C_CMD_POINT_WR,2);
    strncpy(cmd->addr,in+C_CMD_POINT_ADDR,4);
    // strncpy(cmd->value,in+C_CMD_POINT_LEN,);
    cmd->value=(in+C_CMD_POINT_VALUE);
    cmd->cmd_char=in;


    c_print_cmd(cmd);

    // 2. event judge
    c_judge_dwin_event(cmd);

    return;
}

void c_searc_spec_event(c_dwin_cmd * cmd)
{
    printf("search spec event\n");
    dwin_event_key_spec * temp_value ;
    temp_value = &event_key_spec[0];

    // printf("spec event key = %s\n",temp_value->key);

    for(int i = 0; strcmp(temp_value->key,EVENT_KEY_SPEC_VALUE) != 0 && i<EVENT_KEY_SPEC_NUM_MAX ; i++)
    {
        // printf("spec event key = %s\n",temp_value->key);
        // printf("spec event value = %s\n",cmd->cmd_char + DWIN_CMD_CHAR_ADDR_VALUE);
        if(strstr(cmd->cmd_char + DWIN_CMD_CHAR_ADDR_VALUE, temp_value->key ) != NULL)
        {
            temp_value->func();
            printf("find spec event, value = %s, name = %s\n",temp_value->key,temp_value->event_name);
            return;
        }

        temp_value = &event_key_spec[i];

    }

    printf("unfind spec key\n");
    return;
}


dwin_event_flag c_judge_dwin_event(c_dwin_cmd * cmd)
{
    printf("\nenter c_judge_dwin_event\n");

    // print_dwin_cmd(*cmd);
    printf("cmd str = [%s]\n",(cmd->cmd_char));

    // 1. judge ok
    if(strcmp((cmd->cmd_char),DWIN_CMD_OK) == 0)
    {
        printf("recv ok\n");

        // get ok, stop send
        // status_uart_send = false;
        return EVENT_FLAG_OK;
    } 

    // 2. judge event

    printf("\nenter c_judge_dwin_event\n");

    dwin_event_key * temp_value ;
    temp_value = &event_key_list[0];

    for(int i = 0; temp_value->flag != EVENT_FLAG_UNKOWN ; i++)
    {
        // +8 choose add
        // printf("search=%s,key=%s\n",*(cmd->cmd_char) + DWIN_CMD_CHAR_ADDR_VALUE ,temp_value.key);

        // can't use strcmp, due to uart data may have double 0x00
        if(strstr((cmd->addr), temp_value->key) != NULL)
        {
            printf("searched key= %s, value=%d, name=%s\n",temp_value->key,temp_value->flag,temp_value->flag_name);

            if(strstr((cmd->value) , "010001") != NULL)
            {
                printf("status set open\n");
                if(temp_value->open != NULL )
                {
                    temp_value->open();
                    temp_value->status = EVENT_FLAG_STATUS_ING;
                    printf("%s status change: stop -> ing\n",temp_value->event_name);
                }
            }

            if(strstr((cmd->cmd_char) , "010000") != NULL)
            {
                printf("status set close\n");
                if(temp_value->close != NULL )
                {
                    temp_value->close();
                    temp_value->status = EVENT_FLAG_STATUS_STOP;
                    printf("%s status change: ing -> stop\n",temp_value->event_name);
                }
            }

            // change_dwin_status(temp_value->flag);
            // change_dwin_status_key(temp_value);

            printf("has find match key, event = [%s]\n\n",temp_value->event_name);

            return temp_value->flag;
        }
        temp_value = &event_key_list[i];
    }

    printf("hasn't find match key\n");

    c_searc_spec_event(cmd);

    return EVENT_FLAG_UNKOWN;
}
#include "stddef.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
#include "stdint.h"

#define TRUE 1
#define FALSE 0
#define uint8_t u_int8_t
#define bool _Bool

typedef enum{
    EVENT_FLAG_OK = 0X0,
    EVENT_FLAG_AUDIO_RECORD = 0x3,
    EVENT_FLAG_AUDIO_PLAY = 0x4,
    EVENT_FLAG_CAM_SCAN = 0x5,
    EVENT_FLAG_NFC_SCAN = 0x6,
    EVENT_FLAG_BOOK_SEARCH = 0x10,
    EVENT_FLAG_BOOK_INPUT = 0x11,
    EVENT_FLAG_UNKOWN = -1,
}dwin_event_flag;

typedef enum{
    // EVENT_FLAG_STATUS_START = 0x0,
    EVENT_FLAG_STATUS_ING = TRUE,
    EVENT_FLAG_STATUS_STOP = FALSE,
    EVENT_FLAG_STATUS_ERROR = -1,
}dwin_event_flag_status;


typedef enum{
    EVENT_TYPE_DWIN_SEND = 0x0,  // uart read
    EVENT_FLAG_DWIN_RECV = 0x1,  // uart write
}dwin_event_type;

#define DWIN_CMD_LEN_U8_MAX 259

typedef struct
{
    uint8_t head[2];
    uint8_t len;
    uint8_t wr;
    uint8_t addr[2];
    uint8_t * value;
    // uint8_t cmd_u8[DWIN_CMD_LEN_U8_MAX];
    uint8_t * cmd_u8;
    char * cmd_char;
}i_dwin_cmd;



void uart_recv_value_cut(uint8_t * recv_all);
// dwin_event_flag uart_judge_dwin_event(char *str);
dwin_event_flag uart_judge_dwin_event(i_dwin_cmd * cmd);

void print_dwin_cmd(i_dwin_cmd cmd);

char * dwin_cmd_uint8_t2char(i_dwin_cmd cmd);

char * uint8_t2char(uint8_t value);

char * uint8_t2char_list(uint8_t * p_dwin_u8_value,int len);

void change_dwin_status(dwin_event_flag event_flag);

// UART recv/send judge dwin_event
#define EVENT_KEY_NUM_MAX 10
// #define EVENT_KEY_MAX -1

// function 
void func_open_record();
void func_close_record();
void func_open_cam();
void func_close_cam();
void func_open_nfc();
void func_close_nfc();

#define EVENT_NAME_MAX 11
#define EVENT_FLAG_NAME_MAX 30
#define EVENT_KEY_VALUE_MAX 11   //"3000 0001"  is 8

typedef struct
{
    dwin_event_flag flag;
    char event_name[EVENT_NAME_MAX];
    dwin_event_flag_status status;
    char key[EVENT_KEY_VALUE_MAX];   // key[0,3] addr key[4,7] value
    char flag_name[EVENT_FLAG_NAME_MAX];
    void (*open)();
    void (*close)();
}dwin_event_key;

dwin_event_key event_key_list[EVENT_KEY_NUM_MAX];
// {
//     // {
//     //     event_flag, event_name,
//     //     event_status,
//     //     event_addr, event_flag_name,
//     //     event_ops1, enent_ops1
//     // },

//     {
//         EVENT_FLAG_AUDIO_RECORD, "record",
//         EVENT_FLAG_STATUS_STOP,
//         "1503", "EVENT_FLAG_AUDIO_RECORD",
//         func_open_record,   func_close_record
//     },

//     {
//         EVENT_FLAG_CAM_SCAN,    "cam",
//         EVENT_FLAG_STATUS_STOP,
//         "1504", "EVENT_FLAG_CAM_SCAN",
//         func_open_cam,      func_close_cam
//     },

//     {
//         EVENT_FLAG_NFC_SCAN,    "nfc",
//         EVENT_FLAG_STATUS_STOP, 
//         "1505", "EVENT_FLAG_NFC_SCAN",
//         func_open_nfc,      func_close_nfc
//     },

//     {
//         EVENT_FLAG_UNKOWN,  "unknow",
//         EVENT_FLAG_STATUS_STOP,
//         "0000" , "EVENT_FLAG_UNKOWN"
//     }
// };

typedef struct
{
    char key[EVENT_KEY_VALUE_MAX];   // key[0,3] addr key[4,7] value
    char event_name[EVENT_FLAG_NAME_MAX];
    void (*func)();
}dwin_event_key_spec;


void func_search();
void func_spec_end();

void searc_spec_event();

#define EVENT_KEY_SPEC_VALUE "over"
#define EVENT_KEY_SPEC_NUM_MAX 20
dwin_event_key_spec event_key_spec[EVENT_KEY_SPEC_NUM_MAX];
// {
//     // special event, just one ops
//     // {
//     //     event_key, event_name,
//     //     event_ops
//     // },

//     {
//         "1502010012",  "search",
//         func_search
//     },
//     // ...

//     {EVENT_KEY_SPEC_VALUE,  "end", 
//         func_spec_end
//     }
// };

void change_dwin_status_key(dwin_event_key *in_key);

void change_cmd_send_status(dwin_event_flag temp_event_flag);


// -------------------- basic func  --------------------

void copy_u8_2_u8(uint8_t * u8_raw);


void u8_to_char(uint8_t * in_u8, char ** out);


uint8_t * u8_to_u8(uint8_t * in_u8);

// -------------------- dwin func --------------------
void dwin_cmd_init_send();
void init_dwin_status();
void i_dwin_cmd_clear(i_dwin_cmd * cmd);

// get u8 from example 
void uart_dwin_cmd_analysis(uint8_t *str);

void copy_u8_to_cmdu8(i_dwin_cmd *cmd, uint8_t * u8);

//int my_strlen(uint8_t *str);

// int search_str_end(uint8_t *str_z, int count);
// int my_strlen(uint8_t *str);
// int judge_char(uint8_t * str);


#define DWIN_CMD_CHAR_ADDR_VALUE 8
#define DWIN_CMD_CHAR_VALUE_VALUE 12
#define DWIN_CMD_CHAR_MAX 513
#define DWIN_CMD_U8_MAX 256



// add for char
#define C_CMD_POINT_HEAD 0
#define C_CMD_POINT_LEN 4
#define C_CMD_POINT_WR 6
#define C_CMD_POINT_ADDR 8
#define C_CMD_POINT_VALUE 12

typedef struct
{
    char head[5];
    char len[3];
    char wr[3];
    char addr[5];
    char * value;
    char * cmd_char;
}c_dwin_cmd;

int judge_dwin_cmd(uint8_t ** in_u8_raw);
int get_len(uint8_t *cmd_u8);


void c_dwin_cmd_analysis(char * in,c_dwin_cmd *cmd);

void c_dwin_cmd_clear(c_dwin_cmd * cmd);
dwin_event_flag c_judge_dwin_event(c_dwin_cmd * cmd);
void c_print_cmd(c_dwin_cmd *cmd);
void print_uint8(uint8_t * in);
#CC = aarch64-poky-linux-gcc -mcpu=cortex-a55 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/poky/3.1.5/sysroots/aarch64-poky-linux

TARGET=t2_uart

OBJS=t2_uart.o

CFLAGS+=-c -Wall -g
LDFLAGS+= -lpthread

OPENSSL_DIR	= /home/share/forlinx/OKT507/pro/feiling_dwin/v3_event
INC_DIR =  dwin.h
SRC_DIR =  dwin.c

DWIN = dwin

# $(TARGET):$(OBJS)
# 	$(CC) $^ $(LDFLAGS) -o $@  

# %.o:%.c                  
# 	$(CC) $^ $(CFLAGS) -o $@

dwin_test:uart_example.c  $(SRC_DIR) $(INC_DIR)
	$(CC) $^ -o dwin_test

# dwin.o: 
# 	$(CC)  $^ -o dwin.o

# $CC t2_uart.c -o t2_uart

clean:
	$(RM) *.o $(TARGET) -r

install:
	install -m 0755 $(TARGET) ./

配置环境

在这里插入图片描述

【命令】export CC=aarch64-linux-gnu-gcc

编译

在对应目录直接输入make,会调用Makefile进行编译,最终生成dwin_test文件
【命令】make
在这里插入图片描述

传输

通过sftp将文件传输给设备OKT507
在这里插入图片描述
直接拖到右侧的远程站点即可。

运行

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值