completely redid PWM: Now calculate 'microprograms', i.e. pairs of
[moodlight.git] / rfm12.c
1 /* $Id: rfm12.c,v 1.2 2010/07/24 20:55:48 simimeie Exp $
2  * Functions for communicating with the rfm12(b) module
3  */
4
5 #include <avr/io.h>
6 #include "rfm12.h"
7
8 /* Unfortunately, the manufacturer documentation for chip and module is
9  * almost unreadable crap.
10  * This one is better: http://www.mikrocontroller.net/articles/RFM12
11  */
12 /* Note: the signal is inverted, thus pulling this high DEselects the chip */
13 #define spi_ss_hi() { PORTC |= _BV(0); }
14 /* Consequently, this SELECTS the chip */
15 #define spi_ss_lo() { PORTC &= (uint8_t)~_BV(0); }
16
17 /* write and (at the same time) read a word from RFM12.
18  * The module uses 16 bit commands and replies that are
19  * synchronous to the command - except for the status read.
20  * Note: This does not handle chip select! */
21 static uint16_t rfm12_spi_wrword(uint16_t v) {
22   uint16_t res;
23   /* Start transmission */
24   SPDR = v >> 8;
25   /* Wait for transmission complete */
26   while ((SPSR & _BV(SPIF)) == 0) {
27   }
28   res = (uint16_t)(SPDR) << 8;
29   SPDR = v & 0xff;
30   /* Wait for transmission complete */
31   while ((SPSR & _BV(SPIF)) == 0) {
32   }
33   res |= SPDR & 0xff;
34   return res;
35 }
36
37 void rfm12_sendcommand(uint16_t cmd) {
38   spi_ss_lo();
39   rfm12_spi_wrword(cmd);
40   spi_ss_hi();
41 }
42
43 uint32_t rfm12_readstatus(void) {
44   uint32_t res;
45   spi_ss_lo();
46   res = (uint32_t)rfm12_spi_wrword(0x0000) << 16;
47   res |= rfm12_spi_wrword(0x0000);
48   spi_ss_hi();
49   return res;
50 }
51
52 void rfm12_init(void) {
53   /* Set MOSI, SCK and SS output, MISO input */
54   /* Frickel Alert: Also set PB2 output. It is not used, but noise on the
55    * pin could reset our SPI mode to slave (!!!) if it is left as input. */
56   DDRB |= _BV(3) | _BV(5) | _BV(2);
57   DDRC |= _BV(0);
58   DDRB &= (uint8_t)~_BV(4);
59   spi_ss_hi();
60 #if (CPUFREQ <= 10000000UL)
61   /* Enable SPI, Master, set clock rate fck/4.
62    * This works as long as our own clockrate is below 10 MHz - because
63    * 2.5 MHz is the maximum the rfm12b can do. */
64   SPCR |= _BV(SPE) | _BV(MSTR);
65 #else
66   /* For higher clock rates set fck/16. */
67   SPCR |= _BV(SPE) | _BV(MSTR) | _BV(SPR0);
68 #endif /* CPUFREQ */
69   /* Now send some initialization commands. */
70   /* Mostly taken over from http://www.joachim-neu.de/post/70/rfm12b-868/
71    * Seems to be mostly black magic anyways. */
72   rfm12_sendcommand(0x80E7); /* EL, EF, 868band, 12.0pF */
73   rfm12_sendcommand(0x8219); /* !er, !ebb, !ET, ES, EX, !eb, !ew, DC */
74   /* Frequency setting: 0xAnnn; the 12 nnn-bits of value are
75    * calculated like this:   v = ((freq / 20) - 43) * 4000
76    */
77   rfm12_sendcommand(0xA7BC); /* 869,900 MHz */
78   rfm12_sendcommand(0xC647); /* 4.8kbps FIXME? */
79   rfm12_sendcommand(0x94C0); /* VDI, FAST, 67kHz, 0dBm, -103dBm */
80   rfm12_sendcommand(0xC2AC); /* AL, !ml, DIG, DQD4 */
81   rfm12_sendcommand(0xCA81);//FIFO8,SYNC,!ff,DR
82   rfm12_sendcommand(0xCED4);//SYNC=2DD4;
83   rfm12_sendcommand(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN
84   rfm12_sendcommand(0x9820);// !mp,45kHz,MAX OUT*/
85   rfm12_sendcommand(0xCC77);//OB1,OB0, LPX,!ddy,DDIT,BW0
86   rfm12_sendcommand(0xE000);//NOT USE
87   rfm12_sendcommand(0xC800);//NOT USE
88   rfm12_sendcommand(0xC040);//1.66MHz,2.2V
89 }
This page took 0.056705 seconds and 3 git commands to generate.