629 lines
18 KiB
C
629 lines
18 KiB
C
|
|
/****************************************************************************
|
||
|
|
|
||
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||
|
|
|
||
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||
|
|
be copied by any method or incorporated into another program without
|
||
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
||
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
||
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||
|
|
liability for its use in any way and conveys no license or title under
|
||
|
|
any patent or copyright and makes no representation or warranty that this
|
||
|
|
Information is free from patent or copyright infringement.
|
||
|
|
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
|
||
|
|
#include "os_lock_api.h"
|
||
|
|
#include "os_timer_api.h"
|
||
|
|
#include "os_utils_api.h"
|
||
|
|
|
||
|
|
#include "iot_io_api.h"
|
||
|
|
#include "iot_rtc_api.h"
|
||
|
|
#include "iot_oem_api.h"
|
||
|
|
#include "iot_plc_api.h"
|
||
|
|
#include "iot_pkt_api.h"
|
||
|
|
#include "iot_task_api.h"
|
||
|
|
#include "iot_task_api.h"
|
||
|
|
#include "iot_errno_api.h"
|
||
|
|
#include "iot_utils_api.h"
|
||
|
|
#include "iot_cctt_utils.h"
|
||
|
|
#include "iot_plc_msg_api.h"
|
||
|
|
#include "iot_cctt_comm_module.h"
|
||
|
|
#include "iot_cctt_config.h"
|
||
|
|
#include "iot_system_api.h"
|
||
|
|
|
||
|
|
#include "driver/iot_gpio.h"
|
||
|
|
#include "iot_board_api.h"
|
||
|
|
|
||
|
|
#if (IOT_APP_SELECTION == IOT_APP_DEF_22_GE_MICRO_CCTT)
|
||
|
|
#include "iot_proto_ge.h"
|
||
|
|
#include "iot_proto_common.h"
|
||
|
|
#endif // end of #if (IOT_APP_SELECTION == IOT_APP_DEF_22_GE_MICRO_CCTT)
|
||
|
|
|
||
|
|
#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
|
||
|
|
|
||
|
|
#define IOT_CCTT_INVALID_GPIO (0xFF)
|
||
|
|
#define IOT_CCTT_INTERNAL_GPIO(n) (n)
|
||
|
|
#define IOT_CCTT_KL1_EXT_GPIO(n) (iot_gpio_get_inner_gpio_num() + (n))
|
||
|
|
|
||
|
|
/* iot concentrator module, version 3.0 */
|
||
|
|
#ifndef HW_VERSION_IOT_CCTT_V3_0
|
||
|
|
#define HW_VERSION_IOT_CCTT_V3_0 0x720A0100 //114.10.01.00
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* iot concentrator module, version 3.5 */
|
||
|
|
#ifndef HW_VERSION_IOT_CCTT_V3_5
|
||
|
|
#define HW_VERSION_IOT_CCTT_V3_5 0x760A0100 //118.10.01.00
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* CRC table for the CRC-16. */
|
||
|
|
/* The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
|
||
|
|
static const uint16_t iot_crc16_tab[256] = {
|
||
|
|
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||
|
|
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||
|
|
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||
|
|
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||
|
|
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||
|
|
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||
|
|
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||
|
|
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||
|
|
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||
|
|
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||
|
|
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||
|
|
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||
|
|
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||
|
|
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||
|
|
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||
|
|
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||
|
|
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||
|
|
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||
|
|
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||
|
|
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||
|
|
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||
|
|
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||
|
|
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||
|
|
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||
|
|
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||
|
|
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||
|
|
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||
|
|
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||
|
|
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||
|
|
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||
|
|
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||
|
|
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : calc crc16 with poly 0x8005, init 0xFFFF, xorout=0x0000
|
||
|
|
*
|
||
|
|
* @param data: data to calc
|
||
|
|
* @param len : length of data
|
||
|
|
* @return crc16 checksum
|
||
|
|
*/
|
||
|
|
static uint16_t iot_cctt_utils_calc_crc16(uint8_t *data, uint32_t len)
|
||
|
|
{
|
||
|
|
|
||
|
|
register uint16_t crc = 0xFFFF;
|
||
|
|
|
||
|
|
if((NULL == data) || (len == 0)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
while (len--) {
|
||
|
|
crc = (crc>>8) ^ iot_crc16_tab[(crc ^ *data++) & 0xff];
|
||
|
|
}
|
||
|
|
return crc;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : get cctt ethernet mac address
|
||
|
|
* try to use mac address of cco firstly, if failed, use random mac
|
||
|
|
*
|
||
|
|
* @param p_mac : buffer to store mac address
|
||
|
|
* @return none
|
||
|
|
*/
|
||
|
|
void iot_cctt_utils_get_eth_mac(uint8_t *p_mac)
|
||
|
|
{
|
||
|
|
if (NULL == p_mac) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_oem_get_module_mac(p_mac);
|
||
|
|
p_mac[0] &= 0xFE; // to avoid to use multicast mac address
|
||
|
|
iot_cctt_utils_dump_bin("[cctt utils]eth mac", p_mac, IOT_MAC_ADDR_LEN);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : query cctt plc mac address
|
||
|
|
*
|
||
|
|
* @param p_mac : buffer to store mac address
|
||
|
|
* @return ERR_OK if success, error code otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_get_cctt_mac(uint8_t *p_mac)
|
||
|
|
{
|
||
|
|
uint8_t ret = ERR_FAIL;
|
||
|
|
|
||
|
|
if (NULL != p_mac) {
|
||
|
|
iot_cctt_cfg_get_nv_cctt_mac(p_mac);
|
||
|
|
ret = ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : set cctt plc mac address
|
||
|
|
*
|
||
|
|
* @param p_mac : buffer to store mac address
|
||
|
|
* @return ERR_OK if success, error code otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_set_cctt_mac(uint8_t *p_mac)
|
||
|
|
{
|
||
|
|
uint8_t ret = ERR_OK;
|
||
|
|
|
||
|
|
/* save cctt mac to customer part, avoid mac changed after fw update */
|
||
|
|
iot_cctt_cfg_set_cctt_mac(p_mac);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : build login frame
|
||
|
|
*
|
||
|
|
* @param p_buff : buffer to store login frame
|
||
|
|
* @param len : length of p_frame
|
||
|
|
* @return ERR_OK if success, error code otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_build_dbg_svr_login_frm(uint8_t appid,
|
||
|
|
uint8_t *p_buff,
|
||
|
|
uint32_t len)
|
||
|
|
{
|
||
|
|
iot_cctt_tools_login_frame_t *p_login_frame;
|
||
|
|
uint8_t mac_address[IOT_MAC_ADDR_LEN];
|
||
|
|
uint16_t crc16;
|
||
|
|
|
||
|
|
p_login_frame = (iot_cctt_tools_login_frame_t*)p_buff;
|
||
|
|
if ((NULL == p_buff) || (len < sizeof(iot_cctt_tools_login_frame_t))) {
|
||
|
|
return ERR_INVAL;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_cctt_utils_get_cctt_mac(mac_address);
|
||
|
|
|
||
|
|
p_login_frame->preamble = 0xAAAA;
|
||
|
|
p_login_frame->cctt_id[0] = mac_address[0];
|
||
|
|
p_login_frame->cctt_id[1] = (mac_address[1] & 0xF0) | (mac_address[3]&0x0F);
|
||
|
|
p_login_frame->cctt_id[2] = mac_address[4];
|
||
|
|
p_login_frame->cctt_id[3] = mac_address[5];
|
||
|
|
p_login_frame->app_id = appid;
|
||
|
|
p_login_frame->fn = 0x44;
|
||
|
|
p_login_frame->sub_fn = 0x20;
|
||
|
|
p_login_frame->seq = 0x00;
|
||
|
|
p_login_frame->need_ack = 0x01;
|
||
|
|
p_login_frame->reserved = 0xFF;
|
||
|
|
p_login_frame->index = 0x00;
|
||
|
|
p_login_frame->length[0] = 0x00;
|
||
|
|
p_login_frame->length[1] = 0x06;
|
||
|
|
p_login_frame->tail = 0xFF;
|
||
|
|
iot_mac_addr_cpy(p_login_frame->mac, mac_address);
|
||
|
|
crc16 = iot_cctt_utils_calc_crc16(p_buff,
|
||
|
|
sizeof(iot_cctt_tools_login_frame_t) - 3);
|
||
|
|
p_login_frame->crc16[0] = crc16 >> 8;
|
||
|
|
p_login_frame->crc16[1] = crc16 & 0xFF;
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : check whether the data in p_buff is query frame from debug server
|
||
|
|
*
|
||
|
|
* @param p_buff : pointer to data to check
|
||
|
|
* @param len : length of data
|
||
|
|
* @return true if it's a query frame, false otherwise
|
||
|
|
*/
|
||
|
|
bool_t iot_cctt_utils_is_dbg_svr_query_frm(uint8_t *p_buff, uint32_t len)
|
||
|
|
{
|
||
|
|
const uint8_t cctt_id_request[] = {
|
||
|
|
0xAA, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x33, 0x20, 0x00,
|
||
|
|
0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x49, 0xFF,
|
||
|
|
};
|
||
|
|
|
||
|
|
if ((NULL != p_buff) && (sizeof(cctt_id_request) == len) &&
|
||
|
|
(0 == os_mem_cmp(cctt_id_request, p_buff, sizeof(cctt_id_request)))) {
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : dump data to log buffer
|
||
|
|
*
|
||
|
|
* @param descr : descrption of data
|
||
|
|
* @param p_data : data to dump
|
||
|
|
* @param len : length of data
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
void iot_cctt_utils_dump_bin(char *descr, uint8_t *p_data, uint32_t len)
|
||
|
|
{
|
||
|
|
iot_cus_printf("%s:", descr);
|
||
|
|
while (len != 0) {
|
||
|
|
iot_cus_printf("%02X ", *p_data);
|
||
|
|
p_data++;
|
||
|
|
len--;
|
||
|
|
}
|
||
|
|
iot_cus_printf("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : smart dump data to log buffer, if data is all printable string
|
||
|
|
* dump as string format, if not, dump as hex format otherwise
|
||
|
|
*
|
||
|
|
* @param descr : descrption of data
|
||
|
|
* @param p_data : data to dump
|
||
|
|
* @param len : length of data
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
void iot_cctt_utils_smart_dump(char *descr, uint8_t *p_data, uint32_t len)
|
||
|
|
{
|
||
|
|
char str_buff[1024];
|
||
|
|
char *p_str = str_buff;
|
||
|
|
uint32_t i;
|
||
|
|
bool_t print_as_str = true;
|
||
|
|
|
||
|
|
for (i = 0; i < len; i++) {
|
||
|
|
if (p_str + 3 >= str_buff + sizeof(str_buff)) {
|
||
|
|
/* buffer not enough, print as hex code */
|
||
|
|
print_as_str = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if ((p_data[i] >= 0x20) && (p_data[i] < 0x80)) {
|
||
|
|
*p_str++ = p_data[i];
|
||
|
|
} else if ('\r' == p_data[i]) {
|
||
|
|
*p_str++ = '\\';
|
||
|
|
*p_str++ = 'r';
|
||
|
|
} else if ('\n' == p_data[i]) {
|
||
|
|
*p_str++ = '\\';
|
||
|
|
*p_str++ = 'n';
|
||
|
|
} else {
|
||
|
|
/* include non-printable character, print as hex code */
|
||
|
|
print_as_str = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (print_as_str) {
|
||
|
|
*p_str = '\0';
|
||
|
|
iot_cus_printf("%s: %s\r\n", descr, str_buff);
|
||
|
|
} else {
|
||
|
|
iot_cctt_utils_dump_bin(descr, p_data, len);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : check if character is valid hex char
|
||
|
|
*
|
||
|
|
* @param c : character value to check
|
||
|
|
* @return 1 if hex char, 0 otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_char_is_hex(char c)
|
||
|
|
{
|
||
|
|
if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
|
||
|
|
(c >= 'a' && c <= 'f')) {
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : check if character is valid number char
|
||
|
|
*
|
||
|
|
* @param c : character value to check
|
||
|
|
* @return 1 if hex char, 0 otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_char_is_number(char c)
|
||
|
|
{
|
||
|
|
if(c >= '0' && c <= '9') {
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief : parse ip address from specified string
|
||
|
|
*
|
||
|
|
* @param p_str : string to parse
|
||
|
|
* @param p_ip : buffer to store ip address
|
||
|
|
* @return ERR_OK if success, error code otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_ip_str_parse(uint8_t *p_str, uint8_t *p_ip)
|
||
|
|
{
|
||
|
|
uint32_t temp;
|
||
|
|
uint32_t ip_idx = 0;
|
||
|
|
|
||
|
|
if ((NULL == p_str) || (NULL == p_ip)) {
|
||
|
|
return ERR_FAIL;
|
||
|
|
}
|
||
|
|
|
||
|
|
os_mem_set(p_ip, 0x00, IOT_IP4_ADDR_LEN);
|
||
|
|
|
||
|
|
while (*p_str) {
|
||
|
|
if (iot_cctt_utils_char_is_number(*p_str)) {
|
||
|
|
temp = p_ip[ip_idx];
|
||
|
|
temp = temp * 10 + *p_str - '0';
|
||
|
|
if (temp > 255) {
|
||
|
|
return ERR_FAIL;
|
||
|
|
}
|
||
|
|
p_ip[ip_idx] = temp;
|
||
|
|
} else if ('.' == *p_str) {
|
||
|
|
ip_idx++;
|
||
|
|
if (ip_idx >= IOT_IP4_ADDR_LEN) {
|
||
|
|
return ERR_FAIL;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
return ERR_FAIL;
|
||
|
|
}
|
||
|
|
p_str++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief: reboot cctt
|
||
|
|
*
|
||
|
|
* @param reason: reason of requesting to reboot cctt
|
||
|
|
* @return none
|
||
|
|
*/
|
||
|
|
void iot_cctt_utils_reboot_cctt(iot_cctt_utils_reboot_cctt_reason_e reason)
|
||
|
|
{
|
||
|
|
char *p_reboot_reason_str = "unknown reason ";
|
||
|
|
|
||
|
|
switch (reason) {
|
||
|
|
case IOT_CCTT_REBOOT_REASON_MGR_AT_CMD_REQ:
|
||
|
|
p_reboot_reason_str = "reboot cmd from at manager";
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_REBOOT_REASON_IOT_DISCONN_TO:
|
||
|
|
p_reboot_reason_str = "disconnect timeout from iot app";
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
iot_cus_printf("cctt reboot because of reason:%s\n", p_reboot_reason_str);
|
||
|
|
iot_system_restart(IOT_SYS_RST_REASON_APP_REQ);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief: check whether the specified year is leap year
|
||
|
|
*
|
||
|
|
* @param year: year number to check
|
||
|
|
* @return 1 if year is leap year, 0 otherwise
|
||
|
|
*/
|
||
|
|
static inline int iot_cctt_utils_is_leap_year(unsigned int year)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
|
||
|
|
if (((!(year % 4)) && (year % 100)) || !(year % 400)) {
|
||
|
|
ret = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief: calc the number of days from the beginning of year to the month
|
||
|
|
*
|
||
|
|
* @param month: the month to calc days
|
||
|
|
* @param year: the year to calc days
|
||
|
|
* @return: the number of days from the beginning of year to the month
|
||
|
|
*/
|
||
|
|
static int iot_cctt_utils_calc_month_days(unsigned int month, unsigned int year)
|
||
|
|
{
|
||
|
|
static const unsigned char rtc_days_in_month[] = {
|
||
|
|
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||
|
|
};
|
||
|
|
int ret = 0;
|
||
|
|
|
||
|
|
ret = rtc_days_in_month[month];
|
||
|
|
if (iot_cctt_utils_is_leap_year(year) && (month == 1)) {
|
||
|
|
ret++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief: Convert seconds since 01-01-1970 00:00:00 to iot_time_tm_t date.
|
||
|
|
*
|
||
|
|
* @param time: seconds since 01-01-1970 00:00:00
|
||
|
|
* @param p_tm: iot_time_tm_t pointer to store converted time
|
||
|
|
* @return none
|
||
|
|
*/
|
||
|
|
void iot_cctt_utils_time64_to_tm(uint64_t time, iot_time_tm_t *p_tm)
|
||
|
|
{
|
||
|
|
unsigned int month, year;
|
||
|
|
unsigned long secs;
|
||
|
|
int days;
|
||
|
|
|
||
|
|
if (NULL == p_tm) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* time must be positive */
|
||
|
|
days = time / 86400;
|
||
|
|
secs = time - (unsigned int) days * 86400;
|
||
|
|
|
||
|
|
year = 1970 + days / 365;
|
||
|
|
days -= (year - 1970) * 365
|
||
|
|
+ LEAPS_THRU_END_OF(year - 1)
|
||
|
|
- LEAPS_THRU_END_OF(1970 - 1);
|
||
|
|
if (days < 0) {
|
||
|
|
year -= 1;
|
||
|
|
days += 365 + iot_cctt_utils_is_leap_year(year);
|
||
|
|
}
|
||
|
|
p_tm->tm_year = year;
|
||
|
|
|
||
|
|
for (month = 0; month < 11; month++) {
|
||
|
|
int newdays;
|
||
|
|
|
||
|
|
newdays = days - iot_cctt_utils_calc_month_days(month, year);
|
||
|
|
if (newdays < 0)
|
||
|
|
break;
|
||
|
|
days = newdays;
|
||
|
|
}
|
||
|
|
p_tm->tm_mon = month + 1;
|
||
|
|
p_tm->tm_mday = days + 1;
|
||
|
|
|
||
|
|
p_tm->tm_hour = secs / 3600;
|
||
|
|
secs -= p_tm->tm_hour * 3600;
|
||
|
|
p_tm->tm_min = secs / 60;
|
||
|
|
p_tm->tm_sec = secs - p_tm->tm_min * 60;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* @brief: Converts Gregorian date to seconds since 1970-01-01 00:00:00.
|
||
|
|
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
|
||
|
|
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
|
||
|
|
*
|
||
|
|
* @param p_tm : pointed to iot_time_tm_t
|
||
|
|
* @return seconds since 1970-01-01 00:00:00
|
||
|
|
*/
|
||
|
|
uint64_t iot_cctt_utils_tm_to_time64(iot_time_tm_t *p_tm)
|
||
|
|
{
|
||
|
|
unsigned int year, month, day, hour, minute, second;
|
||
|
|
|
||
|
|
if (NULL == p_tm) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
year = p_tm->tm_year;
|
||
|
|
month = p_tm->tm_mon;
|
||
|
|
day = p_tm->tm_mday;
|
||
|
|
hour = p_tm->tm_hour;
|
||
|
|
minute = p_tm->tm_min;
|
||
|
|
second = p_tm->tm_sec;
|
||
|
|
|
||
|
|
/* 1..12 -> 11,12,1..10 */
|
||
|
|
if (0 >= (int) (month -= 2)) {
|
||
|
|
month += 12; /* Puts Feb last since it has leap day */
|
||
|
|
year -= 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ((((uint64_t)
|
||
|
|
(year/4 - year/100 + year/400 + 367*month/12 + day) +
|
||
|
|
year*365 - 719499
|
||
|
|
)*24 + hour /* now have hours */
|
||
|
|
)*60 + minute /* now have minutes */
|
||
|
|
)*60 + second; /* finally seconds */
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* @brief: query gpio pin number according to gpio id.
|
||
|
|
*
|
||
|
|
* @param gpio_id: gpio identifier, see iot_cctt_utils_gpio_id_e definition
|
||
|
|
* @return gpio number if success, 0xFF otherwise
|
||
|
|
*/
|
||
|
|
uint8_t iot_cctt_utils_get_gpio(iot_cctt_utils_gpio_id_e gpio_id)
|
||
|
|
{
|
||
|
|
uint8_t gpio_pin = IOT_CCTT_INVALID_GPIO;
|
||
|
|
|
||
|
|
switch (iot_board_hw_version_hex()) {
|
||
|
|
case HW_VERSION_IOT_CCTT_V3_0: /* micro cctt 3.0 hardware */
|
||
|
|
switch (gpio_id) {
|
||
|
|
case IOT_CCTT_GPIO_ID_ETH_RST:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(9);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_4G_RST:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(0);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_EXT_WDI:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(7);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RSD_SWITCH_IN:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(48);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RSD_LED_OUT:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(12);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RS485_CTL:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(36);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RS485_LED:
|
||
|
|
gpio_pin = IOT_CCTT_INVALID_GPIO;
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_UPGD_LED:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(8);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_PLC_LED:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(44);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_UPLINK_LED:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(45);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case HW_VERSION_IOT_CCTT_V3_5: /* micro cctt 3.5 hardware */
|
||
|
|
default:
|
||
|
|
switch (gpio_id) {
|
||
|
|
case IOT_CCTT_GPIO_ID_ETH_RST:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(1);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_4G_RST:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(3);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_EXT_WDI:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(0);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RSD_SWITCH_IN:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(48);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RSD_LED_OUT:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(4);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RS485_CTL:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(36);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_RS485_LED:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(5);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_UPGD_LED:
|
||
|
|
gpio_pin = IOT_CCTT_KL1_EXT_GPIO(2);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_PLC_LED:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(44);
|
||
|
|
break;
|
||
|
|
case IOT_CCTT_GPIO_ID_UPLINK_LED:
|
||
|
|
gpio_pin = IOT_CCTT_INTERNAL_GPIO(45);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return gpio_pin;
|
||
|
|
}
|