Skyward boardcore
Loading...
Searching...
No Matches
Gamma868.cpp
Go to the documentation of this file.
1/* Copyright (c) 2017 Skyward Experimental Rocketry
2 * Authors: Alvise de'Faveri Tron, Nuno Barcellos
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "Gamma868.h"
24
25using namespace miosix;
26
27namespace Boardcore
28{
29
30/*
31 * A serial port attached to the Gamma868 RX and TX pins is expected
32 * to be passed to the object in order to communicate with the device.
33 *
34 */
35Gamma868::Gamma868(const char* serialPath, const uint16_t multiplier)
36 : sendTimeoutMultiplier(multiplier), conf{}, gammaSwitch{}
37{
38 confEnabled = false;
39 fd = open(serialPath, O_RDWR);
40
41 if (fd < 0)
42 LOG_ERR(logger, "Cannot open {}", serialPath);
43 // TODO: Signal an error if we fail here?
44}
45
46/*
47 * A serial port attached to the Gamma868 RX and TX pins is expected
48 * to be passed to the object in order to communicate with the device.
49 *
50 */
51Gamma868::Gamma868(const char* serialPath, GpioPin* learnModePin,
52 const uint16_t multiplier)
53 : Gamma868(serialPath, multiplier)
54{
55 gammaSwitch = learnModePin;
56 confEnabled = true;
57
58 gammaSwitch->mode(Mode::OUTPUT);
59 gammaSwitch->high();
60}
61
62Gamma868::~Gamma868() { close(fd); }
63
64/*
65 * Immediately sends command (blocking).
66 */
67bool Gamma868::send(uint8_t* pkt, size_t packetLength)
68{
69 bool ret = (write(fd, pkt, packetLength) > 0);
70 Thread::sleep(sendTimeoutMultiplier * packetLength);
71 return ret;
72}
73
74/*
75 * Reads from the gamma868 serial (blocking).
76 */
77ssize_t Gamma868::receive(uint8_t* pkt, size_t packetLength)
78{
79 if (packetLength > 0)
80 return read(fd, pkt, 1);
81 else
82 return 0;
83}
84
85/*
86 * Reads the configuration from the device and updates the conf varaiable.
87 */
89{
90 if (!confEnabled)
91 {
92 conf.isValid = false;
93 }
94 else
95 {
96 enterLearnMode();
97
98 bool ok = updateConfig();
99 if (!ok)
100 conf.isValid = false;
101
102 exitLearnMode();
103 }
104
105 return conf;
106}
107
108/*
109 * Set a new configuration to gamma.
110 * Returns true if the configuration was set right.
111 */
112bool Gamma868::configure(const GammaConf& newConf)
113{
114 bool retValue;
115
116 if (!confEnabled)
117 return false;
118
119 enterLearnMode();
120
121 GammaConf oldConf;
122 memcpy(&oldConf, &conf, sizeof(GammaConf));
123
124 // Write the new configuration
125 LOG_DEBUG(logger, "Writing new configuration...");
126 writeConfig(newConf);
127
128 // Check the current configuration
129 bool ok = updateConfig();
130
131 if (ok && conf == newConf)
132 {
133 LOG_DEBUG(logger, "Config ok");
134 retValue = true;
135 }
136 else
137 {
138 LOG_ERR(logger, "Config error");
139 memcpy(&conf, &oldConf, sizeof(GammaConf)); // rollback
140 retValue = false;
141 }
142
143 exitLearnMode();
144
145 return retValue;
146}
147
148/*
149 * Puts the gamma868 in "learn mode" (configuration mode).
150 */
151void Gamma868::enterLearnMode()
152{
153 // TODO: switch baudrate to 9600
154
155 // Enter learn mode
156 LOG_DEBUG(logger, "Entering learn mode...");
157 gammaSwitch->low();
158
159 // Wait 5 seconds
160 miosix::Thread::sleep(LEARN_MODE_TIMEOUT);
161
162 gammaSwitch->high(); // Stop "pushing" the button
163}
164
165/*
166 * Puts the gamma868 out of "learn mode" (configuration mode).
167 */
168void Gamma868::exitLearnMode()
169{
170 // TODO: switch baudrate according to configuration
171
172 LOG_DEBUG(logger, "Exiting learn mode");
173 write(fd, "#Q", 2);
174}
175
176/*
177 * Sends configuration to the gamma868 module.
178 */
179void Gamma868::writeConfig(const GammaConf& newConf)
180{
181 uint8_t confAddress[8] = "#A";
182 memcpy(confAddress + 2, &(newConf.localAddress), 3);
183 memcpy(confAddress + 5, &(newConf.destinationAddress), 3);
184
185 write(fd, confAddress, 8);
186 waitForOk();
187
188 char confBaud[3] = "#B";
189 confBaud[2] = (uint8_t)newConf.baudrate;
190 write(fd, confBaud, 3);
191 waitForOk();
192
193 char confHandshake[3] = "#H";
194 confHandshake[2] = (uint8_t)newConf.handshake;
195 write(fd, confHandshake, 3);
196 waitForOk();
197
198 char confLora[4] = "#C";
199 confLora[2] = (uint8_t)newConf.loraSf;
200 confLora[3] = (uint8_t)newConf.loraPower;
201 write(fd, confLora, 4);
202 waitForOk();
203
204 memcpy(&conf, &newConf, sizeof(GammaConf));
205 conf.isValid = true;
206}
207
208/*
209 * Reads the configuration from the device and updates the conf varaiable.
210 */
211bool Gamma868::updateConfig()
212{
213 if (!confEnabled)
214 return false;
215
216 GammaMessage msg;
217
218 // Read from device
219 write(fd, "#?", 2);
220 read(fd, &(msg.buf), sizeof(GammaMessage));
221
222 // Check values validity
223 if (msg.conf.loraMode >= LAST_SF || msg.conf.loraPower >= LAST_POWER ||
224 msg.conf.baudrate >= LAST_BAUDRATE)
225 {
226 return false;
227 }
228
229 // Update conf variable
230 conf.isValid = true;
231
232 // Addresses
233 memcpy(&conf.localAddress, msg.conf.localAddress, 3);
234 memcpy(&conf.destinationAddress, msg.conf.destinationAddress, 3);
235
236 // LoRa values
237 conf.loraSf = static_cast<GammaSF>(msg.conf.loraMode);
238 conf.loraPower = static_cast<GammaPower>(msg.conf.loraPower);
239 conf.baudrate = static_cast<GammaBaudrate>(msg.conf.baudrate);
240
241 conf.handshake = (msg.conf.handshake > 0) ? true : false;
242
243 return true;
244}
245
246/*
247 * Waits until an "OK" is received on the serial port (blocking).
248 */
249void Gamma868::waitForOk()
250{
251 char reply[3];
252 read(fd, reply, 3);
253 LOG_DEBUG(logger, "Device replied: {}", reply);
254 Thread::sleep(100);
255}
256
257} // namespace Boardcore
#define LOG_ERR(logger,...)
#define LOG_DEBUG(logger,...)
Gamma868(const char *serialPath, const uint16_t multiplier=0)
Definition Gamma868.cpp:35
const int LEARN_MODE_TIMEOUT
Definition Gamma868.h:37
bool configure(const GammaConf &newConf)
Definition Gamma868.cpp:112
bool send(uint8_t *pkt, size_t packetLength) override
Send a packet.
Definition Gamma868.cpp:67
GammaConf readConfig()
Definition Gamma868.cpp:88
ssize_t receive(uint8_t *pkt, size_t packetLength) override
Wait until a new packet is received.
Definition Gamma868.cpp:77
This file includes all the types the logdecoder script will decode.
@ LAST_BAUDRATE
Definition GammaTypes.h:38
std::array< uint8_t, 3 > destinationAddress
Definition GammaTypes.h:81
std::array< uint8_t, 3 > localAddress
Definition GammaTypes.h:80
GammaBaudrate baudrate
Definition GammaTypes.h:84
GammaPower loraPower
Definition GammaTypes.h:83