#include #include #include #include #include /* #include "avr-stub.h" */ #define DATA (1<<3) #define LED2 (1<<5) #define LED1 (1<<6) #define DDR_SPI DDRB #define PORT_SPI PORTB #define PIN_SPI PINB #define MOSI (1<<5) #define MISO (1<<6) #define SS (1<<4) #define SCK (1<<7) volatile int debug = 1; #define BP() if (debug) breakpoint() union { struct { unsigned int config; unsigned int afc; unsigned int freq; unsigned int recv; unsigned int filter; unsigned int pm; unsigned int fifo; unsigned int pll; unsigned int rate; } cmd; unsigned int words[15]; } rfm12cfg EEMEM = { 0x8017, 0xC431, 0xa608, 0x94c2, 0xC220, 0x82D8, 0xCA00, 0xCC67, 0xC623, 0, 0 }; void sw(unsigned int word) { PORT_SPI &= ~SS; SPDR = word >> 8; while(!(SPSR & (1< ready for decoding */ } ook; #define FRAMESZ 256 struct frame { unsigned char bits[FRAMESZ+1]; /* FIXME: inefficient */ decoder *origin; }; #define NFRAMES 3 volatile struct { struct frame frame[NFRAMES]; unsigned char idx; } frames; ISR(TIMER0_OVF_vect) { if(ook.idx > 0) ook.flag++; } /* Unknwon sensor - somewhere in the neighborhood ...___^_____^__^_^__^_^_^__^_^__^_^_^__^__^_^_^_^__^__^__^__^__^__.... Very short pulses of the same length, spaced differently. pulse length: 0.55ms, short pause length: 1.84ms double pause length: 4.375ms quad pause length: 9.5ms => SYNC 101001010010100000010000001001101001 101001010tt0dddddddddddd????????cccc */ unsigned char unk2() { static int qp = F_CPU / PRESCALER / 105; static int dp = F_CPU / PRESCALER / 228; static int sp = F_CPU / PRESCALER / 543; static int pulse = F_CPU / PRESCALER / 1800; if (ook.idx < 50) return 0; { int idx = 0; /* first pause */ /* search for quad pause and sound pulse lengths */ while(idx < ook.idx) { if(qp - pulse < ook.data[idx] && qp + pulse > ook.data[idx]) if (ook.data[++idx] < 1.5 * pulse) break; else return 0; idx++; if(ook.data[idx] > 1.5 * pulse) return 0; idx++; } /* success */ idx++; { struct frame *f = &(frames.frame[frames.idx++%NFRAMES]); unsigned char *bits=f->bits; f->origin=__func__; unsigned char i; for(;idx < ook.idx && bits < f->bits + FRAMESZ; idx+=2) { if (ook.data[idx] < sp - pulse) *bits++='A'; /* invalid */ else if (ook.data[idx] < sp + pulse) *bits++='0'; else if (ook.data[idx] < dp - pulse) *bits++='B'; /* invalid */ else if (ook.data[idx] < dp + pulse) *bits++='1'; else if (ook.data[idx] < qp - pulse) *bits++='C'; /* invalid */ else if (ook.data[idx] < qp + pulse) *bits++='S'; /* sync */ else if (ook.data[idx] > qp + pulse) *bits++='D'; /* invalid */ } *bits++='\0'; bits = f->bits; retry: /* find sync code */ while (*bits && *bits != 'S') bits++; if (strlen(bits) < 20) { printf("%s::%s\n", __func__, f->bits); return 0; } bits++; { int i; for (i=0; bits[i] && bits[i] != 'S'; i++) if (bits[i] != '1' && bits[i] != '0') goto retry; switch(i) { /* two sensors with different frame lengths */ case 24: /* 011010100000000101111110 */ /* 01101010 dddddddddddd */ if (strncmp("01101010", bits, 8)) goto retry; { long temp = 0; for (i = 10; i < 22; i++) { temp += (bits[i]=='1') << (21 - i); } bits[24] = 0; printf("sens1:%d.%d:%s\n", (int)temp/10, (int)temp%10, bits); return 1; } case 28: /* 1111110110110000011011100100 */ /* cccc11011011dddddddddddd0100 */ /* 0001100100100000011010110110 since may 2010 - channel switched? */ if(strncmp(bits+4, "11011011", 8) && strncmp(bits+4, "10010010", 8)) goto retry; { long temp = 0; for (i = 12; i < 24; i++) { temp += (bits[i]=='1') << (23 - i); } bits[28]=0; printf("sens2:%d.%d:%s\n", (int)temp/10, (int)temp%10, bits); } return 1; } goto retry; } } } return 0; } /* TCM labelled. ...___^_____^__^_^__^_^_^__^_^__^_^_^__^__^_^_^_^__^__^__^__^__^__.... Very short pulses of the same length, spaced differently. pulse length: 0.69ms, 1450/s short pause length: 1.8ms, 556/s => 0 double pause length: 3.8125ms, 262/s => 1 quad pause length: 8.654514ms, 116/s => SYNC 101001010010100000010000001001101001 101001010tt0dddddddddddd????????cccc */ unsigned char tcm() { static int qp = F_CPU / PRESCALER / 116; /* 124 */ static int dp = F_CPU / PRESCALER / 262; /* 54.9 */ static int sp = F_CPU / PRESCALER / 556; /* 25.9 */ static int pulse = F_CPU / PRESCALER / 1450; /* 9.9 */ if (ook.idx < 50) return 0; { int idx = 0; /* first pause */ /* search for quad pause and sound pulse lengths */ while(idx < ook.idx) { if(qp - pulse < ook.data[idx] && qp + pulse > ook.data[idx]) if (ook.data[++idx] < 1.5 * pulse) break; else return 0; idx++; if(ook.data[idx] > 1.5 * pulse) return 0; idx++; } /* success */ idx++; { struct frame *f = &(frames.frame[frames.idx++%NFRAMES]); unsigned char *bits=f->bits; f->origin=__func__; unsigned char i; for(;idx < ook.idx && bits < f->bits + FRAMESZ; idx+=2) { if (ook.data[idx] < sp - pulse) *bits++='A'; /* invalid */ else if (ook.data[idx] < sp + pulse) *bits++='0'; else if (ook.data[idx] < dp - pulse) *bits++='B'; /* invalid */ else if (ook.data[idx] < dp + pulse) *bits++='1'; else if (ook.data[idx] < qp - pulse) *bits++='C'; /* invalid */ else if (ook.data[idx] < qp + pulse) *bits++='S'; /* sync */ else if (ook.data[idx] > qp + pulse) *bits++='D'; /* invalid */ } *bits++='\0'; bits = f->bits; retry: /* find sync code */ while (*bits && *bits != 'S') bits++; if (strlen(bits) <= 37) return 0; bits++; for (i=0; bits[i] && bits[i] != 'S'; i++) if (bits[i] != '1' && bits[i] != '0') goto retry; if (i != 36) goto retry; if (strncmp("10100101", bits, 8)) goto retry; bits[i]=0; { long temp = 0; for(i=12; i<24; i++) temp += (bits[i] == '1') << i%12; printf("%s:%d.%d:%s\n", __func__, (int)temp/10, (int)temp%10, bits); } return 1; } } return 0; } /* Unknown sensor, somewhere in the neighborhood ...__^^^^^^^^____^_^_^_^_^^^_^^^_^_^_^_^_^_^_^_^_^_^_^_^^^_^_.... ^^^_ = 1 ^_ = 0 538 baud 110000000001001000001111 1100aaaabbbbccccddddeeee */ unsigned char unk0() { static unsigned char bittime = F_CPU / PRESCALER / 538 /* baud */; if (ook.idx < 50) /* usually > 70 transitions => > 140 elements */ return 0; { int idx = 1; unsigned char i, on, off, len; /* 8 bit burst */ for (on = off = 0;;) { on += (ook.data[idx++] + bittime / 2) / bittime; if (on == 8) break; off += (ook.data[idx++] + bittime / 2) / bittime; if (off) return 0; } /* 8 bit silence */ off = (ook.data[idx++] + bittime / 2) / bittime; if (off != 4) return 0; /* 0xU */ for(i=0; i<4; i++) { on = (ook.data[idx++] + bittime / 2) / bittime; if (on != 1) return 0; off = (ook.data[idx++] + bittime / 2) / bittime; if (off != 1) return 0; } /* this is probably our signal */ { struct frame *f = &(frames.frame[frames.idx++%NFRAMES]); unsigned char *bits=f->bits; f->origin=__func__; while (idx < ook.idx && bits < f->bits + FRAMESZ) { len = (ook.data[idx++%OOKSZ] + bittime / 2) / bittime; for (i=0; ibits + FRAMESZ; i++) *bits++ = idx & 1 ? '0' : '1'; } *bits = '\0'; { int src, dst; bits = f->bits; for(src = dst = 0; bits[src] && dst < FRAMESZ;) { if (bits[src++] != '1') return 0; if (bits[src++] == '0') bits[dst++] = '0'; else { if (bits[src] == '\0') break; if (bits[src++] == '1' && bits[src++] == '0') bits[dst++] = '1'; else return 0; } } bits[dst] = '\0'; } { printf("%s:%d.%d:%s\n", __func__, 10 * (((bits[8] == '1' )<<3) + ((bits[9] == '1' ) <<2) + ((bits[10] == '1' ) <<1) + ((bits[11] == '1' ) <<0)) + ((bits[12] == '1' )<<3) + ((bits[13] == '1' ) <<2) + ((bits[14] == '1' ) <<1) + ((bits[15] == '1' ) <<0), ((bits[16] == '1' )<<3) + ((bits[17] == '1' ) <<2) + ((bits[18] == '1' ) <<1) + ((bits[19] == '1' ) <<0), bits); } return 1; } } return 0; } void ook_decode() { int i; for(i=0; decoders[i]; i++) if (decoders[i]()) break; ook.idx=0; TCNT0=0; ook.flag=0; } void ook_capture() { unsigned char sample = PINB & DATA; if (ook.value == sample) return; ook.data[ook.idx++%OOKSZ] = TCNT0; TCNT0=0; ook.value = sample; } void ook_poll() { if (ook.flag) ook_decode(); else ook_capture(); } /* local lm35d on ADC pin */ #define ADCAVG 18 /* BITS for oversampling */ void __attribute__((constructor)) adc_init() { ADMUX = 0x7 /* ADC7 SE */ | 0xc0 /* 2.56V ref */; ADCSRA |= 0x80 /* ADEN */ | 0x7 /* prescaler */; ADCSRA |= 1 << ADSC; } void adc_poll() { if (ADCSRA & (1< ((unsigned long)1<> (2+ADCAVG)), /* (unsigned int)(100*((accu >> (ADCAVG))&3))/4, */ /* (unsigned int)(100*((accu >> (ADCAVG-4))&0x3f))/64, */ (unsigned int)(100*((accu >> (ADCAVG-5))&0x7f))/128, curval); accu = 0; samples = 0; } ADCSRA |= 1 << ADSC; } } int main(void) { PORTD |= 1 << 6; sei(); { unsigned char i; for (i=0;++i;) _delay_ms(1); } { unsigned char i=0; unsigned int cmd; do { cmd = eeprom_read_word(&rfm12cfg.words[i++]); sw(cmd); } while (cmd); } while(1) { adc_poll(); ook_poll(); if (PINB & DATA) PORTD |= LED2; else PORTD &= ~LED2; if (ook.idx > 5) PORTD |= LED1; else PORTD &= ~LED1; } return 0; }