1 | /********************************************************************
|
2 | RFM02-Funkmodul (Empfangen)
|
3 |
|
4 | -----------------------
|
5 | ATMEGA168PA RFM01
|
6 | -----------------------
|
7 | XCK (PD4).........SCK
|
8 | TXD (PD1).........SDI
|
9 | PD7...............nSEL
|
10 | RXD (PD0).........SDO
|
11 | PB1...............nIRQ
|
12 | PD3...............nFFS
|
13 |
|
14 | PB5...............LED
|
15 | PD2...............Module-Power
|
16 | *********************************************************************/
|
17 |
|
18 | #include <avr/io.h>
|
19 | #include <util/delay.h>
|
20 | #include <avr/interrupt.h>
|
21 |
|
22 | #define DDR_XCK DDRD
|
23 | #define XCK 4
|
24 | #define DDR_LED DDRB
|
25 | #define LED 5
|
26 | #define DDR_BLED DDRC
|
27 | #define BLED 0
|
28 | #define DDR_MODULE DDRD
|
29 | #define MODULE_POWER 2
|
30 | #define DDR_nSEL DDRD
|
31 | #define nSEL 7
|
32 | #define DDR_nIRQ DDRB
|
33 | #define nIRQ 1
|
34 | #define DDR_nFFS DDRD
|
35 | #define nFFS 3
|
36 |
|
37 |
|
38 | #define LED_ON() PORTB |= (1<<LED)
|
39 | #define LED_OFF() PORTB &= ~(1<<LED)
|
40 | #define BLED_ON() PORTC |= (1<<BLED)
|
41 | #define BLED_OFF() PORTC &= ~(1<<BLED)
|
42 |
|
43 | #define MODULE_ON() PORTD |= (1<<MODULE_POWER)
|
44 | #define MODULE_OFF() PORTD &= ~(1<<MODULE_POWER)
|
45 | #define nSEL_HIGH() PORTD |= (1<<nSEL)
|
46 | #define nSEL_LOW() PORTD &= ~(1<<nSEL)
|
47 | #define nIRQ_HIGH() PINB&(1<<nIRQ)
|
48 | #define nIRQ_LOW() !(PINB&(1<<nIRQ))
|
49 | #define nFFS_HIGH() PORTD |= (1<<nFFS)
|
50 | #define nFFS_LOW() PORTD &= ~(1<<nFFS)
|
51 |
|
52 | #define FOSC 8000000 // Clock Speed
|
53 | #define BAUD 1000
|
54 | #define MYUBRR FOSC/(2*BAUD)-1
|
55 |
|
56 | void init_gpio()
|
57 | {
|
58 | // Initialize On-Board LED on PB5
|
59 | LED_OFF();
|
60 | DDR_LED |= (1<<LED);
|
61 |
|
62 | BLED_OFF();
|
63 | DDR_BLED |= (1<<BLED);
|
64 |
|
65 | // Initialize Module Power
|
66 | MODULE_OFF();
|
67 | DDR_MODULE |= (1<<MODULE_POWER);
|
68 |
|
69 | // Initialize nFFS FIFO Select
|
70 | nFFS_LOW();
|
71 | DDR_nFFS |= (1<<nFFS);
|
72 |
|
73 | // Initialize nSEL
|
74 | nSEL_LOW();
|
75 | DDR_nSEL |= (1<<nSEL);
|
76 |
|
77 | // Initialize nIRQ (Input)
|
78 | // Deactivate internal Pull-Up
|
79 | PORTB &= ~(1<<nIRQ);
|
80 | DDR_nIRQ &= ~(1<<nIRQ);
|
81 | }
|
82 |
|
83 | void init_usart_as_spi_for_cmd(unsigned int ubrr)
|
84 | {
|
85 | // SPI MODE 0 -> Data sheet page 197
|
86 | // This mode is used to transmit commands
|
87 |
|
88 | // Disable transmitter and receiver
|
89 | UCSR0B &= ~((1<<TXEN0) | (1<<RXEN0));
|
90 |
|
91 | //Choose Baud Rate to zero for initialization
|
92 | UBRR0 = 0;
|
93 |
|
94 | // First: Activate the Clock Generation
|
95 | DDR_XCK |=(1<<XCK);
|
96 |
|
97 | // Use USART0 in Master SPI Mode (MSPIM)
|
98 | UCSR0C |= (1<<UMSEL01) | (1<<UMSEL00);
|
99 |
|
100 | // Define SPI Data Order, Clock Phase and Clock Polarity
|
101 | // Data Order of RF02: MSB first
|
102 | UCSR0C &= ~(1<<UCSZ01);
|
103 | // SPI Mode 0 (I found it out with data sheets)
|
104 | // Clock Phase: Data shifted in RF02 on Rising Edge of SCK
|
105 | UCSR0C &= ~(1<<UCSZ00);
|
106 | // Clock Polarity: Low is idle status
|
107 | UCSR0C &= ~(1<<UCPOL0);
|
108 |
|
109 | // Enable transmitter and receiver
|
110 | UCSR0B |= (1<<TXEN0) | (1<<RXEN0);
|
111 | //UCSR0B |= (1<<TXEN0);
|
112 |
|
113 | // Set Baud Rate
|
114 | //UBRR0 = MYUBRR;
|
115 | UBRR0 = 4095;
|
116 |
|
117 | // Data Register Empty Interrupt Enable
|
118 | //UCSR0B |= (1<<TXCIE0) | (1<<RXCIE0);
|
119 | //UCSR0B |= (1<<UDRIE0);
|
120 | //sei();
|
121 | }
|
122 |
|
123 | void init_usart_as_spi_for_read(unsigned int ubrr)
|
124 | {
|
125 | // SPI MODE 1 -> Data sheet page 197
|
126 | // This mode is used to read status or received data
|
127 |
|
128 | // Disable transmitter and receiver
|
129 | UCSR0B &= ~((1<<TXEN0) | (1<<RXEN0));
|
130 |
|
131 | //Choose Baud Rate to zero for initialization
|
132 | UBRR0 = 0;
|
133 |
|
134 | // First: Activate the Clock Generation
|
135 | DDR_XCK |=(1<<XCK);
|
136 |
|
137 | // Use USART0 in Master SPI Mode (MSPIM)
|
138 | UCSR0C |= (1<<UMSEL01) | (1<<UMSEL00);
|
139 |
|
140 | // Define SPI Data Order, Clock Phase and Clock Polarity
|
141 | // Data Order of RF02: MSB first
|
142 | UCSR0C &= ~(1<<UCSZ01);
|
143 | // SPI Mode 1 (I found it out with data sheets)
|
144 | // Clock Phase: Data shifted out of RF01 on Falling Edge of SCK
|
145 | UCSR0C |= (1<<UCSZ00);
|
146 | // Clock Polarity: Low is idle status
|
147 | UCSR0C &= ~(1<<UCPOL0);
|
148 |
|
149 | // Enable transmitter and receiver
|
150 | UCSR0B |= (1<<TXEN0) | (1<<RXEN0);
|
151 | //UCSR0B |= (1<<TXEN0);
|
152 |
|
153 | // Set Baud Rate
|
154 | //UBRR0 = MYUBRR;
|
155 | UBRR0 = 4095;
|
156 |
|
157 | // Data Register Empty Interrupt Enable
|
158 | //UCSR0B |= (1<<TXCIE0) | (1<<RXCIE0);
|
159 | //UCSR0B |= (1<<UDRIE0);
|
160 | //sei();
|
161 | }
|
162 |
|
163 | void view_byte(uint8_t byte)
|
164 | {
|
165 | unsigned wait = 700;
|
166 | for (int bit=0;bit<8;bit++)
|
167 | {
|
168 | LED_ON();
|
169 | if ((byte & 0b00000001)==0) BLED_OFF();
|
170 | else BLED_ON();
|
171 | _delay_ms(wait);
|
172 | LED_OFF();
|
173 | _delay_ms(wait);
|
174 | byte = byte>>1;
|
175 | }
|
176 | BLED_OFF();
|
177 | }
|
178 |
|
179 | void error()
|
180 | {
|
181 | for (int i=0; i<20;i++)
|
182 | {
|
183 | LED_ON();
|
184 | _delay_ms(50);
|
185 | LED_OFF();
|
186 | _delay_ms(50);
|
187 | }
|
188 | }
|
189 |
|
190 | uint8_t receive_usart()
|
191 | {
|
192 | if( UCSR0A & (1<<RXC0) ) return UDR0;
|
193 | else
|
194 | {
|
195 | error();
|
196 | return 0;
|
197 | }
|
198 |
|
199 | }
|
200 |
|
201 | void transmitCmd(uint16_t cmd)
|
202 | {
|
203 | // Clear TXC0 flag for new transmission. It is not cleared automatically because no transmit complete interrupt is executed.
|
204 | // Clearing this bit by writing a one to its bit location <--- Yes, its true!
|
205 | UCSR0A |= (1<<TXC0);
|
206 |
|
207 | nSEL_LOW();
|
208 |
|
209 | uint8_t byteToSend = 0;
|
210 |
|
211 | // Wait for empty transmit buffer
|
212 | while ( !(UCSR0A & (1<<UDRE0)) );
|
213 |
|
214 | byteToSend = (cmd & 0b1111111100000000)>>8;
|
215 | UDR0 = byteToSend;
|
216 |
|
217 | // Wait for empty transmit buffer
|
218 | while ( !(UCSR0A & (1<<UDRE0)) );
|
219 |
|
220 | byteToSend = (cmd & 0b0000000011111111);
|
221 | UDR0 = byteToSend;
|
222 |
|
223 | //while ( !(UCSR0A & (1<<RXC0)) ) LED_ON();
|
224 | //LED_OFF();
|
225 | //_delay_ms(100);
|
226 | /* Get and return received data from buffer */
|
227 |
|
228 | while(!(UCSR0A & (1<<TXC0)));
|
229 | _delay_ms(1);
|
230 | nSEL_HIGH();
|
231 |
|
232 | // Wait for data to be received
|
233 | //while ( !(UCSR0A & (1<<RXC0)) );
|
234 | // Get and return received data from buffer
|
235 | //return UDR0;
|
236 | }
|
237 |
|
238 | /*
|
239 | void transmitData(uint16_t data)
|
240 | {
|
241 | uint8_t irq = 0;
|
242 | while(nIRQ_HIGH());
|
243 | for (int bit=0;bit<8;bit++)
|
244 | {
|
245 | if(data & 0b10000000) HIGH_BIT();
|
246 | else LOW_BIT();
|
247 | data = data<<1;
|
248 |
|
249 | if (nIRQ_LOW()) irq &= ~(1<<bit);
|
250 | while(nIRQ_LOW());
|
251 | if (nIRQ_HIGH()) irq |= (1<<bit);
|
252 | while(nIRQ_HIGH());
|
253 | }
|
254 | view_byte(irq);
|
255 | }
|
256 | */
|
257 |
|
258 | void clearTXBuffer()
|
259 | {
|
260 | uint8_t tmp;
|
261 | while (UCSR0A & (1<<RXC0)) tmp = UDR0;
|
262 | }
|
263 |
|
264 | void init_rf01()
|
265 | {
|
266 | // nFFS High recommended by data sheet
|
267 | nFFS_HIGH();
|
268 |
|
269 | // Switch on RF01
|
270 | MODULE_ON();
|
271 |
|
272 | // Initialize Module
|
273 | nSEL_HIGH();
|
274 | }
|
275 |
|
276 | void heartbeat()
|
277 | {
|
278 | //LED_ON();
|
279 | BLED_ON();
|
280 | _delay_ms(200);
|
281 | //LED_OFF();
|
282 | BLED_OFF();
|
283 | _delay_ms(200);
|
284 | //LED_ON();
|
285 | BLED_ON();
|
286 | _delay_ms(200);
|
287 | //LED_OFF();
|
288 | BLED_OFF();
|
289 | _delay_ms(200);
|
290 | }
|
291 |
|
292 | int main(void)
|
293 | {
|
294 | init_gpio();
|
295 | _delay_ms(1000);
|
296 | init_rf01();
|
297 |
|
298 | heartbeat();
|
299 | _delay_ms(1000);
|
300 |
|
301 | uint8_t dataReceived = 0;
|
302 |
|
303 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
304 | ////////////////////////////////////////////////////////////// COMMANDS /////////////////////////////////////////////////////////////
|
305 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
306 |
|
307 | // 1: Configuration Setting Command: Frequency band, low battery detector, wake-up timer, crystal oscillator load capacitance, baseband filter bandwidth, clock output
|
308 | // 100 (CMD) 01 (433 MHz) 00 (Low Batteery Det Off) 1 (Crystal On During Sleep Mode) 1000 (x3-x0 Crystal Load Cap) 101 (Baseband Bandwidth) 0 (dc)
|
309 | uint16_t configSetCmd = 0b1000100110001010;
|
310 |
|
311 | // 2: Frequency Setting Command: Set the frequency of the local oscillator
|
312 | // 1010 (CMD) 0110 0100 0000 (F) -> f0 = 10 MHz * 1 * (43 + 1600(F)/4000) = 434 MHz
|
313 | // F = 96 to 3903
|
314 | uint16_t freqSetCmd = 0b1010011001000000;
|
315 |
|
316 | // 3: Receiver Setting Command: Set VDI source, LNA gain, RSSI threshold
|
317 | // 1100 0000 (CMD) 10 (Valid Data Indicator VDI Output) 00 (LNA Gain) 000 (RSSI Threshold) 0 (Enable Receiver Chain)
|
318 | uint16_t receiverSetCmd = 0b1100000010000000;
|
319 | uint16_t enableReceiverCmd = 0b1100000010000001;
|
320 |
|
321 | // 4: Wake-Up Timer Command: Wake-up time period
|
322 | uint16_t wakeUpTimerCmd = 0;
|
323 |
|
324 | // 5: Low Duty-Cycle Command: Set duty-cycle, enable low duty-cycle mode
|
325 | uint16_t lowDutyCycleCmd = 0;
|
326 |
|
327 | // 6: Low Battery Detector and Clock Divider Command: Set LBD threshold voltage and microcontroller clock division ratio
|
328 | // 1100 0010 (CMD) 010 (d2-d0 Clk Output Frequency) 00000 (t4-t0 Low Battery Threshold Voltage) -> V = 2.25V + T*0.1V
|
329 | uint16_t lowBatClockDivCmd = 0b1100001001000000;
|
330 |
|
331 | // 7: AFC Control Command: Set AFC parameters
|
332 | // 1100 0110 (CMD) 10 (Automatic Operation) 01 (Frequency Offset Limit) 1 (Strobe Edge) 0 (High accuracy mode) 1 (Output frequency offset register) 1 (Calculate offset frequency)
|
333 | uint16_t afcControlCmd = 0b1100011010011011;
|
334 |
|
335 | // 8: Data Filter Command: Set data filter type, clock recovery parameters
|
336 | // 1100 0100 (CMD) 0 (Clk Recovery Auto Lock Control) 0 (Clk Recovery Lock Control) 1 (x) 01 (Filter Type) 010 (f2-f0 DQD Threshold Parameter)
|
337 | uint16_t dataFilterCmd = 0b1100010000101010;
|
338 |
|
339 | // 9: Data Rate Command: Bit rate
|
340 | // 1100 1000 (CMD) 0 (cs) 100 0111 (R) -> BR = 10 MHz / 29 / (R+1) / (1+cs*7) = 10 MHz / 29 / (71+1) / (1+0*7) = 4,789 kbps
|
341 | // Data rate = 600 bps to 115,2 kbps
|
342 | uint16_t dataRateCmd = 0b1100100001000111;
|
343 |
|
344 | // 10: Output and FIFO Command: Set FIFO IT level, FIFO start control, FIFO enable and FIFO fill enable
|
345 | // 1100 1110 (CMD) 1000 (f3-f0 FIFO Interrupt IT Level) 01 (FIFO Fill Start Condition) 0 (Enables FIFO Fill After Synchron Word Reception) 0 (Enables 16 bit Deep FIFO Mode)
|
346 | uint16_t outputFifoCmd = 0b1100111010000100;
|
347 | uint16_t enableFifoCmd = 0b1100111010000111;
|
348 |
|
349 | // 11: Reset Mode Command: Enable / disable sensitive reset
|
350 | uint16_t resetModeCmd = 0;
|
351 |
|
352 | // 12: Status Register Command: Read status information
|
353 | uint16_t statusReadCmd = 0b0000000000000000;
|
354 |
|
355 |
|
356 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
357 | ////////////////////////////////////////////////////////// Configure RF02 ///////////////////////////////////////////////////////////
|
358 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
359 |
|
360 | uint16_t wait = 250;
|
361 |
|
362 |
|
363 | //transmitCmd(statusReadCmd);
|
364 | //dataReceived = receive_usart();
|
365 | //if(dataReceived != 0) view_byte(dataReceived);
|
366 | //dataReceived = receive_usart();
|
367 | //if(dataReceived != 0) view_byte(dataReceived);
|
368 | /*
|
369 | //_delay_ms(wait);
|
370 | heartbeat();
|
371 | transmitCmd(configSetCmd);
|
372 | clearTXBuffer();
|
373 |
|
374 | //_delay_ms(wait);
|
375 | heartbeat();
|
376 | transmitCmd(freqSetCmd);
|
377 | clearTXBuffer();
|
378 |
|
379 | //_delay_ms(wait);
|
380 | heartbeat();
|
381 | transmitCmd(dataRateCmd);
|
382 | clearTXBuffer();
|
383 |
|
384 | //_delay_ms(wait);
|
385 | heartbeat();
|
386 | transmitCmd(afcControlCmd);
|
387 | clearTXBuffer();
|
388 |
|
389 | //_delay_ms(wait);
|
390 | heartbeat();
|
391 | transmitCmd(dataFilterCmd);
|
392 | clearTXBuffer();
|
393 |
|
394 | //_delay_ms(wait);
|
395 | heartbeat();
|
396 | transmitCmd(lowBatClockDivCmd);
|
397 | clearTXBuffer();
|
398 |
|
399 | //_delay_ms(wait);
|
400 | heartbeat();
|
401 | transmitCmd(receiverSetCmd);
|
402 | clearTXBuffer();
|
403 |
|
404 | //_delay_ms(wait);
|
405 | heartbeat();
|
406 | transmitCmd(outputFifoCmd);
|
407 | clearTXBuffer();
|
408 |
|
409 | //_delay_ms(wait);
|
410 | heartbeat();
|
411 | transmitCmd(enableFifoCmd);
|
412 | clearTXBuffer();
|
413 |
|
414 | //_delay_ms(wait);
|
415 | heartbeat();
|
416 | transmitCmd(enableReceiverCmd);
|
417 | clearTXBuffer();
|
418 | */
|
419 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
420 | /////////////////////////////////////////////////////// Start Transmission //////////////////////////////////////////////////////////
|
421 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
422 | //_delay_ms(wait*4);
|
423 |
|
424 | init_usart_as_spi_for_cmd(MYUBRR);
|
425 |
|
426 | //transmitCmd(outputFifoCmd);
|
427 | //clearTXBuffer();
|
428 |
|
429 | while(1)
|
430 | {
|
431 | BLED_ON();
|
432 | _delay_ms(2000);
|
433 | BLED_OFF();
|
434 | _delay_ms(2000);
|
435 |
|
436 | transmitCmd(statusReadCmd);
|
437 | clearTXBuffer();
|
438 |
|
439 |
|
440 | /*
|
441 | if(dataReceived != 0) view_byte(dataReceived);
|
442 | dataReceived = receive_usart();
|
443 | if(dataReceived != 0) view_byte(dataReceived);
|
444 | */
|
445 |
|
446 | //transmitCmd(statusReadCmd);
|
447 | //clearTXBuffer();
|
448 | /*
|
449 | //dataReceived = receive_usart();
|
450 | //_delay_ms(2000);
|
451 |
|
452 | LED_ON();
|
453 | _delay_ms(2000);
|
454 | transmitCmd(powerManagementCmd);
|
455 | // Wait for PLL and Crystal Start
|
456 | _delay_ms(10);
|
457 | //_delay_ms(wait);
|
458 | transmitData(0b1010101010101010);
|
459 | //_delay_ms(wait);
|
460 | transmitCmd(standbyCmd);
|
461 | LED_OFF();
|
462 |
|
463 | _delay_ms(2000);
|
464 | heartbeat();
|
465 | _delay_ms(2000);
|
466 | */
|
467 | };
|
468 | }
|
469 |
|
470 | ISR (USART_TX_vect)
|
471 | {
|
472 |
|
473 | }
|
474 |
|
475 | ISR (USART_RX_vect)
|
476 | {
|
477 |
|
478 | }
|