-/* $Id: rfm12.c,v 1.1 2010/07/11 09:09:26 simimeie Exp $
+/* $Id: rfm12.c,v 1.2 2010/07/24 20:55:48 simimeie Exp $
* Functions for communicating with the rfm12(b) module
*/
/* Consequently, this SELECTS the chip */
#define spi_ss_lo() { PORTC &= (uint8_t)~_BV(0); }
-static void spi_sendbyte(uint8_t v) {
+/* write and (at the same time) read a word from RFM12.
+ * The module uses 16 bit commands and replies that are
+ * synchronous to the command - except for the status read.
+ * Note: This does not handle chip select! */
+static uint16_t rfm12_spi_wrword(uint16_t v) {
+ uint16_t res;
/* Start transmission */
- SPDR = v;
+ SPDR = v >> 8;
/* Wait for transmission complete */
while ((SPSR & _BV(SPIF)) == 0) {
}
-}
-
-static uint8_t spi_readbyte() {
- SPDR = 0x00; /* Dummy write */
+ res = (uint16_t)(SPDR) << 8;
+ SPDR = v & 0xff;
+ /* Wait for transmission complete */
while ((SPSR & _BV(SPIF)) == 0) {
}
- /* Return Data Register */
- return SPDR;
+ res |= SPDR & 0xff;
+ return res;
+}
+
+void rfm12_sendcommand(uint16_t cmd) {
+ spi_ss_lo();
+ rfm12_spi_wrword(cmd);
+ spi_ss_hi();
+}
+
+uint32_t rfm12_readstatus(void) {
+ uint32_t res;
+ spi_ss_lo();
+ res = (uint32_t)rfm12_spi_wrword(0x0000) << 16;
+ res |= rfm12_spi_wrword(0x0000);
+ spi_ss_hi();
+ return res;
}
void rfm12_init(void) {
/* Set MOSI, SCK and SS output, MISO input */
- DDRB |= _BV(3) | _BV(5);
+ /* Frickel Alert: Also set PB2 output. It is not used, but noise on the
+ * pin could reset our SPI mode to slave (!!!) if it is left as input. */
+ DDRB |= _BV(3) | _BV(5) | _BV(2);
DDRC |= _BV(0);
DDRB &= (uint8_t)~_BV(4);
spi_ss_hi();
+#if (CPUFREQ <= 10000000UL)
/* Enable SPI, Master, set clock rate fck/4.
* This works as long as our own clockrate is below 10 MHz - because
* 2.5 MHz is the maximum the rfm12b can do. */
SPCR |= _BV(SPE) | _BV(MSTR);
+#else
+ /* For higher clock rates set fck/16. */
+ SPCR |= _BV(SPE) | _BV(MSTR) | _BV(SPR0);
+#endif /* CPUFREQ */
+ /* Now send some initialization commands. */
+ /* Mostly taken over from http://www.joachim-neu.de/post/70/rfm12b-868/
+ * Seems to be mostly black magic anyways. */
+ rfm12_sendcommand(0x80E7); /* EL, EF, 868band, 12.0pF */
+ rfm12_sendcommand(0x8219); /* !er, !ebb, !ET, ES, EX, !eb, !ew, DC */
+ /* Frequency setting: 0xAnnn; the 12 nnn-bits of value are
+ * calculated like this: v = ((freq / 20) - 43) * 4000
+ */
+ rfm12_sendcommand(0xA7BC); /* 869,900 MHz */
+ rfm12_sendcommand(0xC647); /* 4.8kbps FIXME? */
+ rfm12_sendcommand(0x94C0); /* VDI, FAST, 67kHz, 0dBm, -103dBm */
+ rfm12_sendcommand(0xC2AC); /* AL, !ml, DIG, DQD4 */
+ rfm12_sendcommand(0xCA81);//FIFO8,SYNC,!ff,DR
+ rfm12_sendcommand(0xCED4);//SYNC=2DD4;
+ rfm12_sendcommand(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN
+ rfm12_sendcommand(0x9820);// !mp,45kHz,MAX OUT*/
+ rfm12_sendcommand(0xCC77);//OB1,OB0, LPX,!ddy,DDIT,BW0
+ rfm12_sendcommand(0xE000);//NOT USE
+ rfm12_sendcommand(0xC800);//NOT USE
+ rfm12_sendcommand(0xC040);//1.66MHz,2.2V
}