Rev 2199 | Rev 2202 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed
| Rev 2199 | Rev 2200 | ||
|---|---|---|---|
| Line 51... | Line 51... | ||
| 51 | #if (IR_PROTOCOLS_USE_NEXA2) |
51 | #if (IR_PROTOCOLS_USE_NEXA2) |
| 52 | if (parseNexa2(buf, len, index, proto)==IR_OK) return IR_OK; |
52 | if (parseNexa2(buf, len, index, proto)==IR_OK) return IR_OK; |
| 53 | #endif |
53 | #endif |
| 54 | #if (IR_PROTOCOLS_USE_NEXA1) |
54 | #if (IR_PROTOCOLS_USE_NEXA1) |
| 55 | if (parseNexa1(buf, len, index, proto)==IR_OK) return IR_OK; |
55 | if (parseNexa1(buf, len, index, proto)==IR_OK) return IR_OK; |
| - | 56 | #endif |
|
| - | 57 | #if (IR_PROTOCOLS_USE_VIKING) |
|
| - | 58 | if (parseViking(buf, len, index, proto)==IR_OK) return IR_OK; |
|
| 56 | #endif |
59 | #endif |
| 57 | /* No protocol matched. */ |
60 | /* No protocol matched. */ |
| 58 | proto->protocol = IR_PROTO_UNKNOWN; |
61 | proto->protocol = IR_PROTO_UNKNOWN; |
| 59 | return IR_NOT_CORRECT_DATA; |
62 | return IR_NOT_CORRECT_DATA; |
| 60 | } |
63 | } |
| Line 342... | Line 345... | ||
| 342 | 345 | ||
| 343 | 346 | ||
| 344 | #if (IR_PROTOCOLS_USE_SHARP) |
347 | #if (IR_PROTOCOLS_USE_SHARP) |
| 345 | /** |
348 | /** |
| 346 | * Test data on SHARP protocol |
349 | * Test data on SHARP protocol |
| 347 | * http://www.sbprojects.com/knowledge/ir/sharp.htm |
350 | * http://www.sbprojects.com/knowledge/ir/sharp.htm |
| 348 | * |
351 | * |
| 349 | * @param buf |
352 | * @param buf |
| 350 | * Pointer to buffer to where to data to parse is stored |
353 | * Pointer to buffer to where to data to parse is stored |
| 351 | * @param len |
354 | * @param len |
| 352 | * Length of the data |
355 | * Length of the data |
| 353 | * @param proto |
356 | * @param proto |
| Line 358... | Line 361... | ||
| 358 | int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) { |
361 | int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) { |
| 359 | /* parse buf[], max is len */ |
362 | /* parse buf[], max is len */ |
| 360 | 363 | ||
| 361 | /* check if we have correct amount of data */ |
364 | /* check if we have correct amount of data */ |
| 362 | if (len != 31) { |
365 | if (len != 31) { |
| 363 | return IR_NOT_CORRECT_DATA; |
366 | return IR_NOT_CORRECT_DATA; |
| 364 | } |
367 | } |
| 365 | 368 | ||
| 366 | uint16_t rawbits=0; |
369 | uint16_t rawbits=0; |
| 367 | 370 | ||
| 368 | for (uint8_t i = 1; i < len; i++) { |
371 | for (uint8_t i = 1; i < len; i++) { |
| 369 | if ((i&1) == 1) { /* if odd, ir-pause */ |
372 | if ((i&1) == 1) { /* if odd, ir-pause */ |
| 370 | /* check length of pause between bits */ |
373 | /* check length of pause between bits */ |
| Line 372... | Line 375... | ||
| 372 | /* write a one */ |
375 | /* write a one */ |
| 373 | rawbits |= 1<<((i-1)>>1); |
376 | rawbits |= 1<<((i-1)>>1); |
| 374 | } else if (buf[i] > IR_SHARP_LOW_ZERO - IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV && buf[i] < IR_SHARP_LOW_ZERO + IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV) { |
377 | } else if (buf[i] > IR_SHARP_LOW_ZERO - IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV && buf[i] < IR_SHARP_LOW_ZERO + IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV) { |
| 375 | /* do nothing, a zero is already in rawbits */ |
378 | /* do nothing, a zero is already in rawbits */ |
| 376 | } else { |
379 | } else { |
| 377 | return IR_NOT_CORRECT_DATA; |
380 | return IR_NOT_CORRECT_DATA; |
| 378 | } |
381 | } |
| 379 | } else { /* if even, ir-bit */ |
382 | } else { /* if even, ir-bit */ |
| 380 | if (buf[i] > IR_SHARP_HIGH + IR_SHARP_HIGH/IR_SHARP_TOL_DIV || buf[i] < IR_SHARP_HIGH - IR_SHARP_HIGH/IR_SHARP_TOL_DIV) { |
383 | if (buf[i] > IR_SHARP_HIGH + IR_SHARP_HIGH/IR_SHARP_TOL_DIV || buf[i] < IR_SHARP_HIGH - IR_SHARP_HIGH/IR_SHARP_TOL_DIV) { |
| 381 | return IR_NOT_CORRECT_DATA; |
384 | return IR_NOT_CORRECT_DATA; |
| 382 | } |
385 | } |
| 383 | } |
386 | } |
| 384 | } |
387 | } |
| 385 | 388 | ||
| 386 | proto->protocol=IR_PROTO_SHARP; |
389 | proto->protocol=IR_PROTO_SHARP; |
| 387 | proto->timeout=IR_SHARP_TIMEOUT; |
390 | proto->timeout=IR_SHARP_TIMEOUT; |
| Line 391... | Line 394... | ||
| 391 | #endif |
394 | #endif |
| 392 | 395 | ||
| 393 | /** |
396 | /** |
| 394 | * Expand data from Sharp protocol |
397 | * Expand data from Sharp protocol |
| 395 | * http://www.sbprojects.com/knowledge/ir/sharp.htm |
398 | * http://www.sbprojects.com/knowledge/ir/sharp.htm |
| 396 | * |
399 | * |
| 397 | * @param buf |
400 | * @param buf |
| 398 | * Pointer to buffer to store the expanded data |
401 | * Pointer to buffer to store the expanded data |
| 399 | * @param len |
402 | * @param len |
| 400 | * Pointer to length of the data |
403 | * Pointer to length of the data |
| 401 | * @param proto |
404 | * @param proto |
| 402 | * Pointer to protocol information |
405 | * Pointer to protocol information |
| 403 | * @return |
406 | * @return |
| 404 | * IR_OK if data expanded successfully, one of several errormessages if not |
407 | * IR_OK if data expanded successfully, one of several errormessages if not |
| 405 | */ |
408 | */ |
| 406 | int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) { |
409 | int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) { |
| 407 | //TODO: Implement this function. |
410 | //TODO: Implement this function. |
| 408 | return IR_NOT_CORRECT_DATA; |
411 | return IR_NOT_CORRECT_DATA; |
| 409 | } |
412 | } |
| 410 | 413 | ||
| 411 | 414 | ||
| 412 | #if (IR_PROTOCOLS_USE_NEC) |
415 | #if (IR_PROTOCOLS_USE_NEC) |
| 413 | /** |
416 | /** |
| 414 | * Test data on NEC protocol |
417 | * Test data on NEC protocol |
| 415 | * http://www.sbprojects.com/knowledge/ir/nec.htm |
418 | * http://www.sbprojects.com/knowledge/ir/nec.htm |
| 416 | * |
419 | * |
| 417 | * @param buf |
420 | * @param buf |
| 418 | * Pointer to buffer to where to data to parse is stored |
421 | * Pointer to buffer to where to data to parse is stored |
| 419 | * @param len |
422 | * @param len |
| 420 | * Length of the data |
423 | * Length of the data |
| 421 | * @param proto |
424 | * @param proto |
| 422 | * Pointer to protocol information |
425 | * Pointer to protocol information |
| Line 484... | Line 487... | ||
| 484 | int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) { |
487 | int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) { |
| 485 | /* Set up startbit */ |
488 | /* Set up startbit */ |
| 486 | buf[0] = IR_NEC_ST_BIT; |
489 | buf[0] = IR_NEC_ST_BIT; |
| 487 | 490 | ||
| 488 | if (proto->framecnt == 0) { |
491 | if (proto->framecnt == 0) { |
| 489 | buf[1] = IR_NEC_ST_PAUSE; |
492 | buf[1] = IR_NEC_ST_PAUSE; |
| 490 | 493 | ||
| 491 | *len = 67; |
494 | *len = 67; |
| 492 | for (uint8_t i = 0; i < 65; i++) { |
495 | for (uint8_t i = 0; i < 65; i++) { |
| 493 | if ((i&1) == 1) { /* if odd, ir-pause */ |
496 | if ((i&1) == 1) { /* if odd, ir-pause */ |
| 494 | if ((proto->data>>(i>>1))&1) { |
497 | if ((proto->data>>(i>>1))&1) { |
| 495 | buf[i+2] = IR_NEC_LOW_ONE; |
498 | buf[i+2] = IR_NEC_LOW_ONE; |
| 496 | } else { |
499 | } else { |
| 497 | buf[i+2] = IR_NEC_LOW_ZERO; |
500 | buf[i+2] = IR_NEC_LOW_ZERO; |
| 498 | } |
501 | } |
| 499 | } else { /* if even, ir-bit */ |
502 | } else { /* if even, ir-bit */ |
| Line 922... | Line 925... | ||
| 922 | rawbits = rawbits<<1; |
925 | rawbits = rawbits<<1; |
| 923 | rawbits |= 1; |
926 | rawbits |= 1; |
| 924 | } |
927 | } |
| 925 | else { |
928 | else { |
| 926 | cnt = 0; |
929 | cnt = 0; |
| 927 | } |
930 | } |
| 928 | } |
931 | } |
| 929 | 932 | ||
| 930 | previous=current; |
933 | previous=current; |
| 931 | 934 | ||
| 932 | } |
935 | } |
| 933 | 936 | ||
| 934 | proto->protocol = IR_PROTO_SKY; |
937 | proto->protocol = IR_PROTO_SKY; |
| 935 | proto->timeout = IR_SKY_TIMEOUT; |
938 | proto->timeout = IR_SKY_TIMEOUT; |
| 936 | proto->data = rawbits; |
939 | proto->data = rawbits; |
| 937 | 940 | ||
| Line 940... | Line 943... | ||
| 940 | #endif |
943 | #endif |
| 941 | 944 | ||
| 942 | /** |
945 | /** |
| 943 | * Expand data from Sky protocol |
946 | * Expand data from Sky protocol |
| 944 | * |
947 | * |
| 945 | * |
948 | * |
| 946 | * @param buf |
949 | * @param buf |
| 947 | * Pointer to buffer to store the expanded data |
950 | * Pointer to buffer to store the expanded data |
| 948 | * @param len |
951 | * @param len |
| 949 | * Pointer to length of the data |
952 | * Pointer to length of the data |
| 950 | * @param proto |
953 | * @param proto |
| 951 | * Pointer to protocol information |
954 | * Pointer to protocol information |
| 952 | * @return |
955 | * @return |
| 953 | * IR_OK if data expanded successfully, one of several errormessages if not |
956 | * IR_OK if data expanded successfully, one of several errormessages if not |
| 954 | */ |
957 | */ |
| 955 | int8_t expandSky(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) { |
958 | int8_t expandSky(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) { |
| 956 | //TODO: Implement this function. |
959 | //TODO: Implement this function. |
| 957 | buf[0] = IR_SKY_ST_BIT; |
960 | buf[0] = IR_SKY_ST_BIT; |
| 958 | buf[1] = IR_SKY_LONG; // |
961 | buf[1] = IR_SKY_LONG; // |
| 959 | 962 | ||
| 960 | 963 | ||
| 961 | return IR_NOT_CORRECT_DATA; |
964 | return IR_NOT_CORRECT_DATA; |
| 962 | } |
965 | } |
| 963 | 966 | ||
| 964 | #if (IR_PROTOCOLS_USE_NEXA2) |
967 | #if (IR_PROTOCOLS_USE_NEXA2) |
| 965 | /** |
968 | /** |
| 966 | * Test data on NEXA protocol |
969 | * Test data on NEXA protocol |
| 967 | * http://elektronikforumet.com/wiki/index.php?title=RF_Protokoll_-_Nexa_sj%C3%A4lvl%C3%A4rande |
970 | * http://elektronikforumet.com/wiki/index.php?title=RF_Protokoll_-_Nexa_sj%C3%A4lvl%C3%A4rande |
| 968 | * http://pastebin.com/PJX3bRAs |
971 | * http://pastebin.com/PJX3bRAs |
| Line 986... | Line 989... | ||
| 986 | uint8_t i; |
989 | uint8_t i; |
| 987 | #if IR_RX_CONTINUOUS_MODE==0 |
990 | #if IR_RX_CONTINUOUS_MODE==0 |
| 988 | i = 0; |
991 | i = 0; |
| 989 | #else |
992 | #else |
| 990 | i=index-132; |
993 | i=index-132; |
| 991 | if (i>index) |
994 | if (i>index) |
| 992 | i+=MAX_NR_TIMES; |
995 | i+=MAX_NR_TIMES; |
| 993 | #endif |
996 | #endif |
| 994 | if ((buf[i] < IR_NEXA2_START1 - IR_NEXA2_START1/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_START1 + IR_NEXA2_START1/IR_NEXA2_TOL_DIV)) { //check start bit |
997 | if ((buf[i] < IR_NEXA2_START1 - IR_NEXA2_START1/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_START1 + IR_NEXA2_START1/IR_NEXA2_TOL_DIV)) { //check start bit |
| 995 | return IR_NOT_CORRECT_DATA; |
998 | return IR_NOT_CORRECT_DATA; |
| 996 | } |
999 | } |
| 997 | #if IR_RX_CONTINUOUS_MODE==0 |
1000 | #if IR_RX_CONTINUOUS_MODE==0 |
| 998 | i = 1; |
1001 | i = 1; |
| 999 | #else |
1002 | #else |
| 1000 | i=index-131; |
1003 | i=index-131; |
| 1001 | if (i>index) |
1004 | if (i>index) |
| 1002 | i+=MAX_NR_TIMES; |
1005 | i+=MAX_NR_TIMES; |
| Line 1004... | Line 1007... | ||
| 1004 | if ((buf[i] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_HIGH + IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV)) { //check start bit |
1007 | if ((buf[i] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_HIGH + IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV)) { //check start bit |
| 1005 | return IR_NOT_CORRECT_DATA; |
1008 | return IR_NOT_CORRECT_DATA; |
| 1006 | } |
1009 | } |
| 1007 | #if IR_RX_CONTINUOUS_MODE==0 |
1010 | #if IR_RX_CONTINUOUS_MODE==0 |
| 1008 | i = 2; |
1011 | i = 2; |
| 1009 | #else |
1012 | #else |
| 1010 | i=index-130; |
1013 | i=index-130; |
| 1011 | if (i>index) |
1014 | if (i>index) |
| 1012 | i+=MAX_NR_TIMES; |
1015 | i+=MAX_NR_TIMES; |
| 1013 | #endif |
1016 | #endif |
| 1014 | if ((buf[i] < IR_NEXA2_START2 - IR_NEXA2_START2/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_START2 + IR_NEXA2_START2/IR_NEXA2_TOL_DIV)) { //check start bit |
1017 | if ((buf[i] < IR_NEXA2_START2 - IR_NEXA2_START2/IR_NEXA2_TOL_DIV) || (buf[i] > IR_NEXA2_START2 + IR_NEXA2_START2/IR_NEXA2_TOL_DIV)) { //check start bit |
| Line 1034... | Line 1037... | ||
| 1034 | rawbitsTemp |= (1UL)<<(bitCounter++); |
1037 | rawbitsTemp |= (1UL)<<(bitCounter++); |
| 1035 | } else if ((buf[i2] > IR_NEXA2_LOW_ZERO - IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV) && (buf[i2] < IR_NEXA2_LOW_ZERO + IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV)) { |
1038 | } else if ((buf[i2] > IR_NEXA2_LOW_ZERO - IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV) && (buf[i2] < IR_NEXA2_LOW_ZERO + IR_NEXA2_LOW_ZERO/IR_NEXA2_TOL_DIV)) { |
| 1036 | /* do nothing, a zero is already in rawbits */ |
1039 | /* do nothing, a zero is already in rawbits */ |
| 1037 | bitCounter++; |
1040 | bitCounter++; |
| 1038 | } else { |
1041 | } else { |
| 1039 | return IR_NOT_CORRECT_DATA; |
1042 | return IR_NOT_CORRECT_DATA; |
| 1040 | } |
1043 | } |
| 1041 | i+=2; // skip every other bit, implement check here in the future |
1044 | i+=2; // skip every other bit, implement check here in the future |
| 1042 | } else { /* if odd, no data */ |
1045 | } else { /* if odd, no data */ |
| 1043 | if ((buf[i2] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) |
1046 | if ((buf[i2] < IR_NEXA2_HIGH - IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV) || (buf[i2] > IR_NEXA2_HIGH + IR_NEXA2_HIGH/IR_NEXA2_TOL_DIV)) { |
| 1044 | return IR_NOT_CORRECT_DATA; |
1047 | return IR_NOT_CORRECT_DATA; |
| 1045 | } |
1048 | } |
| 1046 | } |
1049 | } |
| 1047 | } |
1050 | } |
| 1048 | 1051 | ||
| 1049 | proto->protocol=IR_PROTO_NEXA2; |
1052 | proto->protocol=IR_PROTO_NEXA2; |
| 1050 | proto->timeout=IR_NEXA2_TIMEOUT; |
1053 | proto->timeout=IR_NEXA2_TIMEOUT; |
| 1051 | proto->data=rawbitsTemp; |
1054 | proto->data=rawbitsTemp; |
| 1052 | 1055 | ||
| 1053 | return IR_OK; |
1056 | return IR_OK; |
| 1054 | } |
1057 | } |
| 1055 | - | ||
| 1056 | #endif |
1058 | #endif |
| 1057 | 1059 | ||
| 1058 | /** |
1060 | /** |
| 1059 | * Expand data from Nexa2 protocol |
1061 | * Expand data from Nexa2 protocol |
| 1060 | * |
1062 | * |
| Line 1221... | Line 1223... | ||
| 1221 | proto->timeout = IR_NEXA1_START/1000; |
1223 | proto->timeout = IR_NEXA1_START/1000; |
| 1222 | proto->repeats = IR_NEXA1_REPS; |
1224 | proto->repeats = IR_NEXA1_REPS; |
| 1223 | return IR_OK; |
1225 | return IR_OK; |
| 1224 | } |
1226 | } |
| 1225 | 1227 | ||
| - | 1228 | ||
| - | 1229 | #if (IR_PROTOCOLS_USE_VIKING) |
|
| - | 1230 | /** |
|
| - | 1231 | * Test data on Viking temperature sensor protocol |
|
| - | 1232 | * |
|
| - | 1233 | * |
|
| - | 1234 | * |
|
| - | 1235 | * @param buf |
|
| - | 1236 | * Pointer to buffer to where to data to parse is stored |
|
| - | 1237 | * @param len |
|
| - | 1238 | * Length of the data |
|
| - | 1239 | * @param proto |
|
| - | 1240 | * Pointer to protocol information |
|
| - | 1241 | * @return |
|
| - | 1242 | * IR_OK if data parsed successfully, one of several errormessages if not |
|
| - | 1243 | */ |
|
| - | 1244 | ||
| - | 1245 | int8_t parseViking(const uint16_t *buf, uint8_t len, uint8_t index, Ir_Protocol_Data_t *proto) |
|
| - | 1246 | { |
|
| - | 1247 | /* check if we have correct amount of data */ |
|
| - | 1248 | if (len < 94) { |
|
| - | 1249 | return IR_NOT_CORRECT_DATA; |
|
| - | 1250 | } |
|
| - | 1251 | uint8_t i, i2; |
|
| - | 1252 | uint32_t rawbitsTemp = 0; |
|
| - | 1253 | uint8_t bitCounter = 0; |
|
| - | 1254 | for (i = 0; i < 94; i++) { |
|
| - | 1255 | #if IR_RX_CONTINUOUS_MODE==0 |
|
| - | 1256 | i2 = i; |
|
| - | 1257 | #else |
|
| - | 1258 | i2=index-(94-i); |
|
| - | 1259 | if (i2>index) |
|
| - | 1260 | i2+=MAX_NR_TIMES; |
|
| - | 1261 | #endif |
|
| - | 1262 | if ((i&1) == 0) |
|
| - | 1263 | { /* if even, no data */ |
|
| - | 1264 | if ((buf[i2] < IR_VIKING_LOW - IR_VIKING_LOW/IR_VIKING_TOL_DIV) || (buf[i2] > IR_VIKING_LOW + IR_VIKING_LOW/IR_VIKING_TOL_DIV)) |
|
| - | 1265 | { |
|
| - | 1266 | return IR_NOT_CORRECT_DATA; |
|
| - | 1267 | } |
|
| - | 1268 | } |
|
| - | 1269 | else |
|
| - | 1270 | { /* if odd, data */ |
|
| - | 1271 | /* check length of transmit pulse */ |
|
| - | 1272 | if ((buf[i2] > IR_VIKING_HIGH_ONE - IR_VIKING_HIGH_ONE/IR_VIKING_TOL_DIV) && (buf[i2] < IR_VIKING_HIGH_ONE + IR_VIKING_HIGH_ONE/IR_VIKING_TOL_DIV)) |
|
| - | 1273 | { |
|
| - | 1274 | /* write a one */ |
|
| - | 1275 | rawbitsTemp |= (1UL)<<(bitCounter++); |
|
| - | 1276 | } |
|
| - | 1277 | else if ((buf[i2] > IR_VIKING_HIGH_ZERO - IR_VIKING_HIGH_ZERO/IR_VIKING_TOL_DIV) && (buf[i2] < IR_VIKING_HIGH_ZERO + IR_VIKING_HIGH_ZERO/IR_VIKING_TOL_DIV)) |
|
| - | 1278 | { |
|
| - | 1279 | /* do nothing, a zero is already in rawbits */ |
|
| - | 1280 | bitCounter++; |
|
| - | 1281 | } |
|
| - | 1282 | else |
|
| - | 1283 | { |
|
| - | 1284 | return IR_NOT_CORRECT_DATA; |
|
| - | 1285 | } |
|
| - | 1286 | } |
|
| - | 1287 | } |
|
| - | 1288 | ||
| - | 1289 | proto->protocol=IR_PROTO_VIKING; |
|
| - | 1290 | proto->timeout=0; |
|
| - | 1291 | proto->data=rawbitsTemp; |
|
| - | 1292 | ||
| - | 1293 | return IR_OK; |
|
| - | 1294 | } |
|
| - | 1295 | #endif |
|