From d04aa35dc01398397138afb45f4b862601e0ce4d Mon Sep 17 00:00:00 2001 From: crankyoldgit Date: Tue, 29 Jun 2021 21:37:21 +1000 Subject: [PATCH] Experimental basic support for Tornado/Sanyo 88 bit A/C protocol * Basic support added via `sendSanyoAc88()` & `decodeSanyoAc88()` * Unit test coverage for the additions/changes. Note: Bit ordering has NOT been determined. Data values may change in future. For #1503 --- src/IRrecv.cpp | 4 ++ src/IRrecv.h | 6 ++ src/IRremoteESP8266.h | 15 ++++- src/IRsend.cpp | 9 +++ src/IRsend.h | 5 ++ src/IRtext.cpp | 1 + src/IRutils.cpp | 1 + src/ir_Sanyo.cpp | 81 ++++++++++++++++++++++++- src/ir_Sanyo.h | 3 +- src/locale/defaults.h | 3 + test/ir_Sanyo_test.cpp | 132 ++++++++++++++++++++++++++++++++++++++++- 11 files changed, 255 insertions(+), 5 deletions(-) diff --git a/src/IRrecv.cpp b/src/IRrecv.cpp index 38e9e5ec0..50351b910 100644 --- a/src/IRrecv.cpp +++ b/src/IRrecv.cpp @@ -1024,6 +1024,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save, DPRINTLN("Attempting Kelon decode"); if (decodeKelon(results, offset)) return true; #endif // DECODE_KELON +#if DECODE_SANYO_AC88 + DPRINTLN("Attempting SanyoAc88 decode"); + if (decodeSanyoAc88(results, offset)) return true; +#endif // DECODE_SANYO_AC88 // Typically new protocols are added above this line. } #if DECODE_HASH diff --git a/src/IRrecv.h b/src/IRrecv.h index 3accddc1b..84d8681bb 100644 --- a/src/IRrecv.h +++ b/src/IRrecv.h @@ -308,6 +308,12 @@ class IRrecv { const uint16_t nbits = kSanyoAcBits, const bool strict = true); #endif // DECODE_SANYO_AC +#if DECODE_SANYO_AC88 + bool decodeSanyoAc88(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kSanyoAc88Bits, + const bool strict = true); +#endif // DECODE_SANYO_AC88 #if DECODE_MITSUBISHI bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kMitsubishiBits, diff --git a/src/IRremoteESP8266.h b/src/IRremoteESP8266.h index 691855b89..40e9017bc 100644 --- a/src/IRremoteESP8266.h +++ b/src/IRremoteESP8266.h @@ -209,6 +209,13 @@ #define SEND_SANYO_AC _IR_ENABLE_DEFAULT_ #endif // SEND_SANYO_AC +#ifndef DECODE_SANYO_AC88 +#define DECODE_SANYO_AC88 _IR_ENABLE_DEFAULT_ +#endif // DECODE_SANYO_AC88 +#ifndef SEND_SANYO_AC88 +#define SEND_SANYO_AC88 _IR_ENABLE_DEFAULT_ +#endif // SEND_SANYO_AC88 + #ifndef DECODE_MITSUBISHI #define DECODE_MITSUBISHI _IR_ENABLE_DEFAULT_ #endif // DECODE_MITSUBISHI @@ -782,7 +789,7 @@ DECODE_MITSUBISHI112 || DECODE_HITACHI_AC424 || DECODE_HITACHI_AC3 || \ DECODE_HITACHI_AC344 || DECODE_CORONA_AC || DECODE_SANYO_AC || \ DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \ - DECODE_TEKNOPOINT || DECODE_KELON || \ + DECODE_TEKNOPOINT || DECODE_KELON || DECODE_SANYO_AC88 || \ false) // Add any DECODE to the above if it uses result->state (see kStateSizeMax) // you might also want to add the protocol to hasACState function @@ -926,8 +933,9 @@ enum decode_type_t { HAIER_AC176, TEKNOPOINT, KELON, + SANYO_AC88, // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = KELON, + kLastDecodeType = SANYO_AC88, }; // Message lengths & required repeat values @@ -1113,6 +1121,9 @@ const uint16_t kSamsungAcExtendedBits = kSamsungAcExtendedStateLength * 8; const uint16_t kSamsungAcDefaultRepeat = kNoRepeat; const uint16_t kSanyoAcStateLength = 9; const uint16_t kSanyoAcBits = kSanyoAcStateLength * 8; +const uint16_t kSanyoAc88StateLength = 11; +const uint16_t kSanyoAc88Bits = kSanyoAc88StateLength * 8; +const uint16_t kSanyoAc88MinRepeat = 2; const uint16_t kSanyoSA8650BBits = 12; const uint16_t kSanyoLC7461AddressBits = 13; const uint16_t kSanyoLC7461CommandBits = 8; diff --git a/src/IRsend.cpp b/src/IRsend.cpp index f552000aa..5f675e280 100644 --- a/src/IRsend.cpp +++ b/src/IRsend.cpp @@ -580,6 +580,8 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) { return kDishMinRepeat; case EPSON: return kEpsonMinRepeat; + case SANYO_AC88: + return kSanyoAc88MinRepeat; case SONY: return kSonyMinRepeat; case SONY_38K: @@ -739,6 +741,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { return kSamsungAcBits; case SANYO_AC: return kSanyoAcBits; + case SANYO_AC88: + return kSanyoAc88Bits; case SHARP_AC: return kSharpAcBits; case TCL112AC: @@ -1246,6 +1250,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state, sendSanyoAc(state, nbytes); break; #endif // SEND_SANYO_AC +#if SEND_SANYO_AC88 + case SANYO_AC88: + sendSanyoAc88(state, nbytes); + break; +#endif // SEND_SANYO_AC88 #if SEND_SHARP_AC case SHARP_AC: sendSharpAc(state, nbytes); diff --git a/src/IRsend.h b/src/IRsend.h index 31a78c5b9..087283fab 100644 --- a/src/IRsend.h +++ b/src/IRsend.h @@ -318,6 +318,11 @@ class IRsend { const uint16_t nbytes = kSanyoAcStateLength, const uint16_t repeat = kNoRepeat); #endif // SEND_SANYO_AC +#if SEND_SANYO_AC88 + void sendSanyoAc88(const uint8_t *data, + const uint16_t nbytes = kSanyoAc88StateLength, + const uint16_t repeat = kSanyoAc88MinRepeat); +#endif // SEND_SANYO_AC88 #if SEND_DISH // sendDISH() should typically be called with repeat=3 as DISH devices // expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes) diff --git a/src/IRtext.cpp b/src/IRtext.cpp index 91233ad80..7e18a8661 100644 --- a/src/IRtext.cpp +++ b/src/IRtext.cpp @@ -288,5 +288,6 @@ const PROGMEM char *kAllProtocolNamesStr = D_STR_HAIER_AC176 "\x0" D_STR_TEKNOPOINT "\x0" D_STR_KELON "\x0" + D_STR_SANYO_AC88 "\x0" ///< New protocol strings should be added just above this line. "\x0"; ///< This string requires double null termination. diff --git a/src/IRutils.cpp b/src/IRutils.cpp index 56689ef2e..d9f0d3e02 100644 --- a/src/IRutils.cpp +++ b/src/IRutils.cpp @@ -177,6 +177,7 @@ bool hasACState(const decode_type_t protocol) { case PANASONIC_AC: case SAMSUNG_AC: case SANYO_AC: + case SANYO_AC88: case SHARP_AC: case TCL112AC: case TEKNOPOINT: diff --git a/src/ir_Sanyo.cpp b/src/ir_Sanyo.cpp index 637d346fb..39fce67a7 100644 --- a/src/ir_Sanyo.cpp +++ b/src/ir_Sanyo.cpp @@ -1,6 +1,6 @@ // Copyright 2009 Ken Shirriff // Copyright 2016 marcosamarinho -// Copyright 2017-2020 David Conran +// Copyright 2017-2021 David Conran /// @file /// @brief Support for Sanyo protocols. @@ -13,6 +13,7 @@ /// @see http://slydiman.narod.ru/scr/kb/sanyo.htm /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1211 /// @see https://docs.google.com/spreadsheets/d/1dYfLsnYvpjV-SgO8pdinpfuBIpSzm8Q1R5SabrLeskw/edit?usp=sharing +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503 #include "ir_Sanyo.h" #include @@ -67,6 +68,15 @@ const uint16_t kSanyoAcZeroSpace = 550; ///< uSeconds const uint32_t kSanyoAcGap = kDefaultMessageGap; ///< uSeconds (Guess only) const uint16_t kSanyoAcFreq = 38000; ///< Hz. (Guess only) +const uint16_t kSanyoAc88HdrMark = 5400; ///< uSeconds +const uint16_t kSanyoAc88HdrSpace = 2000; ///< uSeconds +const uint16_t kSanyoAc88BitMark = 500; ///< uSeconds +const uint16_t kSanyoAc88OneSpace = 1500; ///< uSeconds +const uint16_t kSanyoAc88ZeroSpace = 750; ///< uSeconds +const uint32_t kSanyoAc88Gap = 3675; ///< uSeconds +const uint16_t kSanyoAc88Freq = 38000; ///< Hz. (Guess only) +const uint8_t kSanyoAc88ExtraTolerance = 5; /// (%) Extra tolerance to use. + #if SEND_SANYO /// Construct a Sanyo LC7461 message. /// @param[in] address The 13 bit value of the address(Custom) portion of the @@ -656,3 +666,72 @@ String IRSanyoAc::toString(void) const { kOffTimerStr); return result; } + +#if SEND_SANYO_AC88 +/// Send a SanyoAc88 formatted message. +/// Status: ALPHA / Completely untested. +/// @param[in] data An array of bytes containing the IR command. +/// @warning data's bit order may change. It is not yet confirmed. +/// @param[in] nbytes Nr. of bytes of data in the array. +/// @param[in] repeat Nr. of times the message is to be repeated. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503 +void IRsend::sendSanyoAc88(const uint8_t data[], const uint16_t nbytes, + const uint16_t repeat) { + // (Header + Data + Footer) per repeat + sendGeneric(kSanyoAc88HdrMark, kSanyoAc88HdrSpace, + kSanyoAc88BitMark, kSanyoAc88OneSpace, + kSanyoAc88BitMark, kSanyoAc88ZeroSpace, + kSanyoAc88BitMark, kSanyoAc88Gap, + data, nbytes, kSanyoAc88Freq, false, repeat, kDutyDefault); + space(kDefaultMessageGap); // Make a guess at a post message gap. +} +#endif // SEND_SANYO_AC88 + +#if DECODE_SANYO_AC88 +/// Decode the supplied SanyoAc message. +/// Status: ALPHA / Untested. +/// @param[in,out] results Ptr to the data to decode & where to store the decode +/// @warning data's bit order may change. It is not yet confirmed. +/// @param[in] offset The starting index to use when attempting to decode the +/// raw data. Typically/Defaults to kStartOffset. +/// @param[in] nbits The number of data bits to expect. +/// @param[in] strict Flag indicating if we should perform strict matching. +/// @return A boolean. True if it can decode it, false if it can't. +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503 +bool IRrecv::decodeSanyoAc88(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (strict && nbits != kSanyoAc88Bits) + return false; + + uint16_t used = 0; + // Compliance + const uint16_t expected_repeats = strict ? kSanyoAc88MinRepeat : 0; + + // Handle the expected nr of repeats. + for (uint16_t r = 0; r <= expected_repeats; r++) { + // Header + Data + Footer + used = matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, nbits, + kSanyoAc88HdrMark, kSanyoAc88HdrSpace, + kSanyoAc88BitMark, kSanyoAc88OneSpace, + kSanyoAc88BitMark, kSanyoAc88ZeroSpace, + kSanyoAc88BitMark, + // Expect an inter-message gap, or just the end of msg? + (r < expected_repeats) ? kSanyoAc88Gap + : kDefaultMessageGap, + r == expected_repeats, + _tolerance + kSanyoAc88ExtraTolerance, + kMarkExcess, false); + if (!used) return false; // No match! + offset += used; + } + + // Success + results->decode_type = decode_type_t::SANYO_AC88; + results->bits = nbits; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_SANYO_AC88 diff --git a/src/ir_Sanyo.h b/src/ir_Sanyo.h index d02b06c21..be699cc56 100644 --- a/src/ir_Sanyo.h +++ b/src/ir_Sanyo.h @@ -1,4 +1,4 @@ -// Copyright 2020 David Conran +// Copyright 2020-2021 David Conran /// @file /// @brief Support for Sanyo protocols. @@ -11,6 +11,7 @@ /// @see http://slydiman.narod.ru/scr/kb/sanyo.htm /// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1211 /// @see https://docs.google.com/spreadsheets/d/1dYfLsnYvpjV-SgO8pdinpfuBIpSzm8Q1R5SabrLeskw/edit?usp=sharing +/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1503 // Supports: // Brand: Sanyo, Model: SA 8650B - disabled diff --git a/src/locale/defaults.h b/src/locale/defaults.h index 8c6096289..d94d89cbb 100644 --- a/src/locale/defaults.h +++ b/src/locale/defaults.h @@ -739,6 +739,9 @@ #ifndef D_STR_SANYO_AC #define D_STR_SANYO_AC "SANYO_AC" #endif // D_STR_SANYO_AC +#ifndef D_STR_SANYO_AC88 +#define D_STR_SANYO_AC88 "SANYO_AC88" +#endif // D_STR_SANYO_AC88 #ifndef D_STR_SANYO_LC7461 #define D_STR_SANYO_LC7461 "SANYO_LC7461" #endif // D_STR_SANYO_LC7461 diff --git a/test/ir_Sanyo_test.cpp b/test/ir_Sanyo_test.cpp index c494e87d8..38d7344ef 100644 --- a/test/ir_Sanyo_test.cpp +++ b/test/ir_Sanyo_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2020 David Conran +// Copyright 2017-2021 David Conran #include "ir_Sanyo.h" #include "IRac.h" @@ -277,6 +277,13 @@ TEST(TestUtils, Housekeeping) { ASSERT_TRUE(IRac::isProtocolSupported(decode_type_t::SANYO_AC)); ASSERT_EQ(kSanyoAcBits, IRsend::defaultBits(decode_type_t::SANYO_AC)); ASSERT_EQ(kNoRepeat, IRsend::minRepeats(decode_type_t::SANYO_AC)); + // Sanyo A/C 88 Bit. + ASSERT_EQ("SANYO_AC88", typeToString(decode_type_t::SANYO_AC88)); + ASSERT_EQ(decode_type_t::SANYO_AC88, strToDecodeType("SANYO_AC88")); + ASSERT_TRUE(hasACState(decode_type_t::SANYO_AC88)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::SANYO_AC88)); + ASSERT_EQ(kSanyoAc88Bits, IRsend::defaultBits(decode_type_t::SANYO_AC88)); + ASSERT_EQ(kSanyoAc88MinRepeat, IRsend::minRepeats(decode_type_t::SANYO_AC88)); } TEST(TestDecodeSanyoAc, DecodeRealExamples) { @@ -530,3 +537,126 @@ TEST(TestSanyoAcClass, Beep) { ac.setRaw(beep_on); EXPECT_TRUE(ac.getBeep()); } + +TEST(TestDecodeSanyoAc88, DecodeRealExamples) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + // Ref: "On" from https://github.com/crankyoldgit/IRremoteESP8266/issues/1503#issuecomment-868450739 + const uint16_t rawData[539] = {5374, 1972, 512, 762, 522, 1510, 498, 780, 578, + 1486, 462, 790, 462, 1550, 544, 708, 510, 1500, 544, 1470, 516, 762, 482, + 770, 516, 1496, 518, 1510, 498, 780, 468, 1544, 466, 786, 466, 786, 466, + 786, 466, 786, 486, 748, 526, 756, 506, 1520, 516, 764, 516, 1492, 518, + 762, 544, 708, 548, 704, 602, 1434, 556, 1456, 524, 726, 552, 700, 554, + 698, 648, 1438, 548, 684, 536, 1478, 568, 682, 568, 682, 578, 702, 568, + 684, 570, 712, 624, 724, 528, 1482, 528, 726, 528, 1482, 526, 724, 546, + 1524, 568, 682, 540, 710, 544, 734, 542, 1516, 492, 762, 488, 744, 546, + 1482, 492, 788, 544, 734, 494, 758, 492, 760, 490, 744, 548, 828, 494, + 760, 494, 758, 494, 758, 494, 786, 492, 760, 494, 758, 494, 742, 508, 746, + 508, 788, 492, 760, 494, 786, 494, 786, 494, 742, 508, 744, 508, 788, 570, + 760, 494, 784, 494, 788, 568, 786, 492, 744, 508, 772, 608, 768, 538, 714, + 490, 786, 628, 728, 494, 786, 494, 758, 494, 742, 508, 1390, 494, 3692, + 5394, 1960, 494, 784, 494, 1516, 494, 760, 494, 1516, 494, 760, 492, 1516, + 494, 760, 492, 1518, 524, 1486, 494, 790, 486, 764, 492, 1524, 538, 1472, + 540, 740, 538, 1546, 546, 728, 524, 726, 526, 728, 524, 728, 526, 728, + 524, 728, 524, 1486, 526, 726, 546, 1464, 550, 702, 550, 728, 552, 702, + 550, 1460, 550, 1460, 550, 702, 552, 728, 550, 702, 550, 1460, 550, 728, + 550, 1464, 548, 704, 546, 704, 548, 732, 546, 704, 548, 704, 548, 730, + 548, 1462, 548, 706, 518, 1492, 546, 706, 518, 1490, 546, 706, 520, 732, + 520, 732, 522, 1492, 518, 760, 518, 732, 546, 1468, 516, 736, 516, 732, + 520, 732, 520, 758, 520, 818, 478, 772, 480, 802, 454, 894, 520, 734, 518, + 734, 518, 760, 518, 734, 518, 734, 518, 718, 506, 746, 480, 818, 488, 790, + 490, 744, 508, 790, 490, 744, 510, 770, 508, 788, 490, 762, 544, 788, 490, + 788, 462, 818, 566, 788, 490, 744, 480, 770, 456, 794, 458, 894, 492, 762, + 492, 760, 490, 744, 508, 1390, 492, 3664, + 5398, 1960, 490, 746, 476, 1552, 492, 742, 508, 1504, 508, 746, 504, 1522, + 494, 786, 492, 1516, 494, 1516, 494, 760, 492, 786, 494, 1520, 490, 1520, + 458, 822, 458, 1554, 510, 788, 494, 784, 494, 760, 492, 742, 508, 770, + 512, 786, 492, 1516, 520, 760, 520, 1488, 520, 734, 520, 760, 518, 734, + 520, 1490, 520, 1494, 516, 734, 518, 732, 520, 762, 516, 762, 488, 1522, + 458, 1554, 506, 774, 506, 744, 508, 774, 508, 770, 510, 742, 506, 746, + 540, 1472, 506, 744, 508, 1522, 488, 764, 488, 1504, 538, 758, 520, 734, + 520, 760, 520, 1490, 518, 734, 520, 734, 520, 1490, 520, 760, 518, 760, + 538, 770, 488, 764, 516, 734, 518, 734, 518, 818, 476, 802, 476, 774, 478, + 904, 538, 734, 520, 762, 516, 818, 510, 748, 476, 772, 458, 794, 458, 792, + 516, 736, 516, 736, 516, 736, 516, 738, 514, 762, 516, 764, 514, 738, 516, + 738, 538, 766, 516, 738, 514, 738, 514, 766, 512, 794, 486, 768, 486, 794, + 486, 766, 512, 738, 488, 1398, 504}; // UNKNOWN ABF4C698 + + const uint8_t expectedState[kSanyoAc88StateLength] = { + 0xAA, 0x59, 0xA0, 0x18, 0x06, 0x2A, 0x12, 0x00, 0x00, 0x00, 0x80}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 539, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SANYO_AC88, irsend.capture.decode_type); + EXPECT_EQ(kSanyoAc88Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); +} + +TEST(TestDecodeSanyoAc88, SyntheticSelfDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + const uint8_t expectedState[kSanyoAc88StateLength] = { + 0xAA, 0x59, 0xA0, 0x18, 0x06, 0x2A, 0x12, 0x00, 0x00, 0x00, 0x80}; + irsend.begin(); + irsend.reset(); + irsend.sendSanyoAc88(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SANYO_AC88, irsend.capture.decode_type); + EXPECT_EQ(kSanyoAc88Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ( + "", + IRAcUtils::resultAcToString(&irsend.capture)); + EXPECT_EQ( + "f38000d50" + "m5400s2000" + "m500s750m500s1500m500s750m500s1500m500s750m500s1500m500s750m500s1500" + "m500s1500m500s750m500s750m500s1500m500s1500m500s750m500s1500m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s1500m500s750m500s1500" + "m500s750m500s750m500s750m500s1500m500s1500m500s750m500s750m500s750" + "m500s750m500s1500m500s1500m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s1500m500s750m500s1500m500s750m500s1500m500s750m500s750" + "m500s750m500s1500m500s750m500s750m500s1500m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s1500" + "m500s3675" + "m5400s2000" + "m500s750m500s1500m500s750m500s1500m500s750m500s1500m500s750m500s1500" + "m500s1500m500s750m500s750m500s1500m500s1500m500s750m500s1500m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s1500m500s750m500s1500" + "m500s750m500s750m500s750m500s1500m500s1500m500s750m500s750m500s750" + "m500s750m500s1500m500s1500m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s1500m500s750m500s1500m500s750m500s1500m500s750m500s750" + "m500s750m500s1500m500s750m500s750m500s1500m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s1500" + "m500s3675" + "m5400s2000" + "m500s750m500s1500m500s750m500s1500m500s750m500s1500m500s750m500s1500" + "m500s1500m500s750m500s750m500s1500m500s1500m500s750m500s1500m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s1500m500s750m500s1500" + "m500s750m500s750m500s750m500s1500m500s1500m500s750m500s750m500s750" + "m500s750m500s1500m500s1500m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s1500m500s750m500s1500m500s750m500s1500m500s750m500s750" + "m500s750m500s1500m500s750m500s750m500s1500m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s750" + "m500s750m500s750m500s750m500s750m500s750m500s750m500s750m500s1500" + "m500s103675", + irsend.outputStr()); +}