IRremote
ir_Sony.hpp
Go to the documentation of this file.
1 /*
2  * ir_Sony.hpp
3  *
4  * Contains functions for receiving and sending SIRCS/Sony IR Protocol in "raw" and standard format with 5 bit address 7 bit command
5  *
6  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
7  *
8  ************************************************************************************
9  * MIT License
10  *
11  * Copyright (c) 2020-2026 Armin Joachimsmeyer
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is furnished
18  * to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in all
21  * copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
24  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
28  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  *
30  ************************************************************************************
31  */
32 #ifndef _IR_SONY_HPP
33 #define _IR_SONY_HPP
34 
35 #include "LocalDebugLevelStart.h"
36 
40 //==============================================================================
41 // SSSS OOO N N Y Y
42 // S O O NN N Y Y
43 // SSS O O N N N Y
44 // S O O N NN Y
45 // SSSS OOO N N Y
46 //==============================================================================
47 /*
48  * Protocol=Sony Address=0x4B9 Command=0x7 Raw-Data=0x25C87 20 bits LSB first
49  +2550,- 400
50  // 7 command bits
51  +1300,- 450 +1350,- 450 +1300,- 450 + 700,- 450
52  + 700,- 450 + 750,- 450 + 700,- 400
53  // (5,8,) 13 address bits and NO stop bit!
54  +1300,- 500
55  + 700,- 450 + 700,- 450 +1300,- 500 +1300,- 450
56  +1300,- 450 + 700,- 450 +1350,- 400 + 750,- 450
57  + 700,- 450 +1300,- 450 + 700,- 450 + 700
58  Sum: 31100
59  */
60 /*
61  * Sony is the only protocol using the pulse width encoding, which requires no stop bit
62  */
63 // see https://www.sbprojects.net/knowledge/ir/sirc.php
64 // https://www.mikrocontroller.net/articles/IRMP_-_english#SIRCS
65 // Frames are repeated every 45ms (measured from start to start) for as long as the key on the remote control is held down.
66 // This leads to a 12 ms gap for a Sony20 protocol!
67 // Here http://picprojects.org.uk/projects/sirc/ it is claimed, that many Sony remotes send each frame a minimum of 3 times. But 1 repeat (2 sends) has also been seen in real life.
68 // LSB first, start bit + 7 command + 5 to 13 address, no stop bit
69 // IRP: Sony12 {40k,600}<1,-1|2,-1>(4,-1,F:7,D:5,^45m)+ ==> 40 kHz, Unit is 600, LSB, One mark is 2 units, Start bit is 4 units, 7 bit Function, 5 bit Device, no Stop bit, every 45 milliseconds
70 // IRP: Sony15 {40k,600}<1,-1|2,-1>(4,-1,F:7,D:8,^45m)+ ==> 8 bit Device
71 // IRP: Sony20 {40k,600}<1,-1|2,-1>(4,-1,F:7,D:5,S:8,^45m)+ ==> 5 bit Device, 8 bit Subdevice
72 //
73 #define SONY_ADDRESS_BITS 5
74 #define SONY_COMMAND_BITS 7
75 #define SONY_EXTRA_BITS 8
76 #define SONY_BITS_MIN (SONY_COMMAND_BITS + SONY_ADDRESS_BITS) // 12 bits
77 #define SONY_BITS_15 (SONY_COMMAND_BITS + SONY_ADDRESS_BITS + 3) // 15 bits
78 #define SONY_BITS_MAX (SONY_COMMAND_BITS + SONY_ADDRESS_BITS + SONY_EXTRA_BITS) // 20 bits == SIRCS_20_PROTOCOL
79 #define SONY_UNIT 600 // 24 periods of 40kHz
80 
81 #define SONY_HEADER_MARK (4 * SONY_UNIT) // 2400
82 #define SONY_ONE_MARK (2 * SONY_UNIT) // 1200
83 #define SONY_ZERO_MARK SONY_UNIT
84 #define SONY_SPACE SONY_UNIT
85 
86 #define SONY_AVERAGE_DURATION_MIN 21000 // SONY_HEADER_MARK + SONY_SPACE + 12 * 2,5 * SONY_UNIT // 2.5 because we assume more zeros than ones
87 #define SONY_AVERAGE_DURATION_MAX 33000 // SONY_HEADER_MARK + SONY_SPACE + 20 * 2,5 * SONY_UNIT // 2.5 because we assume more zeros than ones
88 #define SONY_REPEAT_PERIOD 45000 // Commands are repeated every 45 ms (measured from start to start) for as long as the key on the remote control is held down.
89 #define SONY_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION_MIN) // 24 ms
90 
93 
94 /************************************
95  * Start of send and decode functions
96  ************************************/
97 
101 void IRsend::sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits) {
102  uint32_t tData = (uint32_t) aAddress << 7 | (aCommand & 0x7F);
103  // send 5, 8, 13 address bits LSB first
104  sendPulseDistanceWidth_P(&SonyProtocolConstants, tData, numberOfBits, aNumberOfRepeats);
105 }
106 
108 
109  if (!checkHeader_P(&SonyProtocolConstants)) {
110  return false;
111  }
112 
113  // Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42
114  if (decodedIRData.rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawlen != (2 * SONY_BITS_MAX) + 2
115  && decodedIRData.rawlen != (2 * SONY_BITS_15) + 2) {
116  DEBUG_PRINT(F("Sony: Data length="));
118  DEBUG_PRINTLN(F(" is not 12, 15 or 20"));
119  return false;
120  }
121 
122  decodePulseDistanceWidthData_P(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3);
123 
124  // Success
125 // decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
126  decodedIRData.command = decodedIRData.decodedRawData & 0x7F; // first 7 bits
127  decodedIRData.address = decodedIRData.decodedRawData >> 7; // next 5 or 8 or 13 bits
130 
131  //Check for repeat
133 
134  return true;
135 }
136 
137 /*********************************************************************************
138  * Old deprecated functions, kept for backward compatibility to old 2.0 tutorials
139  *********************************************************************************/
140 
141 /*
142  * Old version with MSB first data
143  */
144 #define SONY_DOUBLE_SPACE_USECS 500 // usually see 713 - not using ticks as get number wrap around
146  long data = 0;
147  uint8_t bits = 0;
148  unsigned int offset = 0; // Dont skip first space, check its size
149 
150  if (aResults->rawlen < (2 * SONY_BITS_MIN) + 2) {
151  return false;
152  }
153 
154  // Some Sony's deliver repeats fast after first
155  // unfortunately can't spot difference from of repeat from two fast clicks
156  if (aResults->rawbuf[0] < (SONY_DOUBLE_SPACE_USECS / MICROS_PER_TICK)) {
157  DEBUG_PRINTLN(F("IR Gap found"));
158 
159  aResults->bits = 0;
160  aResults->value = 0xFFFFFFFF;
163  return true;
164  }
165  offset++;
166 
167  // Check header "mark"
168  if (!matchMark(aResults->rawbuf[offset], SONY_HEADER_MARK)) {
169  return false;
170  }
171  offset++;
172 
173  // MSB first - Not compatible to standard, which says LSB first :-(
174  while (offset + 1 < aResults->rawlen) {
175 
176  // First check for the constant space length, we do not have a space at the end of raw data
177  // we are lucky, since the start space is equal the data space.
178  if (!matchSpace(aResults->rawbuf[offset], SONY_SPACE)) {
179  return false;
180  }
181  offset++;
182 
183  // bit value is determined by length of the mark
184  if (matchMark(aResults->rawbuf[offset], SONY_ONE_MARK)) {
185  data = (data << 1) | 1;
186  } else if (matchMark(aResults->rawbuf[offset], SONY_ZERO_MARK)) {
187  data = (data << 1) | 0;
188  } else {
189  return false;
190  }
191  offset++;
192  bits++;
193 
194  }
195 
196  aResults->bits = bits;
197  aResults->value = data;
198  aResults->decode_type = SONY;
200  return true;
201 }
202 
206 void IRsend::sendSonyMSB(unsigned long data, int nbits) {
207  // Set IR carrier frequency
209 
210  // Header
212  space(SONY_SPACE);
213 
214  // Old version with MSB first Data
216 }
217 void IRsend::sendSony(unsigned long data, int nbits) {
218  sendSonyMSB(data, nbits);
219 }
220 
222 #include "LocalDebugLevelEnd.h"
223 
224 #endif // _IR_SONY_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRremoteInt.h:164
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:133
decode_results
Results returned from old decoders !!!deprecated!!!
Definition: IRremoteInt.h:193
decode_results::rawbuf
uint16_t * rawbuf
Definition: IRremoteInt.h:204
PROTOCOL_IS_MSB_FIRST
#define PROTOCOL_IS_MSB_FIRST
Definition: IRProtocol.h:156
PROTOCOL_IS_PULSE_WIDTH
#define PROTOCOL_IS_PULSE_WIDTH
Definition: IRProtocol.h:153
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRremoteInt.h:173
DEBUG_PRINT
#define DEBUG_PRINT(...)
Definition: LocalDebugLevelStart.h:79
IRsend::aNumberOfRepeats
void int_fast8_t aNumberOfRepeats
Definition: IRremoteInt.h:528
IRrecv::decodePulseDistanceWidthData_P
void decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset=3)
Definition: IRReceive.hpp:1112
MICROS_IN_ONE_MILLI
#define MICROS_IN_ONE_MILLI
Definition: IRremote.hpp:217
IRrecv::checkHeader_P
bool checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM)
Definition: IRReceive.hpp:1228
IRsend::sendSony
void sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits=12)
Definition: ir_Sony.hpp:101
IRsend::mark
void mark(uint16_t aMarkMicros)
Sends an IR mark for the specified number of microseconds.
Definition: IRSend.hpp:1247
SONY
@ SONY
Definition: IRProtocol.h:101
SONY_HEADER_MARK
#define SONY_HEADER_MARK
Definition: ir_Sony.hpp:81
SONY_MAXIMUM_REPEAT_DISTANCE
#define SONY_MAXIMUM_REPEAT_DISTANCE
Definition: ir_Sony.hpp:89
SONY_DOUBLE_SPACE_USECS
#define SONY_DOUBLE_SPACE_USECS
Definition: ir_Sony.hpp:144
IRDATA_FLAGS_IS_REPEAT
#define IRDATA_FLAGS_IS_REPEAT
The gap between the preceding frame is as smaller than the maximum gap expected for a repeat....
Definition: IRProtocol.h:125
decode_results::bits
uint8_t bits
Definition: IRremoteInt.h:199
decode_results::decode_type
decode_type_t decode_type
Definition: IRremoteInt.h:196
IRrecv::checkForRepeatSpaceTicksAndSetFlag
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks)
Definition: IRReceive.hpp:1248
IRrecv::decodeSonyMSB
bool decodeSonyMSB(decode_results *aResults)
Definition: ir_Sony.hpp:145
SONY_BITS_MIN
#define SONY_BITS_MIN
Definition: ir_Sony.hpp:76
PROGMEM
struct PulseDistanceWidthProtocolConstants const SonyProtocolConstants PROGMEM
Definition: ir_Sony.hpp:91
IRrecv::decodeSony
bool decodeSony()
Definition: ir_Sony.hpp:107
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1375
LocalDebugLevelStart.h
decode_results::value
uint32_t value
Definition: IRremoteInt.h:198
PulseDistanceWidthProtocolConstants
Definition: IRProtocol.h:139
IRsend::sendPulseDistanceWidth_P
void sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats)
Definition: IRSend.hpp:1158
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:401
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRremoteInt.h:174
PROTOCOL_IS_LSB_FIRST
#define PROTOCOL_IS_LSB_FIRST
Definition: IRProtocol.h:157
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRremoteInt.h:165
IRData::decodedRawData
IRDecodedRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send<protocol>Raw functions.
Definition: IRremoteInt.h:167
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1327
DEBUG_PRINTLN
#define DEBUG_PRINTLN(...)
Definition: LocalDebugLevelStart.h:80
SONY_BITS_MAX
#define SONY_BITS_MAX
Definition: ir_Sony.hpp:78
IRsend::sendSonyMSB
void sendSonyMSB(unsigned long data, int nbits)
Old version with MSB first data.
Definition: ir_Sony.hpp:206
SONY_KHZ
#define SONY_KHZ
Definition: IRProtocol.h:166
IRsend::space
static void space(uint16_t aSpaceMicros)
Sends an IR space for the specified number of microseconds.
Definition: IRSend.hpp:1458
SONY_ZERO_MARK
#define SONY_ZERO_MARK
Definition: ir_Sony.hpp:83
IRData::rawlen
IRRawlenType rawlen
Counter of entries in rawbuf of last received frame.
Definition: IRremoteInt.h:182
SONY_REPEAT_PERIOD
#define SONY_REPEAT_PERIOD
Definition: ir_Sony.hpp:88
IRsend::sendPulseDistanceWidthData
void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits)
Sends PulseDistance from data contained in parameter using ProtocolConstants structure for timing etc...
Definition: IRSend.hpp:662
SONY_ONE_MARK
#define SONY_ONE_MARK
Definition: ir_Sony.hpp:82
decode_results::rawlen
uint_fast8_t rawlen
Definition: IRremoteInt.h:205
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRremoteInt.h:163
SONY_BITS_15
#define SONY_BITS_15
Definition: ir_Sony.hpp:77
SONY_SPACE
#define SONY_SPACE
Definition: ir_Sony.hpp:84
IRsend::aCommand
void aCommand
Definition: IRremoteInt.h:617
IRsend::enableIROut
void enableIROut(uint_fast8_t aFrequencyKHz)
Enables IR output.
Definition: IRSend.hpp:1498
LocalDebugLevelEnd.h