From 0de2d18bdbb18cf6068584f33d1c76fea3dac4df Mon Sep 17 00:00:00 2001 From: sstefanov Date: Fri, 23 May 2014 12:20:39 +0300 Subject: [PATCH] Added Samsung protocol --- IRremote.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ IRremote.h | 3 ++ IRremoteInt.h | 73 ++++++++++++++++++++-------------------------- 3 files changed, 116 insertions(+), 41 deletions(-) diff --git a/IRremote.cpp b/IRremote.cpp index 21a5acb..5f394cc 100644 --- a/IRremote.cpp +++ b/IRremote.cpp @@ -65,6 +65,11 @@ int MATCH_SPACE(int measured_ticks, int desired_us) { Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC); return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS); } +#else +int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);} +int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));} +int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));} +// Debugging versions are in IRremote.cpp #endif void IRsend::sendNEC(unsigned long data, int nbits) @@ -221,6 +226,27 @@ void IRsend::sendJVC(unsigned long data, int nbits, int repeat) mark(JVC_BIT_MARK); space(0); } + +void IRsend::sendSAMSUNG(unsigned long data, int nbits) +{ + enableIROut(38); + mark(SAMSUNG_HDR_MARK); + space(SAMSUNG_HDR_SPACE); + for (int i = 0; i < nbits; i++) { + if (data & TOPBIT) { + mark(SAMSUNG_BIT_MARK); + space(SAMSUNG_ONE_SPACE); + } + else { + mark(SAMSUNG_BIT_MARK); + space(SAMSUNG_ZERO_SPACE); + } + data <<= 1; + } + mark(SAMSUNG_BIT_MARK); + space(0); +} + void IRsend::mark(int time) { // Sends an IR mark for the specified number of microseconds. // The mark output is modulated at the PWM frequency. @@ -439,6 +465,12 @@ int IRrecv::decode(decode_results *results) { if (decodeJVC(results)) { return DECODED; } +#ifdef DEBUG + Serial.println("Attempting SAMSUNG decode"); +#endif + if (decodeSAMSUNG(results)) { + return DECODED; + } // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. // If you add any decodes, add them before this. @@ -896,6 +928,55 @@ long IRrecv::decodeJVC(decode_results *results) { return DECODED; } +// SAMSUNGs have a repeat only 4 items long +long IRrecv::decodeSAMSUNG(decode_results *results) { + long data = 0; + int offset = 1; // Skip first space + // Initial mark + if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_HDR_MARK)) { + return ERR; + } + offset++; + // Check for repeat + if (irparams.rawlen == 4 && + MATCH_SPACE(results->rawbuf[offset], SAMSUNG_RPT_SPACE) && + MATCH_MARK(results->rawbuf[offset+1], SAMSUNG_BIT_MARK)) { + results->bits = 0; + results->value = REPEAT; + results->decode_type = SAMSUNG; + return DECODED; + } + if (irparams.rawlen < 2 * SAMSUNG_BITS + 4) { + return ERR; + } + // Initial space + if (!MATCH_SPACE(results->rawbuf[offset], SAMSUNG_HDR_SPACE)) { + return ERR; + } + offset++; + for (int i = 0; i < SAMSUNG_BITS; i++) { + if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_BIT_MARK)) { + return ERR; + } + offset++; + if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ONE_SPACE)) { + data = (data << 1) | 1; + } + else if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ZERO_SPACE)) { + data <<= 1; + } + else { + return ERR; + } + offset++; + } + // Success + results->bits = SAMSUNG_BITS; + results->value = data; + results->decode_type = SAMSUNG; + return DECODED; +} + /* ----------------------------------------------------------------------- * hashdecode - decode an arbitrary IR code. * Instead of decoding using a standard encoding scheme diff --git a/IRremote.h b/IRremote.h index 0e5fdf2..b626711 100644 --- a/IRremote.h +++ b/IRremote.h @@ -45,6 +45,7 @@ public: #define JVC 8 #define SANYO 9 #define MITSUBISHI 10 +#define SAMSUNG 11 #define UNKNOWN -1 // Decoded value for NEC when a repeat code is received @@ -70,6 +71,7 @@ private: long decodeRC6(decode_results *results); long decodePanasonic(decode_results *results); long decodeJVC(decode_results *results); + long decodeSAMSUNG(decode_results *results); long decodeHash(decode_results *results); int compare(unsigned int oldval, unsigned int newval); @@ -100,6 +102,7 @@ public: void sendPanasonic(unsigned int address, unsigned long data); void sendJVC(unsigned long data, int nbits, int repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does. // private: + void sendSAMSUNG(unsigned long data, int nbits); void enableIROut(int khz); VIRTUAL void mark(int usec); VIRTUAL void space(int usec); diff --git a/IRremoteInt.h b/IRremoteInt.h index 3ff620b..d4cc63f 100644 --- a/IRremoteInt.h +++ b/IRremoteInt.h @@ -61,9 +61,6 @@ #elif defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__) #define IR_USE_TIMER1 // tx = pin 9 -#elif defined( __AVR_ATtinyX4__ ) - #define IR_USE_TIMER1 // tx = pin 6 - // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc #else //#define IR_USE_TIMER1 // tx = pin 9 @@ -93,24 +90,24 @@ // Pulse parms are *50-100 for the Mark and *50+100 for the space // First MARK is the one after the long gap // pulse parameters in usec -#define NEC_HDR_MARK 9000 -#define NEC_HDR_SPACE 4500 -#define NEC_BIT_MARK 560 -#define NEC_ONE_SPACE 1600 -#define NEC_ZERO_SPACE 560 -#define NEC_RPT_SPACE 2250 +#define NEC_HDR_MARK 9000 +#define NEC_HDR_SPACE 4500 +#define NEC_BIT_MARK 560 +#define NEC_ONE_SPACE 1600 +#define NEC_ZERO_SPACE 560 +#define NEC_RPT_SPACE 2250 -#define SONY_HDR_MARK 2400 -#define SONY_HDR_SPACE 600 -#define SONY_ONE_MARK 1200 -#define SONY_ZERO_MARK 600 +#define SONY_HDR_MARK 2400 +#define SONY_HDR_SPACE 600 +#define SONY_ONE_MARK 1200 +#define SONY_ZERO_MARK 600 #define SONY_RPT_LENGTH 45000 #define SONY_DOUBLE_SPACE_USECS 500 // usually ssee 713 - not using ticks as get number wrapround // SA 8650B -#define SANYO_HDR_MARK 3500 // seen range 3500 -#define SANYO_HDR_SPACE 950 // seen 950 -#define SANYO_ONE_MARK 2400 // seen 2400 +#define SANYO_HDR_MARK 3500 // seen range 3500 +#define SANYO_HDR_SPACE 950 // seen 950 +#define SANYO_ONE_MARK 2400 // seen 2400 #define SANYO_ZERO_MARK 700 // seen 700 #define SANYO_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround #define SANYO_RPT_LENGTH 45000 @@ -118,21 +115,21 @@ // Mitsubishi RM 75501 // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7 -// #define MITSUBISHI_HDR_MARK 250 // seen range 3500 -#define MITSUBISHI_HDR_SPACE 350 // 7*50+100 -#define MITSUBISHI_ONE_MARK 1950 // 41*50-100 +// #define MITSUBISHI_HDR_MARK 250 // seen range 3500 +#define MITSUBISHI_HDR_SPACE 350 // 7*50+100 +#define MITSUBISHI_ONE_MARK 1950 // 41*50-100 #define MITSUBISHI_ZERO_MARK 750 // 17*50-100 // #define MITSUBISHI_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround // #define MITSUBISHI_RPT_LENGTH 45000 -#define RC5_T1 889 -#define RC5_RPT_LENGTH 46000 +#define RC5_T1 889 +#define RC5_RPT_LENGTH 46000 -#define RC6_HDR_MARK 2666 -#define RC6_HDR_SPACE 889 -#define RC6_T1 444 -#define RC6_RPT_LENGTH 46000 +#define RC6_HDR_MARK 2666 +#define RC6_HDR_SPACE 889 +#define RC6_T1 444 +#define RC6_RPT_LENGTH 46000 #define SHARP_BIT_MARK 245 #define SHARP_ONE_SPACE 1805 @@ -162,6 +159,14 @@ #define JVC_ZERO_SPACE 550 #define JVC_RPT_LENGTH 60000 +#define SAMSUNG_HDR_MARK 5000 +#define SAMSUNG_HDR_SPACE 5000 +#define SAMSUNG_BIT_MARK 560 +#define SAMSUNG_ONE_SPACE 1600 +#define SAMSUNG_ZERO_SPACE 560 +#define SAMSUNG_RPT_SPACE 2250 + + #define SHARP_BITS 15 #define DISH_BITS 16 @@ -175,13 +180,6 @@ #define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK)) #define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1)) -#ifndef DEBUG -int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);} -int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));} -int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));} -// Debugging versions are in IRremote.cpp -#endif - // receiver states #define STATE_IDLE 2 #define STATE_MARK 3 @@ -216,6 +214,7 @@ extern volatile irparams_t irparams; #define MIN_RC6_SAMPLES 1 #define PANASONIC_BITS 48 #define JVC_BITS 16 +#define SAMSUNG_BITS 32 @@ -274,13 +273,7 @@ extern volatile irparams_t irparams; #define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A)) #define TIMER_DISABLE_INTR (TIMSK1 = 0) #endif - -#if defined(__AVR_ATtinyX4__) - #define TIMER_INTR_NAME TIM1_COMPA_vect -#else - #define TIMER_INTR_NAME TIMER1_COMPA_vect -#endif - +#define TIMER_INTR_NAME TIMER1_COMPA_vect #define TIMER_CONFIG_KHZ(val) ({ \ const uint16_t pwmval = SYSCLOCK / 2000 / (val); \ TCCR1A = _BV(WGM11); \ @@ -300,8 +293,6 @@ extern volatile irparams_t irparams; #define TIMER_PWM_PIN 11 /* Arduino Mega */ #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) #define TIMER_PWM_PIN 13 /* Sanguino */ -#elif defined(__AVR_ATtinyX4__) -#define TIMER_PWM_PIN 6 /* ATTiny84 */ #else #define TIMER_PWM_PIN 9 /* Arduino Duemilanove, Diecimila, LilyPad, etc */ #endif