#include "IRremote.h" // Based off the Magiquest fork of Arduino-IRremote by mpflaga // https://github.com/mpflaga/Arduino-IRremote/ //============================================================================== // // // M A G I Q U E S T // // //============================================================================== // MagiQuest packet is both Wand ID and magnitude of swish and flick union magiquest_t { unsigned long long llword; struct { unsigned int magnitude; unsigned long wand_id; char padding; char scrap; // just to pad the struct out to 64 bits so we can union with llword } cmd; }; #define MAGIQUEST_BITS 50 // The number of bits in the command itself #define MAGIQUEST_PERIOD 1150 // Length of time a full MQ "bit" consumes (1100 - 1200 usec) /* * 0 = 25% mark & 75% space across 1 period * 1150 * 0.25 = 288 usec mark * 1150 - 288 = 862 usec space * 1 = 50% mark & 50% space across 1 period * 1150 * 0.5 = 575 usec mark * 1150 - 575 = 575 usec space */ #define MAGIQUEST_ONE_MARK 575 #define MAGIQUEST_ONE_SPACE 575 #define MAGIQUEST_ZERO_MARK 288 #define MAGIQUEST_ZERO_SPACE 862 #define MAGIQUEST_MASK (1ULL << (MAGIQUEST_BITS-1)) //+============================================================================= // #if SEND_MAGIQUEST void IRsend::sendMagiQuest(unsigned long wand_id, unsigned int magnitude) { magiquest_t data; data.llword = 0; data.cmd.wand_id = wand_id; data.cmd.magnitude = magnitude; // Set IR carrier frequency enableIROut(38); // Data for (unsigned long long mask = MAGIQUEST_MASK; mask > 0; mask >>= 1) { if (data.llword & mask) { DBG_PRINT("1"); mark(MAGIQUEST_ONE_MARK); space(MAGIQUEST_ONE_SPACE); } else { DBG_PRINT("0"); mark(MAGIQUEST_ZERO_MARK); space(MAGIQUEST_ZERO_SPACE); } } DBG_PRINTLN(""); // Footer mark(MAGIQUEST_ZERO_MARK); space(0); // Always end with the LED off } #endif //+============================================================================= // #if DECODE_MAGIQUEST bool IRrecv::decodeMagiQuest() { magiquest_t data; // Somewhere to build our code unsigned int offset = 1; // Skip the gap reading unsigned int mark_; unsigned int space_; unsigned int ratio_; #if DEBUG char bitstring[MAGIQUEST_BITS*2]; memset(bitstring, 0, sizeof(bitstring)); #endif // Check we have enough data if (results.rawlen < 2 * MAGIQUEST_BITS) { DBG_PRINT("Not enough bits to be a MagiQuest packet ("); DBG_PRINT(irparams.rawlen); DBG_PRINT(" < "); DBG_PRINT(MAGIQUEST_BITS*2); DBG_PRINTLN(")"); return false; } // Read the bits in data.llword = 0; while (offset + 1 < results.rawlen) { mark_ = results.rawbuf[offset++]; space_ = results.rawbuf[offset++]; ratio_ = space_ / mark_; DBG_PRINT("mark="); DBG_PRINT(mark_ * MICROS_PER_TICK); DBG_PRINT(" space="); DBG_PRINT(space_ * MICROS_PER_TICK); DBG_PRINT(" ratio="); DBG_PRINTLN(ratio_); if (MATCH_MARK(space_ + mark_, MAGIQUEST_PERIOD)) { if (ratio_ > 1) { // It's a 0 data.llword <<= 1; #if DEBUG bitstring[(offset/2)-1] = '0'; #endif } else { // It's a 1 data.llword = (data.llword << 1) | 1; #if DEBUG bitstring[(offset/2)-1] = '1'; #endif } } else { DBG_PRINTLN("MATCH_MARK failed"); return false; } } #if DEBUG DBG_PRINTLN(bitstring); #endif // Success results.decode_type = MAGIQUEST; results.bits = offset / 2; results.value = data.cmd.wand_id; results.magnitude = data.cmd.magnitude; DBG_PRINT("MQ: bits="); DBG_PRINT(results.bits); DBG_PRINT(" value="); DBG_PRINT(results.value); DBG_PRINT(" magnitude="); DBG_PRINTLN(results.magnitude); return true; } bool IRrecv::decodeMagiQuest(decode_results *aResults) { bool aReturnValue = decodeMagiQuest(); *aResults = results; return aReturnValue; } #endif