]>
Commit | Line | Data |
---|---|---|
874bcba6 MW |
1 | /* |
2 | * abstraction of the spi interface of HopeRf rf69 radio module | |
3 | * | |
4 | * Copyright (C) 2016 Wolf-Entwicklungen | |
5 | * Marcus Wolf <linux@wolf-entwicklungen.de> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | */ | |
17 | ||
18 | /* enable prosa debug info */ | |
19 | #undef DEBUG | |
20 | /* enable print of values on reg access */ | |
21 | #undef DEBUG_VALUES | |
22 | /* enable print of values on fifo access */ | |
23 | #undef DEBUG_FIFO_ACCESS | |
24 | ||
25 | #include <linux/types.h> | |
26 | #include <linux/spi/spi.h> | |
27 | ||
28 | #include "rf69.h" | |
29 | #include "rf69_registers.h" | |
30 | ||
31 | #define F_OSC 32000000 /* in Hz */ | |
32 | #define FIFO_SIZE 66 /* in byte */ | |
33 | ||
34 | /*-------------------------------------------------------------------------*/ | |
35 | ||
36 | #define READ_REG(x) rf69_read_reg (spi, x) | |
329822a0 | 37 | #define WRITE_REG(x, y) rf69_write_reg(spi, x, y) |
874bcba6 MW |
38 | |
39 | /*-------------------------------------------------------------------------*/ | |
40 | ||
41 | int rf69_set_mode(struct spi_device *spi, enum mode mode) | |
42 | { | |
43 | #ifdef DEBUG | |
44 | dev_dbg(&spi->dev, "set: mode"); | |
45 | #endif | |
46 | ||
b4bac77f | 47 | switch (mode) { |
874bcba6 MW |
48 | case transmit: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_TRANSMIT); |
49 | case receive: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_RECEIVE); | |
50 | case synthesizer: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_SYNTHESIZER); | |
51 | case standby: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_STANDBY); | |
52 | case mode_sleep: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) & ~MASK_OPMODE_MODE) | OPMODE_MODE_SLEEP); | |
e221b2b1 MC |
53 | default: |
54 | dev_dbg(&spi->dev, "set: illegal input param"); | |
55 | return -EINVAL; | |
874bcba6 MW |
56 | } |
57 | ||
58 | // we are using packet mode, so this check is not really needed | |
59 | // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode | |
60 | //while (_mode == RF69_MODE_SLEEP && (READ_REG(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady | |
61 | ||
62 | } | |
63 | ||
64 | int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode) | |
65 | { | |
66 | #ifdef DEBUG | |
67 | dev_dbg(&spi->dev, "set: data mode"); | |
68 | #endif | |
69 | ||
70 | switch (dataMode) { | |
71 | case packet: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_PACKET); | |
72 | case continuous: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS); | |
73 | case continuousNoSync: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS_NOSYNC); | |
e221b2b1 MC |
74 | default: |
75 | dev_dbg(&spi->dev, "set: illegal input param"); | |
76 | return -EINVAL; | |
874bcba6 MW |
77 | } |
78 | } | |
79 | ||
80 | int rf69_set_modulation(struct spi_device *spi, enum modulation modulation) | |
81 | { | |
82 | #ifdef DEBUG | |
83 | dev_dbg(&spi->dev, "set: modulation"); | |
84 | #endif | |
85 | ||
86 | switch (modulation) { | |
87 | case OOK: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_OOK); | |
88 | case FSK: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_FSK); | |
e221b2b1 MC |
89 | default: |
90 | dev_dbg(&spi->dev, "set: illegal input param"); | |
91 | return -EINVAL; | |
874bcba6 MW |
92 | } |
93 | } | |
94 | ||
95 | enum modulation rf69_get_modulation(struct spi_device *spi) | |
96 | { | |
97 | u8 currentValue; | |
98 | ||
99 | #ifdef DEBUG | |
100 | dev_dbg(&spi->dev, "get: mode"); | |
101 | #endif | |
102 | ||
103 | currentValue = READ_REG(REG_DATAMODUL); | |
104 | ||
202fc673 | 105 | switch (currentValue & MASK_DATAMODUL_MODULATION_TYPE) { |
874bcba6 MW |
106 | case DATAMODUL_MODULATION_TYPE_OOK: return OOK; |
107 | case DATAMODUL_MODULATION_TYPE_FSK: return FSK; | |
108 | default: return undefined; | |
109 | } | |
110 | } | |
111 | ||
112 | int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping modShaping) | |
113 | { | |
114 | #ifdef DEBUG | |
115 | dev_dbg(&spi->dev, "set: mod shaping"); | |
116 | #endif | |
117 | ||
9391cb31 | 118 | if (rf69_get_modulation(spi) == FSK) { |
874bcba6 MW |
119 | switch (modShaping) { |
120 | case shapingOff: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_NONE); | |
121 | case shaping1_0: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_1_0); | |
122 | case shaping0_5: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_0_3); | |
123 | case shaping0_3: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_0_5); | |
e221b2b1 MC |
124 | default: |
125 | dev_dbg(&spi->dev, "set: illegal input param"); | |
126 | return -EINVAL; | |
874bcba6 | 127 | } |
46659ed7 | 128 | } else { |
874bcba6 MW |
129 | switch (modShaping) { |
130 | case shapingOff: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_NONE); | |
131 | case shapingBR: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_BR); | |
132 | case shaping2BR: return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) | DATAMODUL_MODULATION_SHAPE_2BR); | |
e221b2b1 MC |
133 | default: |
134 | dev_dbg(&spi->dev, "set: illegal input param"); | |
135 | return -EINVAL; | |
874bcba6 MW |
136 | } |
137 | } | |
138 | } | |
139 | ||
140 | int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate) | |
141 | { | |
142 | int retval; | |
143 | u32 bitRate_min; | |
144 | u32 bitRate_reg; | |
145 | u8 msb; | |
146 | u8 lsb; | |
147 | ||
148 | #ifdef DEBUG | |
149 | dev_dbg(&spi->dev, "set: bit rate"); | |
150 | #endif | |
151 | ||
152 | // check input value | |
153 | bitRate_min = F_OSC / 8388608; // 8388608 = 2^23; | |
9391cb31 | 154 | if (bitRate < bitRate_min) { |
874bcba6 | 155 | dev_dbg(&spi->dev, "setBitRate: illegal input param"); |
e221b2b1 | 156 | return -EINVAL; |
874bcba6 MW |
157 | } |
158 | ||
159 | // calculate reg settings | |
160 | bitRate_reg = (F_OSC / bitRate); | |
161 | ||
162 | msb = (bitRate_reg&0xff00) >> 8; | |
163 | lsb = (bitRate_reg&0xff); | |
164 | ||
165 | // transmit to RF 69 | |
166 | retval = WRITE_REG(REG_BITRATE_MSB, msb); | |
4a74749a MC |
167 | if (retval) |
168 | return retval; | |
169 | ||
874bcba6 | 170 | retval = WRITE_REG(REG_BITRATE_LSB, lsb); |
4a74749a MC |
171 | if (retval) |
172 | return retval; | |
874bcba6 MW |
173 | |
174 | return 0; | |
175 | } | |
176 | ||
177 | int rf69_set_deviation(struct spi_device *spi, u32 deviation) | |
178 | { | |
179 | int retval; | |
180 |