|
@@ -0,0 +1,248 @@
|
|
|
+#include "esic.h"
|
|
|
+#include <stdint.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include "esp_log.h"
|
|
|
+#include "../rxTimer.h"
|
|
|
+#include "../led.h"
|
|
|
+
|
|
|
+/**
|
|
|
+**********************************************************************************
|
|
|
+* TEMP 3
|
|
|
+* ESIC WT450H
|
|
|
+
|
|
|
+ +---+ +---+ +-------+ + high
|
|
|
+ | | | | | | |
|
|
|
+ | | | | | | |
|
|
|
+ + +---+ +---+ +-------+ low
|
|
|
+
|
|
|
+ ^ ^ ^ ^ ^ clock cycle
|
|
|
+ | 1 | 1 | 0 | 0 | translates as
|
|
|
+
|
|
|
+ Each transmission is 36 bits long (i.e. 72 ms)
|
|
|
+
|
|
|
+ .short_width = 976, // half-bit width 976 us
|
|
|
+ .long_width = 1952, // bit width 1952 us
|
|
|
+
|
|
|
+ Data is transmitted in pure binary values, NOT BCD-coded.
|
|
|
+
|
|
|
+ Example transmission (House 1, Channel 1, RH 59 %, Temperature 23.5 �C)
|
|
|
+ 1100 00010011001110110100100110011000
|
|
|
+
|
|
|
+ b00 - b03 (4 bits): Constant, 1100, probably preamble
|
|
|
+ b04 - b07 (4 bits): House code (here: 0001 = HC 1)
|
|
|
+ b08 - b09 (2 bits): Channel code - 1 (here 00 = CC 1)
|
|
|
+ b10 - b12 (3 bits): Constant, 110
|
|
|
+ b13 - b19 (7 bits): Relative humidity (here 0111011 = 59 %)
|
|
|
+ b20 - b34 (15 bits): Temperature (see below)
|
|
|
+ b35 - b35 (1 bit) : Parity (xor of all bits should give 0)
|
|
|
+
|
|
|
+ The temperature is transmitted as (temp + 50.0) * 128,
|
|
|
+ which equals (temp * 128) + 6400. Adding 50.0 �C makes
|
|
|
+ all values positive, an unsigned 15 bit integer where the
|
|
|
+ first 8 bits correspond to the whole part of the temperature
|
|
|
+ (here 01001001, decimal 73, substract 50 = 23).
|
|
|
+ Remaining 7 bits correspond to the fractional part.
|
|
|
+
|
|
|
+ To avoid floating point calculations I store the raw temperature value
|
|
|
+ as a signed integer in the variable esicTemp, then transform it to
|
|
|
+ actual temperature * 10 using "esicTemp = (esicTemp - 6400) * 10 / 128",
|
|
|
+ where 6400 is the added 50 times 128.
|
|
|
+ When reporting the temperature I simply print "esicTemp / 10" (integer division,
|
|
|
+ no fraction), followed by a decimal point and "esicTemp % 10" (remainder, which
|
|
|
+ equals first fractional decimal digit).
|
|
|
+
|
|
|
+ Summary of bit fields:
|
|
|
+ 1100 0001 00 110 0111011 010010011001100 0
|
|
|
+ c1 hc cc c2 rh t p
|
|
|
+
|
|
|
+ c1, c2 = constant field 1 and 2
|
|
|
+ hc, cc = house code and channel code
|
|
|
+ rh, t = relative humidity, temperature
|
|
|
+ p = parity bit 1111111111111110
|
|
|
+**********************************************************************************
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+volatile unsigned long long temp3_x_data;
|
|
|
+
|
|
|
+
|
|
|
+void ESIC_ResetDecoder() {
|
|
|
+ temp3_x_data = 0;
|
|
|
+}
|
|
|
+
|
|
|
+#define NO_OF_PULSES 60
|
|
|
+#define max(a,b) (((a)>(b))?(a):(b))
|
|
|
+#define isShortPulse(width) (((long_pulse/2)-maxDiff) <= width && width <= ((long_pulse/2)+maxDiff))
|
|
|
+#define isLongPulse(width) ((long_pulse-maxDiff) <= width && width <= (long_pulse+maxDiff))
|
|
|
+
|
|
|
+unsigned int temp3_pulses[NO_OF_PULSES];
|
|
|
+
|
|
|
+
|
|
|
+static int long_pulse = 1955;
|
|
|
+static int maxDiff = 300;
|
|
|
+
|
|
|
+static void storePulses(unsigned int inWidth) {
|
|
|
+
|
|
|
+ int i;
|
|
|
+
|
|
|
+ // Shift pulses down
|
|
|
+ for(i=1;i<NO_OF_PULSES;i++) {
|
|
|
+ temp3_pulses[i-1] = temp3_pulses[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ temp3_pulses[NO_OF_PULSES-1] = inWidth;
|
|
|
+}
|
|
|
+
|
|
|
+static void sweepForNoise() {
|
|
|
+
|
|
|
+ // If we have a short pulse in position 2
|
|
|
+ // Then add together pos 1,2 and 3 if they are a valid pulse
|
|
|
+ // This way we can handle one single noise pulse in a real pulse
|
|
|
+ if( temp3_pulses[NO_OF_PULSES-2] < ((long_pulse/2)-maxDiff) ) {
|
|
|
+
|
|
|
+ int totPulse = temp3_pulses[NO_OF_PULSES-1]+temp3_pulses[NO_OF_PULSES-2]+temp3_pulses[NO_OF_PULSES-3];
|
|
|
+
|
|
|
+ if( isShortPulse(totPulse) || isLongPulse(totPulse) ) {
|
|
|
+
|
|
|
+ // Store new pulse in last position
|
|
|
+ temp3_pulses[NO_OF_PULSES-1] = totPulse;
|
|
|
+
|
|
|
+ // Move everything up again
|
|
|
+ for(int i=NO_OF_PULSES-2;i>1;i--) {
|
|
|
+ temp3_pulses[i] = temp3_pulses[i-2];
|
|
|
+ }
|
|
|
+ temp3_pulses[0] = 0;
|
|
|
+ temp3_pulses[1] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*static void adjustTiming() {
|
|
|
+
|
|
|
+ int p1 = temp3_pulses[NO_OF_PULSES-8];
|
|
|
+ int p2 = temp3_pulses[NO_OF_PULSES-7];
|
|
|
+ int p3 = temp3_pulses[NO_OF_PULSES-6];
|
|
|
+ int p4 = temp3_pulses[NO_OF_PULSES-5];
|
|
|
+ int p5 = temp3_pulses[NO_OF_PULSES-4];
|
|
|
+ int p6 = temp3_pulses[NO_OF_PULSES-3];
|
|
|
+ int p7 = temp3_pulses[NO_OF_PULSES-2];
|
|
|
+ int p8 = temp3_pulses[NO_OF_PULSES-1];
|
|
|
+
|
|
|
+ // Check max differance between the short pulses
|
|
|
+ int sh_mean = (p1+p2+p3+p4) / 4;
|
|
|
+ int sh_max_diff = max(max(abs(p1-sh_mean),abs(p2-sh_mean)),max(abs(p3-sh_mean),abs(p4-sh_mean)));
|
|
|
+
|
|
|
+ // Check max differance between the long pulses
|
|
|
+ int long_mean = (p5+p6+p7+p8) / 4;
|
|
|
+ int long_max_diff = max(max(abs(p5-long_mean),abs(p6-long_mean)),max(abs(p7-long_mean),abs(p8-long_mean)));
|
|
|
+
|
|
|
+ if( sh_max_diff < maxDiff && long_max_diff < maxDiff ) {
|
|
|
+
|
|
|
+ int mean = (long_mean + sh_mean)/2;
|
|
|
+ if( long_mean > (mean+maxDiff) && sh_mean < (mean-maxDiff) ) {
|
|
|
+ if( abs(long_mean - (sh_mean*2)) < maxDiff ) {
|
|
|
+ long_pulse = (long_mean + sh_mean*2)/2;
|
|
|
+ maxDiff = long_mean / 15;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}*/
|
|
|
+
|
|
|
+// The latest/newest pulse is at the end of the array [59]
|
|
|
+// This ([59]) is the latest bit in the bit-stream from the transmitter
|
|
|
+// This is way we input the bits at a high position and shift them towards lower values
|
|
|
+// So..start reading backwards and working towards the first/highest bits
|
|
|
+static int checkPulsePattern() {
|
|
|
+
|
|
|
+ int i = NO_OF_PULSES-1; // Start reading from the last received (end of array)
|
|
|
+ int b = 0;
|
|
|
+
|
|
|
+ unsigned long long code = 0;
|
|
|
+
|
|
|
+ while( i >= 0 ) {
|
|
|
+
|
|
|
+ int combWidth = temp3_pulses[i] + temp3_pulses[i-1];
|
|
|
+
|
|
|
+ if( isLongPulse(temp3_pulses[i]) ) {
|
|
|
+ b++;
|
|
|
+ i-=1;
|
|
|
+ code = code >> 1;
|
|
|
+ }
|
|
|
+ else if( isShortPulse(temp3_pulses[i]) && isShortPulse(temp3_pulses[i-1]) ) {
|
|
|
+ b++;
|
|
|
+ i-=2;
|
|
|
+ code = ((code >> 1) | 0x200000000);
|
|
|
+ }
|
|
|
+ else if( isLongPulse( combWidth ) ) {
|
|
|
+ b++;
|
|
|
+ i-=2;
|
|
|
+ code = ((code >> 1) | 0x200000000);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if( b == 34 ) {
|
|
|
+/*
|
|
|
+ 0000 0001 00 110 0101000 010010110101000 1
|
|
|
+AND: 0011 1111 00 111 0000000 000000000000000 0 = 001111110011100000000000000000000000 = 0x3F3800000
|
|
|
+RES: 0000 0001 00 110 0000000 000000000000000 0 = 000000010011000000000000000000000000 = 0x013000000
|
|
|
+
|
|
|
+ Summary of bit fields:
|
|
|
+ 1100 0001 00 110 0111011 010010011001100 0
|
|
|
+ c1 hc cc c2 rh t p
|
|
|
+ */
|
|
|
+ if( (code & 0x3F3800000) == 0x013000000 ) {
|
|
|
+
|
|
|
+ temp3_x_data = (code&0xFFFFFFFF);
|
|
|
+ // Check parity
|
|
|
+ int even=0;
|
|
|
+ unsigned long long data = temp3_x_data;
|
|
|
+ for(int i=0;i<32;i++) {
|
|
|
+ if( data & 1 ) even++;
|
|
|
+ data >>= 1;
|
|
|
+ }
|
|
|
+ if( even % 2 != 0 ) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ // A correct code has been received
|
|
|
+ //printf("Code received: %llu on row:%d\n",(code&0xFFFFFFFF),row_no);
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int temp3decode (unsigned int inWidth) {
|
|
|
+
|
|
|
+ int width = inWidth; //preProcessPulses(inWidth);
|
|
|
+
|
|
|
+ if( width == -1 ) return -1;
|
|
|
+ if( width == 0 ) return 0;
|
|
|
+
|
|
|
+ storePulses(inWidth);
|
|
|
+ sweepForNoise();
|
|
|
+ //adjustTiming();
|
|
|
+ return checkPulsePattern();
|
|
|
+}
|
|
|
+
|
|
|
+int64_t nextPulseESICSensor(uint32_t width) {
|
|
|
+
|
|
|
+ volatile static int result;
|
|
|
+
|
|
|
+ if( width > 0 ) {
|
|
|
+ if( temp3_x_data == 0 ) {
|
|
|
+
|
|
|
+ result = temp3decode(width);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (temp3_x_data > 0);
|
|
|
+}
|