1 | #include "RFM12B.h"
|
2 | #include "avr/io.h"
|
3 | #include "string.h"
|
4 |
|
5 | #define F_CPU 8000000UL
|
6 | #include <util/delay.h>
|
7 |
|
8 | void SPIInit() {
|
9 |
|
10 | SS_DDR |= (1 << cs_pin);
|
11 | //DI
|
12 | DDRB &= ~(1 << 5);
|
13 | //DO
|
14 | DDRB = (1 << 6);
|
15 | //SCK
|
16 | DDRB |= (1 << 7);
|
17 | //Interrupt Pin has Pullup
|
18 | DDRD &= ~(1 << 2);
|
19 | PORTD |= (1 << 2);
|
20 | }
|
21 |
|
22 |
|
23 | uint8_t Byte(uint8_t out){
|
24 |
|
25 | uint8_t returnvalue = 0;
|
26 | int8_t i;
|
27 | for (i = 7;i>=0;i--){
|
28 |
|
29 | //Bit low or high?
|
30 | if(out & (1<<i))
|
31 | PORTB |= (1<<6);
|
32 | else
|
33 | PORTB &= ~(1<<6);
|
34 |
|
35 | //Clock High
|
36 | PORTB |= (1 << 7);
|
37 | _delay_us(1);
|
38 |
|
39 | //Clock Low
|
40 | PORTB &= ~(1 << 7);
|
41 |
|
42 | //Read input
|
43 | if ( PINB & (1<<PINB5) ) {
|
44 | returnvalue |= (1<<i);
|
45 | }
|
46 | _delay_us(1);
|
47 | }
|
48 | return returnvalue;
|
49 | }
|
50 |
|
51 |
|
52 | uint16_t XFERSlow(uint16_t cmd) {
|
53 |
|
54 | SS_PORT &= ~(1 << cs_pin);
|
55 | uint16_t reply = Byte(cmd >> 8) << 8;
|
56 | reply |= Byte(cmd);
|
57 | SS_PORT |= (1 << cs_pin);
|
58 | return reply;
|
59 | }
|
60 |
|
61 | void XFER(uint16_t cmd) {
|
62 | SS_PORT &= ~(1 << cs_pin);
|
63 | Byte(cmd >> 8) << 8;
|
64 | Byte(cmd);
|
65 | SS_PORT |= (1 << cs_pin);
|
66 | }
|
67 |
|
68 | void Initialize(uint8_t ID, uint8_t networkid)
|
69 | {
|
70 |
|
71 |
|
72 | Data = rf12_data;
|
73 | DataLen = &rf12_buf[3];
|
74 |
|
75 | uint8_t txPower = 0;
|
76 | uint8_t airKbps = 0x08;
|
77 | uint8_t lowVoltageThreshold = RF12_2v75;
|
78 |
|
79 |
|
80 | cs_pin = SS_BIT;
|
81 | nodeID = ID;
|
82 | networkID = networkid;
|
83 | SPIInit();
|
84 | XFER(0x0000); // intitial SPI transfer added to avoid power-up problem
|
85 | XFER(RF_SLEEP_MODE); // DC (disable clk pin), enable lbd
|
86 |
|
87 | // wait until RFM12B is out of power-up reset, this takes several *seconds*
|
88 | XFER(RF_TXREG_WRITE); // in case we're still in OOK mode
|
89 | //Für den Tiny geändert: while (!(PIND & (1 << 3) ))
|
90 | while (!(PIND & (1 << 2) )) // digitalRead(18) == 0)
|
91 | XFER(0x0000);
|
92 |
|
93 | XFER(0x80C7 | (RF12_868MHZ << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF
|
94 | XFER(0xA640); // Frequency is exactly 434/868/915MHz (whatever freqBand is)
|
95 | XFER(0xC600 + airKbps); //Air transmission baud rate: 0x08= ~38.31Kbps
|
96 | XFER(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm
|
97 | XFER(0xC2AC); // AL,!ml,DIG,DQD4
|
98 | if (networkID != 0) {
|
99 | XFER(0xCA83); // FIFO8,2-SYNC,!ff,DR
|
100 | XFER(0xCE00 | networkID); // SYNC=2DXX;
|
101 | } else {
|
102 | XFER(0xCA8B); // FIFO8,1-SYNC,!ff,DR
|
103 | XFER(0xCE2D); // SYNC=2D;
|
104 | }
|
105 |
|
106 |
|
107 | XFER(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN
|
108 | XFER(0x9850 | (txPower > 7 ? 7 : txPower)); // !mp,90kHz,MAX OUT //last byte=power level: 0=highest, 7=lowest
|
109 | XFER(0xCC77); // OB1,OB0, LPX,!ddy,DDIT,BW0
|
110 | XFER(0xE000); // NOT USE
|
111 | XFER(0xC800); // NOT USE
|
112 | XFER(0xC043); // Clock output (1.66MHz), Low Voltage threshold (2.55V)
|
113 |
|
114 | rxstate = TXIDLE;
|
115 |
|
116 | //Für den Tiny geändert
|
117 | //Interupt enable
|
118 | //EICRA |= (1 << ISC31);
|
119 | //EICRA &= ~(1 << ISC30);
|
120 | //EIMSK |= (1 << INT3);
|
121 | MCUCR |= (1<<ISC01);
|
122 | MCUCR &= ~(1<<ISC00);
|
123 | GIMSK |= (1<<INT0);
|
124 |
|
125 | sei();
|
126 |
|
127 | }
|
128 |
|
129 |
|
130 | // access to the RFM12B internal registers with interrupts disabled
|
131 | uint16_t Control(uint16_t cmd) {
|
132 | //Für den Tiny geändert
|
133 | //EIMSK &= ~(1 << INT0);
|
134 | GIMSK &= ~(1<<INT0);
|
135 |
|
136 | uint16_t r = XFERSlow(cmd);
|
137 |
|
138 | //Für den Tiny geändert
|
139 | //EIMSK |= (1 << INT0);
|
140 | GIMSK |= (1<<INT0);
|
141 | return r;
|
142 | }
|
143 |
|
144 |
|
145 |
|
146 | void InterruptHandler() {
|
147 | XFER(0x0000);
|
148 |
|
149 | if (rxstate == TXRECV) {
|
150 | uint8_t in = XFERSlow(RF_RX_FIFO_READ);
|
151 |
|
152 | if (rxfill == 0 && networkID != 0)
|
153 | rf12_buf[rxfill++] = networkID;
|
154 |
|
155 | rf12_buf[rxfill++] = in;
|
156 | rf12_crc = _crc16_update(rf12_crc, in);
|
157 |
|
158 | if (rxfill >= rf12_len + 6 || rxfill >= RF_MAX)
|
159 | XFER(RF_IDLE_MODE);
|
160 | } else {
|
161 | uint8_t out;
|
162 |
|
163 | if (rxstate < 0) {
|
164 | uint8_t pos = 4 + rf12_len + rxstate++;
|
165 | out = rf12_buf[pos];
|
166 | rf12_crc = _crc16_update(rf12_crc, out);
|
167 | } else
|
168 | switch (rxstate++) {
|
169 | case TXSYN1: out = 0x2D; break;
|
170 | case TXSYN2: out = networkID; rxstate = -(3 + rf12_len); break;
|
171 | case TXCRC1: out = rf12_crc; break;
|
172 | case TXCRC2: out = rf12_crc >> 8; break;
|
173 | case TXDONE: XFER(RF_IDLE_MODE);
|
174 | default: out = 0xAA;
|
175 | }
|
176 |
|
177 | XFER(RF_TXREG_WRITE + out);
|
178 | }
|
179 | }
|
180 |
|
181 | //Für den Tiny geändert:
|
182 | //ISR(INT3_vect) {
|
183 | ISR(INT0_vect) {
|
184 |
|
185 | InterruptHandler();
|
186 | }
|
187 |
|
188 |
|
189 | void ReceiveStart() {
|
190 | rxfill = rf12_len = 0;
|
191 | rf12_crc = ~0;
|
192 | if (networkID != 0)
|
193 | rf12_crc = _crc16_update(~0, networkID);
|
194 | rxstate = TXRECV;
|
195 | XFER(RF_RECEIVER_ON);
|
196 | }
|
197 |
|
198 | char ReceiveComplete() {
|
199 | if (rxstate == TXRECV && (rxfill >= rf12_len + 6 || rxfill >= RF_MAX)) {
|
200 | rxstate = TXIDLE;
|
201 | if (rf12_len > RF12_MAXDATA)
|
202 | rf12_crc = 1;
|
203 | if (RF12_DESTID == 0 || RF12_DESTID == nodeID) {
|
204 | if (!rf12_crc)
|
205 | rf12_seq = -1;
|
206 | return 1;
|
207 | }
|
208 | }
|
209 | if (rxstate == TXIDLE)
|
210 | ReceiveStart();
|
211 | return 0;
|
212 | }
|
213 |
|
214 | char CanSend() {
|
215 |
|
216 | if (rxstate == TXRECV && rxfill == 0 && (Byte(0x00) & (RF_RSSI_BIT >> 8)) == 0) {
|
217 | XFER(RF_IDLE_MODE);
|
218 | rxstate = TXIDLE;
|
219 | return 1;
|
220 | }
|
221 | return 0;
|
222 | }
|
223 |
|
224 | void SendStart(uint8_t toNodeID, char requestACK, char sendACK) {
|
225 | rf12_hdr1 = toNodeID | (sendACK ? RF12_HDR_ACKCTLMASK : 0);
|
226 | rf12_hdr2 = nodeID | (requestACK ? RF12_HDR_ACKCTLMASK : 0);
|
227 | rf12_crc = ~0;
|
228 | rf12_crc = _crc16_update(rf12_crc, networkID);
|
229 | rxstate = TXPRE1;
|
230 | XFER(RF_XMITTER_ON);
|
231 | }
|
232 |
|
233 | void SendStart2(uint8_t toNodeID, const void* sendBuf, uint8_t sendLen, char requestACK, char sendACK, uint8_t waitMode) {
|
234 | rf12_len = sendLen;
|
235 | memcpy((void*) rf12_data, sendBuf, sendLen);
|
236 |
|
237 |
|
238 |
|
239 | SendStart(toNodeID, requestACK, sendACK);
|
240 |
|
241 | SendWait(waitMode);
|
242 | }
|
243 |
|
244 |
|
245 | void SendACK2(const void* sendBuf, uint8_t sendLen, uint8_t waitMode) {
|
246 | while (!CanSend()) ReceiveComplete();
|
247 | SendStart2(RF12_SOURCEID, sendBuf, sendLen, 0, 1, waitMode);
|
248 | }
|
249 |
|
250 |
|
251 |
|
252 | void SendACK() {
|
253 | const void* sendBuf = "";
|
254 | uint8_t sendLen = 0;
|
255 | uint8_t waitMode = SLEEP_MODE_IDLE;
|
256 | while (!CanSend()) ReceiveComplete();
|
257 | SendStart2(RF12_SOURCEID, sendBuf, sendLen, 0, 1, waitMode);
|
258 | }
|
259 |
|
260 |
|
261 |
|
262 | void Send(uint8_t toNodeID, const void* sendBuf, uint8_t sendLen, char requestACK)
|
263 | {
|
264 | uint8_t waitMode = SLEEP_MODE_STANDBY;
|
265 | while (!CanSend()) ReceiveComplete();
|
266 | SendStart2(toNodeID, sendBuf, sendLen, requestACK, 0, waitMode);
|
267 | }
|
268 |
|
269 | void SendWait(uint8_t waitMode) {
|
270 | while (rxstate != TXIDLE);
|
271 |
|
272 | }
|
273 |
|
274 | void OnOff(uint8_t value) {
|
275 | XFER(value ? RF_XMITTER_ON : RF_IDLE_MODE);
|
276 | }
|
277 |
|
278 | void Sleep2(char n) {
|
279 | if (n < 0)
|
280 | Control(RF_IDLE_MODE);
|
281 | else {
|
282 | Control(RF_WAKEUP_TIMER | 0x0500 | n);
|
283 | Control(RF_SLEEP_MODE);
|
284 | if (n > 0)
|
285 | Control(RF_WAKEUP_MODE);
|
286 | }
|
287 | rxstate = TXIDLE;
|
288 | }
|
289 | void Sleep() { Sleep2(0); }
|
290 | void Wakeup() { Sleep2(-1); }
|
291 |
|
292 | char LowBattery() {
|
293 | return (Control(0x0000) & RF_LBD_BIT) != 0;
|
294 | }
|
295 |
|
296 | uint8_t GetSender() {
|
297 | return RF12_SOURCEID;
|
298 | }
|
299 |
|
300 | uint8_t * GetData() { return rf12_data; }
|
301 |
|
302 |
|
303 | uint8_t GetDataLen() { return *DataLen; }
|
304 | char ACKRequested() { return RF12_WANTS_ACK; }
|
305 |
|
306 | char ACKReceived(uint8_t fromNodeID) {
|
307 | if (ReceiveComplete())
|
308 | return CRCPass() &&
|
309 | RF12_DESTID == nodeID &&
|
310 | (RF12_SOURCEID == fromNodeID || fromNodeID == 0) &&
|
311 | (rf12_hdr1 & RF12_HDR_ACKCTLMASK) &&
|
312 | !(rf12_hdr2 & RF12_HDR_ACKCTLMASK);
|
313 | return 0;
|
314 | }
|
315 |
|
316 | char CRCPass() {
|
317 | return rf12_crc == 0;
|
318 | }
|