From 0a48d7b3c7de1231afae0ccb306f74b04292839c Mon Sep 17 00:00:00 2001 From: Jimmy <me@jimmy.nz> Date: Fri, 21 Aug 2020 10:27:08 +1200 Subject: [PATCH] It works --- .vscode/c_cpp_properties.json | 20 +++ .vscode/settings.json | 3 + lib/mrf24j.cpp | 318 ++++++++++++++++++++++++++++++++++ lib/mrf24j.h | 238 +++++++++++++++++++++++++ lib/spi.cpp | 35 ++++ lib/spi.h | 33 ++++ lib/usart.cpp | 50 ++++++ lib/usart.h | 14 ++ rx/bin/main.bin | Bin 0 -> 33348 bytes rx/bin/main.elf | Bin 0 -> 33348 bytes rx/bin/main.hex | 234 +++++++++++++++++++++++++ rx/makefile | 25 +++ rx/src/main.cpp | 83 +++++++++ rx/term.py | 11 ++ tx/bin/main.bin | Bin 0 -> 32908 bytes tx/bin/main.elf | Bin 0 -> 32908 bytes tx/bin/main.hex | 228 ++++++++++++++++++++++++ tx/makefile | 25 +++ tx/src/main.cpp | 80 +++++++++ tx/term.py | 11 ++ 20 files changed, 1408 insertions(+) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 lib/mrf24j.cpp create mode 100644 lib/mrf24j.h create mode 100644 lib/spi.cpp create mode 100644 lib/spi.h create mode 100644 lib/usart.cpp create mode 100644 lib/usart.h create mode 100644 rx/bin/main.bin create mode 100644 rx/bin/main.elf create mode 100644 rx/bin/main.hex create mode 100644 rx/makefile create mode 100644 rx/src/main.cpp create mode 100644 rx/term.py create mode 100644 tx/bin/main.bin create mode 100644 tx/bin/main.elf create mode 100644 tx/bin/main.hex create mode 100644 tx/makefile create mode 100644 tx/src/main.cpp create mode 100644 tx/term.py diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..b57f039 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,20 @@ +{ + "configurations": [ + { + "name": "linux", + "includePath": [ + "${workspaceFolder}/**", + "/usr/lib/avr/include/" + ], + "defines": [ + "__AVR_ATmega32__", + "F_CPU 8000000" + ], + "compilerPath": "/usr/bin/avr-g++", + "cStandard": "gnu11", + "cppStandard": "gnu++14", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3b66410 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} \ No newline at end of file diff --git a/lib/mrf24j.cpp b/lib/mrf24j.cpp new file mode 100644 index 0000000..c3bf419 --- /dev/null +++ b/lib/mrf24j.cpp @@ -0,0 +1,318 @@ +/** + * mrf24j.cpp, Karl Palsson, 2011, karlp@tweak.net.au + * modified bsd license / apache license + */ + +#include "mrf24j.h" +#include <avr/io.h> +#include <util/delay.h> +#include <string.h> +#include <avr/interrupt.h> +#include "spi.h" + + +// 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; + + +void Mrf24j::reset(void) { + RESET_PORT &= ~(1<<RESET_PIN); + _delay_ms(10); // just my gut + RESET_PORT |= (1<<RESET_PIN); + _delay_ms(20); // from manual +} + +byte Mrf24j::read_short(byte address) { + spi::cs_low(); + //spi::cs_low(); + // 0 top for short addressing, 0 bottom for read + //spi::transfer(address<<1 & 0b01111110); + spi::transfer(address<<1 & 0b01111110); + byte ret = spi::transfer(0x00); + spi::cs_high(); + spi::cs_high(); + return ret; +} + +byte Mrf24j::read_long(word address) { + spi::cs_low(); + byte ahigh = address >> 3; + byte alow = address << 5; + spi::transfer(0x80 | ahigh); // high bit for long + spi::transfer(alow); + byte ret = spi::transfer(0); + spi::cs_high(); + return ret; +} + + +void Mrf24j::write_short(byte address, byte data) { + spi::cs_low(); + // 0 for top short address, 1 bottom for write + spi::transfer((address<<1 & 0b01111110) | 0x01); + spi::transfer(data); + spi::cs_high(); +} + +void Mrf24j::write_long(word address, byte data) { + spi::cs_low(); + byte ahigh = address >> 3; + byte alow = address << 5; + spi::transfer(0x80 | ahigh); // high bit for long + spi::transfer(alow | 0x10); // last bit for write + spi::transfer(data); + spi::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); +} + +/** + * Simple send 16, with acks, not much of anything.. assumes src16 and local pan only. + * @param data + */ +void Mrf24j::send16(word dest16, char * data) { + byte len = strlen(data); // get the length of the char* array + 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<<MRF_TXNACKREQ | 1<<MRF_TXNTRIG)); +} + +void Mrf24j::set_interrupts(void) { + // interrupts for rx and tx normal complete + write_short(MRF_INTCON, 0b11110110); +} + +/** use the 802.15.4 channel numbers.. + */ +void Mrf24j::set_channel(byte channel) { + write_long(MRF_RFCON0, (((channel - 11) << 4) | 0x03)); +} + +void Mrf24j::init(void) { + RESET_DDR |= (1<<RESET_PIN); + /* + // Seems a bit ridiculous when I use reset pin anyway + write_short(MRF_SOFTRST, 0x7); // from manual + while (read_short(MRF_SOFTRST) & 0x7 != 0) { + ; // wait for soft reset to finish + } + */ + write_short(MRF_PACON2, 0x98); // – Initialize FIFOEN = 1 and TXONTS = 0x6. + write_short(MRF_TXSTBL, 0x95); // – Initialize RFSTBL = 0x9. + + write_long(MRF_RFCON0, 0x03); // – Initialize RFOPT = 0x03. + write_long(MRF_RFCON1, 0x01); // – Initialize VCOOPT = 0x02. + write_long(MRF_RFCON2, 0x80); // – Enable PLL (PLLEN = 1). + write_long(MRF_RFCON6, 0x90); // – Initialize TXFIL = 1 and 20MRECVR = 1. + write_long(MRF_RFCON7, 0x80); // – Initialize SLPCLKSEL = 0x2 (100 kHz Internal oscillator). + write_long(MRF_RFCON8, 0x10); // – Initialize RFVCO = 1. + write_long(MRF_SLPCON1, 0x21); // – Initialize CLKOUTEN = 1 and SLPCLKDIV = 0x01. + + // Configuration for nonbeacon-enabled devices (see Section 3.8 “Beacon-Enabled and + // Nonbeacon-Enabled Networks”): + write_short(MRF_BBREG2, 0x80); // Set CCA mode to ED + write_short(MRF_CCAEDTH, 0x60); // – Set CCA ED threshold. + write_short(MRF_BBREG6, 0x40); // – Set appended RSSI value to RXFIFO. + set_interrupts(); + set_channel(12); + // max power is by default.. just leave it... + // Set transmitter power - See “REGISTER 2-62: RF CONTROL 3 REGISTER (ADDRESS: 0x203)”. + write_short(MRF_RFCTL, 0x04); // – Reset RF state machine. + write_short(MRF_RFCTL, 0x00); // part 2 + _delay_ms(1); // delay at least 192usec +} + +/** + * Call this from within an interrupt handler connected to the MRFs output + * interrupt pin. It handles reading in any data from the module, and letting it + * continue working. + * Only the most recent data is ever kept. + */ +void Mrf24j::interrupt_handler(void) { + uint8_t last_interrupt = read_short(MRF_INTSTAT); + if (last_interrupt & MRF_I_RXIF) { + flag_got_rx++; + // read out the packet data... + cli(); + rx_disable(); + // read start of rxfifo for, has 2 bytes more added by FCS. frame_length = m + n + 2 + uint8_t frame_length = read_long(0x300); + + // buffer all bytes in PHY Payload + if(bufPHY){ + int rb_ptr = 0; + for (int i = 0; i < frame_length; i++) { // from 0x301 to (0x301 + frame_length -1) + rx_buf[rb_ptr++] = read_long(0x301 + i); + } + } + + // buffer data bytes + int rd_ptr = 0; + // from (0x301 + bytes_MHR) to (0x301 + frame_length - bytes_nodata - 1) + for (int i = 0; i < rx_datalength(); i++) { + rx_info.rx_data[rd_ptr++] = read_long(0x301 + bytes_MHR + i); + } + + rx_info.frame_length = frame_length; + // same as datasheet 0x301 + (m + n + 2) <-- frame_length + rx_info.lqi = read_long(0x301 + frame_length); + // same as datasheet 0x301 + (m + n + 3) <-- frame_length + 1 + rx_info.rssi = read_long(0x301 + frame_length + 1); + + rx_enable(); + sei(); + } + if (last_interrupt & MRF_I_TXNIF) { + flag_got_tx++; + uint8_t tmp = read_short(MRF_TXSTAT); + // 1 means it failed, we want 1 to mean it worked. + tx_info.tx_ok = !(tmp & ~(1 << TXNSTAT)); + tx_info.retries = tmp >> 6; + tx_info.channel_busy = (tmp & (1 << CCAFAIL)); + } +} + + +/** + * Call this function periodically, it will invoke your nominated handlers + */ +void Mrf24j::check_flags(void (*rx_handler)(void), void (*tx_handler)(void)){ + // TODO - we could check whether the flags are > 1 here, indicating data was lost? + if (flag_got_rx) { + flag_got_rx = 0; + rx_handler(); + } + if (flag_got_tx) { + flag_got_tx = 0; + 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 +} + diff --git a/lib/mrf24j.h b/lib/mrf24j.h new file mode 100644 index 0000000..d6ba63f --- /dev/null +++ b/lib/mrf24j.h @@ -0,0 +1,238 @@ +/* + * File: mrf24j.h + * copyright Karl Palsson, karlp@tweak.net.au, 2011 + * modified BSD License / apache license + */ + +#pragma once + +#include <avr/io.h> + +#define byte uint8_t +#define boolean bool +#define word uint16_t + + + +#define RESET_DDR DDRB +#define RESET_PORT PORTB +#define RESET_PIN PB0 + +#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 + +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: + void reset(void); + void init(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 send16(word dest16, char * data); + + void interrupt_handler(void); + + void check_flags(void (*rx_handler)(void), void (*tx_handler)(void)); + + private: + int _pin_reset; + int _pin_cs; + int _pin_int; +}; + + + + diff --git a/lib/spi.cpp b/lib/spi.cpp new file mode 100644 index 0000000..01d7872 --- /dev/null +++ b/lib/spi.cpp @@ -0,0 +1,35 @@ +#include "spi.h" + + +namespace spi +{ + void init() { + SPI_PORT |= (1<<SPI_CS); //set chip select pin high + SPI_DDR |= (1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_CS); // spi sck mosi and chip select outputs + + SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0); //enable SPI , Master, fck/16 + } + + uint8_t transfer(uint8_t data) { + SPDR = data; + while(!(SPSR & (1<<SPIF))); //wait for transmition to complete + return SPDR; + } +} + + + +// } // namespace spi + +void SPI::init() { + SPI_PORT |= (1<<SPI_CS); //set chip select pin high + SPI_DDR |= (1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_CS); // spi sck mosi and chip select outputs + + SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0); //enable SPI , Master, fck/16 +} + +uint8_t SPI::transfer(uint8_t data) { + SPDR = data; + while(!(SPSR & (1<<SPIF))); //wait for transmition to complete + return SPDR; +} \ No newline at end of file diff --git a/lib/spi.h b/lib/spi.h new file mode 100644 index 0000000..82d1398 --- /dev/null +++ b/lib/spi.h @@ -0,0 +1,33 @@ +#pragma once + +#include <avr/io.h> + + + +#define SPI_PORT PORTB +#define SPI_DDR DDRB +#define SPI_SCK PB7 +#define SPI_MOSI PB5 +#define SPI_CS PB4 + +namespace spi +{ + void init(); + uint8_t transfer(uint8_t data); + + inline void cs_low() {SPI_PORT &= ~(1<<SPI_CS);} + + inline void cs_high() {SPI_PORT |= (1<<SPI_CS);} +} // namespace spi + + +class SPI { + public: + void init(); + uint8_t transfer(uint8_t data); + inline void cs_low() {SPI_PORT &= ~(1<<SPI_CS);} + + inline void cs_high() {SPI_PORT |= (1<<SPI_CS);} +}; + +extern SPI s; \ No newline at end of file diff --git a/lib/usart.cpp b/lib/usart.cpp new file mode 100644 index 0000000..1b46c9c --- /dev/null +++ b/lib/usart.cpp @@ -0,0 +1,50 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include "usart.h" + +namespace usart +{ + namespace { + static FILE mystdout; + } + + void init( unsigned long baud) { + fdev_setup_stream(&mystdout, put_printf, NULL, _FDEV_SETUP_WRITE); + stdout = &mystdout; + const unsigned int ubrr = F_CPU/16/baud-1; + + /*Set baud rate */ + UBRRH = (unsigned char)(ubrr>>8); + UBRRL = (unsigned char)ubrr; + //Enable receiver and transmitter + UCSRB = (1<<RXEN)|(1<<TXEN); + //UCSRB |= (1<< RXCIE)|(1<<TXCIE); + /* Set frame format: 8data, 2stop bit */ + UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); + sei(); + + } + + void put(char data) { + /* Wait for empty transmit buffer */ + while ( !( UCSRA & (1<<UDRE)) ) + ; + /* Put data into buffer, sends the data */ + UDR = data; + } + + char get( void ) { + /* Wait for data to be received */ + while ( !(UCSRA & (1<<RXC)) ) + ; + /* Get and return received data from buffer */ + return UDR; + } + + int put_printf(char var, FILE *stream) { + put(var); + return 0; + } +} // namespace usart + + diff --git a/lib/usart.h b/lib/usart.h new file mode 100644 index 0000000..ffad848 --- /dev/null +++ b/lib/usart.h @@ -0,0 +1,14 @@ +#pragma once + +#include <stdio.h> + +namespace usart +{ + void init(unsigned long baud); + void put(char data ); + char get(); + int put_printf(char var, FILE *stream); +} // namespace usart + + + diff --git a/rx/bin/main.bin b/rx/bin/main.bin new file mode 100644 index 0000000000000000000000000000000000000000..b14578be2c06eebdae110b2cf39a7fb75c70bab5 GIT binary patch literal 33348 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 literal 0 HcmV?d00001 diff --git a/rx/bin/main.elf b/rx/bin/main.elf new file mode 100644 index 0000000000000000000000000000000000000000..b14578be2c06eebdae110b2cf39a7fb75c70bab5 GIT binary patch literal 33348 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 literal 0 HcmV?d00001 diff --git a/rx/bin/main.hex b/rx/bin/main.hex new file mode 100644 index 0000000..cff4be5 --- /dev/null +++ b/rx/bin/main.hex @@ -0,0 +1,234 @@ +:100000000C942B000C948D000C9453000C94530012 +:100010000C9453000C9453000C9453000C94530014 +:100020000C9453000C9453000C9453000C94530004 +:100030000C9453000C9453000C9453000C945300F4 +:100040000C9453000C9453000C9453000C945300E4 +:100050000C945300E00311241FBECFE5D8E0DEBFAF +:10006000CDBF10E0A0E6B0E0ECE4FEE002C00590F9 +:100070000D92A03AB107D9F721E0A0EAB0E001C0A3 +:100080001D92A83BB207E1F710E0CBE2D0E004C03C +:100090002197FE010E940904CA32D107C9F70E94C4 +:1000A000AF030C9424070C9400000895CF93DF93C2 +:1000B000D89A80EA90E00E949202FC0180811F920F +:1000C0008F9380E690E09F938F930E940F0482E8C5 +:1000D00090E00E942C040F900F900F900F90C0E0C2 +:1000E000D0E080EA90E00E949B02C817D9076CF428 +:1000F00080EA90E00E9492028C0F9D1FFC0181819A +:1001000090E00E9425042196ECCF80E890E00E94C8 +:100110002C04D898DF91CF9108951F920F920FB6BB +:100120000F9211242F933F934F935F936F937F937D +:100130008F939F93AF93BF93EF93FF9380EA90E0E9 +:100140000E94C502FF91EF91BF91AF919F918F9156 +:100150007F916F915F914F913F912F910F900FBEC3 +:100160000F901F901895C0988FE19EE40197F1F7CA +:1001700000C00000C09A8FE39CE90197F1F700C02E +:1001800000000895CF93C62F0E94DC038C2F880FA8 +:100190008E770E946E0380E00E946E03C82F0E943B +:1001A000DE030E94DE038C2FCF910895CF93DF935F +:1001B000EB010E94DC03CE0123E0969587952A95FA +:1001C000E1F780680E946E038C2F8295880F807EF5 +:1001D0000E946E0380E00E946E03C82F0E94DE031F +:1001E0008C2FDF91CF910895CF93DF93C62FD42F1B +:1001F0000E94DC038C2F880F8E7781600E946E0333 +:100200008D2F0E946E03DF91CF910C94DE031F931C +:10021000CF93DF93EB01142F0E94DC03CE0123E088 +:10022000969587952A95E1F780680E946E038C2F3A +:100230008295880F807E80610E946E03812F0E94CC +:100240006E03DF91CF911F910C94DE030F931F93E8 +:10025000CF938C0162E00E94C200C82F61E0C80108 +:100260000E94C2002C2F30E0322F2227A901482BF8 +:10027000CA01CF911F910F9108951F93CF93DF93E0 +:10028000EC01162F472F62E00E94F400412F61E03D +:10029000CE01DF91CF911F910C94F4001F93CF9367 +:1002A000DF93EC01162F472F64E00E94F400412FEA +:1002B00063E0CE01DF91CF911F910C94F4000F9376 +:1002C0001F93CF938C0164E00E94C200C82F63E0AB +:1002D000C8010E94C2002C2F30E0322F2227A90132 +:1002E000482BCA01CF911F910F910895AF92BF92F1 +:1002F000CF92DF92EF92FF920F931F93CF93DF93F2 +:10030000EC017B016A01FA0101900020E9F73197C5 +:100310008F01041B150B49E060E070E00E940701AB +:1003200040912101475F400F61E070E0CE010E94E3 +:10033000070141E662E070E0CE010E94070148E853 +:1003400063E070E0CE010E94070141E064E070E0EC +:10035000CE010E940701CE010E942601B92E482F2E +:1003600065E070E0CE010E9407014B2D66E070E071 +:10037000CE010E9407014E2D67E070E0CE010E9481 +:1003800007014F2D68E070E0CE010E940701CE0109 +:100390000E945F01F92E482F69E070E0CE010E94B3 +:1003A00007014F2D6AE070E0CE010E940701E09046 +:1003B0002101F09022018BE0E80EF11C560111277B +:1003C000C5018C199D09801791075CF4F5014191D5 +:1003D0005F01B701CE010E940701FFEFEF1AFF0A8C +:1003E000EFCF45E06BE1CE01DF91CF911F910F91EF +:1003F000FF90EF90DF90CF90BF90AF900C94F400FF +:1004000046EF62E30C94F400462F50E04B50510944 +:1004100024E0440F551F2A95E1F7436060E072E045 +:100420000C940701CF93DF93EC01B89A48E968E197 +:100430000E94F40045E96EE2CE010E94F40043E020 +:1004400060E072E0CE010E94070141E061E072E0ED +:10045000CE010E94070140E862E072E0CE010E94F6 +:10046000070140E966E072E0CE010E94070140E822 +:1004700067E072E0CE010E94070140E168E072E0AF +:10048000CE010E94070141E260E272E0CE010E94CB +:10049000070140E86AE3CE010E94F40040E66FE302 +:1004A000CE010E94F40040E46EE3CE010E94F4000D +:1004B000CE010E9400026CE0CE010E94040244E0E2 +:1004C00066E3CE010E94F40040E066E3CE010E94A4 +:1004D000F4008FEC97E00197F1F700C00000DF9186 +:1004E000CF910895CF93DF93EA018091A7008823ED +:1004F00021F01092A700FB0109958091A6008823A6 +:1005000031F01092A600FE01DF91CF910994DF91A6 +:10051000CF910895662311F041E001C040E060E012 +:100520000C94F40089EA90E0089588EA90E0089538 +:1005300085E291E008958091A90090E02091230147 +:1005400030912401821B930B0895709322016093D4 +:10055000210108956093200108958091200108955C +:10056000662311F047E001C040E06FE272E00C94B6 +:10057000070141E06DE00C94F40044E069E30C9461 +:10058000F40040E069E30C94F4008F929F92BF92D4 +:10059000CF92DF92EF92FF920F931F93CF93DF934F +:1005A000EC0161E30E94C200B82E83FF61C080911C +:1005B000A7008F5F8093A700F894CE010E94BD0230 +:1005C00060E073E0CE010E94D600082F80912001E8 +:1005D000811107C05AEAE52E50E0F52EC12CD12C2E +:1005E00017C045E2C42E41E0D42EE12CF12C802E20 +:1005F000912CE814F90474F78FEFE81AF80AB701A0 +:100600007D5FCE010E94D600F60181936F01F1CF8C +:100610008091A90090E02091230130912401821B58 +:10062000930BC816D9066CF4FFEFCF1ADF0AB60198 +:10063000675F7C4FCE010E94D600F70181937F0156 +:10064000E7CF0093A90010E0B8016F5F7C4FCE01A7 +:100650000E94D60080931E01B8016E5F7C4FCE01D0 +:100660000E94D60080931F01CE010E94C10278949F +:10067000B0FE20C08091A6008F5F8093A60064E248 +:10068000CE010E94C20090E0AC014E7F31E0452BCC +:1006900009F030E02091A80030FB20F936E0959574 +:1006A00087953A95E1F78370880F297F822B877FA2 +:1006B0008093A800DF91CF911F910F91FF90EF9051 +:1006C000DF90CF90BF909F908F900895C49A87B38A +:1006D000806B87BB8DB181658DB908958FB9779B8C +:1006E000FECF8FB10895C49A87B3806B87BB8DB15D +:1006F00081658DB908956FB9779BFECF8FB108954D +:100700009B01AC01E4EAF1E086EA93E091878087FF +:100710001386128682E0838315861486F093B501D2 +:10072000E093B40160E271EA87E090E00E94E703A1 +:100730002150310930BD29B988E18AB98EE880BDE0 +:10074000789408955D9BFECF8CB908950E94A20312 +:1007500080E090E008955F9BFECF8CB1089560E546 +:1007600073EC80E090E00E9480030E94660380EAC0 +:1007700090E00E94B30080EA90E00E9412026EEFC7 +:100780007AEC80EA90E00E943D0162E072E480EA47 +:1007900090E00E944E0184B7816084BF8BB7806473 +:1007A0008BBF7894D09A45E550E066E570E080EA2A +:1007B00090E00E947202F7CFC4980895C49A0895F9 +:1007C0008BE090E090932401809323010895A1E2AF +:1007D0001A2EAA1BBB1BFD010DC0AA1FBB1FEE1FBB +:1007E000FF1FA217B307E407F50720F0A21BB30B06 +:1007F000E40BF50B661F771F881F991F1A9469F782 +:1008000060957095809590959B01AC01BD01CF01DD +:100810000895EE0FFF1F0590F491E02D0994A0E0DC +:10082000B0E0E5E1F4E00C94FD06AE014B5F5F4FF4 +:10083000FA0161917191AF018091B4019091B5017C +:100840000E945C04E2E00C9419076091B40170917D +:10085000B5010E94530608950F931F93CF93DF9322 +:10086000E091B401F091B501238121FF1BC08C01FF +:10087000D0E0C0E0F80181918F016091B4017091E6 +:10088000B501DB011896ED91FC911997882331F0A1 +:100890000995892B79F3DFEFCFEFECCF8AE009954B +:1008A000892B19F08FEF9FEF02C08D2F9C2FDF91C6 +:1008B000CF911F910F910895ABE0B0E0E2E6F4E034 +:1008C0000C94ED066C017B018A01FC0117821682F3 +:1008D000838181FFCCC1CE0101963C01F601938159 +:1008E000F70193FD859193FF81917F01882309F49E +:1008F000BAC1853239F493FD859193FF81917F01CF +:10090000853229F4B60190E00E945306E7CF912C7E +:10091000212C312CFFE1F315D8F08B3279F038F42B +:10092000803279F08332A1F4232D20611DC08D32F5 +:1009300061F0803369F4232D216016C0832D82601D +:10094000382EE32DE4603E2E2AC0F32DF8601DC042 +:1009500037FC2DC020ED280F2A3040F08E32B9F43C +:1009600036FC81C1232D2064322E19C036FE06C00C +:100970008AE0989E200D1124922E11C0EAE02E9E4E +:10098000200D1124222EF32DF0623F2E08C08C364C +:1009900021F4832D8068382E02C0883641F4F70197 +:1009A00093FD859193FF81917F018111B3CF982FA2 +:1009B0009F7D9554933028F40C5F1F4F9FE39983DC +:1009C0000DC0833631F0833771F0833509F059C09B +:1009D00021C0F801808189830E5F1F4F8824839492 +:1009E000912C530113C02801F2E04F0E511CF80165 +:1009F000A080B18036FE03C0692D70E002C06FEFA9 +:100A00007FEFC5010E9448064C018201F32DFF775C +:100A10003F2E16C0280122E0420E511CF801A08092 +:100A2000B18036FE03C0692D70E002C06FEF7FEF2A +:100A3000C5010E943D064C01F32DF0683F2E820156 +:100A400033FC1BC0822D90E088169906B0F4B601E5 +:100A500080E290E00E9453062A94F4CFF50137FC1F +:100A6000859137FE81915F01B60190E00E945306A7 +:100A700021102A9421E0821A91088114910471F7BF +:100A8000E8C0843611F0893641F5F80137FE07C019 +:100A900060817181828193810C5F1F4F08C06081EA +:100AA0007181072E000C880B990B0E5F1F4FF32DE1 +:100AB000FF763F2E97FF09C09095809570956195C0 +:100AC0007F4F8F4F9F4FF0683F2E2AE030E0A30109 +:100AD0000E948F06882E861845C0853731F4232D55 +:100AE0002F7EB22E2AE030E025C0932D997FB92EBB +:100AF0008F36C1F018F4883579F0B5C0803719F019 +:100B0000883721F0B0C0E92FE061BE2EB4FE0DC0E1 +:100B1000FB2DF460BF2E09C034FE0AC0292F2660C9 +:100B2000B22E06C028E030E005C020E130E002C06F +:100B300020E132E0F801B7FE07C060817181828157 +:100B400093810C5F1F4F06C06081718180E090E04F +:100B50000E5F1F4FA3010E948F06882E8618FB2D63 +:100B6000FF773F2E36FE0DC0232D2E7FA22E891437 +:100B700058F434FE0BC032FC09C0832D8E7EA82EA3 +:100B800005C0B82CA32C03C0B82C01C0B92CA4FEFE +:100B90000FC0FE01E80DF11D8081803321F49A2DF4 +:100BA000997EA92E09C0A2FE06C0B394B39404C0D6 +:100BB0008A2D867809F0B394A3FC11C0A0FE06C06C +:100BC000B21488F4280C922C9B180EC0B21460F456 +:100BD000B60180E290E00E945306B394F7CFB214BE +:100BE00018F42B1802C0982C212CA4FE10C0B601BA +:100BF00080E390E00E945306A2FE17C0A1FC03C050 +:100C000088E790E002C088E590E0B6010CC08A2D2C +:100C1000867859F0A1FE02C08BE201C080E2A7FCF9 +:100C20008DE2B60190E00E945306891438F4B601B3 +:100C300080E390E00E9453069A94F7CF8A94F301E0 +:100C4000E80DF11D8081B60190E00E9453068110ED +:100C5000F5CF222009F442CEB60180E290E00E9456 +:100C600053062A94F6CFF6018681978102C08FEF52 +:100C70009FEF2B96E2E10C940907FC01059061506F +:100C800070400110D8F7809590958E0F9F1F0895A2 +:100C9000FC016150704001900110D8F7809590954B +:100CA0008E0F9F1F08950F931F93CF93DF93FB0128 +:100CB000238121FD03C08FEF9FEF2CC022FF16C0C0 +:100CC00046815781248135814217530744F4A0811E +:100CD000B1819D012F5F3F4F318320838C9326810B +:100CE00037812F5F3F4F3783268314C08B01EC0180 +:100CF000FB010084F185E02D0995892BE1F6D801EF +:100D000016968D919C911797019617969C938E93AA +:100D10001697CE01DF91CF911F910F910895FA019F +:100D2000AA27283051F1203181F1E8946F936E7F2A +:100D30006E5F7F4F8F4F9F4FAF4FB1E03ED0B4E01B +:100D40003CD0670F781F891F9A1FA11D680F791F5C +:100D50008A1F911DA11D6A0F711D811D911DA11D6D +:100D600020D009F468943F912AE0269F112430197D +:100D7000305D3193DEF6CF010895462F4770405D18 +:100D80004193B3E00FD0C9F7F6CF462F4F70405DC7 +:100D90004A3318F0495D31FD4052419302D0A9F722 +:100DA000EACFB4E0A6959795879577956795BA951C +:100DB000C9F700976105710508959B01AC010A2EE2 +:100DC00006945795479537952795BA95C9F7620FB9 +:100DD000731F841F951FA01D08952F923F924F925D +:100DE0005F926F927F928F929F92AF92BF92CF92BB +:100DF000DF92EF92FF920F931F93CF93DF93CDB7C4 +:100E0000DEB7CA1BDB0B0FB6F894DEBF0FBECDBF3B +:100E100009942A88398848885F846E847D848C840C +:100E20009B84AA84B984C884DF80EE80FD800C8115 +:100E30001B81AA81B981CE0FD11D0FB6F894DEBFF8 +:0C0E40000FBECDBFED010895F894FFCF68 +:100E4C0052656365697665642061207061636B65CA +:100E5C0074202569206279746573206C6F6E670A43 +:100E6C000A000D0A415343494920646174612028EA +:100E7C0072656C6576616E742064617461293A00E8 +:00000001FF diff --git a/rx/makefile b/rx/makefile new file mode 100644 index 0000000..8b9adbf --- /dev/null +++ b/rx/makefile @@ -0,0 +1,25 @@ +MCU=atmega32 +F_CPU?=8000000 +PROG=dragon_jtag +CC=avr-g++ +OBJCOPY=avr-objcopy +CFLAGS=-Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I. +TARGET=main +SRCS=src/*.cpp ../lib/*.cpp + +all: build flash + +build: + ${CC} ${CFLAGS} -o bin/${TARGET}.bin ${SRCS} + ${CC} ${CFLAGS} -o bin/${TARGET}.elf ${SRCS} + ${OBJCOPY} -j .text -j .data -O ihex bin/${TARGET}.bin bin/${TARGET}.hex + +flash: + avrdude -p ${MCU} -c ${PROG} -U flash:w:bin/main.hex + +clean: + rm -f bin/* + +term: + python3 term.py + diff --git a/rx/src/main.cpp b/rx/src/main.cpp new file mode 100644 index 0000000..596ba78 --- /dev/null +++ b/rx/src/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 + */ + + +#include <avr/io.h> +#include <avr/interrupt.h> +#include "../../lib/mrf24j.h" +#include "../../lib/usart.h" +#include "../../lib/spi.h" + +const int pin_reset = 5; +const int pin_cs = 10; // default CS pin on ATmega8/168/328 +const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328 + +Mrf24j mrf; + +void handle_rx(); +void handle_tx(); + + +int main() { + usart::init(50000); + spi::init(); + //s.init(); + mrf.reset(); + mrf.init(); + + mrf.set_pan(0xcafe); + // This is _our_ address + mrf.address16_write(0x4202); + + // uncomment if you want to receive any packet on this channel + //mrf.set_promiscuous(true); + + // uncomment if you want to enable PA/LNA external control + //mrf.set_palna(true); + + // uncomment if you want to buffer all PHY Payload + //mrf.set_bufferPHY(true); + + MCUCSR |= (1<<ISC00); // INT2 falling edge + GICR |= (1<<INT0); + + sei(); + DDRA |= (1<<PA0); + + while(1) { + mrf.check_flags(&handle_rx, &handle_tx); + } + return 0; +} + + +ISR(INT0_vect) { + mrf.interrupt_handler(); // mrf24 object interrupt routine +} + + +void handle_rx() { + PORTA |= (1<<PA0); + printf("Received a packet %i bytes long\n\n", mrf.get_rxinfo()->frame_length); + + printf("\r\nASCII data (relevant data):\n"); + for (int i = 0; i < mrf.rx_datalength(); i++) { + printf("%c", mrf.get_rxinfo()->rx_data[i]); + } + printf("\n\n"); + // Serial.print("\r\nLQI/RSSI="); + // Serial.print(mrf.get_rxinfo()->lqi, DEC); + // Serial.print("/"); + // Serial.println(mrf.get_rxinfo()->rssi, DEC); + PORTA &= ~(1<<PA0); +} + +void handle_tx() { + +} \ No newline at end of file diff --git a/rx/term.py b/rx/term.py new file mode 100644 index 0000000..2e7d8ad --- /dev/null +++ b/rx/term.py @@ -0,0 +1,11 @@ +import serial +from time import sleep + +with serial.Serial('/dev/ttyUSB0', 50000, timeout=1) as ser: + while True: + x = ser.read() # read one byte + if x != b'': + pass + print(x.decode('utf'), end ="") + + #print(ser.read()) \ No newline at end of file diff --git a/tx/bin/main.bin b/tx/bin/main.bin new file mode 100644 index 0000000000000000000000000000000000000000..1000056aa2944386d75bd549d97806cd02f01d2e GIT binary patch literal 32908 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 literal 0 HcmV?d00001 diff --git a/tx/bin/main.elf b/tx/bin/main.elf new file mode 100644 index 0000000000000000000000000000000000000000..1000056aa2944386d75bd549d97806cd02f01d2e GIT binary patch literal 32908 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 literal 0 HcmV?d00001 diff --git a/tx/bin/main.hex b/tx/bin/main.hex new file mode 100644 index 0000000..f8d890f --- /dev/null +++ b/tx/bin/main.hex @@ -0,0 +1,228 @@ +:100000000C942B000C947C000C9453000C94530023 +:100010000C9453000C9453000C9453000C94530014 +:100020000C9453000C9453000C9453000C94530004 +:100030000C9453000C9453000C9453000C945300F4 +:100040000C9453000C9453000C9453000C945300E4 +:100050000C945300E20311241FBECFE5D8E0DEBFAD +:10006000CDBF10E0A0E6B0E0E2EEFDE002C00590FA +:100070000D92A639B107D9F721E0A6E9B0E001C099 +:100080001D92AE3AB207E1F710E0CBE2D0E004C037 +:100090002197FE010E940B04CA32D107C9F70E94C2 +:1000A0009E030C94EF060C940000089586E990E0FE +:1000B0000E948402FC01808180FF09C080E690E0FC +:1000C0009F938F930E9411040F900F90089586E9DB +:1000D00090E00E948402FC018081869583701F92CB +:1000E0008F9384E790E09F938F930E9411040F9069 +:1000F0000F900F900F9008951F920F920FB60F92CE +:1001000011242F933F934F935F936F937F938F931C +:100110009F93AF93BF93EF93FF9386E990E00E9484 +:10012000B402FF91EF91BF91AF919F918F917F9119 +:100130006F915F914F913F912F910F900FBE0F9054 +:100140001F901895C0988FE19EE40197F1F700C0C9 +:100150000000C09A8FE39CE90197F1F700C000000E +:100160000895CF93C62F0E94DE038C2F880F8E77C1 +:100170000E945D0380E00E945D03C82F0E94E0039F +:100180000E94E0038C2FCF910895CF93DF93EB0172 +:100190000E94DE03CE0123E0969587952A95E1F72C +:1001A00080680E945D038C2F8295880F807E0E945C +:1001B0005D0380E00E945D03C82F0E94E0038C2F46 +:1001C000DF91CF910895CF93DF93C62FD42F0E9454 +:1001D000DE038C2F880F8E7781600E945D038D2F48 +:1001E0000E945D03DF91CF910C94E0031F93CF93A6 +:1001F000DF93EB01142F0E94DE03CE0123E09695DE +:1002000087952A95E1F780680E945D038C2F82957F +:10021000880F807E80610E945D03812F0E945D03B4 +:10022000DF91CF911F910C94E0030F931F93CF9315 +:100230008C0162E00E94B100C82F61E0C8010E94F9 +:10024000B1002C2F30E0322F2227A901482BCA0100 +:10025000CF911F910F9108951F93CF93DF93EC01DE +:10026000162F472F62E00E94E300412F61E0CE018C +:10027000DF91CF911F910C94E3001F93CF93DF93F5 +:10028000EC01162F472F64E00E94E300412F63E04A +:10029000CE01DF91CF911F910C94E3000F931F9338 +:1002A000CF938C0164E00E94B100C82F63E0C801C5 +:1002B0000E94B1002C2F30E0322F2227A901482BB9 +:1002C000CA01CF911F910F910895AF92BF92CF9223 +:1002D000DF92EF92FF920F931F93CF93DF93EC0186 +:1002E0007B016A01FA0101900020E9F731978F0143 +:1002F000041B150B49E060E070E00E94F60040919D +:100300001701475F400F61E070E0CE010E94F600E8 +:1003100041E662E070E0CE010E94F60048E863E04A +:1003200070E0CE010E94F60041E064E070E0CE0192 +:100330000E94F600CE010E941501B92E482F65E0FB +:1003400070E0CE010E94F6004B2D66E070E0CE0119 +:100350000E94F6004E2D67E070E0CE010E94F6008C +:100360004F2D68E070E0CE010E94F600CE010E94A1 +:100370004E01F92E482F69E070E0CE010E94F60090 +:100380004F2D6AE070E0CE010E94F600E090170168 +:10039000F09018018BE0E80EF11C56011127C50101 +:1003A0008C199D09801791075CF4F50141915F015B +:1003B000B701CE010E94F600FFEFEF1AFF0AEFCF60 +:1003C00045E06BE1CE01DF91CF911F910F91FF903E +:1003D000EF90DF90CF90BF90AF900C94E30046EF8A +:1003E00062E30C94E300462F50E04B50510924E0A7 +:1003F000440F551F2A95E1F7436060E072E00C94CA +:10040000F600CF93DF93EC01B89A48E968E10E94C7 +:10041000E30045E96EE2CE010E94E30043E060E0C4 +:1004200072E0CE010E94F60041E061E072E0CE0190 +:100430000E94F60040E862E072E0CE010E94F60001 +:1004400040E966E072E0CE010E94F60040E867E015 +:1004500072E0CE010E94F60040E168E072E0CE0159 +:100460000E94F60041E260E272E0CE010E94F600D6 +:1004700040E86AE3CE010E94E30040E66FE3CE016C +:100480000E94E30040E46EE3CE010E94E300CE014F +:100490000E94EF016CE0CE010E94F30144E066E3AC +:1004A000CE010E94E30040E066E3CE010E94E3003B +:1004B0008FEC97E00197F1F700C00000DF91CF913A +:1004C0000895CF93DF93EA0180919D00882321F066 +:1004D00010929D00FB01099580919C00882331F0CA +:1004E00010929C00FE01DF91CF910994DF91CF9192 +:1004F0000895662311F041E001C040E060E00C94F3 +:10050000E3008FE990E008958EE990E008958BE193 +:1005100091E0089580919F0090E020911901309121 +:100520001A01821B930B08957093180160931701B1 +:100530000895609316010895809116010895662329 +:1005400011F047E001C040E06FE272E00C94F60069 +:1005500041E06DE00C94E30044E069E30C94E300B7 +:1005600040E069E30C94E3008F929F92BF92CF9298 +:10057000DF92EF92FF920F931F93CF93DF93EC01E3 +:1005800061E30E94B100B82E83FF61C080919D009D +:100590008F5F80939D00F894CE010E94AC0260E0D2 +:1005A00073E0CE010E94C500082F809116018111D1 +:1005B00007C050EAE52E50E0F52EC12CD12C17C013 +:1005C0004BE1C42E41E0D42EE12CF12C802E912C55 +:1005D000E814F90474F78FEFE81AF80AB7017D5FA1 +:1005E000CE010E94C500F60181936F01F1CF809189 +:1005F0009F0090E02091190130911A01821B930B0A +:10060000C816D9066CF4FFEFCF1ADF0AB601675F90 +:100610007C4FCE010E94C500F70181937F01E7CF97 +:1006200000939F0010E0B8016F5F7C4FCE010E94E5 +:10063000C50080931401B8016E5F7C4FCE010E940B +:10064000C50080931501CE010E94B0027894B0FEDF +:1006500020C080919C008F5F80939C0064E2CE015B +:100660000E94B10090E0AC014E7F31E0452B09F0D3 +:1006700030E020919E0030FB20F936E0959587957B +:100680003A95E1F78370880F297F822B877F8093CB +:100690009E00DF91CF911F910F91FF90EF90DF901F +:1006A000CF90BF909F908F900895C49A87B3806B2E +:1006B00087BB8DB181658DB908958FB9779BFECFCA +:1006C0008FB10895C49A87B3806B87BB8DB1816564 +:1006D0008DB908956FB9779BFECF8FB108959B01B7 +:1006E000AC01EAE9F1E085E993E091878087138620 +:1006F000128682E0838315861486F093AB01E09323 +:10070000AA0160E271EA87E090E00E94E9032150CB +:10071000310930BD29B988E18AB98EE880BD789465 +:1007200008955D9BFECF8CB908950E94910380E0EF +:1007300090E008955F9BFECF8CB1089560E573EC67 +:1007400080E090E00E946F030E94550386E990E0EC +:100750000E94A20086E990E00E9401026EEF7AEC0E +:1007600086E990E00E942C0162E072E486E990E064 +:100770000E943D0184B7816084BF8BB780648BBFCA +:100780007894D09AD89A46E550E065E570E086E91D +:1007900090E00E94610240E950E062E072E486E984 +:1007A00090E00E946501D8982FEF89E698E12150EA +:1007B00080409040E1F700C00000E4CFC498089565 +:1007C000C49A08958BE090E090931A0180931901E8 +:1007D0000895A1E21A2EAA1BBB1BFD010DC0AA1F82 +:1007E000BB1FEE1FFF1FA217B307E407F50720F09A +:1007F000A21BB30BE40BF50B661F771F881F991F15 +:100800001A9469F760957095809590959B01AC015D +:10081000BD01CF010895EE0FFF1F0590F491E02D6B +:100820000994A0E0B0E0E7E1F4E00C94C806AE0162 +:100830004B5F5F4FFA0161917191AF018091AA0105 +:100840009091AB010E942704E2E00C94E406ABE037 +:10085000B0E0EDE2F4E00C94B8066C017B018A0193 +:10086000FC0117821682838181FFCCC1CE010196E3 +:100870003C01F6019381F70193FD859193FF8191EE +:100880007F01882309F4BAC1853239F493FD85913B +:1008900093FF81917F01853229F4B60190E00E9497 +:1008A0001E06E7CF912C212C312CFFE1F315D8F057 +:1008B0008B3279F038F4803279F08332A1F4232D31 +:1008C00020611DC08D3261F0803369F4232D2160D9 +:1008D00016C0832D8260382EE32DE4603E2E2AC0A0 +:1008E000F32DF8601DC037FC2DC020ED280F2A30F5 +:1008F00040F08E32B9F436FC81C1232D2064322EB3 +:1009000019C036FE06C08AE0989E200D1124922E52 +:1009100011C0EAE02E9E200D1124222EF32DF0624C +:100920003F2E08C08C3621F4832D8068382E02C0FB +:10093000883641F4F70193FD859193FF81917F0102 +:100940008111B3CF982F9F7D9554933028F40C5F7D +:100950001F4F9FE399830DC0833631F0833771F0C9 +:10096000833509F059C021C0F801808189830E5F69 +:100970001F4F88248394912C530113C02801F2E067 +:100980004F0E511CF801A080B18036FE03C0692DC6 +:1009900070E002C06FEF7FEFC5010E9413064C01AB +:1009A0008201F32DFF773F2E16C0280122E0420E70 +:1009B000511CF801A080B18036FE03C0692D70E0A3 +:1009C00002C06FEF7FEFC5010E9408064C01F32DB6 +:1009D000F0683F2E820133FC1BC0822D90E0881608 +:1009E0009906B0F4B60180E290E00E941E062A94B7 +:1009F000F4CFF50137FC859137FE81915F01B60197 +:100A000090E00E941E0621102A9421E0821A91088B +:100A10008114910471F7E8C0843611F0893641F5EC +:100A2000F80137FE07C060817181828193810C5F7C +:100A30001F4F08C060817181072E000C880B990B35 +:100A40000E5F1F4FF32DFF763F2E97FF09C0909545 +:100A50008095709561957F4F8F4F9F4FF0683F2E27 +:100A60002AE030E0A3010E945A06882E861845C06D +:100A7000853731F4232D2F7EB22E2AE030E025C0B9 +:100A8000932D997FB92E8F36C1F018F4883579F0FF +:100A9000B5C0803719F0883721F0B0C0E92FE06188 +:100AA000BE2EB4FE0DC0FB2DF460BF2E09C034FE77 +:100AB0000AC0292F2660B22E06C028E030E005C00B +:100AC00020E130E002C020E132E0F801B7FE07C0CB +:100AD00060817181828193810C5F1F4F06C06081AC +:100AE000718180E090E00E5F1F4FA3010E945A06C3 +:100AF000882E8618FB2DFF773F2E36FE0DC0232D46 +:100B00002E7FA22E891458F434FE0BC032FC09C08B +:100B1000832D8E7EA82E05C0B82CA32C03C0B82C24 +:100B200001C0B92CA4FE0FC0FE01E80DF11D8081AB +:100B3000803321F49A2D997EA92E09C0A2FE06C009 +:100B4000B394B39404C08A2D867809F0B394A3FCBF +:100B500011C0A0FE06C0B21488F4280C922C9B1879 +:100B60000EC0B21460F4B60180E290E00E941E064E +:100B7000B394F7CFB21418F42B1802C0982C212C80 +:100B8000A4FE10C0B60180E390E00E941E06A2FE03 +:100B900017C0A1FC03C088E790E002C088E590E0A0 +:100BA000B6010CC08A2D867859F0A1FE02C08BE2F6 +:100BB00001C080E2A7FC8DE2B60190E00E941E0613 +:100BC000891438F4B60180E390E00E941E069A94DE +:100BD000F7CF8A94F301E80DF11D8081B60190E012 +:100BE0000E941E068110F5CF222009F442CEB601E4 +:100BF00080E290E00E941E062A94F6CFF6018681DC +:100C0000978102C08FEF9FEF2B96E2E10C94D40600 +:100C1000FC010590615070400110D8F780959095C7 +:100C20008E0F9F1F0895FC016150704001900110CC +:100C3000D8F7809590958E0F9F1F08950F931F935F +:100C4000CF93DF93FB01238121FD03C08FEF9FEF43 +:100C50002CC022FF16C0468157812481358142175E +:100C6000530744F4A081B1819D012F5F3F4F318331 +:100C700020838C93268137812F5F3F4F37832683D4 +:100C800014C08B01EC01FB010084F185E02D099576 +:100C9000892BE1F6D80116968D919C9117970196B4 +:100CA00017969C938E931697CE01DF91CF911F914B +:100CB0000F910895FA01AA27283051F1203181F1CE +:100CC000E8946F936E7F6E5F7F4F8F4F9F4FAF4F54 +:100CD000B1E03ED0B4E03CD0670F781F891F9A1F67 +:100CE000A11D680F791F8A1F911DA11D6A0F711D1B +:100CF000811D911DA11D20D009F468943F912AE027 +:100D0000269F11243019305D3193DEF6CF0108950E +:100D1000462F4770405D4193B3E00FD0C9F7F6CF3F +:100D2000462F4F70405D4A3318F0495D31FD405207 +:100D3000419302D0A9F7EACFB4E0A695979587959D +:100D400077956795BA95C9F700976105710508957C +:100D50009B01AC010A2E0694579547953795279528 +:100D6000BA95C9F7620F731F841F951FA01D0895C0 +:100D70002F923F924F925F926F927F928F929F92AB +:100D8000AF92BF92CF92DF92EF92FF920F931F9399 +:100D9000CF93DF93CDB7DEB7CA1BDB0B0FB6F8944A +:100DA000DEBF0FBECDBF09942A88398848885F848A +:100DB0006E847D848C849B84AA84B984C884DF80FB +:100DC000EE80FD800C811B81AA81B981CE0FD11DDF +:100DD0000FB6F894DEBF0FBECDBFED010895F894B5 +:020DE000FFCF43 +:100DE20054582077656E74206F6B2C20676F7420C7 +:100DF20061636B005458206661696C6564206166AA +:100E020074657220256920726574726965730A00BF +:060E12006163646500004D +:00000001FF diff --git a/tx/makefile b/tx/makefile new file mode 100644 index 0000000..8b9adbf --- /dev/null +++ b/tx/makefile @@ -0,0 +1,25 @@ +MCU=atmega32 +F_CPU?=8000000 +PROG=dragon_jtag +CC=avr-g++ +OBJCOPY=avr-objcopy +CFLAGS=-Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I. +TARGET=main +SRCS=src/*.cpp ../lib/*.cpp + +all: build flash + +build: + ${CC} ${CFLAGS} -o bin/${TARGET}.bin ${SRCS} + ${CC} ${CFLAGS} -o bin/${TARGET}.elf ${SRCS} + ${OBJCOPY} -j .text -j .data -O ihex bin/${TARGET}.bin bin/${TARGET}.hex + +flash: + avrdude -p ${MCU} -c ${PROG} -U flash:w:bin/main.hex + +clean: + rm -f bin/* + +term: + python3 term.py + diff --git a/tx/src/main.cpp b/tx/src/main.cpp new file mode 100644 index 0000000..0ec017e --- /dev/null +++ b/tx/src/main.cpp @@ -0,0 +1,80 @@ +/** + * 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 + */ + + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> +#include "../../lib/mrf24j.h" +#include "../../lib/usart.h" +#include "../../lib/spi.h" + +const int pin_reset = 5; +const int pin_cs = 10; // default CS pin on ATmega8/168/328 +const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328 + +Mrf24j mrf; + +void handle_rx(); +void handle_tx(); + + +int main() { + usart::init(50000); + spi::init(); + mrf.reset(); + mrf.init(); + + mrf.set_pan(0xcafe); + // This is _our_ address + mrf.address16_write(0x4202); + + // uncomment if you want to receive any packet on this channel + //mrf.set_promiscuous(true); + + // uncomment if you want to enable PA/LNA external control + //mrf.set_palna(true); + + // uncomment if you want to buffer all PHY Payload + //mrf.set_bufferPHY(true); + + MCUCSR |= (1<<ISC00); // INT2 falling edge + GICR |= (1<<INT0); + + sei(); + DDRA |= (1<<PA0); + + while(1) { + PORTA |= (1<<PA0); + mrf.check_flags(&handle_rx, &handle_tx); + mrf.send16(0x4202, "acde"); + PORTA &= ~(1<<PA0); + _delay_ms(1000); + } + return 0; +} + + +ISR(INT0_vect) { + mrf.interrupt_handler(); // mrf24 object interrupt routine +} + + +void handle_rx() { + + +} + +void handle_tx() { + if (mrf.get_txinfo()->tx_ok) { + printf("TX went ok, got ack"); + } else { + printf("TX failed after %i retries\n", mrf.get_txinfo()->retries); + } +} \ No newline at end of file diff --git a/tx/term.py b/tx/term.py new file mode 100644 index 0000000..2e7d8ad --- /dev/null +++ b/tx/term.py @@ -0,0 +1,11 @@ +import serial +from time import sleep + +with serial.Serial('/dev/ttyUSB0', 50000, timeout=1) as ser: + while True: + x = ser.read() # read one byte + if x != b'': + pass + print(x.decode('utf'), end ="") + + #print(ser.read()) \ No newline at end of file