110 lines
3.6 KiB
C++
110 lines
3.6 KiB
C++
#include "archtech.h"
|
|
#include "buffer.h"
|
|
|
|
/*******************************************************************************
|
|
--ARCHTECH PROTOCOL SPECIFICATION--
|
|
|
|
----SIGNAL----
|
|
A signal consists of a PREAMBLE, DATA and an POSTAMBLE.
|
|
Each signal is sent 4 times in a row to increase the delivery success rate.
|
|
|
|
----PREAMBLE----
|
|
send high for 250 microseconds
|
|
send low for 2,500 microseconds
|
|
|
|
----DATA----
|
|
26 bits of transmitter id
|
|
1 bit indicating if the on/off bit is targeting a group
|
|
1 bit indicating "on" or "off"
|
|
4 bits indicating the targeted unit/channel/device
|
|
4 bits indicating a absolute dim level (optional)
|
|
|
|
Total: 32 or 36 bits depending if absolute dimming is used
|
|
|
|
Each real bit in the data field is sent over air as a pair of two inverted bits.
|
|
real bit bits over air
|
|
1 = "01"
|
|
0 = "10"
|
|
|
|
Over air a "1"(one) is sent as:
|
|
send high for 250 microseconds
|
|
send low for 1,250 microseconds
|
|
|
|
Over air a "0"(zero) is sent as:
|
|
send high for 250 microseconds
|
|
send low for 250 microseconds
|
|
|
|
----POSTAMBLE----
|
|
send high for 250 microseconds
|
|
send low for 10,000 microseconds
|
|
|
|
*******************************************************************************/
|
|
|
|
#define ARCHTECH_SHORT_MIN 2
|
|
#define ARCHTECH_SHORT_MAX 7
|
|
#define ARCHTECH_LONG_MIN 17
|
|
#define ARCHTECH_LONG_MAX 27
|
|
|
|
#define IS_SHORT(b) ( ARCHTECH_SHORT_MIN <= b && b <= ARCHTECH_SHORT_MAX )
|
|
#define IS_LONG(b) ( ARCHTECH_LONG_MIN <= b && b <= ARCHTECH_LONG_MAX )
|
|
|
|
#define IS_ZERO(b1,b2,b3,b4) ( IS_SHORT(b1) && IS_LONG(b2) && IS_SHORT(b3) && IS_SHORT(b4) )
|
|
#define IS_ONE(b1,b2,b3,b4) ( IS_SHORT(b1) && IS_SHORT(b2) && IS_SHORT(b3) && IS_LONG(b4) )
|
|
|
|
bool parseArctechSelfLearning(uint8_t* bufStartP, uint8_t* bufEndP) { //start points to a "high" buffer byte, end points to a "low" buffer byte
|
|
uint64_t data = 0;
|
|
bool dimValuePresent;
|
|
|
|
uint16_t bitsInBuffer = calculateBufferPointerDistance(bufStartP, bufEndP) / 4; //each bit is representd by 4 high/low
|
|
//Serial.print("bits in buffer: "); Serial.print(bitsInBuffer); Serial.print(" - ");
|
|
if (bitsInBuffer == 33) {
|
|
//Serial.println("default");
|
|
dimValuePresent = false;
|
|
}else if(bitsInBuffer == 37){
|
|
//Serial.println("with dim");
|
|
dimValuePresent = true;
|
|
} else {
|
|
//Serial.println("ignore");
|
|
return false;
|
|
}
|
|
|
|
//stkip two buffers entries.
|
|
stepBufferPointer(&bufStartP);
|
|
stepBufferPointer(&bufStartP);
|
|
|
|
for (uint8_t i = 0; i < bitsInBuffer-1; ++i) {
|
|
|
|
uint8_t b1 = *bufStartP; //no of high
|
|
stepBufferPointer(&bufStartP);
|
|
uint8_t b2 = *bufStartP; //no of low
|
|
stepBufferPointer(&bufStartP);
|
|
uint8_t b3 = *bufStartP; //no of high
|
|
stepBufferPointer(&bufStartP);
|
|
uint8_t b4 = *bufStartP; //no of low
|
|
stepBufferPointer(&bufStartP);
|
|
|
|
//Serial.print(b1); Serial.print(", ");Serial.print(b2); Serial.print(", ");Serial.print(b3); Serial.print(", ");Serial.print(b4);
|
|
|
|
if (IS_ONE(b1,b2,b3,b4)) { //"one" is sent over air
|
|
//Serial.println(" --> 1");
|
|
data <<= 1; //shift in a zero
|
|
data |= 0x1; //add one
|
|
} else if (IS_ZERO(b1,b2,b3,b4)) { //"zero" is sent over air
|
|
//Serial.println(" --> 0");
|
|
data <<= 1; //shift in a zero
|
|
} else {
|
|
//Serial.println(" --> CORRUPT");
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
Serial.print(F("+Wclass:command;protocol:arctech;model:selflearning;data:0x"));
|
|
uint8_t hexToSend = (dimValuePresent ? 9 : 8);
|
|
for (int8_t i = hexToSend - 1; i >= 0; --i) {
|
|
Serial.print( (byte)((data >> (4 * i)) & 0x0F), HEX);
|
|
}
|
|
Serial.println(F(";"));
|
|
|
|
return true;
|
|
}; //end parseArctechSelfLearning
|