You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
4.6 KiB
123 lines
4.6 KiB
/* IRLib_P08_Samsung36.h
|
|
* Part of IRLib Library for Arduino receiving, decoding, and sending
|
|
* infrared signals. See COPYRIGHT.txt and LICENSE.txt for more information.
|
|
*/
|
|
|
|
/*
|
|
* This 36 bit protocol is used by some Samsung devices such as Blu-ray players.
|
|
* It consists of a 16 bit address and 20 bits of data with strange timing in between.
|
|
*/
|
|
/* The IRP notation for this protocol is:
|
|
* {38k,500}<1,-1|1,-3>(9,-9,D:8,S:8,1,-9,E:4,F:8,-68u,~F:8,1,-118)+
|
|
* This means it uses 38k frequency. Base timing is multiples of 500.
|
|
* A "0" is mark(500) space(500). A "1" is mark (500) space(500*3)
|
|
* The header is mark(500*9) space(500*9).
|
|
* The header is followed by 16 bit address (8 device, 8 sub device)
|
|
* This is followed by a mark(500) space(500*9).
|
|
* This is followed by 12 more bits (4+8)
|
|
* This is followed by 68us of space. Actually this means that the space
|
|
* of the last bit of that segment is simply 68us longer than normal.
|
|
* This is followed by 8 more bits and a final stop bit.
|
|
*/
|
|
#ifndef IRLIB_PROTOCOL_08_H
|
|
#define IRLIB_PROTOCOL_08_H
|
|
#define IR_SEND_PROTOCOL_08 case 8: IRsendSamsung36::send(data,data2); break;
|
|
#define IR_DECODE_PROTOCOL_08 if(IRdecodeSamsung36::decode()) return true;
|
|
#ifdef IRLIB_HAVE_COMBO
|
|
#define PV_IR_DECODE_PROTOCOL_08 ,public virtual IRdecodeSamsung36
|
|
#define PV_IR_SEND_PROTOCOL_08 ,public virtual IRsendSamsung36
|
|
#else
|
|
#define PV_IR_DECODE_PROTOCOL_08 public virtual IRdecodeSamsung36
|
|
#define PV_IR_SEND_PROTOCOL_08 public virtual IRsendSamsung36
|
|
#endif
|
|
|
|
#ifdef IRLIBSENDBASE_H
|
|
class IRsendSamsung36: public virtual IRsendBase {
|
|
public:
|
|
void send(uint32_t data, uint32_t address) {
|
|
data <<= 32-20;
|
|
address <<= 32-16;
|
|
enableIROut(38);
|
|
mark(500*9); space(500*9); //Send header
|
|
putBits (address, 16); //Send address 16 bits
|
|
mark (500); space (500*9); //Send break
|
|
putBits (data, 12); //Send 12 bits
|
|
space(68); //Send tiny break
|
|
data <<= 12;
|
|
putBits (data, 8);mark(500); //Final eight bits and one stop bit
|
|
space(118*500); //Lead out is 118 times the base time 500
|
|
};
|
|
private:
|
|
/* Because not all of the data bits are contiguous in the stream,
|
|
* we created this little routine to be called multiple times to send a
|
|
* segment of the data.
|
|
*/
|
|
void putBits (uint32_t data, uint8_t nbits) {
|
|
for (uint8_t i = 0; i < nbits; i++) {
|
|
if (data & TOPBIT) {
|
|
mark(500); space(500*3);
|
|
} else {
|
|
mark(500); space(500);
|
|
};
|
|
data <<= 1;
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif //IRLIBSENDBASE_H
|
|
|
|
#ifdef IRLIBDECODEBASE_H
|
|
class IRdecodeSamsung36: public virtual IRdecodeBase {
|
|
public:
|
|
bool decode(void) {
|
|
IRLIB_ATTEMPT_MESSAGE(F("Samsung36"));
|
|
if (recvGlobal.decodeLength != 78) return RAW_COUNT_ERROR;
|
|
if (!MATCH(recvGlobal.decodeBuffer[1],500*9)) return HEADER_MARK_ERROR(500*9);
|
|
if (!MATCH(recvGlobal.decodeBuffer[2],500*9)) return HEADER_SPACE_ERROR(500*9);
|
|
offset=3; data=0;
|
|
//Get first 16 bits
|
|
if(!getBits(16*2+2))return false;
|
|
//Skip middle header
|
|
if (!MATCH(recvGlobal.decodeBuffer[offset],500)) return DATA_MARK_ERROR(500);
|
|
offset++;
|
|
if (!MATCH(recvGlobal.decodeBuffer[offset],500*9)) return DATA_SPACE_ERROR(4400);
|
|
//save first 16 bits in "address" and reset data
|
|
offset++; address=data; data=0;
|
|
//12 bits into this second segment, the space is extended by 68us.
|
|
// so we adjust the value to its normal length without the extra 68us.
|
|
recvGlobal.decodeBuffer[62]-=68;
|
|
//Now get the remaining 20 bits
|
|
if(!getBits(77))return false;
|
|
bits =36; //set bit length
|
|
value = data; //put remaining 20 bits in value
|
|
protocolNum= SAMSUNG36;
|
|
return true;
|
|
};
|
|
private:
|
|
/* Because not all of the data bits are contiguous in the stream
|
|
* we created this little routine to be called multiple times
|
|
* to decode a segment of the data. Parameter "last_offset" is when we
|
|
* stop decoding the segment.
|
|
*/
|
|
bool getBits(uint8_t last_offset) {
|
|
while (offset < last_offset) {
|
|
if (!MATCH(recvGlobal.decodeBuffer[offset],500)) return DATA_MARK_ERROR(500);
|
|
offset++;
|
|
if (MATCH(recvGlobal.decodeBuffer[offset],500*3))
|
|
data = (data << 1) | 1;
|
|
else if (MATCH(recvGlobal.decodeBuffer[offset],500))
|
|
data <<= 1;
|
|
else return DATA_SPACE_ERROR(500*3);
|
|
offset++;
|
|
};
|
|
return true;
|
|
};
|
|
uint8_t offset;
|
|
uint32_t data;
|
|
};
|
|
#endif //IRLIBDECODEBASE_H
|
|
|
|
#define IRLIB_HAVE_COMBO
|
|
|
|
#endif //IRLIB_PROTOCOL_08_H
|