/* @description reads the upper 8 bits of the status
 * register (the interrupt flags)
 */
static uint8_t rfm12_read_int_flags_inline(void) {
	#if !(RFM12_SPI_SOFTWARE)
		SS_ASSERT();
		SPDR = 0;
		while (!(SPSR & (1<<SPIF)));
		SS_RELEASE();
		return SPDR;
	#else
		SS_ASSERT();
		unsigned char x, d = d;
		PORT_MOSI &= ~(1<<BIT_MOSI);
		for (x = 0; x < 8; x++) {
			PORT_SCK |= (1<<BIT_SCK);
			d <<= 1;
			if (PIN_MISO & (1<<BIT_MISO)) {
				d |= 1;
			}
			PORT_SCK &= ~(1<<BIT_SCK);
		}
		SS_RELEASE();
		return d;
	#endif
}
//non-inlined version of rfm12_data
//warning: without the attribute, gcc will inline this even if -Os is set
static void __attribute__ ((noinline)) rfm12_data(uint16_t d) {
	SS_ASSERT();
	#if !(RFM12_SPI_SOFTWARE)
		SPDR = d >> 8;
		while (!(SPSR & (1<<SPIF)));

		SPDR = d & 0xff;
		while (!(SPSR & (1<<SPIF)));
	#else
		spi_data(d >> 8);
		spi_data(d & 0xff);
	#endif
	SS_RELEASE();
}
//non-inlined version of rfm12_read
//warning: without the attribute, gcc will inline this even if -Os is set
static uint16_t __attribute__ ((noinline)) rfm12_read(uint16_t c) {
	uint16_t retval;
	SS_ASSERT();

	#if !(RFM12_SPI_SOFTWARE)
		SPDR = c >> 8;
		while (!(SPSR & (1<<SPIF)));
		retval = SPDR << 8;
		SPDR = c & 0xff;
		while (!(SPSR & (1<<SPIF)));
		retval |= SPDR;
	#else
		retval = spi_data(c >> 8);
		retval <<= 8;
		retval |= spi_data(c & 0xff);
	#endif
	SS_RELEASE();
	return retval;
}
Exemple #4
0
/**This function takes care of all module initialization, including:
* - Setup of the used frequency band and external capacitor
* - Setting the exact frequency (channel)
* - Setting the transmission data rate
* - Configuring various module related rx parameters, including the amplification
* - Enabling the digital data filter
* - Enabling the use of the modules fifo, as well as enabling sync pattern detection
* - Configuring the automatic frequency correction
* - Setting the transmit power 
*
* This initialization function also sets up various library internal configuration structs and
* puts the module into receive mode before returning.
*
* \note Please note that the transmit power and receive amplification values are currently hard coded.
* Have a look into rfm12_hw.h for possible settings.
*/
void rfm12_init(void)
{
	RFM12_INT_OFF(); // in case rfm12_init is called twice, make sure rfm module does not interfere

	//initialize spi
	SS_RELEASE();
	DDR_SS |= (1<<BIT_SS);	
	spi_init();

	//enable internal data register and fifo
	//setup selected band
	rfm12_data(RFM12_CMD_CFG | RFM12_CFG_EL | RFM12_CFG_EF | RFM12_BASEBAND | RFM12_XTAL_12PF);
	
	//set power default state (usually disable clock output)
	//do not write the power register two times in a short time
	//as it seems to need some recovery
	rfm12_data(RFM12_CMD_PWRMGT | PWRMGT_DEFAULT);

	//set frequency
	rfm12_data(RFM12_CMD_FREQUENCY | RFM12_FREQUENCY_CALC(FREQ) );

	//set data rate
	rfm12_data(RFM12_CMD_DATARATE | DATARATE_VALUE );
	
	//set rx parameters: int-in/vdi-out pin is vdi-out,
	//Bandwith, LNA, RSSI
	rfm12_data(RFM12_CMD_RXCTRL | RFM12_RXCTRL_P16_VDI 
			| RFM12_RXCTRL_VDI_FAST | RFM12_RXCTRL_BW_400 | RFM12_RXCTRL_LNA_6 
			| RFM12_RXCTRL_RSSI_79 );	
	
	//automatic clock lock control(AL), digital Filter(!S),
	//Data quality detector value 3, slow clock recovery lock
	rfm12_data(RFM12_CMD_DATAFILTER | RFM12_DATAFILTER_AL | 3);
	
	//2 Byte Sync Pattern, Start fifo fill when sychron pattern received,
	//disable sensitive reset, Fifo filled interrupt at 8 bits
	rfm12_data(RFM12_CMD_FIFORESET | RFM12_FIFORESET_DR | (8<<4));

	//set AFC to automatic, (+4 or -3)*2.5kHz Limit, fine mode, active and enabled
	rfm12_data(RFM12_CMD_AFC | RFM12_AFC_AUTO_KEEP | RFM12_AFC_LIMIT_4
				| RFM12_AFC_FI | RFM12_AFC_OE | RFM12_AFC_EN);
	
	//set TX Power to -0dB, frequency shift = +-125kHz
	rfm12_data(RFM12_CMD_TXCONF | RFM12_TXCONF_POWER_0 | RFM12_TXCONF_FS_CALC(125000) );
	
	//disable low dutycycle mode
	rfm12_data(RFM12_CMD_DUTYCYCLE);
	
	//disable wakeup timer
	rfm12_data(RFM12_CMD_WAKEUP);

	//store the syncronization pattern to the transmission buffer
	//the sync pattern is used by the receiver to distinguish noise from real transmissions
	//the sync pattern is hardcoded into the receiver
	rf_tx_buffer.sync[0] = SYNC_MSB;
	rf_tx_buffer.sync[1] = SYNC_LSB;
	
	//if receive mode is not disabled (default)
	#if !(RFM12_TRANSMIT_ONLY)
		//init buffer pointers
		ctrl.rf_buffer_out = &rf_rx_buffers[0];
		ctrl.rf_buffer_in  = &rf_rx_buffers[0];
		//ctrl.buffer_in_num = 0;
		//ctrl.buffer_out_num = 0;
	#endif /* !(RFM12_TRANSMIT_ONLY) */
	
	//low battery detector feature initialization
	#if RFM12_LOW_BATT_DETECTOR
		ctrl.low_batt = RFM12_BATT_OKAY;
	#endif /* RFM12_LOW_BATT_DETECTOR */
	
	//enable rf receiver chain, if receiving is not disabled (default)
	//the magic is done via defines
	rfm12_data(RFM12_CMD_PWRMGT | PWRMGT_RECEIVE);
	
	//wakeup timer feature setup
	#if RFM12_USE_WAKEUP_TIMER
		//set power management shadow register to receiver chain enabled or disabled
		//the define correctly handles the transmit only mode
		ctrl.pwrmgt_shadow = (RFM12_CMD_PWRMGT | PWRMGT_RECEIVE);
	#endif /* RFM12_USE_WAKEUP_TIMER */
	
	//ASK receive mode feature initialization
	#if RFM12_RECEIVE_ASK
		adc_init();
	#endif

	//setup interrupt for falling edge trigger
	RFM12_INT_SETUP();
	
	//clear int flag
	rfm12_read(RFM12_CMD_STATUS);
	RFM12_INT_FLAG |= (1<<RFM12_FLAG_BIT);		
	
	//init receiver fifo, we now begin receiving.
	rfm12_data(CLEAR_FIFO);
	rfm12_data(ACCEPT_DATA);
	
	//activate the interrupt
	RFM12_INT_ON();	
}