/* @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; }
/**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(); }