bool RH_RF24::init() { if (!RHSPIDriver::init()) return false; // Determine the interrupt number that corresponds to the interruptPin int interruptNumber = digitalPinToInterrupt(_interruptPin); if (interruptNumber == NOT_AN_INTERRUPT) return false; #ifdef RH_ATTACHINTERRUPT_TAKES_PIN_NUMBER interruptNumber = _interruptPin; #endif // Tell the low level SPI interface we will use SPI within this interrupt spiUsingInterrupt(interruptNumber); // Initialise the radio power_on_reset(); cmd_clear_all_interrupts(); // Get the device type and check it // This also tests whether we are really connected to a device uint8_t buf[8]; if (!command(RH_RF24_CMD_PART_INFO, 0, 0, buf, sizeof(buf))) return false; // SPI error? Not connected? _deviceType = (buf[1] << 8) | buf[2]; // Check PART to be either 0x4460, 0x4461, 0x4463, 0x4464 if (_deviceType != 0x4460 && _deviceType != 0x4461 && _deviceType != 0x4463 && _deviceType != 0x4464) return false; // Unknown radio type, or not connected // Here we use a configuration generated by the Silicon Labs Wireless Development Suite // #included above // We override a few things later that we ned to be sure of. configure(RF24_CONFIGURATION_DATA); // Add by Adrien van den Bossche <*****@*****.**> for Teensy // ARM M4 requires the below. else pin interrupt doesn't work properly. // On all other platforms, its innocuous, belt and braces pinMode(_interruptPin, INPUT); // Set up interrupt handler // Since there are a limited number of interrupt glue functions isr*() available, // we can only support a limited number of devices simultaneously // ON some devices, notably most Arduinos, the interrupt pin passed in is actuallt the // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping // yourself based on knwledge of what Arduino board you are running on. if (_myInterruptIndex == 0xff) { // First run, no interrupt allocated yet if (_interruptCount <= RH_RF24_NUM_INTERRUPTS) _myInterruptIndex = _interruptCount++; else return false; // Too many devices, not enough interrupt vectors } _deviceForInterrupt[_myInterruptIndex] = this; if (_myInterruptIndex == 0) attachInterrupt(interruptNumber, isr0, FALLING); else if (_myInterruptIndex == 1) attachInterrupt(interruptNumber, isr1, FALLING); else if (_myInterruptIndex == 2) attachInterrupt(interruptNumber, isr2, FALLING); else return false; // Too many devices, not enough interrupt vectors // Ensure we get the interrupts we need, irrespective of whats in the radio_config uint8_t int_ctl[] = {RH_RF24_MODEM_INT_STATUS_EN | RH_RF24_PH_INT_STATUS_EN, 0xff, 0xff, 0x00 }; set_properties(RH_RF24_PROPERTY_INT_CTL_ENABLE, int_ctl, sizeof(int_ctl)); // RSSI Latching should be configured in MODEM_RSSI_CONTROL in radio_config // PKT_TX_THRESHOLD and PKT_RX_THRESHOLD should be set to about 0x30 in radio_config // Configure important RH_RF24 registers // Here we set up the standard packet format for use by the RH_RF24 library: // We will use FIFO Mode, with automatic packet generation // We have 2 fields: // Field 1 contains only the (variable) length of field 2, with CRC // Field 2 contains the variable length payload and the CRC // Hmmm, having no CRC on field 1 and CRC on field 2 causes CRC errors when resetting after an odd // number of packets! Anyway its prob a good thing at the cost of some airtime. // Hmmm, enabling WHITEN stops it working! uint8_t pkt_config1[] = { 0x00 }; set_properties(RH_RF24_PROPERTY_PKT_CONFIG1, pkt_config1, sizeof(pkt_config1)); uint8_t pkt_len[] = { 0x02, 0x01, 0x00 }; set_properties(RH_RF24_PROPERTY_PKT_LEN, pkt_len, sizeof(pkt_len)); uint8_t pkt_field1[] = { 0x00, 0x01, 0x00, RH_RF24_FIELD_CONFIG_CRC_START | RH_RF24_FIELD_CONFIG_SEND_CRC | RH_RF24_FIELD_CONFIG_CHECK_CRC | RH_RF24_FIELD_CONFIG_CRC_ENABLE }; set_properties(RH_RF24_PROPERTY_PKT_FIELD_1_LENGTH_12_8, pkt_field1, sizeof(pkt_field1)); uint8_t pkt_field2[] = { 0x00, sizeof(_buf), 0x00, RH_RF24_FIELD_CONFIG_CRC_START | RH_RF24_FIELD_CONFIG_SEND_CRC | RH_RF24_FIELD_CONFIG_CHECK_CRC | RH_RF24_FIELD_CONFIG_CRC_ENABLE }; set_properties(RH_RF24_PROPERTY_PKT_FIELD_2_LENGTH_12_8, pkt_field2, sizeof(pkt_field2)); // Clear all other fields so they are never used, irrespective of the radio_config uint8_t pkt_fieldn[] = { 0x00, 0x00, 0x00, 0x00 }; set_properties(RH_RF24_PROPERTY_PKT_FIELD_3_LENGTH_12_8, pkt_fieldn, sizeof(pkt_fieldn)); set_properties(RH_RF24_PROPERTY_PKT_FIELD_4_LENGTH_12_8, pkt_fieldn, sizeof(pkt_fieldn)); set_properties(RH_RF24_PROPERTY_PKT_FIELD_5_LENGTH_12_8, pkt_fieldn, sizeof(pkt_fieldn)); // The following can be changed later by the user if necessary. // Set up default configuration setCRCPolynomial(CRC_16_IBM); uint8_t syncwords[] = { 0x2d, 0xd4 }; setSyncWords(syncwords, sizeof(syncwords)); // Same as RF22's // 3 would be sufficient, but this is the same as RF22's // actualy, 4 seems to work much better for some modulations setPreambleLength(4); // Default freq comes from the radio config file // About 2.4dBm on RFM24: setTxPower(0x10); return true; }
bool RH_RF95::init() { if (!RHSPIDriver::init()) return false; // Determine the interrupt number that corresponds to the interruptPin int interruptNumber = digitalPinToInterrupt(_interruptPin); if (interruptNumber == NOT_AN_INTERRUPT) return false; #ifdef RH_ATTACHINTERRUPT_TAKES_PIN_NUMBER interruptNumber = _interruptPin; #endif // Tell the low level SPI interface we will use SPI within this interrupt spiUsingInterrupt(interruptNumber); // No way to check the device type :-( // Set sleep mode, so we can also set LORA mode: spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE); delay(10); // Wait for sleep mode to take over from say, CAD // Check we are in sleep mode, with LORA set if (spiRead(RH_RF95_REG_01_OP_MODE) != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE)) { // Serial.println(spiRead(RH_RF95_REG_01_OP_MODE), HEX); return false; // No device present? } // Add by Adrien van den Bossche <*****@*****.**> for Teensy // ARM M4 requires the below. else pin interrupt doesn't work properly. // On all other platforms, its innocuous, belt and braces pinMode(_interruptPin, INPUT); // Set up interrupt handler // Since there are a limited number of interrupt glue functions isr*() available, // we can only support a limited number of devices simultaneously // ON some devices, notably most Arduinos, the interrupt pin passed in is actuallt the // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping // yourself based on knwledge of what Arduino board you are running on. if (_myInterruptIndex == 0xff) { // First run, no interrupt allocated yet if (_interruptCount <= RH_RF95_NUM_INTERRUPTS) _myInterruptIndex = _interruptCount++; else return false; // Too many devices, not enough interrupt vectors } _deviceForInterrupt[_myInterruptIndex] = this; if (_myInterruptIndex == 0) attachInterrupt(interruptNumber, isr0, RISING); else if (_myInterruptIndex == 1) attachInterrupt(interruptNumber, isr1, RISING); else if (_myInterruptIndex == 2) attachInterrupt(interruptNumber, isr2, RISING); else return false; // Too many devices, not enough interrupt vectors // Set up FIFO // We configure so that we can use the entire 256 byte FIFO for either receive // or transmit, but not both at the same time spiWrite(RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0); spiWrite(RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0); // Packet format is preamble + explicit-header + payload + crc // Explicit Header Mode // payload is TO + FROM + ID + FLAGS + message data // RX mode is implmented with RXCONTINUOUS // max message data length is 255 - 4 = 251 octets setModeIdle(); // Set up default configuration // No Sync Words in LORA mode. setModemConfig(Bw125Cr45Sf128); // Radio default // setModemConfig(Bw125Cr48Sf4096); // slow and reliable? setPreambleLength(8); // Default is 8 // An innocuous ISM frequency, same as RF22's setFrequency(434.0); // Lowish power setTxPower(13); return true; }
bool RH_RF69::init() { if (!RHSPIDriver::init()) return false; // Determine the interrupt number that corresponds to the interruptPin int interruptNumber = digitalPinToInterrupt(_interruptPin); if (interruptNumber == NOT_AN_INTERRUPT) return false; #ifdef RH_ATTACHINTERRUPT_TAKES_PIN_NUMBER interruptNumber = _interruptPin; #endif // Tell the low level SPI interface we will use SPI within this interrupt spiUsingInterrupt(interruptNumber); // Get the device type and check it // This also tests whether we are really connected to a device // My test devices return 0x24 _deviceType = spiRead(RH_RF69_REG_10_VERSION); if (_deviceType == 00 || _deviceType == 0xff) return false; // Add by Adrien van den Bossche <*****@*****.**> for Teensy // ARM M4 requires the below. else pin interrupt doesn't work properly. // On all other platforms, its innocuous, belt and braces pinMode(_interruptPin, INPUT); // Set up interrupt handler // Since there are a limited number of interrupt glue functions isr*() available, // we can only support a limited number of devices simultaneously // ON some devices, notably most Arduinos, the interrupt pin passed in is actuallt the // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping // yourself based on knwledge of what Arduino board you are running on. if (_myInterruptIndex == 0xff) { // First run, no interrupt allocated yet if (_interruptCount <= RH_RF69_NUM_INTERRUPTS) _myInterruptIndex = _interruptCount++; else return false; // Too many devices, not enough interrupt vectors } _deviceForInterrupt[_myInterruptIndex] = this; if (_myInterruptIndex == 0) attachInterrupt(interruptNumber, isr0, RISING); else if (_myInterruptIndex == 1) attachInterrupt(interruptNumber, isr1, RISING); else if (_myInterruptIndex == 2) attachInterrupt(interruptNumber, isr2, RISING); else return false; // Too many devices, not enough interrupt vectors setModeIdle(); // Configure important RH_RF69 registers // Here we set up the standard packet format for use by the RH_RF69 library: // 4 bytes preamble // 2 SYNC words 2d, d4 // 2 CRC CCITT octets computed on the header, length and data (this in the modem config data) // 0 to 60 bytes data // RSSI Threshold -114dBm // We dont use the RH_RF69s address filtering: instead we prepend our own headers to the beginning // of the RH_RF69 payload spiWrite(RH_RF69_REG_3C_FIFOTHRESH, RH_RF69_FIFOTHRESH_TXSTARTCONDITION_NOTEMPTY | 0x0f); // thresh 15 is default // RSSITHRESH is default // spiWrite(RH_RF69_REG_29_RSSITHRESH, 220); // -110 dbM // SYNCCONFIG is default. SyncSize is set later by setSyncWords() // spiWrite(RH_RF69_REG_2E_SYNCCONFIG, RH_RF69_SYNCCONFIG_SYNCON); // auto, tolerance 0 // PAYLOADLENGTH is default // spiWrite(RH_RF69_REG_38_PAYLOADLENGTH, RH_RF69_FIFO_SIZE); // max size only for RX // PACKETCONFIG 2 is default spiWrite(RH_RF69_REG_6F_TESTDAGC, RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAOFF); // If high power boost set previously, disable it spiWrite(RH_RF69_REG_5A_TESTPA1, RH_RF69_TESTPA1_NORMAL); spiWrite(RH_RF69_REG_5C_TESTPA2, RH_RF69_TESTPA2_NORMAL); // The following can be changed later by the user if necessary. // Set up default configuration uint8_t syncwords[] = { 0x2d, 0xd4 }; setSyncWords(syncwords, sizeof(syncwords)); // Same as RF22's // Reasonably fast and reliable default speed and modulation setModemConfig(GFSK_Rb250Fd250); // 3 would be sufficient, but this is the same as RF22's setPreambleLength(4); // An innocuous ISM frequency, same as RF22's setFrequency(434.0); // No encryption setEncryptionKey(NULL); // +13dBm, same as power-on default setTxPower(13); return true; }