/*************
 fs_test.c
 SDK_LICENSE
***************/

#include "rom_sym_def.h"
#include "osal.h"
#include "crc16.h"
#include "fs.h"
#include "error.h"
#include "fs_test.h"
#include "clock.h"
#include "log.h"

#if (FS_TEST_TYPE == FS_MODULE_TEST)

#define FTST_MAX_FILE_CNT   256
#define FTST_MAX_FILE_SIZE  4095

typedef struct
{
    uint16_t fid;
    uint16_t fsize;
    uint16_t fcrc;
    uint16_t del_flg;//0: file exist; 1: file deleted
} ftst_t;

static ftst_t s_fpool[FTST_MAX_FILE_CNT];
static uint16_t s_ftst_fid_num = 0;
uint8_t s_ftst_buf[4095];

static void fstest_init(void)
{
    int i = 0;
    osal_memset((void*)s_fpool, 0, sizeof(s_fpool));
    osal_memset(s_ftst_buf, 0, sizeof(s_ftst_buf));
    s_ftst_fid_num = 0;

    for(i = 0; i< FTST_MAX_FILE_CNT; i++)
    {
        s_fpool[i].fid = 0xffff;
    }
}

uint16_t fstest_gen_new_fid(uint16_t fid_num_limit)
{
    uint16_t id;
    uint32_t i;
    bool new_flag = false;

    do
    {
        id = (uint16_t)osal_rand();
        new_flag = true;

        for(i = 0; i< s_ftst_fid_num; i++)
        {
            if((s_fpool[i].fid == id)&&(s_fpool[i].del_flg == false))
            {
                new_flag = false;
                break;
            }
        }
    }
    while(new_flag == false);

    if(s_ftst_fid_num >= fid_num_limit || s_ftst_fid_num >= FTST_MAX_FILE_CNT)
    {
        fid_num_limit = fid_num_limit>FTST_MAX_FILE_CNT ? FTST_MAX_FILE_CNT : fid_num_limit;
        id = id%s_ftst_fid_num;
        return s_fpool[id].fid;
    }

    if(id == 0xffff)
        id = id/2;

    return id;
}

static void fstest_gen_fsdata(ftst_t* pftst, uint16_t size_limit, uint16_t fid_num_limit)
{
    uint16_t size;
    uint16_t i;
    size_limit = size_limit >FTST_MAX_FILE_SIZE?FTST_MAX_FILE_SIZE:size_limit;
    size = 1+ osal_rand()%(size_limit-1);

    if(pftst->fid == 0xffff)
    {
        pftst->fid = fstest_gen_new_fid(fid_num_limit);
    }

    for(i = 0; i< size; i++)
    {
        s_ftst_buf[i] = (uint8_t)(osal_rand()&0xff);
    }

    pftst->del_flg = 0;
    pftst->fcrc = crc16(0, s_ftst_buf, size);
    pftst->fsize = size;
}


static uint16_t fstest_save_fsdata(ftst_t* pftst, uint16_t fid_num_limit)
{
    uint16_t i;
    fid_num_limit = (fid_num_limit > FTST_MAX_FILE_CNT )? FTST_MAX_FILE_CNT: fid_num_limit;

    for(i = 0; i< fid_num_limit; i++)
    {
        if(s_fpool[i].fid == pftst->fid)
        {
            s_fpool[i].del_flg = pftst->del_flg;
            s_fpool[i].fcrc = pftst->fcrc;
            s_fpool[i].fsize = pftst->fsize;
            return i;
        }

        if(s_fpool[i].fid == 0xffff)
        {
            s_fpool[i].fid = pftst->fid;
            s_fpool[i].del_flg = pftst->del_flg;
            s_fpool[i].fcrc = pftst->fcrc;
            s_fpool[i].fsize = pftst->fsize;
            s_ftst_fid_num++;
            return i;
        }
    }

    LOG("file count out of test range\n");
    //while(1);;;
    return 0xffff;
}

bool fstest_validate_fsdata(ftst_t* pftst)
{
    int i;
    int ret;
    uint16_t crc = 0;
    ftst_t* pft;

    if(pftst)
    {
        pft = pftst;
        ret = hal_fs_item_read(pft->fid, s_ftst_buf, pft->fsize, NULL);

        if(ret != 0)
        {
            LOG("ftest_validate_fsdata failed!,fid[0x%x], fsize[%d]\n", pft->fid, pft->fsize);
            //while(1);;;
            return FALSE;
        }

        crc = crc16(0, s_ftst_buf, pft->fsize);

        if(crc != pft->fcrc)
        {
            LOG("ftest_validate_fsdata CRC error!,fid[0x%x], fsize[%d]\n", pft->fid, pft->fsize);
            //while(1);;;
            return FALSE;
        }

        return TRUE;
    }

    for(i = 0; i< s_ftst_fid_num; i++)
    {
        pft = &(s_fpool[i]);

        if(pft->del_flg)
            continue;

        ret = hal_fs_item_read(pft->fid, s_ftst_buf, pft->fsize, NULL);

        if(ret != 0)
        {
            LOG("ftest_validate_fsdata failed!,fid[0x%x], fsize[%d]\n", pft->fid, pft->fsize);
            //hile(1);;;
            return FALSE;
        }

        crc = crc16(0, s_ftst_buf, pft->fsize);

        if(crc != pft->fcrc)
        {
            LOG("ftest_validate_fsdata CRC error!,fid[0x%x], fsize[%d]\n", pft->fid, pft->fsize);
            //while(1);;;
            return FALSE;
        }
    }

    return TRUE;
}

int fstest_del(void)
{
    int ret;
    uint32_t id_index;

    while(1)
    {
        id_index = osal_rand()%s_ftst_fid_num;

        if(s_fpool[id_index].del_flg == false)
        {
            break;
        }
    }

    ret = hal_fs_item_del(s_fpool[id_index].fid);

    if(ret == PPlus_SUCCESS)
    {
        s_fpool[id_index].del_flg = true;
        return PPlus_SUCCESS;
    }

    return PPlus_ERR_FATAL;
}

void ftcase_simple_write_test(void)
{
    int i;
    int iret;
    uint16_t index;
    char* str_result = "Skip";
    ftst_t ftst_item;
    bool error_flag = false;
    fstest_init();
    //if(PPlus_ERR_FS_CONTEXT == hal_fs_init(FS_OFFSET_ADDRESS,FS_SECTOR_NUM))
    {
        iret = hal_fs_format(FS_OFFSET_ADDRESS,FS_SECTOR_NUM);

        if(iret != PPlus_SUCCESS)
        {
            LOG("format error\n");

            while(1);
        }
    }
    str_result = "Success";

    for(i = 0; i < 20; i++)
    {
        ftst_item.fid = 0xffff;
        fstest_gen_fsdata(&ftst_item, 256, 0xffff);//size_limit fid_num_limit
        iret = hal_fs_item_write(ftst_item.fid,s_ftst_buf,ftst_item.fsize);

        if(iret != 0)
        {
            LOG("fs write error[%d], fid[0x%x], fsize[%d]\n",iret,ftst_item.fid,ftst_item.fsize);
            str_result = "FS data validation error";
            error_flag = true;
            //while(1);;;
            break;
        }

        index = fstest_save_fsdata(&ftst_item,256);

        if(index == 0xffff)
        {
            LOG("fs save error[%d], fid[0x%x], fsize[%d]\n",index, ftst_item.fid, ftst_item.fsize);
            str_result = "FS data validation error";
            error_flag = true;
            break;
        }

        if(fstest_validate_fsdata(NULL) == FALSE)
        {
            str_result = "FS data validation error";
            error_flag = true;
            break;
        }
    }

    LOG("fstest_simple_write_test %s\n", str_result);

    if(error_flag == true)
    {
        LOG("fs error!\n");

        while(1);;;
    }
}


void ftcase_write_del_test(void)
{
    int i;
    int iret;
    uint16_t index;
    uint32_t garbage_num = 0;
    char* str_result = "Skip";
    ftst_t ftst_item;
    bool error_flag = false;
    fstest_init();
    //if(PPlus_ERR_FS_CONTEXT == hal_fs_init(FS_OFFSET_ADDRESS,FS_SECTOR_NUM))
    {
        iret = hal_fs_format(FS_OFFSET_ADDRESS,FS_SECTOR_NUM);

        if(iret != PPlus_SUCCESS)
        {
            LOG("format error\n");

            while(1);
        }
    }
    str_result = "Success";

    for(i=0;; i++)
    {
        ftst_item.fid = 0xffff;
        fstest_gen_fsdata(&ftst_item, 256, 0xfffe);

        if(ftst_item.fsize > hal_fs_get_free_size())
        {
            LOG("test end!\n");
            break;
        }

        iret = hal_fs_item_write(ftst_item.fid, s_ftst_buf, ftst_item.fsize);

        if(iret != 0)
        {
            LOG("fs write error[%d], fid[0x%x], fsize[%d]\n", iret,ftst_item.fid, ftst_item.fsize);
            str_result = "FS data validation error";
            error_flag = true;
            break;
        }

        index = fstest_save_fsdata(&ftst_item, 256);

        if(index == 0xffff)
        {
            LOG("fs save error[%d], fid[0x%x], fsize[%d]\n", iret,ftst_item.fid, ftst_item.fsize);
            str_result = "FS data validation error";
            error_flag = true;
            break;
        }

        if(fstest_validate_fsdata(NULL) == FALSE)
        {
            str_result = "FS data validation error";
            error_flag = true;
            break;
        }

        if(((i%8)==0) && (i>0))
        {
            iret = fstest_del();

            if(iret != PPlus_SUCCESS)
            {
                str_result = "FS del error";
                error_flag = true;
            }
        }

        if(hal_fs_get_garbage_size(&garbage_num) > 256)
        {
            iret = hal_fs_garbage_collect();

            if(iret != PPlus_SUCCESS)
            {
                str_result = "FS compresss error";
                error_flag = true;
            }
            else
            {
                LOG("compress_ok\n");
            }
        }

        WaitMs(1);
    }

    LOG("ftcase_write_del_test %s\n", str_result);

    if(error_flag == true)
    {
        LOG("fs error!\n");

        while(1);;;
    }
}


void ftcase_write_del_and_ble_enable_test(void)
{
    static int i;
    int iret;
    uint16_t index;
    ftst_t ftst_item;
    bool error_flag = false;
    static bool firstFlag = true;
    uint32_t garbage_num = 0;

    if(firstFlag == true)
    {
        fstest_init();
        //if(PPlus_ERR_FS_CONTEXT == hal_fs_init(FS_OFFSET_ADDRESS,FS_SECTOR_NUM))
        {
            iret = hal_fs_format(FS_OFFSET_ADDRESS,FS_SECTOR_NUM);

            if(iret != PPlus_SUCCESS)
            {
                LOG("format error\n");

                while(1);
            }
        }
        firstFlag = false;
        i =0;
    }
    else
    {
        i++;
    }

    {
        ftst_item.fid = 0xffff;
        fstest_gen_fsdata(&ftst_item, 256, 0xfffe);

        if(ftst_item.fsize > hal_fs_get_free_size())
        {
            LOG("\nreinit_and_test:%d %d \n",ftst_item.fsize,hal_fs_get_free_size());
            firstFlag = true;
            return;
        }

        iret = hal_fs_item_write(ftst_item.fid, s_ftst_buf, ftst_item.fsize);

        if(iret != 0)
        {
            LOG("fs write error[%d], fid[0x%x], fsize[%d],%d\n", iret,ftst_item.fid, ftst_item.fsize);
            iret = hal_fs_item_write(ftst_item.fid, s_ftst_buf, ftst_item.fsize); //to debug
            error_flag = true;

            while(1);;;
        }

        index = fstest_save_fsdata(&ftst_item, 256);

        if(index == 0xffff)
        {
            LOG("fs save error[%d], fid[0x%x], fsize[%d]\n", iret,ftst_item.fid, ftst_item.fsize);
            error_flag = true;

            while(1);;;
        }

        if(fstest_validate_fsdata(NULL) == FALSE)
        {
            LOG("FS data validation error\n");
            error_flag = true;

            while(1);;;
        }

        if(((i%4)==0) && (i>0))
        {
            iret = fstest_del();

            if(iret != PPlus_SUCCESS)
            {
                LOG("FS del error\n");
                error_flag = true;

                while(1);;;
            }
            else
            {
                LOG(".");
            }
        }

        if(hal_fs_get_garbage_size(&garbage_num) > 1024)
        {
            iret = hal_fs_garbage_collect();

            if(iret != PPlus_SUCCESS)
            {
                LOG("FS compresss error,%d\n",iret);
                error_flag = true;

                while(1);
            }
            else
            {
                LOG("compress_ok\n");
            }
        }
    }

    if(error_flag == true)
    {
        LOG("fs error!\n");

        while(1);;;
    }
}

#elif (FS_TEST_TYPE == FS_EXAMPLE)


#include <string.h>
#define FS_HOLD  {LOG("line:%d\n",__LINE__);while(1);}

uint8_t id_buf[4095];
#define FS_ITEM_TEST2 127
void fs_example(void)
{
    int ret;
    uint32_t free_size;
    uint16 id = 1,id_len;
    uint16 i,file_len;
    static uint8_t testCase = 1;
    static uint8_t testCycle = 0;
    bool errFlag;
    uint32_t garbage_num = 0;

    if(testCycle >= 5)
    {
        LOG("fs example end!\n");
        return;
    }

    if(hal_fs_initialized() == FALSE)
    {
        ret = hal_fs_init(FS_OFFSET_ADDRESS,FS_SECTOR_NUM);

        if(PPlus_SUCCESS != ret)
        {
            LOG("error:%d\n",ret);
            FS_HOLD;
        }
    }

    osal_memset(id_buf,0x00,4095);

    for(i=0; i<4095; i++)
    {
        id_buf[i] = i%256;
    }

    switch(testCase)
    {
    case 1://write two files to fs,one is the mix length,one is the max length
    {
        LOG("\nfs_write................................................\n");
        free_size = hal_fs_get_free_size();
        LOG("free_size:%d\n",free_size);
        id = 1;
        id_len = 1;

        if(id_len < free_size)
        {
            ret = hal_fs_item_write(id,id_buf,id_len);

            if(PPlus_SUCCESS != ret)
            {
                LOG("error:%d\n",ret);
                FS_HOLD;
            }
            else
                LOG("write ok\n");
        }

        id = FS_ITEM_TEST2;
        id_len = FS_ITEM_TEST2;

        if(id_len < free_size)
        {
            ret = hal_fs_item_write(id,id_buf,id_len);

            if(PPlus_SUCCESS != ret)
            {
                LOG("error:%d\n",ret);
                FS_HOLD;
            }
            else
                LOG("write ok\n");
        }

        free_size = hal_fs_get_free_size();
        LOG("free_size:%d\n",free_size);
        //while(1);;;;;
        break;
    }

    case 2://read the two files
    {
        LOG("\nfs_read................................................\n");
        osal_memset(id_buf,0x00,1);
        id = 1;
        ret = hal_fs_item_read(id,id_buf,1,&file_len);

        if(PPlus_SUCCESS != ret)
        {
            LOG("error:%d\n",ret);
            FS_HOLD;
        }

        LOG("id:%d\n",id);
        LOG("id len:%d\n",file_len);
        LOG("id data:\n");
        errFlag = FALSE;

        for(i=0; i<file_len; i++)
        {
            if(id_buf[i] != i%256)
            {
                errFlag = TRUE;
                break;
            }
        }

        if(errFlag)
        {
            LOG("error\n");
            FS_HOLD;
        }
        else
            LOG("ok\n");

        osal_memset(id_buf,0x00,FS_ITEM_TEST2);
        id = FS_ITEM_TEST2;
        hal_fs_item_read(id,id_buf,FS_ITEM_TEST2,&file_len);

        if(PPlus_SUCCESS != ret)
            LOG("error:%d\n",ret);

        LOG("\nid:%d\n",id);
        LOG("id len:%d\n",file_len);
        LOG("id data:\n");
        errFlag = FALSE;

        for(i=0; i<file_len; i++)
        {
            if(id_buf[i] != i%256)
            {
                errFlag = TRUE;
                break;
            }
        }

        if(errFlag)
        {
            LOG("error\n");
            FS_HOLD;
        }
        else
            LOG("ok\n");

        break;
    }

    case 3://delete the two files
    {
        LOG("\nfs_delete................................................\n");
        LOG("free_size:%d\n",hal_fs_get_free_size());
        LOG("garbage_size:%d garbage_num:%d\n",hal_fs_get_garbage_size(&garbage_num),garbage_num);
        id = 1;
        ret = hal_fs_item_del(id);

        if(PPlus_SUCCESS != ret)
            LOG("error:%d\n",ret);
        else
        {
            LOG("ok\n");
            ret = hal_fs_item_read(id,id_buf,4095,&file_len);

            if(ret != PPlus_ERR_FS_NOT_FIND_ID)
            {
                LOG("error:%d\n",ret);
                FS_HOLD;
            }
        }

        id = FS_ITEM_TEST2;
        ret = hal_fs_item_del(id);

        if(PPlus_SUCCESS != ret)
        {
            LOG("error:%d\n",ret);
            FS_HOLD;
        }
        else
        {
            LOG("ok\n");
            ret = hal_fs_item_read(id,id_buf,FS_ITEM_TEST2,&file_len);

            if(ret != PPlus_ERR_FS_NOT_FIND_ID)
            {
                LOG("error:%d\n",ret);
                FS_HOLD;
            }
        }

        LOG("free_size:%d\n",hal_fs_get_free_size());
        LOG("garbage_size:%d garbage_num:%d\n",hal_fs_get_garbage_size(&garbage_num),garbage_num);
        break;
    }

    case 4://garbage collect
    {
        LOG("\nfs_garbage_collect................................................\n");
        LOG("free_size:%d\n",hal_fs_get_free_size());
        LOG("garbage_size:%d garbage_num:%d\n",hal_fs_get_garbage_size(&garbage_num),garbage_num);
        ret = hal_fs_garbage_collect();

        if(PPlus_SUCCESS != ret)
        {
            LOG("error:%d\n",ret);
            FS_HOLD;
        }

        LOG("free_size:%d\n",hal_fs_get_free_size());
        LOG("garbage_size:%d garbage_num:%d\n",hal_fs_get_garbage_size(&garbage_num),garbage_num);
        break;
    }

    default:
        break;
    }

    testCase++;

    if(testCase > 4)
    {
        testCase = 1;
        testCycle++;
        LOG("\nfs test cycle:%d................................................\n",testCycle);
    }
}

#elif (FS_TEST_TYPE == FS_TIMING_TEST)

#include "flash.h"
#define TOGGLE_GPIO GPIO_P14
uint8_t id_buf[4095];
void fs_timing_test(void)
{
    uint8_t testCase = 4,data_wr[4]= {0x12,0x34,0x56,0x78};
    uint16_t i,file_len;
    int ret;
    uint32_t garbage_size,garbage_num;
    hal_gpio_write(TOGGLE_GPIO,1);
    WaitMs(1);
    testCase = 9;

    switch(testCase)
    {
    case 0:
        hal_gpio_write(TOGGLE_GPIO,0);
        hal_flash_erase_sector(0x11005000);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        break;

    case 1:
        hal_gpio_write(TOGGLE_GPIO,0);
        hal_flash_write(0x1100500c,data_wr,4);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        break;

    case 2:
        hal_gpio_write(TOGGLE_GPIO,0);
        osal_memcpy((uint8_t*)id_buf,(uint8_t*)0x11005000,4);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        break;

    case 3:
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_format(0x11005000,3);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);

        if(ret != PPlus_SUCCESS)
        {
            LOG("ret:%d",ret);
        }

        break;

    case 4:
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_init(0x11005000,3);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);

        if(ret != PPlus_SUCCESS)
        {
            LOG("ret:%d",ret);
        }

        ret = hal_fs_item_write(1,id_buf,1);
        ret = hal_fs_item_write(2,id_buf,2);
        ret = hal_fs_item_write(3,id_buf,3);
        ret = hal_fs_item_write(4,id_buf,4);
        ret = hal_fs_item_write(5,id_buf,5);
        ret = hal_fs_item_write(6,id_buf,6);
        ret = hal_fs_item_write(7,id_buf,7);
        ret = hal_fs_item_write(8,id_buf,8);
        ret = hal_fs_item_write(9,id_buf,9);
        ret = hal_fs_item_write(10,id_buf,10);
        WaitMs(1);
        break;

    case 5:
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_init(0x11005000,3);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);

        if(ret != PPlus_SUCCESS)
        {
            LOG("ret:%d",ret);
        }

        break;

    case 6:
        LOG("write file\n");

        for(i=0; i<4095; i++)
            id_buf[i] = (i+1)%256;

        ret = hal_fs_format(0x11005000,3);

        if(ret != PPlus_SUCCESS)
        {
            LOG("ret:%d",ret);
        }

        WaitMs(1);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_write(1,id_buf,1);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(5);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_write(2,id_buf,100);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(5);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_write(3,id_buf,100);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(5);
        break;

    case 7:
        LOG("read file\n");
        ret = hal_fs_init(0x11005000,3);
        WaitMs(1);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_read(1,id_buf,4095,&file_len);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        LOG("ret:%d",ret);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_read(2,id_buf,4095,&file_len);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        LOG("ret:%d",ret);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_read(3,id_buf,4095,&file_len);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        LOG("ret:%d",ret);
        break;

    case 8:
        LOG("del file\n");
        ret = hal_fs_init(0x11005000,3);
        WaitMs(1);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_del(1);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        LOG("ret:%d",ret);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_item_del(2);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        LOG("ret:%d",ret);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret =hal_fs_item_del(3);
        hal_gpio_write(TOGGLE_GPIO,1);
        WaitMs(1);
        LOG("ret:%d",ret);
        break;

    case 9:
        LOG("garbage calc and collect\n");
        ret = hal_fs_init(0x11005000,3);

        if(ret != PPlus_SUCCESS)
        {
            LOG("hal_fs_init error:%d\n",ret);
        }

        WaitMs(5);
        hal_gpio_write(TOGGLE_GPIO,0);
        garbage_size = hal_fs_get_garbage_size(&garbage_num);
        hal_gpio_write(TOGGLE_GPIO,1);
        LOG("garbage_num:%d garbage_size:%d\n",garbage_num,garbage_size);
        WaitMs(5);
        hal_gpio_write(TOGGLE_GPIO,0);
        ret = hal_fs_garbage_collect();
        hal_gpio_write(TOGGLE_GPIO,1);

        if(ret != PPlus_SUCCESS)
        {
            LOG("hal_fs_garbage_collect error:%d\n",ret);
        }

        WaitMs(5);
        break;

    default:
        break;
    }

    while(1);;;
}

#elif (FS_TEST_TYPE == FS_XIP_TEST)

#include "flash.h"

#define FS_LOG LOG
//#define FS_DBG_EN
/*
    test flash api:
    int hal_flash_erase_sector(unsigned int addr)
    int hal_flash_write(uint32_t addr, uint8_t* data, uint32_t size)
    int hal_flash_read(uint32_t addr, uint8_t *data, uint32_t size)

    test config:
    #define MIN_WR_SIZE 4
    #define MIN_RD_SIZE 4
*/
extern  const unsigned char c_data_wr[4096];
unsigned char c_data_rd[4096];
#define FS_RET_RRROR(ret) \
    if(ret!= PPlus_SUCCESS) \
    { \
        LOG("err:%d %d",ret,__LINE__); \
        while(1); \
    }

#define MIN_WR_SIZE 4
#define MIN_RD_SIZE 4
/*
    erase sector
    write 4096
    read 4096
    write 4092 4
    read 4092  4
    ...
    write 2048 2048
    read 2048 2048
*/
//#define DBG_IO_TOGLE(a,b)           do{ for(int i=0;i<b;i++){gpio_write(a,1);gpio_write(a,0);}}while(0);

#define XIP_TIMING     0
#define XIP_FUNCTION   1
#define XIP_TEST_TYPE  XIP_FUNCTION

//#define FS_DBG_EN

void fs_xip_test(void)
#if(XIP_TEST_TYPE == XIP_TIMING)
{
    const uint32_t sector_addr = 0x1103f000;
    uint32_t wr_data_len = 0;
    uint8_t* const p_wr = (uint8_t*)c_data_wr;
    uint8_t* const p_rd = (uint8_t*)c_data_rd;
    volatile int ret0,ret1,ret2;
    #ifdef FS_DBG_EN
    FS_LOG("xip test start:\n");
    FS_LOG("use how long when erase,write,read a sector\n");
    FS_LOG("please make fs_test.c runs on flash\n");
    #endif
    {
        AP_GPIO->swporta_dr |= BIT(P11);//output=1
        AP_GPIO->swporta_ddr |= BIT(P11);//set output
        AP_GPIO->swporta_dr |= BIT(P14);//output=1
        AP_GPIO->swporta_ddr |= BIT(P14);//set output
        AP_GPIO->swporta_dr &= ~BIT(P14);
        AP_GPIO->swporta_dr &= ~BIT(P11);
        {
            ret0 = hal_flash_erase_sector(sector_addr);
        }
        AP_GPIO->swporta_dr |= BIT(P11);
        AP_GPIO->swporta_dr &= ~BIT(P11);
        {
            ret1 = hal_flash_write(sector_addr,p_wr,4096-wr_data_len);
        }
        AP_GPIO->swporta_dr |= BIT(P11);
        AP_GPIO->swporta_dr &= ~BIT(P11);
        {
            ret2 = hal_flash_read(sector_addr,p_rd,4096);
        }
        AP_GPIO->swporta_dr |= BIT(P11);
        AP_GPIO->swporta_dr |= BIT(P14);
        #ifdef FS_DBG_EN
        FS_LOG("xip test end:%d %d %d\n",ret0,ret1,ret2);
        #endif

        while(1);
    }
}

#elif (XIP_TEST_TYPE == XIP_FUNCTION)
{
    const uint32_t sector_addr = 0x1103f000;
    uint32_t i=0,j=0,run_counter = 0;
    uint32_t wr_data_len = 0,rd_data_len = 0;
    uint8_t* const p_wr = (uint8_t*)c_data_wr;
    uint8_t* const p_rd = (uint8_t*)c_data_rd;
    int ret;
    #ifdef FS_DBG_EN
    FS_LOG("\nc_data_wr:%x\n",(uint32_t*)c_data_wr);

    for(j=0; j<4096; j++)
    {
        FS_LOG("0x%x,",*(p_wr+j));

        if((j+1)%0x10==0)
        {
            FS_LOG("\n");
        }
    }

    FS_LOG("\nend\n");
    #endif

    while(1)
    {
        #ifdef FS_DBG_EN
        FS_LOG("wr len:%d rd_len:%d\n",wr_data_len,rd_data_len);
        #endif
        FS_LOG("erase:");
        hal_flash_erase_sector(sector_addr);

        for(i=sector_addr; i<(sector_addr+4096); i+=MIN_RD_SIZE)
        {
            ret = hal_flash_read(i,p_rd,MIN_RD_SIZE);
            FS_RET_RRROR(ret);

            for(j=0; j<4; j++)
            {
                if(*(p_rd+j) != 0xFF)
                {
                    FS_LOG("erase! :l:%d 0x%x 0x%x 0x%x\n",__LINE__,i,j,*(p_rd+j));

                    while(1);
                }
            }
        }

        FS_LOG("wr:");

        for(i=0; i<2; i++)
        {
            if(i==0)
            {
                ret = hal_flash_write(sector_addr,p_wr,4096-wr_data_len);
            }
            else
            {
                ret = hal_flash_write((sector_addr+4096-wr_data_len),p_wr,wr_data_len);
            }

            FS_RET_RRROR(ret);

            if(wr_data_len == 0)
                break;
        }

        FS_LOG("rd:");

        for(i=0; i<2; i++)
        {
            for(j=0; j<4096; j++)
            {
                c_data_rd[j]=0;
            }

            if(i == 0)
            {
                ret = hal_flash_read(sector_addr,p_rd,4096-rd_data_len);
                #ifdef FS_DBG_EN
                FS_LOG("\ndbg_start:0x%x %d\n",sector_addr,(4096-rd_data_len));

                for(j=0; j<4096-rd_data_len; j++)
                {
                    FS_LOG("0x%x,",*(p_rd+j));

                    if((j+1)%0x10==0)
                    {
                        FS_LOG("\n");
                    }
                }

                FS_LOG("\ndbg_end\n");
                #endif
            }
            else
            {
                ret = hal_flash_read((sector_addr+4096-rd_data_len),p_rd,rd_data_len);
                #ifdef FS_DBG_EN
                FS_LOG("\ndbg_start:0x%x %d\n",(sector_addr+4096-rd_data_len),(rd_data_len));

                for(j=0; j<rd_data_len; j++)
                {
                    FS_LOG("0x%x,",*(p_rd+j));

                    if((j+1)%0x10==0)
                    {
                        FS_LOG("\n");
                    }
                }

                FS_LOG("\ndbg_end\n");
                #endif
            }

            FS_RET_RRROR(ret);

            if(i == 0)
            {
                for(j=0; j<4096-rd_data_len; j++)
                {
                    if(*(p_rd+j) != *(p_wr+j))
                    {
                        FS_LOG("addr:0x%x 0x%x 0x%x l:%d\n",(sector_addr+j),*(p_rd+j),*(p_wr+j),__LINE__);

                        while(1);
                    }
                }
            }
            else
            {
                for(j=0; j<rd_data_len; j++)
                {
                    if(*(p_rd+j) != *(p_wr+j))
                    {
                        FS_LOG("addr:0x%x 0x%x 0x%x l:%d\n",(sector_addr+4096-rd_data_len+j),*(p_rd+j),*(p_wr+j),__LINE__);

                        while(1);
                    }
                }
            }

            if(rd_data_len == 0)
                break;
        }

        wr_data_len += MIN_WR_SIZE;
        rd_data_len += MIN_RD_SIZE;
        run_counter += 1;
        FS_LOG("\nrun_counter:%d\n",run_counter);

        //if(wr_data_len > 0)
        //if(wr_data_len > 4)
        if(wr_data_len > 40)
            //if(wr_data_len > 2048)//run_counter=513
            //if(wr_data_len > 4092)//run_counter=1024
        {
            FS_LOG("finish,ok\n");

            while(1);;;
        }
    }
}

#endif

const unsigned char c_data_wr[4096]=
{
    0xa2,0x9f,0x39,0x21,0xc7,0x69,0x87,0x43,0x4e,0x9c,0x2,0x97,0xb8,0x2f,0x1d,0x1,
    0x24,0x30,0xac,0xec,0x94,0xba,0xd0,0xdc,0x3c,0x9a,0xb6,0xd4,0xeb,0xcc,0xc9,0xc5,
    0x9,0x21,0x78,0xd6,0xb1,0xe8,0x1b,0x7,0xaa,0xa2,0xce,0xa9,0xd6,0xda,0x1b,0x65,
    0xc,0xcc,0xc7,0xbb,0x11,0x8a,0x54,0x6f,0x86,0x79,0x4a,0x6a,0x5d,0x45,0x2c,0x1c,
    0x95,0xb2,0xcd,0xdf,0xe2,0xbf,0x9c,0x53,0x72,0xb5,0xa3,0x9a,0xe6,0x3e,0x6c,0x37,
    0xf0,0xfa,0xf7,0xdc,0xde,0xc6,0x3e,0x8,0xfd,0x4a,0xc4,0x7e,0x11,0xad,0x95,0x8f,
    0x2e,0x31,0x34,0x36,0xc3,0x4c,0xc2,0x2f,0x30,0x4c,0xf5,0x83,0x59,0x38,0xd4,0x54,
    0x33,0xac,0x26,0x50,0xb8,0x8f,0xe3,0x29,0xf6,0x3,0xbf,0x31,0x2,0x5,0xe4,0x87,
    0x96,0xd2,0x8a,0x32,0x28,0x7e,0xa0,0x38,0xf,0x8,0xe8,0x89,0xff,0x9c,0xda,0x30,
    0xe7,0x82,0x41,0x73,0x5a,0x1d,0xdf,0xcf,0x6e,0xa2,0x2d,0x8f,0x83,0xb1,0xba,0x16,
    0xaf,0xe3,0xa0,0x29,0xf0,0x8c,0x21,0x9b,0x7e,0xe3,0x3a,0xca,0xef,0x90,0xc9,0x4f,
    0xec,0xcd,0x24,0x44,0x1f,0x54,0x44,0xd8,0xec,0x57,0x7,0xc8,0x81,0x97,0x63,0x38,
    0xbd,0x74,0xa6,0x3c,0xc5,0x3f,0xd5,0xe5,0x15,0x82,0xf7,0xba,0xe4,0x3e,0x9e,0x99,
    0xb3,0xaa,0x1d,0x79,0xc9,0x25,0xd6,0x30,0xca,0x6c,0x8b,0x1e,0x29,0x2,0xa1,0x31,
    0x73,0xff,0x4e,0x63,0x5b,0x57,0xd7,0xc6,0xa8,0x7,0xd,0xb0,0xa2,0x52,0x44,0xd9,
    0xf,0x46,0x8a,0x81,0x3a,0x7f,0xf7,0x8,0x1f,0x93,0x8b,0xb8,0x9c,0x67,0x86,0xa4,
    0x9b,0xbb,0x16,0xfe,0xf6,0x6f,0xae,0x64,0x94,0xcd,0x90,0x9b,0xcb,0x40,0xd0,0x92,
    0x1e,0x2f,0x5f,0x2,0xc6,0x6d,0x5,0xfa,0x1,0x8f,0x41,0xf5,0xea,0x81,0x7b,0x56,
    0x53,0x85,0xd2,0x28,0x90,0x47,0x24,0xe2,0x59,0xe8,0x8a,0x48,0xd1,0x4a,0x8d,0x8e,
    0x51,0x3b,0x9,0x9f,0xc9,0x30,0x84,0xb9,0x74,0x63,0x63,0x3b,0x26,0x9b,0x60,0x91,
    0xb7,0x18,0xbf,0x10,0x9,0xa0,0x43,0xa6,0x71,0x74,0x9a,0xcf,0x89,0x97,0x6e,0x13,
    0xf5,0x93,0xf5,0xc9,0x39,0xfe,0xf7,0x14,0x61,0x72,0x4b,0x5d,0x69,0x22,0x71,0xb3,
    0xbf,0x68,0xd8,0xde,0xaa,0xd2,0xc5,0x82,0x98,0x38,0x86,0x24,0xd7,0xe4,0x7f,0x7b,
    0xed,0x52,0x2f,0xc6,0x64,0x62,0x23,0x25,0x4a,0x17,0xf8,0x83,0xdc,0x18,0x8a,0xb2,
    0xe0,0x23,0xcd,0x5f,0x34,0x5e,0xa2,0x0,0x5d,0xbc,0xc8,0x11,0x8f,0xd8,0x3c,0x8b,
    0x37,0x11,0x7b,0xbf,0x18,0x60,0x2b,0xdb,0x8c,0x5a,0x3b,0x19,0x2b,0x42,0xb4,0xe3,
    0x96,0x9d,0xe,0xdc,0x50,0x54,0x46,0xc1,0x43,0x41,0xb4,0x68,0x8b,0xa2,0x3,0x6a,
    0xaf,0x4b,0xf,0x85,0x39,0xbb,0x74,0x75,0x11,0xa6,0x58,0x76,0xda,0x8a,0x5c,0x31,
    0xb0,0x6e,0xee,0xb7,0x58,0xd,0xf1,0xf6,0xe0,0x1c,0xb5,0xf2,0x5c,0x92,0xdb,0xee,
    0x32,0x57,0xf2,0x5b,0x16,0xd7,0x97,0xa9,0xce,0xe0,0x14,0xd8,0xc,0x66,0x2a,0xac,
    0xfe,0x42,0xd9,0xd0,0x48,0x2c,0x74,0xfb,0xb0,0x37,0x13,0xe6,0x55,0xbd,0x17,0x51,
    0x6f,0x88,0xa5,0x65,0x3d,0x2f,0x6a,0x34,0x85,0x1d,0x6a,0xe4,0x8,0x46,0xe2,0x27,
    0x11,0x4b,0x47,0x7f,0xd3,0xc6,0x5f,0xbf,0x74,0x80,0xcc,0xde,0x98,0x1a,0xf1,0xd3,
    0xdd,0x1c,0x89,0xc,0xfd,0x15,0xcc,0x64,0x3c,0xf4,0xe,0xf3,0x39,0x1c,0x2c,0xe1,
    0x84,0x5e,0xfe,0x5c,0xe4,0x5d,0x3e,0xc5,0xf1,0xda,0xd3,0xa4,0x66,0x28,0xe,0x78,
    0x9d,0x8e,0x67,0xe0,0x43,0xcb,0x3c,0xd5,0xf1,0x10,0x48,0x63,0xb3,0x76,0xd6,0x22,
    0xd9,0x2a,0xc7,0x7d,0x7f,0xef,0x2e,0xb4,0xb9,0xb,0xff,0x65,0xab,0x90,0x31,0x85,
    0x2d,0x61,0x41,0x21,0xd4,0xdd,0xac,0x94,0xb2,0x9b,0x21,0x1c,0xcd,0xda,0xe2,0x3e,
    0x83,0xf1,0x3,0x4b,0x58,0x17,0x7f,0x92,0xb8,0x2a,0xe,0x79,0xb4,0x4e,0x52,0x46,
    0x8b,0xdd,0xf,0xe5,0x9f,0x4a,0x33,0x82,0x5e,0xf6,0x6d,0xe5,0xe6,0x8d,0x20,0xf5,
    0xdc,0x9f,0xb8,0x89,0x8e,0x32,0x32,0xb3,0x7d,0x57,0x43,0xc2,0xa0,0xf4,0x87,0x2,
    0x1a,0xc9,0x45,0x45,0x73,0xb6,0x49,0x5f,0x13,0xd0,0xa2,0xb8,0x7e,0x3a,0x6c,0x89,
    0x32,0x97,0x38,0x67,0x5f,0x29,0xf3,0x8d,0x76,0x22,0x9d,0x3e,0x29,0x56,0xeb,0x14,
    0x4,0xe,0x7e,0x66,0xde,0xc3,0x82,0x10,0xe1,0xc1,0x4a,0x79,0xf0,0xca,0x9b,0x2b,
    0x9d,0x88,0x40,0xe5,0x8,0xe,0x63,0x2d,0x14,0x88,0x16,0x9f,0x13,0xb,0x8d,0x27,
    0x80,0xee,0xb7,0x3c,0x68,0xd9,0xe8,0xf1,0xb8,0x84,0x23,0x18,0x25,0x30,0x34,0xf0,
    0x8,0x43,0x42,0x3,0x5f,0x8d,0x31,0x1e,0x92,0x7d,0x16,0x98,0x6f,0x77,0xef,0xdb,
    0xee,0x8b,0xca,0xb6,0x37,0x11,0x4d,0xad,0xd3,0x47,0x7f,0xc9,0xab,0x2d,0xd5,0x77,
    0x10,0x12,0x50,0x15,0x41,0x3a,0x8d,0xe6,0xbc,0x2b,0x90,0x76,0x84,0x9c,0xae,0x3b,
    0xe7,0x2,0xf3,0x71,0x1d,0x4c,0x98,0x97,0xfd,0x86,0x46,0xb1,0xd2,0x4f,0x94,0x5e,
    0xfc,0xf4,0x23,0x95,0x1f,0x2e,0xd8,0x22,0x62,0xb2,0xb3,0x7,0xba,0xb7,0xdf,0xe,
    0x28,0xfa,0xc2,0x54,0x21,0xf2,0x19,0x38,0x7b,0x21,0xa1,0xb1,0xd0,0xa7,0xeb,0xb5,
    0xcc,0xae,0xb7,0xaf,0x6b,0x60,0x46,0x3a,0x30,0x4d,0x40,0x91,0xf,0x3a,0x56,0x37,
    0x8a,0x31,0x30,0x77,0xd,0xb0,0x5c,0x30,0x7a,0x54,0x78,0xf7,0x93,0x10,0x1e,0xe9,
    0x2f,0xcf,0x21,0xfa,0x81,0x63,0xfb,0xbc,0x7d,0x3b,0xb3,0x56,0x5e,0x76,0xc2,0x2d,
    0x4,0x21,0x37,0xd4,0xc5,0x4a,0xd6,0xb6,0xec,0x3c,0x5c,0xd3,0x9,0x22,0x53,0xdc,
    0x8,0xb2,0x26,0x66,0x47,0xba,0x68,0xa5,0x19,0xac,0x78,0x79,0x78,0x58,0x72,0x9d,
    0xa5,0x11,0xae,0xdb,0xe,0x3a,0x6e,0x1a,0x5,0xf1,0x60,0x29,0x69,0x51,0xe5,0xb4,
    0x8a,0xdd,0x68,0x3,0x41,0xe7,0xbd,0xba,0x65,0xde,0xd6,0x57,0x35,0xdf,0x42,0x7f,
    0x25,0xcf,0x55,0x19,0x19,0xea,0x99,0xeb,0xe8,0x26,0xbe,0xa4,0xa4,0x4f,0xfd,0xb7,
    0x4e,0x4,0x9d,0x1f,0x68,0x9,0xe6,0x71,0x1d,0x60,0x26,0xf9,0xc4,0xab,0x85,0xcf,
    0xf4,0x32,0x4a,0xb5,0x1,0x4e,0x80,0x7,0x9a,0x55,0x35,0x7b,0x8b,0x2e,0xb3,0xf0,
    0x21,0xb4,0xbc,0x9e,0x48,0x87,0x28,0x41,0xe8,0x8f,0x79,0xfd,0x63,0x65,0x87,0x9a,
    0x45,0xb,0x11,0xca,0xab,0x3e,0x5d,0x8d,0xa0,0x8b,0x2a,0xda,0x9f,0xa4,0xd2,0xb3,
    0xe4,0xcc,0xf8,0x65,0xf6,0x1e,0xd5,0xa0,0x9b,0x40,0xb8,0xb1,0x97,0xd6,0x7f,0xa9,
    0xf8,0x51,0x93,0xcc,0x14,0x4d,0xb8,0x66,0x8e,0x36,0x7,0xcb,0xc5,0x3a,0xd1,0x15,
    0x1b,0x6e,0xeb,0xed,0x62,0xae,0x49,0xe7,0x18,0x50,0x89,0xc0,0x74,0x6e,0xdb,0x2b,
    0x91,0xab,0x78,0x2e,0xc5,0x6a,0x62,0x8a,0x5d,0xff,0x48,0x55,0xa8,0xc2,0x6b,0xdb,
    0x4e,0x4f,0x6a,0xe,0xda,0x2e,0x60,0x51,0x4f,0x2b,0x14,0x28,0x1b,0xc6,0xc9,0x45,
    0xe9,0x42,0x6e,0xb6,0xbc,0x3e,0xdd,0x1b,0x6,0xfb,0x76,0x5,0x9,0x45,0x98,0xdc,
    0xc1,0x4,0xc4,0xec,0x57,0x7d,0x57,0x59,0xc,0x40,0x85,0xa2,0xaa,0xce,0x8f,0x5,
    0x77,0xda,0xe3,0x63,0x4e,0x48,0x55,0x4b,0x6e,0x3f,0x3d,0xfd,0x86,0x65,0x6,0x7a,
    0xf6,0x65,0xc3,0x4f,0x59,0xd1,0xca,0x7b,0xd8,0xc,0x4a,0xb6,0x37,0x5b,0xff,0x60,
    0x3d,0xe4,0x5b,0x10,0x22,0xdb,0x11,0xc2,0x9b,0x47,0xa,0xf2,0x9e,0xa6,0x70,0xc2,
    0x13,0x3,0x66,0x7e,0x0,0xe6,0xc4,0xc8,0x6d,0x7a,0x81,0x63,0x30,0x3b,0x72,0xe2,
    0x46,0xab,0x9f,0x19,0x28,0x44,0x87,0x19,0x96,0xdf,0xee,0xac,0x47,0x4d,0xe8,0x35,
    0x93,0xf,0xda,0x37,0xf7,0x2a,0x6,0xc1,0xca,0x75,0xde,0xcd,0xae,0x7d,0x72,0x9f,
    0x4d,0xa9,0x1f,0x91,0xd6,0x93,0x9c,0xbd,0x5f,0x69,0x9a,0x40,0xb4,0x10,0xf3,0x20,
    0x52,0x49,0x86,0x85,0x65,0x37,0x1a,0xd4,0x3f,0xd8,0xaa,0xff,0x16,0x98,0x8c,0x4e,
    0x68,0x4,0xb1,0x88,0x6b,0x7b,0xa7,0x68,0x18,0x4b,0xba,0x83,0x16,0x7d,0x6c,0x7f,
    0x9a,0x5c,0x87,0x25,0x6e,0x6e,0xf5,0xb2,0x2f,0xea,0x5d,0x15,0x9b,0x45,0xe4,0xb1,
    0xd,0x3f,0x78,0x2f,0x2,0x23,0xb5,0x1a,0xa0,0xf,0x56,0xb2,0x82,0x3d,0x8e,0xfd,
    0xf1,0xc4,0x8e,0xd5,0x5b,0xfe,0xc5,0x8f,0xbd,0x12,0x97,0xa4,0x2,0xf,0x8d,0x26,
    0x93,0x1d,0x76,0xf5,0x39,0x1f,0x52,0x9b,0xe1,0x84,0x14,0x2,0x11,0xa8,0xa8,0xf4,
    0x57,0xcc,0x3b,0xd7,0xf,0xbf,0x10,0xf3,0xa,0xb5,0xcd,0x8f,0xd1,0xe3,0xf5,0x71,
    0xa3,0xd4,0x36,0xa1,0xd2,0xa1,0x6f,0x5c,0x98,0xa1,0x94,0x1d,0x6,0x34,0x43,0xdc,
    0x5f,0x7a,0x9,0x4,0x36,0xe6,0x41,0xa5,0x65,0xf2,0x17,0xc2,0xea,0x74,0x82,0xe6,
    0xf9,0xe6,0xfe,0x84,0xcb,0x84,0x58,0xd2,0x99,0x7e,0xdd,0xba,0x9e,0xe7,0xa2,0x79,
    0x60,0x22,0x81,0xea,0xbe,0xbe,0x76,0xc4,0x76,0xe,0xcd,0x25,0x3,0x44,0xbf,0x72,
    0xa4,0x94,0xb2,0x2d,0xb6,0x13,0xa3,0x45,0x3f,0x7e,0x29,0xf4,0xca,0x43,0xaa,0x2f,
    0x3c,0x9d,0xee,0x2f,0x71,0xb9,0x17,0xd5,0x29,0xd8,0xf1,0xb,0xbf,0xa1,0x87,0xf,
    0x95,0x87,0x64,0x5c,0x8,0xf6,0x11,0xd5,0x46,0x31,0xeb,0x8,0xa0,0x3c,0xb7,0x63,
    0x91,0x2,0x50,0x2b,0x88,0x1c,0x49,0x92,0xcd,0xbb,0xac,0x1f,0xa0,0xe,0xdd,0x35,
    0x95,0xb4,0x88,0x18,0x31,0x3f,0x2c,0x15,0xbe,0xaa,0x53,0xdf,0xb2,0x4,0x1a,0xbd,
    0x6a,0xc7,0x6d,0x96,0x3a,0x29,0x9d,0xc7,0x23,0x5a,0xa0,0xc7,0x9b,0xd1,0x66,0x2,
    0x1f,0x30,0x1,0x53,0xc0,0xc3,0xce,0x8f,0xf5,0xf1,0x75,0xb1,0xc1,0xb2,0xb6,0x84,
    0x96,0x45,0xd4,0xc5,0xf,0x12,0x3f,0x1a,0x97,0xda,0xfd,0xc2,0x50,0xf5,0xbf,0x42,
    0x68,0xab,0x8d,0xf1,0xc8,0x8e,0x62,0x92,0x3f,0x53,0xd8,0x1b,0xdd,0xf,0x97,0x7,
    0x43,0x80,0x47,0xfd,0x7,0x40,0x27,0xbf,0x22,0xba,0xf0,0xb9,0x6e,0x63,0x45,0x98,
    0x5d,0x7,0x63,0xd2,0x5c,0xf9,0x91,0x66,0xe6,0xe6,0xfe,0x8e,0x69,0x40,0xd1,0xa8,
    0x58,0x1d,0x46,0xaf,0xeb,0x54,0xe7,0x34,0x89,0x92,0x96,0x9f,0x2e,0x1b,0xb7,0x4b,
    0xeb,0x84,0xf8,0xc9,0xae,0xa8,0x71,0xc4,0x65,0x90,0x94,0xc4,0x8d,0x70,0x81,0x87,
    0x6c,0x51,0x8d,0xdc,0x20,0xa2,0xae,0x99,0xd6,0x94,0x2b,0x38,0xab,0x88,0xa3,0xea,
    0x89,0x91,0x86,0xb8,0x89,0xef,0xac,0x55,0x92,0xd0,0x3f,0xc5,0x7,0x4e,0xa2,0x72,
    0xc8,0x73,0xf9,0x14,0xd8,0x43,0xf6,0xb0,0x82,0xe8,0x79,0x15,0xbd,0x20,0x25,0xe7,
    0xb2,0x33,0xdc,0x1d,0x73,0x31,0x87,0xfd,0x3c,0xda,0xdd,0xb9,0xc,0x7d,0xd2,0x97,
    0x27,0x21,0xa8,0x21,0xa2,0x55,0x4a,0x14,0xb,0xd,0xc8,0x96,0xf4,0x23,0x93,0xee,
    0xb9,0xd3,0x19,0x8c,0x7a,0xe1,0x1,0x68,0xee,0x5e,0x50,0x8,0xed,0x8a,0x1c,0x2b,
    0xab,0x4d,0xfd,0x7b,0xa,0x3e,0xe5,0x55,0x7,0x67,0x83,0x95,0x9f,0x4b,0x71,0x38,
    0x92,0x5a,0xdc,0xb5,0x21,0xa4,0x19,0xac,0x8a,0x60,0xdf,0x7c,0x1b,0x65,0xf6,0x64,
    0x6f,0x28,0x91,0x2c,0x32,0x59,0xb8,0xac,0x4a,0x38,0x27,0x83,0x58,0xd4,0xd4,0x1d,
    0xcf,0x58,0x14,0x26,0xe3,0x3e,0xf2,0xb3,0x20,0xae,0xf3,0x73,0xcd,0x6f,0x87,0xc7,
    0x78,0x10,0xb8,0x22,0xa4,0x89,0x6c,0x71,0x31,0xec,0x1e,0xe8,0x66,0x81,0x6a,0x6c,
    0xd6,0xcd,0xa3,0x3d,0xe6,0xb4,0x2e,0x93,0x4d,0xd0,0xed,0xf2,0xb1,0x73,0x95,0x4e,
    0x46,0x20,0x68,0x90,0x20,0xfa,0x25,0xf2,0x64,0x23,0xe4,0x9,0x90,0x96,0xc1,0xff,
    0x3c,0x71,0x74,0x23,0xcf,0xd5,0x86,0x32,0xd,0xb9,0x2d,0xe6,0x1d,0x6f,0xd2,0xd0,
    0x7a,0xb,0x62,0x7b,0xc7,0xa2,0xc8,0x6e,0x3e,0x9d,0x3b,0xa1,0xae,0x83,0x7d,0x62,
    0xb,0x43,0x43,0x9c,0x75,0xd5,0xe0,0x2f,0xb8,0x9c,0x58,0x5b,0x82,0x1e,0x20,0x88,
    0x4f,0x66,0x55,0x2b,0x31,0x8,0x3b,0x42,0xb6,0xea,0xec,0x75,0xe0,0xb9,0x2b,0xc5,
    0xec,0xf0,0x3b,0xdc,0x92,0xed,0x2e,0x51,0xf8,0xd6,0x9b,0xfd,0x6,0x47,0x8b,0xcc,
    0x6a,0xb5,0x3f,0x7c,0xba,0xe9,0x17,0x9c,0xb5,0xb7,0x29,0x2d,0xd,0xd0,0x47,0x59,
    0x3e,0x49,0x6b,0x45,0xdf,0xe8,0x25,0x97,0x9e,0x77,0x67,0x55,0xc7,0xec,0x70,0x98,
    0x4b,0xbe,0xad,0x40,0xf,0xd,0x37,0xd1,0xb9,0x97,0x76,0xb2,0xbe,0xb7,0x3a,0x16,
    0x2c,0x33,0xab,0x14,0xd7,0x98,0x5a,0xa0,0x4f,0xa1,0xc4,0xc7,0xea,0x37,0x27,0x32,
    0xb5,0xb4,0x96,0x7e,0x46,0x24,0x6f,0x39,0x8b,0x4f,0x47,0x64,0x3f,0xa6,0x59,0x2e,
    0xac,0xcb,0xd7,0x2f,0xde,0x4f,0xd3,0xbb,0x3c,0x10,0xaf,0xd1,0xf4,0x63,0x5d,0x85,
    0xce,0x4c,0x1c,0x2f,0xb2,0x51,0xf,0xeb,0x9a,0x80,0x53,0x7,0x14,0xb5,0x4f,0x66,
    0xd9,0x92,0xd9,0x37,0x53,0x69,0xae,0x15,0x3e,0x7a,0x7a,0xe9,0xa2,0x8c,0x1d,0xbd,
    0x9e,0x7b,0xf5,0x8,0x5c,0xe6,0xbb,0x90,0xf3,0xfd,0x5b,0xd6,0x8b,0x81,0x2a,0xb2,
    0xc3,0xea,0x70,0x99,0xb2,0xc,0x91,0xd8,0x76,0xc1,0xae,0xe0,0xb5,0x51,0x78,0xd,
    0x41,0xc2,0xdc,0xe2,0xa6,0x4b,0xc9,0xe0,0x59,0xb4,0x2d,0xb1,0x9d,0x84,0x3f,0x23,
    0xe9,0xba,0x17,0x1a,0xb4,0xb7,0x42,0x84,0x6c,0xcc,0x9b,0x80,0xf0,0x92,0x93,0x55,
    0xd0,0xd1,0xcd,0x1e,0x60,0xcb,0xee,0xb3,0x2a,0xf3,0x29,0x4f,0x2c,0x42,0x3d,0x1e,
    0x4e,0x2a,0x88,0xca,0xc1,0x69,0xa9,0xa5,0x7c,0xb8,0x93,0xdd,0x8b,0x4b,0x3d,0x4e,
    0xd0,0xe8,0x1e,0xad,0x50,0xc8,0xe6,0xab,0x68,0xf9,0xcd,0x13,0xb6,0x38,0xfd,0xf9,
    0x50,0xfe,0x43,0x6a,0xbb,0x69,0x59,0x6c,0x85,0xc8,0x5,0x87,0x92,0xd5,0xf3,0x63,
    0x8b,0x4c,0x3f,0x8a,0x52,0xd2,0xda,0x22,0xbb,0x39,0xa,0x40,0xc2,0xcc,0x3d,0x9b,
    0xb6,0x61,0x67,0x6d,0xfb,0x5f,0x20,0x33,0xee,0x61,0x58,0xb2,0xfd,0xea,0x1e,0xd5,
    0x14,0x81,0x21,0x28,0x72,0x38,0xeb,0xde,0x4a,0xab,0xa1,0xd,0xaf,0x90,0x4a,0x51,
    0x3d,0x41,0x9f,0x73,0xaf,0xfb,0x1a,0xbe,0xbc,0x86,0xb0,0xa6,0x1d,0x2a,0x74,0x1e,
    0x20,0xa5,0x1f,0xfb,0xf1,0x19,0x1e,0x22,0xb4,0xd,0xfc,0x38,0xd9,0xb5,0x6d,0xf3,
    0x5c,0xc0,0x47,0x28,0x79,0x65,0x16,0xfa,0x6c,0xc9,0x7f,0x8f,0x31,0x7b,0xd2,0x6a,
    0x77,0x94,0x7a,0x26,0xa4,0x9e,0xff,0x4f,0x3b,0xe0,0x52,0xcf,0xda,0xb3,0xcb,0xef,
    0x11,0xeb,0x5a,0xd1,0x1b,0x66,0xb3,0x7a,0x47,0xfa,0xef,0x43,0x20,0x67,0xcd,0x66,
    0xd2,0xa4,0xee,0x25,0x30,0xd8,0x3f,0x8b,0xb,0xd2,0x79,0xb5,0x64,0xb3,0x8b,0xad,
    0x8,0x7f,0x6b,0x76,0xe0,0x74,0xd5,0xd1,0x17,0xb9,0xc7,0x32,0x36,0xe9,0x78,0xfb,
    0xfe,0xc0,0x6a,0x8e,0x1f,0xd6,0xda,0xbd,0x97,0xa6,0xa1,0x42,0xee,0x89,0x51,0xb,
    0x1b,0xb1,0x36,0x63,0x4f,0xeb,0x9,0x19,0x61,0xdb,0x8a,0xb7,0xf3,0xab,0xec,0x1e,
    0x89,0x87,0xd5,0x3e,0x38,0x3e,0xf3,0xde,0xab,0x43,0xd6,0x9e,0xd3,0x41,0xf5,0x66,
    0xf5,0xbb,0x60,0xbe,0xf0,0x16,0x2b,0xb2,0xaa,0xbb,0xad,0xf7,0x3d,0x9c,0x17,0x67,
    0xe,0x37,0xfd,0x3b,0x22,0xac,0xf5,0x89,0x72,0x49,0x60,0x50,0xb5,0xfc,0xe1,0x46,
    0x54,0xfb,0x6d,0x22,0x0,0x33,0xb7,0x46,0x84,0x92,0x4c,0x93,0xb4,0x20,0xfe,0xf,
    0x25,0x27,0xed,0x10,0x8,0x38,0x7,0x5b,0xca,0xdb,0xc2,0x0,0x5c,0x1,0x68,0x5e,
    0x4a,0x50,0xf3,0xcc,0xe,0x74,0xff,0x3b,0x36,0xc6,0xc3,0xf6,0x55,0x4f,0x82,0xa6,
    0xf8,0x2d,0x60,0xce,0x12,0x13,0xe1,0xcf,0x60,0xd9,0x9,0xf,0x9a,0x14,0xc4,0x16,
    0x17,0xf3,0x8d,0xf3,0xe,0x79,0x7e,0xb4,0xfc,0x5c,0xdf,0x70,0xb4,0x75,0xf3,0xcb,
    0xb8,0xe1,0x43,0x1d,0xba,0x6a,0x79,0xfb,0xbb,0x1a,0x51,0x16,0x1f,0xa1,0x1,0x69,
    0xf,0x10,0x53,0x14,0xad,0xc6,0x22,0x55,0x24,0x7f,0x9,0x5e,0xd3,0x46,0xb,0x48,
    0x4c,0x0,0x50,0x86,0x44,0xe,0xa6,0x28,0x7b,0x6,0xa3,0x42,0x5e,0x8b,0x1b,0x88,
    0x31,0x91,0xf0,0x31,0x39,0x8b,0xbe,0x99,0xc6,0x51,0x8c,0x53,0x7c,0x3a,0xb5,0x5b,
    0x96,0xb1,0x67,0x97,0x15,0xc9,0x71,0x6e,0xb8,0x3d,0x1a,0x12,0x1b,0x15,0x2f,0xc1,
    0xce,0x24,0xec,0x4b,0x54,0xba,0x4a,0xa2,0xda,0x23,0xfb,0x72,0x41,0x99,0xf,0x4f,
    0xd5,0xe4,0x2c,0x50,0x7d,0x27,0xca,0xe3,0xda,0x17,0x20,0x67,0x81,0x64,0x28,0x74,
    0x57,0x1d,0x78,0x97,0xc6,0x1f,0xbf,0x6e,0x87,0x8,0xf0,0xe7,0xa5,0x12,0xe3,0xba,
    0x5c,0x50,0xb8,0x2a,0x6c,0xfc,0x2d,0xb5,0xb3,0x41,0x4d,0xbc,0xcb,0xf9,0x89,0x69,
    0x20,0xf9,0xdf,0xad,0x42,0xba,0xe0,0xaa,0x83,0xf8,0x7f,0xd4,0x48,0x5a,0xca,0x3,
    0x61,0x47,0xa2,0xe2,0xe5,0x53,0x2f,0x74,0x52,0x70,0xa7,0x36,0x31,0x88,0xb3,0x34,
    0xb0,0xfb,0x67,0xd3,0x8e,0x36,0xf7,0x91,0x5b,0x91,0x63,0x22,0xa9,0x9e,0xc9,0xf0,
    0xf9,0xf6,0x93,0x5,0x98,0x4f,0x94,0x50,0xfe,0xdd,0x3,0xab,0xb6,0xd0,0x4,0x0,
    0xab,0x22,0x3d,0x47,0xa9,0x9,0xc,0x18,0x31,0xb6,0xe4,0x67,0x3b,0xa0,0xa8,0x48,
    0xa5,0x12,0x8c,0xf9,0x71,0xb1,0xd1,0x20,0x66,0xa9,0x84,0x51,0x5,0x79,0x99,0xad,
    0x2e,0x51,0xba,0xae,0xe5,0xa7,0xa2,0xde,0x3c,0x4d,0xe8,0x36,0x6c,0x25,0xd7,0x89,
    0x9e,0x1c,0x23,0xda,0xe8,0x99,0xe5,0x3c,0xcb,0x6d,0xef,0x7c,0x3f,0xb2,0x1a,0x7,
    0xc1,0x95,0x3e,0x34,0x2c,0x8b,0xcf,0x6f,0xc2,0x7,0x2f,0xca,0x1f,0xa6,0xf9,0x11,
    0x9c,0x61,0xaa,0x7e,0xda,0x87,0x5b,0x65,0x3a,0x2d,0x20,0xda,0xf8,0x66,0x71,0xeb,
    0x28,0xdb,0x51,0xae,0x74,0x26,0x88,0x66,0xd3,0xb1,0xda,0x31,0x6a,0x51,0x3c,0x43,
    0x7f,0xbc,0x61,0x55,0x2e,0xcf,0xe,0x37,0x23,0x96,0x51,0xa4,0x73,0x3d,0x2a,0x5f,
    0x52,0xd0,0x17,0x70,0x54,0x4d,0x74,0x1b,0xfb,0x6f,0x21,0x58,0x7c,0xba,0x81,0x66,
    0xf9,0x2a,0x37,0xda,0x3f,0x6b,0x42,0x3,0x26,0x15,0x86,0x10,0xd0,0xb8,0x6a,0xcf,
    0xb0,0x9b,0xa4,0x6d,0xeb,0xb8,0x9a,0xf3,0x1f,0x15,0xa7,0xa5,0xc6,0x66,0x2c,0xdb,
    0xb4,0x9a,0x42,0x77,0x97,0x7,0xce,0xfa,0x5,0xb4,0xd1,0x6a,0xcd,0xb2,0x8,0x6a,
    0xc8,0x16,0x3e,0x6d,0x16,0xa4,0x4d,0xb6,0x50,0xbd,0xe1,0xe9,0x92,0x9c,0xed,0x6b,
    0x7f,0x46,0xd5,0x16,0xca,0x70,0x61,0x4b,0xdd,0xc8,0x76,0x27,0x64,0x30,0xa5,0x24,
    0xaf,0x95,0x85,0x80,0x8d,0x79,0xf1,0x1,0x8c,0xa1,0xe7,0xb,0xb5,0x92,0x25,0x3,
    0x1c,0xa4,0x7c,0x42,0x6e,0x2d,0x90,0xfd,0xb6,0xaa,0xd2,0x57,0x51,0xa4,0x7d,0xca,
    0x22,0xf3,0x55,0x5a,0xf2,0xe,0x68,0x7f,0x41,0x50,0x91,0x45,0x75,0xf7,0x42,0x2e,
    0x89,0x6c,0xa5,0x9b,0x5c,0x49,0x31,0xea,0xda,0x74,0xca,0xc0,0x13,0x47,0x54,0x8f,
    0xc7,0xed,0xe9,0xb,0xa,0x9,0xb1,0xc2,0xf1,0xb4,0xf8,0x12,0x94,0x68,0x98,0x4,
    0x21,0x44,0x55,0x66,0x94,0x71,0x36,0x91,0x2d,0x32,0x1d,0xc1,0x45,0xac,0x97,0x11,
    0x2b,0x33,0xe4,0xd3,0x49,0xd,0xa6,0xdf,0x4c,0x34,0x1,0x6e,0xf1,0xbb,0xbe,0xf5,
    0x31,0xe,0x93,0x15,0x95,0x88,0x9e,0x14,0x7,0x1c,0x6b,0x66,0x8,0x1c,0xad,0x51,
    0x14,0xca,0x14,0xfa,0x8b,0x27,0x60,0xd0,0x23,0x57,0xb8,0xcf,0xe0,0x45,0x4c,0x12,
    0xdd,0xea,0xde,0x39,0x1c,0x79,0x7e,0xaa,0x8d,0x91,0x8c,0x19,0x9f,0xba,0x25,0x37,
    0xa3,0xb2,0xab,0x67,0x1a,0xbb,0xec,0x38,0xae,0x6b,0x7,0xe2,0xda,0xbd,0x5b,0x10,
    0xcc,0xb0,0x7a,0xb8,0x4d,0x77,0xfa,0x4,0x87,0x48,0x20,0x86,0x6b,0xeb,0x30,0x48,
    0xf4,0xf7,0x4b,0xa5,0xe1,0x66,0x4d,0x76,0x7f,0xd,0xfc,0x21,0x54,0xa9,0x15,0x61,
    0xa8,0x82,0x6c,0xc3,0x5,0xef,0xea,0xf9,0x65,0x8a,0x72,0xe,0xa3,0x4a,0xb2,0xd5,
    0xd2,0x94,0x2,0x56,0xdd,0x8d,0xb6,0xe,0xef,0xab,0x85,0x79,0xac,0xfa,0xe7,0x5c,
    0xa7,0x35,0x35,0x45,0xb8,0xe0,0x86,0x59,0x94,0x6d,0x55,0x95,0x68,0x4a,0x52,0xae,
    0x65,0xb6,0x24,0xce,0xf7,0x6a,0xc2,0xa6,0xd3,0xdc,0x97,0x22,0x3d,0xc2,0xe4,0x30,
    0x3c,0xc9,0xc8,0x98,0xc3,0xce,0x9,0x38,0x94,0x1,0xdf,0x5d,0xe2,0x22,0xd1,0x77,
    0xed,0xa,0xf2,0x3a,0xe7,0x21,0x47,0x43,0x98,0xcc,0x37,0x5f,0x8a,0x77,0x58,0xa8,
    0x18,0xd,0x27,0x85,0xbf,0x29,0x69,0x92,0x19,0x85,0x23,0x64,0xfe,0x89,0xd3,0x60,
    0x32,0xe,0x38,0xae,0x33,0x27,0x75,0xc1,0x6e,0xe1,0x26,0xfa,0xf0,0x71,0x9,0x81,
    0x3c,0xce,0x8e,0x76,0x73,0xd0,0x55,0x13,0x4a,0x95,0x8e,0x5d,0xf3,0x93,0x1e,0x34,
    0x7f,0xeb,0x21,0xe2,0xb5,0x1d,0x26,0x8e,0xbd,0x97,0xa7,0xa1,0x54,0x6c,0x2,0xcb,
    0xa1,0x2c,0x4b,0xd3,0x1d,0xa1,0xbc,0xc4,0x97,0x44,0x47,0xc8,0xbf,0xe7,0xd7,0x72,
    0x23,0x82,0xeb,0x64,0x2d,0x3d,0x1f,0x15,0x44,0x13,0x9f,0xef,0xb0,0x57,0x44,0xfe,
    0x1c,0xdd,0x7f,0xc,0xe5,0x8f,0x7a,0xb8,0x33,0x82,0x78,0xf8,0x43,0x13,0x82,0x87,
    0xb1,0x5c,0xe8,0x9f,0x78,0xad,0xaa,0x29,0xf5,0x93,0x1f,0x78,0xfa,0xcc,0x20,0x63,
    0x97,0xdb,0x13,0x2d,0xa2,0xea,0xda,0x2,0xce,0x18,0x5e,0xf6,0x3,0xe0,0x63,0x4,
    0xfb,0xb4,0x7,0x5f,0xfc,0xde,0xdd,0x38,0x35,0xcc,0xc4,0x1c,0xcf,0x1f,0x19,0x97,
    0xcc,0x85,0x14,0x3f,0xa6,0xa4,0x85,0x19,0x41,0x8e,0x18,0xde,0x9f,0x48,0x5e,0x9d,
    0xe3,0x85,0x3c,0x25,0xbd,0xc0,0xb5,0xfe,0xb2,0xbd,0x24,0xda,0x15,0x18,0xcc,0x64,
    0x18,0x7f,0xc7,0xa7,0x5a,0xea,0x92,0x6,0xa9,0xa6,0xec,0xf0,0x68,0x85,0x9c,0x6,
    0x46,0x94,0x0,0x4e,0x3b,0x14,0x8d,0x55,0xe7,0x80,0x25,0x90,0xfe,0xd2,0x97,0xe0,
    0x17,0x9d,0x5f,0x8f,0xa5,0x62,0x9a,0x8d,0x3e,0x26,0x6d,0x69,0xc5,0xc0,0xb5,0xf,
    0x2,0xe9,0x9c,0x5f,0x92,0x97,0x2b,0xd4,0xd2,0xc,0x16,0x7,0x93,0xb1,0xeb,0x42,
    0x6f,0xe3,0xd,0x6b,0x49,0x26,0x68,0xd5,0x50,0xea,0x8,0xe7,0x10,0x22,0x5b,0xb8,
    0x21,0x16,0x48,0x52,0x34,0x5f,0xad,0x1c,0x70,0x21,0x38,0xfa,0x5a,0xff,0xb5,0x15,
    0x2,0x5a,0x68,0xdf,0x4b,0x33,0x9c,0xad,0x67,0xa4,0xc7,0x72,0x61,0x2f,0x1c,0xf,
    0x7d,0x18,0xf5,0x7a,0xb3,0x2,0xfb,0xc5,0x58,0xa7,0xa2,0xde,0x75,0xc0,0x5c,0x59,
    0xf2,0x7a,0xe,0xf,0x63,0x56,0x41,0x90,0x88,0xb7,0x40,0x5,0x4f,0x3d,0x51,0xbf,
    0x32,0x92,0x2b,0x9a,0xa5,0x3e,0xeb,0xf2,0xd1,0xdc,0x93,0x9b,0xee,0xaf,0x3,0xcc,
    0xbd,0x7d,0xe8,0x96,0x84,0xda,0xa9,0x60,0x64,0x1e,0x60,0x84,0xe4,0xae,0xa5,0x3d,
    0xa2,0x9b,0x37,0xb7,0x21,0x25,0x65,0x94,0xfe,0xe1,0x4b,0x2f,0x2c,0xfb,0x28,0x3f,
    0xb,0x8e,0x15,0x6d,0xa2,0xfb,0x2b,0xe3,0xdc,0x77,0xf5,0xb4,0xdc,0xf2,0xbf,0x4f,
    0xf4,0x86,0xed,0x1f,0x4f,0xbb,0x2a,0x62,0x66,0x4,0x47,0x6e,0x17,0x9c,0x18,0x52,
    0x4b,0x22,0xd0,0x66,0x4f,0x8d,0xcf,0x95,0x23,0x3a,0x6d,0x80,0x71,0x57,0xb3,0xd7,
    0xfa,0x70,0x0,0x73,0x5f,0x49,0x42,0xa7,0x9d,0x91,0x36,0xd5,0x4f,0x64,0xee,0x23,
    0x38,0xb3,0xe3,0x8c,0x2,0x8,0x79,0x2a,0x7f,0x82,0x2e,0x8f,0xd6,0x36,0x7d,0xa0,
    0x8f,0x3d,0x32,0xd3,0xb9,0xad,0xd2,0xac,0xc2,0xba,0xe9,0xd8,0xdc,0xae,0x4b,0xd5,
    0x1a,0x8b,0x50,0x14,0x59,0x5b,0x72,0x96,0xe4,0xb7,0xe2,0x2,0x3d,0x46,0x12,0x62,
    0xcc,0xd4,0x86,0xb0,0x80,0x30,0x70,0x75,0x94,0x51,0x92,0xb5,0x1a,0x93,0x28,0x9f,
    0xa5,0x80,0x69,0x17,0x3e,0xe7,0x80,0x5f,0x12,0x8d,0x4d,0xb5,0x35,0xb4,0xbf,0xc8,
    0x53,0x96,0x18,0x25,0x89,0xa7,0xe6,0x90,0x2d,0x40,0xcc,0xc6,0x17,0xc9,0xef,0x4e,
    0xd6,0x51,0xa4,0x40,0x7e,0xf,0x3a,0xbb,0x84,0xea,0xc9,0x3b,0xc0,0x86,0xc3,0x70,
    0x48,0x1c,0xd2,0x8d,0x54,0x28,0xa1,0x7,0xbc,0xdf,0x4,0x92,0xe2,0x68,0xd4,0x88,
    0x98,0x2c,0x92,0xaa,0x23,0xa5,0x1f,0x4a,0xf0,0x3b,0x7b,0x41,0xf5,0x9b,0x12,0xbb,
    0x8d,0x3a,0x4c,0x2a,0xb9,0xa5,0xc8,0x8c,0x2,0xfa,0x50,0x37,0x2,0x48,0xbb,0x12,
    0xce,0x22,0x7c,0xba,0x7f,0x58,0x5,0xcb,0x7c,0x11,0x45,0x8e,0x81,0xc2,0x93,0xd0,
    0xdf,0x6d,0xde,0x54,0x98,0x6d,0x9f,0x5a,0x99,0x0,0xe5,0x50,0xef,0x4e,0xa8,0x31,
    0xd1,0x64,0x1a,0x77,0xe9,0xb1,0xcd,0xaf,0xe9,0xfa,0x70,0x76,0xb3,0x78,0x31,0xa3,
    0xf7,0x72,0x59,0x20,0x5b,0xf0,0xbb,0xf,0x47,0xc9,0xa3,0xf4,0x8e,0xa0,0xed,0x95,
    0x3c,0x9a,0x7c,0x44,0x1c,0x2c,0x4b,0x6c,0x2a,0x4c,0xb9,0x8c,0x18,0xc1,0xc4,0x73,
    0x84,0x81,0xe5,0xbb,0x79,0x62,0x50,0xe7,0x86,0x87,0xe4,0x24,0x34,0xc2,0x3f,0x80,
    0xad,0xd4,0x87,0x9e,0xf8,0x6c,0x48,0xc0,0x2f,0xbc,0x89,0x47,0xda,0xaa,0x13,0xfe,
    0x5f,0x1a,0x54,0x88,0x98,0xa8,0x5c,0x42,0x7e,0x35,0x62,0xb6,0xf8,0xde,0x69,0x41,
    0x6b,0x48,0x54,0x8,0x38,0xdd,0x2,0x33,0xe5,0xdd,0x1c,0x5d,0x8e,0x5,0x95,0x6b,
    0x6,0x33,0x54,0x81,0x76,0x39,0xce,0x93,0x4c,0x35,0x7a,0x9b,0x4c,0xa8,0xdb,0x9d,
    0xf0,0xca,0xea,0x1b,0x73,0x2d,0x46,0xcc,0x3f,0xcf,0x72,0x6a,0x9a,0x24,0xbc,0xe9,
    0x29,0x42,0xbc,0xba,0x67,0x30,0x19,0xac,0xa9,0xad,0x3f,0xe8,0x79,0x29,0xa0,0x16,
    0x10,0x61,0xd7,0x83,0x58,0x73,0x25,0x3b,0x63,0x1b,0xea,0xfb,0x90,0xa,0xa,0x5,
    0x85,0x34,0x98,0xde,0xde,0x84,0x23,0x2f,0x91,0xf7,0x23,0x67,0xed,0x2b,0x5d,0x30,
    0xa4,0x8d,0x8b,0x7a,0x77,0x7d,0x62,0xce,0x4a,0x4a,0x84,0x18,0xa7,0x96,0xd8,0x2d,
    0xcc,0xed,0xa0,0xda,0x6b,0xbf,0x2c,0xa1,0x20,0xf4,0x7c,0xeb,0x9b,0x97,0x1d,0xb3,
};

#endif
