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 // 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);
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
);
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
);
144 mrf_write_long_addr(addr
++, mrf_seq_num
++);
147 mrf_write_long_addr(addr
++, pan_id
);
148 mrf_write_long_addr(addr
++, pan_id
>>8);
151 mrf_write_long_addr(addr
++, short_addr
);
152 mrf_write_long_addr(addr
++, short_addr
>>8);
155 mrf_write_long_addr(addr
++, mrf_pan_id
);
156 mrf_write_long_addr(addr
++, mrf_pan_id
>>8);
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;
184 *pan_id
= mrf_read_long_addr(MRF_BUF_RX
+ 8) + (mrf_read_long_addr(MRF_BUF_RX
+ 9)<<8);
186 *short_addr
= mrf_read_long_addr(MRF_BUF_RX
+ 10) + (mrf_read_long_addr(MRF_BUF_RX
+ 11)<<8);
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
);
202 #endif // __MRF_IMPL__