/*******************
* Funktransceiver *
*******************/
#include "rfm12.h"
#include <avr/io.h>
#include <avr/pgmspace.h>
/* Empirisches Kanalraster (12 Kanäle im Abstand 145 kHz, ∆F = 58)
Kanal F Anfang Ende
1 1237 433,05 433,195
2 1295 433,195 433,34
3 1353 433,34 433,485
4 1411 433,485 433.63
5 1469 433.63 433.775
6 1527 433.775 433.92
7 1585 433.92 434.065
8 1643 434.065 434.21
9 1701 434.21 434.355
10 1759 434.355 434.5
11 1817 434.5 434.645
12 1991 434.645 434.79
SPI __ (CPOL=CPHA=0) ___
!SS \__________________________ __________/
___ ___ ___ ___
SCK _______/ \___/ \___/ \_ __/ \_______
___ _______ _______ _______ _ ______________
MOSI___X_______X_______X_______X_ ______________
____ _______ _______ _______ ______________
MISO____X__↑____X__↑____X__↑____X __↑___________
*/
// Daten-WORD „austauschen“. Blockiert 2,6 µs
WORD rf_xfer(WORD data) {
PORTB&=~0x04; // !SS aktivieren
asm volatile("out %0,%B1" :: "I" (_SFR_IO_ADDR(SPDR)), "r" (data));
while (!(SPSR&1<<SPIF)); // warten bis High-Byte fertig
asm volatile("in %B0,%2" : "=r" (data): "0"(data), "I" (_SFR_IO_ADDR(SPDR)));
asm volatile("out %0,%A1" :: "I" (_SFR_IO_ADDR(SPDR)), "r" (data));
while (!(SPSR&1<<SPIF)); // warten bis Low-Byte fertig
asm volatile("in %A0,%2" : "=r" (data): "0"(data), "I" (_SFR_IO_ADDR(SPDR)));
PORTB|=0x04; // !SS deaktivieren
return data;
}
BYTE txch=1; // Sende-Kanal (1..12), 0 = keine Belegung
BYTE rxch=1; // Empfangs-Kanal (unterschiedlich während Frequenz-Hopping)
PROGMEM static const WORD rf_inittab[]={
0x8208, // (2) Quarz reaktivieren
0x80D7, // (1) FIFO benutzen, 433-MHz-Band, 12 pF Ballastkapazität
0xC2AC, // (6) Datenfilter: Auto-Lock setzen (??)
0xCA81, // (7) FIFO-Modus: Reset-Modus (??)
0x94C0, // (5) VDI-Ausgang, Bandbreite 67 kHz, maximale Empfindlichkeit
0x9820, // (10) Hub ∆f = ± 45 kHz, Ausgangsleistung = 0 dB (maximal)
0xC611, // (4) Datenrate ≈ 19,2 kbit/s (keine Orthogonalität mit η = 4,68)
// 0xE000, // (12) kein WakeUpTimer (ist sowieso aus!)
// 0xC800, // (13) kein LowDutyCycle (ist sowieso aus!)
// 0xC4F7, // (9) AFC
};
// Kanal (Mittenfrequenz) setzen
void rf_setch(BYTE ch) {
rf_xfer(0xA000|1237+(ch-1)*58); // (3) Mittenfrequenz setzen
}
// Initialisierungssequenz
void rf_init() {
int i;
for (i=0; i<elemof(rf_inittab); i++) {
rf_xfer(pgm_read_word(rf_inittab+i));
}
rf_setch(txch);
}
// Modusumschaltung. Bit 0 = Sender EIN, Bit 1 = Empfänger EIN
void rf_mode(BYTE sw) {
rf_xfer(0xCA81); // (7) Rahmensynchronwort(rest) löschen
if (sw&2) {
rf_xfer(sw&1 ? 0x82F9 : 0x82C9); // (2)
rf_xfer(0xCA83); // FIFO freigeben für Rahmensynchronwort (2DD4h)
}else{
rf_xfer(sw&1 ? 0x8239 : 0x8209); // (2)
}
}
BYTE rf_tx(BYTE b) {
while (PINB&1); // warte bis !IRQ = low
return rf_xfer(0xB800|b); // (11)
}
Detected encoding: UTF-8 | 0
|