11// Copyright 2021 Davide Depau
2+ // Copyright 2022 David Conran
23
34// / @file
4- // / @brief Support for Kelan AC protocol .
5+ // / @brief Support for Kelon AC protocols .
56// / Both sending and decoding should be functional for models of series
67// / KELON ON/OFF 9000-12000.
78// / All features of the standard remote are implemented.
1213// / - Fahrenheit.
1314
1415#include < algorithm>
16+ #include < cassert>
1517
1618#include " ir_Kelon.h"
1719
@@ -39,8 +41,13 @@ const uint16_t kKelonZeroSpace = 600;
3941const uint32_t kKelonGap = 2 * kDefaultMessageGap ;
4042const uint16_t kKelonFreq = 38000 ;
4143
44+ const uint32_t kKelon168FooterSpace = 8000 ;
45+ const uint16_t kKelon168Section1Size = 6 ;
46+ const uint16_t kKelon168Section2Size = 8 ;
47+ const uint16_t kKelon168Section3Size = 7 ;
48+
4249#if SEND_KELON
43- // / Send a Kelon message.
50+ // / Send a Kelon 48-bit message.
4451// / Status: STABLE / Working.
4552// / @param[in] data The data to be transmitted.
4653// / @param[in] nbits Nr. of bits of data to be sent.
@@ -52,12 +59,12 @@ void IRsend::sendKelon(const uint64_t data, const uint16_t nbits,
5259 kKelonBitMark , kKelonZeroSpace ,
5360 kKelonBitMark , kKelonGap ,
5461 data, nbits, kKelonFreq , false , // LSB First.
55- repeat, 50 );
62+ repeat, kDutyDefault );
5663}
5764#endif // SEND_KELON
5865
5966#if DECODE_KELON
60- // / Decode the supplied Kelon message.
67+ // / Decode the supplied Kelon 48-bit message.
6168// / Status: STABLE / Working.
6269// / @param[in,out] results Ptr to the data to decode & where to store the result
6370// / @param[in] offset The starting index to use when attempting to decode the
@@ -440,3 +447,105 @@ String IRKelonAc::toString() const {
440447 result += addBoolToString (true , kSwingVToggleStr );
441448 return result;
442449}
450+
451+ #if SEND_KELON168
452+ // / Send a Kelon 168 bit / 21 byte message.
453+ // / Status: BETA / Probably works.
454+ // / @param[in] data The data to be transmitted.
455+ // / @param[in] nbytes Nr. of bytes of data to be sent.
456+ // / @param[in] repeat The number of times the command is to be repeated.
457+ void IRsend::sendKelon168 (const uint8_t data[], const uint16_t nbytes,
458+ const uint16_t repeat) {
459+ assert (kKelon168StateLength == kKelon168Section1Size + kKelon168Section2Size +
460+ kKelon168Section3Size );
461+ // Enough bytes to send a proper message?
462+ if (nbytes < kKelon168StateLength ) return ;
463+
464+ for (uint16_t r = 0 ; r <= repeat; r++) {
465+ // Section #1 (48 bits)
466+ sendGeneric (kKelonHdrMark , kKelonHdrSpace ,
467+ kKelonBitMark , kKelonOneSpace ,
468+ kKelonBitMark , kKelonZeroSpace ,
469+ kKelonBitMark , kKelon168FooterSpace ,
470+ data, kKelon168Section1Size , kKelonFreq , false , // LSB First.
471+ 0 , // No repeats here
472+ kDutyDefault );
473+ // Section #2 (64 bits)
474+ sendGeneric (0 , 0 ,
475+ kKelonBitMark , kKelonOneSpace ,
476+ kKelonBitMark , kKelonZeroSpace ,
477+ kKelonBitMark , kKelon168FooterSpace ,
478+ data + kKelon168Section1Size , kKelon168Section2Size ,
479+ kKelonFreq , false , // LSB First.
480+ 0 , // No repeats here
481+ kDutyDefault );
482+ // Section #3 (56 bits)
483+ sendGeneric (0 , 0 ,
484+ kKelonBitMark , kKelonOneSpace ,
485+ kKelonBitMark , kKelonZeroSpace ,
486+ kKelonBitMark , kKelonGap ,
487+ data + kKelon168Section1Size + kKelon168Section2Size ,
488+ nbytes - (kKelon168Section1Size + kKelon168Section2Size ),
489+ kKelonFreq , false , // LSB First.
490+ 0 , // No repeats here
491+ kDutyDefault );
492+ }
493+ }
494+ #endif // SEND_KELON168
495+
496+ #if DECODE_KELON168
497+ // / Decode the supplied Kelon 168 bit / 21 byte message.
498+ // / Status: BETA / Probably Working.
499+ // / @param[in,out] results Ptr to the data to decode & where to store the result
500+ // / @param[in] offset The starting index to use when attempting to decode the
501+ // / raw data. Typically/Defaults to kStartOffset.
502+ // / @param[in] nbits The number of data bits to expect.
503+ // / @param[in] strict Flag indicating if we should perform strict matching.
504+ // / @return True if it can decode it, false if it can't.
505+ bool IRrecv::decodeKelon168 (decode_results *results, uint16_t offset,
506+ const uint16_t nbits, const bool strict) {
507+ if (strict && nbits != kKelon168Bits ) return false ;
508+ if (results->rawlen <= 2 * nbits + kHeader + kFooter * 2 - 1 + offset)
509+ return false ; // Can't possibly be a valid Kelon 168 bit message.
510+
511+ uint16_t used = 0 ;
512+
513+ used = matchGeneric (results->rawbuf + offset, results->state ,
514+ results->rawlen - offset, kKelon168Section1Size * 8 ,
515+ kKelonHdrMark , kKelonHdrSpace ,
516+ kKelonBitMark , kKelonOneSpace ,
517+ kKelonBitMark , kKelonZeroSpace ,
518+ kKelonBitMark , kKelon168FooterSpace ,
519+ false , _tolerance, 0 , false );
520+ if (!used) return false ; // Failed to match.
521+ offset += used;
522+
523+ used = matchGeneric (results->rawbuf + offset,
524+ results->state + kKelon168Section1Size ,
525+ results->rawlen - offset, kKelon168Section2Size * 8 ,
526+ 0 , 0 ,
527+ kKelonBitMark , kKelonOneSpace ,
528+ kKelonBitMark , kKelonZeroSpace ,
529+ kKelonBitMark , kKelon168FooterSpace ,
530+ false , _tolerance, 0 , false );
531+ if (!used) return false ; // Failed to match.
532+ offset += used;
533+
534+ used = matchGeneric (results->rawbuf + offset,
535+ results->state + (kKelon168Section1Size +
536+ kKelon168Section2Size ),
537+ results->rawlen - offset,
538+ nbits - (kKelon168Section1Size +
539+ kKelon168Section2Size ) * 8 ,
540+ 0 , 0 ,
541+ kKelonBitMark , kKelonOneSpace ,
542+ kKelonBitMark , kKelonZeroSpace ,
543+ kKelonBitMark , kKelonGap ,
544+ true , _tolerance, 0 , false );
545+ if (!used) return false ; // Failed to match.
546+
547+ results->decode_type = decode_type_t ::KELON168;
548+ results->bits = nbits;
549+ return true ;
550+ }
551+ #endif // DECODE_KELON168
0 commit comments