/* * high state lasts about 500 usecs * * sync pulse is ~4500 usec (from rising edge to rising edge) * zero is ~1500 usec * one is ~2500 usec * * data packet is repeated 8 times * note: the first packet is missing the sync pulse */ #include // weather sensor #define SYNC_MIN 4450 #define SYNC_MAX 4550 #define PULSE0_MIN 1450 #define PULSE0_MAX 1550 #define PULSE1_MIN 2450 #define PULSE1_MAX 2550 #define RF433PIN 7 #define RF433INT 4 uint8_t packet[5]; // current rf packet int8_t state; /* * Ring buffer size must be power of two * * As each data packet is five bytes, 128 byte buffer is enough for 25 packets. * One burst consists of 8 valid packets, so 128 byte buffer can hold three full bursts. */ #define QSIZE 128 uint8_t ringbuf[QSIZE]; // circular buffer, size must be power of two volatile uint16_t rdpos; volatile uint16_t wrpos; void setup() { rdpos = wrpos = 0; state = -1; pinMode(A0, INPUT); Serial.begin(115200); digitalWrite (RF433PIN, HIGH); attachInterrupt(RF433INT, RFpulse, RISING); } /////////////////////////////////////////////////////////////////////// // ring buffer read/write int16_t queue(uint8_t data) { uint16_t p = (wrpos + 1) & (QSIZE - 1); if (p != rdpos) { ringbuf[wrpos] = data; wrpos = p; p = (((p - rdpos) & (QSIZE-1)) - 1); } else { p = -1; } return p; } void queue_block(uint8_t data) { int16_t r; do { r = queue(data); } while (r < 0); } int16_t dequeue() { if (rdpos == wrpos) return -1; int16_t b = ringbuf[rdpos]; rdpos = ((rdpos + 1) & (QSIZE - 1)); return b; } /////////////////////////////////////////////////////////////////////// // store bits into packet, msb first void packetbit(uint8_t b, uint8_t pos) { int8_t mask = 0x80 >> (pos & 7); uint8_t p = pos >>= 3; if (b) { packet[p] |= mask; } else { packet[p] &= (mask ^0xff); } } /////////////////////////////////////////////////////////////////////// // interrupt routine to read RF signal void RFpulse() { static unsigned long then; unsigned long now = micros(); unsigned long delta = now - then; uint16_t d = (delta > 65535) ? 65535 : delta; if (state < 0) { if ((d > SYNC_MIN) && (d < SYNC_MAX)) state = 0; } else { if ((d > PULSE0_MIN) && (d < PULSE0_MAX)) { packetbit(0, state++); } else if ((d > PULSE1_MIN) && (d < PULSE1_MAX)) { packetbit(1, state++); } else { state = -1; } // if we have 36 bits we put them into queue and start over if (state >= 36) { for (uint8_t i = 0; i < 5; i++) { queue(packet[i]); } state = -1; } } then = now; } /////////////////////////////////////////////////////////////////////// // main program - void loop() { static int8_t motion = LOW; static int8_t dolocal = 0; uint8_t t; int8_t randid; // b0:7:8 uint8_t batt; // b1:7 uint8_t manual; // b1:6 uint8_t devnum; // b1:5:2 int16_t temperature; // b1:3:12 uint8_t fill; // b3:7:4 int16_t humidity; // b3:3:8 delay(100); while (rdpos != wrpos) { // output pending data to serial /* 0 8 random id 8 1 battery? (1 = ok) 9 1 manual tx (1 if manual) 10 2 numeric id 0..3 (only 0..2 used) 12 12 temperature (*10) 24 4 1111 28 8 humidity rnd b m id t f h 0 8 9 a c 18 1c M rnd_rnd_ b m id tmp_tmp_tmp_ fill hum_hum_ */ randid = dequeue(); // 0..7 t = dequeue(); // 8..15 batt = t >> 7; manual = (t >> 6) & 1; devnum = ((t >> 4) & 3) + 1; temperature = ((t & 0x0f) << 8) | dequeue(); if (temperature & 0x0800) { temperature |= 0xf000; } t = dequeue(); fill = t >> 4; humidity = ((t & 0x0f) << 4); humidity |= dequeue() >> 4; Serial.write("Device "); Serial.print(devnum, DEC); Serial.write(":"); Serial.print(randid, DEC); Serial.write(manual ? "(m)" : "(a)"); Serial.write(", battery "); Serial.write(batt ? "ok" : "low"); Serial.write(", temp="); Serial.print(temperature, DEC); Serial.write(", humidity="); Serial.print(humidity, DEC); Serial.write(" (fill="); Serial.print(fill, DEC); Serial.write(")\r\n"); } }