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/>.
25 #include <util/delay.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
)
41 spi_shift_byte(0x1 | (addr
<< 1));
47 // get and return value of given short register via spi
48 uint8_t mrf_read_short_addr(uint8_t addr
)
53 spi_shift_byte(addr
<< 1);
54 uint8_t res
= spi_shift_byte(0x00);
60 // set given long register to given value via spi
61 void mrf_write_long_addr(uint16_t addr
, uint8_t val
)
66 spi_shift_byte(0x80 | (addr
>> 3));
67 spi_shift_byte(0x10 | (addr
<< 5));
73 // get and return value of given long register via spi
74 uint8_t mrf_read_long_addr(uint16_t addr
)
79 spi_shift_byte(0x80 | (addr
>> 3));
80 spi_shift_byte(addr
<< 5);
81 uint8_t res
= spi_shift_byte(0x00);
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);
93 mrf_set_reg(MRF_R_RFCTL
, _BV(MRF_B_RFRST
));
94 mrf_set_reg(MRF_R_RFCTL
, 0);
98 // reset and initialize radio
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);
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
);
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
);
141 mrf_write_long_addr(addr
++, mrf_seq_num
++);
144 mrf_write_long_addr(addr
++, pan_id
);
145 mrf_write_long_addr(addr
++, pan_id
>>8);
148 mrf_write_long_addr(addr
++, short_addr
);
149 mrf_write_long_addr(addr
++, short_addr
>>8);
152 mrf_write_long_addr(addr
++, mrf_pan_id
);
153 mrf_write_long_addr(addr
++, mrf_pan_id
>>8);
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;
181 *pan_id
= mrf_read_long_addr(MRF_BUF_RX
+ 8) + (mrf_read_long_addr(MRF_BUF_RX
+ 9)<<8);
183 *short_addr
= mrf_read_long_addr(MRF_BUF_RX
+ 10) + (mrf_read_long_addr(MRF_BUF_RX
+ 11)<<8);
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
);
199 #endif // __MRF_IMPL__