Beispiel #1
0
static void rf12_interrupt () {
    // a transfer of 2x 16 bits @ 2 MHz over SPI takes 2x 8 us inside this ISR
    // correction: now takes 2 + 8 µs, since sending can be done at 8 MHz
    rf12_xfer(0x0000); 

    if (rxstate == TXRECV) {
        uint8_t in = rf12_xferSlow(RF_RX_FIFO_READ);

        if (rxfill == 0 && group != 0)
            rf12_buf[rxfill++] = group;
            
        rf12_buf[rxfill++] = in;
        rf12_crc = _crc16_update(rf12_crc, in);

        if (rxfill >= rf12_len + 5 || rxfill >= RF_MAX)
            rf12_xfer(RF_IDLE_MODE);
    } else {
        uint8_t out;

        if (rxstate < 0) {
            uint8_t pos = 3 + rf12_len + rxstate++;
            out = rf12_buf[pos];
            rf12_crc = _crc16_update(rf12_crc, out);
        } else
            switch (rxstate++) {
                case TXSYN1: out = 0x2D; break;
                case TXSYN2: out = group; rxstate = - (2 + rf12_len); break;
                case TXCRC1: out = rf12_crc; break;
                case TXCRC2: out = rf12_crc >> 8; break;
                case TXDONE: rf12_xfer(RF_IDLE_MODE); // fall through
                default:     out = 0xAA;
            }
            
        rf12_xfer(RF_TXREG_WRITE + out);
    }
}
Beispiel #2
0
static void rf12_recvStart () {
    if (rf12_fixed_pkt_len) {
        rf12_len = rf12_fixed_pkt_len;
        rf12_grp = rf12_hdr = 0;
        rxfill = 3;
    } else
        rxfill = rf12_len = 0;
    rf12_crc = ~0;
#if RF12_VERSION >= 2
    if (group != 0)
        rf12_crc = _crc16_update(~0, group);
#endif
    rxstate = TXRECV;

    rf12_xfer(RF_RECEIVER_ON);
}
Beispiel #3
0
/// @details
/// This can be used to send out slow bit-by-bit On Off Keying signals to other
/// devices such as remotely controlled power switches operating in the 433,
/// 868, or 915 MHz bands.
///
/// To use this, you need to first call rf12initialize() with a zero node ID
/// and the proper frequency band. Then call rf12onOff() in the exact timing
/// you need for sending out the signal. Once done, either call rf12onOff(0) to
/// turn the transmitter off, or reinitialize the wireless module completely
/// with a call to rf12initialize().
/// @param value Turn the transmitter on (if true) or off (if false).
/// @note The timing of this function is relatively coarse, because SPI
/// transfers are used to enable / disable the transmitter. This will add some
/// jitter to the signal, probably in the order of 10 µsec.
void rf12_onOff (uint8_t value) {
    rf12_xfer(value ? RF_XMITTER_ON : RF_IDLE_MODE);
}
Beispiel #4
0
/// @details
/// Call this once with the node ID (0-31), frequency band (0-3), and
/// optional group (0-255 for RFM12B, only 212 allowed for RFM12).
/// @param id The ID of this wireless node. ID's should be unique within the
///           netGroup in which this node is operating. The ID range is 0 to 31,
///           but only 1..30 are available for normal use. You can pass a single
///           capital letter as node ID, with 'A' .. 'Z' corresponding to the
///           node ID's 1..26, but this convention is now discouraged. ID 0 is
///           reserved for OOK use, node ID 31 is special because it will pick
///           up packets for any node (in the same netGroup).
/// @param band This determines in which frequency range the wireless module
///             will operate. The following pre-defined constants are available:
///             RF12_433MHZ, RF12_868MHZ, RF12_915MHZ. You should use the one
///             matching the module you have, to get a useful TX/RX range.
/// @param g Net groups are used to separate nodes: only nodes in the same net
///          group can communicate with each other. Valid values are 1 to 212.
///          This parameter is optional, it defaults to 212 (0xD4) when omitted.
///          This is the only allowed value for RFM12 modules, only RFM12B
///          modules support other group values.
/// @param f Frequency correction to apply. Defaults to 1600, per RF12 docs.
///          This parameter is optional, and was added in February 2014.
/// @returns the nodeId, to be compatible with rf12_config().
///
/// Programming Tips
/// ----------------
/// Note that rf12_initialize() does not use the EEprom netId and netGroup
/// settings, nor does it change the EEPROM settings. To use the netId and
/// netGroup settings saved in EEPROM use rf12_config() instead of
/// rf12_initialize. The choice whether to use rf12_initialize() or
/// rf12_config() at the top of every sketch is one of personal preference.
/// To set EEPROM settings for use with rf12_config() use the RF12demo sketch.
uint8_t rf12_initialize (uint8_t id, uint8_t band, uint8_t g, uint16_t f) {
    nodeid = id;
    group = g;
    frequency = f;
// caller should validate!    if (frequency < 96) frequency = 1600;

    rf12_spiInit();
    rf12_xfer(0x0000); // initial SPI transfer added to avoid power-up problem
    rf12_xfer(RF_SLEEP_MODE); // DC (disable clk pin), enable lbd

    // wait until RFM12B is out of power-up reset, this takes several *seconds*
    rf12_xfer(RF_TXREG_WRITE); // in case we're still in OOK mode
    while (digitalRead(RFM_IRQ) == 0)
        rf12_xfer(0x0000);

    rf12_xfer(0x80C7 | (band << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF
    rf12_xfer(0xA000 + frequency); // 96-3960 freq range of values within band
    rf12_xfer(0xC606); // approx 49.2 Kbps, i.e. 10000/29/(1+6) Kbps
    rf12_xfer(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm
    rf12_xfer(0xC2AC); // AL,!ml,DIG,DQD4
    if (group != 0) {
        rf12_xfer(0xCA83); // FIFO8,2-SYNC,!ff,DR
        rf12_xfer(0xCE00 | group); // SYNC=2DXX;
    } else {
        rf12_xfer(0xCA8B); // FIFO8,1-SYNC,!ff,DR
        rf12_xfer(0xCE2D); // SYNC=2D;
    }
    rf12_xfer(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN
    rf12_xfer(0x9850); // !mp,90kHz,MAX OUT
    rf12_xfer(0xCC77); // OB1,OB0, LPX,!ddy,DDIT,BW0
    rf12_xfer(0xE000); // NOT USE
    rf12_xfer(0xC800); // NOT USE
    rf12_xfer(0xC049); // 1.66MHz,3.1V

    rxstate = TXIDLE;
#if PINCHG_IRQ
#if RFM_IRQ < 8
    if ((nodeid & NODE_ID) != 0) {
        bitClear(DDRB, RFM_IRQ);      // input
        bitSet(PORTB, RFM_IRQ);       // pull-up
        bitSet(PCMSK0, RFM_IRQ);      // pin-change
        bitSet(PCICR, PCIE0);         // enable
    } else
        bitClear(PCMSK0, RFM_IRQ);
#elif RFM_IRQ < 15
    if ((nodeid & NODE_ID) != 0) {
        bitClear(DDRC, RFM_IRQ - 8);  // input
        bitSet(PORTC, RFM_IRQ - 8);   // pull-up
        bitSet(PCMSK1, RFM_IRQ - 8);  // pin-change
        bitSet(PCICR, PCIE1);         // enable
    } else
        bitClear(PCMSK1, RFM_IRQ - 8);
#else
    if ((nodeid & NODE_ID) != 0) {
        bitClear(DDRD, RFM_IRQ - 16); // input
        bitSet(PORTD, RFM_IRQ - 16);  // pull-up
        bitSet(PCMSK2, RFM_IRQ - 16); // pin-change
        bitSet(PCICR, PCIE2);         // enable
    } else
        bitClear(PCMSK2, RFM_IRQ - 16);
#endif
#else
    if ((nodeid & NODE_ID) != 0)
        attachInterrupt(0, rf12_interrupt, LOW);
    else
        detachInterrupt(0);
#endif

    return nodeid;
}
Beispiel #5
0
/// @details
/// Brings RFM12 in idle-mode.
static void rf12_idle() {
	rfmstate &= ~B11110000; // switch off synthesizer, transmitter, receiver and baseband
	rfmstate |=  B00001000; // make sure crystal is running
	rf12_xfer(rfmstate);
}
Beispiel #6
0
/// @details
/// This call provides direct access to the RFM12B registers. If you're careful
/// to avoid configuring the wireless module in a way which stops the driver
/// from functioning, this can be used to adjust frequencies, power levels,
/// RSSI threshold, etc. See the RFM12B wireless module documentation.
///
/// OBSOLETE! Use rf12_xfer instead.
///
/// This function does no longer return anything.
/// @param cmd RF12 command, topmost bits determines which register is affected.
uint16_t rf12_control(uint16_t cmd) {
    return rf12_xfer(cmd);
}
Beispiel #7
0
/// @details
/// Handles a RFM12 interrupt depending on rxstate and the status reported by the RF
/// module.
static void rf12_interrupt() {
    uint8_t in;
    state = rf12_xferState(&in);

    // data received or byte needed for sending
    if (state & RF_FIFO_BIT) {

	    if (rxstate == TXRECV) {  // we are receiving

            if (rxfill == 0 && group != 0) {
                rf12_buf[rxfill++] = group;
#if 0
                if (fixedLength) {
					rf12_crc8 = 0;
					if (((in & 0xF0) == 0xA0) && (fixedLength > 10) && (fixedLengthBase < 10)) {
						minLengthCrcOk = 10; // otherwise repeating Fine Offset packages are missed
					}
					else {
						minLengthCrcOk = fixedLengthBase;
					}

				}
#endif
			}

			rf12_buf[rxfill++] = in;
			if (fixedLength) {
#if 0
				if ((rxfill == 2) && ((in & 0xF) >= 4) && ((in & 0xF) <= 5) && ((rf12_buf[1] & 0xF) == 0xA)) {
					minLengthCrcOk = fixedLength;
					fixedLength = 13 + 1; // ws1600 is longer
				}
#endif
				rf12_crc8 = _crc8_update(rf12_crc8, in);
			}
			else {
        		rf12_crc = _crc16_update(rf12_crc, in);
			}

    	    // do drssi binary-tree search
	        if ( drssi < 3 && ((rxfill-2)%drssi_bytes_per_decision)==0 ) {// not yet final value
	        	// top nibble when going up, bottom one when going down
	        	drssi = bitRead(state,8)
	        			? (drssi_dec_tree[drssi] & B1111)
	        			: (drssi_dec_tree[drssi] >> 4);
	            if ( drssi < 3 ) {     // not yet final destination, set new threshold
                	rf12_xfer(RF_RECV_CONTROL | drssi*2+1);
            	}
           	}

			// check if we got all the bytes (or maximum packet length was reached)
			if (fixedLength) {
				if ((rf12_crc8 == 0) && minLengthCrcOk > 0 && (rxfill >= minLengthCrcOk)) {
					rf12_buf[0] = rxfill;
#if 0
					while (rxfill < fixedLength) {
						rf12_buf[rxfill++] = 0;
					}
#endif
					rf12_idle();
				}
				else if (rxfill >= fixedLength || rxfill >= RF_MAX) {
					rf12_buf[0] = rxfill;
					rf12_idle();
				}
			} else if (rxfill >= rf12_len + 5 || rxfill >= RF_MAX) {
       	    	rf12_idle();
			}

    	} else {                  // we are sending
Beispiel #8
0
// access to the RFM12B internal registers with interrupts disabled
uint16_t rf12_control(uint16_t cmd) {
    bitClear(EIMSK, INT0);
    uint16_t r = rf12_xfer(cmd);
    bitSet(EIMSK, INT0);
    return r;
}
Beispiel #9
0
/*!
  Call this once with the node ID (0-31), frequency band (0-3), and
  optional group (0-255 for RF12B, only 212 allowed for RF12).
*/
void rf12_initialize () {
    spi_initialize();

    pinMode(RFM_IRQ, INPUT);
    digitalWrite(RFM_IRQ, 1); // pull-up

    rf12_xfer(0x0000); // intitial SPI transfer added to avoid power-up problem

    rf12_xfer(RF_SLEEP_MODE); // DC (disable clk pin), enable lbd

    // wait until RFM12B is out of power-up reset, this takes several *seconds*
    rf12_xfer(RF_TXREG_WRITE); // in case we're still in OOK mode
    while (digitalRead(RFM_IRQ) == 0)
        rf12_xfer(0x0000);

    rf12_xfer(0x80C7 | (RF12_433MHZ << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF 
    rf12_xfer(0xA640); // 868MHz 
    rf12_xfer(0xC606); // approx 49.2 Kbps, i.e. 10000/29/(1+6) Kbps
    rf12_xfer(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm 
    rf12_xfer(0xC2AC); // AL,!ml,DIG,DQD4 
    rf12_xfer(0xCA8B); // FIFO8,1-SYNC,!ff,DR 
    rf12_xfer(0xCE2D); // SYNC=2D; 
   
    rf12_xfer(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN 
    rf12_xfer(0x9850); // !mp,90kHz,MAX OUT 
    rf12_xfer(0xCC77); // OB1,OB0, LPX,!ddy,DDIT,BW0 
    rf12_xfer(0xE000); // NOT USE 
    rf12_xfer(0xC800); // NOT USE 
    rf12_xfer(0xC049); // 1.66MHz,3.1V 

    rxstate = TXIDLE;
    attachInterrupt(0, rf12_interrupt, LOW);
}