-
Notifications
You must be signed in to change notification settings - Fork 837
/
Copy pathir_Pioneer.cpp
143 lines (134 loc) · 6 KB
/
ir_Pioneer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2009 Ken Shirriff
// Copyright 2017, 2018 David Conran
// Copyright 2018 Kamil Palczewski
// Copyright 2019 s-hadinger
/// @file
/// @brief Pioneer remote emulation
/// @see http://www.adrian-kingston.com/IRFormatPioneer.htm
/// @see https://github.com/crankyoldgit/IRremoteESP8266/pull/547
/// @see https://www.pioneerelectronics.com/PUSA/Support/Home-Entertainment-Custom-Install/IR+Codes/A+V+Receivers
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1220
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1749#issuecomment-1028122645
// Supports:
// Brand: Pioneer, Model: AV Receivers
// Brand: Pioneer, Model: VSX-324 AV Receiver
// Brand: Pioneer, Model: AXD7690 Remote
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include <algorithm>
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"
// Constants
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1220
const uint16_t kPioneerTick = 534; ///< uSeconds.
const uint16_t kPioneerHdrMark = 8506; ///< uSeconds.
const uint16_t kPioneerHdrSpace = 4191; ///< uSeconds.
const uint16_t kPioneerBitMark = 568; ///< uSeconds.
const uint16_t kPioneerOneSpace = 1542; ///< uSeconds.
const uint16_t kPioneerZeroSpace = 487; ///< uSeconds.
const uint32_t kPioneerMinCommandLength = 84906; ///< uSeconds.
const uint32_t kPioneerMinGap = 25181; ///< uSeconds.
#if SEND_PIONEER
/// Send a raw Pioneer formatted message.
/// Status: STABLE / Expected to be working.
/// @param[in] data The message to be sent.
/// @param[in] nbits The number of bits of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendPioneer(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
// If nbits is to big, abort.
if (nbits > sizeof(data) * 8) return;
for (uint16_t r = 0; r <= repeat; r++) {
// don't use NEC repeat but repeat the whole sequence
if (nbits > 32) {
sendGeneric(kPioneerHdrMark, kPioneerHdrSpace,
kPioneerBitMark, kPioneerOneSpace,
kPioneerBitMark, kPioneerZeroSpace,
kPioneerBitMark, kPioneerMinGap,
kPioneerMinCommandLength,
data >> 32, nbits - 32, 40, true, 0, 33);
}
sendGeneric(kPioneerHdrMark, kPioneerHdrSpace,
kPioneerBitMark, kPioneerOneSpace,
kPioneerBitMark, kPioneerZeroSpace,
kPioneerBitMark, kPioneerMinGap,
kPioneerMinCommandLength,
data, nbits > 32 ? 32 : nbits, 40, true, 0, 33);
}
}
/// Calculate the raw Pioneer data code based on two NEC sub-codes
/// Status: STABLE / Expected to work.
/// @param[in] address A 16-bit "published" NEC value.
/// @param[in] command A 16-bit "published" NEC value.
/// @return A raw 64-bit Pioneer message code for use with `sendPioneer()``
/// @note Address & Command can be take from a decode result OR from the
/// spreadsheets located at:
/// https://www.pioneerelectronics.com/PUSA/Support/Home-Entertainment-Custom-Install/IR+Codes/A+V+Receivers
/// where the first part is considered the address,
/// and the second the command.
/// e.g.
/// "A556+AF20" is an Address of 0xA556 & a Command of 0xAF20.
/// @note If the Address is 0, use it like the following:
/// `irsend.sendPioneer(irsend.encodePioneer(0, 0xAA1C), 32, 1);` or
/// `irsend.sendPioneer(irsend.encodePioneer(0xAA1C, 0xAA1C), 64, 0);`
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1749#issuecomment-1028122645
uint64_t IRsend::encodePioneer(const uint16_t address, const uint16_t command) {
return static_cast<uint64_t>(encodeNEC(address >> 8, address & 0xFF)) << 32 |
encodeNEC(command >> 8, command & 0xFF);
}
#endif // SEND_PIONEER
#if DECODE_PIONEER
/// Decode the supplied Pioneer message.
/// Status: STABLE / Should be working. (Self decodes & real examples)
/// @param[in,out] results Ptr to the data to decode & where to store the result
/// @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 True if it can decode it, false if it can't.
bool IRrecv::decodePioneer(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset)
return false; // Can't possibly be a valid Pioneer message.
if (strict && nbits != kPioneerBits)
return false; // Not strictly an Pioneer message.
uint64_t data = 0;
results->value = 0;
for (uint16_t section = 0; section < 2; section++) {
// Match Header + Data + Footer
uint16_t used;
used = matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, nbits / 2,
kPioneerHdrMark, kPioneerHdrSpace,
kPioneerBitMark, kPioneerOneSpace,
kPioneerBitMark, kPioneerZeroSpace,
kPioneerBitMark, kPioneerMinGap, true);
if (!used) return false;
offset += used;
uint8_t command = data >> 8;
uint8_t command_inverted = data;
uint8_t address = data >> 24;
uint8_t address_inverted = data >> 16;
// Compliance
if (strict) {
if (command != (command_inverted ^ 0xFF))
return false; // Command integrity failed.
if (address != (address_inverted ^ 0xFF))
return false; // Address integrity failed.
}
results->value = (results->value << (nbits / 2)) + data;
// NEC-like commands and addresses are technically in LSB first order so the
// final versions have to be reversed.
uint16_t code = reverseBits((command << 8) + address, 16);
if (section)
results->command = code;
else
results->address = code;
}
// Success
results->bits = nbits;
results->decode_type = PIONEER;
return true;
}
#endif // DECODE_PIONEER