added mrf_is_rx_complete, mrf_wait_rx_complete, mrf_is_tx_complete,
[mrf-link.git] / fw / mrf / mrf_impl.h
blobb38919733866d6200f6875064bb34b89b953cf7c
1 /*
2 * Copyright 2010 Grygoriy Fuchedzhy <grygoriy.fuchedzhy@gmail.com>
4 * This file is part of mrf-link.
6 * mrf-link is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * mrf-link is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with mrf-link. If not, see <http://www.gnu.org/licenses/>.
20 #ifndef __MRF_IMPL__
21 #define __MRF_IMPL__
23 #include <mrf/mrf.h>
25 #include <util/delay.h>
26 #include <avr/spi.h>
27 #include <avr/interrupt.h>
29 uint16_t mrf_short_addr = MRF_SHORT_ADDR;
30 uint16_t mrf_pan_id = MRF_PAN_ID;
31 uint8_t mrf_seq_num = 0;
32 uint8_t mrf_rssi = 0, mrf_lqi = 0;
33 volatile uint8_t mrf_status = 0;
35 // set given short register to given value via spi
36 void mrf_write_short_addr(uint8_t addr, uint8_t val)
38 uint8_t sreg = SREG;
39 cli();
40 spi_select();
41 spi_shift_byte(0x1 | (addr << 1));
42 spi_shift_byte(val);
43 spi_deselect();
44 SREG = sreg;
47 // get and return value of given short register via spi
48 uint8_t mrf_read_short_addr(uint8_t addr)
50 uint8_t sreg = SREG;
51 cli();
52 spi_select();
53 spi_shift_byte(addr << 1);
54 uint8_t res = spi_shift_byte(0x00);
55 spi_deselect();
56 SREG = sreg;
57 return res;
60 // set given long register to given value via spi
61 void mrf_write_long_addr(uint16_t addr, uint8_t val)
63 uint8_t sreg = SREG;
64 cli();
65 spi_select();
66 spi_shift_byte(0x80 | (addr >> 3));
67 spi_shift_byte(0x10 | (addr << 5));
68 spi_shift_byte(val);
69 spi_deselect();
70 SREG = sreg;
73 // get and return value of given long register via spi
74 uint8_t mrf_read_long_addr(uint16_t addr)
76 uint8_t sreg = SREG;
77 cli();
78 spi_select();
79 spi_shift_byte(0x80 | (addr >> 3));
80 spi_shift_byte(addr << 5);
81 uint8_t res = spi_shift_byte(0x00);
82 spi_deselect();
83 SREG = sreg;
84 return res;
87 // set channel, ch must be: 0x0 - 0xF
88 void mrf_set_channel(uint8_t ch)
90 // 0x2 - recommended value
91 mrf_set_reg(MRF_R_RFCON0, (ch<<4) | 0x2);
92 // reset rf module
93 mrf_set_reg(MRF_R_RFCTL, _BV(MRF_B_RFRST));
94 mrf_set_reg(MRF_R_RFCTL, 0);
95 _delay_us(192);
98 // reset and initialize radio
99 void mrf_init()
101 // software reset, the bits will be automatically cleared by hardware.
102 mrf_set_reg(MRF_R_SOFTRST, _BV(MRF_B_RSTPWR) | _BV(MRF_B_RSTBB) | _BV(MRF_B_RSTMAC));
104 // register initialization
105 mrf_set_reg(MRF_R_PACON2, _BV(MRF_B_FIFOEN) | MRF_RV_TXONTS);
106 mrf_set_reg(MRF_R_TXSTBL, MRF_RV_RFSTBL | MRF_RV_MSIFS);
107 mrf_set_reg(MRF_R_RFCON1, MRF_RV_VCOOPT);
108 mrf_set_reg(MRF_R_RFCON2, _BV(MRF_B_PLLEN));
109 mrf_set_reg(MRF_R_RFCON6, _BV(MRF_B_TXFIL) | _BV(MRF_B_20MRECVR));
110 mrf_set_reg(MRF_R_RFCON7, MRF_V_SLPCLKSEL_100kHz);
111 mrf_set_reg(MRF_R_RFCON8, _BV(MRF_B_RFVCO));
112 mrf_set_reg(MRF_R_SLPCON1, _BV(MRF_B_CLKOUTEN) | 0x1);
113 mrf_set_reg(MRF_R_BBREG2, MRF_V_CCAMODE_ENERGY_ABOVE_THRESHOLD);
114 mrf_set_reg(MRF_R_CCAEDTH, MRF_RV_CCAEDTH);
115 mrf_set_reg(MRF_R_BBREG6, _BV(MRF_B_RSSIMODE2));
117 // enable interrupts, (inverted values for this register)
118 mrf_set_reg(MRF_R_INTCON, ~(_BV(MRF_B_TXN) | _BV(MRF_B_RX)));
120 // read and set address
121 mrf_set_reg(MRF_R_PANIDL, mrf_pan_id);
122 mrf_set_reg(MRF_R_PANIDH, mrf_pan_id>>8);
123 mrf_set_reg(MRF_R_SADRL, mrf_short_addr);
124 mrf_set_reg(MRF_R_SADRH, mrf_short_addr>>8);
126 mrf_set_channel(0);
129 void mrf_tx(uint16_t pan_id, uint16_t short_addr, const uint8_t* data, uint8_t data_length)
131 uint16_t addr = MRF_BUF_TX_NORMAL;
133 // frame control + seq.num. + addressing fields
134 const uint8_t hdr_length = 2 + 1 + 2*(IEEE802_15_4_SHORT_ADDR_LENGTH + IEEE802_15_4_PAN_ID_LENGTH);
136 mrf_write_long_addr(addr++, hdr_length);
137 mrf_write_long_addr(addr++, hdr_length + data_length);
139 // frame control
140 mrf_write_long_addr(addr++, IEEE802_15_4_DATA | IEEE802_15_4_ACK_REQ);
141 mrf_write_long_addr(addr++, IEEE802_15_4_SHORT_DESTADDR | IEEE802_15_4_SHORT_SRCADDR | IEEE802_15_4_2003_VERSION);
143 // sequence number
144 mrf_write_long_addr(addr++, mrf_seq_num++);
146 // dest pan id
147 mrf_write_long_addr(addr++, pan_id);
148 mrf_write_long_addr(addr++, pan_id>>8);
150 // dest short addr
151 mrf_write_long_addr(addr++, short_addr);
152 mrf_write_long_addr(addr++, short_addr>>8);
154 // source pan id
155 mrf_write_long_addr(addr++, mrf_pan_id);
156 mrf_write_long_addr(addr++, mrf_pan_id>>8);
158 // source short addr
159 mrf_write_long_addr(addr++, mrf_short_addr);
160 mrf_write_long_addr(addr++, mrf_short_addr>>8);
162 for(uint8_t i = 0; i < data_length; ++i)
163 mrf_write_long_addr(addr++, data[i]);
165 mrf_status &= ~_BV(MRF_B_TXN);
166 // transmit frame, request acknowledgement
167 mrf_set_reg(MRF_R_TXNCON, _BV(MRF_B_ACKREQ) | _BV(MRF_B_TRIG));
170 uint8_t mrf_rx(uint16_t *pan_id, uint16_t *short_addr, uint8_t* data, uint8_t data_length)
172 // relying on fact that header is in same format as in tx function
173 // frame control + seq.num. + addressing fields
174 const uint8_t hdr_length = 2 + 1 + 2*(IEEE802_15_4_SHORT_ADDR_LENGTH + IEEE802_15_4_PAN_ID_LENGTH);
175 const uint16_t data_offset = MRF_BUF_RX + 1 + hdr_length;
177 // disable receiving packets off air
178 mrf_set_reg(MRF_R_BBREG1, _BV(MRF_B_RXDECINV));
180 // -2 because of fcs bytes
181 uint8_t length = mrf_read_long_addr(MRF_BUF_RX) - hdr_length - 2;
183 if(0 != pan_id)
184 *pan_id = mrf_read_long_addr(MRF_BUF_RX + 8) + (mrf_read_long_addr(MRF_BUF_RX + 9)<<8);
185 if(0 != short_addr)
186 *short_addr = mrf_read_long_addr(MRF_BUF_RX + 10) + (mrf_read_long_addr(MRF_BUF_RX + 11)<<8);
188 uint8_t i = 0;
189 for(; length != 0 && i < data_length; i++, length--)
190 data[i] = mrf_read_long_addr(data_offset + i);
192 mrf_lqi = mrf_read_long_addr(data_offset + i + 2);
193 mrf_rssi = mrf_read_long_addr(data_offset + i + 3);
195 // enable receiving packets off air
196 mrf_set_reg(MRF_R_BBREG1, 0);
198 mrf_status &= ~_BV(MRF_B_RX);
199 return i;
202 #endif // __MRF_IMPL__