diff --git a/2016/07/11/STM32_PVD/index.html b/2016/07/11/STM32_PVD/index.html deleted file mode 100644 index 2825129..0000000 --- a/2016/07/11/STM32_PVD/index.html +++ /dev/null @@ -1,983 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STM32L051 PVD的调试 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - STM32L051 PVD的调试 - - -

- - - -
- - - -
- - - - - -

我的PVD的驱动以及例程位于STM32L0xx_Drivers这个库当中,在使用前最好先阅读readme.md文件

-

PVD 是一种检测MCU供电情况的技术。当供电电压高于或者低于一定阈值的时候,可以在寄存器上体现出来,或者直接产生硬件中断。
在实际使用MCU时,特别是电池供电的方案中,往往会遇到供电不够导致MCU或者外设工作不正常的情况。PVD在这个时候就可以派上用场了。
PVD的使用按照数据手册上的说明,就是首先设置PVD阈值(PVD thresholds),当MCU的VDD引脚的电压高于阈值时,则PVD output=1,当VDD电压低于阈值时,PVD output=0,如下图所示:

-

-

其中PVD output的结果可以再在存器中查看到

-


-

关于PVD的阈值的设定共有两种方式:

-
    -
  • 固定阈值(1.9V 2.1V 2.3V 2.5V 2.7V 2.9V 3.1V)
  • -
  • 与引脚比较(PB7)
  • -
-

在实际使用的过程中,PVD可以用查询挥着中断的方式来工作。

-

在测试的例程中,我配置PVD工作方式为中断上升下降沿触发,当VDD高于预设PVD阈值或者低于阈值而产生边沿触发时,都会形成一次PVD中断,然后读取PWR_CSR的PVDO标志位检查是低电压提醒还是高电压提醒,以此来达到监控MCU供电情况的目的。

-

注意:当使用PVD功能检测低电压时,VDD电压刚刚小于阈值时并不会直接产生PVD中断,只有当VDD电压小于(阈值-50MV)时,才会产生中断。

-

如果有什么疑问或者错误欢迎大家指正,email:454626653@qq.com

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/07/11/\346\236\204\345\273\272\344\273\245\345\270\247\344\270\272\345\215\225\344\275\215\347\232\204stack/index.html" "b/2016/07/11/\346\236\204\345\273\272\344\273\245\345\270\247\344\270\272\345\215\225\344\275\215\347\232\204stack/index.html" deleted file mode 100644 index ccaf326..0000000 --- "a/2016/07/11/\346\236\204\345\273\272\344\273\245\345\270\247\344\270\272\345\215\225\344\275\215\347\232\204stack/index.html" +++ /dev/null @@ -1,987 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 以帧为存储单位的循环stack | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - 以帧为存储单位的循环stack - - -

- - - -
- - - -
- - - - - -

此stack主要是作为存储空间使用,主要的借口就是push和pop。

-

stack frame的src以及例程位于stack_FrameTest这个库当中,其中有readme文件,可以快速上手。

-

stack构造及代码实现

其中我对stack以及frame的构造的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct Frame
{
uint8_t frame_len;//帧的字节数
uint8_t frame_data[MAX_TRANSMISSION_UINT];//一帧数据最大为MAX_TRANSMISSION_UINT字节
}Frame;
typedef struct STACK
{
int8_t frame_lastNum;//最新的帧的序号
uint8_t frame_count;//stack中未取出的帧的个数
Frame frame_info[MAX_STACK_FRAME_NUM];//stack中最多允许存储MAX_STACK_FRAME_NUM个帧
}STACK;

-

首先构造了一个stack,stack包含两个内容:

-
    -
  1. stack的统计信息:stack中帧的个数(frame_count),最新的帧的ID(frame_lastNum);
  2. -
  3. 数据存储区–一个数组,数据格式为Frame,容量为MAX_STACK_FRAME_NUM(frame_info[MAX_STACK_FRAME_NUM]);
  4. -
-

然后,帧的构造也包含了两个部分:

-
    -
  1. 此帧数据的字节数(frame_len);
  2. -
  3. 数据存储空间–数组,数据格式为uint8_t,容量为MAX_TRANSMISSION_UINT(frame_data[MAX_TRANSMISSION_UINT]);
  4. -
-

另外,此stack为一个循环栈,当stack存满之后仍有数据存入,并不会发生越界,而是会从头开始覆盖,此种操作,有利也有弊。

-

拼包机制

在最后,此例程中还写了一个拼包的机制,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//将stack中的数据进行拼包,在不造成断包的情况下最大限度地拼包
uint8_t SpliceFrame(uint8_t* dest)
{
uint8_t Splice_len = 0;
Splice_len = 0;
while(1)
{
//确保当前数据加下一帧数据不会超过最大单帧负载量(MTU)
if((Splice_len +Stack_GetFrameLastNum()) <= MAX_TRANSMISSION_UINT)
{
Splice_len +=Stack_PopData(dest+Splice_len);//
if(Stack_GetFrameCount() == 0)//当前融合帧的数量小于stack中已存帧的数量
break;
}
else
{
break;
}
}
return Splice_len;
}

-

思路就是假如当MTU=70,而如果收到的数据为10bytes,10bytes这样的短数据,我们就可以把这样的短数据由多个包拼接成一个包,一次性发送出去,提高通道的利用效率,因为一次发送70个字节所需的时间大约为5s,而一次发送10个字节的时间也基本等于5s,但是拼包的时候如果造成断包,在接收端处理会非常的麻烦,所以拼包机制制定成这样–在不造成断包以及不超过MTU的情况下最大限度地拼包。

-

有任何问题欢迎联系我。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/2016/07/21/74HC165/index.html b/2016/07/21/74HC165/index.html deleted file mode 100644 index a776778..0000000 --- a/2016/07/21/74HC165/index.html +++ /dev/null @@ -1,984 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 74HC165的级联以及MCU硬件SPI的通讯 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - 74HC165的级联以及MCU硬件SPI的通讯 - - -

- - - -
- - - -
- - - - - -

概述

74HC165作为常用的IO口扩展芯片,常用于并行IO口状态转串行数据。一块74HC165芯片可以连接8个IO口,将8个IO口状态转换成8位串行的数据传输给MCU。也就是说可以通过两个IO口获取到8个IO口的状态。
在电路设计中,也经常将74HC165芯片级联使用。通过芯片的级联,可以达到2个IO口读取16个IO口状态(2片级联)的效果,甚至更多。

-

由于74HC165的操作时序刚SPI的时序恰好相同,所以可以通过MCU的硬件SPI接口来操作74HC165芯片,这种通过MCU硬件接口来操作芯片的优点如下:

-
    -
  • 硬件的SPI时钟速度高,STM32芯片舌诊可以达到20MHZ,这样获取IO口状态的速度快,实时性更强
  • -
  • 扫描周期更短,可以使用在一些判断IO口状态的应用中,如扫描是否有物体高速穿过
  • -
-

软件的实现思路

由于使用的是MCU的硬件SPI接口,所以程序和MCU的型号会有较大关系,在这里,我以STM32F103RCT6为例。

-

步骤如下:

-
    -
  1. 将MCU的SPI复用IO口初始化
  2. -
  3. 配置SPI寄存器,示例代码如下:

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SPI_I2S_DeInit(SPI1);
    SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;// Receive-only mode
    SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//
    SPI_InitStructure.SPI_DataSize=SPI_DataSize_16b;// Data word = 16 bit wide
    SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;// Clock default level = L
    SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;// Latch on the first edge (rising from L)
    SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;// Software controls select SS signal, SS pin is GPIO
    SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4; // SPI_BaudRatePrescaler_4
    SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_LSB;// MSB first
    SPI_InitStructure.SPI_CRCPolynomial=7;// No CRC required
    SPI_Init(SPI1, &SPI_InitStructure);
    -

    其中需要注意的是分频的值和数据位长度,由于这边是2片级联,所以使用的是16b

    -
  4. -
  5. SPI读取,代码如下:

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    GPIOC->BSRR = GPIO_Pin_5;//片选选中
    while((SPI1->SR & SPI_I2S_FLAG_TXE) == 0);//判断数据发送完成
    SPI1->DR = 0xFFFF;
    while((SPI1->SR & SPI_I2S_FLAG_RXNE) == 0);//判断数据接受完成
    temp1 = SPI1->DR;
    GPIOC->BRR = GPIO_Pin_5;//片选取消选中
    -

    思路就是利用硬件的SPI时序以及SPI每写一位就会返回一位的特性,向74HC165芯片写入16bit的数据,便会在SPI寄存器中获取到两片级联的74HC165的状态。

    -
  6. -
- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/07/21/CJSON_JSON\345\214\205\347\232\204C\350\257\255\350\250\200\350\247\243\346\236\220\345\272\223/index.html" "b/2016/07/21/CJSON_JSON\345\214\205\347\232\204C\350\257\255\350\250\200\350\247\243\346\236\220\345\272\223/index.html" deleted file mode 100644 index 3bc0fbc..0000000 --- "a/2016/07/21/CJSON_JSON\345\214\205\347\232\204C\350\257\255\350\250\200\350\247\243\346\236\220\345\272\223/index.html" +++ /dev/null @@ -1,982 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cJSON_json包的C语言解析库 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - cJSON_json包的C语言解析库 - - -

- - - -
- - - -
- - - - - -

cJSON库描述

CJSON是一个用于解析JSON包的C语言库,库文件为cJSON.c和cJSON.h,
所有的实现都在这两个文件中。原作者的地址cJSON

-

JSON包的解析

例如有一个JSON的数据包如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"rxpk": [
{
"tmst": 1868500100,
"time": "2016-07-07T13:20:40.003906Z",
"chan": 1,
"rfch": 0,
"freq": 779.7,
"stat": 1,
"modu": "LORA",
"datr": "SF9BW125",
"codr": "4/5",
"lsnr": 9.8,
"rssi": -37,
"size": 83,
"data": "QH/4iimAKgACB0KHP8e0IgQAhI0bBi9bvFfb8jHeSWEAhpnsCGHwt9pUCvrRMazQRBtN+kh3Ge5hFL8jUtHpk3luFtcTLlgGVMPSBLpSp8h6C44="
}
]
}

-

我们需要获取其中的data字段,需要进行的过程如下:

-
    -
  1. 首先声明变量

    -
    1
    2
    3
    4
    cJSON *json;
    cJSON *rxpk;
    cJSON *arr0;
    cJSON *data;
    -
  2. -
  3. 将上述的字符串进行解析,并保存在json中;

    -
  4. -
  5. 获取json其中的rxpk字段的内容,并保存在rxpk中;
  6. -
  7. 获取rxpk中的arr部分,拿出一种的第一个数组,并保存在arr0;
  8. -
  9. 获取arr0的data部分,并保存在data;
  10. -
  11. 使用data->valuestring即可获取其中的data字段的内容
    具体的代码实现如下所示:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    uint16_t rxpk_data_get(char* text,char* dest_str)
    {
    uint16_t len = 0;
    cJSON *json;
    cJSON *data;
    cJSON *arr0;
    cJSON *rxpk;
    json= cJSON_Parse(text);
    if(!json)//对JSON包进行合法性检查
    return 0;
    rxpk = cJSON_GetObjectItem(json,"rxpk");
    if(!rxpk)//对rxpk进行合法性检查
    return 0;
    arr0 = cJSON_GetArrayItem(rxpk,0);
    if(!arr0)//对arr0进行合法性检查
    return 0;
    data =cJSON_GetObjectItem(arr0,"data");
    if(!data)//对data进行合法性检查
    return 0;
    len = strlen(data->valuestring);
    memcpy(dest_str,data->valuestring,len);
    dest_str[len] = 0;
    return len;
    }
    -
  12. -
-

在json包中遇到数组时

1
2
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);

-

这个函数可以获取数组的长度。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/2016/07/21/base64_C/index.html b/2016/07/21/base64_C/index.html deleted file mode 100644 index 9c995ca..0000000 --- a/2016/07/21/base64_C/index.html +++ /dev/null @@ -1,970 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - base64的C语言实现 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - base64的C语言实现 - - -

- - - -
- - - -
- - - - - -

首先谢谢这位大神的github,再谢谢这位大神分享的base64的C语言实现代码,库的地址在这里base64

-

其中提供的接口非常的简单明了

1
2
3
4
5
6
#define BASE64_ENCODE_OUT_SIZE(s) (((s) + 2) / 3 * 4)
#define BASE64_DECODE_OUT_SIZE(s) (((s)) / 4 * 3)
int base64_encode(const unsigned char *in, unsigned int inlen, char *out);
int base64_decode(const char *in, unsigned int inlen,char *out);

-

但是其中有一个问题,base64_decode();函数在返回时并没有返回解码后的字节数,在使用上会存在不方便的情况。

-

故,我把这个函数稍加修改之后,在解码之后返回解码数组的长度,在使用上就方便很多了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int base64_decode(const char *in, unsigned int inlen, char *out)
{
unsigned int i, j;
for (i = j = 0; i < inlen; i++) {
int c;
int s = i % 4; /* from 8/gcd(6, 8) */
if (in[i] == '=')
return j;
if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST ||
(c = base64de[in[i] - BASE64DE_FIRST]) == -1)
return j;
switch (s) {
case 0:
out[j] = ((unsigned int)c << 2) & 0xFF;
continue;
case 1:
out[j++] += ((unsigned int)c >> 4) & 0x3;
/* if not last char with padding */
if (i < (inlen - 3) || in[inlen - 2] != '=')
out[j] = ((unsigned int)c & 0xF) << 4;
continue;
case 2:
out[j++] += ((unsigned int)c >> 2) & 0xF;
/* if not last char with padding */
if (i < (inlen - 2) || in[inlen - 1] != '=')
out[j] = ((unsigned int)c & 0x3) << 6;
continue;
case 3:
out[j++] += (unsigned char)c;
}
}
return j;
}

-

使用代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
int main(void)
{
unsigned char input[] = "pleasure.";
unsigned char decode[13];
char output[13];
uint16_t len_decode = 0;
bzero(output, sizeof(output));
base64_encode(input, sizeof(input) - 1, output);
len_decode = base64_decode(output, sizeof(output) - 1, decode);
return 0;
}

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/07/24/LoRaWAN\345\215\217\350\256\256(\344\270\200)--\346\236\266\346\236\204/index.html" "b/2016/07/24/LoRaWAN\345\215\217\350\256\256(\344\270\200)--\346\236\266\346\236\204/index.html" deleted file mode 100644 index 9246f50..0000000 --- "a/2016/07/24/LoRaWAN\345\215\217\350\256\256(\344\270\200)--\346\236\266\346\236\204/index.html" +++ /dev/null @@ -1,999 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN解析(一)--架构解析 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN解析(一)--架构解析 - - -

- - - -
- - - -
- - - - - -

LoRaWAN 分层

LoRaWAN从底层到最后用户拿到数据的通讯过程通讯大致可分为三段:

-
    -
  1. MOTE <—> GW (MAC层)
  2. -
  3. GW <—> NS
  4. -
  5. NS <—> Customer
  6. -
-

LoRa联盟 规定了 MAC层的通讯协议,只有在设备(GW、MOTE)共同遵守的MAC层协议的前提下,不同硬件厂商的设备才能互相接入。

-

而GW <—> NS以及NS <—> Customer这两层的协议虽然LoRa联盟有所规范,但不同厂商之间可能会存在不同。

-

应用分析

在这里我以LoRaWAN 方式实现农场的土壤湿度检测来做说明。
实现农场的土壤湿度的检测主要分为几个步骤:

-
    -
  • 实现传感器采集土壤湿度(sensor层)
  • -
  • 将采集到的土壤湿度通过MOTE发送给GW(LoRaMac 层)
  • -
  • GW将收到的数据发送给NS(GW<—>NS)
  • -
  • NS再将数据发送给用户(NS<—>Customer)
  • -
  • 用户通过APP或者其他方式可以看到土壤的湿度状态。(Display)
  • -
-

通过以上的几个步骤,就可以实现远程监控农场土壤湿度。

-

好了,第一讲非常的简单。只是讲解了LoRaWAN 作为IOT的一种方式,其中的数据流向。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/07/26/MPU9250\350\260\203\350\257\225/index.html" "b/2016/07/26/MPU9250\350\260\203\350\257\225/index.html" deleted file mode 100644 index 4422955..0000000 --- "a/2016/07/26/MPU9250\350\260\203\350\257\225/index.html" +++ /dev/null @@ -1,1009 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MPU9250调试 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - MPU9250调试 - - -

- - - -
- - - -
- - - - - -

MPU9250 芯片概述

MPU9250芯片是一个9轴姿态传感芯片,其中包含了3轴加速度传感器、3轴角速度传感器以及三轴磁力计。
其本质上是MPU6050芯片+AK8963。

-

可以获取传感芯片的加速度、角速度、以及磁力值。

-

角速度可以知芯片的转动速度,加速度可以知道芯片运动的距离、速度情况,而磁力计可以知道物芯片的运动方向。

-

另外MPU9250芯片内置DMP姿态融合器,可以在不涉及算法的情况下,直接读取出描述物体状态的四元数,从而得出物体的三维角度–航向角、翻滚角、俯仰角。

-

驱动程序的设计

由于MPU9250芯片使用的是I2C接口,所以在这里,我首先需要I2C的驱动。

-

在我的驱动中,I2C使用GPIO口模拟的,因为这样在以后移植时更加方便。

-

在完成IOI2C的驱动之后,就是对MPU9250的寄存器进行操作,来成功获取传感数据。

-

MPU9250的寄存器操作

操作MPU9250寄存器并且开启DMP模式,获取三维角度,其步骤如下:

-
    -
  1. 复位,配置PWR_MGMT_1 0x80,延时一段时间
  2. -
  3. 配置PWR_MGMT_1(一般为00,表示使用内部晶振20Mhz)
  4. -
  5. 设置采样频率
  6. -
  7. 设置量程(角速度、加速度量程)
  8. -
  9. 外部中断打开,并且配置成相应的工作方式
  10. -
  11. 开启DMP,以及FIFO
  12. -
-

其中DMP的开启需要密码,而且具体的操作方法及寄存器在数据手册上都无法找到,是本人在网站经过查找融合了多人的驱动调试出来的。

-

代码调用

本人将调通之后的代码整理之后,只需调用几个API就可以实现参数的获取了。

-

主要分为两步:

-
    -
  1. 初始化
  2. -
-
1
2
3
IIC_Init();//模拟I2C驱动的初始化,一定要先初始化I2C接口才能操作MPU9250芯片
Init_MPU9250_With_DMP();//初始化MPU9250,配置并且开启DMP,设置中断方式为加速度方式
-
    -
  1. 函数调用
  2. -
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
while(1)
{
fifo_count = MPU9250_getFIFOCount();//读取FIFO计数
if(fifo_count >= 0x0200)//如果FIFO值>0x0200,此时DMP的结果错误,直接复位FIFO
{
MPU9250_resetFIFO();
}
else
{
if(fifo_count >= 0x2a)//如果FIFO值 > 0x2a,此时DMP转换完成并且数值正常
{
readdmp(); //首先要读取DMP FIFO,读取之后才能进行计算姿态的操作
MPU9250_resetFIFO();
getyawpitchroll();//计算并且获取yaw、pitch、roll,结果保存在yprf[3]数组中
}
}
}
-

NOTE:

-
    -
  • 在判断DMP是否完成时,应当从FIFO的计数中去判断,当计数大于等于42,说明DMP转换完成,也可以采用中断的方式来作为标志。

    -
  • -
  • 本例程中使用的I2C为GPIO模拟的I2C,主要是移植方便,但是在将此驱动移植到不同平台时需要注意寄存器以及引脚的定义。

    -
  • -
  • 注意芯片上电之后需要先复位,即设置PWR_MGMT_1为0x80,过一段时间之后再设置为0x00,否则有时芯片会工作异常

    -
  • -
-

具体的程序在我的代码库中,欢迎大家能找出其中的不足,E-mail给我。

-

代码链接如下:
MPU9250-MPU6050驱动

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/07/29/LoRaWAN\345\215\217\350\256\256(\344\272\214)--LoRaWAN MAC\350\247\243\346\236\220/index.html" "b/2016/07/29/LoRaWAN\345\215\217\350\256\256(\344\272\214)--LoRaWAN MAC\350\247\243\346\236\220/index.html" deleted file mode 100644 index 85f5888..0000000 --- "a/2016/07/29/LoRaWAN\345\215\217\350\256\256(\344\272\214)--LoRaWAN MAC\350\247\243\346\236\220/index.html" +++ /dev/null @@ -1,1012 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN架构解析(二)--LoRaWAN MAC解析 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN架构解析(二)--LoRaWAN MAC解析 - - -

- - - -
- - - -
- - - - - -

名词解析

上行:终端的数据发送经过一个或多个网关中转到达网络服务器。
下行:由网络服务器发送给终端设备,每条消息对应的终端设备是唯一确定的,而且只通过一个网关中转。

-

LoRaWAN Classes

LoRaWAN Classes 一共分为3类:Class A,Class B,Class C

-

Class A:终端先发送,在发送后开启一段时间的接收窗口,终端只有在发送后才可以接收。也就是说上行没有限制,下行的数据只有在上行包发送上来的时候终端才可以接收到。(功耗最低)

-

Class B:终端和服务器协商好接收的窗口开启的时间以及何时开启,然后再约定的时间进行接收,可以一次接收多个包。(功耗次低)

-

Class C:终端在发送以外的其他时间都开启接收窗口。更耗能,但通讯延时最低。(功耗最高)

-

PHY 层数据链路

上行链路消息:

-

上行链路消息:

-

其中上行最后还有CRC校验,而下行没有CRC校验。其中PHDR PHDR_CRC CRC都是射频芯片用于校准数据的完整新和一致性用的,并非用户生成的数据。

-

MAC 层数据链路

-

由上图可以看到,MAC数据是是作为PHYPayload存在的
其中MAC 层的包有三个部分组成:

-
    -
  • MHDR(MAC层帧头)
  • -
  • MACPayload(MAC层负载)
  • -
  • MIC(4字节的校验)
  • -
-

而MACPayload又由三个部分组成:

-
    -
  • FHDR (MAC层负载头)
  • -
  • FPORT(MAC 层数据的通道号)
  • -
  • FRMPayload(MAC层负载,加密)
  • -
-

而FHDR又由由四个部分组成:

-
    -
  • DevAddr(终端的ID 4字节)
  • -
  • FCtrl(帧的控制字 1个字节)
  • -
  • FCnt (帧的序号 2个字节)
  • -
  • FOpts(帧配置,字节数不定,大部分情况0个字节)
  • -
-

所以,由协议可知,一个上行包或者下行包中的数据内容有哪些,抛开控制命令不说,主要有终端的ID、包的序号、用户的加密负载。

-

例如我抓到的一个数据包:

-

\x40 \x7f \xf8 \x8a \x29 \x80 \x2a \x00 \x02 \x07 \x42 \x87 \x3f \xc7 \xb4 \x22 \x04 \x00 \x84 \x8d \x1b \x06 \x2f \x5b \xbc \x57 \xdb \xf2 \x31 \xde \x49 \x61 \x00 \x86 \x99 \xec \x08 \x61 \xf0 \xb7 \xda \x54 \x0a \xfa \xd1 \x31 \xac \xd0 \x44 \x1b \x4d \xfa \x48 \x77 \x19 \xee \x61 \x14 \xbf \x23 \x52 \xd1 \xe9 \x93 \x79 \x6e \x16 \xd7 \x13 \x2e \x58 \x06 \x54 \xc3 \xd2 \x04 \xba \x52 \xa7 \xc8 \x7a \x0b \x8e

-

这是一个MAC 层的帧即完整的MACPayload部分

-

其中

-
    -
  • MHDR:
    \x40
  • -
  • MACPayload-FHDR-DevAddr:
    \x7f \xf8 \x8a \x29
  • -
  • MACPayload-FHDR-FCtrl:
    \x80
  • -
  • MACPayload-FHDR-FCnt:
    \x2a \x00
  • -
  • MACPayload-FPORT:
    \x02
  • -
  • MACPayload-FRMPayload(加密):
    \x07 \x42 \x87 \x3f \xc7 \xb4 \x22 \x04 \x00 \x84 \x8d \x1b \x06 \x2f \x5b \xbc \x57 \xdb \xf2 \x31 \xde \x49 \x61 \x00 \x86 \x99 \xec \x08 \x61 \xf0 \xb7 \xda \x54 \x0a \xfa \xd1 \x31 \xac \xd0 \x44 \x1b \x4d \xfa \x48 \x77 \x19 \xee \x61 \x14 \xbf \x23 \x52 \xd1 \xe9 \x93 \x79 \x6e \x16 \xd7 \x13 \x2e \x58 \x06 \x54 \xc3 \xd2 \x04 \xba \x52 \xa7
  • -
  • MIC:
    \xc8 \x7a \x0b \x8e
  • -
- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/2016/10/10/semtech_LoRaWAN_timer/index.html b/2016/10/10/semtech_LoRaWAN_timer/index.html deleted file mode 100644 index 053ee74..0000000 --- a/2016/10/10/semtech_LoRaWAN_timer/index.html +++ /dev/null @@ -1,1128 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN源码阅读笔记————RTC闹钟链表的实现 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN源码阅读笔记————RTC闹钟链表的实现 - - -

- - - -
- - - -
- - - - - -

近日在阅读semtech的Lora-net/LoRaMac-node。此代码是LoRaWAN MAC层的node段的代码。

-

此代码中构建了一个定时器链表,此链表构建得非常的巧妙。
通过对源码的阅读,明白了其底层的实现原理,现在讲解一下,和大家分享。

-

此定时器链表底层使用的是RTC的闹钟(Alarm)机制(将日历时间转换成时间戳时间),而非使用一个定时器产生一个固定的定时(比如1ms),然后定时刷新整个链表。

-

用rtc的方法相比较嘀嗒定时器定时的方法,工作效率会明显提升,并不会因为链表中定时器数目的增加使得花费在刷新定时器上的时间增加,因为不需要遍历整个链表。但代码的实现难度会较高

-

假如程序刚开始执行,而且定时器链表为空,此时有4个定时事件需要放入链表,分别为 A 10ms B 30ms C 20ms D 40ms,

-

RTC闹钟链表:
其存储的结果会是这样:

- - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A10
C10
B10
D10
-

而嘀嗒定时链表:
其存储的结果会是这样:

- - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A10
B30
C20
D40
-

当时间过了5ms,RTC闹钟链表中存储的数据并不会发生任何变化,因为它是以RTC的闹钟来作为刷新依据的,而嘀嗒定时链表中的数据就全发生了变化
嘀嗒定时链表 变化得到情况如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A5
B25
C15
D35
-

再过5ms,此时A事件的定时时间就到了,需要被执行,在RTC闹钟链表中的表现是RTC Alarm中断触发,在嘀嗒定时链表中的表现是A事件的定时时间逐渐减少至0。当A事件被执行之后两种定时器链表中的存储都发生了变化,都是原先的链表的头指针指向原先的第二个节点,而原先的头节点被释放。

-

还是上述的例子,在定时器执行了7ms的时候,这时有个事件需要插入,为E 24ms,此时,两种链表对于此事件器的插入操作也会明显不同。

-

RTC闹钟插入之后

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A10
C10
B10
E1
D9
-

而嘀嗒定时器在插入之后为

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A3
B13
C23
D33
E24
-

以下是RTC闹钟的部分插入代码,其中可以看到他的定时器插入的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
elapsedTime = TimerGetValue( );//获取距离上一次设置闹钟的时间
remainingTime = TimerListHead->Timestamp - elapsedTime;//remainingTime表示剩余的头节点中的事件剩余的定时事件,因为此链表是按顺序存储的,所以头节点中的定时时间一定是最少的
static void TimerInsertNewHeadTimer( TimerEvent_t *obj, uint32_t remainingTime )
{
TimerEvent_t* cur = TimerListHead;
if( cur != NULL )//表头不为空,将新的定时器插入之前,将原先表头的定时器时间减去新定时器的定时时间,确保原先的定时器任务定时正常
{
cur->Timestamp = remainingTime - obj->Timestamp;
cur->IsRunning = false;
}
obj->Next = cur;
obj->IsRunning = true;
TimerListHead = obj;
TimerSetTimeout( TimerListHead );//设置超时,等时间到的时候,会发生RTC报警
}

-

另外还有一点,此RTC中的1s并非物理时间的1s,在此具体的时间基准如下:
此项目中,使用的RTC的时钟源为32.768Khz的LSE,通过AsynchPrediv和SynchPrediv分频得到2.048KHz的RTCtick,计算公式为32.768/(3+1)/(3+1) = 2.048;
相关的配置代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
void RtcInit( void )
{
...
RtcHandle.Init.AsynchPrediv = 3;
RtcHandle.Init.SynchPrediv = 3;
...
}
/*!
* RTC Time base in ms
*/
#define RTC_ALARM_TICK_DURATION 0.48828125 // 1 tick every 488us
#define RTC_ALARM_TICK_PER_MS 2.048 // 1/2.048 = tick duration in ms

-

由于原本每个tick相当于1s,而在这里,每个tick相当于0.48828125ms,小于1ms,所以在程序中能够实现ms级的定时任务。

-

RTC定时器的用法主要分为三步:

-
1. 初始化,注册回调函数
-    void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) )//设置回调函数
-2. 设置定时时间
-    void TimerSetValue( TimerEvent_t *obj, uint32_t value )
-3. 开启定时时间
-    void TimerStart( TimerEvent_t *obj )
-
- -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/11/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260(\344\270\200)_RF\347\241\254\344\273\266\347\233\270\345\205\263/index.html" "b/2016/10/11/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260(\344\270\200)_RF\347\241\254\344\273\266\347\233\270\345\205\263/index.html" deleted file mode 100644 index 4c08766..0000000 --- "a/2016/10/11/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260(\344\270\200)_RF\347\241\254\344\273\266\347\233\270\345\205\263/index.html" +++ /dev/null @@ -1,995 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN_stack移植笔记(一)--RF硬件相关 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN_stack移植笔记(一)--RF硬件相关 - - -

- - - -
- - - -
- - - - - -

和硬件相关的问题

TCXO 的使用

根据SX1276数据手册,

-
    -
  • 如果使用TCXO,则需要配置RegTcxo寄存器为0x19,代码如下

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void SX1276SetTcxoConfig(void)//此函数为自定义的
    {
    SX1276Write( REG_TCXO, 0x19 ); //设置TCXO
    }
    //在初始化中调用
    void SX1276Init( RadioEvents_t *events )
    {
    ...
    SX1276SetTcxoConfig();
    ...
    }
    -
  • -
  • 否则配置为0x09,因为芯片上电默认不使用TCXO,即上电寄存器值即为0x09,所以无需配置

    -
  • -
-

PA_BOOST 引脚的使用

根据sx1276 数据手册

-
    -
  • 如果使用PA_BOOST作为RF输出,则需要配置PaSelect脚为1
  • -
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void SX1276SetTxConfig(......)
{
...
paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1276GetPaSelect( SX1276.Settings.Channel );//选择是否使用PA_BOOST引脚
...
}
//根据具体的电路图不一样,此函数也会币一样,比如低频使用PA_BOOST,高频使用RFO_HF,则函数体如下
uint8_t SX1276GetPaSelect( uint32_t channel )
{
//如果是低频的,使用PA_BOOST,高频使用RFO_HF
if( channel < RF_MID_BAND_THRESH )
{
return RF_PACONFIG_PASELECT_PABOOST;
}
else
{
return RF_PACONFIG_PASELECT_RFO;
}
}
//如果高低频都使用PA_BOOST,则函数体如下
uint8_t SX1276GetPaSelect( uint32_t channel )
{
return RF_PACONFIG_PASELECT_PABOOST;
}
//如果高频使用PA_BOOST,低频使用RFO_LF,则函数体如下
uint8_t SX1276GetPaSelect( uint32_t channel )
{
//如果是高频的,使用PA_BOOST,低频使用RFO_LF
if( channel > RF_MID_BAND_THRESH )
{
return RF_PACONFIG_PASELECT_PABOOST;
}
else
{
return RF_PACONFIG_PASELECT_RFO;
}
}
/*!
* RegPaConfig
*/
#define RF_PACONFIG_PASELECT_MASK 0x7F
#define RF_PACONFIG_PASELECT_PABOOST 0x80
#define RF_PACONFIG_PASELECT_RFO 0x00 // Default
-
    -
  • 否则为0
  • -
-

RXTX switch(接收和发送的天线电路的切换)


在图中可以看到,射频输入和射频输出是不一样的电路,但是用的是一个天线,所以用到了一个射频电路切换的芯片。
在程序中,需要做的就是控制FEM_CPS脚,在RX和TX时进行RF1(RFI)和RF2(RFO)的切换。
由于在设计中兼容高低频,并且使用两个引脚分别控制高频和低频部分的射频部分输入输出的切换,所以在实际使用中需要控制两个引脚。

1
2
3
4
5
6
7
8
9
10
11
12
13
void SX1276SetAntSw( uint8_t rxTx )
{
if( rxTx != 0 ) // 1: TX, 0: RX
{
GpioWrite( &AntSwitchLf, 0 );//切换到低频发射电路
GpioWrite( &AntSwitchHf, 1 );//切换到高频发射电路
}
else
{
GpioWrite( &AntSwitchLf, 1 );//切换到低频接收电路
GpioWrite( &AntSwitchHf, 0 );//切换到高频接收电路
}
}

-

如果只有高频或者低频一个部分,上面的代码只要保留相应的部分即可

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/11/STM32\346\227\266\351\222\237\346\272\220\351\205\215\347\275\256/index.html" "b/2016/10/11/STM32\346\227\266\351\222\237\346\272\220\351\205\215\347\275\256/index.html" deleted file mode 100644 index db01288..0000000 --- "a/2016/10/11/STM32\346\227\266\351\222\237\346\272\220\351\205\215\347\275\256/index.html" +++ /dev/null @@ -1,1006 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STM32时钟配置--系统时钟、RTC时钟、IWDG时钟 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - STM32时钟配置--系统时钟、RTC时钟、IWDG时钟 - - -

- - - -
- - - -
- - - - - -

stm32L0x1的时钟分类


先给大家推荐一个软件STM32CubeMX,上面的那张关于时钟的图就是从这个软件中截图得来的,这个软件还可以查看配置的时钟情况以及时钟树,挺方便的。

-

从图上,可以看出,STM32的始终源一共有HSE、HSI、LSE、LSI、MSI、PLL六种,
其中

-
    -
  • HSE是外部的高速晶振,可以直接使用或者通过PLL倍频,最终输出不能超过32Mhz
  • -
  • HSI是内部的高速RC振荡器,频率为16Mhz,可以直接使用或者通过PLL倍频,最终输出不能超过32Mhz
  • -
  • LSE是外部的低速晶振,可以用于RTC或者IWDG,频率为32.768KH在
  • -
  • LSI是内部的低速RC振荡器,频率约为37KHz
  • -
  • MSI是内部的RC振荡器,其频率编程可调
  • -
  • PLL是一个锁相环,可以将HSE或HSI倍频之后再给系统提供时钟。
  • -
-

其中注意的是,内部时钟的精度都比较差,在对时钟要求比较高的场合,建议使用外部晶振

-

系统时钟源


从图中可以看到,系统时钟的选择有

-
    -
  • MSI(65.536 kHz, 131.072 kHz, 262.144 kHz, 524.288 kHz, 1.048 MHz,
    2.097 MHz (default value) and 4.194 MHz)
  • -
  • HSI(16,16/4)
  • -
  • HSE(1-24MHz)
  • -
  • PLLCLK(HSE/HSI倍频锁相环)
  • -
-

其中PLLCLK是比较常用的一种,可以将HSE或HSI(HSI/4)倍频,然后再给主系统提供时钟。
其计算公式为PLLCLK_OUT = (PLLCLK_SOURCE * PLLMUL / PLLDIV);

-

例如要给系统提供32MHz的晶振,可以

-
    -
  • HSI(16) * 4(PLLMUL) / 2(PLLDIV)
  • -
  • HSE(12) * 8(PLLMUL) / 3(PLLDIV)
  • -
-

以上两种方法只是举个例子,倍频的方法并不是固定的。

-

注意,实际使用中,这四个时钟源只能同时选择一个,不能同时选择多个。

-

RTC时钟源 IWDG 时钟源

-

从图中可以看到,IWDG只能使用LSI提供时钟源
而RTC可以使用HSE/32(数据手册上查看得来,软件存在明显错误)、LSE、LSI提供时钟源,其中LSE 的频率为32.768KHz,LSI的频率为37KHz。

-

具体的RTC和IWDG的工作时钟还要进行分频。
RTC的工作时钟的计算方法为:Fck_spre = Frtcclk/(PREDIV_S+1)/(PREDIV_A+1);

-

例如Frtcclk(时钟源频率)为32.768Khz的LSE,PREDIV_S = 3, PREDIV_A =3,则Fck_spre(工作频率) = 32.768/(3+1)/(3+1) = 2.048KHz

1
2
3
4
5
6
7
8
9
10
11
12
13
void RtcInit( void )
{
...
RtcHandle.Init.AsynchPrediv = 3;
RtcHandle.Init.SynchPrediv = 3;
...
}
/*!
* RTC Time base in ms
*/
#define RTC_ALARM_TICK_DURATION 0.48828125 // 1 tick every 488us
#define RTC_ALARM_TICK_PER_MS 2.048 // 1/2.048 = tick duration in ms

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/13/STM32_NVIC\347\232\204\351\205\215\347\275\256/index.html" "b/2016/10/13/STM32_NVIC\347\232\204\351\205\215\347\275\256/index.html" deleted file mode 100644 index 555706c..0000000 --- "a/2016/10/13/STM32_NVIC\347\232\204\351\205\215\347\275\256/index.html" +++ /dev/null @@ -1,976 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STM32_NVIC设置 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - STM32_NVIC设置 - - -

- - - -
- - - -
- - - - - -

接口

1
2
3
4
5
6
7
8
//设置中断的抢占优先级
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
//使能中断
static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn);
//设置优先级组
static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
-

常用的配置中断优先级的函数就是三个,其中最常用的就是两个:

1
2
3
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn);

-

因为NVIC默认就是是组4,可以不用设置,即四位抢占优先级,0位响应优先级

-

优先级冲突的处理

    -
  • 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断;
  • -
  • 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这个两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;
  • -
  • 如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个;
  • -
-

使用方法

例如:
NVIC_SetPriority(UART1_IRQn,2);

-

NVIC_EnableIRQ(UART1_IRQn);

-

NVIC_SetPriority(UART0_IRQn,9);
NVIC_EnableIRQ(UART0_IRQn);
设置UART1_IRQn的优先级为2,UART0_IRQn的优先级为9,并且使能中断。

-

其中,抢占优先级的数字越低,优先级越高

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\344\270\211)__SPI/index.html" "b/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\344\270\211)__SPI/index.html" deleted file mode 100644 index 7f2fa02..0000000 --- "a/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\344\270\211)__SPI/index.html" +++ /dev/null @@ -1,982 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN_stack移植笔记(三)__SPI | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN_stack移植笔记(三)__SPI - - -

- - - -
- - - -
- - - - - -

stm32相关的配置

由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱动所以做修改。

-

SPI 的配置

SPI使用的是STM32的硬件接口-SPI1 MOSI MISO
可以看到例程中,对SPI接口进行了再一层的封装,封装如下:

1
2
3
4
5
6
7
8
9
10
11
/*!
* SPI driver structure definition
*/
struct Spi_s
{
SPI_HandleTypeDef Spi;
Gpio_t Mosi;
Gpio_t Miso;
Gpio_t Sclk;
Gpio_t Nss;
};

-

其中:

1
SPI_HandleTypeDef Spi;

-

是原先的STM32Cube库的封装,在此基础上,将SPI的引脚也封装进了自定义的Spi_s结构体中。这样,查看结构体就可以看到SPI的所有情况。

-

SPI 初始化配置

初始化的函数体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss )
{
__HAL_RCC_SPI1_FORCE_RESET( );
__HAL_RCC_SPI1_RELEASE_RESET( );
__HAL_RCC_SPI1_CLK_ENABLE( );
obj->Spi.Instance = ( SPI_TypeDef *) SPI1_BASE;
GpioInit( &obj->Mosi, mosi, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF0_SPI1 );
GpioInit( &obj->Miso, miso, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF0_SPI1 );
GpioInit( &obj->Sclk, sclk, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF0_SPI1 );
if( nss != NC )
{
GpioInit( &obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF0_SPI1 );
}
else
{
obj->Spi.Init.NSS = SPI_NSS_SOFT;
GpioInit( &SX1276.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
}
if( nss == NC )
{
SpiFormat( obj, SPI_DATASIZE_8BIT, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 0 );
}
else
{
SpiFormat( obj, SPI_DATASIZE_8BIT, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 1 );
}
obj->Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
HAL_SPI_Init( &obj->Spi );
}
``` c
SPI的初始化函数是这样被调用的:
``` c
SpiInit( &SX1276.Spi, RADIO_MOSI, RADIO_MISO,RADIO_SCLK, NC );
//初始化函数的原型
void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss );

-

其中引脚定义是这样的

1
2
3
4
#define RADIO_MOSI PA_7
#define RADIO_MISO PA_6
#define RADIO_SCLK PA_5
#define RADIO_NSS PA_4

-

可以看到SPI的MOSI/MISO/SCLK脚都有看到,但是NSS脚看到,而是传了NC。

-

这是为什么呢?
可以看到程序里面有段话

1
2
3
4
5
6
7
8
9
if( nss != NC )
{
GpioInit( &obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF0_SPI1 );
}
else
{
obj->Spi.Init.NSS = SPI_NSS_SOFT;
GpioInit( &SX1276.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
}

-

其意思就是设置为NC就配置NSS 为软件控制,即NSS脚只做片选使用,x像GPIO一样控制他拉高拉低就可以控制片选的使能与否了。

-

还有一处,设置SPI的工作频率的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SpiFrequency( obj, 10000000 );
void SpiFrequency( Spi_t *obj, uint32_t hz )
{
uint32_t divisor;
divisor = SystemCoreClock / hz;
// Find the nearest power-of-2
divisor = divisor > 0 ? divisor-1 : 0;
divisor |= divisor >> 1;
divisor |= divisor >> 2;
divisor |= divisor >> 4;
divisor |= divisor >> 8;
divisor |= divisor >> 16;
divisor++;
divisor = __ffs( divisor ) - 1;
divisor = ( divisor > 0x07 ) ? 0x07 : divisor;
obj->Spi.Init.BaudRatePrescaler = divisor << 3;
}

-

由于ffs这个函数只有Cotex-M3以上内核才能调用,但是通过计算可知若传参为10000000,ffs这个函数的返回值为0x03,所以可得obj->Spi.Init.BaudRatePrescaler = 8,即SPI_BAUDRATEPRESCALER_8
因为

1
2
3
#define SPI_BAUDRATEPRESCALER_8 ((uint32_t)SPI_CR1_BR_1)
#define SPI_CR1_BR_1 (0x2U << SPI_CR1_BR_Pos)
#define SPI_CR1_BR_Pos (3U)

-

所以此处设置Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
最后再调用

1
HAL_SPI_Init( &obj->Spi );

-

至此,SPI的初始化就完成了。

-

SPI 读写

接下来就是SPI的读写操作了,由于都是使用的Cube库,对寄存器的命名并没有什么不同,直接保留例程中的代码就可以了。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//获取SPI的标志位状态
FlagStatus SpiGetFlag( Spi_t *obj, uint16_t flag )
{
FlagStatus bitstatus = RESET;
// Check the status of the specified SPI flag
if( ( obj->Spi.Instance->SR & flag ) != ( uint16_t )RESET )
{
// SPI_I2S_FLAG is set
bitstatus = SET;
}
else
{
// SPI_I2S_FLAG is reset
bitstatus = RESET;
}
// Return the SPI_I2S_FLAG status
return bitstatus;
}
//SPI读写
uint16_t SpiInOut( Spi_t *obj, uint16_t outData )
{
uint8_t rxData = 0;
if( ( obj == NULL ) || ( obj->Spi.Instance ) == NULL )
{
assert_param( FAIL );
}
__HAL_SPI_ENABLE( &obj->Spi );
while( SpiGetFlag( obj, SPI_FLAG_TXE ) == RESET );
obj->Spi.Instance->DR = ( uint16_t ) ( outData & 0xFF );
while( SpiGetFlag( obj, SPI_FLAG_RXNE ) == RESET );
rxData = ( uint16_t ) obj->Spi.Instance->DR;
return( rxData );
}
-

在使用上,需要注意NSS引脚的操作,在进行读写前进行使能,读写完毕之后失能。程序如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//SPI写
void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
//NSS = 0;
GpioWrite( &SX1276.Spi.Nss, 0 );
SpiInOut( &SX1276.Spi, addr | 0x80 );
for( i = 0; i < size; i++ )
{
SpiInOut( &SX1276.Spi, buffer[i] );
}
//NSS = 1;
GpioWrite( &SX1276.Spi.Nss, 1 );
}
//SPI读
void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
//NSS = 0;
GpioWrite( &SX1276.Spi.Nss, 0 );
SpiInOut( &SX1276.Spi, addr & 0x7F );
for( i = 0; i < size; i++ )
{
buffer[i] = SpiInOut( &SX1276.Spi, 0 );
}
//NSS = 1;
GpioWrite( &SX1276.Spi.Nss, 1 );
}

-

至此,LoRaWAN例程中的SPI的移植就完成了。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\344\272\214)_GPIO/index.html" "b/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\344\272\214)_GPIO/index.html" deleted file mode 100644 index cd87c3b..0000000 --- "a/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\344\272\214)_GPIO/index.html" +++ /dev/null @@ -1,984 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN_stack移植笔记 (二)_GPIO | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN_stack移植笔记 (二)_GPIO - - -

- - - -
- - - -
- - - - - -

stm32相关的配置

由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱动所以做修改。另外例程中对STM32库函数的再一次封装的方法也非常值得学习。

-

GPIO 的配置

1
GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF0_USART1 );
-

例程中可以看到,对IO口的初始化只有这一句,是因为例程中对GPIO的操作进行了封装,方便了上层的使用。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*!
* Board GPIO pin names
*/
typedef enum
{
MCU_PINS,
IOE_PINS,
// Not connected
NC = (int)0xFFFFFFFF
}PinNames;
/*!
* STM32 Pin Names
*/
#define MCU_PINS \
PA_0 = 0, PA_1, PA_2, PA_3, PA_4, PA_5, PA_6, PA_7, PA_8, PA_9, PA_10, PA_11, PA_12, PA_13, PA_14, PA_15, \
PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8, PB_9, PB_10, PB_11, PB_12, PB_13, PB_14, PB_15, \
PC_0, PC_1, PC_2, PC_3, PC_4, PC_5, PC_6, PC_7, PC_8, PC_9, PC_10, PC_11, PC_12, PC_13, PC_14, PC_15, \
PD_0, PD_1, PD_2, PD_3, PD_4, PD_5, PD_6, PD_7, PD_8, PD_9, PD_10, PD_11, PD_12, PD_13, PD_14, PD_15, \
PE_0, PE_1, PE_2, PE_3, PE_4, PE_5, PE_6, PE_7, PE_8, PE_9, PE_10, PE_11, PE_12, PE_13, PE_14, PE_15, \
PF_0, PF_1, PF_2, PF_3, PF_4, PF_5, PF_6, PF_7, PF_8, PF_9, PF_10, PF_11, PF_12, PF_13, PF_14, PF_15, \
PH_0, PH_1, PH_2, PH_3, PH_4, PH_5, PH_6, PH_7, PH_8, PH_9, PH_10, PH_11, PH_12, PH_13, PH_14, PH_15
-

例程中使用Enum定义了64个IO口,其中

-
    -
  • 0-15 表示PA0-15
  • -
  • 16-31表示PB0-15
  • -
  • 32-47表示PC0-15
  • -
  • 48-63表示PD0-15
  • -
  • 64-79表示PE0-15
  • -
  • 80-95表示PF0-15
  • -
  • 96-111表示PH0-15
  • -
-

这样,在定义引脚的时候直接是用Enum变量就可以表示出IO的PIN以及PORT,在完成驱动程序之后,操作引脚非常的方便。

-

例如 使用了一个LED灯,连接的是PB_5,这样我们#define LED PB_5,在程序里面就可以得知使用的是PB口,以及PIN_5,方法如下:

-
由于PB_5 = 16+5 = 21;
-21/16 = 1,得知使用的是PB口,21%16 = 5,得知使用的是PIN_5。
-

其中C语言的时下代码如下,使用(&0xff)以及<<的操作,效率比做除法及取模的效率更高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
void GpioMcuInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, uint32_t value )
{
GPIO_InitTypeDef GPIO_InitStructure;
if( pin == NC )
{
return;
}
obj->pin = pin;
obj->pinIndex = ( 0x01 << ( obj->pin & 0x0F ) );
if( ( obj->pin & 0xF0 ) == 0x00 )
{
obj->port = GPIOA;
__HAL_RCC_GPIOA_CLK_ENABLE( );
}
else if( ( obj->pin & 0xF0 ) == 0x10 )
{
obj->port = GPIOB;
__HAL_RCC_GPIOB_CLK_ENABLE( );
}
else if( ( obj->pin & 0xF0 ) == 0x20 )
{
obj->port = GPIOC;
__HAL_RCC_GPIOC_CLK_ENABLE( );
}
else if( ( obj->pin & 0xF0 ) == 0x30 )
{
obj->port = GPIOD;
__HAL_RCC_GPIOD_CLK_ENABLE( );
}
else
{
obj->port = GPIOH;
__HAL_RCC_GPIOH_CLK_ENABLE( );
}
GPIO_InitStructure.Pin = obj->pinIndex ;
GPIO_InitStructure.Pull = type;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
if( mode == PIN_INPUT )
{
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
}
else if( mode == PIN_ANALOGIC )
{
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
}
else if( mode == PIN_ALTERNATE_FCT )
{
if( config == PIN_OPEN_DRAIN )
{
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
}
else
{
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
}
GPIO_InitStructure.Alternate = value;
}
else // mode ouptut
{
if( config == PIN_OPEN_DRAIN )
{
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
}
else
{
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
}
}
HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
// Sets initial output value
if( mode == PIN_OUTPUT )
{
GpioMcuWrite( obj, value );
}
}

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\345\233\233)__RTC/index.html" "b/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\345\233\233)__RTC/index.html" deleted file mode 100644 index a3ee508..0000000 --- "a/2016/10/14/LoRaWAN_stack\347\247\273\346\244\215\347\254\224\350\256\260 (\345\233\233)__RTC/index.html" +++ /dev/null @@ -1,980 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN_stack移植笔记(四)__RTC | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN_stack移植笔记(四)__RTC - - -

- - - -
- - - -
- - - - - -

stm32相关的配置

由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱动所以做修改。

-

RTC 的配置

此例程中,RTC被当做定时器使用,用于定时执行任务。

-

例程中,RTC使用外部LSE的32.768Khz的晶振作为时钟源,
而在本设计中,使用内部LSI作为RTC的时钟源,需要重新设置RTC的分频参数,使得程序正常运行。

-

根据Fck_spre = Frtcclk/(PREDIV_S+1)/(PREDIV_A+1)
例程中RTC的工作频率为32.778/(3+1)/(3+1) = 2.048Khz,

-

而内部晶振的频率约为37Khz,故PRVEDIV_S和PREDIV_A的值需要改变。

-
37/2.048 ~= 18;
-数据手册里面有这样一句话:    
-Note: When both prescalers are used, it is recommended to configure the asynchronous 
-prescaler to a high value to minimize consumption.
-所以:18 = 9*2;故设置PREDIV_A = 8,PREDIV_S = 1;
-

由于
37/18 ~= 2.055
1/2.055 ~= 0.486618

-

故此处的宏定义需要稍作修改

1
2
3
4
5
/*!
* RTC Time base in ms
*/
#define RTC_ALARM_TICK_DURATION 0.486618 // 1 tick every 466us
#define RTC_ALARM_TICK_PER_MS 2.055 // 1/2.055 = tick duration in ms ((37/(8+1)/(2+1)) = 2.055Khz)

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/2016/10/17/LoRaWAN_specification_ADR/index.html b/2016/10/17/LoRaWAN_specification_ADR/index.html deleted file mode 100644 index b5db6dc..0000000 --- a/2016/10/17/LoRaWAN_specification_ADR/index.html +++ /dev/null @@ -1,975 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN协议(二)__ADR | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN协议(二)__ADR - - -

- - - -
- - - -
- - - - - -

LoRaWAN ADR机制

LoRa network allows the end-devices to individually use any of the possible data rates. This feature is used by the LoRaWAN to adapt and optimize the data rate of static end-devices. This is referred to as Adaptive Data Rate (ADR) and when this is enabled the network will be optimized to use the fastest data rate possible.

-

LoRa网络允许终端设备单独地使用任何可能的数据速率.LoRaWAN使用这个特性去匹配并且优化静态终端的数据速度。这个叫做自适应数据速率(ADR),并且当他使能的时候,网络可能被优化到最快的数据速率。

-

Mobile end-devices should use their fixed default data rate as data rate management is not practical when the moving end-device causes fast changes in the radio environment.

-

当设备处于移动中造成无线电环境快速变化时,移动终端设备应当使用固定的默认的数据速率,因为数据速率管理不是很靠谱。

-

If the ADR bit is set, the network will control the data rate of the end-device through the appropriate MAC commands. If the ADR bit is not set, the network will not attempt to control the data rate of the end-device regardless of the received signal quality. The ADR bit may be set and unset by the end-device or the Network on demand. However, whenever possible, the ADR scheme should be enabled to increase the battery life of the end-device and maximize the network capacity.

-

如果ADR位被设置了,网络会通过适当的MAC层命令来控制终端设备的数据速率。如果ADR位没有被设置,网络不管接收信号的质量如何都不会试图去控制终端设备的数据速率。ADR标志位应当被设置或者不设置根据终端或者网络的需求。然而,无论何时,只要可能,为了增加终端设备的电池使用时间并且最大化网络容量,ADR功能都应当使能。

-

Note: Even mobile end-devices are actually immobile most of the time. So depending on its state of mobility, an end-device can request the network to optimize its data rate using ADR.

-

注意:就算是移动终端设备,实际上大部分时间还是不移动的。所以,终端设备可以使用ADR,根据它的移动情况,请求网络来优化它的数据速率。

-

-

If an end-device whose data rate is optimized by the network to use a data rate higher than its default data rate, it periodically needs to validate that the network still receives the uplink frames. Each time the uplink frame counter is incremented (for each new uplink, repeated transmissions do not increase the counter), the device increments an ADR_ACK_CNT counter.
After ADR_ACK_LIMIT uplinks (ADR_ACK_CNT >= ADR_ACK_LIMIT) without any downlink response, it sets the ADR acknowledgment request bit (ADRACKReq).
The network is required to respond with a downlink frame within the time set by the ADR_ACK_DELAY, any received downlink frame following an uplink frame resets the ADR_ACK_CNT counter.
The downlink ACK bit does not need to be set as any response during the receive slot of the end-device indicates that the gateway has still received the uplinks from this device.
If no reply is received within the next ADR_ACK_DELAY uplinks (i.e., after a total of ADR_ACK_LIMIT + ADR_ACK_DELAY), the end-device may try to regain connectivity by switching to the next lower data rate that provides a longer radio range.
The end-device will further lower its data rate step by step every time ADR_ACK_LIMIT is reached.
The ADRACKReq shall not be set if the device uses its default data rate because in that case no action can be taken to improve the link range.

-

如果终端设备的数据速率被网络优化到大于他的默认速率,那么他需要周期性地去验证网络是否一直收到上行数据帧。
上行数据帧计数器的每一次增长(每一次新的上行帧,重复性的传输不会增长计数器),设备的ADR_ACK_CNT计数器增加。
当ADR_ACK_LIMIT上行帧(ADR_ACK_CNT >= ADR_ACK_LIMIT)没有任何下行回复时,设备设置ADR acknowledgment 请求标志位(ADRACKReq)。
网络必须在设定的ADR_ACK_DELAY时间内回复一个下行帧,任何伴随着上行帧接收到的下行帧都会复位ADR_ACK_CNT计数器。
在设备的接收缝隙期间,任何回复的下行的ACK标志位不需要被设置来指示网关一直接收到这个设备的上行数据帧。
如果在接下来的ADR_ACK_DELAY个上行帧内没有收到回复(例如,在一整个ACR_ACK_LIMIT+ADR_ACK_DELAY),设备会尝试回复链接通过切换到相邻的低一级的速度,因为那提供了更远的无线距离。
终端设备将会进一步的降低它的速率一步一步每当ADR_ACK_LIMIT的次数限制到达。
ADRACKReq不应该被设置如果设备使用默认的速率,因为在这种情况下,没有任何操作可以提高链接的范围。

-

Note: Not requesting an immediate response to an ADR acknowledgement request provides flexibility to the network to optimally schedule its downlinks.
注意: ADR ACK不要求立即回复,网络对他的下行帧提供了弹性的优化计划。

-

Note: In uplink transmissions the ADRACKReq bit is set if ADR_ACK_CNT >= ADR_ACK_LIMIT and the current data-rate is greater than the device defined minimum data rate, it is cleared in other conditions.
注意:在上行的传输中,如果ADR_ACK_CNT>=ADR_ACK_LIMIT并且当前的速率高于设备定义的最小速率,此时ADRACKReq标志位被设置,那么他会在其他情况下被清除掉。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/2016/10/17/LoRaWAN_specification_message_format/index.html b/2016/10/17/LoRaWAN_specification_message_format/index.html deleted file mode 100644 index 53d1d4c..0000000 --- a/2016/10/17/LoRaWAN_specification_message_format/index.html +++ /dev/null @@ -1,1000 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN协议(一)__MAC Message Format | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN协议(一)__MAC Message Format - - -

- - - -
- - - -
- - - - - -

Radio Message & PHYPayload

Radion PHY layer 是无线数据包的底层,PHYPayload开始就是LoRaWAN的数据协议封装

-

可见PHYPayload是由三部分组成的。MHDR是MAC层的header,MACPayload是MAC层的负载部分,MIC是校验位(4个字节)

-

MHDR

-

MHDR共一个字节,其中高3位表示消息类型,低2位表示协议的版本号,中间三个位保留

-

MType

-

一共有8种,其中还是一种是预留的

-

Major

-

MACPayload

-

其主要包含FHDR、FPort、FRMPayload

-

FHDR

-

DevAddr是设备的32位唯一ID,FCtrl存储的是帧的一些控制信息,包括ADR信息,ACK信息以及FOptsLen,FCnt是16位的数据帧的计数,FOpts存储的是数据控制命令的信息。

-

FOpts的控制命令有如下几种:

-

-

FPort

-

FRMPayload

-

FRMPayload是数据帧的负载部分,其负载会使用AES128加密,所以在传输的过程中看不到负载的本身。

-

需要注意的是FRMPayload需要在计算MIC之前进行加密。

-

MIC

-

MIC是数据帧的32位校验位,其中参与校验的是MHDR、FHDR、FPort、FRMPayload。

-

校验的方法如上如所示,使用的是AES128加密算法,在计算完成之后取出前4个字节。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/20/LoRaWAN_ClassA_C_\346\225\260\346\215\256\346\224\266\345\217\221\346\234\272\345\210\266/index.html" "b/2016/10/20/LoRaWAN_ClassA_C_\346\225\260\346\215\256\346\224\266\345\217\221\346\234\272\345\210\266/index.html" deleted file mode 100644 index cc8ae65..0000000 --- "a/2016/10/20/LoRaWAN_ClassA_C_\346\225\260\346\215\256\346\224\266\345\217\221\346\234\272\345\210\266/index.html" +++ /dev/null @@ -1,988 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN__specification_数据收发机制 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN__specification_数据收发机制 - - -

- - - -
- - - -
- - - - - -

终端数据发送

由于LoRaWAN的gw具有49个LoRa的解调器,其配置成8通道,每个通道支持6种速度(DR0-DR5) 8*6 = 48

-

所以,只要在设置的8个通道内,以任何的速度发送都可以,只要满足占空比的要求即可。

-

终端数据接收

由于终端的射频芯片是半双工的,出于省电的考虑,LoRaWAN对终端的接收做了很多的规定(因为接收不是终端自主控制的,长时间的等待会增加终端的功耗)。

-

CLASS A RX

在LoRaWAN specification中,关于Class A的描述如下

-

CLASS A的接收方式是LoRaWAN的三种接收方式中最省电的

-

终端在发送完上行数据之后,会开启两个接收窗口期,RX1 和 RX2 ,其中RX1会在发送完成之后RECEIVE_DELAY1(s)之后开启,RX2会在发送完成之后RECEIVE_DELAY2(S)之后开启。

-

RX1的接收频点和上行时用的发送频点相同,接收的速率和发送速率存在一定的映射关系。默认情况下,接收速率和上一次上行的速率是一样的。

-

RX2的接收频点和速率是固定的。也可以通过MAC COMMAND修改。

-

其中地区不同,默认的接收频点和速率也会不一样。

-

CLASS C RX

CLASS C的设备除了在发送期间,其他时间都处于接收模式,也就是除了Transmit Time On Air 之外,几乎其他时间都是在接收。

-

接收的窗口和频点是RX2的接收串口和频点,是一个固定值。

-

由图可知,CLASS C的接收窗口是在CLASS A的基础上的,即在CLASS A的设备休眠时间打开RX2接收窗口:

-
    -
  1. 首先在RECEIVE_DELAY1这段时间里面打开接收窗口,而CLASS A的设备在这段时间里面是做休眠的,
  2. -
  3. 然后RECEIVE_DELAY1之后打开RX1的接收窗口,再在设备发送完成过了RECEIVE_DELAY2(S)之后,打开RX2接收窗口,之后一直开着RX2的接收窗口,直到设备需要切换到发送状态。
  4. -
- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/10/27/LoRaWAN stack\347\247\273\346\244\215\347\254\224\350\256\260(\344\272\224)__\346\235\202\344\270\203\346\235\202\345\205\253\347\232\204\351\227\256\351\242\230/index.html" "b/2016/10/27/LoRaWAN stack\347\247\273\346\244\215\347\254\224\350\256\260(\344\272\224)__\346\235\202\344\270\203\346\235\202\345\205\253\347\232\204\351\227\256\351\242\230/index.html" deleted file mode 100644 index 0b67ea4..0000000 --- "a/2016/10/27/LoRaWAN stack\347\247\273\346\244\215\347\254\224\350\256\260(\344\272\224)__\346\235\202\344\270\203\346\235\202\345\205\253\347\232\204\351\227\256\351\242\230/index.html" +++ /dev/null @@ -1,1011 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN stack移植笔记(五)__杂七杂八的问题 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN stack移植笔记(五)__杂七杂八的问题 - - -

- - - -
- - - -
- - - - - -

先废话一小段

在将LoRaWAN的程序移植的过程中,调试发现了很多的问题。

-

做好记录工作,防止以后再踩坑

-

移植使用的是LoRaMac-node库,使用的是STM32L151CBT6 MCU,需要要移植到STM32L051C8T6 这个MCU上面。

-

开始正文

JLink的配置

由于第一次使用JLink(SWD方式),在一开始使用时,踩了几处坑:

-
    -
  1. KEIL选择JLINK之后,点击设置进入,会出现一个对话框,要选择NO
  2. -
-

-
    -
  1. KEIL里面JLINK的 方式要选择SW,不然认不到芯片

    -
  2. -
  3. Flash download要选择对应大小的芯片,注意Flash的大小要选择正确

    -
  4. -
-

程序无法进入main,甚至一个函数都没有跑

当配置完JLink之后,程序可以正常烧写调试了,但是问题又出现了,无法跑进main函数,再进一步调试,发现来一个函数都没有执行,直接就进入进入死循环了(通过单步调试看上面的汇编代码)。这个现象就很奇怪了,以前也没有碰到过。
因为3.3V和GND是正常的,这样就算晶振有问题,也会执行程序到配置晶振才会出问题,而不是一句函数都没有执行。
后来顿悟,大概是BOOT0没接,仔细一看原理图,果然BOOT0是悬空的,飞线焊上之后,问题终于得到了解决。

-
NOTE:画原理图时一定要主要,BOOT0一定要接地,这样程序才能正常从FLASH启动
-

RTC定时链表的配置

官方的库中使用了RTC来作为定时器来处理一些定时的事件,这也是库中唯一的任务调度机制。所以保证这个机制的正常运行非常重要。

-

但是,当我把一切参数都配置完成之后,却发现,RTC的定时器不听使唤,经常不进入中断,初步诊断是写入寄存器的定时时间出了问题,但是却找不到出问题的原因。

-

这个问题也是非常的诡异,至今还未发现原因。

-

但是在一次偶然的调试中,我将原本处于

1
static void RtcStartWakeUpAlarm( uint32_t timeoutValue )

-

这个函数中的

1
2
3
RtcCalendar_t now;
RtcCalendar_t alarmTimer;
RTC_AlarmTypeDef alarmStructure;

-

这三个变量由局部变量改为了全局变量,问题就得到了解决。

-

但是原因还未发现。原本以为是变量未赋初值就使用,但是程序中都有在使用前赋初值,具体原因不明。

-

程序进入Default_handler

在调试程序的时候,程序又出现跑死的情况,然后单步调试发现程序进入了Default_handler这里,始终无法跑出来。

-

然后通过搜索得知,进入这里的情况应该是发生了中断但是没有处理,然后程序一直进入中断。

-

后来查看代码发现,由于Cotex-M3和cotex-M0的核,对GPIO的中断的入口是不一样的,在移植时需要做修改,在做了修改之后,程序终于跑正常了。

-

无法点对点通信

需要注意的是,点对点通信中,能够建立条件需要两个点的通信参数配置成相同。

-

特别注意的是iqInverted preamble SYNCWORD

-
note:
-1. 如果发射方使能了iqInverted,那么接收方也要使能iqInverted    
-2. 接收方的preambleLen必须设置大于发射方,否则有很大可能接收不到(偶尔可以收到,但是接收成功率很低)
-3. 发射方和接收方的SYNCWORD必须设置一样(同步字一样),否则认为是不同网络
-

接收机在接收检测时,会先检测前导码的长度,小于设置的最大接收长度时再检测同步字的内容,看是否一致,都符合时,才会接收负载的内容。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/11/03/LoRaWAN stack\347\247\273\346\244\215\347\254\224\350\256\260(\345\205\255)/index.html" "b/2016/11/03/LoRaWAN stack\347\247\273\346\244\215\347\254\224\350\256\260(\345\205\255)/index.html" deleted file mode 100644 index 824a910..0000000 --- "a/2016/11/03/LoRaWAN stack\347\247\273\346\244\215\347\254\224\350\256\260(\345\205\255)/index.html" +++ /dev/null @@ -1,974 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN stack移植笔记(六) | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN stack移植笔记(六) - - -

- - - -
- - - -
- - - - - -

前言

调试的过程中碰到的问题基本都是以前没有遇到过的,而且需要对整个协议栈及射频方面的工作流程较熟悉才能找到问题的原因,需要多读SX1276的数据手册以及与射频芯片的物理层通信例程和MAC层通信例程进行对比相结合。

-

正文

发送失败

LoRa 模块在进行 模式切换时,比如TX 切换到RX模式,需要先将设备切换到standby模式

-

CRC 校验失败,然后程序陷入死循环

按逻辑来讲,CRC校验失败,应该进行的操作是吧校验失败的这个数据包丢弃,然后重启接收机(芯片每次接收完成都应该重启SX1276)

-

但是,程序一旦接收CRC校验失败就陷入循环,通过调试发现,原来是开启了一个定时器,定时时间为0,然后定时器的处理函数中又开启了此定时器,定时时间依旧没0,所以陷入了死循环。

-

这个定时器就是:

1
TimerStart( &RxTimeoutSyncWord );

-

在接收处理函数void SX1276OnDio0Irq( void ) 中的CRC校验失败分支的处理代码中,以及定时器对应的处理函数void SX1276OnTimeoutIrq( void )中都开启了这个定时器。
如果是单个接收模式下,开启这个定时器并没有什么问题,但是在我调试的代码中,我开始的是连续接收模式,此模式根本没有同步字接收超时继续开着接收模式就可以了,并不需要特别的处理,可以不需要处理,
而官方SDK中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
void SX1276OnDio0Irq( void )
{
.........
if( SX1276.Settings.Fsk.CrcOn == true )
{
irqFlags = SX1276Read( REG_IRQFLAGS2 );
if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK )
{
// Clear Irqs
SX1276Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
RF_IRQFLAGS1_PREAMBLEDETECT |
RF_IRQFLAGS1_SYNCADDRESSMATCH );
SX1276Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
TimerStop( &RxTimeoutTimer );
if( SX1276.Settings.Fsk.RxContinuous == false )
{
TimerStop( &RxTimeoutSyncWord );
SX1276.Settings.State = RF_IDLE;
}
else
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError != NULL ) )
{
RadioEvents->RxError( );
}
SX1276.Settings.FskPacketHandler.PreambleDetected = false;
SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
SX1276.Settings.FskPacketHandler.NbBytes = 0;
SX1276.Settings.FskPacketHandler.Size = 0;
break;
}
}
..........
}
void SX1276OnTimeoutIrq( void )
{
switch( SX1276.Settings.State )
{
case RF_RX_RUNNING:
if( SX1276.Settings.Modem == MODEM_FSK )
{
SX1276.Settings.FskPacketHandler.PreambleDetected = false;
SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
SX1276.Settings.FskPacketHandler.NbBytes = 0;
SX1276.Settings.FskPacketHandler.Size = 0;
// Clear Irqs
SX1276Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
RF_IRQFLAGS1_PREAMBLEDETECT |
RF_IRQFLAGS1_SYNCADDRESSMATCH );
SX1276Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
if( SX1276.Settings.Fsk.RxContinuous == true )
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
else
{
SX1276.Settings.State = RF_IDLE;
TimerStop( &RxTimeoutSyncWord );
}
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
{
RadioEvents->RxTimeout( );
}
break;
................
}
}

-

这两处代码有着类似的才做,但是RxTimeoutSyncWord这个定时器会进入void SX1276OnTimeoutIrq( void )这个函数,而这个函数中又会重新开启RxTimeoutSyncWord这个定时器,导致死循环,所以在这里,应该讲两处的开启定时器的操作去掉(TimerStart( &RxTimeoutSyncWord );),这样程序逻辑才正常。

-

CRC 校验失败,然后在单步模式下,CRC一直失败

这个问题不是程序的问题,原因是因为我在单步模式下看CRC做接收,然后我的单步调试打断了射频芯片的正常工作。嗯、、就是这样,这个故事告诉我们,不要手贱。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/11/25/LoRaWAN\345\215\217\350\256\256(\344\270\211)__Server\347\253\257\346\225\260\346\215\256\345\215\217\350\256\256/index.html" "b/2016/11/25/LoRaWAN\345\215\217\350\256\256(\344\270\211)__Server\347\253\257\346\225\260\346\215\256\345\215\217\350\256\256/index.html" deleted file mode 100644 index 4002afa..0000000 --- "a/2016/11/25/LoRaWAN\345\215\217\350\256\256(\344\270\211)__Server\347\253\257\346\225\260\346\215\256\345\215\217\350\256\256/index.html" +++ /dev/null @@ -1,1017 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN协议(三)__Server端数据协议 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN协议(三)__Server端数据协议 - - -

- - - -
- - - -
- - - - - -

LoRaWAN Server 端架构

LoRaWAN 的server包括 NS(Network server)、AS(application server)、CS(Custom server)….

-

其中NS和AS是比不可少的,是完成LoRaWAN协议的重要组成部分

-

NS 职责

NS是直接与GW通信的服务器,也是AS和GW之间的桥梁

-

我所知道的工作有如下几点:

-
    -
  1. 验证数据的合法性(校验MIC)
  2. -
  3. 从GW的信息中提取数据,整理成NS 的JSON数据包
  4. -
  5. 将校验合法的数据打包成新的JSON包上传至AS
  6. -
  7. OTAA入网时向AS发送请求入网消息,然后再将入网信息告诉AS,当获取AS传来的入网的信息,告诉GW
  8. -
  9. GW 和 AS之间的数据通道
  10. -
-

有几点需要注意的是NS端的数据不进行AES解密工作。

-

AS 职责

AS是server端的数据处理中心

-

它的工作有如下几点:

-
    -
  1. 上行数据的解密
  2. -
  3. 下行数据的加密
  4. -
  5. OTAA入网请求的处理(同意入网/生成APPSKEY/NWKSKEY)
  6. -
-

CS 职责

CS负责将AS给的数据处理成用户自定义的数据协议格式,也就是说,CS端必须是用户来完成的,因为上面运行的是用户的协议。这里也就不再多说了。

-

抓包分析

以下是我在本地服务器端通过抓到得来的数据,我们通过分析数据包来理解数据的走向已及现有的server端处理流程。抓包使用的是tcpdump。

-

1.NS->AS数据
这是一帧从NS->AS的数据,使用的是TCP方式,AS的数据端口为4000。从data部分我们可以看出来,这是一个未解密的数据。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
15:30:53.662471 IP localhost.60795 > localhost.4000: Flags [P.], seq 13:328, ack 14,
win 442, options [nop,nop,TS val 414153 ecr 414145], length 315
0x0000: 4500 016f aee3 4000 4006 8ca3 7f00 0001
0x0010: 7f00 0001 ed7b 0fa0 5505 b988 2261 4f1b
0x0020: 8018 01ba ff63 0000 0101 080a 0006 51c9
0x0030: 0006 51c1 7b22 6170 7022 3a7b 226d 6f74
0x0040: 6565 7569 223a 2234 6137 3730 3032 3031
0x0050: 3631 3031 3622 2c22 6469 7222 3a22 7570
0x0060: 222c 2273 6571 6e6f 223a 3532 332c 2275
0x0070: 7365 7264 6174 6122 3a7b 2270 6f72 7422
0x0080: 3a32 2c22 7061 796c 6f61 6422 3a22 5645
0x0090: 7666 6f56 2b72 6631 5838 4177 316e 6c52
0x00a0: 7077 227d 2c22 6d6f 7465 7478 223a 7b22
0x00b0: 6672 6571 223a 3437 312e 352c 2264 6174
0x00c0: 7222 3a22 5346 3132 4257 3132 3522 2c22
0x00d0: 636f 6472 223a 2234 2f35 222c 2261 6472
0x00e0: 223a 6661 6c73 657d 2c22 6777 7278 223a
0x00f0: 5b7b 2265 7569 223a 2266 6666 6562 3832
0x0100: 3765 6266 3231 6130 3722 2c22 7469 6d65
0x0110: 223a 2232 3031 362d 3131 2d32 3454 3135
0x0120: 3a33 303a 3533 5a22 2c22 7469 6d65 6672
0x0130: 6f6d 6761 7465 7761 7922 3a66 616c 7365
0x0140: 2c22 6368 616e 223a 342c 2272 6663 6822
0x0150: 3a30 2c22 7273 7369 223a 2d37 392c 226c
0x0160: 736e 7222 3a2d 3136 2e35 7d5d 7d7d 00
-

提取其中的数据部分为:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"app": {
"moteeui": "4a770020161016",
"dir": "up",
"seqno": 523,
"userdata": {
"port": 2,
"payload": "VEvfoV+rf1X8Aw1nlRpw"
},
"motetx": {
"freq": 471.5,
"datr": "SF12BW125",
"codr": "4/5",
"adr": false
},
"gwrx": [
{
"eui": "fffeb827ebf21a07",
"time": "2016-11-24T15:30:53Z",
"timefromgateway": false,
"chan": 4,
"rfch": 0,
"rssi": -79,
"lsnr": -16.5
}
]
}
}
-

再把app.userdata.payload 做base64解码之后,得到的payload内容是这个:

-
1
2
3
app.userdata.payload base64 decoded:
\x54 \x4b \xdf \xa1 \x5f \xab \x7f \x55
\xfc \x03 \x0d \x67 \x95 \x1a \x70
-

此时看到的payload因为是加密的,所以完全看不出来数据内容是什么。

-

不过在这里,我们可以看到,NS已经将GW上传的数据做了一定的解析,封装成了另外一种JSON格式,由此,我们不难得出,NS做的工作包括–base64解码/MIC校验/GW数据包的重新组包

-

2.AS->CS数据
这是一帧从AS->CS的数据,使用的是TCP方式,CS的数据端口为5000。从data部分我们可以看出来,这是一个已经解密完成的数据了。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
15:30:53.663219 IP localhost.36774 > localhost.5000: Flags [P.], seq 13:328, ack 13,
win 342, options [nop,nop,TS val 414153 ecr 414140], length 315
0x0000: 4500 016f 928b 4000 4006 a8fb 7f00 0001
0x0010: 7f00 0001 8fa6 1388 2a2a 93a0 9d70 4aae
0x0020: 8018 0156 ff63 0000 0101 080a 0006 51c9
0x0030: 0006 51bc 7b22 6170 7022 3a7b 226d 6f74
0x0040: 6565 7569 223a 2234 6137 3730 3032 3031
0x0050: 3631 3031 3622 2c22 6469 7222 3a22 7570
0x0060: 222c 2273 6571 6e6f 223a 3532 332c 2275
0x0070: 7365 7264 6174 6122 3a7b 2270 6f72 7422
0x0080: 3a32 2c22 7061 796c 6f61 6422 3a22 4151
0x0090: 4944 4241 5547 4277 674a 4367 734d 4451
0x00a0: 3450 227d 2c22 6d6f 7465 7478 223a 7b22
0x00b0: 6672 6571 223a 3437 312e 352c 2264 6174
0x00c0: 7222 3a22 5346 3132 4257 3132 3522 2c22
0x00d0: 636f 6472 223a 2234 2f35 222c 2261 6472
0x00e0: 223a 6661 6c73 657d 2c22 6777 7278 223a
0x00f0: 5b7b 2265 7569 223a 2266 6666 6562 3832
0x0100: 3765 6266 3231 6130 3722 2c22 7469 6d65
0x0110: 223a 2232 3031 362d 3131 2d32 3454 3135
0x0120: 3a33 303a 3533 5a22 2c22 7469 6d65 6672
0x0130: 6f6d 6761 7465 7761 7922 3a66 616c 7365
0x0140: 2c22 6368 616e 223a 342c 2272 6663 6822
0x0150: 3a30 2c22 7273 7369 223a 2d37 392c 226c
0x0160: 736e 7222 3a2d 3136 2e35 7d5d 7d7d 00
-

提取其中的数据部分为:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"app": {
"moteeui": "4a770020161016",
"dir": "up",
"seqno": 523,
"userdata": {
"port": 2,
"payload": "AQIDBAUGBwgJCgsMDQ4P"
},
"motetx": {
"freq": 471.5,
"datr": "SF12BW125",
"codr": "4/5",
"adr": false
},
"gwrx": [
{
"eui": "fffeb827ebf21a07",
"time": "2016-11-24T15:30:53Z",
"timefromgateway": false,
"chan": 4,
"rfch": 0,
"rssi": -79,
"lsnr": -16.5
}
]
}
}
-

再把app.userdata.payload 做base64解码之后,得到的payload内容是这个:

-
1
2
\x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08
\x09 \x0a \x0b \x0c \x0d \x0e \x0f
-

而此时,数据已经完全解密了,可以看到数据就是在AS解密的,解密完再发送给CS,CS再做进一步用户协议的处理。

-

在这里,我们可以看到,AS已经将NS传输过来的JSON包的payload部分做了解密,然后再传给了CS。所以解密工作是在AS完成的。

-

本期的LoRaWAN笔记就到这里了,如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/11/26/LoRaWAN\345\215\217\350\256\256(\345\233\233)__\345\205\245\347\275\221\346\226\271\345\274\217\346\246\202\350\277\260/index.html" "b/2016/11/26/LoRaWAN\345\215\217\350\256\256(\345\233\233)__\345\205\245\347\275\221\346\226\271\345\274\217\346\246\202\350\277\260/index.html" deleted file mode 100644 index b85cb73..0000000 --- "a/2016/11/26/LoRaWAN\345\215\217\350\256\256(\345\233\233)__\345\205\245\347\275\221\346\226\271\345\274\217\346\246\202\350\277\260/index.html" +++ /dev/null @@ -1,1028 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN协议(四)__入网方式概述 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN协议(四)__入网方式概述 - - -

- - - -
- - - -
- - - - - -

前言

在LoRaWAN中,node最终和服务器能够正常数据交互,需要先入网,入网的本质,也就是获得一些通信相关的参数,有以下几个:

-
    -
  1. NWKSKEY
  2. -
  3. APPSKEY
  4. -
  5. DEVADDR
  6. -
  7. DEVEUI
  8. -
-

其中

-
    -
  • NWKSKEY用于数据的校验,也就是说在MIC校验时会用到
  • -
  • APPSKEY用于负载的AES加密,也就是说在加密解密时会使用到
  • -
  • DevAddr是node的短地址,在数据通讯时,使用的是node的短地址
  • -
  • DevEUI 在ABP入网方式的通讯中不会使用,在OTAA方式中会使用到,是由设备在入网前就产生了。在入网时,node将DevEUI上传,然后服务器会将此DevEUI注册并返回一个DevAddr,也就是说DevAddr此时和DevEUI就建立了映射关系,在node后续的通讯中,使用DevAddr。
  • -
-

LoRaWAN入网方式有两种:

-
    -
  1. ABP (Activation By Personalization)
  2. -
  3. OTAA(Over-The-Air Activation)
  4. -
-

下面就讲述一下这两种方式。

-

ABP 概述

ABP方式是事先将入网信息烧写在设备上,也就是说设备上电已经入网了,无需再特意去请求入网。

-

这种方式就不再多说了。

-

OTAA 概述

OTAA方式入网的node,在刚上电的时候,是不处于入网状态的,此时就需要进行入网操作。

-

如果我们简单的把服务器看做一个整体,那么入网操作的流程是这样的:

-
    -
  1. node 发送入网请求,即join_request message
  2. -
  3. GW 收到 node 的数据,上传给服务器
  4. -
  5. 服务器收到入网请求,同意入网,并且将设备在服务器注册,建立长地址与短地址之间的联系,生成通讯密钥,将通讯密钥的参数打包下发给GW,即 Join-accept message
  6. -
  7. GW 收到服务器的数据,下发给 node
  8. -
  9. node 根据下发的数据包,得到 DevAddr、APPSKEY、NWKSKEY
  10. -
-

这篇文章先大概的描述一下两种入网方式

-

详细的关于OTAA的入网方式见下一篇文章,会有OTAA的抓包分析,以及APPSKEY/NWKSKEY的生成过程,并且有C语言的Example。

-

本期的LoRaWAN协议分析就到这里了,如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/11/27/LoRaWAN\345\215\217\350\256\256(\344\272\224)__OTAA\345\205\245\347\275\221\346\226\271\345\274\217\350\257\246\350\277\260/index.html" "b/2016/11/27/LoRaWAN\345\215\217\350\256\256(\344\272\224)__OTAA\345\205\245\347\275\221\346\226\271\345\274\217\350\257\246\350\277\260/index.html" deleted file mode 100644 index df1362f..0000000 --- "a/2016/11/27/LoRaWAN\345\215\217\350\256\256(\344\272\224)__OTAA\345\205\245\347\275\221\346\226\271\345\274\217\350\257\246\350\277\260/index.html" +++ /dev/null @@ -1,1220 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN协议(五)__OTAA入网方式详述 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN协议(五)__OTAA入网方式详述 - - -

- - - -
- - - -
- - - - - -

前言

OTAA(Over-The-Air Activation),是LoRaWAN的一种空中入网方式。当node在上电的时候处于非入网状态时,需要先入网才能和服务器进行通信。其操作就是node发送join_request message,请求入网,然后服务器同意入网,并且返回Join-accept message,node再对信息进行解析,获取通信参数,这样就可以和服务器通信了。

-

顺便分享几个工具网站给大家:

-
    -
  1. HEX/字符串转换
  2. -
  3. JSON校验
  4. -
  5. BASE64编码/解码
  6. -
-

OTAA方式入网步骤

准备工作

node端在做OTAA入网之前,需要先具备三个参数:

-
    -
  • APPEUI node自定义的8字节长地址
  • -
  • APPKEY 网络统一的KEY,服务器和node端都事先存好
  • -
  • DevNonce 2字节的随机数,用于生成随机的AppSKey和NwkSKey
  • -
-

这些参数可以通过程序固话在里面,或者通过串口或其他方式在入网操作前告诉node。

-

当这些准备工作都做好了之后,node设备就能够入网了。

-

第一步

1.node发起入网请求,也就是发送join_request message,

-

根据LoRaWAN specification 可知,join_request message的格式如下:

- - - - - - - - - - - - - - - - - - - -
MHDRAPPEUIDevEUIDevNonceMIC
1字节8字节8字节2字节4字节
-

其中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段描述
MHDR数据包头,其中包含了数据包的类型,也就是说从这个包头可以知道,这是一个join_request message
APPEUI应用EUI
DevEUInode的长地址,由node自己定义
DevNonce一个随机数,用来生成密码
MIC4字节的校验
-

需要注意的是Join_request message是未加密的

-

第二步

2.GW将此数据上传至NS

-

GW对MAC层的数据不进行解析,而是直接将其进行base64编码之后,封装成JSON包上传至NS,MAC层的数据位于rxpk.data

-

样例数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"rxpk": [
{
"tmst": 532505620,
"chan": 6,
"rfch": 0,
"freq": 471.9,
"stat": 1,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"lsnr": -17,
"rssi": -81,
"size": 23,
"data": "AAEAACAAxSYsFhAWIAB3SgBUe0At4Zo="
}
]
}

-

此处,将data进行base64解码,我们就可以看到MAC层数据了,因为join_request message数据是未加密的

-

data部分的内容如下:

1
2
3
\x00 \x01 \x00 \x00 \x20 \x00 \xc5 \x26
\x2c \x16 \x10 \x16 \x20 \x00 \x77 \x4a
\x00 \x54 \x7b \x40 \x2d \xe1 \x9a

-

各部分的内容分别为:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段内容
MHDR\x00
AppEUI\x01 \x00 \x00 \x20 \x00 \xc5 \x26 \x2c
DevEUI\x16 \x10 \x16 \x20 \x00 \x77 \x4a \x00
DevNonce\x54 \x7b
MIC\x40 \x2d \xe1 \x9a
-

第三步

3.NS向AS发送设备入网包

-

样例数据:

-
1
2
3
4
5
6
7
{
"join": {
"request": {
"frame": "AAEAACAAxSYsFhAWIAB3SgBUe0At4Zo"
}
}
}
-

可以看到,原先的MAC 层的data数据没有变化

-

第四步

4.AS同意入网并且向NS回复同意入网

-

样例数据:

1
2
3
4
5
6
{
"join": {
"moteeui": "4a770020161016",
"accept": true
}
}

-

第五步

5.NS生成MoteAddr,并将node端的信息发送给AS

-

样例数据:

1
2
3
4
5
6
7
8
9
10
{
"join": {
"appeui": "2c26c50020000001",
"moteeui": "4a770020161016",
"details": {
"moteaddr": "48000002",
"devicenonce": 31572
}
}
}

-

第六步

6.AS生成密钥,并将相关信息告诉NS

-

样例数据:

1
2
3
4
5
6
7
8
9
{
"join": {
"moteeui": "4a770020161016",
"complete": {
"frame": "IPqAKXQ7LS/CmYVCDy8K3k4",
"networkkey": "de03331aeb4254e9727b6fafbf13db3d"
}
}
}

-

可以看到,networkkey直接发送给NS了,这也就是NwkSKey,
之所以明文告诉NS,是因为:
1.NS不做解密的工作
2.networkkey在校验的时候回使用到

-

第七步

7.NS将数据告诉GW,GW再转换成MAC包,发送给node

-

样例数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"txpk": {
"tmst": 537505620,
"freq": 471.9,
"rfch": 0,
"powe": 14,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"ipol": true,
"size": 17,
"data": "IPqAKXQ7LS/CmYVCDy8K3k4"
}
}

-

需要注意的是,此时的data部分是经过base64编码以及AES加密的,直接解码,看到的数据是无效的,需要再进行解密,解密需要使用APPKEY,也就是之前介绍的统一的网络KEY.

-

txpk.data部分就是LoRaWAN MAC的join_accept message.

-

第八步

8.node解析join_accept message 部分

-

根据LoRaWAN specification 可知,join_accept message的格式如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
MHDRAppNonceNetIDDevAddrDLSettingsRxDelayCFList(pad16)MIC
1字节3字节3字节4字节4字节1字节0/16字节4字节
-

其中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段描述
MHDR数据包头,其中包含了数据包的类型,也就是说从这个包头可以知道,这是一个join_accept message
AppNonce3字节的unique ID,服务器生成的,产生AppSKey/NwkSKey 会用到
NetID网络ID,产生AppSKey/NwkSKey 会用到
DevAddr设备的短地址
DLSettings设置RX1和RX2的下行接受串口的速率
RxDelay从发送完成到打开RX1接受串口的事件
CFList(pad16)我也不知道是什么,目前看到的都是0个字节
MIC4字节的校验
-

需要注意的是Join_accept message是加密的,需要使用APPKEY解密

-

txpk.data:
“data”: “IPqAKXQ7LS/CmYVCDy8K3k4”

-

base64解码:
\x20 \xfa \x80 \x29 \x74 \x3b \x2d \x2f
\xc2 \x99 \x85 \x42 \x0f \x2f \x0a \xde
\x4e

-

这个数据是未解密的,我们还需要解密

-

解密后为
\x20 \x43 \x75 \xcb \x24 \x00 \x00 \x02
\x00 \x00 \x48 \x03 \x00 \x82 \xc9 \xd0
\xf9

-

具体的情况如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段解密前解密后
MHDR\x20\x20
AppNonce\xfa \x80 \x29\x43 \x75 \xcb
NetID\x74 \x3b \x2d\x24 \x0 \x0
DevAddr\x2f \xc2 \x99 \x85\x2 \x0 \x0 \x48
DLSettings\x42\x3
RxDelay\x0f\x0
CFList
MIC\x2f \x0a \xde \x4e\x82 \xc9 \xd0 \xf9
-

可以看到,DevAddr为0x48000002,而AppSKey和NwkSKey无法直接看出来,需要再计算

-

计算公式如下:

-
    -
  • NwkSKey = aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16)
  • -
  • AppSKey = aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)
  • -
-

下一篇文章,我会把这个解密的过程,以及NwkSKey/AppSKey的计算过程,配合C语言,再分析一下。

-

本期的LoRaWAN协议分析就到这里了,如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/11/27/LoRaWAN\345\215\217\350\256\256(\345\205\255)__OTAA KEY\347\224\237\346\210\220\350\277\207\347\250\213/index.html" "b/2016/11/27/LoRaWAN\345\215\217\350\256\256(\345\205\255)__OTAA KEY\347\224\237\346\210\220\350\277\207\347\250\213/index.html" deleted file mode 100644 index 2200cc9..0000000 --- "a/2016/11/27/LoRaWAN\345\215\217\350\256\256(\345\205\255)__OTAA KEY\347\224\237\346\210\220\350\277\207\347\250\213/index.html" +++ /dev/null @@ -1,1147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LoRaWAN协议(六)__OTAA KEY生成过程 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - LoRaWAN协议(六)__OTAA KEY生成过程 - - -

- - - -
- - - -
- - - - - -

前言

通过OTAA方式入网的设备,通讯时使用的KEY需要通过服务器获得,在入网之间,设备无法通讯。

-

相关的OTAA入网流程已经在上一章中讲解过了,有兴趣的可以去看看LoRaWAN协议(五)__OTAA入网方式详述

-

这一章讲解的是OTAA中的密钥生成过程。

-

其中使用到的库函数都是从semtech的官方库中来的,官方库代码链接:LoRaMac-node

-

详解

设备在通讯时,会使用的密钥有NwkSKey 和AppSKey。

-

生成的公式如下:

-
    -
  • NwkSKey = aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16)
  • -
  • AppSKey = aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)
  • -
-

可以看到相关的参数一共有四个:
1.AppNonce
2.NetID
3.DevNonce
4.pad16

-

其中AppNonce、NetID、pad16 是产生于服务器的,DevNonce产生于node设备本身。

-

还是使用LoRaWAN协议(五)这篇文章中使用的包数据来进行分析。

-

这里,我们调用官方库的接口,因为我们这里只是熟悉协议,并不是要研究Key的生成算法。

-

如果不明白数据协议的,可以去看LoRaWAN协议(五)这篇文章

-

提取DevNonce

1.GW->NS JSON包,从中提取出来DevNonce,

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"rxpk": [
{
"tmst": 532505620,
"chan": 6,
"rfch": 0,
"freq": 471.9,
"stat": 1,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"lsnr": -17,
"rssi": -81,
"size": 23,
"data": "AAEAACAAxSYsFhAWIAB3SgBUe0At4Zo="
}
]
}
-

data为MAC层数据,为join_request message,其数据包格式为

- - - - - - - - - - - - - - - - - - - -
MHDRAPPEUIDevEUIDevNonceMIC
1字节8字节8字节2字节4字节
-

base64解码:

1
2
3
\x00 \x01 \x00 \x00 \x20 \x00 \xc5 \x26
\x2c \x16 \x10 \x16 \x20 \x00 \x77 \x4a
\x00 \x54 \x7b \x40 \x2d \xe1 \x9a

-

得到的数据:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段内容
MHDR\x00
AppEUI\x01 \x00 \x00 \x20 \x00 \xc5 \x26 \x2c
DevEUI\x16 \x10 \x16 \x20 \x00 \x77 \x4a \x00
DevNonce\x54 \x7b
MIC\x40 \x2d \xe1 \x9a
-

可以得到DevNonce的值为0x7b54

-

提取AppNonce、NetID、CFList

2.NS->GW JSON包,其中txpk.data为包含了MAC层数据内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"txpk": {
"tmst": 537505620,
"freq": 471.9,
"rfch": 0,
"powe": 14,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"ipol": true,
"size": 17,
"data": "IPqAKXQ7LS/CmYVCDy8K3k4"
}
}

-

data base64 decode:

1
2
3
\x20 \xfa \x80 \x29 \x74 \x3b \x2d \x2f
\xc2 \x99 \x85 \x42 \x0f \x2f \x0a \xde
\x4e

-

根据LoRaWAN specification 可知,join_accept message的格式如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
MHDRAppNonceNetIDDevAddrDLSettingsRxDelayCFList(pad16)MIC
1字节3字节3字节4字节4字节1字节0/16字节4字节
-

但是这个数据是加密的,需要使用AppKey进行解密

-

所以,我们需要先使用AppKey解密join_accept message

-

payload为join_accept message,此处为

1
2
3
\x20 \xfa \x80 \x29 \x74 \x3b \x2d \x2f
\xc2 \x99 \x85 \x42 \x0f \x2f \x0a \xde
\x4e

-

解密之后的数据存放在LoRaMacRxPayload数组中

-
1
2
3
4
5
uint8_t LoRaMacAppKey[] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
LoRaMacRxPayload[0] = payload[0];
-

可以得到解析之后的数组

1
2
3
0x20 0x43 0x75 0xcb 0x24 0x0 0x0 0x2
0x0 0x0 0x48 0x3 0x0 0x82 0xc9 0xd0
0xf9

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段解密前解密后
MHDR\x20\x20
AppNonce\xfa \x80 \x29\x43 \x75 \xcb
NetID\x74 \x3b \x2d\x24 \x0 \x0
DevAddr\x2f \xc2 \x99 \x85\x2 \x0 \x0 \x48
DLSettings\x42\x3
RxDelay\x0f\x0
CFList(pad16)
MIC\x2f \x0a \xde \x4e\x82 \xc9 \xd0 \xf9
-

根据协议,我们可以得到:

-
1
2
3
4
AppNonce:\x43 \x75 \xcb
NetID:\x24 \x0 \x0
DevNonce:0x7b54
pad16:没有
-

至此,我们就具备生成密钥的所有参数了

-

产生AppSKey 和 NwkSKey

最后,我们再调用

1
LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );

-

就可以生成AppSKey和NwkSKey了。

-

得到的NwkSKey为

1
2
0xde 0x3 0x33 0x1a 0xeb 0x42 0x54 0xe9
0x72 0x7b 0x6f 0xaf 0xbf 0x13 0xdb 0x3d

-

得到的AppSKey为

1
2
0xe0 0x46 0x9e 0x44 0x9c 0x57 0x47 0x8c
0xbe 0xa7 0x25 0xda 0x84 0xf0 0x13 0x97

-

对比之间抓包的AS->NS的入网信息

-

AS->NS 发送入网信息,可以知道,生成的密码是正确的了。

1
2
3
4
5
6
7
8
9
{
"join": {
"moteeui": "4a770020161016",
"complete": {
"frame": "IPqAKXQ7LS/CmYVCDy8K3k4",
"networkkey": "de03331aeb4254e9727b6fafbf13db3d"
}
}
}

-

当然最好是进行实际负载的验证,我也写了两个小程序进行了验证,证明了这两个Key确实是正确的。

-

两个小程序的链接:

- -

至此,我所知的OTAA入网方面的协议就完了。

-

如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/2016/12/26/\344\275\216\345\212\237\350\200\227\350\260\203\350\257\225\345\277\203\345\276\227/index.html" "b/2016/12/26/\344\275\216\345\212\237\350\200\227\350\260\203\350\257\225\345\277\203\345\276\227/index.html" deleted file mode 100644 index 150fcc4..0000000 --- "a/2016/12/26/\344\275\216\345\212\237\350\200\227\350\260\203\350\257\225\345\277\203\345\276\227/index.html" +++ /dev/null @@ -1,993 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 低功耗调试心得 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
-
-
-
- - -
- - - - - - - - - -
- - -
- - - -

- - - - 低功耗调试心得 - - -

- - - -
- - - -
- - - - - -

最近调试的设备都是用电池供电的,所以电池的消耗显得非常的重要。

-

之前在调试低功耗的路上走过一些坑,现在分享一些最近的调试心得。

-

心得

    -
  1. 休眠之前,不用于唤醒的引脚全部设置成 输入-高阻态
  2. -
-

高阻态可以近似的理解成 引脚断开与连接电路状态。

-
    -
  1. 休眠之前,如不需要RTC定时唤醒,则把RTC关闭
  2. -
-

休眠唤醒之后,设备会从休眠时的下一个语句开始执行,注意恢复引脚。

- - -
- -
- - - - -
- -
- - - - -
- - -
- - - -
- -
-
- -
-
-
-
- -
-
- - -
- - - - -
- -
-
- -
- - -
- - - - - - - - - -
-
- - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CNAME b/CNAME deleted file mode 100644 index 4dea19d..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -chenjunkui.com \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..856b578 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,63 @@ +Creative Commons Attribution 3.0 Unported +http://creativecommons.org/licenses/by/3.0/ + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + + 1. "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. + 2. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. + 3. "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. + 4. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. + 5. "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. + 6. "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. + 7. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. + 8. "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. + 9. "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: + + 1. to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; + 2. to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; + 3. to Distribute and Publicly Perform the Work including as incorporated in Collections; and, + 4. to Distribute and Publicly Perform Adaptations. + 5. + + For the avoidance of doubt: + 1. Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; + 2. Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, + 3. Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. + +The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: + + 1. You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(b), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(b), as requested. + 2. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4 (b) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. + 3. Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + 1. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. + +8. Miscellaneous + + 1. Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. + 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. + 5. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. + 6. The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..3b4fd91 --- /dev/null +++ b/README.txt @@ -0,0 +1,37 @@ +Landed by HTML5 UP +html5up.net | @n33co +Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) + + +A dark, slick, modern, responsive, adjective-drenched design built around an extremely +dynamic landing page (scroll that mofo!). Inspired by Big Picture, another design +of mine with a similarish feel/flow, only this time I took it waaaaaay further and +actually made it multipurpose (versus copping out and making it a one pager like I +did last time ;) Includes multiple pages, a bunch of pre-styled elements, and all +its Sass sources. + +Demo images* courtesy of Unsplash, a radtastic collection of CC0 (public domain) images +you can use for pretty much whatever. + +(* = Not included) + +Feedback, bug reports, and comments are not only welcome, but strongly encouraged :) + +AJ +n33.co @n33co dribbble.com/n33 + + +Credits: + + Demo Images: + Unsplash (unsplash.com) + + Icons: + Font Awesome (fortawesome.github.com/Font-Awesome) + + Other: + jQuery (jquery.com) + html5shiv.js (@afarkas @jdalton @jon_neal @rem) + CSS3 Pie (css3pie.com) + Respond.js (j.mp/respondjs) + Skel (skel.io) \ No newline at end of file diff --git a/Repositories.html b/Repositories.html new file mode 100644 index 0000000..c4506e8 --- /dev/null +++ b/Repositories.html @@ -0,0 +1,116 @@ + + + + + Repositories + + + + + + + + +
+ + + + + +
+
+
+

My repositories

+

和大家分享平时积累的代码,有疑问或者其他的问题,也欢迎大家参与谈论 +
邮箱:454626653@qq.com +

+
+ + +
+ + +

我的所有例程中,带硬件平台的程序使用的是KEIL开发环境,不带硬件的程序使用的是code blocks

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Repositories NameDescriptionLinkDownload ZIP
STM32L0xx_Driversthe reconstruction of STM32L0xx_Drivers base on STM32 Cube LIBgo toDownload
STM32F1xx_Driversthe reconstruction of STM32F1xx_Drivers base on STM32 Std_Peripheral LIBgo toDownload
Data_Structurethe data structure used at usual go toDownload
+
+
+ +
+
+ + + + +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/about/index.html b/about/index.html deleted file mode 100644 index 17a5e23..0000000 --- a/about/index.html +++ /dev/null @@ -1,771 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - about | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/07/11/index.html b/archives/2016/07/11/index.html deleted file mode 100644 index 27eaff0..0000000 --- a/archives/2016/07/11/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/07/index.html b/archives/2016/07/index.html deleted file mode 100644 index a970f9f..0000000 --- a/archives/2016/07/index.html +++ /dev/null @@ -1,1079 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/10/10/index.html b/archives/2016/10/10/index.html deleted file mode 100644 index 70c8dec..0000000 --- a/archives/2016/10/10/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/10/11/index.html b/archives/2016/10/11/index.html deleted file mode 100644 index 2d4ccad..0000000 --- a/archives/2016/10/11/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/10/index.html b/archives/2016/10/index.html deleted file mode 100644 index d30e0e7..0000000 --- a/archives/2016/10/index.html +++ /dev/null @@ -1,1190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/11/03/index.html b/archives/2016/11/03/index.html deleted file mode 100644 index 8ff5daf..0000000 --- a/archives/2016/11/03/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/11/25/index.html b/archives/2016/11/25/index.html deleted file mode 100644 index 308088f..0000000 --- a/archives/2016/11/25/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/11/index.html b/archives/2016/11/index.html deleted file mode 100644 index d8ec669..0000000 --- a/archives/2016/11/index.html +++ /dev/null @@ -1,968 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/12/26/index.html b/archives/2016/12/26/index.html deleted file mode 100644 index 03da51e..0000000 --- a/archives/2016/12/26/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/12/index.html b/archives/2016/12/index.html deleted file mode 100644 index 1850cbd..0000000 --- a/archives/2016/12/index.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/index.html b/archives/2016/index.html deleted file mode 100644 index 5bceacd..0000000 --- a/archives/2016/index.html +++ /dev/null @@ -1,1527 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/2016/page/2/index.html b/archives/2016/page/2/index.html deleted file mode 100644 index 7b616f8..0000000 --- a/archives/2016/page/2/index.html +++ /dev/null @@ -1,972 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/index.html b/archives/index.html deleted file mode 100644 index 7ebf65e..0000000 --- a/archives/index.html +++ /dev/null @@ -1,1527 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archives/page/2/index.html b/archives/page/2/index.html deleted file mode 100644 index 60e468e..0000000 --- a/archives/page/2/index.html +++ /dev/null @@ -1,972 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 归档 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/css/font-awesome.min.css b/assets/css/font-awesome.min.css new file mode 100644 index 0000000..885b384 --- /dev/null +++ b/assets/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.1');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.1') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.1') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.1') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.1') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.1#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/assets/css/ie8.css b/assets/css/ie8.css new file mode 100644 index 0000000..c58a8ed --- /dev/null +++ b/assets/css/ie8.css @@ -0,0 +1,194 @@ +/* + Landed by HTML5 UP + html5up.net | @n33co + Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) +*/ + +/* Basic */ + + body { + color: #ffffff; + } + + body, html, #page-wrapper { + height: 100%; + } + + blockquote { + border-left: solid 4px #606067; + } + + code { + background: #32333b; + } + + hr { + border-bottom: solid 1px #606067; + } + +/* Icon */ + + .icon.major { + -ms-behavior: url("assets/js/ie/PIE.htc"); + } + +/* Image */ + + .image { + position: relative; + -ms-behavior: url("assets/js/ie/PIE.htc"); + } + + .image:before { + display: none; + } + + .image img { + position: relative; + -ms-behavior: url("assets/js/ie/PIE.htc"); + } + +/* Form */ + + input[type="text"], + input[type="password"], + input[type="email"], + select, + textarea { + position: relative; + -ms-behavior: url("assets/js/ie/PIE.htc"); + } + + input[type="text"]:focus, + input[type="password"]:focus, + input[type="email"]:focus, + select:focus, + textarea:focus { + -ms-behavior: url("assets/js/ie/PIE.htc"); + } + + input[type="text"], + input[type="password"], + input[type="email"] { + line-height: 3em; + } + + input[type="checkbox"], + input[type="radio"] { + font-size: 3em; + } + + input[type="checkbox"] + label:before, + input[type="radio"] + label:before { + display: none; + } + +/* Table */ + + table tbody tr { + border: solid 1px #606067; + } + + table thead { + border-bottom: solid 1px #606067; + } + + table tfoot { + border-top: solid 1px #606067; + } + + table.alt tbody tr td { + border: solid 1px #606067; + } + +/* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + .button { + border: solid 1px #ffffff !important; + } + + input[type="submit"].special, + input[type="reset"].special, + input[type="button"].special, + .button.special { + border: 0 !important; + } + +/* Goto Next */ + + .goto-next { + display: none; + } + +/* Spotlight */ + + .spotlight { + height: 100%; + } + + .spotlight .content { + background: #272833; + } + +/* Wrapper */ + + .wrapper.style2 input[type="text"]:focus, + .wrapper.style2 input[type="password"]:focus, + .wrapper.style2 input[type="email"]:focus, + .wrapper.style2 select:focus, + .wrapper.style2 textarea:focus { + border-color: #ffffff; + } + + .wrapper.style2 input[type="submit"].special:hover, .wrapper.style2 input[type="submit"].special:active, + .wrapper.style2 input[type="reset"].special:hover, + .wrapper.style2 input[type="reset"].special:active, + .wrapper.style2 input[type="button"].special:hover, + .wrapper.style2 input[type="button"].special:active, + .wrapper.style2 .button.special:hover, + .wrapper.style2 .button.special:active { + color: #e44c65 !important; + } + +/* Dropotron */ + + .dropotron { + background: #272833; + box-shadow: none !important; + -ms-behavior: url("assets/js/ie/PIE.htc"); + } + + .dropotron > li a, .dropotron > li span { + color: #ffffff !important; + } + + .dropotron.level-0 { + margin-top: 0; + } + + .dropotron.level-0:before { + display: none; + } + +/* Header */ + + #header { + background: #272833; + } + +/* Banner */ + + #banner { + height: 100%; + } + + #banner:before { + height: 100%; + } + + #banner:after { + background-image: url("images/ie/banner-overlay.png"); + } \ No newline at end of file diff --git a/assets/css/ie9.css b/assets/css/ie9.css new file mode 100644 index 0000000..5698a50 --- /dev/null +++ b/assets/css/ie9.css @@ -0,0 +1,33 @@ +/* + Landed by HTML5 UP + html5up.net | @n33co + Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) +*/ + +/* Loader */ + + body.landing:before, body.landing:after { + display: none !important; + } + +/* Icon */ + + .icon.alt { + color: inherit !important; + } + + .icon.major.alt:before { + color: #ffffff !important; + } + +/* Banner */ + + #banner:after { + background-color: rgba(23, 24, 32, 0.95); + } + +/* Footer */ + + #footer .icons .icon.alt:before { + color: #ffffff !important; + } \ No newline at end of file diff --git a/assets/css/images/arrow.svg b/assets/css/images/arrow.svg new file mode 100644 index 0000000..f2543c5 --- /dev/null +++ b/assets/css/images/arrow.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/css/images/ie/banner-overlay.png b/assets/css/images/ie/banner-overlay.png new file mode 100644 index 0000000..14d32bf Binary files /dev/null and b/assets/css/images/ie/banner-overlay.png differ diff --git a/assets/css/images/overlay.png b/assets/css/images/overlay.png new file mode 100644 index 0000000..ec3b66f Binary files /dev/null and b/assets/css/images/overlay.png differ diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 0000000..e5c80d7 --- /dev/null +++ b/assets/css/main.css @@ -0,0 +1,4001 @@ +@import url("font-awesome.min.css"); +@import url("http://fonts.googleapis.com/css?family=Roboto:100,300,100italic,300italic"); + +/* + Landed by HTML5 UP + html5up.net | @n33co + Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) +*/ + +/* Reset */ + + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + } + + article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { + display: block; + } + + body { + line-height: 1; + } + + ol, ul { + list-style: none; + } + + blockquote, q { + quotes: none; + } + + blockquote:before, blockquote:after, q:before, q:after { + content: ''; + content: none; + } + + table { + border-collapse: collapse; + border-spacing: 0; + } + + body { + -webkit-text-size-adjust: none; + } + +/* Box Model */ + + *, *:before, *:after { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + +/* Containers */ + + .container { + margin-left: auto; + margin-right: auto; + } + + .container.\31 25\25 { + width: 100%; + max-width: 87.5em; + min-width: 70em; + } + + .container.\37 5\25 { + width: 52.5em; + } + + .container.\35 0\25 { + width: 35em; + } + + .container.\32 5\25 { + width: 17.5em; + } + + .container { + width: 70em; + } + + @media screen and (max-width: 1680px) { + + .container.\31 25\25 { + width: 100%; + max-width: 87.5em; + min-width: 70em; + } + + .container.\37 5\25 { + width: 52.5em; + } + + .container.\35 0\25 { + width: 35em; + } + + .container.\32 5\25 { + width: 17.5em; + } + + .container { + width: 70em; + } + + } + + @media screen and (max-width: 1280px) { + + .container.\31 25\25 { + width: 100%; + max-width: 112.5%; + min-width: 90%; + } + + .container.\37 5\25 { + width: 67.5%; + } + + .container.\35 0\25 { + width: 45%; + } + + .container.\32 5\25 { + width: 22.5%; + } + + .container { + width: 90%; + } + + } + + @media screen and (max-width: 980px) { + + .container.\31 25\25 { + width: 100%; + max-width: 125%; + min-width: 100%; + } + + .container.\37 5\25 { + width: 75%; + } + + .container.\35 0\25 { + width: 50%; + } + + .container.\32 5\25 { + width: 25%; + } + + .container { + width: 100% !important; + } + + } + + @media screen and (max-width: 736px) { + + .container.\31 25\25 { + width: 100%; + max-width: 125%; + min-width: 100%; + } + + .container.\37 5\25 { + width: 75%; + } + + .container.\35 0\25 { + width: 50%; + } + + .container.\32 5\25 { + width: 25%; + } + + .container { + width: 100% !important; + } + + } + + @media screen and (max-width: 480px) { + + .container.\31 25\25 { + width: 100%; + max-width: 125%; + min-width: 100%; + } + + .container.\37 5\25 { + width: 75%; + } + + .container.\35 0\25 { + width: 50%; + } + + .container.\32 5\25 { + width: 25%; + } + + .container { + width: 100% !important; + } + + } + +/* Grid */ + + .row { + border-bottom: solid 1px transparent; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + + .row > * { + float: left; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + + .row:after, .row:before { + content: ''; + display: block; + clear: both; + height: 0; + } + + .row.uniform > * > :first-child { + margin-top: 0; + } + + .row.uniform > * > :last-child { + margin-bottom: 0; + } + + .row.\30 \25 > * { + padding: 0 0 0 0em; + } + + .row.\30 \25 { + margin: 0 0 -1px 0em; + } + + .row.uniform.\30 \25 > * { + padding: 0em 0 0 0em; + } + + .row.uniform.\30 \25 { + margin: 0em 0 -1px 0em; + } + + .row > * { + padding: 0 0 0 2.5em; + } + + .row { + margin: 0 0 -1px -2.5em; + } + + .row.uniform > * { + padding: 2.5em 0 0 2.5em; + } + + .row.uniform { + margin: -2.5em 0 -1px -2.5em; + } + + .row.\32 00\25 > * { + padding: 0 0 0 5em; + } + + .row.\32 00\25 { + margin: 0 0 -1px -5em; + } + + .row.uniform.\32 00\25 > * { + padding: 5em 0 0 5em; + } + + .row.uniform.\32 00\25 { + margin: -5em 0 -1px -5em; + } + + .row.\31 50\25 > * { + padding: 0 0 0 3.75em; + } + + .row.\31 50\25 { + margin: 0 0 -1px -3.75em; + } + + .row.uniform.\31 50\25 > * { + padding: 3.75em 0 0 3.75em; + } + + .row.uniform.\31 50\25 { + margin: -3.75em 0 -1px -3.75em; + } + + .row.\35 0\25 > * { + padding: 0 0 0 1.25em; + } + + .row.\35 0\25 { + margin: 0 0 -1px -1.25em; + } + + .row.uniform.\35 0\25 > * { + padding: 1.25em 0 0 1.25em; + } + + .row.uniform.\35 0\25 { + margin: -1.25em 0 -1px -1.25em; + } + + .row.\32 5\25 > * { + padding: 0 0 0 0.625em; + } + + .row.\32 5\25 { + margin: 0 0 -1px -0.625em; + } + + .row.uniform.\32 5\25 > * { + padding: 0.625em 0 0 0.625em; + } + + .row.uniform.\32 5\25 { + margin: -0.625em 0 -1px -0.625em; + } + + .\31 2u, .\31 2u\24 { + width: 100%; + clear: none; + margin-left: 0; + } + + .\31 1u, .\31 1u\24 { + width: 91.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 0u, .\31 0u\24 { + width: 83.3333333333%; + clear: none; + margin-left: 0; + } + + .\39 u, .\39 u\24 { + width: 75%; + clear: none; + margin-left: 0; + } + + .\38 u, .\38 u\24 { + width: 66.6666666667%; + clear: none; + margin-left: 0; + } + + .\37 u, .\37 u\24 { + width: 58.3333333333%; + clear: none; + margin-left: 0; + } + + .\36 u, .\36 u\24 { + width: 50%; + clear: none; + margin-left: 0; + } + + .\35 u, .\35 u\24 { + width: 41.6666666667%; + clear: none; + margin-left: 0; + } + + .\34 u, .\34 u\24 { + width: 33.3333333333%; + clear: none; + margin-left: 0; + } + + .\33 u, .\33 u\24 { + width: 25%; + clear: none; + margin-left: 0; + } + + .\32 u, .\32 u\24 { + width: 16.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 u, .\31 u\24 { + width: 8.3333333333%; + clear: none; + margin-left: 0; + } + + .\31 2u\24 + *, + .\31 1u\24 + *, + .\31 0u\24 + *, + .\39 u\24 + *, + .\38 u\24 + *, + .\37 u\24 + *, + .\36 u\24 + *, + .\35 u\24 + *, + .\34 u\24 + *, + .\33 u\24 + *, + .\32 u\24 + *, + .\31 u\24 + * { + clear: left; + } + + .\-11u { + margin-left: 91.66667%; + } + + .\-10u { + margin-left: 83.33333%; + } + + .\-9u { + margin-left: 75%; + } + + .\-8u { + margin-left: 66.66667%; + } + + .\-7u { + margin-left: 58.33333%; + } + + .\-6u { + margin-left: 50%; + } + + .\-5u { + margin-left: 41.66667%; + } + + .\-4u { + margin-left: 33.33333%; + } + + .\-3u { + margin-left: 25%; + } + + .\-2u { + margin-left: 16.66667%; + } + + .\-1u { + margin-left: 8.33333%; + } + + @media screen and (max-width: 1680px) { + + .row > * { + padding: 0 0 0 2.5em; + } + + .row { + margin: 0 0 -1px -2.5em; + } + + .row.uniform > * { + padding: 2.5em 0 0 2.5em; + } + + .row.uniform { + margin: -2.5em 0 -1px -2.5em; + } + + .row.\32 00\25 > * { + padding: 0 0 0 5em; + } + + .row.\32 00\25 { + margin: 0 0 -1px -5em; + } + + .row.uniform.\32 00\25 > * { + padding: 5em 0 0 5em; + } + + .row.uniform.\32 00\25 { + margin: -5em 0 -1px -5em; + } + + .row.\31 50\25 > * { + padding: 0 0 0 3.75em; + } + + .row.\31 50\25 { + margin: 0 0 -1px -3.75em; + } + + .row.uniform.\31 50\25 > * { + padding: 3.75em 0 0 3.75em; + } + + .row.uniform.\31 50\25 { + margin: -3.75em 0 -1px -3.75em; + } + + .row.\35 0\25 > * { + padding: 0 0 0 1.25em; + } + + .row.\35 0\25 { + margin: 0 0 -1px -1.25em; + } + + .row.uniform.\35 0\25 > * { + padding: 1.25em 0 0 1.25em; + } + + .row.uniform.\35 0\25 { + margin: -1.25em 0 -1px -1.25em; + } + + .row.\32 5\25 > * { + padding: 0 0 0 0.625em; + } + + .row.\32 5\25 { + margin: 0 0 -1px -0.625em; + } + + .row.uniform.\32 5\25 > * { + padding: 0.625em 0 0 0.625em; + } + + .row.uniform.\32 5\25 { + margin: -0.625em 0 -1px -0.625em; + } + + .\31 2u\28xlarge\29, .\31 2u\24\28xlarge\29 { + width: 100%; + clear: none; + margin-left: 0; + } + + .\31 1u\28xlarge\29, .\31 1u\24\28xlarge\29 { + width: 91.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 0u\28xlarge\29, .\31 0u\24\28xlarge\29 { + width: 83.3333333333%; + clear: none; + margin-left: 0; + } + + .\39 u\28xlarge\29, .\39 u\24\28xlarge\29 { + width: 75%; + clear: none; + margin-left: 0; + } + + .\38 u\28xlarge\29, .\38 u\24\28xlarge\29 { + width: 66.6666666667%; + clear: none; + margin-left: 0; + } + + .\37 u\28xlarge\29, .\37 u\24\28xlarge\29 { + width: 58.3333333333%; + clear: none; + margin-left: 0; + } + + .\36 u\28xlarge\29, .\36 u\24\28xlarge\29 { + width: 50%; + clear: none; + margin-left: 0; + } + + .\35 u\28xlarge\29, .\35 u\24\28xlarge\29 { + width: 41.6666666667%; + clear: none; + margin-left: 0; + } + + .\34 u\28xlarge\29, .\34 u\24\28xlarge\29 { + width: 33.3333333333%; + clear: none; + margin-left: 0; + } + + .\33 u\28xlarge\29, .\33 u\24\28xlarge\29 { + width: 25%; + clear: none; + margin-left: 0; + } + + .\32 u\28xlarge\29, .\32 u\24\28xlarge\29 { + width: 16.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 u\28xlarge\29, .\31 u\24\28xlarge\29 { + width: 8.3333333333%; + clear: none; + margin-left: 0; + } + + .\31 2u\24\28xlarge\29 + *, + .\31 1u\24\28xlarge\29 + *, + .\31 0u\24\28xlarge\29 + *, + .\39 u\24\28xlarge\29 + *, + .\38 u\24\28xlarge\29 + *, + .\37 u\24\28xlarge\29 + *, + .\36 u\24\28xlarge\29 + *, + .\35 u\24\28xlarge\29 + *, + .\34 u\24\28xlarge\29 + *, + .\33 u\24\28xlarge\29 + *, + .\32 u\24\28xlarge\29 + *, + .\31 u\24\28xlarge\29 + * { + clear: left; + } + + .\-11u\28xlarge\29 { + margin-left: 91.66667%; + } + + .\-10u\28xlarge\29 { + margin-left: 83.33333%; + } + + .\-9u\28xlarge\29 { + margin-left: 75%; + } + + .\-8u\28xlarge\29 { + margin-left: 66.66667%; + } + + .\-7u\28xlarge\29 { + margin-left: 58.33333%; + } + + .\-6u\28xlarge\29 { + margin-left: 50%; + } + + .\-5u\28xlarge\29 { + margin-left: 41.66667%; + } + + .\-4u\28xlarge\29 { + margin-left: 33.33333%; + } + + .\-3u\28xlarge\29 { + margin-left: 25%; + } + + .\-2u\28xlarge\29 { + margin-left: 16.66667%; + } + + .\-1u\28xlarge\29 { + margin-left: 8.33333%; + } + + } + + @media screen and (max-width: 1280px) { + + .row > * { + padding: 0 0 0 2.5em; + } + + .row { + margin: 0 0 -1px -2.5em; + } + + .row.uniform > * { + padding: 2.5em 0 0 2.5em; + } + + .row.uniform { + margin: -2.5em 0 -1px -2.5em; + } + + .row.\32 00\25 > * { + padding: 0 0 0 5em; + } + + .row.\32 00\25 { + margin: 0 0 -1px -5em; + } + + .row.uniform.\32 00\25 > * { + padding: 5em 0 0 5em; + } + + .row.uniform.\32 00\25 { + margin: -5em 0 -1px -5em; + } + + .row.\31 50\25 > * { + padding: 0 0 0 3.75em; + } + + .row.\31 50\25 { + margin: 0 0 -1px -3.75em; + } + + .row.uniform.\31 50\25 > * { + padding: 3.75em 0 0 3.75em; + } + + .row.uniform.\31 50\25 { + margin: -3.75em 0 -1px -3.75em; + } + + .row.\35 0\25 > * { + padding: 0 0 0 1.25em; + } + + .row.\35 0\25 { + margin: 0 0 -1px -1.25em; + } + + .row.uniform.\35 0\25 > * { + padding: 1.25em 0 0 1.25em; + } + + .row.uniform.\35 0\25 { + margin: -1.25em 0 -1px -1.25em; + } + + .row.\32 5\25 > * { + padding: 0 0 0 0.625em; + } + + .row.\32 5\25 { + margin: 0 0 -1px -0.625em; + } + + .row.uniform.\32 5\25 > * { + padding: 0.625em 0 0 0.625em; + } + + .row.uniform.\32 5\25 { + margin: -0.625em 0 -1px -0.625em; + } + + .\31 2u\28large\29, .\31 2u\24\28large\29 { + width: 100%; + clear: none; + margin-left: 0; + } + + .\31 1u\28large\29, .\31 1u\24\28large\29 { + width: 91.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 0u\28large\29, .\31 0u\24\28large\29 { + width: 83.3333333333%; + clear: none; + margin-left: 0; + } + + .\39 u\28large\29, .\39 u\24\28large\29 { + width: 75%; + clear: none; + margin-left: 0; + } + + .\38 u\28large\29, .\38 u\24\28large\29 { + width: 66.6666666667%; + clear: none; + margin-left: 0; + } + + .\37 u\28large\29, .\37 u\24\28large\29 { + width: 58.3333333333%; + clear: none; + margin-left: 0; + } + + .\36 u\28large\29, .\36 u\24\28large\29 { + width: 50%; + clear: none; + margin-left: 0; + } + + .\35 u\28large\29, .\35 u\24\28large\29 { + width: 41.6666666667%; + clear: none; + margin-left: 0; + } + + .\34 u\28large\29, .\34 u\24\28large\29 { + width: 33.3333333333%; + clear: none; + margin-left: 0; + } + + .\33 u\28large\29, .\33 u\24\28large\29 { + width: 25%; + clear: none; + margin-left: 0; + } + + .\32 u\28large\29, .\32 u\24\28large\29 { + width: 16.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 u\28large\29, .\31 u\24\28large\29 { + width: 8.3333333333%; + clear: none; + margin-left: 0; + } + + .\31 2u\24\28large\29 + *, + .\31 1u\24\28large\29 + *, + .\31 0u\24\28large\29 + *, + .\39 u\24\28large\29 + *, + .\38 u\24\28large\29 + *, + .\37 u\24\28large\29 + *, + .\36 u\24\28large\29 + *, + .\35 u\24\28large\29 + *, + .\34 u\24\28large\29 + *, + .\33 u\24\28large\29 + *, + .\32 u\24\28large\29 + *, + .\31 u\24\28large\29 + * { + clear: left; + } + + .\-11u\28large\29 { + margin-left: 91.66667%; + } + + .\-10u\28large\29 { + margin-left: 83.33333%; + } + + .\-9u\28large\29 { + margin-left: 75%; + } + + .\-8u\28large\29 { + margin-left: 66.66667%; + } + + .\-7u\28large\29 { + margin-left: 58.33333%; + } + + .\-6u\28large\29 { + margin-left: 50%; + } + + .\-5u\28large\29 { + margin-left: 41.66667%; + } + + .\-4u\28large\29 { + margin-left: 33.33333%; + } + + .\-3u\28large\29 { + margin-left: 25%; + } + + .\-2u\28large\29 { + margin-left: 16.66667%; + } + + .\-1u\28large\29 { + margin-left: 8.33333%; + } + + } + + @media screen and (max-width: 980px) { + + .row > * { + padding: 0 0 0 2.5em; + } + + .row { + margin: 0 0 -1px -2.5em; + } + + .row.uniform > * { + padding: 2.5em 0 0 2.5em; + } + + .row.uniform { + margin: -2.5em 0 -1px -2.5em; + } + + .row.\32 00\25 > * { + padding: 0 0 0 5em; + } + + .row.\32 00\25 { + margin: 0 0 -1px -5em; + } + + .row.uniform.\32 00\25 > * { + padding: 5em 0 0 5em; + } + + .row.uniform.\32 00\25 { + margin: -5em 0 -1px -5em; + } + + .row.\31 50\25 > * { + padding: 0 0 0 3.75em; + } + + .row.\31 50\25 { + margin: 0 0 -1px -3.75em; + } + + .row.uniform.\31 50\25 > * { + padding: 3.75em 0 0 3.75em; + } + + .row.uniform.\31 50\25 { + margin: -3.75em 0 -1px -3.75em; + } + + .row.\35 0\25 > * { + padding: 0 0 0 1.25em; + } + + .row.\35 0\25 { + margin: 0 0 -1px -1.25em; + } + + .row.uniform.\35 0\25 > * { + padding: 1.25em 0 0 1.25em; + } + + .row.uniform.\35 0\25 { + margin: -1.25em 0 -1px -1.25em; + } + + .row.\32 5\25 > * { + padding: 0 0 0 0.625em; + } + + .row.\32 5\25 { + margin: 0 0 -1px -0.625em; + } + + .row.uniform.\32 5\25 > * { + padding: 0.625em 0 0 0.625em; + } + + .row.uniform.\32 5\25 { + margin: -0.625em 0 -1px -0.625em; + } + + .\31 2u\28medium\29, .\31 2u\24\28medium\29 { + width: 100%; + clear: none; + margin-left: 0; + } + + .\31 1u\28medium\29, .\31 1u\24\28medium\29 { + width: 91.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 0u\28medium\29, .\31 0u\24\28medium\29 { + width: 83.3333333333%; + clear: none; + margin-left: 0; + } + + .\39 u\28medium\29, .\39 u\24\28medium\29 { + width: 75%; + clear: none; + margin-left: 0; + } + + .\38 u\28medium\29, .\38 u\24\28medium\29 { + width: 66.6666666667%; + clear: none; + margin-left: 0; + } + + .\37 u\28medium\29, .\37 u\24\28medium\29 { + width: 58.3333333333%; + clear: none; + margin-left: 0; + } + + .\36 u\28medium\29, .\36 u\24\28medium\29 { + width: 50%; + clear: none; + margin-left: 0; + } + + .\35 u\28medium\29, .\35 u\24\28medium\29 { + width: 41.6666666667%; + clear: none; + margin-left: 0; + } + + .\34 u\28medium\29, .\34 u\24\28medium\29 { + width: 33.3333333333%; + clear: none; + margin-left: 0; + } + + .\33 u\28medium\29, .\33 u\24\28medium\29 { + width: 25%; + clear: none; + margin-left: 0; + } + + .\32 u\28medium\29, .\32 u\24\28medium\29 { + width: 16.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 u\28medium\29, .\31 u\24\28medium\29 { + width: 8.3333333333%; + clear: none; + margin-left: 0; + } + + .\31 2u\24\28medium\29 + *, + .\31 1u\24\28medium\29 + *, + .\31 0u\24\28medium\29 + *, + .\39 u\24\28medium\29 + *, + .\38 u\24\28medium\29 + *, + .\37 u\24\28medium\29 + *, + .\36 u\24\28medium\29 + *, + .\35 u\24\28medium\29 + *, + .\34 u\24\28medium\29 + *, + .\33 u\24\28medium\29 + *, + .\32 u\24\28medium\29 + *, + .\31 u\24\28medium\29 + * { + clear: left; + } + + .\-11u\28medium\29 { + margin-left: 91.66667%; + } + + .\-10u\28medium\29 { + margin-left: 83.33333%; + } + + .\-9u\28medium\29 { + margin-left: 75%; + } + + .\-8u\28medium\29 { + margin-left: 66.66667%; + } + + .\-7u\28medium\29 { + margin-left: 58.33333%; + } + + .\-6u\28medium\29 { + margin-left: 50%; + } + + .\-5u\28medium\29 { + margin-left: 41.66667%; + } + + .\-4u\28medium\29 { + margin-left: 33.33333%; + } + + .\-3u\28medium\29 { + margin-left: 25%; + } + + .\-2u\28medium\29 { + margin-left: 16.66667%; + } + + .\-1u\28medium\29 { + margin-left: 8.33333%; + } + + } + + @media screen and (max-width: 736px) { + + .row > * { + padding: 0 0 0 2.5em; + } + + .row { + margin: 0 0 -1px -2.5em; + } + + .row.uniform > * { + padding: 2.5em 0 0 2.5em; + } + + .row.uniform { + margin: -2.5em 0 -1px -2.5em; + } + + .row.\32 00\25 > * { + padding: 0 0 0 5em; + } + + .row.\32 00\25 { + margin: 0 0 -1px -5em; + } + + .row.uniform.\32 00\25 > * { + padding: 5em 0 0 5em; + } + + .row.uniform.\32 00\25 { + margin: -5em 0 -1px -5em; + } + + .row.\31 50\25 > * { + padding: 0 0 0 3.75em; + } + + .row.\31 50\25 { + margin: 0 0 -1px -3.75em; + } + + .row.uniform.\31 50\25 > * { + padding: 3.75em 0 0 3.75em; + } + + .row.uniform.\31 50\25 { + margin: -3.75em 0 -1px -3.75em; + } + + .row.\35 0\25 > * { + padding: 0 0 0 1.25em; + } + + .row.\35 0\25 { + margin: 0 0 -1px -1.25em; + } + + .row.uniform.\35 0\25 > * { + padding: 1.25em 0 0 1.25em; + } + + .row.uniform.\35 0\25 { + margin: -1.25em 0 -1px -1.25em; + } + + .row.\32 5\25 > * { + padding: 0 0 0 0.625em; + } + + .row.\32 5\25 { + margin: 0 0 -1px -0.625em; + } + + .row.uniform.\32 5\25 > * { + padding: 0.625em 0 0 0.625em; + } + + .row.uniform.\32 5\25 { + margin: -0.625em 0 -1px -0.625em; + } + + .\31 2u\28small\29, .\31 2u\24\28small\29 { + width: 100%; + clear: none; + margin-left: 0; + } + + .\31 1u\28small\29, .\31 1u\24\28small\29 { + width: 91.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 0u\28small\29, .\31 0u\24\28small\29 { + width: 83.3333333333%; + clear: none; + margin-left: 0; + } + + .\39 u\28small\29, .\39 u\24\28small\29 { + width: 75%; + clear: none; + margin-left: 0; + } + + .\38 u\28small\29, .\38 u\24\28small\29 { + width: 66.6666666667%; + clear: none; + margin-left: 0; + } + + .\37 u\28small\29, .\37 u\24\28small\29 { + width: 58.3333333333%; + clear: none; + margin-left: 0; + } + + .\36 u\28small\29, .\36 u\24\28small\29 { + width: 50%; + clear: none; + margin-left: 0; + } + + .\35 u\28small\29, .\35 u\24\28small\29 { + width: 41.6666666667%; + clear: none; + margin-left: 0; + } + + .\34 u\28small\29, .\34 u\24\28small\29 { + width: 33.3333333333%; + clear: none; + margin-left: 0; + } + + .\33 u\28small\29, .\33 u\24\28small\29 { + width: 25%; + clear: none; + margin-left: 0; + } + + .\32 u\28small\29, .\32 u\24\28small\29 { + width: 16.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 u\28small\29, .\31 u\24\28small\29 { + width: 8.3333333333%; + clear: none; + margin-left: 0; + } + + .\31 2u\24\28small\29 + *, + .\31 1u\24\28small\29 + *, + .\31 0u\24\28small\29 + *, + .\39 u\24\28small\29 + *, + .\38 u\24\28small\29 + *, + .\37 u\24\28small\29 + *, + .\36 u\24\28small\29 + *, + .\35 u\24\28small\29 + *, + .\34 u\24\28small\29 + *, + .\33 u\24\28small\29 + *, + .\32 u\24\28small\29 + *, + .\31 u\24\28small\29 + * { + clear: left; + } + + .\-11u\28small\29 { + margin-left: 91.66667%; + } + + .\-10u\28small\29 { + margin-left: 83.33333%; + } + + .\-9u\28small\29 { + margin-left: 75%; + } + + .\-8u\28small\29 { + margin-left: 66.66667%; + } + + .\-7u\28small\29 { + margin-left: 58.33333%; + } + + .\-6u\28small\29 { + margin-left: 50%; + } + + .\-5u\28small\29 { + margin-left: 41.66667%; + } + + .\-4u\28small\29 { + margin-left: 33.33333%; + } + + .\-3u\28small\29 { + margin-left: 25%; + } + + .\-2u\28small\29 { + margin-left: 16.66667%; + } + + .\-1u\28small\29 { + margin-left: 8.33333%; + } + + } + + @media screen and (max-width: 480px) { + + .row > * { + padding: 0 0 0 2.5em; + } + + .row { + margin: 0 0 -1px -2.5em; + } + + .row.uniform > * { + padding: 2.5em 0 0 2.5em; + } + + .row.uniform { + margin: -2.5em 0 -1px -2.5em; + } + + .row.\32 00\25 > * { + padding: 0 0 0 5em; + } + + .row.\32 00\25 { + margin: 0 0 -1px -5em; + } + + .row.uniform.\32 00\25 > * { + padding: 5em 0 0 5em; + } + + .row.uniform.\32 00\25 { + margin: -5em 0 -1px -5em; + } + + .row.\31 50\25 > * { + padding: 0 0 0 3.75em; + } + + .row.\31 50\25 { + margin: 0 0 -1px -3.75em; + } + + .row.uniform.\31 50\25 > * { + padding: 3.75em 0 0 3.75em; + } + + .row.uniform.\31 50\25 { + margin: -3.75em 0 -1px -3.75em; + } + + .row.\35 0\25 > * { + padding: 0 0 0 1.25em; + } + + .row.\35 0\25 { + margin: 0 0 -1px -1.25em; + } + + .row.uniform.\35 0\25 > * { + padding: 1.25em 0 0 1.25em; + } + + .row.uniform.\35 0\25 { + margin: -1.25em 0 -1px -1.25em; + } + + .row.\32 5\25 > * { + padding: 0 0 0 0.625em; + } + + .row.\32 5\25 { + margin: 0 0 -1px -0.625em; + } + + .row.uniform.\32 5\25 > * { + padding: 0.625em 0 0 0.625em; + } + + .row.uniform.\32 5\25 { + margin: -0.625em 0 -1px -0.625em; + } + + .\31 2u\28xsmall\29, .\31 2u\24\28xsmall\29 { + width: 100%; + clear: none; + margin-left: 0; + } + + .\31 1u\28xsmall\29, .\31 1u\24\28xsmall\29 { + width: 91.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 0u\28xsmall\29, .\31 0u\24\28xsmall\29 { + width: 83.3333333333%; + clear: none; + margin-left: 0; + } + + .\39 u\28xsmall\29, .\39 u\24\28xsmall\29 { + width: 75%; + clear: none; + margin-left: 0; + } + + .\38 u\28xsmall\29, .\38 u\24\28xsmall\29 { + width: 66.6666666667%; + clear: none; + margin-left: 0; + } + + .\37 u\28xsmall\29, .\37 u\24\28xsmall\29 { + width: 58.3333333333%; + clear: none; + margin-left: 0; + } + + .\36 u\28xsmall\29, .\36 u\24\28xsmall\29 { + width: 50%; + clear: none; + margin-left: 0; + } + + .\35 u\28xsmall\29, .\35 u\24\28xsmall\29 { + width: 41.6666666667%; + clear: none; + margin-left: 0; + } + + .\34 u\28xsmall\29, .\34 u\24\28xsmall\29 { + width: 33.3333333333%; + clear: none; + margin-left: 0; + } + + .\33 u\28xsmall\29, .\33 u\24\28xsmall\29 { + width: 25%; + clear: none; + margin-left: 0; + } + + .\32 u\28xsmall\29, .\32 u\24\28xsmall\29 { + width: 16.6666666667%; + clear: none; + margin-left: 0; + } + + .\31 u\28xsmall\29, .\31 u\24\28xsmall\29 { + width: 8.3333333333%; + clear: none; + margin-left: 0; + } + + .\31 2u\24\28xsmall\29 + *, + .\31 1u\24\28xsmall\29 + *, + .\31 0u\24\28xsmall\29 + *, + .\39 u\24\28xsmall\29 + *, + .\38 u\24\28xsmall\29 + *, + .\37 u\24\28xsmall\29 + *, + .\36 u\24\28xsmall\29 + *, + .\35 u\24\28xsmall\29 + *, + .\34 u\24\28xsmall\29 + *, + .\33 u\24\28xsmall\29 + *, + .\32 u\24\28xsmall\29 + *, + .\31 u\24\28xsmall\29 + * { + clear: left; + } + + .\-11u\28xsmall\29 { + margin-left: 91.66667%; + } + + .\-10u\28xsmall\29 { + margin-left: 83.33333%; + } + + .\-9u\28xsmall\29 { + margin-left: 75%; + } + + .\-8u\28xsmall\29 { + margin-left: 66.66667%; + } + + .\-7u\28xsmall\29 { + margin-left: 58.33333%; + } + + .\-6u\28xsmall\29 { + margin-left: 50%; + } + + .\-5u\28xsmall\29 { + margin-left: 41.66667%; + } + + .\-4u\28xsmall\29 { + margin-left: 33.33333%; + } + + .\-3u\28xsmall\29 { + margin-left: 25%; + } + + .\-2u\28xsmall\29 { + margin-left: 16.66667%; + } + + .\-1u\28xsmall\29 { + margin-left: 8.33333%; + } + + } + +/* Basic */ + + html, body { + background: #1c1d26; + } + + body.is-loading *, body.is-loading *:before, body.is-loading *:after { + -moz-animation: none !important; + -webkit-animation: none !important; + -ms-animation: none !important; + animation: none !important; + -moz-transition: none !important; + -webkit-transition: none !important; + -ms-transition: none !important; + transition: none !important; + } + + body, input, select, textarea { + color: rgba(255, 255, 255, 0.75); + font-family: "Roboto", Helvetica, sans-serif; + font-size: 15pt; + font-weight: 100; + line-height: 1.75em; + } + + a { + -moz-transition: border-color 0.2s ease-in-out, color 0.2s ease-in-out; + -webkit-transition: border-color 0.2s ease-in-out, color 0.2s ease-in-out; + -ms-transition: border-color 0.2s ease-in-out, color 0.2s ease-in-out; + transition: border-color 0.2s ease-in-out, color 0.2s ease-in-out; + border-bottom: dotted 1px; + color: #e44c65; + text-decoration: none; + } + + a:hover { + color: #e44c65 !important; + border-bottom-color: transparent; + } + + strong, b { + color: #ffffff; + font-weight: 300; + } + + em, i { + font-style: italic; + } + + p { + margin: 0 0 2em 0; + } + + h1, h2, h3, h4, h5, h6 { + color: #ffffff; + font-weight: 300; + line-height: 1em; + margin: 0 0 1em 0; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + color: inherit; + border: 0; + } + + h2 { + font-size: 2em; + line-height: 1.5em; + letter-spacing: -0.025em; + } + + h3 { + font-size: 1.35em; + line-height: 1.5em; + } + + h4 { + font-size: 1.1em; + line-height: 1.5em; + } + + h5 { + font-size: 0.9em; + line-height: 1.5em; + } + + h6 { + font-size: 0.7em; + line-height: 1.5em; + } + + sub { + font-size: 0.8em; + position: relative; + top: 0.5em; + } + + sup { + font-size: 0.8em; + position: relative; + top: -0.5em; + } + + hr { + border: 0; + border-bottom: solid 1px rgba(255, 255, 255, 0.3); + margin: 3em 0; + } + + hr.major { + margin: 4em 0; + } + + blockquote { + border-left: solid 4px rgba(255, 255, 255, 0.3); + font-style: italic; + margin: 0 0 2em 0; + padding: 0.5em 0 0.5em 2em; + } + + code { + background: rgba(255, 255, 255, 0.075); + border-radius: 4px; + font-family: "Courier New", monospace; + font-size: 0.9em; + margin: 0 0.25em; + padding: 0.25em 0.65em; + } + + pre { + -webkit-overflow-scrolling: touch; + font-family: "Courier New", monospace; + font-size: 0.9em; + margin: 0 0 2em 0; + } + + pre code { + display: block; + line-height: 1.75em; + padding: 1em 1.5em; + overflow-x: auto; + } + + .align-left { + text-align: left; + } + + .align-center { + text-align: center; + } + + .align-right { + text-align: right; + } + +/* Loader */ + + @-moz-keyframes spinner-show { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } + } + + @-webkit-keyframes spinner-show { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } + } + + @-ms-keyframes spinner-show { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } + } + + @keyframes spinner-show { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } + } + + @-moz-keyframes spinner-hide { + 0% { + color: rgba(255, 255, 255, 0.15); + z-index: 100001; + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 99% { + color: #1c1d26; + z-index: 100001; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + + 100% { + color: #1c1d26; + z-index: -1; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + } + + @-webkit-keyframes spinner-hide { + 0% { + color: rgba(255, 255, 255, 0.15); + z-index: 100001; + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 99% { + color: #1c1d26; + z-index: 100001; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + + 100% { + color: #1c1d26; + z-index: -1; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + } + + @-ms-keyframes spinner-hide { + 0% { + color: rgba(255, 255, 255, 0.15); + z-index: 100001; + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 99% { + color: #1c1d26; + z-index: 100001; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + + 100% { + color: #1c1d26; + z-index: -1; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + } + + @keyframes spinner-hide { + 0% { + color: rgba(255, 255, 255, 0.15); + z-index: 100001; + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 99% { + color: #1c1d26; + z-index: 100001; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + + 100% { + color: #1c1d26; + z-index: -1; + -moz-transform: scale(0.5) rotate(360deg); + -webkit-transform: scale(0.5) rotate(360deg); + -ms-transform: scale(0.5) rotate(360deg); + transform: scale(0.5) rotate(360deg); + } + } + + @-moz-keyframes spinner-rotate { + 0% { + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 100% { + -moz-transform: scale(1) rotate(360deg); + -webkit-transform: scale(1) rotate(360deg); + -ms-transform: scale(1) rotate(360deg); + transform: scale(1) rotate(360deg); + } + } + + @-webkit-keyframes spinner-rotate { + 0% { + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 100% { + -moz-transform: scale(1) rotate(360deg); + -webkit-transform: scale(1) rotate(360deg); + -ms-transform: scale(1) rotate(360deg); + transform: scale(1) rotate(360deg); + } + } + + @-ms-keyframes spinner-rotate { + 0% { + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 100% { + -moz-transform: scale(1) rotate(360deg); + -webkit-transform: scale(1) rotate(360deg); + -ms-transform: scale(1) rotate(360deg); + transform: scale(1) rotate(360deg); + } + } + + @keyframes spinner-rotate { + 0% { + -moz-transform: scale(1) rotate(0deg); + -webkit-transform: scale(1) rotate(0deg); + -ms-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); + } + + 100% { + -moz-transform: scale(1) rotate(360deg); + -webkit-transform: scale(1) rotate(360deg); + -ms-transform: scale(1) rotate(360deg); + transform: scale(1) rotate(360deg); + } + } + + @-moz-keyframes overlay-hide { + 0% { + opacity: 1; + z-index: 100000; + } + + 15% { + opacity: 1; + z-index: 100000; + } + + 99% { + opacity: 0; + z-index: 100000; + } + + 100% { + opacity: 0; + z-index: -1; + } + } + + @-webkit-keyframes overlay-hide { + 0% { + opacity: 1; + z-index: 100000; + } + + 15% { + opacity: 1; + z-index: 100000; + } + + 99% { + opacity: 0; + z-index: 100000; + } + + 100% { + opacity: 0; + z-index: -1; + } + } + + @-ms-keyframes overlay-hide { + 0% { + opacity: 1; + z-index: 100000; + } + + 15% { + opacity: 1; + z-index: 100000; + } + + 99% { + opacity: 0; + z-index: 100000; + } + + 100% { + opacity: 0; + z-index: -1; + } + } + + @keyframes overlay-hide { + 0% { + opacity: 1; + z-index: 100000; + } + + 15% { + opacity: 1; + z-index: 100000; + } + + 99% { + opacity: 0; + z-index: 100000; + } + + 100% { + opacity: 0; + z-index: -1; + } + } + + body.landing { + text-decoration: none; + } + + body.landing:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + body.landing:before { + -moz-animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-hide 0.25s ease-in-out forwards !important; + -webkit-animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-hide 0.25s ease-in-out forwards !important; + -ms-animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-hide 0.25s ease-in-out forwards !important; + animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-hide 0.25s ease-in-out forwards !important; + -moz-transform-origin: 50% 50%; + -webkit-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + color: rgba(255, 255, 255, 0.15); + content: '\f1ce'; + cursor: default; + display: block; + font-size: 2em; + height: 2em; + left: 50%; + line-height: 2em; + margin: -1em 0 0 -1em; + opacity: 0; + position: fixed; + text-align: center; + top: 50%; + width: 2em; + z-index: -1; + } + + body.landing:after { + -moz-animation: overlay-hide 1.5s ease-in forwards !important; + -webkit-animation: overlay-hide 1.5s ease-in forwards !important; + -ms-animation: overlay-hide 1.5s ease-in forwards !important; + animation: overlay-hide 1.5s ease-in forwards !important; + background: #1c1d26; + content: ''; + display: block; + height: 100%; + left: 0; + opacity: 0; + position: fixed; + top: 0; + width: 100%; + z-index: -1; + } + + body.landing.is-loading:before { + -moz-animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-rotate 0.75s infinite linear !important; + -webkit-animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-rotate 0.75s infinite linear !important; + -ms-animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-rotate 0.75s infinite linear !important; + animation: spinner-show 1.5s 1 0.25s ease forwards, spinner-rotate 0.75s infinite linear !important; + z-index: 100001; + } + + body.landing.is-loading:after { + -moz-animation: none !important; + -webkit-animation: none !important; + -ms-animation: none !important; + animation: none !important; + opacity: 1; + z-index: 100000; + } + + @media (-webkit-min-device-pixel-ratio: 2) { + + body.landing:before { + line-height: 2.025em; + } + + } + +/* Section/Article */ + + section.special, article.special { + text-align: center; + } + + header p { + color: #ffffff; + position: relative; + margin: 0 0 1.5em 0; + } + + header h2 + p { + font-size: 1.25em; + margin-top: -1em; + line-height: 1.75em; + } + + header h3 + p { + font-size: 1.1em; + margin-top: -0.8em; + line-height: 1.75em; + } + + header h4 + p, + header h5 + p, + header h6 + p { + font-size: 0.9em; + margin-top: -0.6em; + line-height: 1.5em; + } + + header.major { + margin: 0 0 4em 0; + position: relative; + text-align: center; + } + + header.major:after { + background: #e44c65; + content: ''; + display: inline-block; + height: 0.2em; + max-width: 20em; + width: 75%; + } + + footer.major { + margin: 4em 0 0 0; + } + +/* Form */ + + form { + margin: 0 0 2em 0; + } + + label { + color: #ffffff; + display: block; + font-size: 0.9em; + font-weight: 300; + margin: 0 0 1em 0; + } + + input[type="text"], + input[type="password"], + input[type="email"], + select, + textarea { + -moz-appearance: none; + -webkit-appearance: none; + -ms-appearance: none; + appearance: none; + -moz-transition: border-color 0.2s ease-in-out; + -webkit-transition: border-color 0.2s ease-in-out; + -ms-transition: border-color 0.2s ease-in-out; + transition: border-color 0.2s ease-in-out; + background: transparent; + border-radius: 4px; + border: solid 1px rgba(255, 255, 255, 0.3); + color: inherit; + display: block; + outline: 0; + padding: 0 1em; + text-decoration: none; + width: 100%; + } + + input[type="text"]:invalid, + input[type="password"]:invalid, + input[type="email"]:invalid, + select:invalid, + textarea:invalid { + box-shadow: none; + } + + input[type="text"]:focus, + input[type="password"]:focus, + input[type="email"]:focus, + select:focus, + textarea:focus { + border-color: #e44c65; + } + + .select-wrapper { + text-decoration: none; + display: block; + position: relative; + } + + .select-wrapper:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + .select-wrapper:before { + color: rgba(255, 255, 255, 0.3); + content: '\f078'; + display: block; + height: 3em; + line-height: 3em; + pointer-events: none; + position: absolute; + right: 0; + text-align: center; + top: 0; + width: 3em; + } + + .select-wrapper select::-ms-expand { + display: none; + } + + input[type="text"], + input[type="password"], + input[type="email"], + select { + height: 3em; + } + + textarea { + padding: 0.75em 1em; + } + + select option { + background-color: #1c1d26; + color: #ffffff; + } + + select:focus::-ms-value { + background: transparent; + } + + input[type="checkbox"], + input[type="radio"] { + -moz-appearance: none; + -webkit-appearance: none; + -ms-appearance: none; + appearance: none; + display: block; + float: left; + margin-right: -2em; + opacity: 0; + width: 1em; + z-index: -1; + } + + input[type="checkbox"] + label, + input[type="radio"] + label { + text-decoration: none; + color: rgba(255, 255, 255, 0.75); + cursor: pointer; + display: inline-block; + font-size: 1em; + font-weight: 100; + padding-left: 2.55em; + padding-right: 0.75em; + position: relative; + } + + input[type="checkbox"] + label:before, + input[type="radio"] + label:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + input[type="checkbox"] + label:before, + input[type="radio"] + label:before { + border-radius: 4px; + border: solid 1px rgba(255, 255, 255, 0.3); + content: ''; + display: inline-block; + height: 1.8em; + left: 0; + line-height: 1.725em; + position: absolute; + text-align: center; + top: 0; + width: 1.8em; + } + + input[type="checkbox"]:checked + label:before, + input[type="radio"]:checked + label:before { + background: rgba(255, 255, 255, 0.25); + color: #ffffff; + content: '\f00c'; + } + + input[type="checkbox"]:focus + label:before, + input[type="radio"]:focus + label:before { + border-color: #e44c65; + } + + input[type="checkbox"] + label:before { + border-radius: 4px; + } + + input[type="radio"] + label:before { + border-radius: 100%; + } + + ::-webkit-input-placeholder { + color: rgba(255, 255, 255, 0.5) !important; + opacity: 1.0; + } + + :-moz-placeholder { + color: rgba(255, 255, 255, 0.5) !important; + opacity: 1.0; + } + + ::-moz-placeholder { + color: rgba(255, 255, 255, 0.5) !important; + opacity: 1.0; + } + + :-ms-input-placeholder { + color: rgba(255, 255, 255, 0.5) !important; + opacity: 1.0; + } + + .formerize-placeholder { + color: rgba(255, 255, 255, 0.5) !important; + opacity: 1.0; + } + +/* Box */ + + .box { + border-radius: 4px; + border: solid 1px rgba(255, 255, 255, 0.3); + margin-bottom: 2em; + padding: 1.5em; + } + + .box > :last-child, + .box > :last-child > :last-child, + .box > :last-child > :last-child > :last-child { + margin-bottom: 0; + } + + .box.alt { + border: 0; + border-radius: 0; + padding: 0; + } + +/* Icon */ + + .icon { + text-decoration: none; + border-bottom: none; + position: relative; + } + + .icon:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + .icon > .label { + display: none; + } + + .icon.alt { + text-decoration: none; + } + + .icon.alt:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + .icon.alt:before { + color: #1c1d26 !important; + text-shadow: 1px 0 0 #ffffff, -1px 0 0 #ffffff, 0 1px 0 #ffffff, 0 -1px 0 #ffffff; + } + + .icon.major { + background: #272833; + border-radius: 100%; + cursor: default; + display: inline-block; + height: 6em; + line-height: 6em; + margin: 0 0 2em 0; + text-align: center; + width: 6em; + } + + .icon.major:before { + font-size: 2.25em; + } + + .icon.major.alt { + text-decoration: none; + } + + .icon.major.alt:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + .icon.major.alt:before { + color: #272833 !important; + text-shadow: 1px 0 0 #ffffff, -1px 0 0 #ffffff, 0 1px 0 #ffffff, 0 -1px 0 #ffffff; + } + +/* Image */ + + .image { + border-radius: 4px; + border: 0; + display: inline-block; + position: relative; + overflow: hidden; + } + + .image:before { + content: ''; + display: block; + position: absolute; + left: 0; + top: 0; + background-image: url("images/overlay.png"); + width: 100%; + height: 100%; + z-index: 1; + } + + .image img { + border-radius: 4px; + display: block; + } + + .image.left { + float: left; + margin: 0 1.5em 1em 0; + top: 0.25em; + } + + .image.right { + float: right; + margin: 0 0 1em 1.5em; + top: 0.25em; + } + + .image.left, .image.right { + max-width: 40%; + } + + .image.left img, .image.right img { + width: 100%; + } + + .image.fit { + display: block; + margin: 0 0 2em 0; + width: 100%; + } + + .image.fit img { + width: 100%; + } + +/* List */ + + ol { + list-style: decimal; + margin: 0 0 2em 0; + padding-left: 1.25em; + } + + ol li { + padding-left: 0.25em; + } + + ul { + list-style: disc; + margin: 0 0 2em 0; + padding-left: 1em; + } + + ul li { + padding-left: 0.5em; + } + + ul.alt { + list-style: none; + padding-left: 0; + } + + ul.alt li { + border-top: solid 1px rgba(255, 255, 255, 0.3); + padding: 0.5em 0; + } + + ul.alt li:first-child { + border-top: 0; + padding-top: 0; + } + + ul.icons { + cursor: default; + list-style: none; + padding-left: 0; + } + + ul.icons li { + display: inline-block; + height: 2.5em; + line-height: 2.5em; + padding: 0 0.5em; + } + + ul.icons li .icon { + font-size: 0.8em; + } + + ul.icons li .icon:before { + font-size: 2em; + } + + ul.actions { + cursor: default; + list-style: none; + padding-left: 0; + } + + ul.actions li { + display: inline-block; + padding: 0 1em 0 0; + vertical-align: middle; + } + + ul.actions li:last-child { + padding-right: 0; + } + + ul.actions.small li { + padding: 0 0.5em 0 0; + } + + ul.actions.vertical li { + display: block; + padding: 1em 0 0 0; + } + + ul.actions.vertical li:first-child { + padding-top: 0; + } + + ul.actions.vertical li > * { + margin-bottom: 0; + } + + ul.actions.vertical.small li { + padding: 0.5em 0 0 0; + } + + ul.actions.vertical.small li:first-child { + padding-top: 0; + } + + ul.actions.fit { + display: table; + margin-left: -1em; + padding: 0; + table-layout: fixed; + width: calc(100% + 1em); + } + + ul.actions.fit li { + display: table-cell; + padding: 0 0 0 1em; + } + + ul.actions.fit li > * { + margin-bottom: 0; + } + + ul.actions.fit.small { + margin-left: -0.5em; + width: calc(100% + 0.5em); + } + + ul.actions.fit.small li { + padding: 0 0 0 0.5em; + } + + dl { + margin: 0 0 2em 0; + } + +/* Table */ + + .table-wrapper { + -webkit-overflow-scrolling: touch; + overflow-x: auto; + } + + table { + margin: 0 0 2em 0; + width: 100%; + } + + table tbody tr { + border: solid 1px rgba(255, 255, 255, 0.3); + border-left: 0; + border-right: 0; + } + + table tbody tr:nth-child(2n + 1) { + background-color: rgba(255, 255, 255, 0.075); + } + + table td { + padding: 0.75em 0.75em; + } + + table th { + color: #ffffff; + font-size: 0.9em; + font-weight: 300; + padding: 0 0.75em 0.75em 0.75em; + text-align: left; + } + + table thead { + border-bottom: solid 1px rgba(255, 255, 255, 0.3); + } + + table tfoot { + border-top: solid 1px rgba(255, 255, 255, 0.3); + } + + table.alt { + border-collapse: separate; + } + + table.alt tbody tr td { + border: solid 1px rgba(255, 255, 255, 0.3); + border-left-width: 0; + border-top-width: 0; + } + + table.alt tbody tr td:first-child { + border-left-width: 1px; + } + + table.alt tbody tr:first-child td { + border-top-width: 1px; + } + + table.alt thead { + border-bottom: 0; + } + + table.alt tfoot { + border-top: 0; + } + +/* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + .button { + -moz-appearance: none; + -webkit-appearance: none; + -ms-appearance: none; + appearance: none; + -moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; + -webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; + -ms-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; + transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; + background-color: transparent; + border-radius: 4px; + border: 0; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3); + color: #ffffff !important; + cursor: pointer; + display: inline-block; + font-weight: 300; + height: 3em; + line-height: 3em; + padding: 0 2.25em; + text-align: center; + text-decoration: none; + white-space: nowrap; + } + + input[type="submit"]:hover, input[type="submit"]:active, + input[type="reset"]:hover, + input[type="reset"]:active, + input[type="button"]:hover, + input[type="button"]:active, + .button:hover, + .button:active { + box-shadow: inset 0 0 0 1px #e44c65; + color: #e44c65 !important; + } + + input[type="submit"]:active, + input[type="reset"]:active, + input[type="button"]:active, + .button:active { + background-color: rgba(228, 76, 101, 0.15); + } + + input[type="submit"].icon:before, + input[type="reset"].icon:before, + input[type="button"].icon:before, + .button.icon:before { + margin-right: 0.5em; + } + + input[type="submit"].fit, + input[type="reset"].fit, + input[type="button"].fit, + .button.fit { + display: block; + margin: 0 0 1em 0; + width: 100%; + } + + input[type="submit"].small, + input[type="reset"].small, + input[type="button"].small, + .button.small { + font-size: 0.8em; + } + + input[type="submit"].big, + input[type="reset"].big, + input[type="button"].big, + .button.big { + font-size: 1.35em; + } + + input[type="submit"].special, + input[type="reset"].special, + input[type="button"].special, + .button.special { + background-color: #e44c65; + box-shadow: none; + color: #ffffff !important; + } + + input[type="submit"].special:hover, + input[type="reset"].special:hover, + input[type="button"].special:hover, + .button.special:hover { + background-color: #e76278; + } + + input[type="submit"].special:active, + input[type="reset"].special:active, + input[type="button"].special:active, + .button.special:active { + background-color: #e13652; + } + + input[type="submit"].disabled, input[type="submit"]:disabled, + input[type="reset"].disabled, + input[type="reset"]:disabled, + input[type="button"].disabled, + input[type="button"]:disabled, + .button.disabled, + .button:disabled { + background-color: rgba(255, 255, 255, 0.3) !important; + box-shadow: none !important; + color: #ffffff !important; + cursor: default; + opacity: 0.25; + } + +/* Goto Next */ + + .goto-next { + border: 0; + bottom: 0; + display: block; + height: 5em; + left: 50%; + margin: 0 0 0 -5em; + overflow: hidden; + position: absolute; + text-indent: 10em; + white-space: nowrap; + width: 10em; + z-index: 1; + } + + .goto-next:before { + background-image: url("images/arrow.svg"); + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + content: ''; + display: block; + height: 1.5em; + left: 50%; + margin: -0.75em 0 0 -1em; + position: absolute; + top: 50%; + width: 2em; + z-index: 1; + } + +/* Spotlight */ + + .spotlight { + background-attachment: fixed; + background-position: center center; + background-size: cover; + box-shadow: 0 0.25em 0.5em 0 rgba(0, 0, 0, 0.25); + height: 100vh; + overflow: hidden; + position: relative; + } + + .spotlight:nth-last-of-type(1) { + z-index: 1; + } + + .spotlight:nth-last-of-type(2) { + z-index: 2; + } + + .spotlight:nth-last-of-type(3) { + z-index: 3; + } + + .spotlight:nth-last-of-type(4) { + z-index: 4; + } + + .spotlight:nth-last-of-type(5) { + z-index: 5; + } + + .spotlight:nth-last-of-type(6) { + z-index: 6; + } + + .spotlight:nth-last-of-type(7) { + z-index: 7; + } + + .spotlight:nth-last-of-type(8) { + z-index: 8; + } + + .spotlight:nth-last-of-type(9) { + z-index: 9; + } + + .spotlight:nth-last-of-type(10) { + z-index: 10; + } + + .spotlight:nth-last-of-type(11) { + z-index: 11; + } + + .spotlight:nth-last-of-type(12) { + z-index: 12; + } + + .spotlight:nth-last-of-type(13) { + z-index: 13; + } + + .spotlight:nth-last-of-type(14) { + z-index: 14; + } + + .spotlight:nth-last-of-type(15) { + z-index: 15; + } + + .spotlight:nth-last-of-type(16) { + z-index: 16; + } + + .spotlight:nth-last-of-type(17) { + z-index: 17; + } + + .spotlight:nth-last-of-type(18) { + z-index: 18; + } + + .spotlight:nth-last-of-type(19) { + z-index: 19; + } + + .spotlight:nth-last-of-type(20) { + z-index: 20; + } + + .spotlight:before { + background-image: url("images/overlay.png"); + content: ''; + display: block; + height: 100%; + left: 0; + top: 0; + width: 100%; + } + + .spotlight .image.main { + display: none; + } + + .spotlight .image.main img { + position: relative; + } + + .spotlight .content { + -moz-transform: translate(0,0); + -webkit-transform: translate(0,0); + -ms-transform: translate(0,0); + transform: translate(0,0); + -moz-transition: -moz-transform 1s ease, opacity 1s ease; + -webkit-transition: -webkit-transform 1s ease, opacity 1s ease; + -ms-transition: -ms-transform 1s ease, opacity 1s ease; + transition: transform 1s ease, opacity 1s ease; + background: rgba(23, 24, 32, 0.95); + border-style: solid; + opacity: 1; + position: absolute; + } + + .spotlight .goto-next { + -moz-transform: translate(0,0); + -webkit-transform: translate(0,0); + -ms-transform: translate(0,0); + transform: translate(0,0); + -moz-transition: -moz-transform 0.75s ease, opacity 1s ease-in; + -webkit-transition: -webkit-transform 0.75s ease, opacity 1s ease-in; + -ms-transition: -ms-transform 0.75s ease, opacity 1s ease-in; + transition: transform 0.75s ease, opacity 1s ease-in; + -moz-transition-delay: 0.5s; + -webkit-transition-delay: 0.5s; + -ms-transition-delay: 0.5s; + transition-delay: 0.5s; + opacity: 1; + } + + .spotlight.top .content, .spotlight.bottom .content { + left: 0; + padding: 5.1em 0 3.1em 0; + width: 100%; + } + + .spotlight.top .content { + border-bottom-width: 0.35em; + top: 0; + } + + .spotlight.bottom .content { + border-top-width: 0.35em; + bottom: 0; + } + + .spotlight.left .content, .spotlight.right .content { + height: 101%; + padding: 6em 3em; + top: 0; + width: 28em; + } + + .spotlight.left .content { + border-right-width: 0.35em; + left: 0; + } + + .spotlight.right .content { + border-left-width: 0.35em; + right: 0; + } + + .spotlight.style1 .content { + border-color: #e44c65; + } + + .spotlight.style2 .content { + border-color: #5480f1; + } + + .spotlight.style3 .content { + border-color: #39c088; + } + + .spotlight.inactive .content { + opacity: 0; + } + + .spotlight.inactive .goto-next { + -moz-transform: translate(0,1.5em); + -webkit-transform: translate(0,1.5em); + -ms-transform: translate(0,1.5em); + transform: translate(0,1.5em); + opacity: 0; + } + + .spotlight.inactive.top .content { + -moz-transform: translate(0,-5em); + -webkit-transform: translate(0,-5em); + -ms-transform: translate(0,-5em); + transform: translate(0,-5em); + } + + .spotlight.inactive.bottom .content { + -moz-transform: translate(0,5em); + -webkit-transform: translate(0,5em); + -ms-transform: translate(0,5em); + transform: translate(0,5em); + } + + .spotlight.inactive.left .content { + -moz-transform: translate(-5em,0); + -webkit-transform: translate(-5em,0); + -ms-transform: translate(-5em,0); + transform: translate(-5em,0); + } + + .spotlight.inactive.right .content { + -moz-transform: translate(5em,0); + -webkit-transform: translate(5em,0); + -ms-transform: translate(5em,0); + transform: translate(5em,0); + } + + body.is-touch .spotlight { + background-attachment: scroll; + } + +/* Wrapper */ + + .wrapper { + padding: 6em 0 4em 0; + } + + .wrapper.style2 { + background: #e44c65; + } + + .wrapper.style2 input[type="text"]:focus, + .wrapper.style2 input[type="password"]:focus, + .wrapper.style2 input[type="email"]:focus, + .wrapper.style2 select:focus, + .wrapper.style2 textarea:focus { + border-color: rgba(255, 255, 255, 0.5); + } + + .wrapper.style2 input[type="submit"]:hover, .wrapper.style2 input[type="submit"]:active, + .wrapper.style2 input[type="reset"]:hover, + .wrapper.style2 input[type="reset"]:active, + .wrapper.style2 input[type="button"]:hover, + .wrapper.style2 input[type="button"]:active, + .wrapper.style2 .button:hover, + .wrapper.style2 .button:active { + background-color: rgba(255, 255, 255, 0.075) !important; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5) !important; + color: #ffffff !important; + } + + .wrapper.style2 input[type="submit"]:active, + .wrapper.style2 input[type="reset"]:active, + .wrapper.style2 input[type="button"]:active, + .wrapper.style2 .button:active { + background-color: rgba(255, 255, 255, 0.25) !important; + } + + .wrapper.style2 input[type="submit"].special, + .wrapper.style2 input[type="reset"].special, + .wrapper.style2 input[type="button"].special, + .wrapper.style2 .button.special { + background-color: #ffffff; + color: #e44c65 !important; + } + + .wrapper.style2 input[type="submit"].special:hover, .wrapper.style2 input[type="submit"].special:active, + .wrapper.style2 input[type="reset"].special:hover, + .wrapper.style2 input[type="reset"].special:active, + .wrapper.style2 input[type="button"].special:hover, + .wrapper.style2 input[type="button"].special:active, + .wrapper.style2 .button.special:hover, + .wrapper.style2 .button.special:active { + background-color: rgba(255, 255, 255, 0.075) !important; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5) !important; + color: #ffffff !important; + } + + .wrapper.style2 input[type="submit"].special:active, + .wrapper.style2 input[type="reset"].special:active, + .wrapper.style2 input[type="button"].special:active, + .wrapper.style2 .button.special:active { + background-color: rgba(255, 255, 255, 0.25) !important; + } + + .wrapper.fade-down > .container { + -moz-transform: translate(0,0); + -webkit-transform: translate(0,0); + -ms-transform: translate(0,0); + transform: translate(0,0); + -moz-transition: -moz-transform 1s ease, opacity 1s ease; + -webkit-transition: -webkit-transform 1s ease, opacity 1s ease; + -ms-transition: -ms-transform 1s ease, opacity 1s ease; + transition: transform 1s ease, opacity 1s ease; + opacity: 1; + } + + .wrapper.fade-down.inactive > .container { + -moz-transform: translate(0,-1em); + -webkit-transform: translate(0,-1em); + -ms-transform: translate(0,-1em); + transform: translate(0,-1em); + opacity: 0; + } + + .wrapper.fade-up > .container { + -moz-transform: translate(0,0); + -webkit-transform: translate(0,0); + -ms-transform: translate(0,0); + transform: translate(0,0); + -moz-transition: -moz-transform 1s ease, opacity 1s ease; + -webkit-transition: -webkit-transform 1s ease, opacity 1s ease; + -ms-transition: -ms-transform 1s ease, opacity 1s ease; + transition: transform 1s ease, opacity 1s ease; + opacity: 1; + } + + .wrapper.fade-up.inactive > .container { + -moz-transform: translate(0,1em); + -webkit-transform: translate(0,1em); + -ms-transform: translate(0,1em); + transform: translate(0,1em); + opacity: 0; + } + + .wrapper.fade > .container { + -moz-transition: opacity 1s ease; + -webkit-transition: opacity 1s ease; + -ms-transition: opacity 1s ease; + transition: opacity 1s ease; + opacity: 1; + } + + .wrapper.fade.inactive > .container { + opacity: 0; + } + +/* Dropotron */ + + .dropotron { + background: rgba(39, 40, 51, 0.965); + border-radius: 4px; + box-shadow: 0 0.075em 0.35em 0 rgba(0, 0, 0, 0.125); + list-style: none; + margin-top: calc(-0.25em + 1px); + min-width: 12em; + padding: 0.25em 0; + } + + .dropotron > li { + border-top: solid 1px rgba(255, 255, 255, 0.035); + padding: 0; + } + + .dropotron > li a, .dropotron > li span { + border: 0; + color: rgba(255, 255, 255, 0.75); + display: block; + padding: 0.1em 1em; + text-decoration: none; + } + + .dropotron > li:first-child { + border-top: 0; + } + + .dropotron > li.active > a, .dropotron > li.active > span { + color: #e44c65; + } + + .dropotron.level-0 { + font-size: 0.8em; + margin-top: 1em; + } + + .dropotron.level-0:before { + -moz-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + background: #272833; + content: ''; + display: block; + height: 1em; + position: absolute; + right: 1.5em; + top: -0.5em; + width: 1em; + } + + body.landing .dropotron.level-0 { + margin-top: 0; + } + +/* Header */ + + #page-wrapper { + padding-top: 3.5em; + } + + #header { + background: rgba(39, 40, 51, 0.965); + box-shadow: 0 0 0.25em 0 rgba(0, 0, 0, 0.25); + cursor: default; + height: 3.5em; + left: 0; + line-height: 3.5em; + position: fixed; + top: 0; + width: 100%; + z-index: 100; + } + + #header h1 { + height: inherit; + left: 1.25em; + line-height: inherit; + margin: 0; + position: absolute; + top: 0; + } + + #header nav { + position: absolute; + right: 1em; + top: 0; + } + + #header nav ul { + margin: 0; + } + + #header nav ul li { + display: inline-block; + margin-left: 1em; + } + + #header nav ul li a, #header nav ul li span { + border: 0; + color: inherit; + display: inline-block; + height: inherit; + line-height: inherit; + outline: 0; + } + + #header nav ul li a.button, #header nav ul li span.button { + height: 2em; + line-height: 2em; + padding: 0 1.25em; + } + + #header nav ul li a:not(.button):before, #header nav ul li span:not(.button):before { + margin-right: 0.5em; + } + + #header nav ul li.active > a, #header nav ul li.active > span { + color: #e44c65; + } + + #header nav ul li > ul { + display: none; + } + + body.landing #page-wrapper { + padding-top: 0; + } + + body.landing #header { + background: transparent; + box-shadow: none; + position: absolute; + } + +/* Banner */ + + #banner { + background-attachment: fixed; + background-color: #272833; + background-image: url("../../images/banner.jpg"); + background-position: center center; + background-size: cover; + box-shadow: 0 0.25em 0.5em 0 rgba(0, 0, 0, 0.25); + min-height: 100vh; + position: relative; + text-align: center; + z-index: 21; + } + + #banner:before { + content: ''; + display: inline-block; + height: 100vh; + vertical-align: middle; + width: 1%; + } + + #banner:after { + background-image: -moz-linear-gradient(top, rgba(23, 24, 32, 0.95), rgba(23, 24, 32, 0.95)), url("images/overlay.png");; + background-image: -webkit-linear-gradient(top, rgba(23, 24, 32, 0.95), rgba(23, 24, 32, 0.95)), url("images/overlay.png");; + background-image: -ms-linear-gradient(top, rgba(23, 24, 32, 0.95), rgba(23, 24, 32, 0.95)), url("images/overlay.png");; + background-image: linear-gradient(top, rgba(23, 24, 32, 0.95), rgba(23, 24, 32, 0.95)), url("images/overlay.png");; + content: ''; + display: block; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + + #banner .content { + display: inline-block; + margin-right: 1%; + max-width: 95%; + padding: 6em; + position: relative; + text-align: right; + vertical-align: middle; + z-index: 1; + } + + #banner .content header { + display: inline-block; + vertical-align: middle; + } + + #banner .content header h2 { + font-size: 2.5em; + margin: 0; + } + + #banner .content header p { + margin: 0.5em 0 0 0; + top: 0; + } + + #banner .content .image { + border-radius: 100%; + display: inline-block; + height: 18em; + margin-left: 3em; + vertical-align: middle; + width: 18em; + } + + #banner .content .image img { + border-radius: 100%; + display: block; + width: 100%; + } + + body.is-touch #banner { + background-attachment: scroll; + } + +/* Footer */ + + #footer { + background: #272833; + padding: 6em 0; + text-align: center; + } + + #footer .icons .icon.alt { + text-decoration: none; + } + + #footer .icons .icon.alt:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + #footer .icons .icon.alt:before { + color: #272833 !important; + text-shadow: 1px 0 0 rgba(255, 255, 255, 0.5), -1px 0 0 rgba(255, 255, 255, 0.5), 0 1px 0 rgba(255, 255, 255, 0.5), 0 -1px 0 rgba(255, 255, 255, 0.5); + } + + #footer .copyright { + color: rgba(255, 255, 255, 0.5); + font-size: 0.8em; + line-height: 1em; + margin: 2em 0 0 0; + padding: 0; + text-align: center; + } + + #footer .copyright li { + border-left: solid 1px rgba(255, 255, 255, 0.3); + display: inline-block; + list-style: none; + margin-left: 1.5em; + padding-left: 1.5em; + } + + #footer .copyright li:first-child { + border-left: 0; + margin-left: 0; + padding-left: 0; + } + + #footer .copyright li a { + color: inherit; + } + +/* XLarge */ + + @media screen and (max-width: 1680px) { + + /* Basic */ + + body, input, select, textarea { + font-size: 13pt; + } + + } + +/* Large */ + + @media screen and (max-width: 1280px) { + + /* Basic */ + + body, input, select, textarea { + font-size: 11.5pt; + } + + /* Spotlight */ + + .spotlight.top .content { + padding: 3.825em 0 1.825em 0; + } + + .spotlight.bottom .content { + padding: 3.825em 0 2.95em 0; + } + + .spotlight.left .content, .spotlight.right .content { + padding: 4.5em 2.5em; + width: 25em; + } + + /* Wrapper */ + + .wrapper { + padding: 4.5em 0 2.5em 0; + } + + /* Dropotron */ + + .dropotron.level-0 { + font-size: 1em; + } + + /* Banner */ + + #banner .content { + padding: 4.5em; + } + + /* Footer */ + + #footer { + padding: 4.5em 0; + } + + } + +/* Medium */ + + @media screen and (max-width: 980px) { + + /* Basic */ + + body, input, select, textarea { + font-size: 12pt; + } + + /* Spotlight */ + + .spotlight { + background-attachment: scroll; + height: auto; + } + + .spotlight .image.main { + display: block; + margin: 0; + max-height: 40vh; + overflow: hidden; + } + + .spotlight .content { + background-color: #1c1d26; + border-width: 0 !important; + border-top-width: 0.35em !important; + bottom: auto !important; + left: auto !important; + padding: 4.5em 2.5em 2.5em 2.5em !important; + position: relative; + right: auto !important; + text-align: center; + top: auto !important; + width: 100% !important; + } + + .spotlight .goto-next { + display: none; + } + + /* Wrapper */ + + .wrapper { + padding: 4.5em 2.5em 2.5em 2.5em; + } + + /* Banner */ + + #banner { + background-attachment: scroll; + } + + #banner .goto-next { + height: 7em; + } + + #banner .content { + padding: 9em 0; + text-align: center; + } + + #banner .content header { + display: block; + margin: 0 0 2em 0; + text-align: center; + } + + #banner .content .image { + margin: 0; + } + + /* Footer */ + + #footer { + padding: 4.5em 0; + } + + } + +/* Small */ + + #navPanel, #titleBar { + display: none; + } + + @media screen and (max-width: 736px) { + + /* Basic */ + + html, body { + overflow-x: hidden; + } + + body, input, select, textarea { + font-size: 12pt; + } + + h2 { + font-size: 1.5em; + } + + h3 { + font-size: 1.2em; + } + + h4 { + font-size: 1em; + } + + /* Section/Article */ + + header p br { + display: none; + } + + header h2 + p { + font-size: 1em; + } + + header h3 + p { + font-size: 1em; + } + + header h4 + p, + header h5 + p, + header h6 + p { + font-size: 0.9em; + } + + header.major { + margin: 0 0 2em 0; + } + + /* Goto Next */ + + .goto-next:before { + height: 0.8em; + margin: -0.4em 0 0 -0.6em; + width: 1.2em; + } + + /* Spotlight */ + + .spotlight { + box-shadow: 0 0.125em 0.5em 0 rgba(0, 0, 0, 0.25); + } + + .spotlight .image.main { + max-height: 60vh; + } + + .spotlight .content { + border-top-width: 0.2em !important; + padding: 3.25em 1.5em 1.25em 1.5em !important; + } + + /* Wrapper */ + + .wrapper { + padding: 3.25em 1.5em 1.25em 1.5em; + } + + /* Header */ + + #header { + display: none; + } + + /* Banner */ + + #banner { + box-shadow: 0 0.125em 0.5em 0 rgba(0, 0, 0, 0.25); + min-height: calc(100vh - 44px); + } + + #banner:before { + height: calc(100vh - 44px); + } + + #banner .content { + padding: 4.0625em 1.5em 4.875em 1.5em; + } + + #banner .content header h2 { + font-size: 1.5em; + } + + #banner .content .image { + height: 9em; + width: 9em; + } + + /* Off-Canvas Navigation */ + + #page-wrapper { + -moz-backface-visibility: hidden; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + -moz-transition: -moz-transform 0.5s ease; + -webkit-transition: -webkit-transform 0.5s ease; + -ms-transition: -ms-transform 0.5s ease; + transition: transform 0.5s ease; + padding-bottom: 1px; + padding-top: 44px !important; + } + + #titleBar { + -moz-backface-visibility: hidden; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + -moz-transition: -moz-transform 0.5s ease; + -webkit-transition: -webkit-transform 0.5s ease; + -ms-transition: -ms-transform 0.5s ease; + transition: transform 0.5s ease; + display: block; + height: 44px; + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 10001; + background: #272833; + box-shadow: 0 0.125em 0.125em 0 rgba(0, 0, 0, 0.125); + } + + #titleBar .title { + color: #ffffff; + display: block; + font-weight: 300; + height: 44px; + line-height: 44px; + text-align: center; + } + + #titleBar .title a { + color: inherit; + border: 0; + } + + #titleBar .toggle { + text-decoration: none; + height: 60px; + left: 0; + position: absolute; + top: 0; + width: 90px; + outline: 0; + border: 0; + } + + #titleBar .toggle:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + text-transform: none !important; + } + + #titleBar .toggle:before { + background: #e44c65; + color: rgba(255, 255, 255, 0.5); + content: '\f0c9'; + display: block; + font-size: 18px; + height: 44px; + left: 0; + line-height: 44px; + position: absolute; + text-align: center; + top: 0; + width: 54px; + } + + #navPanel { + -moz-backface-visibility: hidden; + -webkit-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + -moz-transform: translateX(-275px); + -webkit-transform: translateX(-275px); + -ms-transform: translateX(-275px); + transform: translateX(-275px); + -moz-transition: -moz-transform 0.5s ease; + -webkit-transition: -webkit-transform 0.5s ease; + -ms-transition: -ms-transform 0.5s ease; + transition: transform 0.5s ease; + display: block; + height: 100%; + left: 0; + overflow-y: auto; + position: fixed; + top: 0; + width: 275px; + z-index: 10002; + background: #181920; + padding: 0.75em 1.25em; + } + + #navPanel .link { + border: 0; + border-top: solid 1px rgba(255, 255, 255, 0.05); + color: rgba(255, 255, 255, 0.75); + display: block; + height: 3em; + line-height: 3em; + text-decoration: none; + } + + #navPanel .link:hover { + color: inherit !important; + } + + #navPanel .link:first-child { + border-top: 0; + } + + #navPanel .link.depth-0 { + color: #ffffff; + font-weight: 300; + } + + #navPanel .link .indent-1 { + display: inline-block; + width: 1.25em; + } + + #navPanel .link .indent-2 { + display: inline-block; + width: 2.5em; + } + + #navPanel .link .indent-3 { + display: inline-block; + width: 3.75em; + } + + #navPanel .link .indent-4 { + display: inline-block; + width: 5em; + } + + #navPanel .link .indent-5 { + display: inline-block; + width: 6.25em; + } + + body.navPanel-visible #page-wrapper { + -moz-transform: translateX(275px); + -webkit-transform: translateX(275px); + -ms-transform: translateX(275px); + transform: translateX(275px); + } + + body.navPanel-visible #titleBar { + -moz-transform: translateX(275px); + -webkit-transform: translateX(275px); + -ms-transform: translateX(275px); + transform: translateX(275px); + } + + body.navPanel-visible #navPanel { + -moz-transform: translateX(0); + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + /* Footer */ + + #footer { + padding: 3.25em 1.5em; + } + + } + +/* XSmall */ + + @media screen and (max-width: 480px) { + + /* Basic */ + + html, body { + min-width: 320px; + } + + body, input, select, textarea { + font-size: 12pt; + } + + /* List */ + + ul.actions { + margin: 0 0 2em 0; + } + + ul.actions li { + display: block; + padding: 1em 0 0 0; + text-align: center; + width: 100%; + } + + ul.actions li:first-child { + padding-top: 0; + } + + ul.actions li > * { + margin: 0 !important; + width: 100%; + } + + ul.actions.small li { + padding: 0.5em 0 0 0; + } + + ul.actions.small li:first-child { + padding-top: 0; + } + + /* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + .button { + padding: 0; + } + + /* Spotlight */ + + .spotlight .image.main { + max-height: 50vh; + } + + .spotlight .content { + padding: 3em 1.25em 1em 1.25em !important; + } + + /* Wrapper */ + + .wrapper { + padding: 3em 1.25em 1em 1.25em; + } + + /* Banner */ + + #banner .content { + padding: 3em 1.5625em 5.25em 1.5625em; + } + + /* Footer */ + + #footer { + padding: 3em 1.25em; + } + + #footer .copyright { + line-height: inherit; + } + + #footer .copyright li { + border-left: 0; + display: block; + margin: 0; + padding: 0; + } + + } \ No newline at end of file diff --git a/assets/fonts/FontAwesome.otf b/assets/fonts/FontAwesome.otf new file mode 100644 index 0000000..59853bc Binary files /dev/null and b/assets/fonts/FontAwesome.otf differ diff --git a/assets/fonts/fontawesome-webfont.eot b/assets/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..96f92f9 Binary files /dev/null and b/assets/fonts/fontawesome-webfont.eot differ diff --git a/vendors/font-awesome/fonts/fontawesome-webfont.svg b/assets/fonts/fontawesome-webfont.svg similarity index 89% rename from vendors/font-awesome/fonts/fontawesome-webfont.svg rename to assets/fonts/fontawesome-webfont.svg index 6fd19ab..5a5f0ec 100644 --- a/vendors/font-awesome/fonts/fontawesome-webfont.svg +++ b/assets/fonts/fontawesome-webfont.svg @@ -1,6 +1,6 @@ - + @@ -169,7 +169,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -219,8 +219,8 @@ - - + + @@ -362,7 +362,7 @@ - + @@ -410,7 +410,7 @@ - + @@ -454,7 +454,7 @@ - + @@ -484,7 +484,7 @@ - + @@ -555,7 +555,7 @@ - + @@ -600,11 +600,11 @@ - - + + - + @@ -621,20 +621,65 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendors/font-awesome/fonts/fontawesome-webfont.ttf b/assets/fonts/fontawesome-webfont.ttf similarity index 78% rename from vendors/font-awesome/fonts/fontawesome-webfont.ttf rename to assets/fonts/fontawesome-webfont.ttf index d7994e1..86784df 100644 Binary files a/vendors/font-awesome/fonts/fontawesome-webfont.ttf and b/assets/fonts/fontawesome-webfont.ttf differ diff --git a/assets/fonts/fontawesome-webfont.woff b/assets/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..c7faa19 Binary files /dev/null and b/assets/fonts/fontawesome-webfont.woff differ diff --git a/assets/fonts/fontawesome-webfont.woff2 b/assets/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..cab8571 Binary files /dev/null and b/assets/fonts/fontawesome-webfont.woff2 differ diff --git a/assets/js/ie/PIE.htc b/assets/js/ie/PIE.htc new file mode 100644 index 0000000..ca3b547 --- /dev/null +++ b/assets/js/ie/PIE.htc @@ -0,0 +1,96 @@ + + + + + + + + + STM32L051 PVD的调试 + + + + + + + + + +
+ + + + + +
+
+
+

STM32L051 PVD的调试

+
+ + +
+

我的PVD的驱动以及例程位于STM32L0xx_Drivers这个库当中,在使用前最好先阅读readme.md文件

+ +

PVD 是一种检测MCU供电情况的技术。当供电电压高于或者低于一定阈值的时候,可以在寄存器上体现出来,或者直接产生硬件中断。 +
+
在实际使用MCU时,特别是电池供电的方案中,往往会遇到供电不够导致MCU或者外设工作不正常的情况。PVD在这个时候就可以派上用场了。 +
+
PVD的使用按照数据手册上的说明,就是首先设置PVD阈值(PVD thresholds),当MCU的VDD引脚的电压高于阈值时,则PVD output=1,当VDD电压低于阈值时,PVD output=0,如下图所示: +

+
其中PVD output的结果可以再在存器中查看到 +
+
+
关于PVD的阈值的设定共有两种方式: +
+
    +
  • 固定阈值(1.9V 2.1V 2.3V 2.5V 2.7V 2.9V 3.1V)
  • +
  • 与引脚比较(PB7)
  • +
+
在实际使用的过程中,PVD可以用查询挥着中断的方式来工作。 +

+ +

+ 在测试的例程中,我配置PVD工作方式为中断上升下降沿触发,当VDD高于预设PVD阈值或者低于阈值而产生边沿触发时,都会形成一次PVD中断,然后读取PWR_CSR的PVDO标志位检查是低电压提醒还是高电压提醒,以此来达到监控MCU供电情况的目的。 +

注意:当使用PVD功能检测低电压时,VDD电压刚刚小于阈值时并不会直接产生PVD中断,只有当VDD电压小于(阈值-50MV)时,才会产生中断。 +

+ +

如果有什么疑问或者错误欢迎大家指正,email:454626653@qq.com

+
+ +
+
+ + + + +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/blog_stack.html b/blog/blog_stack.html new file mode 100644 index 0000000..80282c1 --- /dev/null +++ b/blog/blog_stack.html @@ -0,0 +1,152 @@ + + + + + stack frame + + + + + + + + + +
+ + + + + +
+
+
+

以帧为存储单位的循环stack存储结构的设计

+
+ + +
+

我的stack frame的src以及例程位于Data_Structure这个库当中,在使用前最好先阅读readme.md文件

+ +

为了配合项目的需要,我构造了一个循环的stack,stack是一种后进先出的存储结构,在实际中使用这种存储结构,可以使保证最新的数据拥有最高优先级。 +
在物联网的系统中,往往需要获取传感器的最新的状态,所以传输传感器的最新状态往往比传送之前的状态更有意义。 +
其中我对stack以及frame的构造的代码如下: +

typedef struct Frame
+{
+	uint8_t frame_len;//帧的字节数
+	uint8_t frame_data[MAX_TRANSMISSION_UINT];//帧的存储空间
+}Frame;
+
+typedef struct STACK
+{
+	int8_t frame_lastNum;//最近的帧的序号
+	uint8_t frame_count;//stack中的帧的个数
+	Frame frame_info[MAX_STACK_FRAME_NUM];//最多允许存储MAX_STACK_FRAME_NUM帧,MAX_STACK_FRAME_NUM当前为10
+}STACK;
+ +

首先构造了一个stack,stack包含两个内容:

+
    +
  1. stack的统计信息:stack中frame的个数,最新的帧的ID;
  2. +
  3. 数据存储区,所有帧的数据存放区域;
  4. +
+

然后,frame的构造也包含了两个部分:

+
    +
  1. 此frame中的数据存储区中的有效数据的字节数;
  2. +
  3. 数据存储区,此帧的数据存放区域;
  4. +
+

+ +

循环意味着此stack并非标准的stack,没有栈顶限制,当栈满了,仍然有数据进入时,数据从帧底开始存储,相当于栈底的原来的数据会被覆盖掉,也就没了栈越界的危险。

+ +

+

此数据结构的优点就是:

+
    +
  1. 永远是最新的数据被最优先处理;
  2. +
  3. 没有栈越界的危险,在嵌入式或者其他队稳定性要求较高的环境中,可靠,不会因为数据过多出现指针异常导致崩溃的情况出现;
  4. +
  5. 在海量数据涌来但无法全部进行处理的时候,选择最新的数据保存,进行处理,保证了数据的实时性;
  6. +
+ +

同样的,此数据结构也有明显的缺点:

+
    +
  1. 如果处理速度慢,较早的未处理的数据被覆盖就再也无法找回了;
  2. +
  3. 由于stack中frame的存储空间是静态分配的,而不是在运行时动态分配的,若frame的负载情况远远小于MTU,则会出现大量空间被浪费的情况;
  4. +
+

+


在最后,此例程中还写了一个拼包的机制,代码如下 +

//将stack中的数据进行拼包,在不造成断包的情况下最大限度地拼包
+uint8_t SpliceFrame(uint8_t* dest)
+{
+    uint8_t Splice_len = 0;
+
+    Splice_len = 0;
+
+    while(1)
+    {
+        if((Splice_len +Stack_GetFrameLastNum()) <= MAX_TRANSMISSION_UINT)//确保当前数据加下一帧数据不会超过最大单帧负载量
+        {
+            Splice_len +=Stack_PopData(dest+Splice_len);//
+            if(Stack_GetFrameCount() == 0)//当前融合的帧的数量小于stack中保存的帧的数量
+               break;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return Splice_len;
+}
+
从程序中可见,此拼包的机制就是在MTU的限制内,在不造成断包的情况下,最大限度的地将stack中已经已有的数据包进行拼包,打包成一个较长的数据包进行处理。此拼包机制在无线网络中可以大大提高无线信道的传输效率。具体的测试情况可以查看源代码。 +

+

如果有什么疑问或者错误欢迎大家指正,email:454626653@qq.com

+ +
+ +
+
+ + + + +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/blogindex.html b/blog/blogindex.html new file mode 100644 index 0000000..0f590f4 --- /dev/null +++ b/blog/blogindex.html @@ -0,0 +1,92 @@ + + + + + Blog + + + + + + + + +
+ + + + + +
+
+
+

我的blog

+

和大家分享平时调试时的心得和经验,也欢迎大家参与谈论 +
邮箱:454626653@qq.com +

+
+ + +
+

blog list

+

我的所有例程中,带硬件平台的程序使用的是KEIL开发环境,不带硬件的程序使用的是code blocks

+ +
+ +
+
+ + + + +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/uploads/PVD_images/PVD_1.jpg b/blog/pvd_image/PVD_1.jpg similarity index 100% rename from uploads/PVD_images/PVD_1.jpg rename to blog/pvd_image/PVD_1.jpg diff --git a/uploads/PVD_images/PVD_3.jpg b/blog/pvd_image/PVD_3.jpg similarity index 100% rename from uploads/PVD_images/PVD_3.jpg rename to blog/pvd_image/PVD_3.jpg diff --git a/uploads/PVD_images/PVD_4.jpg b/blog/pvd_image/PVD_4.jpg similarity index 100% rename from uploads/PVD_images/PVD_4.jpg rename to blog/pvd_image/PVD_4.jpg diff --git "a/categories/C\350\257\255\350\250\200/index.html" "b/categories/C\350\257\255\350\250\200/index.html" deleted file mode 100644 index b6363cb..0000000 --- "a/categories/C\350\257\255\350\250\200/index.html" +++ /dev/null @@ -1,823 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: C语言 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/categories/LoRaWAN/index.html b/categories/LoRaWAN/index.html deleted file mode 100644 index 20da732..0000000 --- a/categories/LoRaWAN/index.html +++ /dev/null @@ -1,1051 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: LoRaWAN | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/categories/LoRaWAN/page/2/index.html b/categories/LoRaWAN/page/2/index.html deleted file mode 100644 index 8299293..0000000 --- a/categories/LoRaWAN/page/2/index.html +++ /dev/null @@ -1,939 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: LoRaWAN | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/categories/MCU/index.html b/categories/MCU/index.html deleted file mode 100644 index b7b4d2b..0000000 --- a/categories/MCU/index.html +++ /dev/null @@ -1,795 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: MCU | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/categories/MCU\345\244\226\350\256\276/index.html" "b/categories/MCU\345\244\226\350\256\276/index.html" deleted file mode 100644 index c27a650..0000000 --- "a/categories/MCU\345\244\226\350\256\276/index.html" +++ /dev/null @@ -1,823 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: MCU外设 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/categories/STM32/index.html b/categories/STM32/index.html deleted file mode 100644 index 881721a..0000000 --- a/categories/STM32/index.html +++ /dev/null @@ -1,851 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: STM32 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/categories/index.html b/categories/index.html deleted file mode 100644 index 4a9a6c6..0000000 --- a/categories/index.html +++ /dev/null @@ -1,782 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" "b/categories/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" deleted file mode 100644 index 7deabde..0000000 --- "a/categories/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" +++ /dev/null @@ -1,795 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 分类: 数据结构 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/css/main.css b/css/main.css deleted file mode 100644 index 63b8126..0000000 --- a/css/main.css +++ /dev/null @@ -1,2522 +0,0 @@ -/* normalize.css v3.0.2 | MIT License | git.io/normalize */ -html { - font-family: sans-serif; /* 1 */ - -ms-text-size-adjust: 100%; /* 2 */ - -webkit-text-size-adjust: 100%; /* 2 */ -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; /* 1 */ - vertical-align: baseline; /* 2 */ -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden], -template { - display: none; -} -a { - background-color: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - font-size: 2em; - margin: 0.67em 0; -} -mark { - background: #ff0; - color: #000; -} -small { - font-size: 80%; -} -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - color: inherit; /* 1 */ - font: inherit; /* 2 */ - margin: 0; /* 3 */ -} -button { - overflow: visible; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ -} -button[disabled], -html input[disabled] { - cursor: default; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -td, -th { - padding: 0; -} -::selection { - background: #262a30; - color: #fff; -} -body { - position: relative; - font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; - font-size: 14px; - line-height: 2; - color: #555; - background: #fff; -} -@media (max-width: 767px) { - body { - padding-right: 0 !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - body { - padding-right: 0 !important; - } -} -@media (min-width: 1600px) { - body { - font-size: 16px; - } -} -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; - padding: 0; - font-weight: bold; - line-height: 1.5; - font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; -} -h2, -h3, -h4, -h5, -h6 { - margin: 20px 0 15px; -} -h1 { - font-size: 22px; -} -@media (max-width: 767px) { - h1 { - font-size: 18px; - } -} -h2 { - font-size: 20px; -} -@media (max-width: 767px) { - h2 { - font-size: 16px; - } -} -h3 { - font-size: 18px; -} -@media (max-width: 767px) { - h3 { - font-size: 14px; - } -} -h4 { - font-size: 16px; -} -@media (max-width: 767px) { - h4 { - font-size: 12px; - } -} -h5 { - font-size: 14px; -} -@media (max-width: 767px) { - h5 { - font-size: 10px; - } -} -h6 { - font-size: 12px; -} -@media (max-width: 767px) { - h6 { - font-size: 8px; - } -} -p { - margin: 0 0 25px 0; -} -a { - color: #555; - text-decoration: none; - border-bottom: 1px solid #999; - word-wrap: break-word; -} -a:hover { - color: #222; - border-bottom-color: #222; -} -ul { - list-style: none; -} -blockquote { - margin: 0; - padding: 0; -} -img { - display: block; - margin: auto; - max-width: 100%; - height: auto; -} -hr { - margin: 40px 0; - height: 3px; - border: none; - background-color: #ddd; - background-image: repeating-linear-gradient(-45deg, #fff, #fff 4px, transparent 4px, transparent 8px); -} -blockquote { - padding: 0 15px; - color: #666; - border-left: 4px solid #ddd; -} -blockquote cite::before { - content: "-"; - padding: 0 5px; -} -dt { - font-weight: 700; -} -dd { - margin: 0; - padding: 0; -} -.text-left { - text-align: left; -} -.text-center { - text-align: center; -} -.text-right { - text-align: right; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.center-block { - display: block; - margin-left: auto; - margin-right: auto; -} -.clearfix:before, -.clearfix:after { - content: " "; - display: table; -} -.clearfix:after { - clear: both; -} -.pullquote { - width: 45%; -} -.pullquote.left { - float: left; - margin-left: 5px; - margin-right: 10px; -} -.pullquote.right { - float: right; - margin-left: 10px; - margin-right: 5px; -} -.affix.affix.affix { - position: fixed; -} -.translation { - margin-top: -20px; - font-size: 14px; - color: #999; -} -.scrollbar-measure { - width: 100px; - height: 100px; - overflow: scroll; - position: absolute; - top: -9999px; -} -.use-motion .motion-element { - opacity: 0; -} -#local-search-input { - padding: 3px; - border: none; - text-indent: 14px; - border-radius: 0; - width: 140px; - outline: none; - border-bottom: 1px solid #999; - background: inherit; - opacity: 0.5; -} -#local-search-input:focus { - opacity: 1; -} -.search-icon { - position: absolute; - top: 9px; -} -table { - margin: 20px 0; - width: 100%; - border-collapse: collapse; - border-spacing: 0; - border: 1px solid #ddd; - font-size: 14px; - table-layout: fixed; - word-wrap: break-all; -} -table>tbody>tr:nth-of-type(odd) { - background-color: #f9f9f9; -} -table>tbody>tr:hover { - background-color: #f5f5f5; -} -caption, -th, -td { - padding: 8px; - text-align: left; - vertical-align: middle; - font-weight: normal; -} -th, -td { - border-bottom: 3px solid #ddd; - border-right: 1px solid #eee; -} -th { - padding-bottom: 10px; - font-weight: 700; -} -td { - border-bottom-width: 1px; -} -html, -body { - height: 100%; -} -.container { - position: relative; - min-height: 100%; -} -.header-inner { - margin: 0 auto; - padding: 100px 0 70px; - width: 700px; -} -@media (min-width: 1600px) { - .container .header-inner { - width: 900px; - } -} -.main { - padding-bottom: 150px; -} -.main-inner { - margin: 0 auto; - width: 700px; -} -@media (min-width: 1600px) { - .container .main-inner { - width: 900px; - } -} -.footer { - position: absolute; - left: 0; - bottom: 0; - width: 100%; - min-height: 50px; -} -.footer-inner { - box-sizing: border-box; - margin: 20px auto; - width: 700px; -} -@media (min-width: 1600px) { - .container .footer-inner { - width: 900px; - } -} -pre, -.highlight { - overflow: auto; - margin: 20px 0; - padding: 15px; - font-size: 13px; - color: #ccc; - background: #2d2d2d; - line-height: 1.6; -} -pre, -code { - font-family: consolas, Menlo, "PingFang SC", "Microsoft YaHei", monospace; -} -code { - padding: 2px 4px; - word-break: break-all; - color: #555; - background: #eee; - border-radius: 4px; - font-size: 13px; -} -pre code { - padding: 0; - color: #ccc; - background: none; - text-shadow: none; -} -.highlight pre { - border: none; - margin: 0; - padding: 1px; -} -.highlight table { - margin: 0; - width: auto; - border: none; -} -.highlight td { - border: none; - padding: 0; -} -.highlight figcaption { - font-size: 1em; - color: #ccc; - line-height: 1em; - margin-bottom: 1em; -} -.highlight figcaption:before, -.highlight figcaption:after { - content: " "; - display: table; -} -.highlight figcaption:after { - clear: both; -} -.highlight figcaption a { - float: right; - color: #ccc; -} -.highlight figcaption a:hover { - border-bottom-color: #ccc; -} -.highlight .gutter pre { - color: #666; - text-align: right; - padding-right: 20px; -} -.highlight .line { - height: 20px; -} -.gist table { - width: auto; -} -.gist table td { - border: none; -} -pre .comment { - color: #999; -} -pre .variable, -pre .attribute, -pre .tag, -pre .regexp, -pre .ruby .constant, -pre .xml .tag .title, -pre .xml .pi, -pre .xml .doctype, -pre .html .doctype, -pre .css .id, -pre .css .class, -pre .css .pseudo { - color: #f2777a; -} -pre .number, -pre .preprocessor, -pre .built_in, -pre .literal, -pre .params, -pre .constant, -pre .command { - color: #f99157; -} -pre .ruby .class .title, -pre .css .rules .attribute, -pre .string, -pre .value, -pre .inheritance, -pre .header, -pre .ruby .symbol, -pre .xml .cdata, -pre .special, -pre .number, -pre .formula { - color: #9c9; -} -pre .title, -pre .css .hexcolor { - color: #6cc; -} -pre .function, -pre .python .decorator, -pre .python .title, -pre .ruby .function .title, -pre .ruby .title .keyword, -pre .perl .sub, -pre .javascript .title, -pre .coffeescript .title { - color: #69c; -} -pre .keyword, -pre .javascript .function { - color: #c9c; -} -.full-image.full-image.full-image { - border: none; - max-width: 100%; - width: auto; - margin: 20px auto; -} -@media (min-width: 992px) { - .full-image.full-image.full-image { - max-width: none; - width: 126%; - margin: 0 -13%; - } -} -.blockquote-center, -.page-home .post-type-quote blockquote, -.page-post-detail .post-type-quote blockquote { - position: relative; - margin: 40px 0; - padding: 0; - border-left: none; - text-align: center; -} -.blockquote-center::before, -.page-home .post-type-quote blockquote::before, -.page-post-detail .post-type-quote blockquote::before, -.blockquote-center::after, -.page-home .post-type-quote blockquote::after, -.page-post-detail .post-type-quote blockquote::after { - position: absolute; - content: ' '; - display: block; - width: 100%; - height: 24px; - opacity: 0.2; - background-repeat: no-repeat; - background-position: 0 -6px; - background-size: 22px 22px; -} -.blockquote-center::before, -.page-home .post-type-quote blockquote::before, -.page-post-detail .post-type-quote blockquote::before { - top: -20px; - background-image: url("../images/quote-l.svg"); - border-top: 1px solid #ccc; -} -.blockquote-center::after, -.page-home .post-type-quote blockquote::after, -.page-post-detail .post-type-quote blockquote::after { - bottom: -20px; - background-image: url("../images/quote-r.svg"); - border-bottom: 1px solid #ccc; - background-position: 100% 8px; -} -.blockquote-center p, -.page-home .post-type-quote blockquote p, -.page-post-detail .post-type-quote blockquote p, -.blockquote-center div, -.page-home .post-type-quote blockquote div, -.page-post-detail .post-type-quote blockquote div { - text-align: center; -} -.post .post-body .group-picture img { - box-sizing: border-box; - padding: 0 3px; - border: none; -} -.post .group-picture-row { - overflow: hidden; - margin-top: 6px; -} -.post .group-picture-row:first-child { - margin-top: 0; -} -.post .group-picture-column { - float: left; -} -.page-post-detail .post-body .group-picture-column { - float: none; - margin-top: 10px; - width: auto !important; -} -.page-post-detail .post-body .group-picture-column img { - margin: 0 auto; -} -.page-archive .group-picture-container { - overflow: hidden; -} -.page-archive .group-picture-row { - float: left; -} -.page-archive .group-picture-row:first-child { - margin-top: 6px; -} -.page-archive .group-picture-column { - max-width: 150px; - max-height: 150px; -} -.btn { - display: inline-block; - padding: 0 20px; - font-size: 14px; - color: #fff; - background: #222; - border: 2px solid #555; - text-decoration: none; - border-radius: 0; - transition-property: background-color; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; -} -.btn:hover, -.post-more-link .btn:hover { - border-color: #222; - color: #fff; - background: #222; -} -.btn-bar { - display: block; - width: 22px; - height: 2px; - background: #555; - border-radius: 1px; -} -.btn-bar+.btn-bar { - margin-top: 4px; -} -.pagination { - margin: 120px 0 40px; - text-align: center; - border-top: 1px solid #eee; -} -.page-number-basic, -.pagination .prev, -.pagination .next, -.pagination .page-number, -.pagination .space { - display: inline-block; - position: relative; - top: -1px; - margin: 0 10px; - padding: 0 10px; - line-height: 30px; -} -@media (max-width: 767px) { - .page-number-basic, - .pagination .prev, - .pagination .next, - .pagination .page-number, - .pagination .space { - margin: 0 5px; - } -} -.pagination .prev, -.pagination .next, -.pagination .page-number { - border-bottom: 0; - border-top: 1px solid #eee; - transition-property: border-color; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; -} -.pagination .prev:hover, -.pagination .next:hover, -.pagination .page-number:hover { - border-top-color: #222; -} -.pagination .space { - padding: 0; - margin: 0; -} -.pagination .prev { - margin-left: 0; -} -.pagination .next { - margin-right: 0; -} -.pagination .page-number.current { - color: #fff; - background: #ccc; - border-top-color: #ccc; -} -@media (max-width: 767px) { - .pagination { - border-top: none; - } - .pagination .prev, - .pagination .next, - .pagination .page-number { - margin-bottom: 10px; - border-top: 0; - border-bottom: 1px solid #eee; - } - .pagination .prev:hover, - .pagination .next:hover, - .pagination .page-number:hover { - border-bottom-color: #222; - } -} -.comments { - margin: 60px 20px 0; -} -.tag-cloud { - text-align: center; -} -.tag-cloud a { - display: inline-block; - margin: 10px; -} -.back-to-top { - box-sizing: border-box; - position: fixed; - bottom: -100px; - right: 50px; - z-index: 1050; - padding: 0 6px; - width: 25px; - background: #222; - font-size: 12px; - opacity: 0.6; - color: #fff; - cursor: pointer; - text-align: center; - -webkit-transform: translateZ(0); - transition-property: bottom; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; -} -@media (max-width: 767px) { - .back-to-top { - display: none; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .back-to-top { - display: none; - } -} -.back-to-top.back-to-top-on { - bottom: 40px; -} -.header { - background: #fff; -} -.header-inner { - position: relative; -} -.headband { - height: 3px; - background: #222; -} -.site-meta { - margin: 0; - text-align: center; -} -@media (max-width: 767px) { - .site-meta { - text-align: center; - } -} -.brand { - position: relative; - display: inline-block; - padding: 0 40px; - color: #fff; - background: #222; - border-bottom: none; -} -.brand:hover { - color: #fff; -} -.logo { - display: inline-block; - margin-right: 5px; - line-height: 36px; - vertical-align: top; -} -.site-title { - display: inline-block; - vertical-align: top; - line-height: 36px; - font-size: 20px; - font-weight: normal; - font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; -} -.site-subtitle { - margin-top: 10px; - font-size: 13px; - color: #ddd; -} -.use-motion .brand { - opacity: 0; -} -.use-motion .logo, -.use-motion .site-title, -.use-motion .site-subtitle { - opacity: 0; - position: relative; - top: -10px; -} -.site-nav-toggle { - display: none; - position: absolute; - top: 10px; - left: 10px; -} -@media (max-width: 767px) { - .site-nav-toggle { - display: block; - } -} -.site-nav-toggle button { - margin-top: 2px; - padding: 9px 10px; - background: transparent; - border: none; -} -@media (max-width: 767px) { - .site-nav { - display: none; - margin: 0 -10px; - padding: 0 10px; - clear: both; - border-top: 1px solid #ddd; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .site-nav { - display: block !important; - } -} -@media (min-width: 992px) { - .site-nav { - display: block !important; - } -} -.menu { - margin-top: 20px; - padding-left: 0; - text-align: center; -} -.menu .menu-item { - display: inline-block; - margin: 0 10px; -} -@media screen and (max-width: 767px) { - .menu .menu-item { - margin-top: 10px; - } -} -.menu .menu-item a { - display: block; - font-size: 13px; - text-transform: capitalize; - line-height: inherit; - border-bottom: 1px solid transparent; - transition-property: border-color; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; -} -.menu .menu-item a:hover, -.menu-item-active a { - border-bottom-color: #222; -} -.menu .menu-item .fa { - margin-right: 5px; -} -.use-motion .menu-item { - opacity: 0; -} -.post-body { - font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; -} -@media (max-width: 767px) { - .post-body { - word-break: break-word; - } -} -.post-body .fancybox img { - display: block !important; - margin: 0 auto; - cursor: pointer; - cursor: zoom-in; - cursor: -webkit-zoom-in; -} -.post-body .image-caption, -.post-body .figure .caption { - margin: 10px auto 15px; - text-align: center; - font-size: 14px; - color: #999; - font-weight: bold; - line-height: 1; -} -.post-sticky-flag { - display: inline-block; - font-size: 16px; - -ms-transform: rotate(30deg); - -webkit-transform: rotate(30deg); - -moz-transform: rotate(30deg); - -ms-transform: rotate(30deg); - -o-transform: rotate(30deg); - transform: rotate(30deg); -} -.posts-expand { - padding-top: 40px; -} -@media (max-width: 767px) { - .posts-expand { - margin: 0 20px; - } - .post-body pre, - .post-body .highlight { - padding: 10px; - } - .post-body pre .gutter pre, - .post-body .highlight .gutter pre { - padding-right: 10px; - } -} -@media (min-width: 992px) { - .posts-expand .post-body { - text-align: justify; - } -} -.posts-expand .post-body h2, -.posts-expand .post-body h3, -.posts-expand .post-body h4, -.posts-expand .post-body h5, -.posts-expand .post-body h6 { - padding-top: 10px; -} -.posts-expand .post-body h2 .header-anchor, -.posts-expand .post-body h3 .header-anchor, -.posts-expand .post-body h4 .header-anchor, -.posts-expand .post-body h5 .header-anchor, -.posts-expand .post-body h6 .header-anchor { - float: right; - margin-left: 10px; - color: #ccc; - border-bottom-style: none; - visibility: hidden; -} -.posts-expand .post-body h2 .header-anchor:hover, -.posts-expand .post-body h3 .header-anchor:hover, -.posts-expand .post-body h4 .header-anchor:hover, -.posts-expand .post-body h5 .header-anchor:hover, -.posts-expand .post-body h6 .header-anchor:hover { - color: inherit; -} -.posts-expand .post-body h2:hover .header-anchor, -.posts-expand .post-body h3:hover .header-anchor, -.posts-expand .post-body h4:hover .header-anchor, -.posts-expand .post-body h5:hover .header-anchor, -.posts-expand .post-body h6:hover .header-anchor { - visibility: visible; -} -.posts-expand .post-body ul li { - list-style: circle; -} -.posts-expand .post-body img { - box-sizing: border-box; - margin: auto; - padding: 3px; - border: 1px solid #ddd; -} -.posts-expand .fancybox img { - margin: 0 auto; -} -@media (max-width: 767px) { - .posts-collapse { - margin: 0 20px; - } - .posts-collapse .post-title, - .posts-collapse .post-meta { - display: block; - width: auto; - text-align: left; - } -} -.posts-collapse { - position: relative; - z-index: 1010; - margin-left: 55px; -} -.posts-collapse::after { - content: " "; - position: absolute; - top: 20px; - left: 0; - margin-left: -2px; - width: 4px; - height: 100%; - background: #f5f5f5; - z-index: -1; -} -@media (max-width: 767px) { - .posts-collapse { - margin: 0 20px; - } -} -.posts-collapse .collection-title { - position: relative; - margin: 60px 0; -} -.posts-collapse .collection-title h2 { - margin-left: 20px; -} -.posts-collapse .collection-title small { - color: #bbb; -} -.posts-collapse .collection-title::before { - content: " "; - position: absolute; - left: 0; - top: 50%; - margin-left: -4px; - margin-top: -4px; - width: 8px; - height: 8px; - background: #bbb; - border-radius: 50%; -} -.posts-collapse .post { - margin: 30px 0; -} -.posts-collapse .post-header { - position: relative; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; - transition-property: border; - border-bottom: 1px dashed #ccc; -} -.posts-collapse .post-header::before { - content: " "; - position: absolute; - left: 0; - top: 12px; - width: 6px; - height: 6px; - margin-left: -4px; - background: #bbb; - border-radius: 50%; - border: 1px solid #fff; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; - transition-property: background; -} -.posts-collapse .post-header:hover { - border-bottom-color: #666; -} -.posts-collapse .post-header:hover::before { - background: #222; -} -.posts-collapse .post-meta { - position: absolute; - font-size: 12px; - left: 20px; - top: 5px; -} -.posts-collapse .post-comments-count { - display: none; -} -.posts-collapse .post-title { - margin-left: 60px; - font-size: 16px; - font-weight: normal; - line-height: inherit; -} -.posts-collapse .post-title::after { - margin-left: 3px; - opacity: 0.6; -} -.posts-collapse .post-title a { - color: #666; - border-bottom: none; -} -.page-home .post-type-quote .post-header, -.page-post-detail .post-type-quote .post-header, -.page-home .post-type-quote .post-tags, -.page-post-detail .post-type-quote .post-tags { - display: none; -} -.posts-expand .post-title { - font-size: 26px; - text-align: center; - word-break: break-word; - font-weight: 300; -} -@media (max-width: 767px) { - .posts-expand .post-title { - font-size: 22px; - } -} -.posts-expand .post-title-link { - display: inline-block; - position: relative; - color: #555; - border-bottom: none; - line-height: 1.2; - vertical-align: top; -} -.posts-expand .post-title-link::before { - content: ""; - position: absolute; - width: 100%; - height: 2px; - bottom: 0; - left: 0; - background-color: #000; - visibility: hidden; - -webkit-transform: scaleX(0); - -moz-transform: scaleX(0); - -ms-transform: scaleX(0); - -o-transform: scaleX(0); - transform: scaleX(0); - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; -} -.posts-expand .post-title-link:hover::before { - visibility: visible; - -webkit-transform: scaleX(1); - -moz-transform: scaleX(1); - -ms-transform: scaleX(1); - -o-transform: scaleX(1); - transform: scaleX(1); -} -.posts-expand .post-title-link .fa { - font-size: 16px; -} -.posts-expand .post-meta { - margin: 3px 0 60px 0; - color: #999; - font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; - font-size: 12px; - text-align: center; -} -.posts-expand .post-meta .post-category-list { - display: inline-block; - margin: 0; - padding: 3px; -} -.posts-expand .post-meta .post-category-list-link { - color: #999; -} -.post-meta-item-icon { - display: none; - margin-right: 3px; -} -@media (min-width: 768px) and (max-width: 991px) { - .post-meta-item-icon { - display: inline-block; - } -} -@media (max-width: 767px) { - .post-meta-item-icon { - display: inline-block; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .post-meta-item-text { - display: none; - } -} -@media (max-width: 767px) { - .post-meta-item-text { - display: none; - } -} -@media (max-width: 767px) { - .posts-expand .post-comments-count { - display: none; - } -} -.post-more-link { - margin-top: 50px; -} -.post-more-link .btn { - color: #555; - font-size: 14px; - background: #fff; - border-radius: 2px; - line-height: 2; -} -.posts-expand .post-tags { - margin-top: 40px; - text-align: center; -} -.posts-expand .post-tags a { - display: inline-block; - margin-right: 10px; - font-size: 13px; -} -.post-nav { - overflow: hidden; - margin-top: 60px; - padding: 10px; - white-space: nowrap; - border-top: 1px solid #eee; -} -.post-nav-item { - display: inline-block; - width: 50%; - white-space: normal; -} -.post-nav-item a { - position: relative; - display: inline-block; - line-height: 25px; - font-size: 14px; - color: #555; - border-bottom: none; -} -.post-nav-item a:hover { - color: #222; - border-bottom: none; -} -.post-nav-item a:active { - top: 2px; -} -.post-nav-item a i { - font-size: 12px; -} -.post-nav-prev { - text-align: right; -} -.posts-expand .post-eof { - display: block; - margin: 80px auto 60px; - width: 8%; - height: 1px; - background: #ccc; - text-align: center; -} -.post:last-child .post-eof.post-eof.post-eof { - display: none; -} -.post-gallery { - display: table; - table-layout: fixed; - width: 100%; - border-collapse: separate; -} -.post-gallery-row { - display: table-row; -} -.post-gallery .post-gallery-img { - display: table-cell; - text-align: center; - vertical-align: middle; - border: none; -} -.post-gallery .post-gallery-img img { - max-width: 100%; - max-height: 100%; - border: none; -} -.fancybox-close, -.fancybox-close:hover { - border: none; -} -.sidebar { - position: fixed; - right: 0; - top: 0; - bottom: 0; - width: 0; - z-index: 1040; - box-shadow: inset 0 2px 6px #000; - background: #222; - -webkit-transform: translateZ(0); -} -.sidebar a { - color: #999; - border-bottom-color: #555; -} -.sidebar a:hover { - color: #eee; -} -@media (min-width: 768px) and (max-width: 991px) { - .sidebar { - display: none !important; - } -} -@media (max-width: 767px) { - .sidebar { - display: none !important; - } -} -.sidebar-inner { - position: relative; - padding: 20px 10px; - color: #999; - text-align: center; -} -.sidebar-toggle { - position: fixed; - right: 50px; - bottom: 45px; - width: 15px; - height: 15px; - padding: 5px; - background: #222; - line-height: 0; - z-index: 1050; - cursor: pointer; - -webkit-transform: translateZ(0); -} -@media (min-width: 768px) and (max-width: 991px) { - .sidebar-toggle { - display: none; - } -} -@media (max-width: 767px) { - .sidebar-toggle { - display: none; - } -} -.sidebar-toggle-line { - position: relative; - display: inline-block; - vertical-align: top; - height: 2px; - width: 100%; - background: #fff; - margin-top: 3px; -} -.sidebar-toggle-line:first-child { - margin-top: 0; -} -.site-author-image { - display: block; - margin: 0 auto; - padding: 2px; - max-width: 120px; - height: auto; - border: 1px solid #eee; -} -.site-author-name { - margin: 0; - text-align: center; - color: #222; - font-weight: 600; -} -.site-description { - margin-top: 0; - text-align: center; - font-size: 13px; - color: #999; -} -.site-state { - overflow: hidden; - line-height: 1.4; - white-space: nowrap; - text-align: center; -} -.site-state-item { - display: inline-block; - padding: 0 15px; - border-left: 1px solid #eee; -} -.site-state-item:first-child { - border-left: none; -} -.site-state-item a { - border-bottom: none; -} -.site-state-item-count { - display: block; - text-align: center; - color: inherit; - font-weight: 600; - font-size: 16px; -} -.site-state-item-name { - font-size: 13px; - color: #999; -} -.feed-link { - margin-top: 20px; -} -.feed-link a { - display: inline-block; - padding: 0 15px; - color: #fc6423; - border: 1px solid #fc6423; - border-radius: 4px; -} -.feed-link a i { - color: #fc6423; - font-size: 14px; -} -.feed-link a:hover { - color: #fff; - background: #fc6423; -} -.feed-link a:hover i { - color: #fff; -} -.links-of-author { - margin-top: 20px; -} -.links-of-author a { - display: inline-block; - vertical-align: middle; - margin-right: 10px; - margin-bottom: 10px; - border-bottom-color: #555; - font-size: 13px; -} -.links-of-author a:before { - display: inline-block; - vertical-align: middle; - margin-right: 3px; - content: " "; - width: 4px; - height: 4px; - border-radius: 50%; - background: #f2ff54; -} -.links-of-blogroll { - font-size: 13px; -} -.links-of-blogroll-title { - margin-top: 20px; - font-size: 14px; - font-weight: 600; -} -.links-of-blogroll-list { - margin: 0; - padding: 0; -} -.links-of-blogroll-item { - padding: 2px 10px; -} -.sidebar-nav { - margin: 0 0 20px; - padding-left: 0; -} -.sidebar-nav li { - display: inline-block; - cursor: pointer; - border-bottom: 1px solid transparent; - font-size: 14px; - color: #555; -} -.sidebar-nav li:hover { - color: #fc6423; -} -.page-post-detail .sidebar-nav-toc { - padding: 0 5px; -} -.page-post-detail .sidebar-nav-overview { - margin-left: 10px; -} -.sidebar-nav .sidebar-nav-active { - color: #fc6423; - border-bottom-color: #fc6423; -} -.sidebar-nav .sidebar-nav-active:hover { - color: #fc6423; -} -.sidebar-panel { - display: none; -} -.sidebar-panel-active { - display: block; -} -.post-toc-empty { - font-size: 14px; - color: #666; -} -.post-toc-wrap { - overflow: hidden; -} -.post-toc { - overflow: auto; -} -.post-toc ol { - margin: 0; - padding: 0 2px 5px 10px; - text-align: left; - list-style: none; - font-size: 14px; -} -.post-toc ol > ol { - padding-left: 0; -} -.post-toc ol a { - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; - transition-property: all; - color: #666; - border-bottom-color: #ccc; -} -.post-toc ol a:hover { - color: #000; - border-bottom-color: #000; -} -.post-toc .nav-item { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - line-height: 1.8; -} -.post-toc .nav .nav-child { - display: none; -} -.post-toc .nav .active > .nav-child { - display: block; -} -.post-toc .nav .active-current > .nav-child { - display: block; -} -.post-toc .nav .active-current > .nav-child > .nav-item { - display: block; -} -.post-toc .nav .active > a { - color: #fc6423; - border-bottom-color: #fc6423; -} -.post-toc .nav .active-current > a { - color: #fc6423; -} -.post-toc .nav .active-current > a:hover { - color: #fc6423; -} -.footer { - font-size: 14px; - color: #999; -} -.footer img { - border: none; -} -.footer-inner { - text-align: center; -} -.with-love { - display: inline-block; - margin: 0 5px; -} -.powered-by, -.theme-info { - display: inline-block; -} -.powered-by { - margin-right: 10px; -} -.powered-by::after { - content: "|"; - padding-left: 10px; -} -.cc-license { - margin-top: 10px; - text-align: center; -} -.cc-license .cc-opacity { - opacity: 0.7; - border-bottom: none; -} -.cc-license .cc-opacity:hover { - opacity: 0.9; -} -.cc-license img { - display: inline-block; -} -.theme-next #ds-thread #ds-reset { - color: #555; -} -.theme-next #ds-thread #ds-reset .ds-replybox { - margin-bottom: 30px; -} -.theme-next #ds-thread #ds-reset .ds-replybox .ds-avatar, -.theme-next #ds-reset .ds-avatar img { - box-shadow: none; -} -.theme-next #ds-thread #ds-reset .ds-textarea-wrapper { - border-color: #c7d4e1; - background: none; - border-top-right-radius: 3px; - border-top-left-radius: 3px; -} -.theme-next #ds-thread #ds-reset .ds-textarea-wrapper textarea { - height: 60px; -} -.theme-next #ds-reset .ds-rounded-top { - border-radius: 0; -} -.theme-next #ds-thread #ds-reset .ds-post-toolbar { - box-sizing: border-box; - border: 1px solid #c7d4e1; - background: #f6f8fa; -} -.theme-next #ds-thread #ds-reset .ds-post-options { - height: 40px; - border: none; - background: none; -} -.theme-next #ds-thread #ds-reset .ds-toolbar-buttons { - top: 11px; -} -.theme-next #ds-thread #ds-reset .ds-sync { - top: 5px; -} -.theme-next #ds-thread #ds-reset .ds-post-button { - top: 4px; - right: 5px; - width: 90px; - height: 30px; - border: 1px solid #c5ced7; - border-radius: 3px; - background-image: linear-gradient(#fbfbfc, #f5f7f9); - color: #60676d; -} -.theme-next #ds-thread #ds-reset .ds-post-button:hover { - background-position: 0 -30px; - color: #60676d; -} -.theme-next #ds-thread #ds-reset .ds-comments-info { - padding: 10px 0; -} -.theme-next #ds-thread #ds-reset .ds-sort { - display: none; -} -.theme-next #ds-thread #ds-reset li.ds-tab a.ds-current { - border: none; - background: #f6f8fa; - color: #60676d; -} -.theme-next #ds-thread #ds-reset li.ds-tab a.ds-current:hover { - background-color: #e9f0f7; - color: #60676d; -} -.theme-next #ds-thread #ds-reset li.ds-tab a { - border-radius: 2px; - padding: 5px; -} -.theme-next #ds-thread #ds-reset .ds-login-buttons p { - color: #999; - line-height: 36px; -} -.theme-next #ds-thread #ds-reset .ds-login-buttons .ds-service-list li { - height: 28px; -} -.theme-next #ds-thread #ds-reset .ds-service-list a { - background: none; - padding: 5px; - border: 1px solid; - border-radius: 3px; - text-align: center; -} -.theme-next #ds-thread #ds-reset .ds-service-list a:hover { - color: #fff; - background: #666; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-weibo { - color: #fc9b00; - border-color: #fc9b00; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-weibo:hover { - background: #fc9b00; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-qq { - color: #60a3ec; - border-color: #60a3ec; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-qq:hover { - background: #60a3ec; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-renren { - color: #2e7ac4; - border-color: #2e7ac4; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-renren:hover { - background: #2e7ac4; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-douban { - color: #37994c; - border-color: #37994c; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-douban:hover { - background: #37994c; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-kaixin { - color: #fef20d; - border-color: #fef20d; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-kaixin:hover { - background: #fef20d; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-netease { - color: #f00; - border-color: #f00; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-netease:hover { - background: #f00; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-sohu { - color: #ffcb05; - border-color: #ffcb05; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-sohu:hover { - background: #ffcb05; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-baidu { - color: #2831e0; - border-color: #2831e0; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-baidu:hover { - background: #2831e0; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-google { - color: #166bec; - border-color: #166bec; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-google:hover { - background: #166bec; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-weixin { - color: #00ce0d; - border-color: #00ce0d; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-weixin:hover { - background: #00ce0d; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-more-services { - border: none; -} -.theme-next #ds-thread #ds-reset .ds-service-list .ds-more-services:hover { - background: none; -} -.theme-next #ds-reset .duoshuo-ua-admin { - display: inline-block; - color: #f00; -} -.theme-next #ds-reset .duoshuo-ua-platform, -.theme-next #ds-reset .duoshuo-ua-browser { - color: #ccc; -} -.theme-next #ds-reset .duoshuo-ua-platform .fa, -.theme-next #ds-reset .duoshuo-ua-browser .fa { - display: inline-block; - margin-right: 3px; -} -.theme-next #ds-reset .duoshuo-ua-separator { - display: inline-block; - margin-left: 5px; -} -.theme-next .this_ua { - background-color: #ccc !important; - border-radius: 4px; - padding: 0 5px !important; - margin: 1px 1px !important; - border: 1px solid #bbb !important; - color: #fff; - display: inline-block !important; -} -.theme-next .this_ua.admin { - background-color: #d9534f !important; - border-color: #d9534f !important; -} -.theme-next .this_ua.platform.iOS, -.theme-next .this_ua.platform.Mac, -.theme-next .this_ua.platform.Windows { - background-color: #39b3d7 !important; - border-color: #46b8da !important; -} -.theme-next .this_ua.platform.Linux { - background-color: #3a3a3a !important; - border-color: #1f1f1f !important; -} -.theme-next .this_ua.platform.Android { - background-color: #00c47d !important; - border-color: #01b171 !important; -} -.theme-next .this_ua.browser.Mobile, -.theme-next .this_ua.browser.Chrome { - background-color: #5cb85c !important; - border-color: #4cae4c !important; -} -.theme-next .this_ua.browser.Firefox { - background-color: #f0ad4e !important; - border-color: #eea236 !important; -} -.theme-next .this_ua.browser.Maxthon, -.theme-next .this_ua.browser.IE { - background-color: #428bca !important; - border-color: #357ebd !important; -} -.theme-next .this_ua.browser.baidu, -.theme-next .this_ua.browser.UCBrowser, -.theme-next .this_ua.browser.Opera { - background-color: #d9534f !important; - border-color: #d43f3a !important; -} -.theme-next .this_ua.browser.Android, -.theme-next .this_ua.browser.QQBrowser { - background-color: #78ace9 !important; - border-color: #4cae4c !important; -} -.post-spread { - margin-top: 20px; - text-align: center; -} -.jiathis_style { - display: inline-block; -} -.jiathis_style a { - border: none; -} -.post-spread { - margin-top: 20px; - text-align: center; -} -.bdshare-slide-button-box a { - border: none; -} -.bdsharebuttonbox { - display: inline-block; -} -.bdsharebuttonbox a { - border: none; -} -ul.search-result-list { - padding-left: 0px; - margin: 0px 5px 0px 8px; -} -p.search-result { - border-bottom: 1px dashed #ccc; - padding: 5px 0; -} -a.search-result-title { - font-weight: bold; -} -a.search-result { - border-bottom: transparent; - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.search-keyword { - border-bottom: 1px dashed #4088b8; - font-weight: bold; -} -#local-search-result { - height: 90%; - overflow: auto; -} -.popup { - display: none; - position: fixed; - top: 10%; - left: 50%; - width: 700px; - height: 80%; - margin-left: -350px; - padding: 3px 0 0 10px; - background: #fff; - color: #333; - z-index: 9999; - border-radius: 5px; -} -@media (max-width: 767px) { - .popup { - padding: 3px; - top: 0; - left: 0; - margin: 0; - width: 100%; - height: 100%; - border-radius: 0px; - } -} -.popoverlay { - position: fixed; - width: 100%; - height: 100%; - top: 0px; - left: 0px; - z-index: 2080; - background-color: rgba(0,0,0,0.3); -} -#local-search-input { - margin-bottom: 10px; - width: 50%; -} -.popup-btn-close { - position: absolute; - top: 6px; - right: 14px; - color: #4ebd79; - font-size: 14px; - font-weight: bold; - text-transform: uppercase; - cursor: pointer; -} -#no-result { - position: absolute; - left: 44%; - top: 42%; - color: #ccc; -} -.busuanzi-count:before { - content: " "; - float: left; - width: 260px; - min-height: 25px; -} -@media (min-width: 768px) and (max-width: 991px) { - .busuanzi-count { - width: auto; - } - .busuanzi-count:before { - display: none; - } -} -@media (max-width: 767px) { - .busuanzi-count { - width: auto; - } - .busuanzi-count:before { - display: none; - } -} -.site-uv, -.site-pv, -.page-pv { - display: inline-block; -} -.site-uv .busuanzi-value, -.site-pv .busuanzi-value, -.page-pv .busuanzi-value { - margin: 0 5px; -} -.site-uv { - margin-right: 10px; -} -.site-uv::after { - content: "|"; - padding-left: 10px; -} -.use-motion .post { - opacity: 0; -} -.page-archive .archive-page-counter { - position: relative; - top: 3px; - left: 20px; -} -@media (max-width: 767px) { - .page-archive .archive-page-counter { - top: 5px; - } -} -.page-archive .posts-collapse .archive-move-on { - position: absolute; - top: 11px; - left: 0; - margin-left: -6px; - width: 10px; - height: 10px; - opacity: 0.5; - background: #555; - border: 1px solid #fff; - border-radius: 50%; -} -.category-all-page .category-all-title { - text-align: center; -} -.category-all-page .category-all { - margin-top: 20px; -} -.category-all-page .category-list { - margin: 0; - padding: 0; - list-style: none; -} -.category-all-page .category-list-item { - margin: 5px 10px; -} -.category-all-page .category-list-count { - color: #bbb; -} -.category-all-page .category-list-count:before { - display: inline; - content: " ("; -} -.category-all-page .category-list-count:after { - display: inline; - content: ") "; -} -.category-all-page .category-list-child { - padding-left: 10px; -} -.page-post-detail .sidebar-toggle-line { - background: #fc6423; -} -.page-post-detail .comments { - overflow: hidden; -} -body { - background: #f5f7f9; -} -@media (min-width: 992px) { - .full-image.full-image.full-image { - max-width: none; - width: 118%; - margin: 0 -9%; - } -} -.header { - position: relative; - margin: 0 auto; - width: 70%; -} -@media (min-width: 768px) and (max-width: 991px) { - .header { - width: auto; - } -} -@media (max-width: 767px) { - .header { - width: auto; - } -} -.header-inner { - position: absolute; - top: 0; - overflow: hidden; - padding: 0; - width: 240px; - background: #fff; -} -@media (min-width: 1600px) { - .container .header-inner { - width: 240px; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .header-inner { - position: relative; - width: auto; - } -} -@media (max-width: 767px) { - .header-inner { - position: relative; - width: auto; - } -} -.main:before, -.main:after { - content: " "; - display: table; -} -.main:after { - clear: both; -} -@media (min-width: 768px) and (max-width: 991px) { - .main { - padding-bottom: 100px; - } -} -@media (max-width: 767px) { - .main { - padding-bottom: 100px; - } -} -.container .main-inner { - width: 70%; -} -@media (min-width: 768px) and (max-width: 991px) { - .container .main-inner { - width: auto; - } -} -@media (max-width: 767px) { - .container .main-inner { - width: auto; - } -} -.content-wrap { - float: right; - box-sizing: border-box; - padding: 40px; - width: calc(100% - 260px); - background: #fff; - min-height: 700px; -} -@media (min-width: 768px) and (max-width: 991px) { - .content-wrap { - width: 100%; - padding: 20px; - } -} -@media (max-width: 767px) { - .content-wrap { - width: 100%; - padding: 20px; - min-height: auto; - } -} -.sidebar { - position: static; - float: left; - margin-top: 300px; - width: 240px; - background: #fff; - box-shadow: none; -} -@media (min-width: 768px) and (max-width: 991px) { - .sidebar { - display: none; - } -} -@media (max-width: 767px) { - .sidebar { - display: none; - } -} -.sidebar-toggle { - display: none; -} -.footer-inner { - width: 960px; -} -.footer-inner:before { - content: " "; - float: left; - width: 260px; - min-height: 50px; -} -@media (min-width: 768px) and (max-width: 991px) { - .footer-inner { - width: auto; - } - .footer-inner:before { - display: none; - } -} -@media (max-width: 767px) { - .footer-inner { - width: auto; - } - .footer-inner:before { - display: none; - } -} -.sidebar-position-right .header-inner { - right: 0; -} -.sidebar-position-right .content-wrap { - float: left; -} -.sidebar-position-right .sidebar { - float: right; -} -.sidebar-position-right .footer-inner:before { - float: right; -} -.site-meta { - padding: 20px 0; - color: #fff; - background: #222; -} -@media (min-width: 768px) and (max-width: 991px) { - .site-meta { - box-shadow: 0 0 16px rgba(0,0,0,0.5); - } -} -@media (max-width: 767px) { - .site-meta { - box-shadow: 0 0 16px rgba(0,0,0,0.5); - } -} -.brand { - display: block; - padding: 0; - background: none; -} -.brand:hover { - color: #fff; -} -.site-subtitle { - margin: 0; -} -.site-search form { - display: none; -} -.site-nav { - border-top: none; -} -@media (min-width: 768px) and (max-width: 991px) { - .site-nav { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .site-nav-on { - display: block !important; - } -} -.menu .menu-item { - display: block; - margin: 0; - list-style: none; -} -.menu .menu-item a { - position: relative; - box-sizing: border-box; - padding: 5px 20px; - text-align: left; - line-height: inherit; - transition-property: background-color; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - transition-delay: 0s; -} -.menu .menu-item a:hover, -.menu-item-active a { - background: #f9f9f9; - border-bottom-color: #fff; -} -.menu .menu-item br { - display: none; -} -.menu-item-active a:after { - content: " "; - position: absolute; - top: 50%; - margin-top: -3px; - right: 15px; - width: 6px; - height: 6px; - border-radius: 50%; - background-color: #bbb; -} -.btn-bar { - background-color: #fff; -} -.site-nav-toggle { - top: 20px; - left: 20px; -} -@media (min-width: 768px) and (max-width: 991px) { - .site-nav-toggle { - display: block; - } -} -.use-motion .sidebar .motion-element { - opacity: 1; -} -.sidebar { - display: none; - right: auto; - bottom: auto; - -webkit-transform: none; -} -.sidebar-inner { - box-sizing: border-box; - width: 240px; - color: #555; - background: #fff; -} -.sidebar-inner.affix { - position: fixed; - top: 0; -} -.site-overview { - margin: 0 2px; - text-align: left; -} -.site-author:before, -.site-author:after { - content: " "; - display: table; -} -.site-author:after { - clear: both; -} -.sidebar a { - color: #555; -} -.sidebar a:hover { - color: #222; -} -.links-of-author-item a:before { - display: none; -} -.links-of-author-item a { - border-bottom: none; - text-decoration: underline; -} -.feed-link { - border-top: 1px dotted #ccc; - border-bottom: 1px dotted #ccc; - text-align: center; -} -.feed-link a { - display: block; - color: #fc6423; - border: none; -} -.feed-link a:hover { - background: none; - color: #e34603; -} -.feed-link a:hover i { - color: #e34603; -} -.links-of-author:before, -.links-of-author:after { - content: " "; - display: table; -} -.links-of-author:after { - clear: both; -} -.links-of-author-item { - float: left; - margin: 5px 0 0; - width: 50%; -} -.links-of-author-item a { - box-sizing: border-box; - display: inline-block; - margin-right: 0; - margin-bottom: 0; - padding: 0 5px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -.links-of-author-item a { - display: block; - text-decoration: none; -} -.links-of-author-item a:hover { - border-radius: 4px; - background: #eee; -} -.links-of-author-item .fa { - margin-right: 2px; - font-size: 16px; -} -.links-of-author-item .fa-globe { - font-size: 15px; -} -.links-of-blogroll { - margin-top: 20px; - padding: 3px 0 0; - border-top: 1px dotted #ccc; -} -.links-of-blogroll-title { - margin-top: 0; -} -.links-of-blogroll-item { - padding: 0; -} -.links-of-blogroll-inline:before, -.links-of-blogroll-inline:after { - content: " "; - display: table; -} -.links-of-blogroll-inline:after { - clear: both; -} -.links-of-blogroll-inline .links-of-blogroll-item { - float: left; - margin: 5px 0 0; - width: 50%; -} -.links-of-blogroll-inline .links-of-blogroll-item a { - box-sizing: border-box; - display: inline-block; - margin-right: 0; - margin-bottom: 0; - padding: 0 5px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -@media (max-width: 767px) { - .post-body { - text-align: justify; - } -} diff --git a/images/Iverson_1.jpg b/images/Iverson_1.jpg new file mode 100644 index 0000000..51bc7aa Binary files /dev/null and b/images/Iverson_1.jpg differ diff --git a/images/Iverson_4.jpg b/images/Iverson_4.jpg new file mode 100644 index 0000000..90333be Binary files /dev/null and b/images/Iverson_4.jpg differ diff --git a/images/Iverson_5.jpg b/images/Iverson_5.jpg new file mode 100644 index 0000000..f00f831 Binary files /dev/null and b/images/Iverson_5.jpg differ diff --git a/images/Iverson_6.jpg b/images/Iverson_6.jpg new file mode 100644 index 0000000..9f6aa9e Binary files /dev/null and b/images/Iverson_6.jpg differ diff --git a/images/avatar.png b/images/avatar.png deleted file mode 100644 index f79418b..0000000 Binary files a/images/avatar.png and /dev/null differ diff --git a/images/cc-by-nc-nd.svg b/images/cc-by-nc-nd.svg deleted file mode 100644 index 79a4f2e..0000000 --- a/images/cc-by-nc-nd.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - diff --git a/images/cc-by-nc-sa.svg b/images/cc-by-nc-sa.svg deleted file mode 100644 index bf6bc26..0000000 --- a/images/cc-by-nc-sa.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - diff --git a/images/cc-by-nc.svg b/images/cc-by-nc.svg deleted file mode 100644 index 3697349..0000000 --- a/images/cc-by-nc.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - diff --git a/images/cc-by-nd.svg b/images/cc-by-nd.svg deleted file mode 100644 index 934c61e..0000000 --- a/images/cc-by-nd.svg +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - diff --git a/images/cc-by-sa.svg b/images/cc-by-sa.svg deleted file mode 100644 index 463276a..0000000 --- a/images/cc-by-sa.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - diff --git a/images/cc-by.svg b/images/cc-by.svg deleted file mode 100644 index 4bccd14..0000000 --- a/images/cc-by.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - diff --git a/images/cc-zero.svg b/images/cc-zero.svg deleted file mode 100644 index 0f86639..0000000 --- a/images/cc-zero.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/loading.gif b/images/loading.gif deleted file mode 100644 index efb6768..0000000 Binary files a/images/loading.gif and /dev/null differ diff --git a/images/placeholder.gif b/images/placeholder.gif deleted file mode 100644 index efb6768..0000000 Binary files a/images/placeholder.gif and /dev/null differ diff --git a/images/quote-l.svg b/images/quote-l.svg deleted file mode 100644 index 6dd94a4..0000000 --- a/images/quote-l.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/images/quote-r.svg b/images/quote-r.svg deleted file mode 100644 index 312b64d..0000000 --- a/images/quote-r.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/images/searchicon.png b/images/searchicon.png deleted file mode 100644 index 14a16ca..0000000 Binary files a/images/searchicon.png and /dev/null differ diff --git a/index.html b/index.html index 8901241..af295f3 100644 --- a/index.html +++ b/index.html @@ -1,1458 +1,220 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + AnswerInTheWind's space + + + + + + + + +
+ + + + + + + + +
+ +
+
+
+
+
+

The Answer

+

Take every ball as the last.

+
+
+
+

"我永远不会离开NBA"
+ "我永远只打首发"
+ 还真是个悲情英雄当初自大时说的台词啊。

+ +
+
+

几十年后,在费城或是丹佛的主场,会有一位白发苍苍的老球迷指着球场上 + 空高悬的3号球衣对他身边的年轻人说:“那是一位在这里忠诚战斗过的勇士,真正的男人, + 不屈的英雄。他的名字叫阿伦•艾弗森。” +

+
+
+
+
+ Next +
+ + +
+ +
+
+

有人说

+

从他进入联盟,指责和批评的声音就没停止过

+
+
有人指责他的文身和发型,我不明白这与你何干,不爱看你可以不看。 +
有人说他嚣张,我不明白什么叫嚣张,如果这算嚣张的话,我喜欢这样的嚣张。请看看高中生球员中的科比、麦迪、小斯甚至狼王,哪一个不是在高中就意气风发,有哪一个在职业生涯前期出现低谷?他深知没有大学篮球的历练,无法适应弱肉强食的NBA,他在球队做了十年老大,他嚣张得有理由,有资本。 +
有人说他年轻没经验不成熟,有人说他黏球,有人说他防守不够好,有人说……

+
    + +
+
+ Next +
+ + +
+ +
+
+

十年

+ +
+

恍然间,进入联盟已经十年,三十岁的他,已不再年轻。 + 他很难被称为是一个强壮的后卫,但他身上的伤是最多的。 + 他不再是那个能扣篮绝不上篮的青涩小子,他知道过猛的突破让自己遍体鳞伤,他学会用上篮抛投和柔和的跳投解决战斗。他从没像乔丹那样吐着舌头大讲垃圾话,不像伯德尖酸地讽刺,球场上他只为胜利而战,不变的是他那无辜、坚毅而清澈的眼神。 +
他依然透着嚣张,依然满手满臂的文身,依然挂着两三条巨大的钻石项链,依然穿黑人肥大的服装,依然梳着垄沟辫,依然热爱着篮球,追寻着总冠军。但是,十年也可以改变很多东西,一场场惨烈的失败后,他只是无奈地看着记分牌,用球衫擦擦脸上的汗———不是不努力,只是白努力。他不再和主帅斗气,不再成为警察局的常客,不再抱怨队友的无能,不再……他恐怕也不再做梦能拿总冠军。 +
一枚总冠军戒指就是他苦寻了十年的答案。

+
    + +
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/js/src/affix.js b/js/src/affix.js deleted file mode 100644 index 11a3d39..0000000 --- a/js/src/affix.js +++ /dev/null @@ -1,162 +0,0 @@ -/* ======================================================================== - * Bootstrap: affix.js v3.3.5 - * http://getbootstrap.com/javascript/#affix - * ======================================================================== - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== */ - - -+function ($) { - 'use strict'; - - // AFFIX CLASS DEFINITION - // ====================== - - var Affix = function (element, options) { - this.options = $.extend({}, Affix.DEFAULTS, options) - - this.$target = $(this.options.target) - .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) - .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) - - this.$element = $(element) - this.affixed = null - this.unpin = null - this.pinnedOffset = null - - this.checkPosition() - } - - Affix.VERSION = '3.3.5' - - Affix.RESET = 'affix affix-top affix-bottom' - - Affix.DEFAULTS = { - offset: 0, - target: window - } - - Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() - var targetHeight = this.$target.height() - - if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false - - if (this.affixed == 'bottom') { - if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' - return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' - } - - var initializing = this.affixed == null - var colliderTop = initializing ? scrollTop : position.top - var colliderHeight = initializing ? targetHeight : height - - if (offsetTop != null && scrollTop <= offsetTop) return 'top' - if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' - - return false - } - - Affix.prototype.getPinnedOffset = function () { - if (this.pinnedOffset) return this.pinnedOffset - this.$element.removeClass(Affix.RESET).addClass('affix') - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() - return (this.pinnedOffset = position.top - scrollTop) - } - - Affix.prototype.checkPositionWithEventLoop = function () { - setTimeout($.proxy(this.checkPosition, this), 1) - } - - Affix.prototype.checkPosition = function () { - if (!this.$element.is(':visible')) return - - var height = this.$element.height() - var offset = this.options.offset - var offsetTop = offset.top - var offsetBottom = offset.bottom - var scrollHeight = Math.max($(document).height(), $(document.body).height()) - - if (typeof offset != 'object') offsetBottom = offsetTop = offset - if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) - if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) - - var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) - - if (this.affixed != affix) { - if (this.unpin != null) this.$element.css('top', '') - - var affixType = 'affix' + (affix ? '-' + affix : '') - var e = $.Event(affixType + '.bs.affix') - - this.$element.trigger(e) - - if (e.isDefaultPrevented()) return - - this.affixed = affix - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null - - this.$element - .removeClass(Affix.RESET) - .addClass(affixType) - .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') - } - - if (affix == 'bottom') { - this.$element.offset({ - top: scrollHeight - height - offsetBottom - }) - } - } - - - // AFFIX PLUGIN DEFINITION - // ======================= - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.affix') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.affix', (data = new Affix(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.affix - - $.fn.affix = Plugin - $.fn.affix.Constructor = Affix - - - // AFFIX NO CONFLICT - // ================= - - $.fn.affix.noConflict = function () { - $.fn.affix = old - return this - } - - - // AFFIX DATA-API - // ============== - - $(window).on('load', function () { - $('[data-spy="affix"]').each(function () { - var $spy = $(this) - var data = $spy.data() - - data.offset = data.offset || {} - - if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom - if (data.offsetTop != null) data.offset.top = data.offsetTop - - Plugin.call($spy, data) - }) - }) - -}(jQuery); diff --git a/js/src/bootstrap.js b/js/src/bootstrap.js deleted file mode 100644 index 49b9425..0000000 --- a/js/src/bootstrap.js +++ /dev/null @@ -1,44 +0,0 @@ -/* global NexT: true */ - -$(document).ready(function () { - - $(document).trigger('bootstrap:before'); - - NexT.utils.isMobile() && window.FastClick.attach(document.body); - - NexT.utils.lazyLoadPostsImages(); - - NexT.utils.registerBackToTop(); - - $('.site-nav-toggle button').on('click', function () { - var $siteNav = $('.site-nav'); - var ON_CLASS_NAME = 'site-nav-on'; - var isSiteNavOn = $siteNav.hasClass(ON_CLASS_NAME); - var animateAction = isSiteNavOn ? 'slideUp' : 'slideDown'; - var animateCallback = isSiteNavOn ? 'removeClass' : 'addClass'; - - $siteNav.stop()[animateAction]('fast', function () { - $siteNav[animateCallback](ON_CLASS_NAME); - }); - }); - - - CONFIG.fancybox && NexT.utils.wrapImageWithFancyBox(); - NexT.utils.embeddedVideoTransformer(); - NexT.utils.addActiveClassToMenuItem(); - - - // Define Motion Sequence. - NexT.motion.integrator - .add(NexT.motion.middleWares.logo) - .add(NexT.motion.middleWares.menu) - .add(NexT.motion.middleWares.postList) - .add(NexT.motion.middleWares.sidebar); - - $(document).trigger('motion:before'); - - // Bootstrap Motion. - CONFIG.motion && NexT.motion.integrator.bootstrap(); - - $(document).trigger('bootstrap:after'); -}); diff --git a/js/src/hook-duoshuo.js b/js/src/hook-duoshuo.js deleted file mode 100644 index ca64dbd..0000000 --- a/js/src/hook-duoshuo.js +++ /dev/null @@ -1,115 +0,0 @@ -/* global DUOSHUO: true */ -/* jshint camelcase: false */ - -typeof DUOSHUO !== 'undefined' ? - hookTemplate() : - ($('#duoshuo-script')[0].onload = hookTemplate); - - -function hookTemplate() { - var post = DUOSHUO.templates.post; - - DUOSHUO.templates.post = function (e, t) { - var rs = post(e, t); - var agent = e.post.agent; - var userId = e.post.author.user_id; - var admin = ''; - - if (userId && (userId == CONFIG.duoshuo.userId)) { - admin = '' + CONFIG.duoshuo.author + ''; - } - - if (agent && /^Mozilla/.test(agent)) { - rs = rs.replace(/<\/div>

/, admin + getAgentInfo(agent) + '

'); - } - - return rs; - }; -} - -function getAgentInfo(string) { - $.ua.set(string); - - var UNKNOWN = 'Unknown'; - var sua = $.ua; - var separator = isMobile() ? '

' : ''; - var osName = sua.os.name || UNKNOWN; - var osVersion = sua.os.version || UNKNOWN; - var browserName = sua.browser.name || UNKNOWN; - var browserVersion = sua.browser.version || UNKNOWN; - var iconMapping = { - os: { - android : 'android', - linux : 'linux', - windows : 'windows', - ios : 'apple', - 'mac os': 'apple', - unknown : 'desktop' - }, - browser: { - chrome : 'chrome', - chromium : 'chrome', - firefox : 'firefox', - opera : 'opera', - safari : 'safari', - ie : 'internet-explorer', - wechat : 'wechat', - qq : 'qq', - unknown : 'globe' - } - }; - var osIcon = iconMapping.os[osName.toLowerCase()]; - var browserIcon = iconMapping.browser[getBrowserKey()]; - - return separator + - '' + - '' + - osName + ' ' + osVersion + - '' + separator + - '' + - '' + - browserName + ' ' + browserVersion + - ''; - - function getBrowserKey () { - var key = browserName.toLowerCase(); - - if (key.match(/WeChat/i)) { - return 'wechat'; - } - - if (key.match(/QQBrowser/i)) { - return 'qq'; - } - - return key; - } - - function isMobile() { - var userAgent = window.navigator.userAgent; - - var isiPad = userAgent.match(/iPad/i) !== null; - var mobileUA = [ - 'iphone', 'android', 'phone', 'mobile', - 'wap', 'netfront', 'x11', 'java', 'opera mobi', - 'opera mini', 'ucweb', 'windows ce', 'symbian', - 'symbianos', 'series', 'webos', 'sony', - 'blackberry', 'dopod', 'nokia', 'samsung', - 'palmsource', 'xda', 'pieplus', 'meizu', - 'midp' ,'cldc' , 'motorola', 'foma', - 'docomo', 'up.browser', 'up.link', 'blazer', - 'helio', 'hosin', 'huawei', 'novarra', - 'coolpad', 'webos', 'techfaith', 'palmsource', - 'alcatel', 'amoi', 'ktouch', 'nexian', - 'ericsson', 'philips', 'sagem', 'wellcom', - 'bunjalloo', 'maui', 'smartphone', 'iemobile', - 'spice', 'bird', 'zte-', 'longcos', - 'pantech', 'gionee', 'portalmmm', 'jig browser', - 'hiptop', 'benq', 'haier', '^lct', - '320x320', '240x320', '176x220' - ]; - var pattern = new RegExp(mobileUA.join('|'), 'i'); - - return !isiPad && userAgent.match(pattern); - } -} diff --git a/js/src/motion.js b/js/src/motion.js deleted file mode 100644 index cbfb824..0000000 --- a/js/src/motion.js +++ /dev/null @@ -1,291 +0,0 @@ -/* global NexT: true */ - -$(document).ready(function () { - NexT.motion = {}; - - var sidebarToggleLines = { - lines: [], - push: function (line) { - this.lines.push(line); - }, - init: function () { - this.lines.forEach(function (line) { - line.init(); - }); - }, - arrow: function () { - this.lines.forEach(function (line) { - line.arrow(); - }); - }, - close: function () { - this.lines.forEach(function (line) { - line.close(); - }); - } - }; - - function SidebarToggleLine(settings) { - this.el = $(settings.el); - this.status = $.extend({}, { - init: { - width: '100%', - opacity: 1, - left: 0, - rotateZ: 0, - top: 0 - } - }, settings.status); - } - - SidebarToggleLine.prototype.init = function () { - this.transform('init'); - }; - SidebarToggleLine.prototype.arrow = function () { - this.transform('arrow'); - }; - SidebarToggleLine.prototype.close = function () { - this.transform('close'); - }; - SidebarToggleLine.prototype.transform = function (status) { - this.el.velocity('stop').velocity(this.status[status]); - }; - - var sidebarToggleLine1st = new SidebarToggleLine({ - el: '.sidebar-toggle-line-first', - status: { - arrow: {width: '50%', rotateZ: '-45deg', top: '2px'}, - close: {width: '100%', rotateZ: '-45deg', top: '5px'} - } - }); - var sidebarToggleLine2nd = new SidebarToggleLine({ - el: '.sidebar-toggle-line-middle', - status: { - arrow: {width: '90%'}, - close: {opacity: 0} - } - }); - var sidebarToggleLine3rd = new SidebarToggleLine({ - el: '.sidebar-toggle-line-last', - status: { - arrow: {width: '50%', rotateZ: '45deg', top: '-2px'}, - close: {width: '100%', rotateZ: '45deg', top: '-5px'} - } - }); - - sidebarToggleLines.push(sidebarToggleLine1st); - sidebarToggleLines.push(sidebarToggleLine2nd); - sidebarToggleLines.push(sidebarToggleLine3rd); - - var SIDEBAR_WIDTH = '320px'; - var SIDEBAR_DISPLAY_DURATION = 200; - - var sidebarToggleMotion = { - toggleEl: $('.sidebar-toggle'), - sidebarEl: $('.sidebar'), - isSidebarVisible: false, - init: function () { - this.toggleEl.on('click', this.clickHandler.bind(this)); - this.toggleEl.on('mouseenter', this.mouseEnterHandler.bind(this)); - this.toggleEl.on('mouseleave', this.mouseLeaveHandler.bind(this)); - - $(document) - .on('sidebar.isShowing', function () { - NexT.utils.isDesktop() && $('body').velocity('stop').velocity( - {paddingRight: SIDEBAR_WIDTH}, - SIDEBAR_DISPLAY_DURATION - ); - }) - .on('sidebar.isHiding', function () { - }); - }, - clickHandler: function () { - this.isSidebarVisible ? this.hideSidebar() : this.showSidebar(); - this.isSidebarVisible = !this.isSidebarVisible; - }, - mouseEnterHandler: function () { - if (this.isSidebarVisible) { - return; - } - sidebarToggleLines.arrow(); - }, - mouseLeaveHandler: function () { - if (this.isSidebarVisible) { - return; - } - sidebarToggleLines.init(); - }, - showSidebar: function () { - var self = this; - - sidebarToggleLines.close(); - - this.sidebarEl.velocity('stop').velocity({ - width: SIDEBAR_WIDTH - }, { - display: 'block', - duration: SIDEBAR_DISPLAY_DURATION, - begin: function () { - $('.sidebar .motion-element').velocity( - 'transition.slideRightIn', - { - stagger: 50, - drag: true, - complete: function () { - self.sidebarEl.trigger('sidebar.motion.complete'); - } - } - ); - }, - complete: function () { - self.sidebarEl.addClass('sidebar-active'); - self.sidebarEl.trigger('sidebar.didShow'); - } - } - ); - - this.sidebarEl.trigger('sidebar.isShowing'); - }, - hideSidebar: function () { - NexT.utils.isDesktop() && $('body').velocity('stop').velocity({paddingRight: 0}); - this.sidebarEl.find('.motion-element').velocity('stop').css('display', 'none'); - this.sidebarEl.velocity('stop').velocity({width: 0}, {display: 'none'}); - - sidebarToggleLines.init(); - - this.sidebarEl.removeClass('sidebar-active'); - this.sidebarEl.trigger('sidebar.isHiding'); - - //在 post 页面下按下隐藏 sidebar 时如果当前选中的是“站点概览”,将 toc 去除 motion 效果 - //防止再次打开时会出现在“站点概览”下的 bug - if (!!$('.post-toc-wrap')) { - if ($('.site-overview').css('display') === 'block') { - $('.post-toc-wrap').removeClass('motion-element'); - } - } - } - }; - sidebarToggleMotion.init(); - - NexT.motion.integrator = { - queue: [], - cursor: -1, - add: function (fn) { - this.queue.push(fn); - return this; - }, - next: function () { - this.cursor++; - var fn = this.queue[this.cursor]; - $.isFunction(fn) && fn(NexT.motion.integrator); - }, - bootstrap: function () { - this.next(); - } - }; - - NexT.motion.middleWares = { - logo: function (integrator) { - var sequence = []; - var $brand = $('.brand'); - var $title = $('.site-title'); - var $subtitle = $('.site-subtitle'); - var $logoLineTop = $('.logo-line-before i'); - var $logoLineBottom = $('.logo-line-after i'); - - $brand.size() > 0 && sequence.push({ - e: $brand, - p: {opacity: 1}, - o: {duration: 200} - }); - - NexT.utils.isMist() && hasElement([$logoLineTop, $logoLineBottom]) && - sequence.push( - getMistLineSettings($logoLineTop, '100%'), - getMistLineSettings($logoLineBottom, '-100%') - ); - - hasElement($title) && sequence.push({ - e: $title, - p: {opacity: 1, top: 0}, - o: { duration: 200 } - }); - - hasElement($subtitle) && sequence.push({ - e: $subtitle, - p: {opacity: 1, top: 0}, - o: {duration: 200} - }); - - if (sequence.length > 0) { - sequence[sequence.length - 1].o.complete = function () { - integrator.next(); - }; - $.Velocity.RunSequence(sequence); - } else { - integrator.next(); - } - - - function getMistLineSettings (element, translateX) { - return { - e: $(element), - p: {translateX: translateX}, - o: { - duration: 500, - sequenceQueue: false - } - }; - } - - /** - * Check if $elements exist. - * @param {jQuery|Array} $elements - * @returns {boolean} - */ - function hasElement ($elements) { - $elements = Array.isArray($elements) ? $elements : [$elements]; - return $elements.every(function ($element) { - return $.isFunction($element.size) && $element.size() > 0; - }); - } - }, - - menu: function (integrator) { - $('.menu-item').velocity('transition.slideDownIn', { - display: null, - duration: 200, - complete: function () { - integrator.next(); - } - }); - }, - - postList: function (integrator) { - var $post = $('.post'); - var hasPost = $post.size() > 0; - - hasPost ? postMotion() : integrator.next(); - - function postMotion () { - var postMotionOptions = window.postMotionOptions || { - stagger: 100, - drag: true - }; - postMotionOptions.complete = function () { - integrator.next(); - }; - - $post.velocity('transition.slideDownIn', postMotionOptions); - } - }, - - sidebar: function (integrator) { - if (CONFIG.sidebar.display === 'always') { - NexT.utils.displaySidebar(); - } - integrator.next(); - } - }; - -}); diff --git a/js/src/post-details.js b/js/src/post-details.js deleted file mode 100644 index 156b697..0000000 --- a/js/src/post-details.js +++ /dev/null @@ -1,140 +0,0 @@ -/* global NexT: true */ - -$(document).ready(function () { - - initScrollSpy(); - NexT.utils.needAffix() && initAffix(); - initTOCDimension(); - - function initScrollSpy () { - var tocSelector = '.post-toc'; - var $tocElement = $(tocSelector); - var activeCurrentSelector = '.active-current'; - - $tocElement - .on('activate.bs.scrollspy', function () { - var $currentActiveElement = $(tocSelector + ' .active').last(); - - removeCurrentActiveClass(); - $currentActiveElement.addClass('active-current'); - }) - .on('clear.bs.scrollspy', removeCurrentActiveClass); - - $('body').scrollspy({ target: tocSelector }); - - function removeCurrentActiveClass () { - $(tocSelector + ' ' + activeCurrentSelector) - .removeClass(activeCurrentSelector.substring(1)); - } - } - - function initAffix () { - var headerHeight = $('.header-inner').height(); - var footerOffset = parseInt($('.main').css('padding-bottom'), 10); - var sidebarTop = headerHeight + 10; - - $('.sidebar-inner').affix({ - offset: { - top: sidebarTop, - bottom: footerOffset - } - }); - - $(document) - .on('affixed.bs.affix', function () { - updateTOCHeight(document.body.clientHeight - 100); - }); - } - - function initTOCDimension () { - var updateTOCHeightTimer; - - $(window).on('resize', function () { - updateTOCHeightTimer && clearTimeout(updateTOCHeightTimer); - - updateTOCHeightTimer = setTimeout(function () { - var tocWrapperHeight = document.body.clientHeight - 100; - - updateTOCHeight(tocWrapperHeight); - }, 0); - }); - - // Initialize TOC Height. - updateTOCHeight(document.body.clientHeight - 100); - - // Initialize TOC Width. - var scrollbarWidth = NexT.utils.getScrollbarWidth(); - $('.post-toc').css('width', 'calc(100% + ' + scrollbarWidth + 'px)'); - } - - function updateTOCHeight (height) { - height = height || 'auto'; - $('.post-toc').css('max-height', height); - } - -}); - -$(document).ready(function () { - var html = $('html'); - var TAB_ANIMATE_DURATION = 200; - var hasVelocity = $.isFunction(html.velocity); - - $('.sidebar-nav li').on('click', function () { - var item = $(this); - var activeTabClassName = 'sidebar-nav-active'; - var activePanelClassName = 'sidebar-panel-active'; - if (item.hasClass(activeTabClassName)) { - return; - } - - var currentTarget = $('.' + activePanelClassName); - var target = $('.' + item.data('target')); - - hasVelocity ? - currentTarget.velocity('transition.slideUpOut', TAB_ANIMATE_DURATION, function () { - target - .velocity('stop') - .velocity('transition.slideDownIn', TAB_ANIMATE_DURATION) - .addClass(activePanelClassName); - }) : - currentTarget.animate({ opacity: 0 }, TAB_ANIMATE_DURATION, function () { - currentTarget.hide(); - target - .stop() - .css({'opacity': 0, 'display': 'block'}) - .animate({ opacity: 1 }, TAB_ANIMATE_DURATION, function () { - currentTarget.removeClass(activePanelClassName); - target.addClass(activePanelClassName); - }); - }); - - item.siblings().removeClass(activeTabClassName); - item.addClass(activeTabClassName); - }); - - $('.post-toc a').on('click', function (e) { - e.preventDefault(); - var targetSelector = NexT.utils.escapeSelector(this.getAttribute('href')); - var offset = $(targetSelector).offset().top; - - hasVelocity ? - html.velocity('stop').velocity('scroll', { - offset: offset + 'px', - mobileHA: false - }) : - $('html, body').stop().animate({ - scrollTop: offset - }, 500); - }); - - // Expand sidebar on post detail page by default, when post has a toc. - NexT.motion.middleWares.sidebar = function () { - var $tocContent = $('.post-toc-content'); - - if (CONFIG.sidebar.display === 'post' || CONFIG.sidebar.display === 'always') { - if ($tocContent.length > 0 && $tocContent.html().trim().length > 0) { - NexT.utils.displaySidebar(); - } - } - }; -}); diff --git a/js/src/schemes/pisces.js b/js/src/schemes/pisces.js deleted file mode 100644 index 07d5682..0000000 --- a/js/src/schemes/pisces.js +++ /dev/null @@ -1,5 +0,0 @@ -$(document).ready(function () { - var sidebarTop = $('.header-inner').height() + 10; - - $('#sidebar').css({ 'margin-top': sidebarTop }).show(); -}); diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js deleted file mode 100644 index f5c5c6c..0000000 --- a/js/src/scrollspy.js +++ /dev/null @@ -1,182 +0,0 @@ -/* ======================================================================== -* Bootstrap: scrollspy.js v3.3.2 -* http://getbootstrap.com/javascript/#scrollspy -* ======================================================================== -* Copyright 2011-2015 Twitter, Inc. -* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) -* ======================================================================== */ - -/** - * Custom by iissnan - * - * - Add a `clear.bs.scrollspy` event. - * - Esacpe targets selector. - */ - - -+function ($) { - 'use strict'; - - // SCROLLSPY CLASS DEFINITION - // ========================== - - function ScrollSpy(element, options) { - this.$body = $(document.body) - this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) - this.options = $.extend({}, ScrollSpy.DEFAULTS, options) - this.selector = (this.options.target || '') + ' .nav li > a' - this.offsets = [] - this.targets = [] - this.activeTarget = null - this.scrollHeight = 0 - - this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) - this.refresh() - this.process() - } - - ScrollSpy.VERSION = '3.3.2' - - ScrollSpy.DEFAULTS = { - offset: 10 - } - - ScrollSpy.prototype.getScrollHeight = function () { - return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) - } - - ScrollSpy.prototype.refresh = function () { - var that = this - var offsetMethod = 'offset' - var offsetBase = 0 - - this.offsets = [] - this.targets = [] - this.scrollHeight = this.getScrollHeight() - - if (!$.isWindow(this.$scrollElement[0])) { - offsetMethod = 'position' - offsetBase = this.$scrollElement.scrollTop() - } - - this.$body - .find(this.selector) - .map(function () { - var $el = $(this) - var href = $el.data('target') || $el.attr('href') - var $href = /^#./.test(href) && $(NexT.utils.escapeSelector(href)) // Need to escape selector. - - return ($href - && $href.length - && $href.is(':visible') - && [[$href[offsetMethod]().top + offsetBase, href]]) || null - }) - .sort(function (a, b) { return a[0] - b[0] }) - .each(function () { - that.offsets.push(this[0]) - that.targets.push(this[1]) - }) - - - } - - ScrollSpy.prototype.process = function () { - var scrollTop = this.$scrollElement.scrollTop() + this.options.offset - var scrollHeight = this.getScrollHeight() - var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() - var offsets = this.offsets - var targets = this.targets - var activeTarget = this.activeTarget - var i - - if (this.scrollHeight != scrollHeight) { - this.refresh() - } - - if (scrollTop >= maxScroll) { - return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) - } - - if (activeTarget && scrollTop < offsets[0]) { - $(this.selector).trigger('clear.bs.scrollspy') // Add a custom event. - this.activeTarget = null - return this.clear() - } - - for (i = offsets.length; i--;) { - activeTarget != targets[i] - && scrollTop >= offsets[i] - && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) - && this.activate(targets[i]) - } - } - - ScrollSpy.prototype.activate = function (target) { - this.activeTarget = target - - this.clear() - - var selector = this.selector + - '[data-target="' + target + '"],' + - this.selector + '[href="' + target + '"]' - - var active = $(selector) - .parents('li') - .addClass('active') - - if (active.parent('.dropdown-menu').length) { - active = active - .closest('li.dropdown') - .addClass('active') - } - - active.trigger('activate.bs.scrollspy') - } - - ScrollSpy.prototype.clear = function () { - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') - } - - - // SCROLLSPY PLUGIN DEFINITION - // =========================== - - function Plugin(option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.scrollspy') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - var old = $.fn.scrollspy - - $.fn.scrollspy = Plugin - $.fn.scrollspy.Constructor = ScrollSpy - - - // SCROLLSPY NO CONFLICT - // ===================== - - $.fn.scrollspy.noConflict = function () { - $.fn.scrollspy = old - return this - } - - - // SCROLLSPY DATA-API - // ================== - - $(window).on('load.bs.scrollspy.data-api', function () { - $('[data-spy="scroll"]').each(function () { - var $spy = $(this) - Plugin.call($spy, $spy.data()) - }) - }) - -}(jQuery); diff --git a/js/src/utils.js b/js/src/utils.js deleted file mode 100644 index 473f5d9..0000000 --- a/js/src/utils.js +++ /dev/null @@ -1,207 +0,0 @@ -/* global NexT: true */ - -NexT.utils = NexT.$u = { - /** - * Wrap images with fancybox support. - */ - wrapImageWithFancyBox: function () { - $('.content img').not('.group-picture img').each(function () { - - var $image = $(this); - var imageTitle = $image.attr('title'); - var $imageWrapLink = $image.parent('a'); - - if ($imageWrapLink.size() < 1) { - $imageWrapLink = $image.wrap('').parent('a'); - } - - $imageWrapLink.addClass('fancybox'); - $imageWrapLink.attr('rel', 'group'); - - if (imageTitle) { - $imageWrapLink.append('

' + imageTitle + '

'); - $imageWrapLink.attr('title', imageTitle); //make sure img title tag will show correctly in fancybox - } - }); - - $('.fancybox').fancybox({ - helpers: { - overlay: { - locked: false - } - } - }); - }, - - lazyLoadPostsImages: function () { - $('#posts').find('img').lazyload({ - placeholder: '/images/loading.gif', - effect: 'fadeIn' - }); - }, - - registerBackToTop: function () { - var THRESHOLD = 50; - var $top = $('.back-to-top'); - - $(window).on('scroll', function () { - $top.toggleClass('back-to-top-on', window.pageYOffset > THRESHOLD); - }); - - $top.on('click', function () { - $('body').velocity('scroll'); - }); - }, - - /** - * Transform embedded video to support responsive layout. - * @see http://toddmotto.com/fluid-and-responsive-youtube-and-vimeo-videos-with-fluidvids-js/ - */ - embeddedVideoTransformer: function () { - var $iframes = $('iframe'); - - // Supported Players. Extend this if you need more players. - var SUPPORTED_PLAYERS = [ - 'www.youtube.com', - 'player.vimeo.com', - 'player.youku.com', - 'music.163.com', - 'www.tudou.com' - ]; - var pattern = new RegExp( SUPPORTED_PLAYERS.join('|') ); - - $iframes.each(function () { - var iframe = this; - var $iframe = $(this); - var oldDimension = getDimension($iframe); - var newDimension; - - if (this.src.search(pattern) > 0) { - - // Calculate the video ratio based on the iframe's w/h dimensions - var videoRatio = getAspectRadio(oldDimension.width, oldDimension.height); - - // Replace the iframe's dimensions and position the iframe absolute - // This is the trick to emulate the video ratio - $iframe.width('100%').height('100%') - .css({ - position: 'absolute', - top: '0', - left: '0' - }); - - - // Wrap the iframe in a new
which uses a dynamically fetched padding-top property - // based on the video's w/h dimensions - var wrap = document.createElement('div'); - wrap.className = 'fluid-vids'; - wrap.style.position = 'relative'; - wrap.style.marginBottom = '20px'; - wrap.style.width = '100%'; - wrap.style.paddingTop = videoRatio + '%'; - - // Add the iframe inside our newly created
- var iframeParent = iframe.parentNode; - iframeParent.insertBefore(wrap, iframe); - wrap.appendChild(iframe); - - // Additional adjustments for 163 Music - if (this.src.search('music.163.com') > 0) { - newDimension = getDimension($iframe); - var shouldRecalculateAspect = newDimension.width > oldDimension.width || - newDimension.height < oldDimension.height; - - // 163 Music Player has a fixed height, so we need to reset the aspect radio - if (shouldRecalculateAspect) { - wrap.style.paddingTop = getAspectRadio(newDimension.width, oldDimension.height) + '%'; - } - } - } - }); - - function getDimension($element) { - return { - width: $element.width(), - height: $element.height() - }; - } - - function getAspectRadio(width, height) { - return height / width * 100; - } - }, - - /** - * Add `menu-item-active` class name to menu item - * via comparing location.path with menu item's href. - */ - addActiveClassToMenuItem: function () { - var path = window.location.pathname; - path = path === '/' ? path : path.substring(0, path.length - 1); - $('.menu-item a[href="' + path + '"]').parent().addClass('menu-item-active'); - }, - - hasMobileUA: function () { - var nav = window.navigator; - var ua = nav.userAgent; - var pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g; - - return pa.test(ua); - }, - - isTablet: function () { - return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA(); - }, - - isMobile: function () { - return window.screen.width < 767 && this.hasMobileUA(); - }, - - isDesktop: function () { - return !this.isTablet() && !this.isMobile(); - }, - - /** - * Escape meta symbols in jQuery selectors. - * - * @param selector - * @returns {string|void|XML|*} - */ - escapeSelector: function (selector) { - return selector.replace(/[!"$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&'); - }, - - displaySidebar: function () { - if (!this.isDesktop() || this.isPisces()) { - return; - } - $('.sidebar-toggle').trigger('click'); - }, - - isMist: function () { - return CONFIG.scheme === 'Mist'; - }, - - isPisces: function () { - return CONFIG.scheme === 'Pisces'; - }, - - getScrollbarWidth: function () { - var $div = $('
').addClass('scrollbar-measure').prependTo('body'); - var div = $div[0]; - var scrollbarWidth = div.offsetWidth - div.clientWidth; - - $div.remove(); - - return scrollbarWidth; - }, - - /** - * Affix behaviour for Sidebar. - * - * @returns {Boolean} - */ - needAffix: function () { - return this.isPisces(); - } -}; diff --git a/page/2/index.html b/page/2/index.html deleted file mode 100644 index 7441a57..0000000 --- a/page/2/index.html +++ /dev/null @@ -1,1441 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/page/3/index.html b/page/3/index.html deleted file mode 100644 index 2a4ceea..0000000 --- a/page/3/index.html +++ /dev/null @@ -1,1441 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/page/4/index.html b/page/4/index.html deleted file mode 100644 index 56aa777..0000000 --- a/page/4/index.html +++ /dev/null @@ -1,1449 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/page/5/index.html b/page/5/index.html deleted file mode 100644 index aaec8b7..0000000 --- a/page/5/index.html +++ /dev/null @@ -1,1439 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/search.xml b/search.xml deleted file mode 100644 index 550f9ad..0000000 --- a/search.xml +++ /dev/null @@ -1,1202 +0,0 @@ - - - - - - - <![CDATA[低功耗调试心得]]> - http://yoursite.com/2016/12/26/%E4%BD%8E%E5%8A%9F%E8%80%97%E8%B0%83%E8%AF%95%E5%BF%83%E5%BE%97/ - 最近调试的设备都是用电池供电的,所以电池的消耗显得非常的重要。

-

之前在调试低功耗的路上走过一些坑,现在分享一些最近的调试心得。

-

心得

    -
  1. 休眠之前,不用于唤醒的引脚全部设置成 输入-高阻态
  2. -
-

高阻态可以近似的理解成 引脚断开与连接电路状态。

-
    -
  1. 休眠之前,如不需要RTC定时唤醒,则把RTC关闭
  2. -
-

休眠唤醒之后,设备会从休眠时的下一个语句开始执行,注意恢复引脚。

-]]>
-
- - - <![CDATA[LoRaWAN协议(六)__OTAA KEY生成过程]]> - http://yoursite.com/2016/11/27/LoRaWAN%E5%8D%8F%E8%AE%AE(%E5%85%AD)__OTAA%20KEY%E7%94%9F%E6%88%90%E8%BF%87%E7%A8%8B/ - 前言

通过OTAA方式入网的设备,通讯时使用的KEY需要通过服务器获得,在入网之间,设备无法通讯。

-

相关的OTAA入网流程已经在上一章中讲解过了,有兴趣的可以去看看LoRaWAN协议(五)__OTAA入网方式详述

-

这一章讲解的是OTAA中的密钥生成过程。

-

其中使用到的库函数都是从semtech的官方库中来的,官方库代码链接:LoRaMac-node

-

详解

设备在通讯时,会使用的密钥有NwkSKey 和AppSKey。

-

生成的公式如下:

-
    -
  • NwkSKey = aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16)
  • -
  • AppSKey = aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)
  • -
-

可以看到相关的参数一共有四个:
1.AppNonce
2.NetID
3.DevNonce
4.pad16

-

其中AppNonce、NetID、pad16 是产生于服务器的,DevNonce产生于node设备本身。

-

还是使用LoRaWAN协议(五)这篇文章中使用的包数据来进行分析。

-

这里,我们调用官方库的接口,因为我们这里只是熟悉协议,并不是要研究Key的生成算法。

-

如果不明白数据协议的,可以去看LoRaWAN协议(五)这篇文章

-

提取DevNonce

1.GW->NS JSON包,从中提取出来DevNonce,

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"rxpk": [
{
"tmst": 532505620,
"chan": 6,
"rfch": 0,
"freq": 471.9,
"stat": 1,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"lsnr": -17,
"rssi": -81,
"size": 23,
"data": "AAEAACAAxSYsFhAWIAB3SgBUe0At4Zo="
}
]
}
-

data为MAC层数据,为join_request message,其数据包格式为

- - - - - - - - - - - - - - - - - - - -
MHDRAPPEUIDevEUIDevNonceMIC
1字节8字节8字节2字节4字节
-

base64解码:

1
2
3
\x00 \x01 \x00 \x00 \x20 \x00 \xc5 \x26
\x2c \x16 \x10 \x16 \x20 \x00 \x77 \x4a
\x00 \x54 \x7b \x40 \x2d \xe1 \x9a

-

得到的数据:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段内容
MHDR\x00
AppEUI\x01 \x00 \x00 \x20 \x00 \xc5 \x26 \x2c
DevEUI\x16 \x10 \x16 \x20 \x00 \x77 \x4a \x00
DevNonce\x54 \x7b
MIC\x40 \x2d \xe1 \x9a
-

可以得到DevNonce的值为0x7b54

-

提取AppNonce、NetID、CFList

2.NS->GW JSON包,其中txpk.data为包含了MAC层数据内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"txpk": {
"tmst": 537505620,
"freq": 471.9,
"rfch": 0,
"powe": 14,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"ipol": true,
"size": 17,
"data": "IPqAKXQ7LS/CmYVCDy8K3k4"
}
}

-

data base64 decode:

1
2
3
\x20 \xfa \x80 \x29 \x74 \x3b \x2d \x2f
\xc2 \x99 \x85 \x42 \x0f \x2f \x0a \xde
\x4e

-

根据LoRaWAN specification 可知,join_accept message的格式如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
MHDRAppNonceNetIDDevAddrDLSettingsRxDelayCFList(pad16)MIC
1字节3字节3字节4字节4字节1字节0/16字节4字节
-

但是这个数据是加密的,需要使用AppKey进行解密

-

所以,我们需要先使用AppKey解密join_accept message

-

payload为join_accept message,此处为

1
2
3
\x20 \xfa \x80 \x29 \x74 \x3b \x2d \x2f
\xc2 \x99 \x85 \x42 \x0f \x2f \x0a \xde
\x4e

-

解密之后的数据存放在LoRaMacRxPayload数组中

-
1
2
3
4
5
uint8_t LoRaMacAppKey[] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
LoRaMacRxPayload[0] = payload[0];
-

可以得到解析之后的数组

1
2
3
0x20 0x43 0x75 0xcb 0x24 0x0 0x0 0x2
0x0 0x0 0x48 0x3 0x0 0x82 0xc9 0xd0
0xf9

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段解密前解密后
MHDR\x20\x20
AppNonce\xfa \x80 \x29\x43 \x75 \xcb
NetID\x74 \x3b \x2d\x24 \x0 \x0
DevAddr\x2f \xc2 \x99 \x85\x2 \x0 \x0 \x48
DLSettings\x42\x3
RxDelay\x0f\x0
CFList(pad16)
MIC\x2f \x0a \xde \x4e\x82 \xc9 \xd0 \xf9
-

根据协议,我们可以得到:

-
1
2
3
4
AppNonce:\x43 \x75 \xcb
NetID:\x24 \x0 \x0
DevNonce:0x7b54
pad16:没有
-

至此,我们就具备生成密钥的所有参数了

-

产生AppSKey 和 NwkSKey

最后,我们再调用

1
LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );

-

就可以生成AppSKey和NwkSKey了。

-

得到的NwkSKey为

1
2
0xde 0x3 0x33 0x1a 0xeb 0x42 0x54 0xe9
0x72 0x7b 0x6f 0xaf 0xbf 0x13 0xdb 0x3d

-

得到的AppSKey为

1
2
0xe0 0x46 0x9e 0x44 0x9c 0x57 0x47 0x8c
0xbe 0xa7 0x25 0xda 0x84 0xf0 0x13 0x97

-

对比之间抓包的AS->NS的入网信息

-

AS->NS 发送入网信息,可以知道,生成的密码是正确的了。

1
2
3
4
5
6
7
8
9
{
"join": {
"moteeui": "4a770020161016",
"complete": {
"frame": "IPqAKXQ7LS/CmYVCDy8K3k4",
"networkkey": "de03331aeb4254e9727b6fafbf13db3d"
}
}
}

-

当然最好是进行实际负载的验证,我也写了两个小程序进行了验证,证明了这两个Key确实是正确的。

-

两个小程序的链接:

- -

至此,我所知的OTAA入网方面的协议就完了。

-

如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

-]]>
-
- - - <![CDATA[LoRaWAN协议(五)__OTAA入网方式详述]]> - http://yoursite.com/2016/11/27/LoRaWAN%E5%8D%8F%E8%AE%AE(%E4%BA%94)__OTAA%E5%85%A5%E7%BD%91%E6%96%B9%E5%BC%8F%E8%AF%A6%E8%BF%B0/ - 前言

OTAA(Over-The-Air Activation),是LoRaWAN的一种空中入网方式。当node在上电的时候处于非入网状态时,需要先入网才能和服务器进行通信。其操作就是node发送join_request message,请求入网,然后服务器同意入网,并且返回Join-accept message,node再对信息进行解析,获取通信参数,这样就可以和服务器通信了。

-

顺便分享几个工具网站给大家:

-
    -
  1. HEX/字符串转换
  2. -
  3. JSON校验
  4. -
  5. BASE64编码/解码
  6. -
-

OTAA方式入网步骤

准备工作

node端在做OTAA入网之前,需要先具备三个参数:

-
    -
  • APPEUI node自定义的8字节长地址
  • -
  • APPKEY 网络统一的KEY,服务器和node端都事先存好
  • -
  • DevNonce 2字节的随机数,用于生成随机的AppSKey和NwkSKey
  • -
-

这些参数可以通过程序固话在里面,或者通过串口或其他方式在入网操作前告诉node。

-

当这些准备工作都做好了之后,node设备就能够入网了。

-

第一步

1.node发起入网请求,也就是发送join_request message,

-

根据LoRaWAN specification 可知,join_request message的格式如下:

- - - - - - - - - - - - - - - - - - - -
MHDRAPPEUIDevEUIDevNonceMIC
1字节8字节8字节2字节4字节
-

其中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段描述
MHDR数据包头,其中包含了数据包的类型,也就是说从这个包头可以知道,这是一个join_request message
APPEUI应用EUI
DevEUInode的长地址,由node自己定义
DevNonce一个随机数,用来生成密码
MIC4字节的校验
-

需要注意的是Join_request message是未加密的

-

第二步

2.GW将此数据上传至NS

-

GW对MAC层的数据不进行解析,而是直接将其进行base64编码之后,封装成JSON包上传至NS,MAC层的数据位于rxpk.data

-

样例数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"rxpk": [
{
"tmst": 532505620,
"chan": 6,
"rfch": 0,
"freq": 471.9,
"stat": 1,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"lsnr": -17,
"rssi": -81,
"size": 23,
"data": "AAEAACAAxSYsFhAWIAB3SgBUe0At4Zo="
}
]
}

-

此处,将data进行base64解码,我们就可以看到MAC层数据了,因为join_request message数据是未加密的

-

data部分的内容如下:

1
2
3
\x00 \x01 \x00 \x00 \x20 \x00 \xc5 \x26
\x2c \x16 \x10 \x16 \x20 \x00 \x77 \x4a
\x00 \x54 \x7b \x40 \x2d \xe1 \x9a

-

各部分的内容分别为:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段内容
MHDR\x00
AppEUI\x01 \x00 \x00 \x20 \x00 \xc5 \x26 \x2c
DevEUI\x16 \x10 \x16 \x20 \x00 \x77 \x4a \x00
DevNonce\x54 \x7b
MIC\x40 \x2d \xe1 \x9a
-

第三步

3.NS向AS发送设备入网包

-

样例数据:

-
1
2
3
4
5
6
7
{
"join": {
"request": {
"frame": "AAEAACAAxSYsFhAWIAB3SgBUe0At4Zo"
}
}
}
-

可以看到,原先的MAC 层的data数据没有变化

-

第四步

4.AS同意入网并且向NS回复同意入网

-

样例数据:

1
2
3
4
5
6
{
"join": {
"moteeui": "4a770020161016",
"accept": true
}
}

-

第五步

5.NS生成MoteAddr,并将node端的信息发送给AS

-

样例数据:

1
2
3
4
5
6
7
8
9
10
{
"join": {
"appeui": "2c26c50020000001",
"moteeui": "4a770020161016",
"details": {
"moteaddr": "48000002",
"devicenonce": 31572
}
}
}

-

第六步

6.AS生成密钥,并将相关信息告诉NS

-

样例数据:

1
2
3
4
5
6
7
8
9
{
"join": {
"moteeui": "4a770020161016",
"complete": {
"frame": "IPqAKXQ7LS/CmYVCDy8K3k4",
"networkkey": "de03331aeb4254e9727b6fafbf13db3d"
}
}
}

-

可以看到,networkkey直接发送给NS了,这也就是NwkSKey,
之所以明文告诉NS,是因为:
1.NS不做解密的工作
2.networkkey在校验的时候回使用到

-

第七步

7.NS将数据告诉GW,GW再转换成MAC包,发送给node

-

样例数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"txpk": {
"tmst": 537505620,
"freq": 471.9,
"rfch": 0,
"powe": 14,
"modu": "LORA",
"datr": "SF12BW125",
"codr": "4/5",
"ipol": true,
"size": 17,
"data": "IPqAKXQ7LS/CmYVCDy8K3k4"
}
}

-

需要注意的是,此时的data部分是经过base64编码以及AES加密的,直接解码,看到的数据是无效的,需要再进行解密,解密需要使用APPKEY,也就是之前介绍的统一的网络KEY.

-

txpk.data部分就是LoRaWAN MAC的join_accept message.

-

第八步

8.node解析join_accept message 部分

-

根据LoRaWAN specification 可知,join_accept message的格式如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
MHDRAppNonceNetIDDevAddrDLSettingsRxDelayCFList(pad16)MIC
1字节3字节3字节4字节4字节1字节0/16字节4字节
-

其中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段描述
MHDR数据包头,其中包含了数据包的类型,也就是说从这个包头可以知道,这是一个join_accept message
AppNonce3字节的unique ID,服务器生成的,产生AppSKey/NwkSKey 会用到
NetID网络ID,产生AppSKey/NwkSKey 会用到
DevAddr设备的短地址
DLSettings设置RX1和RX2的下行接受串口的速率
RxDelay从发送完成到打开RX1接受串口的事件
CFList(pad16)我也不知道是什么,目前看到的都是0个字节
MIC4字节的校验
-

需要注意的是Join_accept message是加密的,需要使用APPKEY解密

-

txpk.data:
“data”: “IPqAKXQ7LS/CmYVCDy8K3k4”

-

base64解码:
\x20 \xfa \x80 \x29 \x74 \x3b \x2d \x2f
\xc2 \x99 \x85 \x42 \x0f \x2f \x0a \xde
\x4e

-

这个数据是未解密的,我们还需要解密

-

解密后为
\x20 \x43 \x75 \xcb \x24 \x00 \x00 \x02
\x00 \x00 \x48 \x03 \x00 \x82 \xc9 \xd0
\xf9

-

具体的情况如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段解密前解密后
MHDR\x20\x20
AppNonce\xfa \x80 \x29\x43 \x75 \xcb
NetID\x74 \x3b \x2d\x24 \x0 \x0
DevAddr\x2f \xc2 \x99 \x85\x2 \x0 \x0 \x48
DLSettings\x42\x3
RxDelay\x0f\x0
CFList
MIC\x2f \x0a \xde \x4e\x82 \xc9 \xd0 \xf9
-

可以看到,DevAddr为0x48000002,而AppSKey和NwkSKey无法直接看出来,需要再计算

-

计算公式如下:

-
    -
  • NwkSKey = aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16)
  • -
  • AppSKey = aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)
  • -
-

下一篇文章,我会把这个解密的过程,以及NwkSKey/AppSKey的计算过程,配合C语言,再分析一下。

-

本期的LoRaWAN协议分析就到这里了,如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

-]]>
-
- - - <![CDATA[LoRaWAN协议(四)__入网方式概述]]> - http://yoursite.com/2016/11/26/LoRaWAN%E5%8D%8F%E8%AE%AE(%E5%9B%9B)__%E5%85%A5%E7%BD%91%E6%96%B9%E5%BC%8F%E6%A6%82%E8%BF%B0/ - 前言

在LoRaWAN中,node最终和服务器能够正常数据交互,需要先入网,入网的本质,也就是获得一些通信相关的参数,有以下几个:

-
    -
  1. NWKSKEY
  2. -
  3. APPSKEY
  4. -
  5. DEVADDR
  6. -
  7. DEVEUI
  8. -
-

其中

-
    -
  • NWKSKEY用于数据的校验,也就是说在MIC校验时会用到
  • -
  • APPSKEY用于负载的AES加密,也就是说在加密解密时会使用到
  • -
  • DevAddr是node的短地址,在数据通讯时,使用的是node的短地址
  • -
  • DevEUI 在ABP入网方式的通讯中不会使用,在OTAA方式中会使用到,是由设备在入网前就产生了。在入网时,node将DevEUI上传,然后服务器会将此DevEUI注册并返回一个DevAddr,也就是说DevAddr此时和DevEUI就建立了映射关系,在node后续的通讯中,使用DevAddr。
  • -
-

LoRaWAN入网方式有两种:

-
    -
  1. ABP (Activation By Personalization)
  2. -
  3. OTAA(Over-The-Air Activation)
  4. -
-

下面就讲述一下这两种方式。

-

ABP 概述

ABP方式是事先将入网信息烧写在设备上,也就是说设备上电已经入网了,无需再特意去请求入网。

-

这种方式就不再多说了。

-

OTAA 概述

OTAA方式入网的node,在刚上电的时候,是不处于入网状态的,此时就需要进行入网操作。

-

如果我们简单的把服务器看做一个整体,那么入网操作的流程是这样的:

-
    -
  1. node 发送入网请求,即join_request message
  2. -
  3. GW 收到 node 的数据,上传给服务器
  4. -
  5. 服务器收到入网请求,同意入网,并且将设备在服务器注册,建立长地址与短地址之间的联系,生成通讯密钥,将通讯密钥的参数打包下发给GW,即 Join-accept message
  6. -
  7. GW 收到服务器的数据,下发给 node
  8. -
  9. node 根据下发的数据包,得到 DevAddr、APPSKEY、NWKSKEY
  10. -
-

这篇文章先大概的描述一下两种入网方式

-

详细的关于OTAA的入网方式见下一篇文章,会有OTAA的抓包分析,以及APPSKEY/NWKSKEY的生成过程,并且有C语言的Example。

-

本期的LoRaWAN协议分析就到这里了,如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

-]]>
-
- - - <![CDATA[LoRaWAN协议(三)__Server端数据协议]]> - http://yoursite.com/2016/11/25/LoRaWAN%E5%8D%8F%E8%AE%AE(%E4%B8%89)__Server%E7%AB%AF%E6%95%B0%E6%8D%AE%E5%8D%8F%E8%AE%AE/ - LoRaWAN Server 端架构

LoRaWAN 的server包括 NS(Network server)、AS(application server)、CS(Custom server)….

-

其中NS和AS是比不可少的,是完成LoRaWAN协议的重要组成部分

-

NS 职责

NS是直接与GW通信的服务器,也是AS和GW之间的桥梁

-

我所知道的工作有如下几点:

-
    -
  1. 验证数据的合法性(校验MIC)
  2. -
  3. 从GW的信息中提取数据,整理成NS 的JSON数据包
  4. -
  5. 将校验合法的数据打包成新的JSON包上传至AS
  6. -
  7. OTAA入网时向AS发送请求入网消息,然后再将入网信息告诉AS,当获取AS传来的入网的信息,告诉GW
  8. -
  9. GW 和 AS之间的数据通道
  10. -
-

有几点需要注意的是NS端的数据不进行AES解密工作。

-

AS 职责

AS是server端的数据处理中心

-

它的工作有如下几点:

-
    -
  1. 上行数据的解密
  2. -
  3. 下行数据的加密
  4. -
  5. OTAA入网请求的处理(同意入网/生成APPSKEY/NWKSKEY)
  6. -
-

CS 职责

CS负责将AS给的数据处理成用户自定义的数据协议格式,也就是说,CS端必须是用户来完成的,因为上面运行的是用户的协议。这里也就不再多说了。

-

抓包分析

以下是我在本地服务器端通过抓到得来的数据,我们通过分析数据包来理解数据的走向已及现有的server端处理流程。抓包使用的是tcpdump。

-

1.NS->AS数据
这是一帧从NS->AS的数据,使用的是TCP方式,AS的数据端口为4000。从data部分我们可以看出来,这是一个未解密的数据。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
15:30:53.662471 IP localhost.60795 > localhost.4000: Flags [P.], seq 13:328, ack 14,
win 442, options [nop,nop,TS val 414153 ecr 414145], length 315
0x0000: 4500 016f aee3 4000 4006 8ca3 7f00 0001
0x0010: 7f00 0001 ed7b 0fa0 5505 b988 2261 4f1b
0x0020: 8018 01ba ff63 0000 0101 080a 0006 51c9
0x0030: 0006 51c1 7b22 6170 7022 3a7b 226d 6f74
0x0040: 6565 7569 223a 2234 6137 3730 3032 3031
0x0050: 3631 3031 3622 2c22 6469 7222 3a22 7570
0x0060: 222c 2273 6571 6e6f 223a 3532 332c 2275
0x0070: 7365 7264 6174 6122 3a7b 2270 6f72 7422
0x0080: 3a32 2c22 7061 796c 6f61 6422 3a22 5645
0x0090: 7666 6f56 2b72 6631 5838 4177 316e 6c52
0x00a0: 7077 227d 2c22 6d6f 7465 7478 223a 7b22
0x00b0: 6672 6571 223a 3437 312e 352c 2264 6174
0x00c0: 7222 3a22 5346 3132 4257 3132 3522 2c22
0x00d0: 636f 6472 223a 2234 2f35 222c 2261 6472
0x00e0: 223a 6661 6c73 657d 2c22 6777 7278 223a
0x00f0: 5b7b 2265 7569 223a 2266 6666 6562 3832
0x0100: 3765 6266 3231 6130 3722 2c22 7469 6d65
0x0110: 223a 2232 3031 362d 3131 2d32 3454 3135
0x0120: 3a33 303a 3533 5a22 2c22 7469 6d65 6672
0x0130: 6f6d 6761 7465 7761 7922 3a66 616c 7365
0x0140: 2c22 6368 616e 223a 342c 2272 6663 6822
0x0150: 3a30 2c22 7273 7369 223a 2d37 392c 226c
0x0160: 736e 7222 3a2d 3136 2e35 7d5d 7d7d 00
-

提取其中的数据部分为:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"app": {
"moteeui": "4a770020161016",
"dir": "up",
"seqno": 523,
"userdata": {
"port": 2,
"payload": "VEvfoV+rf1X8Aw1nlRpw"
},
"motetx": {
"freq": 471.5,
"datr": "SF12BW125",
"codr": "4/5",
"adr": false
},
"gwrx": [
{
"eui": "fffeb827ebf21a07",
"time": "2016-11-24T15:30:53Z",
"timefromgateway": false,
"chan": 4,
"rfch": 0,
"rssi": -79,
"lsnr": -16.5
}
]
}
}
-

再把app.userdata.payload 做base64解码之后,得到的payload内容是这个:

-
1
2
3
app.userdata.payload base64 decoded:
\x54 \x4b \xdf \xa1 \x5f \xab \x7f \x55
\xfc \x03 \x0d \x67 \x95 \x1a \x70
-

此时看到的payload因为是加密的,所以完全看不出来数据内容是什么。

-

不过在这里,我们可以看到,NS已经将GW上传的数据做了一定的解析,封装成了另外一种JSON格式,由此,我们不难得出,NS做的工作包括–base64解码/MIC校验/GW数据包的重新组包

-

2.AS->CS数据
这是一帧从AS->CS的数据,使用的是TCP方式,CS的数据端口为5000。从data部分我们可以看出来,这是一个已经解密完成的数据了。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
15:30:53.663219 IP localhost.36774 > localhost.5000: Flags [P.], seq 13:328, ack 13,
win 342, options [nop,nop,TS val 414153 ecr 414140], length 315
0x0000: 4500 016f 928b 4000 4006 a8fb 7f00 0001
0x0010: 7f00 0001 8fa6 1388 2a2a 93a0 9d70 4aae
0x0020: 8018 0156 ff63 0000 0101 080a 0006 51c9
0x0030: 0006 51bc 7b22 6170 7022 3a7b 226d 6f74
0x0040: 6565 7569 223a 2234 6137 3730 3032 3031
0x0050: 3631 3031 3622 2c22 6469 7222 3a22 7570
0x0060: 222c 2273 6571 6e6f 223a 3532 332c 2275
0x0070: 7365 7264 6174 6122 3a7b 2270 6f72 7422
0x0080: 3a32 2c22 7061 796c 6f61 6422 3a22 4151
0x0090: 4944 4241 5547 4277 674a 4367 734d 4451
0x00a0: 3450 227d 2c22 6d6f 7465 7478 223a 7b22
0x00b0: 6672 6571 223a 3437 312e 352c 2264 6174
0x00c0: 7222 3a22 5346 3132 4257 3132 3522 2c22
0x00d0: 636f 6472 223a 2234 2f35 222c 2261 6472
0x00e0: 223a 6661 6c73 657d 2c22 6777 7278 223a
0x00f0: 5b7b 2265 7569 223a 2266 6666 6562 3832
0x0100: 3765 6266 3231 6130 3722 2c22 7469 6d65
0x0110: 223a 2232 3031 362d 3131 2d32 3454 3135
0x0120: 3a33 303a 3533 5a22 2c22 7469 6d65 6672
0x0130: 6f6d 6761 7465 7761 7922 3a66 616c 7365
0x0140: 2c22 6368 616e 223a 342c 2272 6663 6822
0x0150: 3a30 2c22 7273 7369 223a 2d37 392c 226c
0x0160: 736e 7222 3a2d 3136 2e35 7d5d 7d7d 00
-

提取其中的数据部分为:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"app": {
"moteeui": "4a770020161016",
"dir": "up",
"seqno": 523,
"userdata": {
"port": 2,
"payload": "AQIDBAUGBwgJCgsMDQ4P"
},
"motetx": {
"freq": 471.5,
"datr": "SF12BW125",
"codr": "4/5",
"adr": false
},
"gwrx": [
{
"eui": "fffeb827ebf21a07",
"time": "2016-11-24T15:30:53Z",
"timefromgateway": false,
"chan": 4,
"rfch": 0,
"rssi": -79,
"lsnr": -16.5
}
]
}
}
-

再把app.userdata.payload 做base64解码之后,得到的payload内容是这个:

-
1
2
\x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08
\x09 \x0a \x0b \x0c \x0d \x0e \x0f
-

而此时,数据已经完全解密了,可以看到数据就是在AS解密的,解密完再发送给CS,CS再做进一步用户协议的处理。

-

在这里,我们可以看到,AS已经将NS传输过来的JSON包的payload部分做了解密,然后再传给了CS。所以解密工作是在AS完成的。

-

本期的LoRaWAN笔记就到这里了,如果本文有什么错误,或者对LoRaWAN有什么不理解的,欢迎联系我,邮箱(454626653@qq.com),在左边也有链接,谢谢大家。 -

-]]>
-
- - - <![CDATA[LoRaWAN stack移植笔记(六)]]> - http://yoursite.com/2016/11/03/LoRaWAN%20stack%E7%A7%BB%E6%A4%8D%E7%AC%94%E8%AE%B0(%E5%85%AD)/ - 前言

调试的过程中碰到的问题基本都是以前没有遇到过的,而且需要对整个协议栈及射频方面的工作流程较熟悉才能找到问题的原因,需要多读SX1276的数据手册以及与射频芯片的物理层通信例程和MAC层通信例程进行对比相结合。

-

正文

发送失败

LoRa 模块在进行 模式切换时,比如TX 切换到RX模式,需要先将设备切换到standby模式

-

CRC 校验失败,然后程序陷入死循环

按逻辑来讲,CRC校验失败,应该进行的操作是吧校验失败的这个数据包丢弃,然后重启接收机(芯片每次接收完成都应该重启SX1276)

-

但是,程序一旦接收CRC校验失败就陷入循环,通过调试发现,原来是开启了一个定时器,定时时间为0,然后定时器的处理函数中又开启了此定时器,定时时间依旧没0,所以陷入了死循环。

-

这个定时器就是:

1
TimerStart( &RxTimeoutSyncWord );

-

在接收处理函数void SX1276OnDio0Irq( void ) 中的CRC校验失败分支的处理代码中,以及定时器对应的处理函数void SX1276OnTimeoutIrq( void )中都开启了这个定时器。
如果是单个接收模式下,开启这个定时器并没有什么问题,但是在我调试的代码中,我开始的是连续接收模式,此模式根本没有同步字接收超时继续开着接收模式就可以了,并不需要特别的处理,可以不需要处理,
而官方SDK中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
void SX1276OnDio0Irq( void )
{
.........
if( SX1276.Settings.Fsk.CrcOn == true )
{
irqFlags = SX1276Read( REG_IRQFLAGS2 );
if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK )
{
// Clear Irqs
SX1276Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
RF_IRQFLAGS1_PREAMBLEDETECT |
RF_IRQFLAGS1_SYNCADDRESSMATCH );
SX1276Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
TimerStop( &RxTimeoutTimer );
if( SX1276.Settings.Fsk.RxContinuous == false )
{
TimerStop( &RxTimeoutSyncWord );
SX1276.Settings.State = RF_IDLE;
}
else
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError != NULL ) )
{
RadioEvents->RxError( );
}
SX1276.Settings.FskPacketHandler.PreambleDetected = false;
SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
SX1276.Settings.FskPacketHandler.NbBytes = 0;
SX1276.Settings.FskPacketHandler.Size = 0;
break;
}
}
..........
}
void SX1276OnTimeoutIrq( void )
{
switch( SX1276.Settings.State )
{
case RF_RX_RUNNING:
if( SX1276.Settings.Modem == MODEM_FSK )
{
SX1276.Settings.FskPacketHandler.PreambleDetected = false;
SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
SX1276.Settings.FskPacketHandler.NbBytes = 0;
SX1276.Settings.FskPacketHandler.Size = 0;
// Clear Irqs
SX1276Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
RF_IRQFLAGS1_PREAMBLEDETECT |
RF_IRQFLAGS1_SYNCADDRESSMATCH );
SX1276Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
if( SX1276.Settings.Fsk.RxContinuous == true )
{
// Continuous mode restart Rx chain
SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
TimerStart( &RxTimeoutSyncWord );
}
else
{
SX1276.Settings.State = RF_IDLE;
TimerStop( &RxTimeoutSyncWord );
}
}
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
{
RadioEvents->RxTimeout( );
}
break;
................
}
}

-

这两处代码有着类似的才做,但是RxTimeoutSyncWord这个定时器会进入void SX1276OnTimeoutIrq( void )这个函数,而这个函数中又会重新开启RxTimeoutSyncWord这个定时器,导致死循环,所以在这里,应该讲两处的开启定时器的操作去掉(TimerStart( &RxTimeoutSyncWord );),这样程序逻辑才正常。

-

CRC 校验失败,然后在单步模式下,CRC一直失败

这个问题不是程序的问题,原因是因为我在单步模式下看CRC做接收,然后我的单步调试打断了射频芯片的正常工作。嗯、、就是这样,这个故事告诉我们,不要手贱。

-]]>
-
- - - <![CDATA[LoRaWAN stack移植笔记(五)__杂七杂八的问题]]> - http://yoursite.com/2016/10/27/LoRaWAN%20stack%E7%A7%BB%E6%A4%8D%E7%AC%94%E8%AE%B0(%E4%BA%94)__%E6%9D%82%E4%B8%83%E6%9D%82%E5%85%AB%E7%9A%84%E9%97%AE%E9%A2%98/ - 先废话一小段

在将LoRaWAN的程序移植的过程中,调试发现了很多的问题。

-

做好记录工作,防止以后再踩坑

-

移植使用的是LoRaMac-node库,使用的是STM32L151CBT6 MCU,需要要移植到STM32L051C8T6 这个MCU上面。

-

开始正文

JLink的配置

由于第一次使用JLink(SWD方式),在一开始使用时,踩了几处坑:

-
    -
  1. KEIL选择JLINK之后,点击设置进入,会出现一个对话框,要选择NO
  2. -
-

-
    -
  1. KEIL里面JLINK的 方式要选择SW,不然认不到芯片

    -
  2. -
  3. Flash download要选择对应大小的芯片,注意Flash的大小要选择正确

    -
  4. -
-

程序无法进入main,甚至一个函数都没有跑

当配置完JLink之后,程序可以正常烧写调试了,但是问题又出现了,无法跑进main函数,再进一步调试,发现来一个函数都没有执行,直接就进入进入死循环了(通过单步调试看上面的汇编代码)。这个现象就很奇怪了,以前也没有碰到过。
因为3.3V和GND是正常的,这样就算晶振有问题,也会执行程序到配置晶振才会出问题,而不是一句函数都没有执行。
后来顿悟,大概是BOOT0没接,仔细一看原理图,果然BOOT0是悬空的,飞线焊上之后,问题终于得到了解决。

-
NOTE:画原理图时一定要主要,BOOT0一定要接地,这样程序才能正常从FLASH启动
-

RTC定时链表的配置

官方的库中使用了RTC来作为定时器来处理一些定时的事件,这也是库中唯一的任务调度机制。所以保证这个机制的正常运行非常重要。

-

但是,当我把一切参数都配置完成之后,却发现,RTC的定时器不听使唤,经常不进入中断,初步诊断是写入寄存器的定时时间出了问题,但是却找不到出问题的原因。

-

这个问题也是非常的诡异,至今还未发现原因。

-

但是在一次偶然的调试中,我将原本处于

1
static void RtcStartWakeUpAlarm( uint32_t timeoutValue )

-

这个函数中的

1
2
3
RtcCalendar_t now;
RtcCalendar_t alarmTimer;
RTC_AlarmTypeDef alarmStructure;

-

这三个变量由局部变量改为了全局变量,问题就得到了解决。

-

但是原因还未发现。原本以为是变量未赋初值就使用,但是程序中都有在使用前赋初值,具体原因不明。

-

程序进入Default_handler

在调试程序的时候,程序又出现跑死的情况,然后单步调试发现程序进入了Default_handler这里,始终无法跑出来。

-

然后通过搜索得知,进入这里的情况应该是发生了中断但是没有处理,然后程序一直进入中断。

-

后来查看代码发现,由于Cotex-M3和cotex-M0的核,对GPIO的中断的入口是不一样的,在移植时需要做修改,在做了修改之后,程序终于跑正常了。

-

无法点对点通信

需要注意的是,点对点通信中,能够建立条件需要两个点的通信参数配置成相同。

-

特别注意的是iqInverted preamble SYNCWORD

-
note:
-1. 如果发射方使能了iqInverted,那么接收方也要使能iqInverted    
-2. 接收方的preambleLen必须设置大于发射方,否则有很大可能接收不到(偶尔可以收到,但是接收成功率很低)
-3. 发射方和接收方的SYNCWORD必须设置一样(同步字一样),否则认为是不同网络
-

接收机在接收检测时,会先检测前导码的长度,小于设置的最大接收长度时再检测同步字的内容,看是否一致,都符合时,才会接收负载的内容。

-]]>
-
- - - <![CDATA[LoRaWAN__specification_数据收发机制]]> - http://yoursite.com/2016/10/20/LoRaWAN_ClassA_C_%E6%95%B0%E6%8D%AE%E6%94%B6%E5%8F%91%E6%9C%BA%E5%88%B6/ - 终端数据发送

由于LoRaWAN的gw具有49个LoRa的解调器,其配置成8通道,每个通道支持6种速度(DR0-DR5) 8*6 = 48

-

所以,只要在设置的8个通道内,以任何的速度发送都可以,只要满足占空比的要求即可。

-

终端数据接收

由于终端的射频芯片是半双工的,出于省电的考虑,LoRaWAN对终端的接收做了很多的规定(因为接收不是终端自主控制的,长时间的等待会增加终端的功耗)。

-

CLASS A RX

在LoRaWAN specification中,关于Class A的描述如下

-

CLASS A的接收方式是LoRaWAN的三种接收方式中最省电的

-

终端在发送完上行数据之后,会开启两个接收窗口期,RX1 和 RX2 ,其中RX1会在发送完成之后RECEIVE_DELAY1(s)之后开启,RX2会在发送完成之后RECEIVE_DELAY2(S)之后开启。

-

RX1的接收频点和上行时用的发送频点相同,接收的速率和发送速率存在一定的映射关系。默认情况下,接收速率和上一次上行的速率是一样的。

-

RX2的接收频点和速率是固定的。也可以通过MAC COMMAND修改。

-

其中地区不同,默认的接收频点和速率也会不一样。

-

CLASS C RX

CLASS C的设备除了在发送期间,其他时间都处于接收模式,也就是除了Transmit Time On Air 之外,几乎其他时间都是在接收。

-

接收的窗口和频点是RX2的接收串口和频点,是一个固定值。

-

由图可知,CLASS C的接收窗口是在CLASS A的基础上的,即在CLASS A的设备休眠时间打开RX2接收窗口:

-
    -
  1. 首先在RECEIVE_DELAY1这段时间里面打开接收窗口,而CLASS A的设备在这段时间里面是做休眠的,
  2. -
  3. 然后RECEIVE_DELAY1之后打开RX1的接收窗口,再在设备发送完成过了RECEIVE_DELAY2(S)之后,打开RX2接收窗口,之后一直开着RX2的接收窗口,直到设备需要切换到发送状态。
  4. -
-]]>
-
- - - <![CDATA[LoRaWAN协议(二)__ADR]]> - http://yoursite.com/2016/10/17/LoRaWAN_specification_ADR/ - LoRaWAN ADR机制

LoRa network allows the end-devices to individually use any of the possible data rates. This feature is used by the LoRaWAN to adapt and optimize the data rate of static end-devices. This is referred to as Adaptive Data Rate (ADR) and when this is enabled the network will be optimized to use the fastest data rate possible.

-

LoRa网络允许终端设备单独地使用任何可能的数据速率.LoRaWAN使用这个特性去匹配并且优化静态终端的数据速度。这个叫做自适应数据速率(ADR),并且当他使能的时候,网络可能被优化到最快的数据速率。

-

Mobile end-devices should use their fixed default data rate as data rate management is not practical when the moving end-device causes fast changes in the radio environment.

-

当设备处于移动中造成无线电环境快速变化时,移动终端设备应当使用固定的默认的数据速率,因为数据速率管理不是很靠谱。

-

If the ADR bit is set, the network will control the data rate of the end-device through the appropriate MAC commands. If the ADR bit is not set, the network will not attempt to control the data rate of the end-device regardless of the received signal quality. The ADR bit may be set and unset by the end-device or the Network on demand. However, whenever possible, the ADR scheme should be enabled to increase the battery life of the end-device and maximize the network capacity.

-

如果ADR位被设置了,网络会通过适当的MAC层命令来控制终端设备的数据速率。如果ADR位没有被设置,网络不管接收信号的质量如何都不会试图去控制终端设备的数据速率。ADR标志位应当被设置或者不设置根据终端或者网络的需求。然而,无论何时,只要可能,为了增加终端设备的电池使用时间并且最大化网络容量,ADR功能都应当使能。

-

Note: Even mobile end-devices are actually immobile most of the time. So depending on its state of mobility, an end-device can request the network to optimize its data rate using ADR.

-

注意:就算是移动终端设备,实际上大部分时间还是不移动的。所以,终端设备可以使用ADR,根据它的移动情况,请求网络来优化它的数据速率。

-

-

If an end-device whose data rate is optimized by the network to use a data rate higher than its default data rate, it periodically needs to validate that the network still receives the uplink frames. Each time the uplink frame counter is incremented (for each new uplink, repeated transmissions do not increase the counter), the device increments an ADR_ACK_CNT counter.
After ADR_ACK_LIMIT uplinks (ADR_ACK_CNT >= ADR_ACK_LIMIT) without any downlink response, it sets the ADR acknowledgment request bit (ADRACKReq).
The network is required to respond with a downlink frame within the time set by the ADR_ACK_DELAY, any received downlink frame following an uplink frame resets the ADR_ACK_CNT counter.
The downlink ACK bit does not need to be set as any response during the receive slot of the end-device indicates that the gateway has still received the uplinks from this device.
If no reply is received within the next ADR_ACK_DELAY uplinks (i.e., after a total of ADR_ACK_LIMIT + ADR_ACK_DELAY), the end-device may try to regain connectivity by switching to the next lower data rate that provides a longer radio range.
The end-device will further lower its data rate step by step every time ADR_ACK_LIMIT is reached.
The ADRACKReq shall not be set if the device uses its default data rate because in that case no action can be taken to improve the link range.

-

如果终端设备的数据速率被网络优化到大于他的默认速率,那么他需要周期性地去验证网络是否一直收到上行数据帧。
上行数据帧计数器的每一次增长(每一次新的上行帧,重复性的传输不会增长计数器),设备的ADR_ACK_CNT计数器增加。
当ADR_ACK_LIMIT上行帧(ADR_ACK_CNT >= ADR_ACK_LIMIT)没有任何下行回复时,设备设置ADR acknowledgment 请求标志位(ADRACKReq)。
网络必须在设定的ADR_ACK_DELAY时间内回复一个下行帧,任何伴随着上行帧接收到的下行帧都会复位ADR_ACK_CNT计数器。
在设备的接收缝隙期间,任何回复的下行的ACK标志位不需要被设置来指示网关一直接收到这个设备的上行数据帧。
如果在接下来的ADR_ACK_DELAY个上行帧内没有收到回复(例如,在一整个ACR_ACK_LIMIT+ADR_ACK_DELAY),设备会尝试回复链接通过切换到相邻的低一级的速度,因为那提供了更远的无线距离。
终端设备将会进一步的降低它的速率一步一步每当ADR_ACK_LIMIT的次数限制到达。
ADRACKReq不应该被设置如果设备使用默认的速率,因为在这种情况下,没有任何操作可以提高链接的范围。

-

Note: Not requesting an immediate response to an ADR acknowledgement request provides flexibility to the network to optimally schedule its downlinks.
注意: ADR ACK不要求立即回复,网络对他的下行帧提供了弹性的优化计划。

-

Note: In uplink transmissions the ADRACKReq bit is set if ADR_ACK_CNT >= ADR_ACK_LIMIT and the current data-rate is greater than the device defined minimum data rate, it is cleared in other conditions.
注意:在上行的传输中,如果ADR_ACK_CNT>=ADR_ACK_LIMIT并且当前的速率高于设备定义的最小速率,此时ADRACKReq标志位被设置,那么他会在其他情况下被清除掉。

-]]>
-
- - - <![CDATA[LoRaWAN协议(一)__MAC Message Format]]> - http://yoursite.com/2016/10/17/LoRaWAN_specification_message_format/ - Radio Message & PHYPayload

Radion PHY layer 是无线数据包的底层,PHYPayload开始就是LoRaWAN的数据协议封装

-

可见PHYPayload是由三部分组成的。MHDR是MAC层的header,MACPayload是MAC层的负载部分,MIC是校验位(4个字节)

-

MHDR

-

MHDR共一个字节,其中高3位表示消息类型,低2位表示协议的版本号,中间三个位保留

-

MType

-

一共有8种,其中还是一种是预留的

-

Major

-

MACPayload

-

其主要包含FHDR、FPort、FRMPayload

-

FHDR

-

DevAddr是设备的32位唯一ID,FCtrl存储的是帧的一些控制信息,包括ADR信息,ACK信息以及FOptsLen,FCnt是16位的数据帧的计数,FOpts存储的是数据控制命令的信息。

-

FOpts的控制命令有如下几种:

-

-

FPort

-

FRMPayload

-

FRMPayload是数据帧的负载部分,其负载会使用AES128加密,所以在传输的过程中看不到负载的本身。

-

需要注意的是FRMPayload需要在计算MIC之前进行加密。

-

MIC

-

MIC是数据帧的32位校验位,其中参与校验的是MHDR、FHDR、FPort、FRMPayload。

-

校验的方法如上如所示,使用的是AES128加密算法,在计算完成之后取出前4个字节。

-]]>
-
- - - <![CDATA[LoRaWAN_stack移植笔记(四)__RTC]]> - http://yoursite.com/2016/10/14/LoRaWAN_stack%E7%A7%BB%E6%A4%8D%E7%AC%94%E8%AE%B0%20(%E5%9B%9B)__RTC/ - stm32相关的配置

由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱动所以做修改。

-

RTC 的配置

此例程中,RTC被当做定时器使用,用于定时执行任务。

-

例程中,RTC使用外部LSE的32.768Khz的晶振作为时钟源,
而在本设计中,使用内部LSI作为RTC的时钟源,需要重新设置RTC的分频参数,使得程序正常运行。

-

根据Fck_spre = Frtcclk/(PREDIV_S+1)/(PREDIV_A+1)
例程中RTC的工作频率为32.778/(3+1)/(3+1) = 2.048Khz,

-

而内部晶振的频率约为37Khz,故PRVEDIV_S和PREDIV_A的值需要改变。

-
37/2.048 ~= 18;
-数据手册里面有这样一句话:    
-Note: When both prescalers are used, it is recommended to configure the asynchronous 
-prescaler to a high value to minimize consumption.
-所以:18 = 9*2;故设置PREDIV_A = 8,PREDIV_S = 1;
-

由于
37/18 ~= 2.055
1/2.055 ~= 0.486618

-

故此处的宏定义需要稍作修改

1
2
3
4
5
/*!
* RTC Time base in ms
*/
#define RTC_ALARM_TICK_DURATION 0.486618 // 1 tick every 466us
#define RTC_ALARM_TICK_PER_MS 2.055 // 1/2.055 = tick duration in ms ((37/(8+1)/(2+1)) = 2.055Khz)

-]]>
-
- - - <![CDATA[LoRaWAN_stack移植笔记(三)__SPI]]> - http://yoursite.com/2016/10/14/LoRaWAN_stack%E7%A7%BB%E6%A4%8D%E7%AC%94%E8%AE%B0%20(%E4%B8%89)__SPI/ - stm32相关的配置

由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱动所以做修改。

-

SPI 的配置

SPI使用的是STM32的硬件接口-SPI1 MOSI MISO
可以看到例程中,对SPI接口进行了再一层的封装,封装如下:

1
2
3
4
5
6
7
8
9
10
11
/*!
* SPI driver structure definition
*/
struct Spi_s
{
SPI_HandleTypeDef Spi;
Gpio_t Mosi;
Gpio_t Miso;
Gpio_t Sclk;
Gpio_t Nss;
};

-

其中:

1
SPI_HandleTypeDef Spi;

-

是原先的STM32Cube库的封装,在此基础上,将SPI的引脚也封装进了自定义的Spi_s结构体中。这样,查看结构体就可以看到SPI的所有情况。

-

SPI 初始化配置

初始化的函数体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss )
{
__HAL_RCC_SPI1_FORCE_RESET( );
__HAL_RCC_SPI1_RELEASE_RESET( );
__HAL_RCC_SPI1_CLK_ENABLE( );
obj->Spi.Instance = ( SPI_TypeDef *) SPI1_BASE;
GpioInit( &obj->Mosi, mosi, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF0_SPI1 );
GpioInit( &obj->Miso, miso, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF0_SPI1 );
GpioInit( &obj->Sclk, sclk, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, GPIO_AF0_SPI1 );
if( nss != NC )
{
GpioInit( &obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF0_SPI1 );
}
else
{
obj->Spi.Init.NSS = SPI_NSS_SOFT;
GpioInit( &SX1276.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
}
if( nss == NC )
{
SpiFormat( obj, SPI_DATASIZE_8BIT, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 0 );
}
else
{
SpiFormat( obj, SPI_DATASIZE_8BIT, SPI_POLARITY_LOW, SPI_PHASE_1EDGE, 1 );
}
obj->Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
HAL_SPI_Init( &obj->Spi );
}
``` c
SPI的初始化函数是这样被调用的:
``` c
SpiInit( &SX1276.Spi, RADIO_MOSI, RADIO_MISO,RADIO_SCLK, NC );
//初始化函数的原型
void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss );

-

其中引脚定义是这样的

1
2
3
4
#define RADIO_MOSI PA_7
#define RADIO_MISO PA_6
#define RADIO_SCLK PA_5
#define RADIO_NSS PA_4

-

可以看到SPI的MOSI/MISO/SCLK脚都有看到,但是NSS脚看到,而是传了NC。

-

这是为什么呢?
可以看到程序里面有段话

1
2
3
4
5
6
7
8
9
if( nss != NC )
{
GpioInit( &obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF0_SPI1 );
}
else
{
obj->Spi.Init.NSS = SPI_NSS_SOFT;
GpioInit( &SX1276.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
}

-

其意思就是设置为NC就配置NSS 为软件控制,即NSS脚只做片选使用,x像GPIO一样控制他拉高拉低就可以控制片选的使能与否了。

-

还有一处,设置SPI的工作频率的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SpiFrequency( obj, 10000000 );
void SpiFrequency( Spi_t *obj, uint32_t hz )
{
uint32_t divisor;
divisor = SystemCoreClock / hz;
// Find the nearest power-of-2
divisor = divisor > 0 ? divisor-1 : 0;
divisor |= divisor >> 1;
divisor |= divisor >> 2;
divisor |= divisor >> 4;
divisor |= divisor >> 8;
divisor |= divisor >> 16;
divisor++;
divisor = __ffs( divisor ) - 1;
divisor = ( divisor > 0x07 ) ? 0x07 : divisor;
obj->Spi.Init.BaudRatePrescaler = divisor << 3;
}

-

由于ffs这个函数只有Cotex-M3以上内核才能调用,但是通过计算可知若传参为10000000,ffs这个函数的返回值为0x03,所以可得obj->Spi.Init.BaudRatePrescaler = 8,即SPI_BAUDRATEPRESCALER_8
因为

1
2
3
#define SPI_BAUDRATEPRESCALER_8 ((uint32_t)SPI_CR1_BR_1)
#define SPI_CR1_BR_1 (0x2U << SPI_CR1_BR_Pos)
#define SPI_CR1_BR_Pos (3U)

-

所以此处设置Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
最后再调用

1
HAL_SPI_Init( &obj->Spi );

-

至此,SPI的初始化就完成了。

-

SPI 读写

接下来就是SPI的读写操作了,由于都是使用的Cube库,对寄存器的命名并没有什么不同,直接保留例程中的代码就可以了。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//获取SPI的标志位状态
FlagStatus SpiGetFlag( Spi_t *obj, uint16_t flag )
{
FlagStatus bitstatus = RESET;
// Check the status of the specified SPI flag
if( ( obj->Spi.Instance->SR & flag ) != ( uint16_t )RESET )
{
// SPI_I2S_FLAG is set
bitstatus = SET;
}
else
{
// SPI_I2S_FLAG is reset
bitstatus = RESET;
}
// Return the SPI_I2S_FLAG status
return bitstatus;
}
//SPI读写
uint16_t SpiInOut( Spi_t *obj, uint16_t outData )
{
uint8_t rxData = 0;
if( ( obj == NULL ) || ( obj->Spi.Instance ) == NULL )
{
assert_param( FAIL );
}
__HAL_SPI_ENABLE( &obj->Spi );
while( SpiGetFlag( obj, SPI_FLAG_TXE ) == RESET );
obj->Spi.Instance->DR = ( uint16_t ) ( outData & 0xFF );
while( SpiGetFlag( obj, SPI_FLAG_RXNE ) == RESET );
rxData = ( uint16_t ) obj->Spi.Instance->DR;
return( rxData );
}
-

在使用上,需要注意NSS引脚的操作,在进行读写前进行使能,读写完毕之后失能。程序如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//SPI写
void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
//NSS = 0;
GpioWrite( &SX1276.Spi.Nss, 0 );
SpiInOut( &SX1276.Spi, addr | 0x80 );
for( i = 0; i < size; i++ )
{
SpiInOut( &SX1276.Spi, buffer[i] );
}
//NSS = 1;
GpioWrite( &SX1276.Spi.Nss, 1 );
}
//SPI读
void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
//NSS = 0;
GpioWrite( &SX1276.Spi.Nss, 0 );
SpiInOut( &SX1276.Spi, addr & 0x7F );
for( i = 0; i < size; i++ )
{
buffer[i] = SpiInOut( &SX1276.Spi, 0 );
}
//NSS = 1;
GpioWrite( &SX1276.Spi.Nss, 1 );
}

-

至此,LoRaWAN例程中的SPI的移植就完成了。

-]]>
-
- - - <![CDATA[LoRaWAN_stack移植笔记 (二)_GPIO]]> - http://yoursite.com/2016/10/14/LoRaWAN_stack%E7%A7%BB%E6%A4%8D%E7%AC%94%E8%AE%B0%20(%E4%BA%8C)_GPIO/ - stm32相关的配置

由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱动所以做修改。另外例程中对STM32库函数的再一次封装的方法也非常值得学习。

-

GPIO 的配置

1
GpioInit( &obj->Tx, tx, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_UP, GPIO_AF0_USART1 );
-

例程中可以看到,对IO口的初始化只有这一句,是因为例程中对GPIO的操作进行了封装,方便了上层的使用。

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*!
* Board GPIO pin names
*/
typedef enum
{
MCU_PINS,
IOE_PINS,
// Not connected
NC = (int)0xFFFFFFFF
}PinNames;
/*!
* STM32 Pin Names
*/
#define MCU_PINS \
PA_0 = 0, PA_1, PA_2, PA_3, PA_4, PA_5, PA_6, PA_7, PA_8, PA_9, PA_10, PA_11, PA_12, PA_13, PA_14, PA_15, \
PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8, PB_9, PB_10, PB_11, PB_12, PB_13, PB_14, PB_15, \
PC_0, PC_1, PC_2, PC_3, PC_4, PC_5, PC_6, PC_7, PC_8, PC_9, PC_10, PC_11, PC_12, PC_13, PC_14, PC_15, \
PD_0, PD_1, PD_2, PD_3, PD_4, PD_5, PD_6, PD_7, PD_8, PD_9, PD_10, PD_11, PD_12, PD_13, PD_14, PD_15, \
PE_0, PE_1, PE_2, PE_3, PE_4, PE_5, PE_6, PE_7, PE_8, PE_9, PE_10, PE_11, PE_12, PE_13, PE_14, PE_15, \
PF_0, PF_1, PF_2, PF_3, PF_4, PF_5, PF_6, PF_7, PF_8, PF_9, PF_10, PF_11, PF_12, PF_13, PF_14, PF_15, \
PH_0, PH_1, PH_2, PH_3, PH_4, PH_5, PH_6, PH_7, PH_8, PH_9, PH_10, PH_11, PH_12, PH_13, PH_14, PH_15
-

例程中使用Enum定义了64个IO口,其中

-
    -
  • 0-15 表示PA0-15
  • -
  • 16-31表示PB0-15
  • -
  • 32-47表示PC0-15
  • -
  • 48-63表示PD0-15
  • -
  • 64-79表示PE0-15
  • -
  • 80-95表示PF0-15
  • -
  • 96-111表示PH0-15
  • -
-

这样,在定义引脚的时候直接是用Enum变量就可以表示出IO的PIN以及PORT,在完成驱动程序之后,操作引脚非常的方便。

-

例如 使用了一个LED灯,连接的是PB_5,这样我们#define LED PB_5,在程序里面就可以得知使用的是PB口,以及PIN_5,方法如下:

-
由于PB_5 = 16+5 = 21;
-21/16 = 1,得知使用的是PB口,21%16 = 5,得知使用的是PIN_5。
-

其中C语言的时下代码如下,使用(&0xff)以及<<的操作,效率比做除法及取模的效率更高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
void GpioMcuInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, uint32_t value )
{
GPIO_InitTypeDef GPIO_InitStructure;
if( pin == NC )
{
return;
}
obj->pin = pin;
obj->pinIndex = ( 0x01 << ( obj->pin & 0x0F ) );
if( ( obj->pin & 0xF0 ) == 0x00 )
{
obj->port = GPIOA;
__HAL_RCC_GPIOA_CLK_ENABLE( );
}
else if( ( obj->pin & 0xF0 ) == 0x10 )
{
obj->port = GPIOB;
__HAL_RCC_GPIOB_CLK_ENABLE( );
}
else if( ( obj->pin & 0xF0 ) == 0x20 )
{
obj->port = GPIOC;
__HAL_RCC_GPIOC_CLK_ENABLE( );
}
else if( ( obj->pin & 0xF0 ) == 0x30 )
{
obj->port = GPIOD;
__HAL_RCC_GPIOD_CLK_ENABLE( );
}
else
{
obj->port = GPIOH;
__HAL_RCC_GPIOH_CLK_ENABLE( );
}
GPIO_InitStructure.Pin = obj->pinIndex ;
GPIO_InitStructure.Pull = type;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
if( mode == PIN_INPUT )
{
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
}
else if( mode == PIN_ANALOGIC )
{
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
}
else if( mode == PIN_ALTERNATE_FCT )
{
if( config == PIN_OPEN_DRAIN )
{
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
}
else
{
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
}
GPIO_InitStructure.Alternate = value;
}
else // mode ouptut
{
if( config == PIN_OPEN_DRAIN )
{
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
}
else
{
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
}
}
HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
// Sets initial output value
if( mode == PIN_OUTPUT )
{
GpioMcuWrite( obj, value );
}
}

-]]>
-
- - - <![CDATA[STM32_NVIC设置]]> - http://yoursite.com/2016/10/13/STM32_NVIC%E7%9A%84%E9%85%8D%E7%BD%AE/ - 接口
1
2
3
4
5
6
7
8
//设置中断的抢占优先级
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
//使能中断
static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn);
//设置优先级组
static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
-

常用的配置中断优先级的函数就是三个,其中最常用的就是两个:

1
2
3
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn);

-

因为NVIC默认就是是组4,可以不用设置,即四位抢占优先级,0位响应优先级

-

优先级冲突的处理

    -
  • 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断;
  • -
  • 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这个两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;
  • -
  • 如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个;
  • -
-

使用方法

例如:
NVIC_SetPriority(UART1_IRQn,2);

-

NVIC_EnableIRQ(UART1_IRQn);

-

NVIC_SetPriority(UART0_IRQn,9);
NVIC_EnableIRQ(UART0_IRQn);
设置UART1_IRQn的优先级为2,UART0_IRQn的优先级为9,并且使能中断。

-

其中,抢占优先级的数字越低,优先级越高

-]]>
-
- - - <![CDATA[LoRaWAN_stack移植笔记(一)--RF硬件相关]]> - http://yoursite.com/2016/10/11/LoRaWAN_stack%E7%A7%BB%E6%A4%8D%E7%AC%94%E8%AE%B0(%E4%B8%80)_RF%E7%A1%AC%E4%BB%B6%E7%9B%B8%E5%85%B3/ - 和硬件相关的问题

TCXO 的使用

根据SX1276数据手册,

-
    -
  • 如果使用TCXO,则需要配置RegTcxo寄存器为0x19,代码如下

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void SX1276SetTcxoConfig(void)//此函数为自定义的
    {
    SX1276Write( REG_TCXO, 0x19 ); //设置TCXO
    }
    //在初始化中调用
    void SX1276Init( RadioEvents_t *events )
    {
    ...
    SX1276SetTcxoConfig();
    ...
    }
    -
  • -
  • 否则配置为0x09,因为芯片上电默认不使用TCXO,即上电寄存器值即为0x09,所以无需配置

    -
  • -
-

PA_BOOST 引脚的使用

根据sx1276 数据手册

-
    -
  • 如果使用PA_BOOST作为RF输出,则需要配置PaSelect脚为1
  • -
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void SX1276SetTxConfig(......)
{
...
paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1276GetPaSelect( SX1276.Settings.Channel );//选择是否使用PA_BOOST引脚
...
}
//根据具体的电路图不一样,此函数也会币一样,比如低频使用PA_BOOST,高频使用RFO_HF,则函数体如下
uint8_t SX1276GetPaSelect( uint32_t channel )
{
//如果是低频的,使用PA_BOOST,高频使用RFO_HF
if( channel < RF_MID_BAND_THRESH )
{
return RF_PACONFIG_PASELECT_PABOOST;
}
else
{
return RF_PACONFIG_PASELECT_RFO;
}
}
//如果高低频都使用PA_BOOST,则函数体如下
uint8_t SX1276GetPaSelect( uint32_t channel )
{
return RF_PACONFIG_PASELECT_PABOOST;
}
//如果高频使用PA_BOOST,低频使用RFO_LF,则函数体如下
uint8_t SX1276GetPaSelect( uint32_t channel )
{
//如果是高频的,使用PA_BOOST,低频使用RFO_LF
if( channel > RF_MID_BAND_THRESH )
{
return RF_PACONFIG_PASELECT_PABOOST;
}
else
{
return RF_PACONFIG_PASELECT_RFO;
}
}
/*!
* RegPaConfig
*/
#define RF_PACONFIG_PASELECT_MASK 0x7F
#define RF_PACONFIG_PASELECT_PABOOST 0x80
#define RF_PACONFIG_PASELECT_RFO 0x00 // Default
-
    -
  • 否则为0
  • -
-

RXTX switch(接收和发送的天线电路的切换)


在图中可以看到,射频输入和射频输出是不一样的电路,但是用的是一个天线,所以用到了一个射频电路切换的芯片。
在程序中,需要做的就是控制FEM_CPS脚,在RX和TX时进行RF1(RFI)和RF2(RFO)的切换。
由于在设计中兼容高低频,并且使用两个引脚分别控制高频和低频部分的射频部分输入输出的切换,所以在实际使用中需要控制两个引脚。

1
2
3
4
5
6
7
8
9
10
11
12
13
void SX1276SetAntSw( uint8_t rxTx )
{
if( rxTx != 0 ) // 1: TX, 0: RX
{
GpioWrite( &AntSwitchLf, 0 );//切换到低频发射电路
GpioWrite( &AntSwitchHf, 1 );//切换到高频发射电路
}
else
{
GpioWrite( &AntSwitchLf, 1 );//切换到低频接收电路
GpioWrite( &AntSwitchHf, 0 );//切换到高频接收电路
}
}

-

如果只有高频或者低频一个部分,上面的代码只要保留相应的部分即可

-]]>
-
- - - <![CDATA[STM32时钟配置--系统时钟、RTC时钟、IWDG时钟]]> - http://yoursite.com/2016/10/11/STM32%E6%97%B6%E9%92%9F%E6%BA%90%E9%85%8D%E7%BD%AE/ - stm32L0x1的时钟分类


先给大家推荐一个软件STM32CubeMX,上面的那张关于时钟的图就是从这个软件中截图得来的,这个软件还可以查看配置的时钟情况以及时钟树,挺方便的。

-

从图上,可以看出,STM32的始终源一共有HSE、HSI、LSE、LSI、MSI、PLL六种,
其中

-
    -
  • HSE是外部的高速晶振,可以直接使用或者通过PLL倍频,最终输出不能超过32Mhz
  • -
  • HSI是内部的高速RC振荡器,频率为16Mhz,可以直接使用或者通过PLL倍频,最终输出不能超过32Mhz
  • -
  • LSE是外部的低速晶振,可以用于RTC或者IWDG,频率为32.768KH在
  • -
  • LSI是内部的低速RC振荡器,频率约为37KHz
  • -
  • MSI是内部的RC振荡器,其频率编程可调
  • -
  • PLL是一个锁相环,可以将HSE或HSI倍频之后再给系统提供时钟。
  • -
-

其中注意的是,内部时钟的精度都比较差,在对时钟要求比较高的场合,建议使用外部晶振

-

系统时钟源


从图中可以看到,系统时钟的选择有

-
    -
  • MSI(65.536 kHz, 131.072 kHz, 262.144 kHz, 524.288 kHz, 1.048 MHz,
    2.097 MHz (default value) and 4.194 MHz)
  • -
  • HSI(16,16/4)
  • -
  • HSE(1-24MHz)
  • -
  • PLLCLK(HSE/HSI倍频锁相环)
  • -
-

其中PLLCLK是比较常用的一种,可以将HSE或HSI(HSI/4)倍频,然后再给主系统提供时钟。
其计算公式为PLLCLK_OUT = (PLLCLK_SOURCE * PLLMUL / PLLDIV);

-

例如要给系统提供32MHz的晶振,可以

-
    -
  • HSI(16) * 4(PLLMUL) / 2(PLLDIV)
  • -
  • HSE(12) * 8(PLLMUL) / 3(PLLDIV)
  • -
-

以上两种方法只是举个例子,倍频的方法并不是固定的。

-

注意,实际使用中,这四个时钟源只能同时选择一个,不能同时选择多个。

-

RTC时钟源 IWDG 时钟源

-

从图中可以看到,IWDG只能使用LSI提供时钟源
而RTC可以使用HSE/32(数据手册上查看得来,软件存在明显错误)、LSE、LSI提供时钟源,其中LSE 的频率为32.768KHz,LSI的频率为37KHz。

-

具体的RTC和IWDG的工作时钟还要进行分频。
RTC的工作时钟的计算方法为:Fck_spre = Frtcclk/(PREDIV_S+1)/(PREDIV_A+1);

-

例如Frtcclk(时钟源频率)为32.768Khz的LSE,PREDIV_S = 3, PREDIV_A =3,则Fck_spre(工作频率) = 32.768/(3+1)/(3+1) = 2.048KHz

1
2
3
4
5
6
7
8
9
10
11
12
13
void RtcInit( void )
{
...
RtcHandle.Init.AsynchPrediv = 3;
RtcHandle.Init.SynchPrediv = 3;
...
}
/*!
* RTC Time base in ms
*/
#define RTC_ALARM_TICK_DURATION 0.48828125 // 1 tick every 488us
#define RTC_ALARM_TICK_PER_MS 2.048 // 1/2.048 = tick duration in ms

-]]>
-
- - - <![CDATA[LoRaWAN源码阅读笔记————RTC闹钟链表的实现]]> - http://yoursite.com/2016/10/10/semtech_LoRaWAN_timer/ - 近日在阅读semtech的Lora-net/LoRaMac-node。此代码是LoRaWAN MAC层的node段的代码。

-

此代码中构建了一个定时器链表,此链表构建得非常的巧妙。
通过对源码的阅读,明白了其底层的实现原理,现在讲解一下,和大家分享。

-

此定时器链表底层使用的是RTC的闹钟(Alarm)机制(将日历时间转换成时间戳时间),而非使用一个定时器产生一个固定的定时(比如1ms),然后定时刷新整个链表。

-

用rtc的方法相比较嘀嗒定时器定时的方法,工作效率会明显提升,并不会因为链表中定时器数目的增加使得花费在刷新定时器上的时间增加,因为不需要遍历整个链表。但代码的实现难度会较高

-

假如程序刚开始执行,而且定时器链表为空,此时有4个定时事件需要放入链表,分别为 A 10ms B 30ms C 20ms D 40ms,

-

RTC闹钟链表:
其存储的结果会是这样:

- - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A10
C10
B10
D10
-

而嘀嗒定时链表:
其存储的结果会是这样:

- - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A10
B30
C20
D40
-

当时间过了5ms,RTC闹钟链表中存储的数据并不会发生任何变化,因为它是以RTC的闹钟来作为刷新依据的,而嘀嗒定时链表中的数据就全发生了变化
嘀嗒定时链表 变化得到情况如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A5
B25
C15
D35
-

再过5ms,此时A事件的定时时间就到了,需要被执行,在RTC闹钟链表中的表现是RTC Alarm中断触发,在嘀嗒定时链表中的表现是A事件的定时时间逐渐减少至0。当A事件被执行之后两种定时器链表中的存储都发生了变化,都是原先的链表的头指针指向原先的第二个节点,而原先的头节点被释放。

-

还是上述的例子,在定时器执行了7ms的时候,这时有个事件需要插入,为E 24ms,此时,两种链表对于此事件器的插入操作也会明显不同。

-

RTC闹钟插入之后

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A10
C10
B10
E1
D9
-

而嘀嗒定时器在插入之后为

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
事件名称定时时间
A3
B13
C23
D33
E24
-

以下是RTC闹钟的部分插入代码,其中可以看到他的定时器插入的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
elapsedTime = TimerGetValue( );//获取距离上一次设置闹钟的时间
remainingTime = TimerListHead->Timestamp - elapsedTime;//remainingTime表示剩余的头节点中的事件剩余的定时事件,因为此链表是按顺序存储的,所以头节点中的定时时间一定是最少的
static void TimerInsertNewHeadTimer( TimerEvent_t *obj, uint32_t remainingTime )
{
TimerEvent_t* cur = TimerListHead;
if( cur != NULL )//表头不为空,将新的定时器插入之前,将原先表头的定时器时间减去新定时器的定时时间,确保原先的定时器任务定时正常
{
cur->Timestamp = remainingTime - obj->Timestamp;
cur->IsRunning = false;
}
obj->Next = cur;
obj->IsRunning = true;
TimerListHead = obj;
TimerSetTimeout( TimerListHead );//设置超时,等时间到的时候,会发生RTC报警
}

-

另外还有一点,此RTC中的1s并非物理时间的1s,在此具体的时间基准如下:
此项目中,使用的RTC的时钟源为32.768Khz的LSE,通过AsynchPrediv和SynchPrediv分频得到2.048KHz的RTCtick,计算公式为32.768/(3+1)/(3+1) = 2.048;
相关的配置代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
void RtcInit( void )
{
...
RtcHandle.Init.AsynchPrediv = 3;
RtcHandle.Init.SynchPrediv = 3;
...
}
/*!
* RTC Time base in ms
*/
#define RTC_ALARM_TICK_DURATION 0.48828125 // 1 tick every 488us
#define RTC_ALARM_TICK_PER_MS 2.048 // 1/2.048 = tick duration in ms

-

由于原本每个tick相当于1s,而在这里,每个tick相当于0.48828125ms,小于1ms,所以在程序中能够实现ms级的定时任务。

-

RTC定时器的用法主要分为三步:

-
1. 初始化,注册回调函数
-    void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) )//设置回调函数
-2. 设置定时时间
-    void TimerSetValue( TimerEvent_t *obj, uint32_t value )
-3. 开启定时时间
-    void TimerStart( TimerEvent_t *obj )
-
]]>
-
- - - <![CDATA[LoRaWAN架构解析(二)--LoRaWAN MAC解析]]> - http://yoursite.com/2016/07/29/LoRaWAN%E5%8D%8F%E8%AE%AE(%E4%BA%8C)--LoRaWAN%20MAC%E8%A7%A3%E6%9E%90/ - 名词解析

上行:终端的数据发送经过一个或多个网关中转到达网络服务器。
下行:由网络服务器发送给终端设备,每条消息对应的终端设备是唯一确定的,而且只通过一个网关中转。

-

LoRaWAN Classes

LoRaWAN Classes 一共分为3类:Class A,Class B,Class C

-

Class A:终端先发送,在发送后开启一段时间的接收窗口,终端只有在发送后才可以接收。也就是说上行没有限制,下行的数据只有在上行包发送上来的时候终端才可以接收到。(功耗最低)

-

Class B:终端和服务器协商好接收的窗口开启的时间以及何时开启,然后再约定的时间进行接收,可以一次接收多个包。(功耗次低)

-

Class C:终端在发送以外的其他时间都开启接收窗口。更耗能,但通讯延时最低。(功耗最高)

-

PHY 层数据链路

上行链路消息:

-

上行链路消息:

-

其中上行最后还有CRC校验,而下行没有CRC校验。其中PHDR PHDR_CRC CRC都是射频芯片用于校准数据的完整新和一致性用的,并非用户生成的数据。

-

MAC 层数据链路

-

由上图可以看到,MAC数据是是作为PHYPayload存在的
其中MAC 层的包有三个部分组成:

-
    -
  • MHDR(MAC层帧头)
  • -
  • MACPayload(MAC层负载)
  • -
  • MIC(4字节的校验)
  • -
-

而MACPayload又由三个部分组成:

-
    -
  • FHDR (MAC层负载头)
  • -
  • FPORT(MAC 层数据的通道号)
  • -
  • FRMPayload(MAC层负载,加密)
  • -
-

而FHDR又由由四个部分组成:

-
    -
  • DevAddr(终端的ID 4字节)
  • -
  • FCtrl(帧的控制字 1个字节)
  • -
  • FCnt (帧的序号 2个字节)
  • -
  • FOpts(帧配置,字节数不定,大部分情况0个字节)
  • -
-

所以,由协议可知,一个上行包或者下行包中的数据内容有哪些,抛开控制命令不说,主要有终端的ID、包的序号、用户的加密负载。

-

例如我抓到的一个数据包:

-

\x40 \x7f \xf8 \x8a \x29 \x80 \x2a \x00 \x02 \x07 \x42 \x87 \x3f \xc7 \xb4 \x22 \x04 \x00 \x84 \x8d \x1b \x06 \x2f \x5b \xbc \x57 \xdb \xf2 \x31 \xde \x49 \x61 \x00 \x86 \x99 \xec \x08 \x61 \xf0 \xb7 \xda \x54 \x0a \xfa \xd1 \x31 \xac \xd0 \x44 \x1b \x4d \xfa \x48 \x77 \x19 \xee \x61 \x14 \xbf \x23 \x52 \xd1 \xe9 \x93 \x79 \x6e \x16 \xd7 \x13 \x2e \x58 \x06 \x54 \xc3 \xd2 \x04 \xba \x52 \xa7 \xc8 \x7a \x0b \x8e

-

这是一个MAC 层的帧即完整的MACPayload部分

-

其中

-
    -
  • MHDR:
    \x40
  • -
  • MACPayload-FHDR-DevAddr:
    \x7f \xf8 \x8a \x29
  • -
  • MACPayload-FHDR-FCtrl:
    \x80
  • -
  • MACPayload-FHDR-FCnt:
    \x2a \x00
  • -
  • MACPayload-FPORT:
    \x02
  • -
  • MACPayload-FRMPayload(加密):
    \x07 \x42 \x87 \x3f \xc7 \xb4 \x22 \x04 \x00 \x84 \x8d \x1b \x06 \x2f \x5b \xbc \x57 \xdb \xf2 \x31 \xde \x49 \x61 \x00 \x86 \x99 \xec \x08 \x61 \xf0 \xb7 \xda \x54 \x0a \xfa \xd1 \x31 \xac \xd0 \x44 \x1b \x4d \xfa \x48 \x77 \x19 \xee \x61 \x14 \xbf \x23 \x52 \xd1 \xe9 \x93 \x79 \x6e \x16 \xd7 \x13 \x2e \x58 \x06 \x54 \xc3 \xd2 \x04 \xba \x52 \xa7
  • -
  • MIC:
    \xc8 \x7a \x0b \x8e
  • -
-]]>
-
- - - <![CDATA[MPU9250调试]]> - http://yoursite.com/2016/07/26/MPU9250%E8%B0%83%E8%AF%95/ - MPU9250 芯片概述

MPU9250芯片是一个9轴姿态传感芯片,其中包含了3轴加速度传感器、3轴角速度传感器以及三轴磁力计。
其本质上是MPU6050芯片+AK8963。

-

可以获取传感芯片的加速度、角速度、以及磁力值。

-

角速度可以知芯片的转动速度,加速度可以知道芯片运动的距离、速度情况,而磁力计可以知道物芯片的运动方向。

-

另外MPU9250芯片内置DMP姿态融合器,可以在不涉及算法的情况下,直接读取出描述物体状态的四元数,从而得出物体的三维角度–航向角、翻滚角、俯仰角。

-

驱动程序的设计

由于MPU9250芯片使用的是I2C接口,所以在这里,我首先需要I2C的驱动。

-

在我的驱动中,I2C使用GPIO口模拟的,因为这样在以后移植时更加方便。

-

在完成IOI2C的驱动之后,就是对MPU9250的寄存器进行操作,来成功获取传感数据。

-

MPU9250的寄存器操作

操作MPU9250寄存器并且开启DMP模式,获取三维角度,其步骤如下:

-
    -
  1. 复位,配置PWR_MGMT_1 0x80,延时一段时间
  2. -
  3. 配置PWR_MGMT_1(一般为00,表示使用内部晶振20Mhz)
  4. -
  5. 设置采样频率
  6. -
  7. 设置量程(角速度、加速度量程)
  8. -
  9. 外部中断打开,并且配置成相应的工作方式
  10. -
  11. 开启DMP,以及FIFO
  12. -
-

其中DMP的开启需要密码,而且具体的操作方法及寄存器在数据手册上都无法找到,是本人在网站经过查找融合了多人的驱动调试出来的。

-

代码调用

本人将调通之后的代码整理之后,只需调用几个API就可以实现参数的获取了。

-

主要分为两步:

-
    -
  1. 初始化
  2. -
-
1
2
3
IIC_Init();//模拟I2C驱动的初始化,一定要先初始化I2C接口才能操作MPU9250芯片
Init_MPU9250_With_DMP();//初始化MPU9250,配置并且开启DMP,设置中断方式为加速度方式
-
    -
  1. 函数调用
  2. -
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
while(1)
{
fifo_count = MPU9250_getFIFOCount();//读取FIFO计数
if(fifo_count >= 0x0200)//如果FIFO值>0x0200,此时DMP的结果错误,直接复位FIFO
{
MPU9250_resetFIFO();
}
else
{
if(fifo_count >= 0x2a)//如果FIFO值 > 0x2a,此时DMP转换完成并且数值正常
{
readdmp(); //首先要读取DMP FIFO,读取之后才能进行计算姿态的操作
MPU9250_resetFIFO();
getyawpitchroll();//计算并且获取yaw、pitch、roll,结果保存在yprf[3]数组中
}
}
}
-

NOTE:

-
    -
  • 在判断DMP是否完成时,应当从FIFO的计数中去判断,当计数大于等于42,说明DMP转换完成,也可以采用中断的方式来作为标志。

    -
  • -
  • 本例程中使用的I2C为GPIO模拟的I2C,主要是移植方便,但是在将此驱动移植到不同平台时需要注意寄存器以及引脚的定义。

    -
  • -
  • 注意芯片上电之后需要先复位,即设置PWR_MGMT_1为0x80,过一段时间之后再设置为0x00,否则有时芯片会工作异常

    -
  • -
-

具体的程序在我的代码库中,欢迎大家能找出其中的不足,E-mail给我。

-

代码链接如下:
MPU9250-MPU6050驱动

-]]>
-
- - - <![CDATA[LoRaWAN解析(一)--架构解析]]> - http://yoursite.com/2016/07/24/LoRaWAN%E5%8D%8F%E8%AE%AE(%E4%B8%80)--%E6%9E%B6%E6%9E%84/ - LoRaWAN 分层

LoRaWAN从底层到最后用户拿到数据的通讯过程通讯大致可分为三段:

-
    -
  1. MOTE <—> GW (MAC层)
  2. -
  3. GW <—> NS
  4. -
  5. NS <—> Customer
  6. -
-

LoRa联盟 规定了 MAC层的通讯协议,只有在设备(GW、MOTE)共同遵守的MAC层协议的前提下,不同硬件厂商的设备才能互相接入。

-

而GW <—> NS以及NS <—> Customer这两层的协议虽然LoRa联盟有所规范,但不同厂商之间可能会存在不同。

-

应用分析

在这里我以LoRaWAN 方式实现农场的土壤湿度检测来做说明。
实现农场的土壤湿度的检测主要分为几个步骤:

-
    -
  • 实现传感器采集土壤湿度(sensor层)
  • -
  • 将采集到的土壤湿度通过MOTE发送给GW(LoRaMac 层)
  • -
  • GW将收到的数据发送给NS(GW<—>NS)
  • -
  • NS再将数据发送给用户(NS<—>Customer)
  • -
  • 用户通过APP或者其他方式可以看到土壤的湿度状态。(Display)
  • -
-

通过以上的几个步骤,就可以实现远程监控农场土壤湿度。

-

好了,第一讲非常的简单。只是讲解了LoRaWAN 作为IOT的一种方式,其中的数据流向。

-]]>
-
- - - <![CDATA[cJSON_json包的C语言解析库]]> - http://yoursite.com/2016/07/21/CJSON_JSON%E5%8C%85%E7%9A%84C%E8%AF%AD%E8%A8%80%E8%A7%A3%E6%9E%90%E5%BA%93/ - cJSON库描述

CJSON是一个用于解析JSON包的C语言库,库文件为cJSON.c和cJSON.h,
所有的实现都在这两个文件中。原作者的地址cJSON

-

JSON包的解析

例如有一个JSON的数据包如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"rxpk": [
{
"tmst": 1868500100,
"time": "2016-07-07T13:20:40.003906Z",
"chan": 1,
"rfch": 0,
"freq": 779.7,
"stat": 1,
"modu": "LORA",
"datr": "SF9BW125",
"codr": "4/5",
"lsnr": 9.8,
"rssi": -37,
"size": 83,
"data": "QH/4iimAKgACB0KHP8e0IgQAhI0bBi9bvFfb8jHeSWEAhpnsCGHwt9pUCvrRMazQRBtN+kh3Ge5hFL8jUtHpk3luFtcTLlgGVMPSBLpSp8h6C44="
}
]
}

-

我们需要获取其中的data字段,需要进行的过程如下:

-
    -
  1. 首先声明变量

    -
    1
    2
    3
    4
    cJSON *json;
    cJSON *rxpk;
    cJSON *arr0;
    cJSON *data;
    -
  2. -
  3. 将上述的字符串进行解析,并保存在json中;

    -
  4. -
  5. 获取json其中的rxpk字段的内容,并保存在rxpk中;
  6. -
  7. 获取rxpk中的arr部分,拿出一种的第一个数组,并保存在arr0;
  8. -
  9. 获取arr0的data部分,并保存在data;
  10. -
  11. 使用data->valuestring即可获取其中的data字段的内容
    具体的代码实现如下所示:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    uint16_t rxpk_data_get(char* text,char* dest_str)
    {
    uint16_t len = 0;
    cJSON *json;
    cJSON *data;
    cJSON *arr0;
    cJSON *rxpk;
    json= cJSON_Parse(text);
    if(!json)//对JSON包进行合法性检查
    return 0;
    rxpk = cJSON_GetObjectItem(json,"rxpk");
    if(!rxpk)//对rxpk进行合法性检查
    return 0;
    arr0 = cJSON_GetArrayItem(rxpk,0);
    if(!arr0)//对arr0进行合法性检查
    return 0;
    data =cJSON_GetObjectItem(arr0,"data");
    if(!data)//对data进行合法性检查
    return 0;
    len = strlen(data->valuestring);
    memcpy(dest_str,data->valuestring,len);
    dest_str[len] = 0;
    return len;
    }
    -
  12. -
-

在json包中遇到数组时

1
2
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);

-

这个函数可以获取数组的长度。

-]]>
-
- - - <![CDATA[base64的C语言实现]]> - http://yoursite.com/2016/07/21/base64_C/ - 首先谢谢这位大神的github,再谢谢这位大神分享的base64的C语言实现代码,库的地址在这里base64

-

其中提供的接口非常的简单明了

1
2
3
4
5
6
#define BASE64_ENCODE_OUT_SIZE(s) (((s) + 2) / 3 * 4)
#define BASE64_DECODE_OUT_SIZE(s) (((s)) / 4 * 3)
int base64_encode(const unsigned char *in, unsigned int inlen, char *out);
int base64_decode(const char *in, unsigned int inlen,char *out);

-

但是其中有一个问题,base64_decode();函数在返回时并没有返回解码后的字节数,在使用上会存在不方便的情况。

-

故,我把这个函数稍加修改之后,在解码之后返回解码数组的长度,在使用上就方便很多了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int base64_decode(const char *in, unsigned int inlen, char *out)
{
unsigned int i, j;
for (i = j = 0; i < inlen; i++) {
int c;
int s = i % 4; /* from 8/gcd(6, 8) */
if (in[i] == '=')
return j;
if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST ||
(c = base64de[in[i] - BASE64DE_FIRST]) == -1)
return j;
switch (s) {
case 0:
out[j] = ((unsigned int)c << 2) & 0xFF;
continue;
case 1:
out[j++] += ((unsigned int)c >> 4) & 0x3;
/* if not last char with padding */
if (i < (inlen - 3) || in[inlen - 2] != '=')
out[j] = ((unsigned int)c & 0xF) << 4;
continue;
case 2:
out[j++] += ((unsigned int)c >> 2) & 0xF;
/* if not last char with padding */
if (i < (inlen - 2) || in[inlen - 1] != '=')
out[j] = ((unsigned int)c & 0x3) << 6;
continue;
case 3:
out[j++] += (unsigned char)c;
}
}
return j;
}

-

使用代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
int main(void)
{
unsigned char input[] = "pleasure.";
unsigned char decode[13];
char output[13];
uint16_t len_decode = 0;
bzero(output, sizeof(output));
base64_encode(input, sizeof(input) - 1, output);
len_decode = base64_decode(output, sizeof(output) - 1, decode);
return 0;
}

-]]>
-
- - - <![CDATA[74HC165的级联以及MCU硬件SPI的通讯]]> - http://yoursite.com/2016/07/21/74HC165/ - 概述

74HC165作为常用的IO口扩展芯片,常用于并行IO口状态转串行数据。一块74HC165芯片可以连接8个IO口,将8个IO口状态转换成8位串行的数据传输给MCU。也就是说可以通过两个IO口获取到8个IO口的状态。
在电路设计中,也经常将74HC165芯片级联使用。通过芯片的级联,可以达到2个IO口读取16个IO口状态(2片级联)的效果,甚至更多。

-

由于74HC165的操作时序刚SPI的时序恰好相同,所以可以通过MCU的硬件SPI接口来操作74HC165芯片,这种通过MCU硬件接口来操作芯片的优点如下:

-
    -
  • 硬件的SPI时钟速度高,STM32芯片舌诊可以达到20MHZ,这样获取IO口状态的速度快,实时性更强
  • -
  • 扫描周期更短,可以使用在一些判断IO口状态的应用中,如扫描是否有物体高速穿过
  • -
-

软件的实现思路

由于使用的是MCU的硬件SPI接口,所以程序和MCU的型号会有较大关系,在这里,我以STM32F103RCT6为例。

-

步骤如下:

-
    -
  1. 将MCU的SPI复用IO口初始化
  2. -
  3. 配置SPI寄存器,示例代码如下:

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SPI_I2S_DeInit(SPI1);
    SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;// Receive-only mode
    SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//
    SPI_InitStructure.SPI_DataSize=SPI_DataSize_16b;// Data word = 16 bit wide
    SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;// Clock default level = L
    SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;// Latch on the first edge (rising from L)
    SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;// Software controls select SS signal, SS pin is GPIO
    SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4; // SPI_BaudRatePrescaler_4
    SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_LSB;// MSB first
    SPI_InitStructure.SPI_CRCPolynomial=7;// No CRC required
    SPI_Init(SPI1, &SPI_InitStructure);
    -

    其中需要注意的是分频的值和数据位长度,由于这边是2片级联,所以使用的是16b

    -
  4. -
  5. SPI读取,代码如下:

    -
    1
    2
    3
    4
    5
    6
    7
    8
    9
    GPIOC->BSRR = GPIO_Pin_5;//片选选中
    while((SPI1->SR & SPI_I2S_FLAG_TXE) == 0);//判断数据发送完成
    SPI1->DR = 0xFFFF;
    while((SPI1->SR & SPI_I2S_FLAG_RXNE) == 0);//判断数据接受完成
    temp1 = SPI1->DR;
    GPIOC->BRR = GPIO_Pin_5;//片选取消选中
    -

    思路就是利用硬件的SPI时序以及SPI每写一位就会返回一位的特性,向74HC165芯片写入16bit的数据,便会在SPI寄存器中获取到两片级联的74HC165的状态。

    -
  6. -
-]]>
-
- - - <![CDATA[STM32L051 PVD的调试]]> - http://yoursite.com/2016/07/11/STM32_PVD/ - 我的PVD的驱动以及例程位于STM32L0xx_Drivers这个库当中,在使用前最好先阅读readme.md文件

-

PVD 是一种检测MCU供电情况的技术。当供电电压高于或者低于一定阈值的时候,可以在寄存器上体现出来,或者直接产生硬件中断。
在实际使用MCU时,特别是电池供电的方案中,往往会遇到供电不够导致MCU或者外设工作不正常的情况。PVD在这个时候就可以派上用场了。
PVD的使用按照数据手册上的说明,就是首先设置PVD阈值(PVD thresholds),当MCU的VDD引脚的电压高于阈值时,则PVD output=1,当VDD电压低于阈值时,PVD output=0,如下图所示:

-

-

其中PVD output的结果可以再在存器中查看到

-


-

关于PVD的阈值的设定共有两种方式:

-
    -
  • 固定阈值(1.9V 2.1V 2.3V 2.5V 2.7V 2.9V 3.1V)
  • -
  • 与引脚比较(PB7)
  • -
-

在实际使用的过程中,PVD可以用查询挥着中断的方式来工作。

-

在测试的例程中,我配置PVD工作方式为中断上升下降沿触发,当VDD高于预设PVD阈值或者低于阈值而产生边沿触发时,都会形成一次PVD中断,然后读取PWR_CSR的PVDO标志位检查是低电压提醒还是高电压提醒,以此来达到监控MCU供电情况的目的。

-

注意:当使用PVD功能检测低电压时,VDD电压刚刚小于阈值时并不会直接产生PVD中断,只有当VDD电压小于(阈值-50MV)时,才会产生中断。

-

如果有什么疑问或者错误欢迎大家指正,email:454626653@qq.com

-]]>
-
- - - <![CDATA[以帧为存储单位的循环stack]]> - http://yoursite.com/2016/07/11/%E6%9E%84%E5%BB%BA%E4%BB%A5%E5%B8%A7%E4%B8%BA%E5%8D%95%E4%BD%8D%E7%9A%84stack/ - 此stack主要是作为存储空间使用,主要的借口就是push和pop。

-

stack frame的src以及例程位于stack_FrameTest这个库当中,其中有readme文件,可以快速上手。

-

stack构造及代码实现

其中我对stack以及frame的构造的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct Frame
{
uint8_t frame_len;//帧的字节数
uint8_t frame_data[MAX_TRANSMISSION_UINT];//一帧数据最大为MAX_TRANSMISSION_UINT字节
}Frame;
typedef struct STACK
{
int8_t frame_lastNum;//最新的帧的序号
uint8_t frame_count;//stack中未取出的帧的个数
Frame frame_info[MAX_STACK_FRAME_NUM];//stack中最多允许存储MAX_STACK_FRAME_NUM个帧
}STACK;

-

首先构造了一个stack,stack包含两个内容:

-
    -
  1. stack的统计信息:stack中帧的个数(frame_count),最新的帧的ID(frame_lastNum);
  2. -
  3. 数据存储区–一个数组,数据格式为Frame,容量为MAX_STACK_FRAME_NUM(frame_info[MAX_STACK_FRAME_NUM]);
  4. -
-

然后,帧的构造也包含了两个部分:

-
    -
  1. 此帧数据的字节数(frame_len);
  2. -
  3. 数据存储空间–数组,数据格式为uint8_t,容量为MAX_TRANSMISSION_UINT(frame_data[MAX_TRANSMISSION_UINT]);
  4. -
-

另外,此stack为一个循环栈,当stack存满之后仍有数据存入,并不会发生越界,而是会从头开始覆盖,此种操作,有利也有弊。

-

拼包机制

在最后,此例程中还写了一个拼包的机制,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//将stack中的数据进行拼包,在不造成断包的情况下最大限度地拼包
uint8_t SpliceFrame(uint8_t* dest)
{
uint8_t Splice_len = 0;
Splice_len = 0;
while(1)
{
//确保当前数据加下一帧数据不会超过最大单帧负载量(MTU)
if((Splice_len +Stack_GetFrameLastNum()) <= MAX_TRANSMISSION_UINT)
{
Splice_len +=Stack_PopData(dest+Splice_len);//
if(Stack_GetFrameCount() == 0)//当前融合帧的数量小于stack中已存帧的数量
break;
}
else
{
break;
}
}
return Splice_len;
}

-

思路就是假如当MTU=70,而如果收到的数据为10bytes,10bytes这样的短数据,我们就可以把这样的短数据由多个包拼接成一个包,一次性发送出去,提高通道的利用效率,因为一次发送70个字节所需的时间大约为5s,而一次发送10个字节的时间也基本等于5s,但是拼包的时候如果造成断包,在接收端处理会非常的麻烦,所以拼包机制制定成这样–在不造成断包以及不超过MTU的情况下最大限度地拼包。

-

有任何问题欢迎联系我。

-]]>
-
- - - -
diff --git a/tags/74HC165/index.html b/tags/74HC165/index.html deleted file mode 100644 index 5ad19fc..0000000 --- a/tags/74HC165/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: 74HC165 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/C/index.html b/tags/C/index.html deleted file mode 100644 index ec3deed..0000000 --- a/tags/C/index.html +++ /dev/null @@ -1,850 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: C | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/JSON/index.html b/tags/JSON/index.html deleted file mode 100644 index af1da4b..0000000 --- a/tags/JSON/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: JSON | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/LoRaWAN/index.html b/tags/LoRaWAN/index.html deleted file mode 100644 index 7468934..0000000 --- a/tags/LoRaWAN/index.html +++ /dev/null @@ -1,1050 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: LoRaWAN | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/LoRaWAN/page/2/index.html b/tags/LoRaWAN/page/2/index.html deleted file mode 100644 index ce9b17b..0000000 --- a/tags/LoRaWAN/page/2/index.html +++ /dev/null @@ -1,938 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: LoRaWAN | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/tags/MCU\345\244\226\350\256\276/index.html" "b/tags/MCU\345\244\226\350\256\276/index.html" deleted file mode 100644 index 92e6104..0000000 --- "a/tags/MCU\345\244\226\350\256\276/index.html" +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: MCU外设 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/MPU9250/index.html b/tags/MPU9250/index.html deleted file mode 100644 index 7408952..0000000 --- a/tags/MPU9250/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: MPU9250 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/MTU/index.html b/tags/MTU/index.html deleted file mode 100644 index 0cb7818..0000000 --- a/tags/MTU/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: MTU | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/NVIC/index.html b/tags/NVIC/index.html deleted file mode 100644 index cb8f1dc..0000000 --- a/tags/NVIC/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: NVIC | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/PVD/index.html b/tags/PVD/index.html deleted file mode 100644 index 67112fe..0000000 --- a/tags/PVD/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: PVD | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/STM32/index.html b/tags/STM32/index.html deleted file mode 100644 index cc17f6f..0000000 --- a/tags/STM32/index.html +++ /dev/null @@ -1,962 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: STM32 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/Sensor/index.html b/tags/Sensor/index.html deleted file mode 100644 index 795c25d..0000000 --- a/tags/Sensor/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: Sensor | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/base64/index.html b/tags/base64/index.html deleted file mode 100644 index 9031d1b..0000000 --- a/tags/base64/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: base64 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/index.html b/tags/index.html deleted file mode 100644 index 9b681b7..0000000 --- a/tags/index.html +++ /dev/null @@ -1,782 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/stack/index.html b/tags/stack/index.html deleted file mode 100644 index 4ab09bf..0000000 --- a/tags/stack/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: stack | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/sx1276/index.html b/tags/sx1276/index.html deleted file mode 100644 index 1517fc7..0000000 --- a/tags/sx1276/index.html +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: sx1276 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/tags/\346\213\206\345\214\205/index.html" "b/tags/\346\213\206\345\214\205/index.html" deleted file mode 100644 index 59c652f..0000000 --- "a/tags/\346\213\206\345\214\205/index.html" +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: 拆包 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/tags/\346\213\274\345\214\205/index.html" "b/tags/\346\213\274\345\214\205/index.html" deleted file mode 100644 index 5d25767..0000000 --- "a/tags/\346\213\274\345\214\205/index.html" +++ /dev/null @@ -1,794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: 拼包 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" deleted file mode 100644 index 31bb026..0000000 --- "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" +++ /dev/null @@ -1,822 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 标签: 数据结构 | 陈均奎 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/uploads/LoRa/PHY_data_format.png b/uploads/LoRa/PHY_data_format.png deleted file mode 100644 index 75d8d11..0000000 Binary files a/uploads/LoRa/PHY_data_format.png and /dev/null differ diff --git a/uploads/LoRa/downlink.png b/uploads/LoRa/downlink.png deleted file mode 100644 index b74bf2c..0000000 Binary files a/uploads/LoRa/downlink.png and /dev/null differ diff --git a/uploads/LoRa/uplink.png b/uploads/LoRa/uplink.png deleted file mode 100644 index 6d2910a..0000000 Binary files a/uploads/LoRa/uplink.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/FLASH_DOWNLOAD.png b/uploads/LoRaWAN_STM32/FLASH_DOWNLOAD.png deleted file mode 100644 index d5cdb29..0000000 Binary files a/uploads/LoRaWAN_STM32/FLASH_DOWNLOAD.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/JLINK_DEVICE_SELECTION.png b/uploads/LoRaWAN_STM32/JLINK_DEVICE_SELECTION.png deleted file mode 100644 index 6ec67b5..0000000 Binary files a/uploads/LoRaWAN_STM32/JLINK_DEVICE_SELECTION.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_ADR.png b/uploads/LoRaWAN_STM32/LoRaWAN_ADR.png deleted file mode 100644 index 5b138f2..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_ADR.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_CLASSA_RX.png b/uploads/LoRaWAN_STM32/LoRaWAN_CLASSA_RX.png deleted file mode 100644 index a27ddd0..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_CLASSA_RX.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_CLASSC_RX.png b/uploads/LoRaWAN_STM32/LoRaWAN_CLASSC_RX.png deleted file mode 100644 index 85cb3dd..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_CLASSC_RX.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_FHDR.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_FHDR.png deleted file mode 100644 index f48f772..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_FHDR.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MACPayload.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MACPayload.png deleted file mode 100644 index 5a39286..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MACPayload.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_Commands.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_Commands.png deleted file mode 100644 index ddbd3d3..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_Commands.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_FPort.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_FPort.png deleted file mode 100644 index f5758c4..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_FPort.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_FRMPayload.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_FRMPayload.png deleted file mode 100644 index cd2fe1d..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MAC_FRMPayload.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MHDR.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MHDR.png deleted file mode 100644 index ec1a569..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MHDR.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MIC.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MIC.png deleted file mode 100644 index c67fd20..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MIC.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_MType.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_MType.png deleted file mode 100644 index 5d88c2a..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_MType.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_Major.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_Major.png deleted file mode 100644 index 9477f0c..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_Major.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_PHYPayload.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_PHYPayload.png deleted file mode 100644 index 95e3b6f..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_PHYPayload.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/LoRaWAN_message_format.png b/uploads/LoRaWAN_STM32/LoRaWAN_message_format.png deleted file mode 100644 index 93233df..0000000 Binary files a/uploads/LoRaWAN_STM32/LoRaWAN_message_format.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/REGPACONFIG.png b/uploads/LoRaWAN_STM32/REGPACONFIG.png deleted file mode 100644 index f151f0b..0000000 Binary files a/uploads/LoRaWAN_STM32/REGPACONFIG.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/REGTCXO.png b/uploads/LoRaWAN_STM32/REGTCXO.png deleted file mode 100644 index 6e77993..0000000 Binary files a/uploads/LoRaWAN_STM32/REGTCXO.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/STM32_NVIC.png b/uploads/LoRaWAN_STM32/STM32_NVIC.png deleted file mode 100644 index 8e606e2..0000000 Binary files a/uploads/LoRaWAN_STM32/STM32_NVIC.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/STM32_OSC.png b/uploads/LoRaWAN_STM32/STM32_OSC.png deleted file mode 100644 index 4eca3d4..0000000 Binary files a/uploads/LoRaWAN_STM32/STM32_OSC.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/STM32_OSC_RTC.png b/uploads/LoRaWAN_STM32/STM32_OSC_RTC.png deleted file mode 100644 index 1b479c9..0000000 Binary files a/uploads/LoRaWAN_STM32/STM32_OSC_RTC.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/STM32_OSC_SYSTEM.png b/uploads/LoRaWAN_STM32/STM32_OSC_SYSTEM.png deleted file mode 100644 index 89761ac..0000000 Binary files a/uploads/LoRaWAN_STM32/STM32_OSC_SYSTEM.png and /dev/null differ diff --git a/uploads/LoRaWAN_STM32/TXRX.png b/uploads/LoRaWAN_STM32/TXRX.png deleted file mode 100644 index 051b944..0000000 Binary files a/uploads/LoRaWAN_STM32/TXRX.png and /dev/null differ diff --git a/vendors/fancybox/source/blank.gif b/vendors/fancybox/source/blank.gif deleted file mode 100644 index 35d42e8..0000000 Binary files a/vendors/fancybox/source/blank.gif and /dev/null differ diff --git a/vendors/fancybox/source/fancybox_loading.gif b/vendors/fancybox/source/fancybox_loading.gif deleted file mode 100644 index a03a40c..0000000 Binary files a/vendors/fancybox/source/fancybox_loading.gif and /dev/null differ diff --git a/vendors/fancybox/source/fancybox_loading@2x.gif b/vendors/fancybox/source/fancybox_loading@2x.gif deleted file mode 100644 index 9205aeb..0000000 Binary files a/vendors/fancybox/source/fancybox_loading@2x.gif and /dev/null differ diff --git a/vendors/fancybox/source/fancybox_overlay.png b/vendors/fancybox/source/fancybox_overlay.png deleted file mode 100644 index a439139..0000000 Binary files a/vendors/fancybox/source/fancybox_overlay.png and /dev/null differ diff --git a/vendors/fancybox/source/fancybox_sprite.png b/vendors/fancybox/source/fancybox_sprite.png deleted file mode 100644 index fd8d5ca..0000000 Binary files a/vendors/fancybox/source/fancybox_sprite.png and /dev/null differ diff --git a/vendors/fancybox/source/fancybox_sprite@2x.png b/vendors/fancybox/source/fancybox_sprite@2x.png deleted file mode 100644 index d0e4779..0000000 Binary files a/vendors/fancybox/source/fancybox_sprite@2x.png and /dev/null differ diff --git a/vendors/fancybox/source/helpers/fancybox_buttons.png b/vendors/fancybox/source/helpers/fancybox_buttons.png deleted file mode 100644 index 0787207..0000000 Binary files a/vendors/fancybox/source/helpers/fancybox_buttons.png and /dev/null differ diff --git a/vendors/fancybox/source/helpers/jquery.fancybox-buttons.css b/vendors/fancybox/source/helpers/jquery.fancybox-buttons.css deleted file mode 100644 index a26273a..0000000 --- a/vendors/fancybox/source/helpers/jquery.fancybox-buttons.css +++ /dev/null @@ -1,97 +0,0 @@ -#fancybox-buttons { - position: fixed; - left: 0; - width: 100%; - z-index: 8050; -} - -#fancybox-buttons.top { - top: 10px; -} - -#fancybox-buttons.bottom { - bottom: 10px; -} - -#fancybox-buttons ul { - display: block; - width: 166px; - height: 30px; - margin: 0 auto; - padding: 0; - list-style: none; - border: 1px solid #111; - border-radius: 3px; - -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - box-shadow: inset 0 0 0 1px rgba(255,255,255,.05); - background: rgb(50,50,50); - background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51))); - background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - background: linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 ); -} - -#fancybox-buttons ul li { - float: left; - margin: 0; - padding: 0; -} - -#fancybox-buttons a { - display: block; - width: 30px; - height: 30px; - text-indent: -9999px; - background-color: transparent; - background-image: url('fancybox_buttons.png'); - background-repeat: no-repeat; - outline: none; - opacity: 0.8; -} - -#fancybox-buttons a:hover { - opacity: 1; -} - -#fancybox-buttons a.btnPrev { - background-position: 5px 0; -} - -#fancybox-buttons a.btnNext { - background-position: -33px 0; - border-right: 1px solid #3e3e3e; -} - -#fancybox-buttons a.btnPlay { - background-position: 0 -30px; -} - -#fancybox-buttons a.btnPlayOn { - background-position: -30px -30px; -} - -#fancybox-buttons a.btnToggle { - background-position: 3px -60px; - border-left: 1px solid #111; - border-right: 1px solid #3e3e3e; - width: 35px -} - -#fancybox-buttons a.btnToggleOn { - background-position: -27px -60px; -} - -#fancybox-buttons a.btnClose { - border-left: 1px solid #111; - width: 35px; - background-position: -56px 0px; -} - -#fancybox-buttons a.btnDisabled { - opacity : 0.4; - cursor: default; -} \ No newline at end of file diff --git a/vendors/fancybox/source/helpers/jquery.fancybox-buttons.js b/vendors/fancybox/source/helpers/jquery.fancybox-buttons.js deleted file mode 100644 index fd8b955..0000000 --- a/vendors/fancybox/source/helpers/jquery.fancybox-buttons.js +++ /dev/null @@ -1,122 +0,0 @@ - /*! - * Buttons helper for fancyBox - * version: 1.0.5 (Mon, 15 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * buttons: { - * position : 'top' - * } - * } - * }); - * - */ -(function ($) { - //Shortcut for fancyBox object - var F = $.fancybox; - - //Add helper object - F.helpers.buttons = { - defaults : { - skipSingle : false, // disables if gallery contains single image - position : 'top', // 'top' or 'bottom' - tpl : '
' - }, - - list : null, - buttons: null, - - beforeLoad: function (opts, obj) { - //Remove self if gallery do not have at least two items - - if (opts.skipSingle && obj.group.length < 2) { - obj.helpers.buttons = false; - obj.closeBtn = true; - - return; - } - - //Increase top margin to give space for buttons - obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30; - }, - - onPlayStart: function () { - if (this.buttons) { - this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn'); - } - }, - - onPlayEnd: function () { - if (this.buttons) { - this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn'); - } - }, - - afterShow: function (opts, obj) { - var buttons = this.buttons; - - if (!buttons) { - this.list = $(opts.tpl).addClass(opts.position).appendTo('body'); - - buttons = { - prev : this.list.find('.btnPrev').click( F.prev ), - next : this.list.find('.btnNext').click( F.next ), - play : this.list.find('.btnPlay').click( F.play ), - toggle : this.list.find('.btnToggle').click( F.toggle ), - close : this.list.find('.btnClose').click( F.close ) - } - } - - //Prev - if (obj.index > 0 || obj.loop) { - buttons.prev.removeClass('btnDisabled'); - } else { - buttons.prev.addClass('btnDisabled'); - } - - //Next / Play - if (obj.loop || obj.index < obj.group.length - 1) { - buttons.next.removeClass('btnDisabled'); - buttons.play.removeClass('btnDisabled'); - - } else { - buttons.next.addClass('btnDisabled'); - buttons.play.addClass('btnDisabled'); - } - - this.buttons = buttons; - - this.onUpdate(opts, obj); - }, - - onUpdate: function (opts, obj) { - var toggle; - - if (!this.buttons) { - return; - } - - toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn'); - - //Size toggle button - if (obj.canShrink) { - toggle.addClass('btnToggleOn'); - - } else if (!obj.canExpand) { - toggle.addClass('btnDisabled'); - } - }, - - beforeClose: function () { - if (this.list) { - this.list.remove(); - } - - this.list = null; - this.buttons = null; - } - }; - -}(jQuery)); diff --git a/vendors/fancybox/source/helpers/jquery.fancybox-media.js b/vendors/fancybox/source/helpers/jquery.fancybox-media.js deleted file mode 100644 index 3584c8a..0000000 --- a/vendors/fancybox/source/helpers/jquery.fancybox-media.js +++ /dev/null @@ -1,199 +0,0 @@ -/*! - * Media helper for fancyBox - * version: 1.0.6 (Fri, 14 Jun 2013) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * media: true - * } - * }); - * - * Set custom URL parameters: - * $(".fancybox").fancybox({ - * helpers : { - * media: { - * youtube : { - * params : { - * autoplay : 0 - * } - * } - * } - * } - * }); - * - * Or: - * $(".fancybox").fancybox({, - * helpers : { - * media: true - * }, - * youtube : { - * autoplay: 0 - * } - * }); - * - * Supports: - * - * Youtube - * http://www.youtube.com/watch?v=opj24KnzrWo - * http://www.youtube.com/embed/opj24KnzrWo - * http://youtu.be/opj24KnzrWo - * http://www.youtube-nocookie.com/embed/opj24KnzrWo - * Vimeo - * http://vimeo.com/40648169 - * http://vimeo.com/channels/staffpicks/38843628 - * http://vimeo.com/groups/surrealism/videos/36516384 - * http://player.vimeo.com/video/45074303 - * Metacafe - * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/ - * http://www.metacafe.com/watch/7635964/ - * Dailymotion - * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people - * Twitvid - * http://twitvid.com/QY7MD - * Twitpic - * http://twitpic.com/7p93st - * Instagram - * http://instagr.am/p/IejkuUGxQn/ - * http://instagram.com/p/IejkuUGxQn/ - * Google maps - * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17 - * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16 - * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56 - */ -(function ($) { - "use strict"; - - //Shortcut for fancyBox object - var F = $.fancybox, - format = function( url, rez, params ) { - params = params || ''; - - if ( $.type( params ) === "object" ) { - params = $.param(params, true); - } - - $.each(rez, function(key, value) { - url = url.replace( '$' + key, value || '' ); - }); - - if (params.length) { - url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params; - } - - return url; - }; - - //Add helper object - F.helpers.media = { - defaults : { - youtube : { - matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i, - params : { - autoplay : 1, - autohide : 1, - fs : 1, - rel : 0, - hd : 1, - wmode : 'opaque', - enablejsapi : 1 - }, - type : 'iframe', - url : '//www.youtube.com/embed/$3' - }, - vimeo : { - matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/, - params : { - autoplay : 1, - hd : 1, - show_title : 1, - show_byline : 1, - show_portrait : 0, - fullscreen : 1 - }, - type : 'iframe', - url : '//player.vimeo.com/video/$1' - }, - metacafe : { - matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/, - params : { - autoPlay : 'yes' - }, - type : 'swf', - url : function( rez, params, obj ) { - obj.swf.flashVars = 'playerVars=' + $.param( params, true ); - - return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf'; - } - }, - dailymotion : { - matcher : /dailymotion.com\/video\/(.*)\/?(.*)/, - params : { - additionalInfos : 0, - autoStart : 1 - }, - type : 'swf', - url : '//www.dailymotion.com/swf/video/$1' - }, - twitvid : { - matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i, - params : { - autoplay : 0 - }, - type : 'iframe', - url : '//www.twitvid.com/embed.php?guid=$1' - }, - twitpic : { - matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i, - type : 'image', - url : '//twitpic.com/show/full/$1/' - }, - instagram : { - matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i, - type : 'image', - url : '//$1/p/$2/media/?size=l' - }, - google_maps : { - matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i, - type : 'iframe', - url : function( rez ) { - return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed'); - } - } - }, - - beforeLoad : function(opts, obj) { - var url = obj.href || '', - type = false, - what, - item, - rez, - params; - - for (what in opts) { - if (opts.hasOwnProperty(what)) { - item = opts[ what ]; - rez = url.match( item.matcher ); - - if (rez) { - type = item.type; - params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null)); - - url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params ); - - break; - } - } - } - - if (type) { - obj.href = url; - obj.type = type; - - obj.autoHeight = false; - } - } - }; - -}(jQuery)); \ No newline at end of file diff --git a/vendors/fancybox/source/helpers/jquery.fancybox-thumbs.css b/vendors/fancybox/source/helpers/jquery.fancybox-thumbs.css deleted file mode 100644 index 63d2943..0000000 --- a/vendors/fancybox/source/helpers/jquery.fancybox-thumbs.css +++ /dev/null @@ -1,55 +0,0 @@ -#fancybox-thumbs { - position: fixed; - left: 0; - width: 100%; - overflow: hidden; - z-index: 8050; -} - -#fancybox-thumbs.bottom { - bottom: 2px; -} - -#fancybox-thumbs.top { - top: 2px; -} - -#fancybox-thumbs ul { - position: relative; - list-style: none; - margin: 0; - padding: 0; -} - -#fancybox-thumbs ul li { - float: left; - padding: 1px; - opacity: 0.5; -} - -#fancybox-thumbs ul li.active { - opacity: 0.75; - padding: 0; - border: 1px solid #fff; -} - -#fancybox-thumbs ul li:hover { - opacity: 1; -} - -#fancybox-thumbs ul li a { - display: block; - position: relative; - overflow: hidden; - border: 1px solid #222; - background: #111; - outline: none; -} - -#fancybox-thumbs ul li img { - display: block; - position: relative; - border: 0; - padding: 0; - max-width: none; -} \ No newline at end of file diff --git a/vendors/fancybox/source/helpers/jquery.fancybox-thumbs.js b/vendors/fancybox/source/helpers/jquery.fancybox-thumbs.js deleted file mode 100644 index 5db3d4a..0000000 --- a/vendors/fancybox/source/helpers/jquery.fancybox-thumbs.js +++ /dev/null @@ -1,162 +0,0 @@ - /*! - * Thumbnail helper for fancyBox - * version: 1.0.7 (Mon, 01 Oct 2012) - * @requires fancyBox v2.0 or later - * - * Usage: - * $(".fancybox").fancybox({ - * helpers : { - * thumbs: { - * width : 50, - * height : 50 - * } - * } - * }); - * - */ -(function ($) { - //Shortcut for fancyBox object - var F = $.fancybox; - - //Add helper object - F.helpers.thumbs = { - defaults : { - width : 50, // thumbnail width - height : 50, // thumbnail height - position : 'bottom', // 'top' or 'bottom' - source : function ( item ) { // function to obtain the URL of the thumbnail image - var href; - - if (item.element) { - href = $(item.element).find('img').attr('src'); - } - - if (!href && item.type === 'image' && item.href) { - href = item.href; - } - - return href; - } - }, - - wrap : null, - list : null, - width : 0, - - init: function (opts, obj) { - var that = this, - list, - thumbWidth = opts.width, - thumbHeight = opts.height, - thumbSource = opts.source; - - //Build list structure - list = ''; - - for (var n = 0; n < obj.group.length; n++) { - list += '
  • '; - } - - this.wrap = $('
    ').addClass(opts.position).appendTo('body'); - this.list = $('
      ' + list + '
    ').appendTo(this.wrap); - - //Load each thumbnail - $.each(obj.group, function (i) { - var href = thumbSource( obj.group[ i ] ); - - if (!href) { - return; - } - - $("").load(function () { - var width = this.width, - height = this.height, - widthRatio, heightRatio, parent; - - if (!that.list || !width || !height) { - return; - } - - //Calculate thumbnail width/height and center it - widthRatio = width / thumbWidth; - heightRatio = height / thumbHeight; - - parent = that.list.children().eq(i).find('a'); - - if (widthRatio >= 1 && heightRatio >= 1) { - if (widthRatio > heightRatio) { - width = Math.floor(width / heightRatio); - height = thumbHeight; - - } else { - width = thumbWidth; - height = Math.floor(height / widthRatio); - } - } - - $(this).css({ - width : width, - height : height, - top : Math.floor(thumbHeight / 2 - height / 2), - left : Math.floor(thumbWidth / 2 - width / 2) - }); - - parent.width(thumbWidth).height(thumbHeight); - - $(this).hide().appendTo(parent).fadeIn(300); - - }).attr('src', href); - }); - - //Set initial width - this.width = this.list.children().eq(0).outerWidth(true); - - this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))); - }, - - beforeLoad: function (opts, obj) { - //Remove self if gallery do not have at least two items - if (obj.group.length < 2) { - obj.helpers.thumbs = false; - - return; - } - - //Increase bottom margin to give space for thumbs - obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15); - }, - - afterShow: function (opts, obj) { - //Check if exists and create or update list - if (this.list) { - this.onUpdate(opts, obj); - - } else { - this.init(opts, obj); - } - - //Set active element - this.list.children().removeClass('active').eq(obj.index).addClass('active'); - }, - - //Center list - onUpdate: function (opts, obj) { - if (this.list) { - this.list.stop(true).animate({ - 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)) - }, 150); - } - }, - - beforeClose: function () { - if (this.wrap) { - this.wrap.remove(); - } - - this.wrap = null; - this.list = null; - this.width = 0; - } - } - -}(jQuery)); \ No newline at end of file diff --git a/vendors/fancybox/source/jquery.fancybox.css b/vendors/fancybox/source/jquery.fancybox.css deleted file mode 100644 index 367890a..0000000 --- a/vendors/fancybox/source/jquery.fancybox.css +++ /dev/null @@ -1,274 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -.fancybox-wrap, -.fancybox-skin, -.fancybox-outer, -.fancybox-inner, -.fancybox-image, -.fancybox-wrap iframe, -.fancybox-wrap object, -.fancybox-nav, -.fancybox-nav span, -.fancybox-tmp -{ - padding: 0; - margin: 0; - border: 0; - outline: none; - vertical-align: top; -} - -.fancybox-wrap { - position: absolute; - top: 0; - left: 0; - z-index: 8020; -} - -.fancybox-skin { - position: relative; - background: #f9f9f9; - color: #444; - text-shadow: none; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.fancybox-opened { - z-index: 8030; -} - -.fancybox-opened .fancybox-skin { - -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); -} - -.fancybox-outer, .fancybox-inner { - position: relative; -} - -.fancybox-inner { - overflow: hidden; -} - -.fancybox-type-iframe .fancybox-inner { - -webkit-overflow-scrolling: touch; -} - -.fancybox-error { - color: #444; - font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - margin: 0; - padding: 15px; - white-space: nowrap; -} - -.fancybox-image, .fancybox-iframe { - display: block; - width: 100%; - height: 100%; -} - -.fancybox-image { - max-width: 100%; - max-height: 100%; -} - -#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url('fancybox_sprite.png'); -} - -#fancybox-loading { - position: fixed; - top: 50%; - left: 50%; - margin-top: -22px; - margin-left: -22px; - background-position: 0 -108px; - opacity: 0.8; - cursor: pointer; - z-index: 8060; -} - -#fancybox-loading div { - width: 44px; - height: 44px; - background: url('fancybox_loading.gif') center center no-repeat; -} - -.fancybox-close { - position: absolute; - top: -18px; - right: -18px; - width: 36px; - height: 36px; - cursor: pointer; - z-index: 8040; -} - -.fancybox-nav { - position: absolute; - top: 0; - width: 40%; - height: 100%; - cursor: pointer; - text-decoration: none; - background: transparent url('blank.gif'); /* helps IE */ - -webkit-tap-highlight-color: rgba(0,0,0,0); - z-index: 8040; -} - -.fancybox-prev { - left: 0; -} - -.fancybox-next { - right: 0; -} - -.fancybox-nav span { - position: absolute; - top: 50%; - width: 36px; - height: 34px; - margin-top: -18px; - cursor: pointer; - z-index: 8040; - visibility: hidden; -} - -.fancybox-prev span { - left: 10px; - background-position: 0 -36px; -} - -.fancybox-next span { - right: 10px; - background-position: 0 -72px; -} - -.fancybox-nav:hover span { - visibility: visible; -} - -.fancybox-tmp { - position: absolute; - top: -99999px; - left: -99999px; - visibility: hidden; - max-width: 99999px; - max-height: 99999px; - overflow: visible !important; -} - -/* Overlay helper */ - -.fancybox-lock { - overflow: hidden !important; - width: auto; -} - -.fancybox-lock body { - overflow: hidden !important; -} - -.fancybox-lock-test { - overflow-y: hidden !important; -} - -.fancybox-overlay { - position: absolute; - top: 0; - left: 0; - overflow: hidden; - display: none; - z-index: 8010; - background: url('fancybox_overlay.png'); -} - -.fancybox-overlay-fixed { - position: fixed; - bottom: 0; - right: 0; -} - -.fancybox-lock .fancybox-overlay { - overflow: auto; - overflow-y: scroll; -} - -/* Title helper */ - -.fancybox-title { - visibility: hidden; - font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; - position: relative; - text-shadow: none; - z-index: 8050; -} - -.fancybox-opened .fancybox-title { - visibility: visible; -} - -.fancybox-title-float-wrap { - position: absolute; - bottom: 0; - right: 50%; - margin-bottom: -35px; - z-index: 8050; - text-align: center; -} - -.fancybox-title-float-wrap .child { - display: inline-block; - margin-right: -100%; - padding: 2px 20px; - background: transparent; /* Fallback for web browsers that doesn't support RGBa */ - background: rgba(0, 0, 0, 0.8); - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; - text-shadow: 0 1px 2px #222; - color: #FFF; - font-weight: bold; - line-height: 24px; - white-space: nowrap; -} - -.fancybox-title-outside-wrap { - position: relative; - margin-top: 10px; - color: #fff; -} - -.fancybox-title-inside-wrap { - padding-top: 10px; -} - -.fancybox-title-over-wrap { - position: absolute; - bottom: 0; - left: 0; - color: #fff; - padding: 10px; - background: #000; - background: rgba(0, 0, 0, .8); -} - -/*Retina graphics!*/ -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), - only screen and (min--moz-device-pixel-ratio: 1.5), - only screen and (min-device-pixel-ratio: 1.5){ - - #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span { - background-image: url('fancybox_sprite@2x.png'); - background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/ - } - - #fancybox-loading div { - background-image: url('fancybox_loading@2x.gif'); - background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/ - } -} \ No newline at end of file diff --git a/vendors/fancybox/source/jquery.fancybox.js b/vendors/fancybox/source/jquery.fancybox.js deleted file mode 100644 index e8e1987..0000000 --- a/vendors/fancybox/source/jquery.fancybox.js +++ /dev/null @@ -1,2020 +0,0 @@ -/*! - * fancyBox - jQuery Plugin - * version: 2.1.5 (Fri, 14 Jun 2013) - * @requires jQuery v1.6 or later - * - * Examples at http://fancyapps.com/fancybox/ - * License: www.fancyapps.com/fancybox/#license - * - * Copyright 2012 Janis Skarnelis - janis@fancyapps.com - * - */ - -(function (window, document, $, undefined) { - "use strict"; - - var H = $("html"), - W = $(window), - D = $(document), - F = $.fancybox = function () { - F.open.apply( this, arguments ); - }, - IE = navigator.userAgent.match(/msie/i), - didUpdate = null, - isTouch = document.createTouch !== undefined, - - isQuery = function(obj) { - return obj && obj.hasOwnProperty && obj instanceof $; - }, - isString = function(str) { - return str && $.type(str) === "string"; - }, - isPercentage = function(str) { - return isString(str) && str.indexOf('%') > 0; - }, - isScrollable = function(el) { - return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight))); - }, - getScalar = function(orig, dim) { - var value = parseInt(orig, 10) || 0; - - if (dim && isPercentage(orig)) { - value = F.getViewport()[ dim ] / 100 * value; - } - - return Math.ceil(value); - }, - getValue = function(value, dim) { - return getScalar(value, dim) + 'px'; - }; - - $.extend(F, { - // The current version of fancyBox - version: '2.1.5', - - defaults: { - padding : 15, - margin : 20, - - width : 800, - height : 600, - minWidth : 100, - minHeight : 100, - maxWidth : 9999, - maxHeight : 9999, - pixelRatio: 1, // Set to 2 for retina display support - - autoSize : true, - autoHeight : false, - autoWidth : false, - - autoResize : true, - autoCenter : !isTouch, - fitToView : true, - aspectRatio : false, - topRatio : 0.5, - leftRatio : 0.5, - - scrolling : 'auto', // 'auto', 'yes' or 'no' - wrapCSS : '', - - arrows : true, - closeBtn : true, - closeClick : false, - nextClick : false, - mouseWheel : true, - autoPlay : false, - playSpeed : 3000, - preload : 3, - modal : false, - loop : true, - - ajax : { - dataType : 'html', - headers : { 'X-fancyBox': true } - }, - iframe : { - scrolling : 'auto', - preload : true - }, - swf : { - wmode: 'transparent', - allowfullscreen : 'true', - allowscriptaccess : 'always' - }, - - keys : { - next : { - 13 : 'left', // enter - 34 : 'up', // page down - 39 : 'left', // right arrow - 40 : 'up' // down arrow - }, - prev : { - 8 : 'right', // backspace - 33 : 'down', // page up - 37 : 'right', // left arrow - 38 : 'down' // up arrow - }, - close : [27], // escape key - play : [32], // space - start/stop slideshow - toggle : [70] // letter "f" - toggle fullscreen - }, - - direction : { - next : 'left', - prev : 'right' - }, - - scrollOutside : true, - - // Override some properties - index : 0, - type : null, - href : null, - content : null, - title : null, - - // HTML templates - tpl: { - wrap : '
    ', - image : '', - iframe : '', - error : '

    The requested content cannot be loaded.
    Please try again later.

    ', - closeBtn : '', - next : '', - prev : '' - }, - - // Properties for each animation type - // Opening fancyBox - openEffect : 'fade', // 'elastic', 'fade' or 'none' - openSpeed : 250, - openEasing : 'swing', - openOpacity : true, - openMethod : 'zoomIn', - - // Closing fancyBox - closeEffect : 'fade', // 'elastic', 'fade' or 'none' - closeSpeed : 250, - closeEasing : 'swing', - closeOpacity : true, - closeMethod : 'zoomOut', - - // Changing next gallery item - nextEffect : 'elastic', // 'elastic', 'fade' or 'none' - nextSpeed : 250, - nextEasing : 'swing', - nextMethod : 'changeIn', - - // Changing previous gallery item - prevEffect : 'elastic', // 'elastic', 'fade' or 'none' - prevSpeed : 250, - prevEasing : 'swing', - prevMethod : 'changeOut', - - // Enable default helpers - helpers : { - overlay : true, - title : true - }, - - // Callbacks - onCancel : $.noop, // If canceling - beforeLoad : $.noop, // Before loading - afterLoad : $.noop, // After loading - beforeShow : $.noop, // Before changing in current item - afterShow : $.noop, // After opening - beforeChange : $.noop, // Before changing gallery item - beforeClose : $.noop, // Before closing - afterClose : $.noop // After closing - }, - - //Current state - group : {}, // Selected group - opts : {}, // Group options - previous : null, // Previous element - coming : null, // Element being loaded - current : null, // Currently loaded element - isActive : false, // Is activated - isOpen : false, // Is currently open - isOpened : false, // Have been fully opened at least once - - wrap : null, - skin : null, - outer : null, - inner : null, - - player : { - timer : null, - isActive : false - }, - - // Loaders - ajaxLoad : null, - imgPreload : null, - - // Some collections - transitions : {}, - helpers : {}, - - /* - * Static methods - */ - - open: function (group, opts) { - if (!group) { - return; - } - - if (!$.isPlainObject(opts)) { - opts = {}; - } - - // Close if already active - if (false === F.close(true)) { - return; - } - - // Normalize group - if (!$.isArray(group)) { - group = isQuery(group) ? $(group).get() : [group]; - } - - // Recheck if the type of each element is `object` and set content type (image, ajax, etc) - $.each(group, function(i, element) { - var obj = {}, - href, - title, - content, - type, - rez, - hrefParts, - selector; - - if ($.type(element) === "object") { - // Check if is DOM element - if (element.nodeType) { - element = $(element); - } - - if (isQuery(element)) { - obj = { - href : element.data('fancybox-href') || element.attr('href'), - title : element.data('fancybox-title') || element.attr('title'), - isDom : true, - element : element - }; - - if ($.metadata) { - $.extend(true, obj, element.metadata()); - } - - } else { - obj = element; - } - } - - href = opts.href || obj.href || (isString(element) ? element : null); - title = opts.title !== undefined ? opts.title : obj.title || ''; - - content = opts.content || obj.content; - type = content ? 'html' : (opts.type || obj.type); - - if (!type && obj.isDom) { - type = element.data('fancybox-type'); - - if (!type) { - rez = element.prop('class').match(/fancybox\.(\w+)/); - type = rez ? rez[1] : null; - } - } - - if (isString(href)) { - // Try to guess the content type - if (!type) { - if (F.isImage(href)) { - type = 'image'; - - } else if (F.isSWF(href)) { - type = 'swf'; - - } else if (href.charAt(0) === '#') { - type = 'inline'; - - } else if (isString(element)) { - type = 'html'; - content = element; - } - } - - // Split url into two pieces with source url and content selector, e.g, - // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id" - if (type === 'ajax') { - hrefParts = href.split(/\s+/, 2); - href = hrefParts.shift(); - selector = hrefParts.shift(); - } - } - - if (!content) { - if (type === 'inline') { - if (href) { - content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7 - - } else if (obj.isDom) { - content = element; - } - - } else if (type === 'html') { - content = href; - - } else if (!type && !href && obj.isDom) { - type = 'inline'; - content = element; - } - } - - $.extend(obj, { - href : href, - type : type, - content : content, - title : title, - selector : selector - }); - - group[ i ] = obj; - }); - - // Extend the defaults - F.opts = $.extend(true, {}, F.defaults, opts); - - // All options are merged recursive except keys - if (opts.keys !== undefined) { - F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false; - } - - F.group = group; - - return F._start(F.opts.index); - }, - - // Cancel image loading or abort ajax request - cancel: function () { - var coming = F.coming; - - if (!coming || false === F.trigger('onCancel')) { - return; - } - - F.hideLoading(); - - if (F.ajaxLoad) { - F.ajaxLoad.abort(); - } - - F.ajaxLoad = null; - - if (F.imgPreload) { - F.imgPreload.onload = F.imgPreload.onerror = null; - } - - if (coming.wrap) { - coming.wrap.stop(true, true).trigger('onReset').remove(); - } - - F.coming = null; - - // If the first item has been canceled, then clear everything - if (!F.current) { - F._afterZoomOut( coming ); - } - }, - - // Start closing animation if is open; remove immediately if opening/closing - close: function (event) { - F.cancel(); - - if (false === F.trigger('beforeClose')) { - return; - } - - F.unbindEvents(); - - if (!F.isActive) { - return; - } - - if (!F.isOpen || event === true) { - $('.fancybox-wrap').stop(true).trigger('onReset').remove(); - - F._afterZoomOut(); - - } else { - F.isOpen = F.isOpened = false; - F.isClosing = true; - - $('.fancybox-item, .fancybox-nav').remove(); - - F.wrap.stop(true, true).removeClass('fancybox-opened'); - - F.transitions[ F.current.closeMethod ](); - } - }, - - // Manage slideshow: - // $.fancybox.play(); - toggle slideshow - // $.fancybox.play( true ); - start - // $.fancybox.play( false ); - stop - play: function ( action ) { - var clear = function () { - clearTimeout(F.player.timer); - }, - set = function () { - clear(); - - if (F.current && F.player.isActive) { - F.player.timer = setTimeout(F.next, F.current.playSpeed); - } - }, - stop = function () { - clear(); - - D.unbind('.player'); - - F.player.isActive = false; - - F.trigger('onPlayEnd'); - }, - start = function () { - if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) { - F.player.isActive = true; - - D.bind({ - 'onCancel.player beforeClose.player' : stop, - 'onUpdate.player' : set, - 'beforeLoad.player' : clear - }); - - set(); - - F.trigger('onPlayStart'); - } - }; - - if (action === true || (!F.player.isActive && action !== false)) { - start(); - } else { - stop(); - } - }, - - // Navigate to next gallery item - next: function ( direction ) { - var current = F.current; - - if (current) { - if (!isString(direction)) { - direction = current.direction.next; - } - - F.jumpto(current.index + 1, direction, 'next'); - } - }, - - // Navigate to previous gallery item - prev: function ( direction ) { - var current = F.current; - - if (current) { - if (!isString(direction)) { - direction = current.direction.prev; - } - - F.jumpto(current.index - 1, direction, 'prev'); - } - }, - - // Navigate to gallery item by index - jumpto: function ( index, direction, router ) { - var current = F.current; - - if (!current) { - return; - } - - index = getScalar(index); - - F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ]; - F.router = router || 'jumpto'; - - if (current.loop) { - if (index < 0) { - index = current.group.length + (index % current.group.length); - } - - index = index % current.group.length; - } - - if (current.group[ index ] !== undefined) { - F.cancel(); - - F._start(index); - } - }, - - // Center inside viewport and toggle position type to fixed or absolute if needed - reposition: function (e, onlyAbsolute) { - var current = F.current, - wrap = current ? current.wrap : null, - pos; - - if (wrap) { - pos = F._getPosition(onlyAbsolute); - - if (e && e.type === 'scroll') { - delete pos.position; - - wrap.stop(true, true).animate(pos, 200); - - } else { - wrap.css(pos); - - current.pos = $.extend({}, current.dim, pos); - } - } - }, - - update: function (e) { - var type = (e && e.type), - anyway = !type || type === 'orientationchange'; - - if (anyway) { - clearTimeout(didUpdate); - - didUpdate = null; - } - - if (!F.isOpen || didUpdate) { - return; - } - - didUpdate = setTimeout(function() { - var current = F.current; - - if (!current || F.isClosing) { - return; - } - - F.wrap.removeClass('fancybox-tmp'); - - if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) { - F._setDimension(); - } - - if (!(type === 'scroll' && current.canShrink)) { - F.reposition(e); - } - - F.trigger('onUpdate'); - - didUpdate = null; - - }, (anyway && !isTouch ? 0 : 300)); - }, - - // Shrink content to fit inside viewport or restore if resized - toggle: function ( action ) { - if (F.isOpen) { - F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView; - - // Help browser to restore document dimensions - if (isTouch) { - F.wrap.removeAttr('style').addClass('fancybox-tmp'); - - F.trigger('onUpdate'); - } - - F.update(); - } - }, - - hideLoading: function () { - D.unbind('.loading'); - - $('#fancybox-loading').remove(); - }, - - showLoading: function () { - var el, viewport; - - F.hideLoading(); - - el = $('
    ').click(F.cancel).appendTo('body'); - - // If user will press the escape-button, the request will be canceled - D.bind('keydown.loading', function(e) { - if ((e.which || e.keyCode) === 27) { - e.preventDefault(); - - F.cancel(); - } - }); - - if (!F.defaults.fixed) { - viewport = F.getViewport(); - - el.css({ - position : 'absolute', - top : (viewport.h * 0.5) + viewport.y, - left : (viewport.w * 0.5) + viewport.x - }); - } - }, - - getViewport: function () { - var locked = (F.current && F.current.locked) || false, - rez = { - x: W.scrollLeft(), - y: W.scrollTop() - }; - - if (locked) { - rez.w = locked[0].clientWidth; - rez.h = locked[0].clientHeight; - - } else { - // See http://bugs.jquery.com/ticket/6724 - rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width(); - rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height(); - } - - return rez; - }, - - // Unbind the keyboard / clicking actions - unbindEvents: function () { - if (F.wrap && isQuery(F.wrap)) { - F.wrap.unbind('.fb'); - } - - D.unbind('.fb'); - W.unbind('.fb'); - }, - - bindEvents: function () { - var current = F.current, - keys; - - if (!current) { - return; - } - - // Changing document height on iOS devices triggers a 'resize' event, - // that can change document height... repeating infinitely - W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update); - - keys = current.keys; - - if (keys) { - D.bind('keydown.fb', function (e) { - var code = e.which || e.keyCode, - target = e.target || e.srcElement; - - // Skip esc key if loading, because showLoading will cancel preloading - if (code === 27 && F.coming) { - return false; - } - - // Ignore key combinations and key events within form elements - if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) { - $.each(keys, function(i, val) { - if (current.group.length > 1 && val[ code ] !== undefined) { - F[ i ]( val[ code ] ); - - e.preventDefault(); - return false; - } - - if ($.inArray(code, val) > -1) { - F[ i ] (); - - e.preventDefault(); - return false; - } - }); - } - }); - } - - if ($.fn.mousewheel && current.mouseWheel) { - F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) { - var target = e.target || null, - parent = $(target), - canScroll = false; - - while (parent.length) { - if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) { - break; - } - - canScroll = isScrollable( parent[0] ); - parent = $(parent).parent(); - } - - if (delta !== 0 && !canScroll) { - if (F.group.length > 1 && !current.canShrink) { - if (deltaY > 0 || deltaX > 0) { - F.prev( deltaY > 0 ? 'down' : 'left' ); - - } else if (deltaY < 0 || deltaX < 0) { - F.next( deltaY < 0 ? 'up' : 'right' ); - } - - e.preventDefault(); - } - } - }); - } - }, - - trigger: function (event, o) { - var ret, obj = o || F.coming || F.current; - - if (!obj) { - return; - } - - if ($.isFunction( obj[event] )) { - ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1)); - } - - if (ret === false) { - return false; - } - - if (obj.helpers) { - $.each(obj.helpers, function (helper, opts) { - if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) { - F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj); - } - }); - } - - D.trigger(event); - }, - - isImage: function (str) { - return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); - }, - - isSWF: function (str) { - return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i); - }, - - _start: function (index) { - var coming = {}, - obj, - href, - type, - margin, - padding; - - index = getScalar( index ); - obj = F.group[ index ] || null; - - if (!obj) { - return false; - } - - coming = $.extend(true, {}, F.opts, obj); - - // Convert margin and padding properties to array - top, right, bottom, left - margin = coming.margin; - padding = coming.padding; - - if ($.type(margin) === 'number') { - coming.margin = [margin, margin, margin, margin]; - } - - if ($.type(padding) === 'number') { - coming.padding = [padding, padding, padding, padding]; - } - - // 'modal' propery is just a shortcut - if (coming.modal) { - $.extend(true, coming, { - closeBtn : false, - closeClick : false, - nextClick : false, - arrows : false, - mouseWheel : false, - keys : null, - helpers: { - overlay : { - closeClick : false - } - } - }); - } - - // 'autoSize' property is a shortcut, too - if (coming.autoSize) { - coming.autoWidth = coming.autoHeight = true; - } - - if (coming.width === 'auto') { - coming.autoWidth = true; - } - - if (coming.height === 'auto') { - coming.autoHeight = true; - } - - /* - * Add reference to the group, so it`s possible to access from callbacks, example: - * afterLoad : function() { - * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : ''); - * } - */ - - coming.group = F.group; - coming.index = index; - - // Give a chance for callback or helpers to update coming item (type, title, etc) - F.coming = coming; - - if (false === F.trigger('beforeLoad')) { - F.coming = null; - - return; - } - - type = coming.type; - href = coming.href; - - if (!type) { - F.coming = null; - - //If we can not determine content type then drop silently or display next/prev item if looping through gallery - if (F.current && F.router && F.router !== 'jumpto') { - F.current.index = index; - - return F[ F.router ]( F.direction ); - } - - return false; - } - - F.isActive = true; - - if (type === 'image' || type === 'swf') { - coming.autoHeight = coming.autoWidth = false; - coming.scrolling = 'visible'; - } - - if (type === 'image') { - coming.aspectRatio = true; - } - - if (type === 'iframe' && isTouch) { - coming.scrolling = 'scroll'; - } - - // Build the neccessary markup - coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' ); - - $.extend(coming, { - skin : $('.fancybox-skin', coming.wrap), - outer : $('.fancybox-outer', coming.wrap), - inner : $('.fancybox-inner', coming.wrap) - }); - - $.each(["Top", "Right", "Bottom", "Left"], function(i, v) { - coming.skin.css('padding' + v, getValue(coming.padding[ i ])); - }); - - F.trigger('onReady'); - - // Check before try to load; 'inline' and 'html' types need content, others - href - if (type === 'inline' || type === 'html') { - if (!coming.content || !coming.content.length) { - return F._error( 'content' ); - } - - } else if (!href) { - return F._error( 'href' ); - } - - if (type === 'image') { - F._loadImage(); - - } else if (type === 'ajax') { - F._loadAjax(); - - } else if (type === 'iframe') { - F._loadIframe(); - - } else { - F._afterLoad(); - } - }, - - _error: function ( type ) { - $.extend(F.coming, { - type : 'html', - autoWidth : true, - autoHeight : true, - minWidth : 0, - minHeight : 0, - scrolling : 'no', - hasError : type, - content : F.coming.tpl.error - }); - - F._afterLoad(); - }, - - _loadImage: function () { - // Reset preload image so it is later possible to check "complete" property - var img = F.imgPreload = new Image(); - - img.onload = function () { - this.onload = this.onerror = null; - - F.coming.width = this.width / F.opts.pixelRatio; - F.coming.height = this.height / F.opts.pixelRatio; - - F._afterLoad(); - }; - - img.onerror = function () { - this.onload = this.onerror = null; - - F._error( 'image' ); - }; - - img.src = F.coming.href; - - if (img.complete !== true) { - F.showLoading(); - } - }, - - _loadAjax: function () { - var coming = F.coming; - - F.showLoading(); - - F.ajaxLoad = $.ajax($.extend({}, coming.ajax, { - url: coming.href, - error: function (jqXHR, textStatus) { - if (F.coming && textStatus !== 'abort') { - F._error( 'ajax', jqXHR ); - - } else { - F.hideLoading(); - } - }, - success: function (data, textStatus) { - if (textStatus === 'success') { - coming.content = data; - - F._afterLoad(); - } - } - })); - }, - - _loadIframe: function() { - var coming = F.coming, - iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())) - .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling) - .attr('src', coming.href); - - // This helps IE - $(coming.wrap).bind('onReset', function () { - try { - $(this).find('iframe').hide().attr('src', '//about:blank').end().empty(); - } catch (e) {} - }); - - if (coming.iframe.preload) { - F.showLoading(); - - iframe.one('load', function() { - $(this).data('ready', 1); - - // iOS will lose scrolling if we resize - if (!isTouch) { - $(this).bind('load.fb', F.update); - } - - // Without this trick: - // - iframe won't scroll on iOS devices - // - IE7 sometimes displays empty iframe - $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show(); - - F._afterLoad(); - }); - } - - coming.content = iframe.appendTo( coming.inner ); - - if (!coming.iframe.preload) { - F._afterLoad(); - } - }, - - _preloadImages: function() { - var group = F.group, - current = F.current, - len = group.length, - cnt = current.preload ? Math.min(current.preload, len - 1) : 0, - item, - i; - - for (i = 1; i <= cnt; i += 1) { - item = group[ (current.index + i ) % len ]; - - if (item.type === 'image' && item.href) { - new Image().src = item.href; - } - } - }, - - _afterLoad: function () { - var coming = F.coming, - previous = F.current, - placeholder = 'fancybox-placeholder', - current, - content, - type, - scrolling, - href, - embed; - - F.hideLoading(); - - if (!coming || F.isActive === false) { - return; - } - - if (false === F.trigger('afterLoad', coming, previous)) { - coming.wrap.stop(true).trigger('onReset').remove(); - - F.coming = null; - - return; - } - - if (previous) { - F.trigger('beforeChange', previous); - - previous.wrap.stop(true).removeClass('fancybox-opened') - .find('.fancybox-item, .fancybox-nav') - .remove(); - } - - F.unbindEvents(); - - current = coming; - content = coming.content; - type = coming.type; - scrolling = coming.scrolling; - - $.extend(F, { - wrap : current.wrap, - skin : current.skin, - outer : current.outer, - inner : current.inner, - current : current, - previous : previous - }); - - href = current.href; - - switch (type) { - case 'inline': - case 'ajax': - case 'html': - if (current.selector) { - content = $('
    ').html(content).find(current.selector); - - } else if (isQuery(content)) { - if (!content.data(placeholder)) { - content.data(placeholder, $('
    ').insertAfter( content ).hide() ); - } - - content = content.show().detach(); - - current.wrap.bind('onReset', function () { - if ($(this).find(content).length) { - content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false); - } - }); - } - break; - - case 'image': - content = current.tpl.image.replace('{href}', href); - break; - - case 'swf': - content = ''; - embed = ''; - - $.each(current.swf, function(name, val) { - content += ''; - embed += ' ' + name + '="' + val + '"'; - }); - - content += ''; - break; - } - - if (!(isQuery(content) && content.parent().is(current.inner))) { - current.inner.append( content ); - } - - // Give a chance for helpers or callbacks to update elements - F.trigger('beforeShow'); - - // Set scrolling before calculating dimensions - current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling)); - - // Set initial dimensions and start position - F._setDimension(); - - F.reposition(); - - F.isOpen = false; - F.coming = null; - - F.bindEvents(); - - if (!F.isOpened) { - $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove(); - - } else if (previous.prevMethod) { - F.transitions[ previous.prevMethod ](); - } - - F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ](); - - F._preloadImages(); - }, - - _setDimension: function () { - var viewport = F.getViewport(), - steps = 0, - canShrink = false, - canExpand = false, - wrap = F.wrap, - skin = F.skin, - inner = F.inner, - current = F.current, - width = current.width, - height = current.height, - minWidth = current.minWidth, - minHeight = current.minHeight, - maxWidth = current.maxWidth, - maxHeight = current.maxHeight, - scrolling = current.scrolling, - scrollOut = current.scrollOutside ? current.scrollbarWidth : 0, - margin = current.margin, - wMargin = getScalar(margin[1] + margin[3]), - hMargin = getScalar(margin[0] + margin[2]), - wPadding, - hPadding, - wSpace, - hSpace, - origWidth, - origHeight, - origMaxWidth, - origMaxHeight, - ratio, - width_, - height_, - maxWidth_, - maxHeight_, - iframe, - body; - - // Reset dimensions so we could re-check actual size - wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp'); - - wPadding = getScalar(skin.outerWidth(true) - skin.width()); - hPadding = getScalar(skin.outerHeight(true) - skin.height()); - - // Any space between content and viewport (margin, padding, border, title) - wSpace = wMargin + wPadding; - hSpace = hMargin + hPadding; - - origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width; - origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height; - - if (current.type === 'iframe') { - iframe = current.content; - - if (current.autoHeight && iframe.data('ready') === 1) { - try { - if (iframe[0].contentWindow.document.location) { - inner.width( origWidth ).height(9999); - - body = iframe.contents().find('body'); - - if (scrollOut) { - body.css('overflow-x', 'hidden'); - } - - origHeight = body.outerHeight(true); - } - - } catch (e) {} - } - - } else if (current.autoWidth || current.autoHeight) { - inner.addClass( 'fancybox-tmp' ); - - // Set width or height in case we need to calculate only one dimension - if (!current.autoWidth) { - inner.width( origWidth ); - } - - if (!current.autoHeight) { - inner.height( origHeight ); - } - - if (current.autoWidth) { - origWidth = inner.width(); - } - - if (current.autoHeight) { - origHeight = inner.height(); - } - - inner.removeClass( 'fancybox-tmp' ); - } - - width = getScalar( origWidth ); - height = getScalar( origHeight ); - - ratio = origWidth / origHeight; - - // Calculations for the content - minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth); - maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth); - - minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight); - maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight); - - // These will be used to determine if wrap can fit in the viewport - origMaxWidth = maxWidth; - origMaxHeight = maxHeight; - - if (current.fitToView) { - maxWidth = Math.min(viewport.w - wSpace, maxWidth); - maxHeight = Math.min(viewport.h - hSpace, maxHeight); - } - - maxWidth_ = viewport.w - wMargin; - maxHeight_ = viewport.h - hMargin; - - if (current.aspectRatio) { - if (width > maxWidth) { - width = maxWidth; - height = getScalar(width / ratio); - } - - if (height > maxHeight) { - height = maxHeight; - width = getScalar(height * ratio); - } - - if (width < minWidth) { - width = minWidth; - height = getScalar(width / ratio); - } - - if (height < minHeight) { - height = minHeight; - width = getScalar(height * ratio); - } - - } else { - width = Math.max(minWidth, Math.min(width, maxWidth)); - - if (current.autoHeight && current.type !== 'iframe') { - inner.width( width ); - - height = inner.height(); - } - - height = Math.max(minHeight, Math.min(height, maxHeight)); - } - - // Try to fit inside viewport (including the title) - if (current.fitToView) { - inner.width( width ).height( height ); - - wrap.width( width + wPadding ); - - // Real wrap dimensions - width_ = wrap.width(); - height_ = wrap.height(); - - if (current.aspectRatio) { - while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) { - if (steps++ > 19) { - break; - } - - height = Math.max(minHeight, Math.min(maxHeight, height - 10)); - width = getScalar(height * ratio); - - if (width < minWidth) { - width = minWidth; - height = getScalar(width / ratio); - } - - if (width > maxWidth) { - width = maxWidth; - height = getScalar(width / ratio); - } - - inner.width( width ).height( height ); - - wrap.width( width + wPadding ); - - width_ = wrap.width(); - height_ = wrap.height(); - } - - } else { - width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_))); - height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_))); - } - } - - if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) { - width += scrollOut; - } - - inner.width( width ).height( height ); - - wrap.width( width + wPadding ); - - width_ = wrap.width(); - height_ = wrap.height(); - - canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight; - canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight)); - - $.extend(current, { - dim : { - width : getValue( width_ ), - height : getValue( height_ ) - }, - origWidth : origWidth, - origHeight : origHeight, - canShrink : canShrink, - canExpand : canExpand, - wPadding : wPadding, - hPadding : hPadding, - wrapSpace : height_ - skin.outerHeight(true), - skinSpace : skin.height() - height - }); - - if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) { - inner.height('auto'); - } - }, - - _getPosition: function (onlyAbsolute) { - var current = F.current, - viewport = F.getViewport(), - margin = current.margin, - width = F.wrap.width() + margin[1] + margin[3], - height = F.wrap.height() + margin[0] + margin[2], - rez = { - position: 'absolute', - top : margin[0], - left : margin[3] - }; - - if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) { - rez.position = 'fixed'; - - } else if (!current.locked) { - rez.top += viewport.y; - rez.left += viewport.x; - } - - rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))); - rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio))); - - return rez; - }, - - _afterZoomIn: function () { - var current = F.current; - - if (!current) { - return; - } - - F.isOpen = F.isOpened = true; - - F.wrap.css('overflow', 'visible').addClass('fancybox-opened'); - - F.update(); - - // Assign a click event - if ( current.closeClick || (current.nextClick && F.group.length > 1) ) { - F.inner.css('cursor', 'pointer').bind('click.fb', function(e) { - if (!$(e.target).is('a') && !$(e.target).parent().is('a')) { - e.preventDefault(); - - F[ current.closeClick ? 'close' : 'next' ](); - } - }); - } - - // Create a close button - if (current.closeBtn) { - $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) { - e.preventDefault(); - - F.close(); - }); - } - - // Create navigation arrows - if (current.arrows && F.group.length > 1) { - if (current.loop || current.index > 0) { - $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev); - } - - if (current.loop || current.index < F.group.length - 1) { - $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next); - } - } - - F.trigger('afterShow'); - - // Stop the slideshow if this is the last item - if (!current.loop && current.index === current.group.length - 1) { - F.play( false ); - - } else if (F.opts.autoPlay && !F.player.isActive) { - F.opts.autoPlay = false; - - F.play(); - } - }, - - _afterZoomOut: function ( obj ) { - obj = obj || F.current; - - $('.fancybox-wrap').trigger('onReset').remove(); - - $.extend(F, { - group : {}, - opts : {}, - router : false, - current : null, - isActive : false, - isOpened : false, - isOpen : false, - isClosing : false, - wrap : null, - skin : null, - outer : null, - inner : null - }); - - F.trigger('afterClose', obj); - } - }); - - /* - * Default transitions - */ - - F.transitions = { - getOrigPosition: function () { - var current = F.current, - element = current.element, - orig = current.orig, - pos = {}, - width = 50, - height = 50, - hPadding = current.hPadding, - wPadding = current.wPadding, - viewport = F.getViewport(); - - if (!orig && current.isDom && element.is(':visible')) { - orig = element.find('img:first'); - - if (!orig.length) { - orig = element; - } - } - - if (isQuery(orig)) { - pos = orig.offset(); - - if (orig.is('img')) { - width = orig.outerWidth(); - height = orig.outerHeight(); - } - - } else { - pos.top = viewport.y + (viewport.h - height) * current.topRatio; - pos.left = viewport.x + (viewport.w - width) * current.leftRatio; - } - - if (F.wrap.css('position') === 'fixed' || current.locked) { - pos.top -= viewport.y; - pos.left -= viewport.x; - } - - pos = { - top : getValue(pos.top - hPadding * current.topRatio), - left : getValue(pos.left - wPadding * current.leftRatio), - width : getValue(width + wPadding), - height : getValue(height + hPadding) - }; - - return pos; - }, - - step: function (now, fx) { - var ratio, - padding, - value, - prop = fx.prop, - current = F.current, - wrapSpace = current.wrapSpace, - skinSpace = current.skinSpace; - - if (prop === 'width' || prop === 'height') { - ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start); - - if (F.isClosing) { - ratio = 1 - ratio; - } - - padding = prop === 'width' ? current.wPadding : current.hPadding; - value = now - padding; - - F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) ); - F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) ); - } - }, - - zoomIn: function () { - var current = F.current, - startPos = current.pos, - effect = current.openEffect, - elastic = effect === 'elastic', - endPos = $.extend({opacity : 1}, startPos); - - // Remove "position" property that breaks older IE - delete endPos.position; - - if (elastic) { - startPos = this.getOrigPosition(); - - if (current.openOpacity) { - startPos.opacity = 0.1; - } - - } else if (effect === 'fade') { - startPos.opacity = 0.1; - } - - F.wrap.css(startPos).animate(endPos, { - duration : effect === 'none' ? 0 : current.openSpeed, - easing : current.openEasing, - step : elastic ? this.step : null, - complete : F._afterZoomIn - }); - }, - - zoomOut: function () { - var current = F.current, - effect = current.closeEffect, - elastic = effect === 'elastic', - endPos = {opacity : 0.1}; - - if (elastic) { - endPos = this.getOrigPosition(); - - if (current.closeOpacity) { - endPos.opacity = 0.1; - } - } - - F.wrap.animate(endPos, { - duration : effect === 'none' ? 0 : current.closeSpeed, - easing : current.closeEasing, - step : elastic ? this.step : null, - complete : F._afterZoomOut - }); - }, - - changeIn: function () { - var current = F.current, - effect = current.nextEffect, - startPos = current.pos, - endPos = { opacity : 1 }, - direction = F.direction, - distance = 200, - field; - - startPos.opacity = 0.1; - - if (effect === 'elastic') { - field = direction === 'down' || direction === 'up' ? 'top' : 'left'; - - if (direction === 'down' || direction === 'right') { - startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance); - endPos[ field ] = '+=' + distance + 'px'; - - } else { - startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance); - endPos[ field ] = '-=' + distance + 'px'; - } - } - - // Workaround for http://bugs.jquery.com/ticket/12273 - if (effect === 'none') { - F._afterZoomIn(); - - } else { - F.wrap.css(startPos).animate(endPos, { - duration : current.nextSpeed, - easing : current.nextEasing, - complete : F._afterZoomIn - }); - } - }, - - changeOut: function () { - var previous = F.previous, - effect = previous.prevEffect, - endPos = { opacity : 0.1 }, - direction = F.direction, - distance = 200; - - if (effect === 'elastic') { - endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px'; - } - - previous.wrap.animate(endPos, { - duration : effect === 'none' ? 0 : previous.prevSpeed, - easing : previous.prevEasing, - complete : function () { - $(this).trigger('onReset').remove(); - } - }); - } - }; - - /* - * Overlay helper - */ - - F.helpers.overlay = { - defaults : { - closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay - speedOut : 200, // duration of fadeOut animation - showEarly : true, // indicates if should be opened immediately or wait until the content is ready - css : {}, // custom CSS properties - locked : !isTouch, // if true, the content will be locked into overlay - fixed : true // if false, the overlay CSS position property will not be set to "fixed" - }, - - overlay : null, // current handle - fixed : false, // indicates if the overlay has position "fixed" - el : $('html'), // element that contains "the lock" - - // Public methods - create : function(opts) { - opts = $.extend({}, this.defaults, opts); - - if (this.overlay) { - this.close(); - } - - this.overlay = $('
    ').appendTo( F.coming ? F.coming.parent : opts.parent ); - this.fixed = false; - - if (opts.fixed && F.defaults.fixed) { - this.overlay.addClass('fancybox-overlay-fixed'); - - this.fixed = true; - } - }, - - open : function(opts) { - var that = this; - - opts = $.extend({}, this.defaults, opts); - - if (this.overlay) { - this.overlay.unbind('.overlay').width('auto').height('auto'); - - } else { - this.create(opts); - } - - if (!this.fixed) { - W.bind('resize.overlay', $.proxy( this.update, this) ); - - this.update(); - } - - if (opts.closeClick) { - this.overlay.bind('click.overlay', function(e) { - if ($(e.target).hasClass('fancybox-overlay')) { - if (F.isActive) { - F.close(); - } else { - that.close(); - } - - return false; - } - }); - } - - this.overlay.css( opts.css ).show(); - }, - - close : function() { - var scrollV, scrollH; - - W.unbind('resize.overlay'); - - if (this.el.hasClass('fancybox-lock')) { - $('.fancybox-margin').removeClass('fancybox-margin'); - - scrollV = W.scrollTop(); - scrollH = W.scrollLeft(); - - this.el.removeClass('fancybox-lock'); - - W.scrollTop( scrollV ).scrollLeft( scrollH ); - } - - $('.fancybox-overlay').remove().hide(); - - $.extend(this, { - overlay : null, - fixed : false - }); - }, - - // Private, callbacks - - update : function () { - var width = '100%', offsetWidth; - - // Reset width/height so it will not mess - this.overlay.width(width).height('100%'); - - // jQuery does not return reliable result for IE - if (IE) { - offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth); - - if (D.width() > offsetWidth) { - width = D.width(); - } - - } else if (D.width() > W.width()) { - width = D.width(); - } - - this.overlay.width(width).height(D.height()); - }, - - // This is where we can manipulate DOM, because later it would cause iframes to reload - onReady : function (opts, obj) { - var overlay = this.overlay; - - $('.fancybox-overlay').stop(true, true); - - if (!overlay) { - this.create(opts); - } - - if (opts.locked && this.fixed && obj.fixed) { - if (!overlay) { - this.margin = D.height() > W.height() ? $('html').css('margin-right').replace("px", "") : false; - } - - obj.locked = this.overlay.append( obj.wrap ); - obj.fixed = false; - } - - if (opts.showEarly === true) { - this.beforeShow.apply(this, arguments); - } - }, - - beforeShow : function(opts, obj) { - var scrollV, scrollH; - - if (obj.locked) { - if (this.margin !== false) { - $('*').filter(function(){ - return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") ); - }).addClass('fancybox-margin'); - - this.el.addClass('fancybox-margin'); - } - - scrollV = W.scrollTop(); - scrollH = W.scrollLeft(); - - this.el.addClass('fancybox-lock'); - - W.scrollTop( scrollV ).scrollLeft( scrollH ); - } - - this.open(opts); - }, - - onUpdate : function() { - if (!this.fixed) { - this.update(); - } - }, - - afterClose: function (opts) { - // Remove overlay if exists and fancyBox is not opening - // (e.g., it is not being open using afterClose callback) - //if (this.overlay && !F.isActive) { - if (this.overlay && !F.coming) { - this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this )); - } - } - }; - - /* - * Title helper - */ - - F.helpers.title = { - defaults : { - type : 'float', // 'float', 'inside', 'outside' or 'over', - position : 'bottom' // 'top' or 'bottom' - }, - - beforeShow: function (opts) { - var current = F.current, - text = current.title, - type = opts.type, - title, - target; - - if ($.isFunction(text)) { - text = text.call(current.element, current); - } - - if (!isString(text) || $.trim(text) === '') { - return; - } - - title = $('
    ' + text + '
    '); - - switch (type) { - case 'inside': - target = F.skin; - break; - - case 'outside': - target = F.wrap; - break; - - case 'over': - target = F.inner; - break; - - default: // 'float' - target = F.skin; - - title.appendTo('body'); - - if (IE) { - title.width( title.width() ); - } - - title.wrapInner(''); - - //Increase bottom margin so this title will also fit into viewport - F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) ); - break; - } - - title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target); - } - }; - - // jQuery plugin initialization - $.fn.fancybox = function (options) { - var index, - that = $(this), - selector = this.selector || '', - run = function(e) { - var what = $(this).blur(), idx = index, relType, relVal; - - if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) { - relType = options.groupAttr || 'data-fancybox-group'; - relVal = what.attr(relType); - - if (!relVal) { - relType = 'rel'; - relVal = what.get(0)[ relType ]; - } - - if (relVal && relVal !== '' && relVal !== 'nofollow') { - what = selector.length ? $(selector) : that; - what = what.filter('[' + relType + '="' + relVal + '"]'); - idx = what.index(this); - } - - options.index = idx; - - // Stop an event from bubbling if everything is fine - if (F.open(what, options) !== false) { - e.preventDefault(); - } - } - }; - - options = options || {}; - index = options.index || 0; - - if (!selector || options.live === false) { - that.unbind('click.fb-start').bind('click.fb-start', run); - - } else { - D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run); - } - - this.filter('[data-fancybox-start=1]').trigger('click'); - - return this; - }; - - // Tests that need a body at doc ready - D.ready(function() { - var w1, w2; - - if ( $.scrollbarWidth === undefined ) { - // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth - $.scrollbarWidth = function() { - var parent = $('
    ').appendTo('body'), - child = parent.children(), - width = child.innerWidth() - child.height( 99 ).innerWidth(); - - parent.remove(); - - return width; - }; - } - - if ( $.support.fixedPosition === undefined ) { - $.support.fixedPosition = (function() { - var elem = $('
    ').appendTo('body'), - fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 ); - - elem.remove(); - - return fixed; - }()); - } - - $.extend(F.defaults, { - scrollbarWidth : $.scrollbarWidth(), - fixed : $.support.fixedPosition, - parent : $('body') - }); - - //Get real width of page scroll-bar - w1 = $(window).width(); - - H.addClass('fancybox-lock-test'); - - w2 = $(window).width(); - - H.removeClass('fancybox-lock-test'); - - $("").appendTo("head"); - }); - -}(window, document, jQuery)); \ No newline at end of file diff --git a/vendors/fancybox/source/jquery.fancybox.pack.js b/vendors/fancybox/source/jquery.fancybox.pack.js deleted file mode 100644 index 73f7578..0000000 --- a/vendors/fancybox/source/jquery.fancybox.pack.js +++ /dev/null @@ -1,46 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -(function(r,G,f,v){var J=f("html"),n=f(r),p=f(G),b=f.fancybox=function(){b.open.apply(this,arguments)},I=navigator.userAgent.match(/msie/i),B=null,s=G.createTouch!==v,t=function(a){return a&&a.hasOwnProperty&&a instanceof f},q=function(a){return a&&"string"===f.type(a)},E=function(a){return q(a)&&0
    ',image:'',iframe:'",error:'

    The requested content cannot be loaded.
    Please try again later.

    ',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, -openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, -isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=t(a)?f(a).get():[a]),f.each(a,function(e,c){var k={},g,h,j,m,l;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),t(c)?(k={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0,k, -c.metadata())):k=c);g=d.href||k.href||(q(c)?c:null);h=d.title!==v?d.title:k.title||"";m=(j=d.content||k.content)?"html":d.type||k.type;!m&&k.isDom&&(m=c.data("fancybox-type"),m||(m=(m=c.prop("class").match(/fancybox\.(\w+)/))?m[1]:null));q(g)&&(m||(b.isImage(g)?m="image":b.isSWF(g)?m="swf":"#"===g.charAt(0)?m="inline":q(c)&&(m="html",j=c)),"ajax"===m&&(l=g.split(/\s+/,2),g=l.shift(),l=l.shift()));j||("inline"===m?g?j=f(q(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):k.isDom&&(j=c):"html"===m?j=g:!m&&(!g&& -k.isDom)&&(m="inline",j=c));f.extend(k,{href:g,type:m,content:j,title:h,selector:l});a[e]=k}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==v&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current|| -b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer= -setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==v&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,k;c&&(k=b._getPosition(d),a&&"scroll"===a.type?(delete k.position,c.stop(!0,!0).animate(k,200)):(c.css(k),e.pos=f.extend({},e.dim,k)))},update:function(a){var d= -a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(B),B=null);b.isOpen&&!B&&(B=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),B=null)},e&&!s?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,s&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"),b.trigger("onUpdate")), -b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
    ').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked||!1,d={x:n.scrollLeft(), -y:n.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=s&&r.innerWidth?r.innerWidth:n.width(),d.h=s&&r.innerHeight?r.innerHeight:n.height());return d},unbindEvents:function(){b.wrap&&t(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");n.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(n.bind("orientationchange.fb"+(s?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c=e.which||e.keyCode,k=e.target||e.srcElement; -if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!k||!k.type&&!f(k).is("[contenteditable]")))&&f.each(d,function(d,k){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!j&&1g||0>k)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&&b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0, -{},b.helpers[d].defaults,e),c)});p.trigger(a)}},isImage:function(a){return q(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return q(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=l(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1, -mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio= -!0);"iframe"===c&&s&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(s?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,w(d.padding[a]))});b.trigger("onReady");if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href"); -"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width=this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload= -this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",s?"auto":a.iframe.scrolling).attr("src",a.href); -f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);s||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload, -e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,k,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents();e=a.content;c=a.type;k=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin, -outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
    ").html(e).find(a.selector):t(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
    ').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder",!1)}));break;case "image":e=a.tpl.image.replace("{href}", -g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}(!t(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow");a.inner.css("overflow","yes"===k?"scroll": -"no"===k?"hidden":k);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,k=b.skin,g=b.inner,h=b.current,c=h.width,j=h.height,m=h.minWidth,u=h.minHeight,n=h.maxWidth,p=h.maxHeight,s=h.scrolling,q=h.scrollOutside? -h.scrollbarWidth:0,x=h.margin,y=l(x[1]+x[3]),r=l(x[0]+x[2]),v,z,t,C,A,F,B,D,H;e.add(k).add(g).width("auto").height("auto").removeClass("fancybox-tmp");x=l(k.outerWidth(!0)-k.width());v=l(k.outerHeight(!0)-k.height());z=y+x;t=r+v;C=E(c)?(a.w-z)*l(c)/100:c;A=E(j)?(a.h-t)*l(j)/100:j;if("iframe"===h.type){if(H=h.content,h.autoHeight&&1===H.data("ready"))try{H[0].contentWindow.document.location&&(g.width(C).height(9999),F=H.contents().find("body"),q&&F.css("overflow-x","hidden"),A=F.outerHeight(!0))}catch(G){}}else if(h.autoWidth|| -h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=l(C);j=l(A);D=C/A;m=l(E(m)?l(m,"w")-z:m);n=l(E(n)?l(n,"w")-z:n);u=l(E(u)?l(u,"h")-t:u);p=l(E(p)?l(p,"h")-t:p);F=n;B=p;h.fitToView&&(n=Math.min(a.w-z,n),p=Math.min(a.h-t,p));z=a.w-y;r=a.h-r;h.aspectRatio?(c>n&&(c=n,j=l(c/D)),j>p&&(j=p,c=l(j*D)),cz||y>r)&&(c>m&&j>u)&&!(19n&&(c=n,j=l(c/D)),g.width(c).height(j),e.width(c+x),a=e.width(),y=e.height();else c=Math.max(m,Math.min(c,c-(a-z))),j=Math.max(u,Math.min(j,j-(y-r)));q&&("auto"===s&&jz||y>r)&&c>m&&j>u;c=h.aspectRatio?cu&&j
    ').appendTo(b.coming?b.coming.parent:a.parent);this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(n.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive? -b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){var a,b;n.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),a=n.scrollTop(),b=n.scrollLeft(),this.el.removeClass("fancybox-lock"),n.scrollTop(a).scrollLeft(b));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%");I?(b=Math.max(G.documentElement.offsetWidth,G.body.offsetWidth), -p.width()>b&&(a=p.width())):p.width()>n.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&(this.fixed&&b.fixed)&&(e||(this.margin=p.height()>n.height()?f("html").css("margin-right").replace("px",""):!1),b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){var e,c;b.locked&&(!1!==this.margin&&(f("*").filter(function(){return"fixed"=== -f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin")),e=n.scrollTop(),c=n.scrollLeft(),this.el.addClass("fancybox-lock"),n.scrollTop(e).scrollLeft(c));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d= -b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(q(e)&&""!==f.trim(e)){d=f('
    '+e+"
    ");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),I&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(l(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d, -e=f(this),c=this.selector||"",k=function(g){var h=f(this).blur(),j=d,k,l;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(k=a.groupAttr||"data-fancybox-group",l=h.attr(k),l||(k="rel",l=h.get(0)[k]),l&&(""!==l&&"nofollow"!==l)&&(h=c.length?f(c):e,h=h.filter("["+k+'="'+l+'"]'),j=h.index(this)),a.index=j,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",k):p.undelegate(c,"click.fb-start").delegate(c+ -":not('.fancybox-item, .fancybox-nav')","click.fb-start",k);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===v&&(f.scrollbarWidth=function(){var a=f('
    ').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===v){a=f.support;d=f('
    ').appendTo("body");var e=20=== -d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(r).width();J.addClass("fancybox-lock-test");d=f(r).width();J.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery); \ No newline at end of file diff --git a/vendors/fastclick/LICENSE b/vendors/fastclick/LICENSE deleted file mode 100644 index 459a20d..0000000 --- a/vendors/fastclick/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2014 The Financial Times Ltd. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendors/fastclick/README.html b/vendors/fastclick/README.html deleted file mode 100644 index c9ab89c..0000000 --- a/vendors/fastclick/README.html +++ /dev/null @@ -1,70 +0,0 @@ -

    FastClick

    FastClick is a simple, easy-to-use library for eliminating the 300ms delay between a physical tap and the firing of a click event on mobile browsers. The aim is to make your application feel less laggy and more responsive while avoiding any interference with your current logic.

    -

    FastClick is developed by FT Labs, part of the Financial Times.

    -

    Explication en français.

    -

    日本語で説明

    -

    Why does the delay exist?

    According to Google:

    -
    -

    …mobile browsers will wait approximately 300ms from the time that you tap the button to fire the click event. The reason for this is that the browser is waiting to see if you are actually performing a double tap.

    -
    -

    Compatibility

    The library has been deployed as part of the FT Web App and is tried and tested on the following mobile browsers:

    -
      -
    • Mobile Safari on iOS 3 and upwards
    • -
    • Chrome on iOS 5 and upwards
    • -
    • Chrome on Android (ICS)
    • -
    • Opera Mobile 11.5 and upwards
    • -
    • Android Browser since Android 2
    • -
    • PlayBook OS 1 and upwards
    • -
    -

    When it isn’t needed

    FastClick doesn’t attach any listeners on desktop browsers.

    -

    Chrome 32+ on Android with width=device-width in the viewport meta tag doesn’t have a 300ms delay, therefore listeners aren’t attached.

    -
    <meta name="viewport" content="width=device-width, initial-scale=1">
    -
    -

    Same goes for Chrome on Android (all versions) with user-scalable=no in the viewport meta tag. But be aware that user-scalable=no also disables pinch zooming, which may be an accessibility concern.

    -

    For IE11+, you can use touch-action: manipulation; to disable double-tap-to-zoom on certain elements (like links and buttons). For IE10 use -ms-touch-action: manipulation.

    -

    Usage

    Include fastclick.js in your JavaScript bundle or add it to your HTML page like this:

    -
    <script type='application/javascript' src='/path/to/fastclick.js'></script>
    -
    -

    The script must be loaded prior to instantiating FastClick on any element of the page.

    -

    To instantiate FastClick on the body, which is the recommended method of use:

    -
    if ('addEventListener' in document) {
    -    document.addEventListener('DOMContentLoaded', function() {
    -        FastClick.attach(document.body);
    -    }, false);
    -}
    -
    -

    Or, if you’re using jQuery:

    -
    $(function() {
    -    FastClick.attach(document.body);
    -});
    -
    -

    If you’re using Browserify or another CommonJS-style module system, the FastClick.attach function will be returned when you call require('fastclick'). As a result, the easiest way to use FastClick with these loaders is as follows:

    -
    var attachFastClick = require('fastclick');
    -attachFastClick(document.body);
    -
    -

    Minified

    Run make to build a minified version of FastClick using the Closure Compiler REST API. The minified file is saved to build/fastclick.min.js or you can download a pre-minified version.

    -

    Note: the pre-minified version is built using our build service which exposes the FastClick object through Origami.fastclick and will have the Browserify/CommonJS API (see above).

    -
    var attachFastClick = Origami.fastclick;
    -attachFastClick(document.body);
    -
    -

    AMD

    FastClick has AMD (Asynchronous Module Definition) support. This allows it to be lazy-loaded with an AMD loader, such as RequireJS. Note that when using the AMD style require, the full FastClick object will be returned, not FastClick.attach

    -
    var FastClick = require('fastclick');
    -FastClick.attach(document.body, options);
    -
    -

    Package managers

    You can install FastClick using Component, npm or Bower.

    -

    For Ruby, there’s a third-party gem called fastclick-rails. For .NET there’s a NuGet package.

    -

    Advanced

    Ignore certain elements with needsclick

    Sometimes you need FastClick to ignore certain elements. You can do this easily by adding the needsclick class.

    -
    <a class="needsclick">Ignored by FastClick</a>
    -
    -

    Use case 1: non-synthetic click required

    Internally, FastClick uses document.createEvent to fire a synthetic click event as soon as touchend is fired by the browser. It then suppresses the additional click event created by the browser after that. In some cases, the non-synthetic click event created by the browser is required, as described in the triggering focus example.

    -

    This is where the needsclick class comes in. Add the class to any element that requires a non-synthetic click.

    -

    Use case 2: Twitter Bootstrap 2.2.2 dropdowns

    Another example of when to use the needsclick class is with dropdowns in Twitter Bootstrap 2.2.2. Bootstrap add its own touchstart listener for dropdowns, so you want to tell FastClick to ignore those. If you don’t, touch devices will automatically close the dropdown as soon as it is clicked, because both FastClick and Bootstrap execute the synthetic click, one opens the dropdown, the second closes it immediately after.

    -
    <a class="dropdown-toggle needsclick" data-toggle="dropdown">Dropdown</a>
    -
    -

    Examples

    FastClick is designed to cope with many different browser oddities. Here are some examples to illustrate this:

    - -

    Tests

    There are no automated tests. The files in tests/ are manual reduced test cases. We’ve had a think about how best to test these cases, but they tend to be very browser/device specific and sometimes subjective which means it’s not so trivial to test.

    -

    Credits and collaboration

    FastClick is maintained by Rowan Beentje, Matthew Caruana Galizia and Matthew Andrews at FT Labs. All open source code released by FT Labs is licenced under the MIT licence. We welcome comments, feedback and suggestions. Please feel free to raise an issue or pull request.

    diff --git a/vendors/fastclick/bower.json b/vendors/fastclick/bower.json deleted file mode 100644 index cdbbf93..0000000 --- a/vendors/fastclick/bower.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"fastclick","main":"lib/fastclick.js","ignore":["**/.*","component.json","package.json","Makefile","tests","examples"]} \ No newline at end of file diff --git a/vendors/fastclick/lib/fastclick.js b/vendors/fastclick/lib/fastclick.js deleted file mode 100644 index 3af4f9d..0000000 --- a/vendors/fastclick/lib/fastclick.js +++ /dev/null @@ -1,841 +0,0 @@ -;(function () { - 'use strict'; - - /** - * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs. - * - * @codingstandard ftlabs-jsv2 - * @copyright The Financial Times Limited [All Rights Reserved] - * @license MIT License (see LICENSE.txt) - */ - - /*jslint browser:true, node:true*/ - /*global define, Event, Node*/ - - - /** - * Instantiate fast-clicking listeners on the specified layer. - * - * @constructor - * @param {Element} layer The layer to listen on - * @param {Object} [options={}] The options to override the defaults - */ - function FastClick(layer, options) { - var oldOnClick; - - options = options || {}; - - /** - * Whether a click is currently being tracked. - * - * @type boolean - */ - this.trackingClick = false; - - - /** - * Timestamp for when click tracking started. - * - * @type number - */ - this.trackingClickStart = 0; - - - /** - * The element being tracked for a click. - * - * @type EventTarget - */ - this.targetElement = null; - - - /** - * X-coordinate of touch start event. - * - * @type number - */ - this.touchStartX = 0; - - - /** - * Y-coordinate of touch start event. - * - * @type number - */ - this.touchStartY = 0; - - - /** - * ID of the last touch, retrieved from Touch.identifier. - * - * @type number - */ - this.lastTouchIdentifier = 0; - - - /** - * Touchmove boundary, beyond which a click will be cancelled. - * - * @type number - */ - this.touchBoundary = options.touchBoundary || 10; - - - /** - * The FastClick layer. - * - * @type Element - */ - this.layer = layer; - - /** - * The minimum time between tap(touchstart and touchend) events - * - * @type number - */ - this.tapDelay = options.tapDelay || 200; - - /** - * The maximum time for a tap - * - * @type number - */ - this.tapTimeout = options.tapTimeout || 700; - - if (FastClick.notNeeded(layer)) { - return; - } - - // Some old versions of Android don't have Function.prototype.bind - function bind(method, context) { - return function() { return method.apply(context, arguments); }; - } - - - var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel']; - var context = this; - for (var i = 0, l = methods.length; i < l; i++) { - context[methods[i]] = bind(context[methods[i]], context); - } - - // Set up event handlers as required - if (deviceIsAndroid) { - layer.addEventListener('mouseover', this.onMouse, true); - layer.addEventListener('mousedown', this.onMouse, true); - layer.addEventListener('mouseup', this.onMouse, true); - } - - layer.addEventListener('click', this.onClick, true); - layer.addEventListener('touchstart', this.onTouchStart, false); - layer.addEventListener('touchmove', this.onTouchMove, false); - layer.addEventListener('touchend', this.onTouchEnd, false); - layer.addEventListener('touchcancel', this.onTouchCancel, false); - - // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) - // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick - // layer when they are cancelled. - if (!Event.prototype.stopImmediatePropagation) { - layer.removeEventListener = function(type, callback, capture) { - var rmv = Node.prototype.removeEventListener; - if (type === 'click') { - rmv.call(layer, type, callback.hijacked || callback, capture); - } else { - rmv.call(layer, type, callback, capture); - } - }; - - layer.addEventListener = function(type, callback, capture) { - var adv = Node.prototype.addEventListener; - if (type === 'click') { - adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) { - if (!event.propagationStopped) { - callback(event); - } - }), capture); - } else { - adv.call(layer, type, callback, capture); - } - }; - } - - // If a handler is already declared in the element's onclick attribute, it will be fired before - // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and - // adding it as listener. - if (typeof layer.onclick === 'function') { - - // Android browser on at least 3.2 requires a new reference to the function in layer.onclick - // - the old one won't work if passed to addEventListener directly. - oldOnClick = layer.onclick; - layer.addEventListener('click', function(event) { - oldOnClick(event); - }, false); - layer.onclick = null; - } - } - - /** - * Windows Phone 8.1 fakes user agent string to look like Android and iPhone. - * - * @type boolean - */ - var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0; - - /** - * Android requires exceptions. - * - * @type boolean - */ - var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone; - - - /** - * iOS requires exceptions. - * - * @type boolean - */ - var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone; - - - /** - * iOS 4 requires an exception for select elements. - * - * @type boolean - */ - var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent); - - - /** - * iOS 6.0-7.* requires the target element to be manually derived - * - * @type boolean - */ - var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent); - - /** - * BlackBerry requires exceptions. - * - * @type boolean - */ - var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0; - - /** - * Determine whether a given element requires a native click. - * - * @param {EventTarget|Element} target Target DOM element - * @returns {boolean} Returns true if the element needs a native click - */ - FastClick.prototype.needsClick = function(target) { - switch (target.nodeName.toLowerCase()) { - - // Don't send a synthetic click to disabled inputs (issue #62) - case 'button': - case 'select': - case 'textarea': - if (target.disabled) { - return true; - } - - break; - case 'input': - - // File inputs need real clicks on iOS 6 due to a browser bug (issue #68) - if ((deviceIsIOS && target.type === 'file') || target.disabled) { - return true; - } - - break; - case 'label': - case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames - case 'video': - return true; - } - - return (/\bneedsclick\b/).test(target.className); - }; - - - /** - * Determine whether a given element requires a call to focus to simulate click into element. - * - * @param {EventTarget|Element} target Target DOM element - * @returns {boolean} Returns true if the element requires a call to focus to simulate native click. - */ - FastClick.prototype.needsFocus = function(target) { - switch (target.nodeName.toLowerCase()) { - case 'textarea': - return true; - case 'select': - return !deviceIsAndroid; - case 'input': - switch (target.type) { - case 'button': - case 'checkbox': - case 'file': - case 'image': - case 'radio': - case 'submit': - return false; - } - - // No point in attempting to focus disabled inputs - return !target.disabled && !target.readOnly; - default: - return (/\bneedsfocus\b/).test(target.className); - } - }; - - - /** - * Send a click event to the specified element. - * - * @param {EventTarget|Element} targetElement - * @param {Event} event - */ - FastClick.prototype.sendClick = function(targetElement, event) { - var clickEvent, touch; - - // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) - if (document.activeElement && document.activeElement !== targetElement) { - document.activeElement.blur(); - } - - touch = event.changedTouches[0]; - - // Synthesise a click event, with an extra attribute so it can be tracked - clickEvent = document.createEvent('MouseEvents'); - clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); - clickEvent.forwardedTouchEvent = true; - targetElement.dispatchEvent(clickEvent); - }; - - FastClick.prototype.determineEventType = function(targetElement) { - - //Issue #159: Android Chrome Select Box does not open with a synthetic click event - if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') { - return 'mousedown'; - } - - return 'click'; - }; - - - /** - * @param {EventTarget|Element} targetElement - */ - FastClick.prototype.focus = function(targetElement) { - var length; - - // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724. - if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') { - length = targetElement.value.length; - targetElement.setSelectionRange(length, length); - } else { - targetElement.focus(); - } - }; - - - /** - * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it. - * - * @param {EventTarget|Element} targetElement - */ - FastClick.prototype.updateScrollParent = function(targetElement) { - var scrollParent, parentElement; - - scrollParent = targetElement.fastClickScrollParent; - - // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the - // target element was moved to another parent. - if (!scrollParent || !scrollParent.contains(targetElement)) { - parentElement = targetElement; - do { - if (parentElement.scrollHeight > parentElement.offsetHeight) { - scrollParent = parentElement; - targetElement.fastClickScrollParent = parentElement; - break; - } - - parentElement = parentElement.parentElement; - } while (parentElement); - } - - // Always update the scroll top tracker if possible. - if (scrollParent) { - scrollParent.fastClickLastScrollTop = scrollParent.scrollTop; - } - }; - - - /** - * @param {EventTarget} targetElement - * @returns {Element|EventTarget} - */ - FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) { - - // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node. - if (eventTarget.nodeType === Node.TEXT_NODE) { - return eventTarget.parentNode; - } - - return eventTarget; - }; - - - /** - * On touch start, record the position and scroll offset. - * - * @param {Event} event - * @returns {boolean} - */ - FastClick.prototype.onTouchStart = function(event) { - var targetElement, touch, selection; - - // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111). - if (event.targetTouches.length > 1) { - return true; - } - - targetElement = this.getTargetElementFromEventTarget(event.target); - touch = event.targetTouches[0]; - - if (deviceIsIOS) { - - // Only trusted events will deselect text on iOS (issue #49) - selection = window.getSelection(); - if (selection.rangeCount && !selection.isCollapsed) { - return true; - } - - if (!deviceIsIOS4) { - - // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23): - // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched - // with the same identifier as the touch event that previously triggered the click that triggered the alert. - // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an - // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform. - // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string, - // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long, - // random integers, it's safe to to continue if the identifier is 0 here. - if (touch.identifier && touch.identifier === this.lastTouchIdentifier) { - event.preventDefault(); - return false; - } - - this.lastTouchIdentifier = touch.identifier; - - // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and: - // 1) the user does a fling scroll on the scrollable layer - // 2) the user stops the fling scroll with another tap - // then the event.target of the last 'touchend' event will be the element that was under the user's finger - // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check - // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42). - this.updateScrollParent(targetElement); - } - } - - this.trackingClick = true; - this.trackingClickStart = event.timeStamp; - this.targetElement = targetElement; - - this.touchStartX = touch.pageX; - this.touchStartY = touch.pageY; - - // Prevent phantom clicks on fast double-tap (issue #36) - if ((event.timeStamp - this.lastClickTime) < this.tapDelay) { - event.preventDefault(); - } - - return true; - }; - - - /** - * Based on a touchmove event object, check whether the touch has moved past a boundary since it started. - * - * @param {Event} event - * @returns {boolean} - */ - FastClick.prototype.touchHasMoved = function(event) { - var touch = event.changedTouches[0], boundary = this.touchBoundary; - - if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) { - return true; - } - - return false; - }; - - - /** - * Update the last position. - * - * @param {Event} event - * @returns {boolean} - */ - FastClick.prototype.onTouchMove = function(event) { - if (!this.trackingClick) { - return true; - } - - // If the touch has moved, cancel the click tracking - if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) { - this.trackingClick = false; - this.targetElement = null; - } - - return true; - }; - - - /** - * Attempt to find the labelled control for the given label element. - * - * @param {EventTarget|HTMLLabelElement} labelElement - * @returns {Element|null} - */ - FastClick.prototype.findControl = function(labelElement) { - - // Fast path for newer browsers supporting the HTML5 control attribute - if (labelElement.control !== undefined) { - return labelElement.control; - } - - // All browsers under test that support touch events also support the HTML5 htmlFor attribute - if (labelElement.htmlFor) { - return document.getElementById(labelElement.htmlFor); - } - - // If no for attribute exists, attempt to retrieve the first labellable descendant element - // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label - return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'); - }; - - - /** - * On touch end, determine whether to send a click event at once. - * - * @param {Event} event - * @returns {boolean} - */ - FastClick.prototype.onTouchEnd = function(event) { - var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement; - - if (!this.trackingClick) { - return true; - } - - // Prevent phantom clicks on fast double-tap (issue #36) - if ((event.timeStamp - this.lastClickTime) < this.tapDelay) { - this.cancelNextClick = true; - return true; - } - - if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) { - return true; - } - - // Reset to prevent wrong click cancel on input (issue #156). - this.cancelNextClick = false; - - this.lastClickTime = event.timeStamp; - - trackingClickStart = this.trackingClickStart; - this.trackingClick = false; - this.trackingClickStart = 0; - - // On some iOS devices, the targetElement supplied with the event is invalid if the layer - // is performing a transition or scroll, and has to be re-detected manually. Note that - // for this to function correctly, it must be called *after* the event target is checked! - // See issue #57; also filed as rdar://13048589 . - if (deviceIsIOSWithBadTarget) { - touch = event.changedTouches[0]; - - // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null - targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement; - targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent; - } - - targetTagName = targetElement.tagName.toLowerCase(); - if (targetTagName === 'label') { - forElement = this.findControl(targetElement); - if (forElement) { - this.focus(targetElement); - if (deviceIsAndroid) { - return false; - } - - targetElement = forElement; - } - } else if (this.needsFocus(targetElement)) { - - // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through. - // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37). - if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { - this.targetElement = null; - return false; - } - - this.focus(targetElement); - this.sendClick(targetElement, event); - - // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open. - // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others) - if (!deviceIsIOS || targetTagName !== 'select') { - this.targetElement = null; - event.preventDefault(); - } - - return false; - } - - if (deviceIsIOS && !deviceIsIOS4) { - - // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled - // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). - scrollParent = targetElement.fastClickScrollParent; - if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) { - return true; - } - } - - // Prevent the actual click from going though - unless the target node is marked as requiring - // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted. - if (!this.needsClick(targetElement)) { - event.preventDefault(); - this.sendClick(targetElement, event); - } - - return false; - }; - - - /** - * On touch cancel, stop tracking the click. - * - * @returns {void} - */ - FastClick.prototype.onTouchCancel = function() { - this.trackingClick = false; - this.targetElement = null; - }; - - - /** - * Determine mouse events which should be permitted. - * - * @param {Event} event - * @returns {boolean} - */ - FastClick.prototype.onMouse = function(event) { - - // If a target element was never set (because a touch event was never fired) allow the event - if (!this.targetElement) { - return true; - } - - if (event.forwardedTouchEvent) { - return true; - } - - // Programmatically generated events targeting a specific element should be permitted - if (!event.cancelable) { - return true; - } - - // Derive and check the target element to see whether the mouse event needs to be permitted; - // unless explicitly enabled, prevent non-touch click events from triggering actions, - // to prevent ghost/doubleclicks. - if (!this.needsClick(this.targetElement) || this.cancelNextClick) { - - // Prevent any user-added listeners declared on FastClick element from being fired. - if (event.stopImmediatePropagation) { - event.stopImmediatePropagation(); - } else { - - // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) - event.propagationStopped = true; - } - - // Cancel the event - event.stopPropagation(); - event.preventDefault(); - - return false; - } - - // If the mouse event is permitted, return true for the action to go through. - return true; - }; - - - /** - * On actual clicks, determine whether this is a touch-generated click, a click action occurring - * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or - * an actual click which should be permitted. - * - * @param {Event} event - * @returns {boolean} - */ - FastClick.prototype.onClick = function(event) { - var permitted; - - // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early. - if (this.trackingClick) { - this.targetElement = null; - this.trackingClick = false; - return true; - } - - // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target. - if (event.target.type === 'submit' && event.detail === 0) { - return true; - } - - permitted = this.onMouse(event); - - // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through. - if (!permitted) { - this.targetElement = null; - } - - // If clicks are permitted, return true for the action to go through. - return permitted; - }; - - - /** - * Remove all FastClick's event listeners. - * - * @returns {void} - */ - FastClick.prototype.destroy = function() { - var layer = this.layer; - - if (deviceIsAndroid) { - layer.removeEventListener('mouseover', this.onMouse, true); - layer.removeEventListener('mousedown', this.onMouse, true); - layer.removeEventListener('mouseup', this.onMouse, true); - } - - layer.removeEventListener('click', this.onClick, true); - layer.removeEventListener('touchstart', this.onTouchStart, false); - layer.removeEventListener('touchmove', this.onTouchMove, false); - layer.removeEventListener('touchend', this.onTouchEnd, false); - layer.removeEventListener('touchcancel', this.onTouchCancel, false); - }; - - - /** - * Check whether FastClick is needed. - * - * @param {Element} layer The layer to listen on - */ - FastClick.notNeeded = function(layer) { - var metaViewport; - var chromeVersion; - var blackberryVersion; - var firefoxVersion; - - // Devices that don't support touch don't need FastClick - if (typeof window.ontouchstart === 'undefined') { - return true; - } - - // Chrome version - zero for other browsers - chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1]; - - if (chromeVersion) { - - if (deviceIsAndroid) { - metaViewport = document.querySelector('meta[name=viewport]'); - - if (metaViewport) { - // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89) - if (metaViewport.content.indexOf('user-scalable=no') !== -1) { - return true; - } - // Chrome 32 and above with width=device-width or less don't need FastClick - if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) { - return true; - } - } - - // Chrome desktop doesn't need FastClick (issue #15) - } else { - return true; - } - } - - if (deviceIsBlackBerry10) { - blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/); - - // BlackBerry 10.3+ does not require Fastclick library. - // https://github.com/ftlabs/fastclick/issues/251 - if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) { - metaViewport = document.querySelector('meta[name=viewport]'); - - if (metaViewport) { - // user-scalable=no eliminates click delay. - if (metaViewport.content.indexOf('user-scalable=no') !== -1) { - return true; - } - // width=device-width (or less than device-width) eliminates click delay. - if (document.documentElement.scrollWidth <= window.outerWidth) { - return true; - } - } - } - } - - // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97) - if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') { - return true; - } - - // Firefox version - zero for other browsers - firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1]; - - if (firefoxVersion >= 27) { - // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896 - - metaViewport = document.querySelector('meta[name=viewport]'); - if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) { - return true; - } - } - - // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version - // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx - if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') { - return true; - } - - return false; - }; - - - /** - * Factory method for creating a FastClick object - * - * @param {Element} layer The layer to listen on - * @param {Object} [options={}] The options to override the defaults - */ - FastClick.attach = function(layer, options) { - return new FastClick(layer, options); - }; - - - if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) { - - // AMD. Register as an anonymous module. - define(function() { - return FastClick; - }); - } else if (typeof module !== 'undefined' && module.exports) { - module.exports = FastClick.attach; - module.exports.FastClick = FastClick; - } else { - window.FastClick = FastClick; - } -}()); diff --git a/vendors/fastclick/lib/fastclick.min.js b/vendors/fastclick/lib/fastclick.min.js deleted file mode 100644 index cf06427..0000000 --- a/vendors/fastclick/lib/fastclick.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";function t(e,o){function i(t,e){return function(){return t.apply(e,arguments)}}var r;if(o=o||{},this.trackingClick=!1,this.trackingClickStart=0,this.targetElement=null,this.touchStartX=0,this.touchStartY=0,this.lastTouchIdentifier=0,this.touchBoundary=o.touchBoundary||10,this.layer=e,this.tapDelay=o.tapDelay||200,this.tapTimeout=o.tapTimeout||700,!t.notNeeded(e)){for(var a=["onMouse","onClick","onTouchStart","onTouchMove","onTouchEnd","onTouchCancel"],c=this,s=0,u=a.length;u>s;s++)c[a[s]]=i(c[a[s]],c);n&&(e.addEventListener("mouseover",this.onMouse,!0),e.addEventListener("mousedown",this.onMouse,!0),e.addEventListener("mouseup",this.onMouse,!0)),e.addEventListener("click",this.onClick,!0),e.addEventListener("touchstart",this.onTouchStart,!1),e.addEventListener("touchmove",this.onTouchMove,!1),e.addEventListener("touchend",this.onTouchEnd,!1),e.addEventListener("touchcancel",this.onTouchCancel,!1),Event.prototype.stopImmediatePropagation||(e.removeEventListener=function(t,n,o){var i=Node.prototype.removeEventListener;"click"===t?i.call(e,t,n.hijacked||n,o):i.call(e,t,n,o)},e.addEventListener=function(t,n,o){var i=Node.prototype.addEventListener;"click"===t?i.call(e,t,n.hijacked||(n.hijacked=function(t){t.propagationStopped||n(t)}),o):i.call(e,t,n,o)}),"function"==typeof e.onclick&&(r=e.onclick,e.addEventListener("click",function(t){r(t)},!1),e.onclick=null)}}var e=navigator.userAgent.indexOf("Windows Phone")>=0,n=navigator.userAgent.indexOf("Android")>0&&!e,o=/iP(ad|hone|od)/.test(navigator.userAgent)&&!e,i=o&&/OS 4_\d(_\d)?/.test(navigator.userAgent),r=o&&/OS [6-7]_\d/.test(navigator.userAgent),a=navigator.userAgent.indexOf("BB10")>0;t.prototype.needsClick=function(t){switch(t.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(t.disabled)return!0;break;case"input":if(o&&"file"===t.type||t.disabled)return!0;break;case"label":case"iframe":case"video":return!0}return/\bneedsclick\b/.test(t.className)},t.prototype.needsFocus=function(t){switch(t.nodeName.toLowerCase()){case"textarea":return!0;case"select":return!n;case"input":switch(t.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return!1}return!t.disabled&&!t.readOnly;default:return/\bneedsfocus\b/.test(t.className)}},t.prototype.sendClick=function(t,e){var n,o;document.activeElement&&document.activeElement!==t&&document.activeElement.blur(),o=e.changedTouches[0],n=document.createEvent("MouseEvents"),n.initMouseEvent(this.determineEventType(t),!0,!0,window,1,o.screenX,o.screenY,o.clientX,o.clientY,!1,!1,!1,!1,0,null),n.forwardedTouchEvent=!0,t.dispatchEvent(n)},t.prototype.determineEventType=function(t){return n&&"select"===t.tagName.toLowerCase()?"mousedown":"click"},t.prototype.focus=function(t){var e;o&&t.setSelectionRange&&0!==t.type.indexOf("date")&&"time"!==t.type&&"month"!==t.type?(e=t.value.length,t.setSelectionRange(e,e)):t.focus()},t.prototype.updateScrollParent=function(t){var e,n;if(e=t.fastClickScrollParent,!e||!e.contains(t)){n=t;do{if(n.scrollHeight>n.offsetHeight){e=n,t.fastClickScrollParent=n;break}n=n.parentElement}while(n)}e&&(e.fastClickLastScrollTop=e.scrollTop)},t.prototype.getTargetElementFromEventTarget=function(t){return t.nodeType===Node.TEXT_NODE?t.parentNode:t},t.prototype.onTouchStart=function(t){var e,n,r;if(t.targetTouches.length>1)return!0;if(e=this.getTargetElementFromEventTarget(t.target),n=t.targetTouches[0],o){if(r=window.getSelection(),r.rangeCount&&!r.isCollapsed)return!0;if(!i){if(n.identifier&&n.identifier===this.lastTouchIdentifier)return t.preventDefault(),!1;this.lastTouchIdentifier=n.identifier,this.updateScrollParent(e)}}return this.trackingClick=!0,this.trackingClickStart=t.timeStamp,this.targetElement=e,this.touchStartX=n.pageX,this.touchStartY=n.pageY,t.timeStamp-this.lastClickTimen||Math.abs(e.pageY-this.touchStartY)>n?!0:!1},t.prototype.onTouchMove=function(t){return this.trackingClick?((this.targetElement!==this.getTargetElementFromEventTarget(t.target)||this.touchHasMoved(t))&&(this.trackingClick=!1,this.targetElement=null),!0):!0},t.prototype.findControl=function(t){return void 0!==t.control?t.control:t.htmlFor?document.getElementById(t.htmlFor):t.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")},t.prototype.onTouchEnd=function(t){var e,a,c,s,u,l=this.targetElement;if(!this.trackingClick)return!0;if(t.timeStamp-this.lastClickTimethis.tapTimeout)return!0;if(this.cancelNextClick=!1,this.lastClickTime=t.timeStamp,a=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,r&&(u=t.changedTouches[0],l=document.elementFromPoint(u.pageX-window.pageXOffset,u.pageY-window.pageYOffset)||l,l.fastClickScrollParent=this.targetElement.fastClickScrollParent),c=l.tagName.toLowerCase(),"label"===c){if(e=this.findControl(l)){if(this.focus(l),n)return!1;l=e}}else if(this.needsFocus(l))return t.timeStamp-a>100||o&&window.top!==window&&"input"===c?(this.targetElement=null,!1):(this.focus(l),this.sendClick(l,t),o&&"select"===c||(this.targetElement=null,t.preventDefault()),!1);return o&&!i&&(s=l.fastClickScrollParent,s&&s.fastClickLastScrollTop!==s.scrollTop)?!0:(this.needsClick(l)||(t.preventDefault(),this.sendClick(l,t)),!1)},t.prototype.onTouchCancel=function(){this.trackingClick=!1,this.targetElement=null},t.prototype.onMouse=function(t){return this.targetElement?t.forwardedTouchEvent?!0:t.cancelable&&(!this.needsClick(this.targetElement)||this.cancelNextClick)?(t.stopImmediatePropagation?t.stopImmediatePropagation():t.propagationStopped=!0,t.stopPropagation(),t.preventDefault(),!1):!0:!0},t.prototype.onClick=function(t){var e;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):"submit"===t.target.type&&0===t.detail?!0:(e=this.onMouse(t),e||(this.targetElement=null),e)},t.prototype.destroy=function(){var t=this.layer;n&&(t.removeEventListener("mouseover",this.onMouse,!0),t.removeEventListener("mousedown",this.onMouse,!0),t.removeEventListener("mouseup",this.onMouse,!0)),t.removeEventListener("click",this.onClick,!0),t.removeEventListener("touchstart",this.onTouchStart,!1),t.removeEventListener("touchmove",this.onTouchMove,!1),t.removeEventListener("touchend",this.onTouchEnd,!1),t.removeEventListener("touchcancel",this.onTouchCancel,!1)},t.notNeeded=function(t){var e,o,i,r;if("undefined"==typeof window.ontouchstart)return!0;if(o=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!n)return!0;if(e=document.querySelector("meta[name=viewport]")){if(-1!==e.content.indexOf("user-scalable=no"))return!0;if(o>31&&document.documentElement.scrollWidth<=window.outerWidth)return!0}}if(a&&(i=navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/),i[1]>=10&&i[2]>=3&&(e=document.querySelector("meta[name=viewport]")))){if(-1!==e.content.indexOf("user-scalable=no"))return!0;if(document.documentElement.scrollWidth<=window.outerWidth)return!0}return"none"===t.style.msTouchAction||"manipulation"===t.style.touchAction?!0:(r=+(/Firefox\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1],r>=27&&(e=document.querySelector("meta[name=viewport]"),e&&(-1!==e.content.indexOf("user-scalable=no")||document.documentElement.scrollWidth<=window.outerWidth))?!0:"none"===t.style.touchAction||"manipulation"===t.style.touchAction?!0:!1)},t.attach=function(e,n){return new t(e,n)},"function"==typeof define&&"object"==typeof define.amd&&define.amd?define(function(){return t}):"undefined"!=typeof module&&module.exports?(module.exports=t.attach,module.exports.FastClick=t):window.FastClick=t}(); \ No newline at end of file diff --git a/vendors/font-awesome/HELP-US-OUT.txt b/vendors/font-awesome/HELP-US-OUT.txt deleted file mode 100644 index cfd9d9f..0000000 --- a/vendors/font-awesome/HELP-US-OUT.txt +++ /dev/null @@ -1,7 +0,0 @@ -I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, -Fonticons (https://fonticons.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, -comprehensive icon sets or copy and paste your own. - -Please. Check it out. - --Dave Gandy diff --git a/vendors/font-awesome/bower.json b/vendors/font-awesome/bower.json deleted file mode 100644 index 772570a..0000000 --- a/vendors/font-awesome/bower.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"font-awesome","description":"Font Awesome","keywords":[],"homepage":"http://fontawesome.io","dependencies":{},"devDependencies":{},"license":["OFL-1.1","MIT","CC-BY-3.0"],"main":["less/font-awesome.less","scss/font-awesome.scss"],"ignore":["*/.*","*.json","src","*.yml","Gemfile","Gemfile.lock","*.md"]} \ No newline at end of file diff --git a/vendors/font-awesome/css/font-awesome.css b/vendors/font-awesome/css/font-awesome.css deleted file mode 100644 index 880eb82..0000000 --- a/vendors/font-awesome/css/font-awesome.css +++ /dev/null @@ -1,2026 +0,0 @@ -/*! - * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.4.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.fa-pull-left { - float: left; -} -.fa-pull-right { - float: right; -} -.fa.fa-pull-left { - margin-right: .3em; -} -.fa.fa-pull-right { - margin-left: .3em; -} -/* Deprecated as of 4.4.0 */ -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-feed:before, -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} -.fa-space-shuttle:before { - content: "\f197"; -} -.fa-slack:before { - content: "\f198"; -} -.fa-envelope-square:before { - content: "\f199"; -} -.fa-wordpress:before { - content: "\f19a"; -} -.fa-openid:before { - content: "\f19b"; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} -.fa-yahoo:before { - content: "\f19e"; -} -.fa-google:before { - content: "\f1a0"; -} -.fa-reddit:before { - content: "\f1a1"; -} -.fa-reddit-square:before { - content: "\f1a2"; -} -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} -.fa-stumbleupon:before { - content: "\f1a4"; -} -.fa-delicious:before { - content: "\f1a5"; -} -.fa-digg:before { - content: "\f1a6"; -} -.fa-pied-piper:before { - content: "\f1a7"; -} -.fa-pied-piper-alt:before { - content: "\f1a8"; -} -.fa-drupal:before { - content: "\f1a9"; -} -.fa-joomla:before { - content: "\f1aa"; -} -.fa-language:before { - content: "\f1ab"; -} -.fa-fax:before { - content: "\f1ac"; -} -.fa-building:before { - content: "\f1ad"; -} -.fa-child:before { - content: "\f1ae"; -} -.fa-paw:before { - content: "\f1b0"; -} -.fa-spoon:before { - content: "\f1b1"; -} -.fa-cube:before { - content: "\f1b2"; -} -.fa-cubes:before { - content: "\f1b3"; -} -.fa-behance:before { - content: "\f1b4"; -} -.fa-behance-square:before { - content: "\f1b5"; -} -.fa-steam:before { - content: "\f1b6"; -} -.fa-steam-square:before { - content: "\f1b7"; -} -.fa-recycle:before { - content: "\f1b8"; -} -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} -.fa-tree:before { - content: "\f1bb"; -} -.fa-spotify:before { - content: "\f1bc"; -} -.fa-deviantart:before { - content: "\f1bd"; -} -.fa-soundcloud:before { - content: "\f1be"; -} -.fa-database:before { - content: "\f1c0"; -} -.fa-file-pdf-o:before { - content: "\f1c1"; -} -.fa-file-word-o:before { - content: "\f1c2"; -} -.fa-file-excel-o:before { - content: "\f1c3"; -} -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} -.fa-file-code-o:before { - content: "\f1c9"; -} -.fa-vine:before { - content: "\f1ca"; -} -.fa-codepen:before { - content: "\f1cb"; -} -.fa-jsfiddle:before { - content: "\f1cc"; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} -.fa-circle-o-notch:before { - content: "\f1ce"; -} -.fa-ra:before, -.fa-rebel:before { - content: "\f1d0"; -} -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} -.fa-git-square:before { - content: "\f1d2"; -} -.fa-git:before { - content: "\f1d3"; -} -.fa-y-combinator-square:before, -.fa-yc-square:before, -.fa-hacker-news:before { - content: "\f1d4"; -} -.fa-tencent-weibo:before { - content: "\f1d5"; -} -.fa-qq:before { - content: "\f1d6"; -} -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} -.fa-history:before { - content: "\f1da"; -} -.fa-circle-thin:before { - content: "\f1db"; -} -.fa-header:before { - content: "\f1dc"; -} -.fa-paragraph:before { - content: "\f1dd"; -} -.fa-sliders:before { - content: "\f1de"; -} -.fa-share-alt:before { - content: "\f1e0"; -} -.fa-share-alt-square:before { - content: "\f1e1"; -} -.fa-bomb:before { - content: "\f1e2"; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} -.fa-tty:before { - content: "\f1e4"; -} -.fa-binoculars:before { - content: "\f1e5"; -} -.fa-plug:before { - content: "\f1e6"; -} -.fa-slideshare:before { - content: "\f1e7"; -} -.fa-twitch:before { - content: "\f1e8"; -} -.fa-yelp:before { - content: "\f1e9"; -} -.fa-newspaper-o:before { - content: "\f1ea"; -} -.fa-wifi:before { - content: "\f1eb"; -} -.fa-calculator:before { - content: "\f1ec"; -} -.fa-paypal:before { - content: "\f1ed"; -} -.fa-google-wallet:before { - content: "\f1ee"; -} -.fa-cc-visa:before { - content: "\f1f0"; -} -.fa-cc-mastercard:before { - content: "\f1f1"; -} -.fa-cc-discover:before { - content: "\f1f2"; -} -.fa-cc-amex:before { - content: "\f1f3"; -} -.fa-cc-paypal:before { - content: "\f1f4"; -} -.fa-cc-stripe:before { - content: "\f1f5"; -} -.fa-bell-slash:before { - content: "\f1f6"; -} -.fa-bell-slash-o:before { - content: "\f1f7"; -} -.fa-trash:before { - content: "\f1f8"; -} -.fa-copyright:before { - content: "\f1f9"; -} -.fa-at:before { - content: "\f1fa"; -} -.fa-eyedropper:before { - content: "\f1fb"; -} -.fa-paint-brush:before { - content: "\f1fc"; -} -.fa-birthday-cake:before { - content: "\f1fd"; -} -.fa-area-chart:before { - content: "\f1fe"; -} -.fa-pie-chart:before { - content: "\f200"; -} -.fa-line-chart:before { - content: "\f201"; -} -.fa-lastfm:before { - content: "\f202"; -} -.fa-lastfm-square:before { - content: "\f203"; -} -.fa-toggle-off:before { - content: "\f204"; -} -.fa-toggle-on:before { - content: "\f205"; -} -.fa-bicycle:before { - content: "\f206"; -} -.fa-bus:before { - content: "\f207"; -} -.fa-ioxhost:before { - content: "\f208"; -} -.fa-angellist:before { - content: "\f209"; -} -.fa-cc:before { - content: "\f20a"; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} -.fa-meanpath:before { - content: "\f20c"; -} -.fa-buysellads:before { - content: "\f20d"; -} -.fa-connectdevelop:before { - content: "\f20e"; -} -.fa-dashcube:before { - content: "\f210"; -} -.fa-forumbee:before { - content: "\f211"; -} -.fa-leanpub:before { - content: "\f212"; -} -.fa-sellsy:before { - content: "\f213"; -} -.fa-shirtsinbulk:before { - content: "\f214"; -} -.fa-simplybuilt:before { - content: "\f215"; -} -.fa-skyatlas:before { - content: "\f216"; -} -.fa-cart-plus:before { - content: "\f217"; -} -.fa-cart-arrow-down:before { - content: "\f218"; -} -.fa-diamond:before { - content: "\f219"; -} -.fa-ship:before { - content: "\f21a"; -} -.fa-user-secret:before { - content: "\f21b"; -} -.fa-motorcycle:before { - content: "\f21c"; -} -.fa-street-view:before { - content: "\f21d"; -} -.fa-heartbeat:before { - content: "\f21e"; -} -.fa-venus:before { - content: "\f221"; -} -.fa-mars:before { - content: "\f222"; -} -.fa-mercury:before { - content: "\f223"; -} -.fa-intersex:before, -.fa-transgender:before { - content: "\f224"; -} -.fa-transgender-alt:before { - content: "\f225"; -} -.fa-venus-double:before { - content: "\f226"; -} -.fa-mars-double:before { - content: "\f227"; -} -.fa-venus-mars:before { - content: "\f228"; -} -.fa-mars-stroke:before { - content: "\f229"; -} -.fa-mars-stroke-v:before { - content: "\f22a"; -} -.fa-mars-stroke-h:before { - content: "\f22b"; -} -.fa-neuter:before { - content: "\f22c"; -} -.fa-genderless:before { - content: "\f22d"; -} -.fa-facebook-official:before { - content: "\f230"; -} -.fa-pinterest-p:before { - content: "\f231"; -} -.fa-whatsapp:before { - content: "\f232"; -} -.fa-server:before { - content: "\f233"; -} -.fa-user-plus:before { - content: "\f234"; -} -.fa-user-times:before { - content: "\f235"; -} -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} -.fa-viacoin:before { - content: "\f237"; -} -.fa-train:before { - content: "\f238"; -} -.fa-subway:before { - content: "\f239"; -} -.fa-medium:before { - content: "\f23a"; -} -.fa-yc:before, -.fa-y-combinator:before { - content: "\f23b"; -} -.fa-optin-monster:before { - content: "\f23c"; -} -.fa-opencart:before { - content: "\f23d"; -} -.fa-expeditedssl:before { - content: "\f23e"; -} -.fa-battery-4:before, -.fa-battery-full:before { - content: "\f240"; -} -.fa-battery-3:before, -.fa-battery-three-quarters:before { - content: "\f241"; -} -.fa-battery-2:before, -.fa-battery-half:before { - content: "\f242"; -} -.fa-battery-1:before, -.fa-battery-quarter:before { - content: "\f243"; -} -.fa-battery-0:before, -.fa-battery-empty:before { - content: "\f244"; -} -.fa-mouse-pointer:before { - content: "\f245"; -} -.fa-i-cursor:before { - content: "\f246"; -} -.fa-object-group:before { - content: "\f247"; -} -.fa-object-ungroup:before { - content: "\f248"; -} -.fa-sticky-note:before { - content: "\f249"; -} -.fa-sticky-note-o:before { - content: "\f24a"; -} -.fa-cc-jcb:before { - content: "\f24b"; -} -.fa-cc-diners-club:before { - content: "\f24c"; -} -.fa-clone:before { - content: "\f24d"; -} -.fa-balance-scale:before { - content: "\f24e"; -} -.fa-hourglass-o:before { - content: "\f250"; -} -.fa-hourglass-1:before, -.fa-hourglass-start:before { - content: "\f251"; -} -.fa-hourglass-2:before, -.fa-hourglass-half:before { - content: "\f252"; -} -.fa-hourglass-3:before, -.fa-hourglass-end:before { - content: "\f253"; -} -.fa-hourglass:before { - content: "\f254"; -} -.fa-hand-grab-o:before, -.fa-hand-rock-o:before { - content: "\f255"; -} -.fa-hand-stop-o:before, -.fa-hand-paper-o:before { - content: "\f256"; -} -.fa-hand-scissors-o:before { - content: "\f257"; -} -.fa-hand-lizard-o:before { - content: "\f258"; -} -.fa-hand-spock-o:before { - content: "\f259"; -} -.fa-hand-pointer-o:before { - content: "\f25a"; -} -.fa-hand-peace-o:before { - content: "\f25b"; -} -.fa-trademark:before { - content: "\f25c"; -} -.fa-registered:before { - content: "\f25d"; -} -.fa-creative-commons:before { - content: "\f25e"; -} -.fa-gg:before { - content: "\f260"; -} -.fa-gg-circle:before { - content: "\f261"; -} -.fa-tripadvisor:before { - content: "\f262"; -} -.fa-odnoklassniki:before { - content: "\f263"; -} -.fa-odnoklassniki-square:before { - content: "\f264"; -} -.fa-get-pocket:before { - content: "\f265"; -} -.fa-wikipedia-w:before { - content: "\f266"; -} -.fa-safari:before { - content: "\f267"; -} -.fa-chrome:before { - content: "\f268"; -} -.fa-firefox:before { - content: "\f269"; -} -.fa-opera:before { - content: "\f26a"; -} -.fa-internet-explorer:before { - content: "\f26b"; -} -.fa-tv:before, -.fa-television:before { - content: "\f26c"; -} -.fa-contao:before { - content: "\f26d"; -} -.fa-500px:before { - content: "\f26e"; -} -.fa-amazon:before { - content: "\f270"; -} -.fa-calendar-plus-o:before { - content: "\f271"; -} -.fa-calendar-minus-o:before { - content: "\f272"; -} -.fa-calendar-times-o:before { - content: "\f273"; -} -.fa-calendar-check-o:before { - content: "\f274"; -} -.fa-industry:before { - content: "\f275"; -} -.fa-map-pin:before { - content: "\f276"; -} -.fa-map-signs:before { - content: "\f277"; -} -.fa-map-o:before { - content: "\f278"; -} -.fa-map:before { - content: "\f279"; -} -.fa-commenting:before { - content: "\f27a"; -} -.fa-commenting-o:before { - content: "\f27b"; -} -.fa-houzz:before { - content: "\f27c"; -} -.fa-vimeo:before { - content: "\f27d"; -} -.fa-black-tie:before { - content: "\f27e"; -} -.fa-fonticons:before { - content: "\f280"; -} diff --git a/vendors/font-awesome/css/font-awesome.css.map b/vendors/font-awesome/css/font-awesome.css.map deleted file mode 100644 index 60763a8..0000000 --- a/vendors/font-awesome/css/font-awesome.css.map +++ /dev/null @@ -1,7 +0,0 @@ -{ -"version": 3, -"mappings": ";;;;;;;AAGA,UAUC;EATC,WAAW,EAAE,aAAa;EAC1B,GAAG,EAAE,+CAAgE;EACrE,GAAG,EAAE,ySAAmG;EAKxG,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;ACTpB,GAAmB;EACjB,OAAO,EAAE,YAAY;EACrB,IAAI,EAAE,uCAAwD;EAC9D,SAAS,EAAE,OAAO;EAClB,cAAc,EAAE,IAAI;EACpB,sBAAsB,EAAE,WAAW;EACnC,uBAAuB,EAAE,SAAS;EAClC,SAAS,EAAE,eAAe;;;ACN5B,MAAsB;EACpB,SAAS,EAAE,SAAS;EACpB,WAAW,EAAE,MAAS;EACtB,cAAc,EAAE,IAAI;;AAEtB,MAAsB;EAAE,SAAS,EAAE,GAAG;;AACtC,MAAsB;EAAE,SAAS,EAAE,GAAG;;AACtC,MAAsB;EAAE,SAAS,EAAE,GAAG;;AACtC,MAAsB;EAAE,SAAS,EAAE,GAAG;;ACVtC,MAAsB;EACpB,KAAK,EAAE,SAAW;EAClB,UAAU,EAAE,MAAM;;ACDpB,MAAsB;EACpB,YAAY,EAAE,CAAC;EACf,WAAW,ECKU,SAAS;EDJ9B,eAAe,EAAE,IAAI;EACrB,WAAK;IAAE,QAAQ,EAAE,QAAQ;;AAE3B,MAAsB;EACpB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,UAAa;EACnB,KAAK,ECFgB,SAAS;EDG9B,GAAG,EAAE,SAAU;EACf,UAAU,EAAE,MAAM;EAClB,YAAuB;IACrB,IAAI,EAAE,UAA0B;;AEbpC,UAA0B;EACxB,OAAO,EAAE,gBAAgB;EACzB,MAAM,EAAE,iBAA4B;EACpC,aAAa,EAAE,IAAI;;AAGrB,WAAY;EAAE,KAAK,EAAE,KAAK;;AAC1B,UAAW;EAAE,KAAK,EAAE,IAAI;;AAGtB,aAAY;EAAE,YAAY,EAAE,IAAI;AAChC,cAAa;EAAE,WAAW,EAAE,IAAI;;ACXlC,QAAwB;EACtB,iBAAiB,EAAE,0BAA0B;EACrC,SAAS,EAAE,0BAA0B;;AAG/C,SAAyB;EACvB,iBAAiB,EAAE,4BAA4B;EACvC,SAAS,EAAE,4BAA4B;;AAGjD,0BASC;EARC,EAAG;IACD,iBAAiB,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;EAEjC,IAAK;IACH,iBAAiB,EAAE,cAAc;IACzB,SAAS,EAAE,cAAc;AAIrC,kBASC;EARC,EAAG;IACD,iBAAiB,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;EAEjC,IAAK;IACH,iBAAiB,EAAE,cAAc;IACzB,SAAS,EAAE,cAAc;AC5BrC,aAA8B;ECY5B,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,aAAgB;EAC/B,aAAa,EAAE,aAAgB;EAC3B,SAAS,EAAE,aAAgB;;ADdrC,cAA8B;ECW5B,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,cAAgB;EAC/B,aAAa,EAAE,cAAgB;EAC3B,SAAS,EAAE,cAAgB;;ADbrC,cAA8B;ECU5B,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,cAAgB;EAC/B,aAAa,EAAE,cAAgB;EAC3B,SAAS,EAAE,cAAgB;;ADXrC,mBAAmC;ECejC,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,YAAoB;EACnC,aAAa,EAAE,YAAoB;EAC/B,SAAS,EAAE,YAAoB;;ADjBzC,iBAAmC;ECcjC,MAAM,EAAE,wDAAmE;EAC3E,iBAAiB,EAAE,YAAoB;EACnC,aAAa,EAAE,YAAoB;EAC/B,SAAS,EAAE,YAAoB;;ADZzC;;;;uBAIuC;EACrC,MAAM,EAAE,IAAI;;AEfd,SAAyB;EACvB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,GAAG;EACX,WAAW,EAAE,GAAG;EAChB,cAAc,EAAE,MAAM;;AAExB,0BAAyD;EACvD,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;;AAEpB,YAA4B;EAAE,WAAW,EAAE,OAAO;;AAClD,YAA4B;EAAE,SAAS,EAAE,GAAG;;AAC5C,WAA2B;EAAE,KAAK,ELVZ,IAAI;;;;AMN1B,gBAAgC;EAAE,OAAO,ENoQ1B,GAAO;;AMnQtB,gBAAgC;EAAE,OAAO,EN0W1B,GAAO;;AMzWtB,iBAAiC;EAAE,OAAO,ENmb1B,GAAO;;AMlbvB,qBAAqC;EAAE,OAAO,ENmL1B,GAAO;;AMlL3B,gBAAgC;EAAE,OAAO,ENkR1B,GAAO;;AMjRtB,eAA+B;EAAE,OAAO,ENke1B,GAAO;;AMjerB,iBAAiC;EAAE,OAAO,ENse1B,GAAO;;AMrevB,eAA+B;EAAE,OAAO,EN+iB1B,GAAO;;AM9iBrB,eAA+B;EAAE,OAAO,ENyN1B,GAAO;;AMxNrB,mBAAmC;EAAE,OAAO,ENggB1B,GAAO;;AM/fzB,aAA6B;EAAE,OAAO,EN8f1B,GAAO;;AM7fnB,kBAAkC;EAAE,OAAO,EN+f1B,GAAO;;AM9fxB,gBAAgC;EAAE,OAAO,ENoG1B,GAAO;;AMnGtB;;gBAEgC;EAAE,OAAO,ENkgB1B,GAAO;;AMjgBtB,sBAAsC;EAAE,OAAO,ENua1B,GAAO;;AMta5B,uBAAuC;EAAE,OAAO,ENqa1B,GAAO;;AMpa7B,oBAAoC;EAAE,OAAO,EN+X1B,GAAO;;AM9X1B,iBAAiC;EAAE,OAAO,ENsb1B,GAAO;;AMrbvB;cAC8B;EAAE,OAAO,ENwH1B,GAAO;;AMvHpB,kBAAkC;EAAE,OAAO,ENygB1B,GAAO;;AMxgBxB,eAA+B;EAAE,OAAO,ENmQ1B,GAAO;;AMlQrB,iBAAiC;EAAE,OAAO,EN6L1B,GAAO;;AM5LvB,kBAAkC;EAAE,OAAO,EN0G1B,GAAO;;AMzGxB,eAA+B;EAAE,OAAO,EN+Y1B,GAAO;;AM9YrB,mBAAmC;EAAE,OAAO,ENiJ1B,GAAO;;AMhJzB,8BAA8C;EAAE,OAAO,ENI1B,GAAO;;AMHpC,4BAA4C;EAAE,OAAO,ENM1B,GAAO;;AMLlC,gBAAgC;EAAE,OAAO,ENkQ1B,GAAO;;AMjQtB,wBAAwC;EAAE,OAAO,EN4W1B,GAAO;;AM3W9B;iBACiC;EAAE,OAAO,ENmY1B,GAAO;;AMlYvB,kBAAkC;EAAE,OAAO,EN8X1B,GAAO;;AM7XxB,mBAAmC;EAAE,OAAO,ENiS1B,GAAO;;AMhSzB,eAA+B;EAAE,OAAO,ENoS1B,GAAO;;AMnSrB,eAA+B;EAAE,OAAO,ENgM1B,GAAO;;AM/LrB,qBAAqC;EAAE,OAAO,EN+O1B,GAAO;;AM9O3B,qBAAqC;EAAE,OAAO,EN8hB1B,GAAO;;AM7hB3B,sBAAsC;EAAE,OAAO,EN4hB1B,GAAO;;AM3hB5B,oBAAoC;EAAE,OAAO,EN6hB1B,GAAO;;AM5hB1B,iBAAiC;EAAE,OAAO,EN2W1B,GAAO;;AM1WvB,kBAAkC;EAAE,OAAO,ENW1B,GAAO;;AMVxB,cAA8B;EAAE,OAAO,ENod1B,GAAO;;AMndpB,eAA+B;EAAE,OAAO,ENod1B,GAAO;;AMndrB,eAA+B;EAAE,OAAO,EN2B1B,GAAO;;AM1BrB,mBAAmC;EAAE,OAAO,EN2B1B,GAAO;;AM1BzB,gBAAgC;EAAE,OAAO,ENkW1B,GAAO;;AMjWtB,iBAAiC;EAAE,OAAO,ENwC1B,GAAO;;AMvCvB,eAA+B;EAAE,OAAO,EN8L1B,GAAO;;AM7LrB,eAA+B;EAAE,OAAO,ENmB1B,GAAO;;AMlBrB,iBAAiC;EAAE,OAAO,ENoP1B,GAAO;;AMnPvB,sBAAsC;EAAE,OAAO,ENid1B,GAAO;;AMhd5B,qBAAqC;EAAE,OAAO,ENid1B,GAAO;;AMhd3B,qBAAqC;EAAE,OAAO,EN1C1B,GAAO;;AM2C3B,uBAAuC;EAAE,OAAO,EN7C1B,GAAO;;AM8C7B,sBAAsC;EAAE,OAAO,EN3C1B,GAAO;;AM4C5B,wBAAwC;EAAE,OAAO,EN9C1B,GAAO;;AM+C9B,eAA+B;EAAE,OAAO,ENwQ1B,GAAO;;AMvQrB;kBACkC;EAAE,OAAO,ENmT1B,GAAO;;AMlTxB,iBAAiC;EAAE,OAAO,ENmO1B,GAAO;;AMlOvB,uBAAuC;EAAE,OAAO,ENigB1B,GAAO;;AMhgB7B;;oBAEoC;EAAE,OAAO,EN+T1B,GAAO;;AM9T1B,iBAAiC;EAAE,OAAO,ENwT1B,GAAO;;AMvTvB,qBAAqC;EAAE,OAAO,EN+Q1B,GAAO;;AM9Q3B,iBAAiC;EAAE,OAAO,EN5D1B,GAAO;;AM6DvB,eAA+B;EAAE,OAAO,EN8c1B,GAAO;;AM7crB;0BAC0C;EAAE,OAAO,ENqT1B,GAAO;;AMpThC,yBAAyC;EAAE,OAAO,ENuX1B,GAAO;;AMtX/B,yBAAyC;EAAE,OAAO,EN0C1B,GAAO;;AMzC/B,iBAAiC;EAAE,OAAO,ENjC1B,GAAO;;AMkCvB,wBAAwC;EAAE,OAAO,ENma1B,GAAO;;AMla9B,wBAAwC;EAAE,OAAO,EN4H1B,GAAO;;AM3H9B,mBAAmC;EAAE,OAAO,EN7B1B,GAAO;;AM8BzB,eAA+B;EAAE,OAAO,EN0T1B,GAAO;;AMzTrB,gBAAgC;EAAE,OAAO,ENwS1B,GAAO;;AMvStB,eAA+B;EAAE,OAAO,ENia1B,GAAO;;AMharB,kBAAkC;EAAE,OAAO,ENgK1B,GAAO;;AM/JxB,uBAAuC;EAAE,OAAO,ENuH1B,GAAO;;AMtH7B,uBAAuC;EAAE,OAAO,EN4Z1B,GAAO;;AM3Z7B,gBAAgC;EAAE,OAAO,EN4F1B,GAAO;;AM3FtB,uBAAuC;EAAE,OAAO,ENoC1B,GAAO;;AMnC7B,wBAAwC;EAAE,OAAO,ENoC1B,GAAO;;AMnC9B,sBAAsC;EAAE,OAAO,ENsT1B,GAAO;;AMrT5B,uBAAuC;EAAE,OAAO,ENyQ1B,GAAO;;AMxQ7B,uBAAuC;EAAE,OAAO,ENwb1B,GAAO;;AMvb7B,uBAAuC;EAAE,OAAO,ENsB1B,GAAO;;AMrB7B,0BAA0C;EAAE,OAAO,EN2T1B,GAAO;;AM1ThC,sBAAsC;EAAE,OAAO,ENsM1B,GAAO;;AMrM5B,qBAAqC;EAAE,OAAO,EN6D1B,GAAO;;AM5D3B,yBAAyC;EAAE,OAAO,ENob1B,GAAO;;AMnb/B,yBAAyC;EAAE,OAAO,ENkB1B,GAAO;;AMjB/B,cAA8B;EAAE,OAAO,EN/C1B,GAAO;;AMgDpB,qBAAqC;EAAE,OAAO,EN3D1B,GAAO;;AM4D3B,sBAAsC;EAAE,OAAO,EN3D1B,GAAO;;AM4D5B,mBAAmC;EAAE,OAAO,EN3D1B,GAAO;;AM4DzB,qBAAqC;EAAE,OAAO,EN/D1B,GAAO;;AMgE3B;gBACgC;EAAE,OAAO,ENqV1B,GAAO;;AMpVtB,iBAAiC;EAAE,OAAO,ENuF1B,GAAO;;AMtFvB,mBAAmC;EAAE,OAAO,EN4C1B,GAAO;;AM3CzB,eAA+B;EAAE,OAAO,ENmS1B,GAAO;;AMlSrB,gBAAgC;EAAE,OAAO,ENsP1B,GAAO;;AMrPtB,mBAAmC;EAAE,OAAO,EN9D1B,GAAO;;AM+DzB,6BAA6C;EAAE,OAAO,ENgF1B,GAAO;;AM/EnC,eAA+B;EAAE,OAAO,EN+I1B,GAAO;;AM9IrB,eAA+B;EAAE,OAAO,ENoM1B,GAAO;;AMnMrB,eAA+B;EAAE,OAAO,ENmH1B,GAAO;;AMlHrB,cAA8B;EAAE,OAAO,ENiF1B,GAAO;;AMhFpB,oBAAoC;EAAE,OAAO,ENiF1B,GAAO;;AMhF1B;+BAC+C;EAAE,OAAO,EN0E1B,GAAO;;AMzErC,gBAAgC;EAAE,OAAO,ENmR1B,GAAO;;AMlRtB,mBAAmC;EAAE,OAAO,EN/B1B,GAAO;;AMgCzB,iBAAiC;EAAE,OAAO,ENoS1B,GAAO;;AMnSvB,kBAAkC;EAAE,OAAO,ENwB1B,GAAO;;AMvBxB,iBAAiC;EAAE,OAAO,ENqN1B,GAAO;;AMpNvB,qBAAqC;EAAE,OAAO,ENE1B,GAAO;;AMD3B,uBAAuC;EAAE,OAAO,ENF1B,GAAO;;AMG7B,kBAAkC;EAAE,OAAO,EN2S1B,GAAO;;AM1SxB,wBAAwC;EAAE,OAAO,ENyU1B,GAAO;;AMxU9B,iBAAiC;EAAE,OAAO,EN8G1B,GAAO;;AM7GvB,sBAAsC;EAAE,OAAO,EN+G1B,GAAO;;AM9G5B,mBAAmC;EAAE,OAAO,ENnF1B,GAAO;;AMoFzB,mBAAmC;EAAE,OAAO,ENrF1B,GAAO;;AMsFzB;oBACoC;EAAE,OAAO,EN/E1B,GAAO;;AMgF1B,yBAAyC;EAAE,OAAO,ENua1B,GAAO;;AMta/B,0BAA0C;EAAE,OAAO,ENmE1B,GAAO;;AMlEhC,uBAAuC;EAAE,OAAO,EN5C1B,GAAO;;AM6C7B,cAA8B;EAAE,OAAO,ENqK1B,GAAO;;AMpKpB;eAC+B;EAAE,OAAO,ENK1B,GAAO;;AMJrB,mBAAmC;EAAE,OAAO,ENQ1B,GAAO;;AMPzB,sBAAsC;EAAE,OAAO,ENmY1B,GAAO;;AMlY5B,wBAAwC;EAAE,OAAO,ENiY1B,GAAO;;AMhY9B,oBAAoC;EAAE,OAAO,EN2V1B,GAAO;;AM1V1B,kBAAkC;EAAE,OAAO,ENyI1B,GAAO;;AMxIxB,mBAAmC;EAAE,OAAO,ENyT1B,GAAO;;AMxTzB,0BAA0C;EAAE,OAAO,ENiL1B,GAAO;;AMhLhC,qBAAqC;EAAE,OAAO,EN0X1B,GAAO;;AMzX3B,wBAAwC;EAAE,OAAO,EN8C1B,GAAO;;AM7C9B,kBAAkC;EAAE,OAAO,ENoT1B,GAAO;;AMnTxB,iBAAiC;EAAE,OAAO,EN8Y1B,GAAO;;AM7YvB,wBAAwC;EAAE,OAAO,EN6G1B,GAAO;;AM5G9B,iBAAiC;EAAE,OAAO,EN8Z1B,GAAO;;AM7ZvB,kBAAkC;EAAE,OAAO,EN+J1B,GAAO;;AM9JxB,gBAAgC;EAAE,OAAO,ENsO1B,GAAO;;AMrOtB,mBAAmC;EAAE,OAAO,EN2U1B,GAAO;;AM1UzB,qBAAqC;EAAE,OAAO,EN/E1B,GAAO;;AMgF3B,uBAAuC;EAAE,OAAO,ENoO1B,GAAO;;AMnO7B,kBAAkC;EAAE,OAAO,EN8Y1B,GAAO;;AM7YxB;mBACmC;EAAE,OAAO,ENuC1B,GAAO;;AMtCzB,iBAAiC;EAAE,OAAO,ENiG1B,GAAO;;AMhGvB,iBAAiC;EAAE,OAAO,ENiZ1B,GAAO;;AMhZvB,sBAAsC;EAAE,OAAO,ENR1B,GAAO;;AMS5B,cAA8B;EAAE,OAAO,EN4Q1B,GAAO;;AM3QpB,gBAAgC;EAAE,OAAO,ENgH1B,GAAO;;AM/GtB,mBAAmC;EAAE,OAAO,ENnF1B,GAAO;;AMoFzB,eAA+B;EAAE,OAAO,ENzG1B,GAAO;;AM0GrB,sBAAsC;EAAE,OAAO,ENzD1B,GAAO;;AM0D5B,uBAAuC;EAAE,OAAO,EN0G1B,GAAO;;AMzG7B,sBAAsC;EAAE,OAAO,ENwG1B,GAAO;;AMvG5B,oBAAoC;EAAE,OAAO,ENyG1B,GAAO;;AMxG1B,sBAAsC;EAAE,OAAO,ENqG1B,GAAO;;AMpG5B,4BAA4C;EAAE,OAAO,EN5I1B,GAAO;;AM6IlC,6BAA6C;EAAE,OAAO,ENxI1B,GAAO;;AMyInC,0BAA0C;EAAE,OAAO,ENxI1B,GAAO;;AMyIhC,4BAA4C;EAAE,OAAO,ENhJ1B,GAAO;;AMiJlC,gBAAgC;EAAE,OAAO,ENsF1B,GAAO;;AMrFtB,iBAAiC;EAAE,OAAO,ENia1B,GAAO;;AMhavB,gBAAgC;EAAE,OAAO,ENiV1B,GAAO;;AMhVtB,iBAAiC;EAAE,OAAO,ENgD1B,GAAO;;AM/CvB,oBAAoC;EAAE,OAAO,ENvG1B,GAAO;;AMwG1B,qBAAqC;EAAE,OAAO,ENzI1B,GAAO;;AM0I3B;gBACgC;EAAE,OAAO,ENqY1B,GAAO;;AMpYtB;eAC+B;EAAE,OAAO,ENuI1B,GAAO;;AMtIrB,gBAAgC;EAAE,OAAO,ENpD1B,GAAO;;AMqDtB,gBAAgC;EAAE,OAAO,EN+C1B,GAAO;;AM9CtB;mBACmC;EAAE,OAAO,ENwP1B,GAAO;;AMvPzB;kBACkC;EAAE,OAAO,ENkC1B,GAAO;;AMjCxB,oBAAoC;EAAE,OAAO,ENsL1B,GAAO;;AMrL1B;mBACmC;EAAE,OAAO,EN0C1B,GAAO;;AMzCzB,iBAAiC;EAAE,OAAO,ENiS1B,GAAO;;AMhSvB;;eAE+B;EAAE,OAAO,EN9I1B,GAAO;;AM+IrB,kBAAkC;EAAE,OAAO,ENgI1B,GAAO;;AM/HxB,kBAAkC;EAAE,OAAO,EN8H1B,GAAO;;AM7HxB,wBAAwC;EAAE,OAAO,EN4S1B,GAAO;;AM3S9B,oBAAoC;EAAE,OAAO,ENoW1B,GAAO;;AMnW1B,gBAAgC;EAAE,OAAO,ENmT1B,GAAO;;AMlTtB,gBAAgC;EAAE,OAAO,ENkI1B,GAAO;;AMjItB,gBAAgC;EAAE,OAAO,ENuV1B,GAAO;;AMtVtB,oBAAoC;EAAE,OAAO,ENwL1B,GAAO;;AMvL1B,2BAA2C;EAAE,OAAO,ENyL1B,GAAO;;AMxLjC,6BAA6C;EAAE,OAAO,ENyD1B,GAAO;;AMxDnC,sBAAsC;EAAE,OAAO,ENuD1B,GAAO;;AMtD5B,gBAAgC;EAAE,OAAO,ENsJ1B,GAAO;;AMrJtB,qBAAqC;EAAE,OAAO,ENtH1B,GAAO;;AMuH3B,mBAAmC;EAAE,OAAO,ENhH1B,GAAO;;AMiHzB,qBAAqC;EAAE,OAAO,ENvH1B,GAAO;;AMwH3B,sBAAsC;EAAE,OAAO,ENvH1B,GAAO;;AMwH5B,kBAAkC;EAAE,OAAO,ENvE1B,GAAO;;AMwExB;eAC+B;EAAE,OAAO,EN2P1B,GAAO;;AM1PrB;oBACoC;EAAE,OAAO,EN+P1B,GAAO;;AM9P1B;mBACmC;EAAE,OAAO,EN4P1B,GAAO;;AM3PzB,mBAAmC;EAAE,OAAO,ENxC1B,GAAO;;AMyCzB,mBAAmC;EAAE,OAAO,ENkG1B,GAAO;;AMjGzB;eAC+B;EAAE,OAAO,EN8U1B,GAAO;;AM7UrB;gBACgC;EAAE,OAAO,ENqB1B,GAAO;;AMpBtB;qBACqC;EAAE,OAAO,EN2R1B,GAAO;;AM1R3B,oBAAoC;EAAE,OAAO,ENpF1B,GAAO;;AMqF1B,qBAAqC;EAAE,OAAO,ENnF1B,GAAO;;AMoF3B;eAC+B;EAAE,OAAO,ENjK1B,GAAO;;AMkKrB,kBAAkC;EAAE,OAAO,ENkO1B,GAAO;;AMjOxB,mBAAmC;EAAE,OAAO,ENkU1B,GAAO;;AMjUzB;oBACoC;EAAE,OAAO,EN1G1B,GAAO;;AM2G1B,sBAAsC;EAAE,OAAO,ENgF1B,GAAO;;AM/E5B,mBAAmC;EAAE,OAAO,ENnD1B,GAAO;;AMoDzB,yBAAyC;EAAE,OAAO,ENzG1B,GAAO;;AM0G/B,uBAAuC;EAAE,OAAO,ENzG1B,GAAO;;AM0G7B,kBAAkC;EAAE,OAAO,ENsU1B,GAAO;;AMrUxB,sBAAsC;EAAE,OAAO,EN+P1B,GAAO;;AM9P5B,mBAAmC;EAAE,OAAO,ENsQ1B,GAAO;;AMrQzB,iBAAiC;EAAE,OAAO,ENvL1B,GAAO;;AMwLvB,iBAAiC;EAAE,OAAO,ENzG1B,GAAO;;AM0GvB,kBAAkC;EAAE,OAAO,ENtF1B,GAAO;;AMuFxB,sBAAsC;EAAE,OAAO,EN3B1B,GAAO;;AM4B5B,qBAAqC;EAAE,OAAO,ENxK1B,GAAO;;AMyK3B,qBAAqC;EAAE,OAAO,ENkC1B,GAAO;;AMjC3B,oBAAoC;EAAE,OAAO,EN3O1B,GAAO;;AM4O1B,iBAAiC;EAAE,OAAO,ENiG1B,GAAO;;AMhGvB,sBAAsC;EAAE,OAAO,EN/C1B,GAAO;;AMgD5B,eAA+B;EAAE,OAAO,ENpM1B,GAAO;;AMqMrB,mBAAmC;EAAE,OAAO,ENe1B,GAAO;;AMdzB,sBAAsC;EAAE,OAAO,ENgJ1B,GAAO;;AM/I5B,4BAA4C;EAAE,OAAO,EN5O1B,GAAO;;AM6OlC,6BAA6C;EAAE,OAAO,EN5O1B,GAAO;;AM6OnC,0BAA0C;EAAE,OAAO,EN5O1B,GAAO;;AM6OhC,4BAA4C;EAAE,OAAO,ENhP1B,GAAO;;AMiPlC,qBAAqC;EAAE,OAAO,EN5O1B,GAAO;;AM6O3B,sBAAsC;EAAE,OAAO,EN5O1B,GAAO;;AM6O5B,mBAAmC;EAAE,OAAO,EN5O1B,GAAO;;AM6OzB,qBAAqC;EAAE,OAAO,ENhP1B,GAAO;;AMiP3B,kBAAkC;EAAE,OAAO,ENlG1B,GAAO;;AMmGxB,iBAAiC;EAAE,OAAO,ENuC1B,GAAO;;AMtCvB,iBAAiC;EAAE,OAAO,ENoP1B,GAAO;;AMnPvB;iBACiC;EAAE,OAAO,ENyF1B,GAAO;;AMxFvB,mBAAmC;EAAE,OAAO,EN9I1B,GAAO;;AM+IzB,qBAAqC;EAAE,OAAO,EN0I1B,GAAO;;AMzI3B,sBAAsC;EAAE,OAAO,EN0I1B,GAAO;;AMzI5B,kBAAkC;EAAE,OAAO,ENgN1B,GAAO;;AM/MxB,iBAAiC;EAAE,OAAO,ENnJ1B,GAAO;;AMoJvB;gBACgC;EAAE,OAAO,ENkJ1B,GAAO;;AMjJtB,qBAAqC;EAAE,OAAO,ENnB1B,GAAO;;AMoB3B,mBAAmC;EAAE,OAAO,ENxC1B,GAAO;;AMyCzB,wBAAwC;EAAE,OAAO,ENvC1B,GAAO;;AMwC9B,kBAAkC;EAAE,OAAO,EN0L1B,GAAO;;AMzLxB,kBAAkC;EAAE,OAAO,ENpC1B,GAAO;;AMqCxB,gBAAgC;EAAE,OAAO,ENoE1B,GAAO;;AMnEtB,kBAAkC;EAAE,OAAO,ENpC1B,GAAO;;AMqCxB,qBAAqC;EAAE,OAAO,ENkB1B,GAAO;;AMjB3B,iBAAiC;EAAE,OAAO,ENrD1B,GAAO;;AMsDvB,yBAAyC;EAAE,OAAO,ENvD1B,GAAO;;AMwD/B,mBAAmC;EAAE,OAAO,ENuO1B,GAAO;;AMtOzB,eAA+B;EAAE,OAAO,ENtJ1B,GAAO;;AMuJrB;oBACoC;EAAE,OAAO,ENqI1B,GAAO;;AMpI1B;;sBAEsC;EAAE,OAAO,ENuM1B,GAAO;;AMtM5B,yBAAyC;EAAE,OAAO,ENkC1B,GAAO;;AMjC/B,eAA+B;EAAE,OAAO,EN5I1B,GAAO;;AM6IrB,oBAAoC;EAAE,OAAO,EN7J1B,GAAO;;AM8J1B;uBACuC;EAAE,OAAO,EN1L1B,GAAO;;AM2L7B,mBAAmC;EAAE,OAAO,EN4G1B,GAAO;;AM3GzB,eAA+B;EAAE,OAAO,ENT1B,GAAO;;AMUrB,sBAAsC;EAAE,OAAO,ENhH1B,GAAO;;AMiH5B,sBAAsC;EAAE,OAAO,EN8M1B,GAAO;;AM7M5B,oBAAoC;EAAE,OAAO,ENyM1B,GAAO;;AMxM1B,iBAAiC;EAAE,OAAO,ENvH1B,GAAO;;AMwHvB,uBAAuC;EAAE,OAAO,ENmG1B,GAAO;;AMlG7B,qBAAqC;EAAE,OAAO,EN8C1B,GAAO;;AM7C3B,2BAA2C;EAAE,OAAO,EN8C1B,GAAO;;AM7CjC,iBAAiC;EAAE,OAAO,ENgJ1B,GAAO;;AM/IvB,qBAAqC;EAAE,OAAO,EN5N1B,GAAO;;AM6N3B,4BAA4C;EAAE,OAAO,ENjF1B,GAAO;;AMkFlC,iBAAiC;EAAE,OAAO,ENoH1B,GAAO;;AMnHvB,iBAAiC;EAAE,OAAO,ENkC1B,GAAO;;AMjCvB,8BAA8C;EAAE,OAAO,ENlM1B,GAAO;;AMmMpC,+BAA+C;EAAE,OAAO,ENlM1B,GAAO;;AMmMrC,4BAA4C;EAAE,OAAO,ENlM1B,GAAO;;AMmMlC,8BAA8C;EAAE,OAAO,ENtM1B,GAAO;;AMuMpC,gBAAgC;EAAE,OAAO,EN/B1B,GAAO;;AMgCtB,eAA+B;EAAE,OAAO,ENjK1B,GAAO;;AMkKrB,iBAAiC;EAAE,OAAO,EN9S1B,GAAO;;AM+SvB,qBAAqC;EAAE,OAAO,ENmP1B,GAAO;;AMlP3B,mBAAmC;EAAE,OAAO,EN9O1B,GAAO;;AM+OzB,qBAAqC;EAAE,OAAO,EN/I1B,GAAO;;AMgJ3B,qBAAqC;EAAE,OAAO,EN/I1B,GAAO;;AMgJ3B,qBAAqC;EAAE,OAAO,EN4G1B,GAAO;;AM3G3B,sBAAsC;EAAE,OAAO,ENsE1B,GAAO;;AMrE5B,iBAAiC;EAAE,OAAO,EN2M1B,GAAO;;AM1MvB,uBAAuC;EAAE,OAAO,EN6B1B,GAAO;;AM5B7B,yBAAyC;EAAE,OAAO,EN6B1B,GAAO;;AM5B/B,mBAAmC;EAAE,OAAO,ENhB1B,GAAO;;AMiBzB,qBAAqC;EAAE,OAAO,ENlB1B,GAAO;;AMmB3B,uBAAuC;EAAE,OAAO,ENvN1B,GAAO;;AMwN7B,wBAAwC;EAAE,OAAO,ENiD1B,GAAO;;AMhD9B,+BAA+C;EAAE,OAAO,EN3I1B,GAAO;;AM4IrC,uBAAuC;EAAE,OAAO,ENkH1B,GAAO;;AMjH7B,kBAAkC;EAAE,OAAO,EN1L1B,GAAO;;AM2LxB;8BAC8C;EAAE,OAAO,ENjP1B,GAAO;;AMkPpC;4BAC4C;EAAE,OAAO,ENhP1B,GAAO;;AMiPlC;+BAC+C;EAAE,OAAO,ENnP1B,GAAO;;AMoPrC;cAC8B;EAAE,OAAO,EN7J1B,GAAO;;AM8JpB,cAA8B;EAAE,OAAO,EN/F1B,GAAO;;AMgGpB;cAC8B;EAAE,OAAO,EN4N1B,GAAO;;AM3NpB;cAC8B;EAAE,OAAO,ENvD1B,GAAO;;AMwDpB;;;cAG8B;EAAE,OAAO,ENrD1B,GAAO;;AMsDpB;;cAE8B;EAAE,OAAO,EN8E1B,GAAO;;AM7EpB;cAC8B;EAAE,OAAO,ENtD1B,GAAO;;AMuDpB;cAC8B;EAAE,OAAO,ENzR1B,GAAO;;AM0RpB,eAA+B;EAAE,OAAO,ENzJ1B,GAAO;;AM0JrB,oBAAoC;EAAE,OAAO,EN7I1B,GAAO;;AM8I1B,yBAAyC;EAAE,OAAO,EN2G1B,GAAO;;AM1G/B,0BAA0C;EAAE,OAAO,EN2G1B,GAAO;;AM1GhC,0BAA0C;EAAE,OAAO,EN2G1B,GAAO;;AM1GhC,2BAA2C;EAAE,OAAO,EN2G1B,GAAO;;AM1GjC,2BAA2C;EAAE,OAAO,EN8G1B,GAAO;;AM7GjC,4BAA4C;EAAE,OAAO,EN8G1B,GAAO;;AM7GlC,oBAAoC;EAAE,OAAO,ENgK1B,GAAO;;AM/J1B,sBAAsC;EAAE,OAAO,EN4J1B,GAAO;;AM3J5B,yBAAyC;EAAE,OAAO,ENwO1B,GAAO;;AMvO/B,kBAAkC;EAAE,OAAO,ENqO1B,GAAO;;AMpOxB,eAA+B;EAAE,OAAO,EN+N1B,GAAO;;AM9NrB,sBAAsC;EAAE,OAAO,EN+N1B,GAAO;;AM9N5B,uBAAuC;EAAE,OAAO,ENmO1B,GAAO;;AMlO7B,kBAAkC;EAAE,OAAO,ENxM1B,GAAO;;AMyMxB,yBAAyC;EAAE,OAAO,EN+G1B,GAAO;;AM9G/B,oBAAoC;EAAE,OAAO,ENnF1B,GAAO;;AMoF1B,iBAAiC;EAAE,OAAO,EN/I1B,GAAO;;AMgJvB,cAA8B;EAAE,OAAO,ENhX1B,GAAO;;AMiXpB,oBAAoC;EAAE,OAAO,ENxT1B,GAAO;;AMyT1B,2BAA2C;EAAE,OAAO,ENxT1B,GAAO;;AMyTjC,iBAAiC;EAAE,OAAO,ENyK1B,GAAO;;AMxKvB,wBAAwC;EAAE,OAAO,ENyK1B,GAAO;;AMxK9B,0BAA0C;EAAE,OAAO,ENtD1B,GAAO;;AMuDhC,wBAAwC;EAAE,OAAO,ENpD1B,GAAO;;AMqD9B,0BAA0C;EAAE,OAAO,ENvD1B,GAAO;;AMwDhC,2BAA2C;EAAE,OAAO,ENvD1B,GAAO;;AMwDjC,gBAAgC;EAAE,OAAO,ENxW1B,GAAO;;AMyWtB,kBAAkC;EAAE,OAAO,EN0M1B,GAAO;;AMzMxB,kBAAkC;EAAE,OAAO,ENpX1B,GAAO;;AMqXxB,gBAAgC;EAAE,OAAO,ENpE1B,GAAO;;AMqEtB,mBAAmC;EAAE,OAAO,EN1N1B,GAAO;;AM2NzB,gBAAgC;EAAE,OAAO,ENqE1B,GAAO;;AMpEtB,qBAAqC;EAAE,OAAO,ENtJ1B,GAAO;;AMuJ3B,iBAAiC;EAAE,OAAO,ENuJ1B,GAAO;;AMtJvB,iBAAiC;EAAE,OAAO,EN/L1B,GAAO;;AMgMvB,eAA+B;EAAE,OAAO,EN1D1B,GAAO;;AM2DrB;mBACmC;EAAE,OAAO,ENnI1B,GAAO;;AMoIzB,gBAAgC;EAAE,OAAO,EN2G1B,GAAO;;AM1GtB,iBAAiC;EAAE,OAAO,ENxC1B,GAAO;;AMyCvB,kBAAkC;EAAE,OAAO,ENrX1B,GAAO;;AMsXxB,cAA8B;EAAE,OAAO,ENpU1B,GAAO;;AMqUpB,aAA6B;EAAE,OAAO,ENgL1B,GAAO;;AM/KnB,gBAAgC;EAAE,OAAO,ENqL1B,GAAO;;AMpLtB,iBAAiC;EAAE,OAAO,ENa1B,GAAO;;AMZvB,oBAAoC;EAAE,OAAO,ENrC1B,GAAO;;AMsC1B,yBAAyC;EAAE,OAAO,EN8E1B,GAAO;;AM7E/B,+BAA+C;EAAE,OAAO,ENtX1B,GAAO;;AMuXrC,8BAA8C;EAAE,OAAO,ENxX1B,GAAO;;AMyXpC;8BAC8C;EAAE,OAAO,EN3T1B,GAAO;;AM4TpC,uBAAuC;EAAE,OAAO,ENjP1B,GAAO;;AMkP7B,qBAAqC;EAAE,OAAO,EN+K1B,GAAO;;AM9K3B,uBAAuC;EAAE,OAAO,ENmK1B,GAAO;;AMlK7B;cAC8B;EAAE,OAAO,ENoI1B,GAAO;;AMnIpB,wBAAwC;EAAE,OAAO,ENjB1B,GAAO;;AMkB9B,wBAAwC;EAAE,OAAO,EN6D1B,GAAO;;AM5D9B,gBAAgC;EAAE,OAAO,EN2C1B,GAAO;;AM1CtB,0BAA0C;EAAE,OAAO,EN7O1B,GAAO;;AM8OhC,oBAAoC;EAAE,OAAO,EN2K1B,GAAO;;AM1K1B,iBAAiC;EAAE,OAAO,ENvD1B,GAAO;;AMwDvB;;qBAEqC;EAAE,OAAO,ENsI1B,GAAO;;AMrI3B;yBACyC;EAAE,OAAO,ENjK1B,GAAO;;AMkK/B,gBAAgC;EAAE,OAAO,ENwK1B,GAAO;;AMvKtB,iBAAiC;EAAE,OAAO,ENvK1B,GAAO;;AMwKvB,iBAAiC;EAAE,OAAO,ENhB1B,GAAO;;AMiBvB,wBAAwC;EAAE,OAAO,ENhB1B,GAAO;;AMiB9B,6BAA6C;EAAE,OAAO,ENsE1B,GAAO;;AMrEnC,sBAAsC;EAAE,OAAO,ENoE1B,GAAO;;AMnE5B,oBAAoC;EAAE,OAAO,EN7Q1B,GAAO;;AM8Q1B,eAA+B;EAAE,OAAO,EN1Q1B,GAAO;;AM2QrB,qBAAqC;EAAE,OAAO,ENjD1B,GAAO;;AMkD3B,yBAAyC;EAAE,OAAO,ENjD1B,GAAO;;AMkD/B,iBAAiC;EAAE,OAAO,ENvQ1B,GAAO;;AMwQvB,iBAAiC;EAAE,OAAO,EN9I1B,GAAO;;AM+IvB,mBAAmC;EAAE,OAAO,ENzI1B,GAAO;;AM0IzB,cAA8B;EAAE,OAAO,EN9O1B,GAAO;;AM+OpB,mBAAmC;EAAE,OAAO,EN3W1B,GAAO;;AM4WzB,gBAAgC;EAAE,OAAO,EN9T1B,GAAO;;AM+TtB,cAA8B;EAAE,OAAO,ENnE1B,GAAO;;AMoEpB,gBAAgC;EAAE,OAAO,ENoC1B,GAAO;;AMnCtB,eAA+B;EAAE,OAAO,ENjS1B,GAAO;;AMkSrB,gBAAgC;EAAE,OAAO,ENjS1B,GAAO;;AMkStB,kBAAkC;EAAE,OAAO,ENtY1B,GAAO;;AMuYxB,yBAAyC;EAAE,OAAO,ENtY1B,GAAO;;AMuY/B,gBAAgC;EAAE,OAAO,EN2C1B,GAAO;;AM1CtB,uBAAuC;EAAE,OAAO,EN2C1B,GAAO;;AM1C7B,kBAAkC;EAAE,OAAO,ENvC1B,GAAO;;AMwCxB;cAC8B;EAAE,OAAO,EN3W1B,GAAO;;AM4WpB;eAC+B;EAAE,OAAO,EN2D1B,GAAO;;AM1DrB,eAA+B;EAAE,OAAO,ENuF1B,GAAO;;AMtFrB,kBAAkC;EAAE,OAAO,ENwB1B,GAAO;;AMvBxB,qBAAqC;EAAE,OAAO,ENpS1B,GAAO;;AMqS3B,qBAAqC;EAAE,OAAO,ENkB1B,GAAO;;AMjB3B,mBAAmC;EAAE,OAAO,EN1S1B,GAAO;;AM2SzB,qBAAqC;EAAE,OAAO,ENxP1B,GAAO;;AMyP3B,sBAAsC;EAAE,OAAO,ENjP1B,GAAO;;AMkP5B,uBAAuC;EAAE,OAAO,EN9P1B,GAAO;;AM+P7B,4BAA4C;EAAE,OAAO,ENxP1B,GAAO;;AMyPlC;;uBAEuC;EAAE,OAAO,ENjQ1B,GAAO;;AMkQ7B;yBACyC;EAAE,OAAO,ENvQ1B,GAAO;;AMwQ/B;uBACuC;EAAE,OAAO,ENxQ1B,GAAO;;AMyQ7B;uBACuC;EAAE,OAAO,EN7P1B,GAAO;;AM8P7B,sBAAsC;EAAE,OAAO,EN1Q1B,GAAO;;AM2Q5B,eAA+B;EAAE,OAAO,ENsG1B,GAAO;;AMrGrB,kBAAkC;EAAE,OAAO,ENlV1B,GAAO;;AMmVxB,mBAAmC;EAAE,OAAO,ENnL1B,GAAO;;AMoLzB;;;;oBAIoC;EAAE,OAAO,ENxK1B,GAAO;;AMyK1B,yBAAyC;EAAE,OAAO,ENpW1B,GAAO;;AMqW/B;gBACgC;EAAE,OAAO,EN1E1B,GAAO;;AM2EtB;iBACiC;EAAE,OAAO,ENpT1B,GAAO;;AMqTvB,qBAAqC;EAAE,OAAO,EN1O1B,GAAO;;AM2O3B,cAA8B;EAAE,OAAO,EN5O1B,GAAO;;AM6OpB,sBAAsC;EAAE,OAAO,EN7N1B,GAAO;;AM8N5B,wBAAwC;EAAE,OAAO,ENwB1B,GAAO;;AMvB9B,aAA6B;EAAE,OAAO,ENzF1B,GAAO;;AM0FnB;iBACiC;EAAE,OAAO,EN2F1B,GAAO;;AM1FvB;sBACsC;EAAE,OAAO,EN9H1B,GAAO;;AM+H5B;wBACwC;EAAE,OAAO,EN/H1B,GAAO;;AMgI9B,kBAAkC;EAAE,OAAO,EN3N1B,GAAO;;AM4NxB;sBACsC;EAAE,OAAO,ENrX1B,GAAO;;AMsX5B,iBAAiC;EAAE,OAAO,ENnO1B,GAAO;;AMoOvB,oBAAoC;EAAE,OAAO,ENlI1B,GAAO;;AMmI1B,kBAAkC;EAAE,OAAO,EN1C1B,GAAO;;AM2CxB,oBAAoC;EAAE,OAAO,EN7D1B,GAAO;;AM8D1B,2BAA2C;EAAE,OAAO,EN7D1B,GAAO;;AM8DjC,eAA+B;EAAE,OAAO,ENpb1B,GAAO;;AMqbrB;mBACmC;EAAE,OAAO,ENzQ1B,GAAO;;AM0QzB,cAA8B;EAAE,OAAO,ENsC1B,GAAO;;AMrCpB,qBAAqC;EAAE,OAAO,EN/b1B,GAAO;;AMgc3B,eAA+B;EAAE,OAAO,ENrH1B,GAAO;;AMsHrB,qBAAqC;EAAE,OAAO,ENlD1B,GAAO;;AMmD3B,iBAAiC;EAAE,OAAO,ENsC1B,GAAO;;AMrCvB,eAA+B;EAAE,OAAO,ENiF1B,GAAO;;AMhFrB,sBAAsC;EAAE,OAAO,ENvJ1B,GAAO;;AMwJ5B,eAA+B;EAAE,OAAO,ENuE1B,GAAO;;AMtErB,qBAAqC;EAAE,OAAO,ENjb1B,GAAO;;AMkb3B,iBAAiC;EAAE,OAAO,EN9I1B,GAAO;;AM+IvB,wBAAwC;EAAE,OAAO,ENhQ1B,GAAO;;AMiQ9B,kBAAkC;EAAE,OAAO,EN9Z1B,GAAO;;AM+ZxB,wBAAwC;EAAE,OAAO,ENla1B,GAAO;;AMma9B,sBAAsC;EAAE,OAAO,ENpa1B,GAAO;;AMqa5B,kBAAkC;EAAE,OAAO,ENta1B,GAAO;;AMuaxB,oBAAoC;EAAE,OAAO,ENpa1B,GAAO;;AMqa1B,oBAAoC;EAAE,OAAO,ENpa1B,GAAO;;AMqa1B,qBAAqC;EAAE,OAAO,ENld1B,GAAO;;AMmd3B,uBAAuC;EAAE,OAAO,ENld1B,GAAO;;AMmd7B,gBAAgC;EAAE,OAAO,ENY1B,GAAO;;AMXtB,oBAAoC;EAAE,OAAO,EN3X1B,GAAO;;AM4X1B,aAA6B;EAAE,OAAO,ENre1B,GAAO;;AMsenB,qBAAqC;EAAE,OAAO,ENjV1B,GAAO;;AMkV3B,sBAAsC;EAAE,OAAO,ENpK1B,GAAO;;AMqK5B,wBAAwC;EAAE,OAAO,ENrd1B,GAAO;;AMsd9B,qBAAqC;EAAE,OAAO,EN3f1B,GAAO;;AM4f3B,oBAAoC;EAAE,OAAO,ENvJ1B,GAAO;;AMwJ1B,qBAAqC;EAAE,OAAO,EN5N1B,GAAO;;AM6N3B,iBAAiC;EAAE,OAAO,EN1O1B,GAAO;;AM2OvB,wBAAwC;EAAE,OAAO,EN1O1B,GAAO;;AM2O9B,qBAAqC;EAAE,OAAO,ENN1B,GAAO;;AMO3B,oBAAoC;EAAE,OAAO,ENN1B,GAAO;;AMO1B,kBAAkC;EAAE,OAAO,EN/d1B,GAAO;;AMgexB,cAA8B;EAAE,OAAO,EN7c1B,GAAO;;AM8cpB,kBAAkC;EAAE,OAAO,EN1P1B,GAAO;;AM2PxB,oBAAoC;EAAE,OAAO,ENhhB1B,GAAO;;AMihB1B,aAA6B;EAAE,OAAO,EN7b1B,GAAO;;AM8bnB;;cAE8B;EAAE,OAAO,ENxQ1B,GAAO;;AMyQpB,mBAAmC;EAAE,OAAO,EN7M1B,GAAO;;AM8MzB,qBAAqC;EAAE,OAAO,ENpd1B,GAAO;;AMqd3B,yBAAyC;EAAE,OAAO,ENnZ1B,GAAO;;AMoZ/B,mBAAmC;EAAE,OAAO,ENxY1B,GAAO;;AMyYzB,mBAAmC;EAAE,OAAO,EN1T1B,GAAO;;AM2TzB,kBAAkC;EAAE,OAAO,ENxP1B,GAAO;;AMyPxB,iBAAiC;EAAE,OAAO,ENrH1B,GAAO;;AMsHvB,uBAAuC;EAAE,OAAO,ENzG1B,GAAO;;AM0G7B,sBAAsC;EAAE,OAAO,ENrG1B,GAAO;;AMsG5B,mBAAmC;EAAE,OAAO,ENpG1B,GAAO;;AMqGzB,oBAAoC;EAAE,OAAO,EN5c1B,GAAO;;AM6c1B,0BAA0C;EAAE,OAAO,EN9c1B,GAAO;;AM+chC,kBAAkC;EAAE,OAAO,EN3Y1B,GAAO;;AM4YxB,eAA+B;EAAE,OAAO,ENhH1B,GAAO;;AMiHrB,sBAAsC;EAAE,OAAO,ENI1B,GAAO;;AMH5B,qBAAqC;EAAE,OAAO,EN5M1B,GAAO;;AM6M3B,sBAAsC;EAAE,OAAO,ENpE1B,GAAO;;AMqE5B,oBAAoC;EAAE,OAAO,ENhS1B,GAAO;;AMiS1B,gBAAgC;EAAE,OAAO,ENG1B,GAAO;;AMFtB,eAA+B;EAAE,OAAO,ENtO1B,GAAO;;AMuOrB,kBAAkC;EAAE,OAAO,EN7N1B,GAAO;;AM8NxB,sBAAsC;EAAE,OAAO,ENhC1B,GAAO;;AMiC5B,0BAA0C;EAAE,OAAO,ENhC1B,GAAO;;AMiChC,uBAAuC;EAAE,OAAO,END1B,GAAO;;AME7B,sBAAsC;EAAE,OAAO,EN1O1B,GAAO;;AM2O5B,qBAAqC;EAAE,OAAO,ENF1B,GAAO;;AMG3B,sBAAsC;EAAE,OAAO,EN3O1B,GAAO;;AM4O5B,wBAAwC;EAAE,OAAO,EN1O1B,GAAO;;AM2O9B,wBAAwC;EAAE,OAAO,EN5O1B,GAAO;;AM6O9B,iBAAiC;EAAE,OAAO,ENvN1B,GAAO;;AMwNvB,4BAA4C;EAAE,OAAO,EN9X1B,GAAO;;AM+XlC,sBAAsC;EAAE,OAAO,ENhM1B,GAAO;;AMiM5B,mBAAmC;EAAE,OAAO,ENI1B,GAAO;;AMHzB,iBAAiC;EAAE,OAAO,EN7I1B,GAAO;;AM8IvB,oBAAoC;EAAE,OAAO,ENjB1B,GAAO;;AMkB1B,qBAAqC;EAAE,OAAO,ENhB1B,GAAO;;AMiB3B;cAC8B;EAAE,OAAO,ENphB1B,GAAO;;AMqhBpB,kBAAkC;EAAE,OAAO,ENd1B,GAAO;;AMexB,gBAAgC;EAAE,OAAO,ENnD1B,GAAO;;AMoDtB,iBAAiC;EAAE,OAAO,ENvF1B,GAAO;;AMwFvB,iBAAiC;EAAE,OAAO,ENrP1B,GAAO", -"sources": ["../scss/_path.scss","../scss/_core.scss","../scss/_larger.scss","../scss/_fixed-width.scss","../scss/_list.scss","../scss/_variables.scss","../scss/_bordered-pulled.scss","../scss/_animated.scss","../scss/_rotated-flipped.scss","../scss/_mixins.scss","../scss/_stacked.scss","../scss/_icons.scss"], -"names": [], -"file": "font-awesome.css" -} diff --git a/vendors/font-awesome/css/font-awesome.min.css b/vendors/font-awesome/css/font-awesome.min.css deleted file mode 100644 index ee4e978..0000000 --- a/vendors/font-awesome/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} diff --git a/vendors/font-awesome/fonts/FontAwesome.otf b/vendors/font-awesome/fonts/FontAwesome.otf deleted file mode 100644 index 681bdd4..0000000 Binary files a/vendors/font-awesome/fonts/FontAwesome.otf and /dev/null differ diff --git a/vendors/font-awesome/fonts/fontawesome-webfont.eot b/vendors/font-awesome/fonts/fontawesome-webfont.eot deleted file mode 100644 index a30335d..0000000 Binary files a/vendors/font-awesome/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/vendors/font-awesome/fonts/fontawesome-webfont.woff b/vendors/font-awesome/fonts/fontawesome-webfont.woff deleted file mode 100644 index 6fd4ede..0000000 Binary files a/vendors/font-awesome/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/vendors/font-awesome/fonts/fontawesome-webfont.woff2 b/vendors/font-awesome/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 5560193..0000000 Binary files a/vendors/font-awesome/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/vendors/jquery/index.js b/vendors/jquery/index.js deleted file mode 100644 index 25714ed..0000000 --- a/vendors/jquery/index.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c) -},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("