diff --git a/RFM69.py b/RFM69.py index 6cbe411..54d8d3b 100755 --- a/RFM69.py +++ b/RFM69.py @@ -247,6 +247,8 @@ def sendFrame(self, toAddress, buff, requestACK, sendACK): #wait for modeReady while (self.readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00: pass + # DIO0 is "Packet Sent" + self.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00) if (len(buff) > RF69_MAX_DATA_LEN): buff = buff[0:RF69_MAX_DATA_LEN] @@ -263,8 +265,12 @@ def sendFrame(self, toAddress, buff, requestACK, sendACK): self.DATASENT = False self.setMode(RF69_MODE_TX) - while (self.readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT) == 0x00: - pass + slept = 0 + while not self.DATASENT: + time.sleep(self.sendSleepTime) + slept += self.sendSleepTime + if slept > 1.0: + break self.setMode(RF69_MODE_RX) def interruptHandler(self, pin): @@ -391,3 +397,131 @@ def shutdown(self): self.setHighPower(False) self.sleep() GPIO.cleanup() + + # + # Sends data in a special manner (cf. https://lowpowerlab.com/forum/low-power-techniques/low-power-radio-wakeup/) + # Parameters: + # toAddress: nodeId of the recipient + # buff: data buffer to send + # burstDurationSec: duration of burst transmission in seconds + # (should match the setting on the receiver side) + def sendBurst(self, toAddress, buff, burstDurationSec = 1.0): + + self.setMode(RF69_MODE_STANDBY) + self.writeReg(REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_WHITENING | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON ) + self.writeReg(REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF) + self.writeReg(REG_SYNCVALUE1, 0x5A) + self.writeReg(REG_SYNCVALUE2, 0x5A) + self.writeReg(REG_FRFMSB, self.readReg(REG_FRFMSB) + 1) + self.writeReg(REG_FRFLSB, self.readReg(REG_FRFLSB)) + + #listenModeApplyHighSpeedSettings + self.writeReg(REG_BITRATEMSB, RF_BITRATEMSB_200000) + self.writeReg(REG_BITRATELSB, RF_BITRATELSB_200000) + self.writeReg(REG_FDEVMSB, RF_FDEVMSB_100000) + self.writeReg(REG_FDEVLSB, RF_FDEVLSB_100000) + self.writeReg(REG_RXBW, RF_RXBW_DCCFREQ_000 | RF_RXBW_MANT_20 | RF_RXBW_EXP_0 ) + + Duration = 1 + StartDuration = Duration + StartTime = time.time() + + while(Duration > 0): + + # DIO0 is "Packet Sent" + self.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00) + + if (len(buff) > RF69_MAX_DATA_LEN): + buff = buff[0:RF69_MAX_DATA_LEN] + + ack = 0x40 + + if isinstance(buff, basestring): + self.spi.xfer2([REG_FIFO | 0x80, len(buff) + 3, toAddress, self.address, ack] + [int(ord(i)) for i in list(buff)]) + else: + self.spi.xfer2([REG_FIFO | 0x80, len(buff) + 3, toAddress, self.address, ack] + buff) + + self.DATASENT = False + self.setMode(RF69_MODE_TX) + slept = 0 + while not self.DATASENT: + time.sleep(self.sendSleepTime) + slept += self.sendSleepTime + if slept > burstDurationSec: + break + + Duration = StartDuration - (time.time() - StartTime) + + self.setMode(RF69_MODE_STANDBY) + self.setFreqeuncy(self.freqBand) + self.resetToNormalMode() + + def resetToNormalMode(self): + + frfMSB = {RF69_315MHZ: RF_FRFMSB_315, RF69_433MHZ: RF_FRFMSB_433, + RF69_868MHZ: RF_FRFMSB_868, RF69_915MHZ: RF_FRFMSB_915} + frfMID = {RF69_315MHZ: RF_FRFMID_315, RF69_433MHZ: RF_FRFMID_433, + RF69_868MHZ: RF_FRFMID_868, RF69_915MHZ: RF_FRFMID_915} + frfLSB = {RF69_315MHZ: RF_FRFLSB_315, RF69_433MHZ: RF_FRFLSB_433, + RF69_868MHZ: RF_FRFLSB_868, RF69_915MHZ: RF_FRFLSB_915} + + self.CONFIG = { + 0x01: [REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY], + #no shaping + 0x02: [REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00], + #default:4.8 KBPS + 0x03: [REG_BITRATEMSB, RF_BITRATEMSB_55555], + 0x04: [REG_BITRATELSB, RF_BITRATELSB_55555], + #default:5khz, (FDEV + BitRate/2 <= 500Khz) + 0x05: [REG_FDEVMSB, RF_FDEVMSB_50000], + 0x06: [REG_FDEVLSB, RF_FDEVLSB_50000], + + 0x07: [REG_FRFMSB, frfMSB[self.freqBand]], + 0x08: [REG_FRFMID, frfMID[self.freqBand]], + 0x09: [REG_FRFLSB, frfLSB[self.freqBand]], + + # looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm + # +17dBm and +20dBm are possible on RFM69HW + # +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**) + # +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)** + # +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) + #0x11: [REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111], + #over current protection (default is 95mA) + #0x13: [REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95], + + # RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4khz) + #//(BitRate < 2 * RxBw) + 0x19: [REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2], + #for BR-19200: //* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, + #DIO0 is the only IRQ we're using + 0x25: [REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01], + #must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm + 0x29: [REG_RSSITHRESH, 220], + #/* 0x2d */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA + 0x2e: [REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0], + #attempt to make this compatible with sync1 byte of RFM12B lib + 0x2f: [REG_SYNCVALUE1, 0x2D], + #NETWORK ID + 0x30: [REG_SYNCVALUE2, self.networkID], + 0x37: [REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | + RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF], + #in variable length mode: the max frame size, not used in TX + 0x38: [REG_PAYLOADLENGTH, 66], + #* 0x39 */ { REG_NODEADRS, nodeID }, //turned off because we're not using address filtering + #TX on FIFO not empty + 0x3C: [REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE], + #RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) + 0x3d: [REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF], + #for BR-19200: //* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) + #* 0x6F */ { REG_TESTDAGC, RF_DAGC_CONTINUOUS }, // run DAGC continuously in RX mode + # run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0 + 0x6F: [REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0], + 0x00: [255, 0] + } + + #write config + for value in self.CONFIG.values(): + self.writeReg(value[0], value[1]) + + self.writeReg(REG_LNA, (self.readReg(REG_LNA) & ~0x3) | RF_LNA_GAINSELECT_AUTO) + self.setHighPower(self.isRFM69HW) diff --git a/wiring.fzz b/wiring.fzz new file mode 100644 index 0000000..a669c4b Binary files /dev/null and b/wiring.fzz differ