moved to waf-1.6 build system
[mrf-link.git] / fw / mrf / mrf_impl.h
blobcf4aac2ec0ae0db6dc1fbbc37b64ca661975dc12
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 // read and set address
118 mrf_set_reg(MRF_R_PANIDL, mrf_pan_id);
119 mrf_set_reg(MRF_R_PANIDH, mrf_pan_id>>8);
120 mrf_set_reg(MRF_R_SADRL, mrf_short_addr);
121 mrf_set_reg(MRF_R_SADRH, mrf_short_addr>>8);
123 mrf_set_channel(0);
126 void mrf_tx(uint16_t pan_id, uint16_t short_addr, const uint8_t* data, uint8_t data_length)
128 uint16_t addr = MRF_BUF_TX_NORMAL;
130 // frame control + seq.num. + addressing fields
131 const uint8_t hdr_length = 2 + 1 + 2*(IEEE802_15_4_SHORT_ADDR_LENGTH + IEEE802_15_4_PAN_ID_LENGTH);
133 mrf_write_long_addr(addr++, hdr_length);
134 mrf_write_long_addr(addr++, hdr_length + data_length);
136 // frame control
137 mrf_write_long_addr(addr++, IEEE802_15_4_DATA | IEEE802_15_4_ACK_REQ);
138 mrf_write_long_addr(addr++, IEEE802_15_4_SHORT_DESTADDR | IEEE802_15_4_SHORT_SRCADDR | IEEE802_15_4_2003_VERSION);
140 // sequence number
141 mrf_write_long_addr(addr++, mrf_seq_num++);
143 // dest pan id
144 mrf_write_long_addr(addr++, pan_id);
145 mrf_write_long_addr(addr++, pan_id>>8);
147 // dest short addr
148 mrf_write_long_addr(addr++, short_addr);
149 mrf_write_long_addr(addr++, short_addr>>8);
151 // source pan id
152 mrf_write_long_addr(addr++, mrf_pan_id);
153 mrf_write_long_addr(addr++, mrf_pan_id>>8);
155 // source short addr
156 mrf_write_long_addr(addr++, mrf_short_addr);
157 mrf_write_long_addr(addr++, mrf_short_addr>>8);
159 for(uint8_t i = 0; i < data_length; ++i)
160 mrf_write_long_addr(addr++, data[i]);
162 mrf_status &= ~_BV(MRF_B_TXN);
163 // transmit frame, request acknowledgement
164 mrf_set_reg(MRF_R_TXNCON, _BV(MRF_B_ACKREQ) | _BV(MRF_B_TRIG));
167 uint8_t mrf_rx(uint16_t *pan_id, uint16_t *short_addr, uint8_t* data, uint8_t data_length)
169 // relying on fact that header is in same format as in tx function
170 // frame control + seq.num. + addressing fields
171 const uint8_t hdr_length = 2 + 1 + 2*(IEEE802_15_4_SHORT_ADDR_LENGTH + IEEE802_15_4_PAN_ID_LENGTH);
172 const uint16_t data_offset = MRF_BUF_RX + 1 + hdr_length;
174 // disable receiving packets off air
175 mrf_set_reg(MRF_R_BBREG1, _BV(MRF_B_RXDECINV));
177 // -2 because of fcs bytes
178 uint8_t length = mrf_read_long_addr(MRF_BUF_RX) - hdr_length - 2;
180 if(0 != pan_id)
181 *pan_id = mrf_read_long_addr(MRF_BUF_RX + 8) + (mrf_read_long_addr(MRF_BUF_RX + 9)<<8);
182 if(0 != short_addr)
183 *short_addr = mrf_read_long_addr(MRF_BUF_RX + 10) + (mrf_read_long_addr(MRF_BUF_RX + 11)<<8);
185 uint8_t i = 0;
186 for(; length != 0 && i < data_length; i++, length--)
187 data[i] = mrf_read_long_addr(data_offset + i);
189 mrf_lqi = mrf_read_long_addr(data_offset + i + 2);
190 mrf_rssi = mrf_read_long_addr(data_offset + i + 3);
192 // enable receiving packets off air
193 mrf_set_reg(MRF_R_BBREG1, 0);
195 mrf_status &= ~_BV(MRF_B_RX);
196 return i;
199 #endif // __MRF_IMPL__