/*
 * @Author: chenjie
 * @Date: 2022-06-06
 * @LastEditTime: 2022-10-27
 * @LastEditors: chenjie
 * @Description: 
 * @FilePath: \S32K146_4G\code\app\lib\AppFuncLib.c
 * Copyright (c) 2022 by chenjie, All Rights Reserved.
 */
#include "AppFuncLib.h"
#include "AppGlobalVar.h"
#include "Hal_Fls.h"
#include "AppTaskUart1.h"
/**
 * @brief : 获取故障码函数,从故障数组中获取故障码,并将之前的故障码向前移动
 * @param {UINT16} *ErrorArray
 * @param {UINT8} Errorlen
 * @return {*}
 */
static uint8 bcc_chk_fota(uint8 *data, uint8 length);
static uint8 Fota_crc_chk(uint8 *data, uint8 length);
uint16 GetErrorNum(uint16 *ErrorArray, uint8 Errorlen)
{
    uint16 OutNum;
    OutNum = *(ErrorArray);
    for (uint8 i = 0; i < Errorlen - 1; i++)
    {
        *(ErrorArray + i) = *(ErrorArray + i + 1);
        if (*(ErrorArray + i + 1) == 0)
            break;
    }
    return OutNum;
}
uint8 PutErrorNum(uint16 *ErrorArray, uint8 Errorlen, uint16 ErrorNum)
{
    for (uint8 i = 0; i < Errorlen; i++)
    {
        if (*(ErrorArray + i) == 0)
        {
            *(ErrorArray + i) = ErrorNum;
            return 0;
        }
        else
        {
            if (*(ErrorArray + i) == ErrorNum)
            {
                return 1;
            }
            else
            {
                continue;
            }
        }
    }
    return 2;
}
uint16 ATstrdel(char *str)
{
    char *p = str;
    bool flag = false;
    while (*str)
    {
        if (*str > 0x20)
        {
            *(p) = *str;
            p = p + 1;
            flag = false;
        }
        else
        {
            if (!flag)
            {
                *(p) = ',';
                p = p + 1;
                flag = true;
            }
        }
        str++;
    }
    *p = '\0';
    return 0;
}
uint16 mstrlen(const char *s)
{
    uint16 out = 0;
    const char *ss = s;
    while (*ss)
        ss++;
    out = (ss - s);
    return out;
}
int mstrncmp(const char *s1, const char *s2, int n)
{
    const unsigned char *c1 = (const unsigned char *)s1;
    const unsigned char *c2 = (const unsigned char *)s2;
    unsigned char ch;
    int d = 0;
    while (n--)
    {
        d = (int)(ch = *c1++) - (int)*c2++;
        if (d || !ch)
            break;
    }
    return d;
}
unsigned char HexToChar(unsigned char bHex)
{
    if ((bHex >= 0) && (bHex <= 9))
        bHex += 0x30;
    else if ((bHex >= 10) && (bHex <= 15)) //大写字母
        bHex += 0x37;
    else
        bHex = 0xff;
    return bHex;
}
unsigned char CharToHex(unsigned char bChar)
{
    if ((bChar >= 0x30) && (bChar <= 0x39))
        bChar -= 0x30;
    else if ((bChar >= 0x41) && (bChar <= 0x46)) //大写字母
        bChar -= 0x37;
    else if ((bChar >= 0x61) && (bChar <= 0x66)) //小写字母
        bChar -= 0x57;
    else
        bChar = 0xff;
    return bChar;
}
uint8 AtStrCompare(const char *a, const char *b)
{
    uint8 out = 1;
    while (1)
    {
        if (*a == '\0' || *b == '\0') //判断其中是否有字符串结束
        {
            if (strlen(a) == strlen(b))
            {
                out = 1;
                break;
            }
            else
            {
                out = 0;
                break;
            }
        }
        else
        {
            if (*a != *b)
            {
                out = 0;
                break;
            }
            else if (*a == '=' && *b == '=')
            {
                out = 1;
                break;
            }
        }
        a++;
        b++;
    }
    return out;
}
unsigned short CRC16_Modbus(unsigned char *pdata, int len)
{
    unsigned short crc = 0xFFFF;
    int i, j;
    for (j = 0; j < len; j++)
    {
        crc = crc ^ pdata[j];
        for (i = 0; i < 8; i++)
        {
            if ((crc & 0x0001) > 0)
            {
                crc = crc >> 1;
                crc = crc ^ 0xa001;
            }
            else
                crc = crc >> 1;
        }
    }
    return crc;
}
char *Myitoa(int value, char *result, int base)
{
    // check that the base if valid
    if (base < 2 || base > 36)
    {
        *result = '\0';
        return result;
    }

    char *ptr = result, *ptr1 = result, tmp_char;
    int tmp_value;

    do
    {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
    } while (value);

    // Apply negative sign
    if (tmp_value < 0)
        *ptr++ = '-';
    *ptr-- = '\0';
    while (ptr1 < ptr)
    {
        tmp_char = *ptr;
        *ptr-- = *ptr1;
        *ptr1++ = tmp_char;
    }
    return result;
}

/************************************************************************
 * @brief 整数转字符串
 * @param[in] num 整数
 * @param[out] buf 字符串
 * @return 返回字符串长度
 ************************************************************************/
inline int _itoa(int num, char buf[32])
{
    return _i2a(num, buf, 10);
}

/************************************************************************
 * @brief 整数转字符串
 * @param[in] num 整数
 * @param[out] buf 字符串
 * @param[in] radix 进位制整数
 * @return 返回字符串长度
 ************************************************************************/
int _i2a(int num, char buf[32], int radix)
{
    static const char s[] = "0123456789abcdef";
    int n = num, R = radix;
    char *dst = buf;
    if (n < 0)
    {
        *dst++ = '-';
        n = -n;
    }
    if (n < 10)
    {
        *dst++ = s[n];
        *dst = 0;
    }
    else
    {
        char tmp[32], *p = tmp;
        while (n)
        {
            *p++ = s[n % R];
            n /= R;
        }
        while (--p != tmp)
            *dst++ = *p;
        *dst++ = *tmp;
        *dst = 0;
    }
    return dst - buf;
}

/************************************************************************
 * @brief 浮点数转字符串
 * @param[in] val 浮点数
 * @param[out] buf 字符串
 * @param[in] eps 精度(小数位)
 * @return 返回字符串长度
 ************************************************************************/
int _ftoa(double val, char buf[32], int eps)
{
    double f = val;
    char *p = buf;
    if (val < 0)
    {
        *p++ = '-';
        f = -f;
    }
    int n = f;
    int len = _itoa(n, p);
    return len + __ftoa(f - n, p + len, eps);
}

/************************************************************************
 * @brief 浮点数转字符串:范围(-1, 1)
 * @param[in] val 浮点数
 * @param[out] buf 字符串
 * @param[in] eps 精度(小数位)
 * @return 返回字符串长度
 ************************************************************************/
int __ftoa(double val, char buf[32], int eps)
{
    double f = val;
    char *p = buf;
    static const char s[] = "0123456789";
    if (f < 0)
    {
        *p++ = '-';
        f = -f;
    }
    *p++ = '.';
    for (int i = eps + 1, n; --i; ++p, f -= n)
        *p = s[n = f *= 10.0];
    *p = 0;
    return p - buf;
}

/************************************************************************
 * @brief 替换sprintf
 * @ref 可变长参数列表误区与陷阱——va_arg不可接受的类型
 * http://www.cppblog.com/ownwaterloo/archive/2009/04/21/80655.aspx
 ************************************************************************/
int _sprintf(char *dst, const char *format, ...)
{
    char *s = dst;
    const char *f = format;
    va_list ap, another;
    va_start(ap, format);
    va_copy(another, ap);
    while (*f)
    {
        int n = 1;
        if ('%' != *f)
        {
            *s = *f;
        }
        else
        {
            ++f;
            switch (*f)
            {
            case 's': // 字符串
            {
                const char *p = va_arg(ap, char *);
                n = strlen(p);
                memcpy(s, p, n);
            }
            break;

            case 'd':
            case 'u': // 整数
            {
                char buf[32];
                n = _itoa(va_arg(ap, int), buf);
                memcpy(s, buf, n);
            }
            break;

            case 'f': // 浮点数
            {
                char buf[32];
                n = _ftoa(va_arg(ap, double), buf, 6);
                memcpy(s, buf, n);
            }
            break;

            case 'x': // 16进制数
            {
                char buf[32];
                n = _i2a(va_arg(ap, int), buf, 16);
                memcpy(s, buf, n);
            }
            break;

            case 'c': // 字符
            {
                *s = va_arg(ap, int);
            }
            break;

            case '%': // 百分号
            {
                *s = '%';
            }
            break;

            default:
            {
                va_end(ap);
                int x = vsprintf(dst, format, another);
                va_end(another);
                return x;
            }
            break;
            }
        }
        ++f;
        s += n;
    }
    *s = 0;
    va_end(ap);
    return s - dst;
}
uint8 bcc_chk(uint8 *data, uint16 length)
{
    uint8 bcc_chk_return = 0x00;
    uint16 count = 0;
    while (count < length)
    {
        bcc_chk_return ^= data[count];
        count++;
    }
    return bcc_chk_return;
}
uint16 crc_chk(uint8 *data, uint8 length)
{
    uint8 j;
    uint16 reg_crc = 0xFFFF;
    while (length--)
    {
        reg_crc ^= *data++;
        for (j = 0; j < 8; j++)
        {
            if (reg_crc & 0x01)
            {
                reg_crc = (reg_crc >> 1) ^ 0xA001;
            }
            else
            {
                reg_crc = reg_crc >> 1;
            }
        }
    }
    return reg_crc;
}