From 2b609b9d02602a288d4e44558a62e2e273d27d12 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 18 Mar 2022 12:54:43 +0000 Subject: [PATCH] Inital commit --- .gitignore | 53 +------ main | Bin 0 -> 21208 bytes makefile | 5 + src/driver.cpp | 49 +++++++ src/driver.h | 20 +++ src/mrf24j.cpp | 351 +++++++++++++++++++++++++++++++++++++++++++++++ src/mrf24j.h | 250 +++++++++++++++++++++++++++++++++ test/rx/main.cpp | 67 +++++++++ test/tx/main.cpp | 83 +++++++++++ 9 files changed, 826 insertions(+), 52 deletions(-) create mode 100755 main create mode 100644 makefile create mode 100644 src/driver.cpp create mode 100644 src/driver.h create mode 100644 src/mrf24j.cpp create mode 100644 src/mrf24j.h create mode 100644 test/rx/main.cpp create mode 100644 test/tx/main.cpp diff --git a/.gitignore b/.gitignore index cd531cf..03515f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,54 +1,3 @@ -# ---> C -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj *.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 +*.bin *.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf - diff --git a/main b/main new file mode 100755 index 0000000000000000000000000000000000000000..74535a32ce61057b02083bfa02da9ff227540cbc GIT binary patch literal 21208 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 literal 0 HcmV?d00001 diff --git a/makefile b/makefile new file mode 100644 index 0000000..19bc1a5 --- /dev/null +++ b/makefile @@ -0,0 +1,5 @@ +all: build run +build: + g++ -Wall -pthread -o main test/${MODE}/main.cpp src/*.cpp -lpigpio -lrt +run: + sudo ./main \ No newline at end of file diff --git a/src/driver.cpp b/src/driver.cpp new file mode 100644 index 0000000..c6aafef --- /dev/null +++ b/src/driver.cpp @@ -0,0 +1,49 @@ +#include "driver.h" +#include + +namespace driver +{ + namespace { + Mrf24j *mrf; + int spi; + } + + void callback(int gpio, int level, uint32_t tick) { + mrf->interrupt_handler(); + mrf->check_flags(); + } + + void init(Mrf24j *mrf) { + + gpioInitialise(); + driver::mrf = mrf; + spi = spiOpen(0, 1000000, 0); + gpioSetMode(RESET, PI_OUTPUT); + gpioWrite(RESET, 1); + gpioSetMode(SPI_CS, PI_OUTPUT); + cs_high(); + gpioSetAlertFunc(INT, callback); + } + + uint8_t transfer(uint8_t data) { + char txbuff[1], rxbuff[1]; + txbuff[0] = data; + spiXfer(spi, txbuff, rxbuff, 1); + return rxbuff[0]; + } + void reset() { + gpioWrite(RESET , 0); + time_sleep(0.01); + gpioWrite(RESET, 1); + time_sleep(0.02); + } + + void wake() { + } + + // INTERRUPT { + // mrf->interrupt_handler(); // mrf24 object interrupt routine + // mrf->check_flags(); + // } +} + diff --git a/src/driver.h b/src/driver.h new file mode 100644 index 0000000..eadaf96 --- /dev/null +++ b/src/driver.h @@ -0,0 +1,20 @@ +#pragma once + +#include "mrf24j.h" +#include + +#define RESET 24 //24 +#define SPI_CS 8 //8 +#define INT 25 //25 + +namespace driver +{ + void init(Mrf24j *mrf); + uint8_t transfer(uint8_t data); + + inline void cs_low() {gpioWrite(SPI_CS, 0);} + + inline void cs_high() {gpioWrite(SPI_CS, 1);} + void wake(); + void reset(); +} // namespace spi diff --git a/src/mrf24j.cpp b/src/mrf24j.cpp new file mode 100644 index 0000000..f6709b7 --- /dev/null +++ b/src/mrf24j.cpp @@ -0,0 +1,351 @@ +/** + * mrf24j.cpp, Karl Palsson, 2011, karlp@tweak.net.au + * modified bsd license / apache license + */ + +#include "mrf24j.h" +#include "driver.h" +#include +#include + + +// aMaxPHYPacketSize = 127, from the 802.15.4-2006 standard. +static uint8_t rx_buf[127]; + +// essential for obtaining the data frame only +// bytes_MHR = 2 Frame control + 1 sequence number + 2 panid + 2 shortAddr Destination + 2 shortAddr Source +static int bytes_MHR = 9; +static int bytes_FCS = 2; // FCS length = 2 +static int bytes_nodata = bytes_MHR + bytes_FCS; // no_data bytes in PHY payload, header length + FCS + +static int ignoreBytes = 0; // bytes to ignore, some modules behaviour. + +static bool bufPHY = false; // flag to buffer all bytes in PHY Payload, or not + +volatile uint8_t flag_got_rx; +volatile uint8_t flag_got_tx; + +static rx_info_t rx_info; +static tx_info_t tx_info; + + +/** + * Constructor MRF24J Object. + */ +Mrf24j::Mrf24j() { + driver::init(this); +} + +void Mrf24j::reset(void) { + driver::reset(); +} +void Mrf24j::handlers(void (*rx_handler)(void), void (*tx_handler)(void)) { + this->rx_handler = rx_handler; + this->tx_handler = tx_handler; + +} + +byte Mrf24j::read_short(byte address) { + driver::cs_low(); + // 0 top for short addressing, 0 bottom for read + driver::transfer(address<<1 & 0b01111110); + byte ret = driver::transfer(0x00); + driver::cs_high(); + return ret; +} + +byte Mrf24j::read_long(word address) { + driver::cs_low(); + byte ahigh = address >> 3; + byte alow = address << 5; + driver::transfer(0x80 | ahigh); // high bit for long + driver::transfer(alow); + byte ret = driver::transfer(0); + driver::cs_high(); + return ret; +} + + +void Mrf24j::write_short(byte address, byte data) { + driver::cs_low(); + // 0 for top short address, 1 bottom for write + driver::transfer((address<<1 & 0b01111110) | 0x01); + driver::transfer(data); + driver::cs_high(); +} + +void Mrf24j::write_long(word address, byte data) { + driver::cs_low(); + byte ahigh = address >> 3; + byte alow = address << 5; + driver::transfer(0x80 | ahigh); // high bit for long + driver::transfer(alow | 0x10); // last bit for write + driver::transfer(data); + driver::cs_high(); +} + +word Mrf24j::get_pan(void) { + byte panh = read_short(MRF_PANIDH); + return panh << 8 | read_short(MRF_PANIDL); +} + +void Mrf24j::set_pan(word panid) { + write_short(MRF_PANIDH, panid >> 8); + write_short(MRF_PANIDL, panid & 0xff); +} + +void Mrf24j::address16_write(word address16) { + write_short(MRF_SADRH, address16 >> 8); + write_short(MRF_SADRL, address16 & 0xff); +} + +word Mrf24j::address16_read(void) { + byte a16h = read_short(MRF_SADRH); + return a16h << 8 | read_short(MRF_SADRL); +} + + +void Mrf24j::send_str(word dest16, char * data) { + byte len = strlen(data); // get the length of the char* array + send(dest16, data, len); +} + +/** + * Simple send 16, with acks, not much of anything.. assumes src16 and local pan only. + * @param data + */ +void Mrf24j::send(word dest16, char * data, int len) { + int i = 0; + write_long(i++, bytes_MHR); // header length + // +ignoreBytes is because some module seems to ignore 2 bytes after the header?!. + // default: ignoreBytes = 0; + write_long(i++, bytes_MHR+ignoreBytes+len); + + // 0 | pan compression | ack | no security | no data pending | data frame[3 bits] + write_long(i++, 0b01100001); // first byte of Frame Control + // 16 bit source, 802.15.4 (2003), 16 bit dest, + write_long(i++, 0b10001000); // second byte of frame control + write_long(i++, 1); // sequence number 1 + + word panid = get_pan(); + + write_long(i++, panid & 0xff); // dest panid + write_long(i++, panid >> 8); + write_long(i++, dest16 & 0xff); // dest16 low + write_long(i++, dest16 >> 8); // dest16 high + + word src16 = address16_read(); + write_long(i++, src16 & 0xff); // src16 low + write_long(i++, src16 >> 8); // src16 high + + // All testing seems to indicate that the next two bytes are ignored. + //2 bytes on FCS appended by TXMAC + i+=ignoreBytes; + for (int q = 0; q < len; q++) { + write_long(i++, data[q]); + } + // ack on, and go! + write_short(MRF_TXNCON, (1<> 6; + tx_info.channel_busy = (tmp & (1 << CCAFAIL)); + } +} + + +/** + * Call this function periodically, it will invoke your nominated handlers + */ +void Mrf24j::check_flags(){ + // TODO - we could check whether the flags are > 1 here, indicating data was lost? + if (flag_got_rx) { + flag_got_rx = 0; + this->rx_handler(); + } + if (flag_got_tx) { + flag_got_tx = 0; + this->tx_handler(); + } +} + +/** + * Set RX mode to promiscuous, or normal + */ +void Mrf24j::set_promiscuous(boolean enabled) { + if (enabled) { + write_short(MRF_RXMCR, 0x01); + } else { + write_short(MRF_RXMCR, 0x00); + } +} + +rx_info_t * Mrf24j::get_rxinfo(void) { + return &rx_info; +} + +tx_info_t * Mrf24j::get_txinfo(void) { + return &tx_info; +} + +uint8_t * Mrf24j::get_rxbuf(void) { + return rx_buf; +} + +int Mrf24j::rx_datalength(void) { + return rx_info.frame_length - bytes_nodata; +} + +void Mrf24j::set_ignoreBytes(int ib) { + // some modules behaviour + ignoreBytes = ib; +} + +/** + * Set bufPHY flag to buffer all bytes in PHY Payload, or not + */ +void Mrf24j::set_bufferPHY(boolean bp) { + bufPHY = bp; +} + +boolean Mrf24j::get_bufferPHY(void) { + return bufPHY; +} + +/** + * Set PA/LNA external control + */ +void Mrf24j::set_palna(boolean enabled) { + if (enabled) { + write_long(MRF_TESTMODE, 0x07); // Enable PA/LNA on MRF24J40MB module. + }else{ + write_long(MRF_TESTMODE, 0x00); // Disable PA/LNA on MRF24J40MB module. + } +} + +void Mrf24j::rx_flush(void) { + write_short(MRF_RXFLUSH, 0x01); +} + +void Mrf24j::rx_disable(void) { + write_short(MRF_BBREG1, 0x04); // RXDECINV - disable receiver +} + +void Mrf24j::rx_enable(void) { + write_short(MRF_BBREG1, 0x00); // RXDECINV - enable receiver +} + +void Mrf24j::enable_wake() { + write_short(MRF_RXFLUSH, 0x60); // Enable WAKE pin and set polarity to active-high + write_short(MRF_WAKECON, 0x80); // Enable Immediate Wake-up mode +} + +void Mrf24j::sleep() { + write_short(MRF_SOFTRST, 0x04); // Perform a Power Management Reset + write_short(MRF_SLPACK, 0x80); // Put MRF24J40 to Sleep immediately +} + +void Mrf24j::wake() { + driver::wake(); + write_short(MRF_RFCTL, 0x04); // RF State Machine reset + write_short(MRF_RFCTL, 0x00); + gpioSleep(0, 0 ,2000); // Delay 2 ms to allow 20 MHz main oscillator time to stabilize before transmitting or receiving. +} + +void Mrf24j::turbo() { + write_short(MRF_BBREG0, 0x01); + write_short(MRF_BBREG3, (1<<5)|(1<<4)); + write_short(MRF_BBREG4, (1<<6)); + write_short(MRF_SOFTRST, (1<<1)); +} + +void Mrf24j::set_power(byte level) { + write_short(MRF_RFCON3, level); +} \ No newline at end of file diff --git a/src/mrf24j.h b/src/mrf24j.h new file mode 100644 index 0000000..2c8f71e --- /dev/null +++ b/src/mrf24j.h @@ -0,0 +1,250 @@ +/* + * File: mrf24j.h + * copyright Karl Palsson, karlp@tweak.net.au, 2011 + * modified BSD License / apache license + */ +typedef unsigned char uint8_t; + +typedef unsigned char byte; +typedef unsigned int word; +typedef bool boolean; + +#ifndef LIB_MRF24J_H +#define LIB_MRF24J_H + +#define MRF_RXMCR 0x00 +#define MRF_PANIDL 0x01 +#define MRF_PANIDH 0x02 +#define MRF_SADRL 0x03 +#define MRF_SADRH 0x04 +#define MRF_EADR0 0x05 +#define MRF_EADR1 0x06 +#define MRF_EADR2 0x07 +#define MRF_EADR3 0x08 +#define MRF_EADR4 0x09 +#define MRF_EADR5 0x0A +#define MRF_EADR6 0x0B +#define MRF_EADR7 0x0C +#define MRF_RXFLUSH 0x0D +//#define MRF_Reserved 0x0E +//#define MRF_Reserved 0x0F +#define MRF_ORDER 0x10 +#define MRF_TXMCR 0x11 +#define MRF_ACKTMOUT 0x12 +#define MRF_ESLOTG1 0x13 +#define MRF_SYMTICKL 0x14 +#define MRF_SYMTICKH 0x15 +#define MRF_PACON0 0x16 +#define MRF_PACON1 0x17 +#define MRF_PACON2 0x18 +//#define MRF_Reserved 0x19 +#define MRF_TXBCON0 0x1A + +// TXNCON: TRANSMIT NORMAL FIFO CONTROL REGISTER (ADDRESS: 0x1B) +#define MRF_TXNCON 0x1B +#define MRF_TXNTRIG 0 +#define MRF_TXNSECEN 1 +#define MRF_TXNACKREQ 2 +#define MRF_INDIRECT 3 +#define MRF_FPSTAT 4 + +#define MRF_TXG1CON 0x1C +#define MRF_TXG2CON 0x1D +#define MRF_ESLOTG23 0x1E +#define MRF_ESLOTG45 0x1F +#define MRF_ESLOTG67 0x20 +#define MRF_TXPEND 0x21 +#define MRF_WAKECON 0x22 +#define MRF_FRMOFFSET 0x23 +// TXSTAT: TX MAC STATUS REGISTER (ADDRESS: 0x24) +#define MRF_TXSTAT 0x24 +#define TXNRETRY1 7 +#define TXNRETRY0 6 +#define CCAFAIL 5 +#define TXG2FNT 4 +#define TXG1FNT 3 +#define TXG2STAT 2 +#define TXG1STAT 1 +#define TXNSTAT 0 + +#define MRF_TXBCON1 0x25 +#define MRF_GATECLK 0x26 +#define MRF_TXTIME 0x27 +#define MRF_HSYMTMRL 0x28 +#define MRF_HSYMTMRH 0x29 +#define MRF_SOFTRST 0x2A +//#define MRF_Reserved 0x2B +#define MRF_SECCON0 0x2C +#define MRF_SECCON1 0x2D +#define MRF_TXSTBL 0x2E +//#define MRF_Reserved 0x2F +#define MRF_RXSR 0x30 +#define MRF_INTSTAT 0x31 +#define MRF_INTCON 0x32 +#define MRF_GPIO 0x33 +#define MRF_TRISGPIO 0x34 +#define MRF_SLPACK 0x35 +#define MRF_RFCTL 0x36 +#define MRF_SECCR2 0x37 +#define MRF_BBREG0 0x38 +#define MRF_BBREG1 0x39 +#define MRF_BBREG2 0x3A +#define MRF_BBREG3 0x3B +#define MRF_BBREG4 0x3C +//#define MRF_Reserved 0x3D +#define MRF_BBREG6 0x3E +#define MRF_CCAEDTH 0x3F + +#define MRF_RFCON0 0x200 +#define MRF_RFCON1 0x201 +#define MRF_RFCON2 0x202 +#define MRF_RFCON3 0x203 +#define MRF_RFCON5 0x205 +#define MRF_RFCON6 0x206 +#define MRF_RFCON7 0x207 +#define MRF_RFCON8 0x208 +#define MRF_SLPCAL0 0x209 +#define MRF_SLPCAL1 0x20A +#define MRF_SLPCAL2 0x20B +#define MRF_RSSI 0x210 +#define MRF_SLPCON0 0x211 +#define MRF_SLPCON1 0x220 +#define MRF_WAKETIMEL 0x222 +#define MRF_WAKETIMEH 0x223 +#define MRF_REMCNTL 0x224 +#define MRF_REMCNTH 0x225 +#define MRF_MAINCNT0 0x226 +#define MRF_MAINCNT1 0x227 +#define MRF_MAINCNT2 0x228 +#define MRF_MAINCNT3 0x229 +#define MRF_TESTMODE 0x22F +#define MRF_ASSOEADR1 0x231 +#define MRF_ASSOEADR2 0x232 +#define MRF_ASSOEADR3 0x233 +#define MRF_ASSOEADR4 0x234 +#define MRF_ASSOEADR5 0x235 +#define MRF_ASSOEADR6 0x236 +#define MRF_ASSOEADR7 0x237 +#define MRF_ASSOSADR0 0x238 +#define MRF_ASSOSADR1 0x239 +#define MRF_UPNONCE0 0x240 +#define MRF_UPNONCE1 0x241 +#define MRF_UPNONCE2 0x242 +#define MRF_UPNONCE3 0x243 +#define MRF_UPNONCE4 0x244 +#define MRF_UPNONCE5 0x245 +#define MRF_UPNONCE6 0x246 +#define MRF_UPNONCE7 0x247 +#define MRF_UPNONCE8 0x248 +#define MRF_UPNONCE9 0x249 +#define MRF_UPNONCE10 0x24A +#define MRF_UPNONCE11 0x24B +#define MRF_UPNONCE12 0x24C + +#define MRF_I_RXIF 0b00001000 +#define MRF_I_TXNIF 0b00000001 + +#define MRF_S_WAKEPOL (1<<6) +#define MRF_S_PAKEPAD (1<<5) +#define MRF_S_IMMWAKE (1<<8) +#define MRF_S_SLPACK (1<<7) +#define MRF_S_RFRST (1<<2) + + + + +typedef struct _rx_info_t{ + uint8_t frame_length; + uint8_t rx_data[116]; //max data length = (127 aMaxPHYPacketSize - 2 Frame control - 1 sequence number - 2 panid - 2 shortAddr Destination - 2 shortAddr Source - 2 FCS) + uint8_t lqi; + uint8_t rssi; +} rx_info_t; + +/** + * Based on the TXSTAT register, but "better" + */ +typedef struct _tx_info_t{ + uint8_t tx_ok:1; + uint8_t retries:2; + uint8_t channel_busy:1; +} tx_info_t; + +class Mrf24j +{ + public: + Mrf24j(); + void reset(void); + void init(void); + void handlers(void (*rx_handler)(void), void (*tx_handler)(void)); + + byte read_short(byte address); + byte read_long(word address); + + void write_short(byte address, byte data); + void write_long(word address, byte data); + + word get_pan(void); + void set_pan(word panid); + + void address16_write(word address16); + word address16_read(void); + + void set_interrupts(void); + + void set_promiscuous(boolean enabled); + + /** + * Set the channel, using 802.15.4 channel numbers (11..26) + */ + void set_channel(byte channel); + + void rx_enable(void); + void rx_disable(void); + + /** If you want to throw away rx data */ + void rx_flush(void); + + rx_info_t * get_rxinfo(void); + + tx_info_t * get_txinfo(void); + + uint8_t * get_rxbuf(void); + + int rx_datalength(void); + + void set_ignoreBytes(int ib); + + /** + * Set bufPHY flag to buffer all bytes in PHY Payload, or not + */ + void set_bufferPHY(boolean bp); + + boolean get_bufferPHY(void); + + /** + * Set PA/LNA external control + */ + void set_palna(boolean enabled); + + void send(word dest16, char * data, int len); + void send_str(word dest16, char * data); + + void interrupt_handler(void); + + void check_flags(); + + void enable_wake(); + void sleep(); + void wake(); + void turbo(); + void set_power(byte level); + + private: + int _pin_reset; + int _pin_cs; + int _pin_int; + void (*rx_handler)(void); + void (*tx_handler)(void); +}; + +#endif /* LIB_MRF24J_H */ diff --git a/test/rx/main.cpp b/test/rx/main.cpp new file mode 100644 index 0000000..726b319 --- /dev/null +++ b/test/rx/main.cpp @@ -0,0 +1,67 @@ +/** + * Example code for using a microchip mrf24j40 module to send and receive + * packets using plain 802.15.4 + * Requirements: 3 pins for spi, 3 pins for reset, chip select and interrupt + * notifications + * This example file is considered to be in the public domain + * Originally written by Karl Palsson, karlp@tweak.net.au, March 2011 + */ +#define F_CPU 8000000UL +#include "../../src/mrf24j.h" +#include +#include + +Mrf24j mrf; + +void handle_rx(); +void handle_tx(); + +int main() { + mrf.reset(); + mrf.init(); + + mrf.set_pan(0xcafe); + mrf.set_bufferPHY(true); + // This is _our_ address + mrf.address16_write(0x4202); + mrf.handlers(&handle_rx, &handle_tx); + printf("Pan id: %x\n\r", mrf.get_pan()); + //mrf.turbo(); + + printf("Started"); + while(1) { + printf("Hello\n\r"); + time_sleep(2); + + } +} + + + +void handle_rx() { + printf("------------------------------------------------------\n\r"); + printf("received a packet %i bytes long\n\r", mrf.get_rxinfo()->frame_length); + + if(mrf.get_bufferPHY()){ + printf("Packet data (PHY Payload): "); + for (int i = 0; i < mrf.get_rxinfo()->frame_length; i++) { + printf("%x", mrf.get_rxbuf()[i]); + } + } + + printf("\r\nASCII data (relevant data): "); + for (int i = 0; i < mrf.rx_datalength(); i++) { + putchar(mrf.get_rxinfo()->rx_data[i]); + } + + printf("LQI/RSSI="); + printf("%i/%i\n\r", mrf.get_rxinfo()->lqi, mrf.get_rxinfo()->rssi); +} + +void handle_tx() { + if (mrf.get_txinfo()->tx_ok) { + printf("TX went ok, got ack\n\r"); + } else { + printf("TX failed after %i retries\n\n\r", mrf.get_txinfo()->retries); + } +} diff --git a/test/tx/main.cpp b/test/tx/main.cpp new file mode 100644 index 0000000..0bf1f35 --- /dev/null +++ b/test/tx/main.cpp @@ -0,0 +1,83 @@ +/** + * Example code for using a microchip mrf24j40 module to send and receive + * packets using plain 802.15.4 + * Requirements: 3 pins for spi, 3 pins for reset, chip select and interrupt + * notifications + * This example file is considered to be in the public domain + * Originally written by Karl Palsson, karlp@tweak.net.au, March 2011 + */ + +#define F_CPU 8000000UL +#include "../../src/mrf24j.h" +#include "../../src/driver.h" +#include +#include + + +Mrf24j mrf; +int i = 0; + +void handle_rx(); +void handle_tx(); + +int main() { + + mrf.reset(); + mrf.init(); + time_sleep(1); + + mrf.set_pan(0xcafe); + // This is _our_ address + mrf.address16_write(0x4201); + mrf.handlers(&handle_rx, &handle_tx); + printf("Pan id: %x\n\r", mrf.get_pan()); + //mrf.enable_wake(); + //mrf.set_bufferPHY(true); + //mrf.turbo(); + //mrf.set_power(0b1100000); + //mrf.sleep(); + + printf("Started\n\r"); + + char tmp[20]; + while(1) { + printf("txxxing... %i\n\r", i++); + //mrf.wake(); + + sprintf(tmp,"Received %i\n\r", i); + mrf.send_str(0x4202, tmp); + + time_sleep(2); + } +} + + + +void handle_rx() { + printf("received a packet %i bytes long\n\r", mrf.get_rxinfo()->frame_length); + + if(mrf.get_bufferPHY()){ + printf("Packet data (PHY Payload):\n\r"); + for (int i = 0; i < mrf.get_rxinfo()->frame_length; i++) { + printf("%i", mrf.get_rxbuf()[i]); + } + } + + // printf("\r\nASCII data (relevant data):\n\r"); + // for (int i = 0; i < mrf.rx_datalength(); i++) { + // usart::put(mrf.get_rxinfo()->rx_data[i]); + // } + + printf("\r\nLQI/RSSI="); + printf("%i/%i\n\r", mrf.get_rxinfo()->lqi, mrf.get_rxinfo()->rssi); +} + +void handle_tx() { + if (mrf.get_txinfo()->tx_ok) { + printf("TX went ok, got ack %i\n\r", i); + } else { + printf("TX failed after %i retries\n\n\r", mrf.get_txinfo()->retries); + } + printf("Sleeping\n\r"); + //mrf.sleep(); +}