-
Notifications
You must be signed in to change notification settings - Fork 0
/
ble.c
304 lines (261 loc) · 11.6 KB
/
ble.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/**
* @file ble.c
* @author Sonal Tamrakar
* @date 11/9/2021
* @brief Contains all the functions to interface the application with the HM-18
* BLE module and the LEUART driver
*
*/
//***********************************************************************************
// Include files
//***********************************************************************************
#include "ble.h"
#include <string.h>
//***********************************************************************************
// defined files
//***********************************************************************************
//***********************************************************************************
// private variables
//***********************************************************************************
/***************************************************************************//**
* @brief BLE module
* @details
* This module contains all the functions to interface the application layer
* with the HM-18 Bluetooth module. The application does not have the
* responsibility of knowing the physical resources required, how to
* configure, or interface to the Bluetooth resource including the LEUART
* driver that communicates with the HM-18 BLE module.
*
******************************************************************************/
//***********************************************************************************
// Private functions
//***********************************************************************************
/***************************************************************************//**
* @brief
* This is the bluetooth driver function that initializes bluetooth module
*
* @details
* Initializes all the LEUART_OPEN_STRUCT values and sends the values to the leuart_open() function. The bluetooth module
* HM-10 values are acquired from it's datasheet and are used to initialize the module.
*
* @note
* The receive and transmit callbacks are also set here.
*
* @param[in] tx_event
* Transmitting data callback
*
*@param[in] rx_event
* Receiving data callback
******************************************************************************/
void ble_open(uint32_t tx_event, uint32_t rx_event){
LEUART_OPEN_STRUCT ble_open_values;
ble_open_values.baudrate = HM10_BAUDRATE;
ble_open_values.databits = HM10_DATABITS;
ble_open_values.enable = HM10_ENABLE;
ble_open_values.parity = HM10_PARITY;
ble_open_values.stopbits = HM10_STOPBITS;
ble_open_values.rxblocken = true;
ble_open_values.sfubrx = true;
ble_open_values.startframe_en = true;
ble_open_values.startframe = '#';//STARTTFRAME;
ble_open_values.sigframe_en = true;
ble_open_values.sigframe = '!'; //SIGGFRAME;
ble_open_values.rx_loc = LEUART0_RX_ROUTE;
ble_open_values.tx_loc = LEUART0_TX_ROUTE;
ble_open_values.rx_pin_en = true;
ble_open_values.tx_pin_en = true;
ble_open_values.rx_en = true;
ble_open_values.tx_en = true;
ble_open_values.rx_done_evt = rx_event;
ble_open_values.tx_done_evt = tx_event;
ble_open_values.refFreq = 0; //should be zero
leuart_open(LEUART0, &ble_open_values);
}
/***************************************************************************//**
* @brief
* The ble_write gets an input pointer to a string which is then send to the leuart_start function.
* @details
* In order to call the leuart_start function, you need to specify the specific LEUART peripheral you
* want to choose and the input string itself.
* @param[in] * string
* The input string that you want to write to the phone via bluetooth.
******************************************************************************/
void ble_write(char* string){
//uint32_t length_of_string = strlen(string);
leuart_start(LEUART0, string, strlen(string));
}
/***************************************************************************//**
* @brief
* BLE Test performs two functions. First, it is a Test Driven Development
* routine to verify that the LEUART is correctly configured to communicate
* with the BLE HM-18 module. Second, the input argument passed to this
* function will be written into the BLE module and become the new name
* advertised by the module while it is looking to pair.
*
* @details
* This global function will use polling functions provided by the LEUART
* driver for both transmit and receive to validate communications with
* the HM-18 BLE module. For the assignment, the communication with the
* BLE module must use low energy design principles of being an interrupt
* driven state machine.
*
* @note
* For this test to run to completion, the phone most not be paired with
* the BLE module. In addition for the name to be stored into the module
* a breakpoint must be placed at the end of the test routine and stopped
* at this breakpoint while in the debugger for a minimum of 5 seconds.
*
* @param[in] *mod_name
* The name that will be written to the HM-18 BLE module to identify it
* while it is advertising over Bluetooth Low Energy.
*
* @return
* Returns bool true if successfully passed through the tests in this
* function.
******************************************************************************/
bool ble_test(char *mod_name){
uint32_t str_len;
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
// This test will limit the test to the proper setup of the LEUART
// peripheral, routing of the signals to the proper pins, pin
// configuration, and transmit/reception verification. The test
// will communicate with the BLE module using polling routines
// instead of interrupts.
// How is polling different than using interrupts?
// ANSWER:
// How does interrupts benefit the system for low energy operation?
// ANSWER:
// How does interrupts benefit the system that has multiple tasks?
// ANSWER:
// First, you will need to review the DSD HM10 datasheet to determine
// what the default strings to write data to the BLE module and the
// expected return statement from the BLE module to test / verify the
// correct response
// The test_str is used to tell the BLE module to end a Bluetooth connection
// such as with your phone. The ok_str is the result sent from the BLE module
// to the micro-controller if there was not active BLE connection at the time
// the break command was sent to the BLE module.
// Replace the test_str "" with the command to break or end a BLE connection
// Replace the ok_str "" with the result that will be returned from the BLE
// module if there was no BLE connection
char test_str[80] = "AT";
char ok_str[80] = "OK";
// output_str will be the string that will program a name to the BLE module.
// From the DSD HM10 datasheet, what is the command to program a name into
// the BLE module?
// The output_str will be a string concatenation of the DSD HM10 command
// and the input argument sent to the ble_test() function
// Replace the output_str "" with the command to change the program name
// Replace the result_str "" with the first part of the expected result
// The HM-10 datasheet has an error. This response starts with "OK+Set:"
// the backend of the expected response will be concatenated with the
// input argument
char output_str[80] = "AT+NAME";
char result_str[80] = "OK+Set:";
// To program the name into your module, you must reset the module after you
// have sent the command to update the modules name. What is the DSD HM10
// name to reset the module?
// Replace the reset_str "" with the command to reset the module
// Replace the reset_result_str "" with the expected BLE module response to
// to the reset command
char reset_str[80] = "AT+RESET";
char reset_result_str[80] = "OK+RESET";
char return_str[80];
bool success;
bool rx_disabled, rx_en, tx_en;
uint32_t status;
// These are the routines that will build up the entire command and response
// of programming the name into the BLE module. Concatenating the command or
// response with the input argument name
strcat(output_str, mod_name);
strcat(result_str, mod_name);
// The test routine must not alter the function of the configuration of the
// LEUART driver, but requires certain functionality to insure the logical test
// of writing and reading to the DSD HM10 module. The following c-lines of code
// save the current state of the LEUART driver that will be used later to
// re-instate the LEUART configuration
status = leuart_status(HM10_LEUART0);
if (status & LEUART_STATUS_RXBLOCK) {
rx_disabled = true;
// Enabling, unblocking, the receiving of data from the LEUART RX port
leuart_cmd_write(HM10_LEUART0, LEUART_CMD_RXBLOCKDIS);
}
else rx_disabled = false;
if (status & LEUART_STATUS_RXENS) {
rx_en = true;
} else {
rx_en = false;
// Enabling the receiving of data from the RX port
leuart_cmd_write(HM10_LEUART0, LEUART_CMD_RXEN);
// Why could you be stuck in the below while loop after a write to CMD register?
// Answer:
while (!(leuart_status(HM10_LEUART0) & LEUART_STATUS_RXENS));
}
if (status & LEUART_STATUS_TXENS){
tx_en = true;
} else {
// Enabling the transmission of data to the TX port
leuart_cmd_write(HM10_LEUART0, LEUART_CMD_TXEN);
while (!(leuart_status(HM10_LEUART0) & LEUART_STATUS_TXENS));
tx_en = false;
}
// leuart_cmd_write(HM10_LEUART0, (LEUART_CMD_CLEARRX | LEUART_CMD_CLEARTX));
// This sequence of instructions is sending the break ble connection
// to the DSD HM10 module.
// Why is this command required if you want to change the name of the
// DSD HM10 module?
// ANSWER:
str_len = strlen(test_str);
for (uint32_t i = 0; i < str_len; i++){
leuart_app_transmit_byte(HM10_LEUART0, test_str[i]);
}
// What will the ble module response back to this command if there is
// a current ble connection?
// ANSWER:
str_len = strlen(ok_str);
for (uint32_t i = 0; i < str_len; i++){
return_str[i] = leuart_app_receive_byte(HM10_LEUART0);
if (ok_str[i] != return_str[i]) {
EFM_ASSERT(false);;
}
}
// This sequence of code will be writing or programming the name of
// the module to the DSD HM10
str_len = strlen(output_str);
for (uint32_t i = 0; i < str_len; i++){
leuart_app_transmit_byte(HM10_LEUART0, output_str[i]);
}
// Here will be the check on the response back from the DSD HM10 on the
// programming of its name
str_len = strlen(result_str);
for (uint32_t i = 0; i < str_len; i++){
return_str[i] = leuart_app_receive_byte(HM10_LEUART0);
if (result_str[i] != return_str[i]) {
EFM_ASSERT(false);;
}
}
// It is now time to send the command to RESET the DSD HM10 module
str_len = strlen(reset_str);
for (uint32_t i = 0; i < str_len; i++){
leuart_app_transmit_byte(HM10_LEUART0, reset_str[i]);
}
// After sending the command to RESET, the DSD HM10 will send a response
// back to the micro-controller
str_len = strlen(reset_result_str);
for (uint32_t i = 0; i < str_len; i++){
return_str[i] = leuart_app_receive_byte(HM10_LEUART0);
if (reset_result_str[i] != return_str[i]) {
EFM_ASSERT(false);;
}
}
// After the test and programming have been completed, the original
// state of the LEUART must be restored
if (!rx_en) leuart_cmd_write(HM10_LEUART0, LEUART_CMD_RXDIS);
if (rx_disabled) leuart_cmd_write(HM10_LEUART0, LEUART_CMD_RXBLOCKEN);
if (!tx_en) leuart_cmd_write(HM10_LEUART0, LEUART_CMD_TXDIS);
leuart_if_reset(HM10_LEUART0);
success = true;
CORE_EXIT_CRITICAL();
return success;
}