Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- lru
- Date:
- 2019-11-21
- Revision:
- 59:c3aa24e36354
- Parent:
- 56:39847849d219
- Child:
- 60:4b5ab8ab1353
File content as of revision 59:c3aa24e36354:
/**
* Copyright (c) 2017, Arm Limited and affiliates.
* Copyright (c) 2019, Future Electronics.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "lorawan/LoRaWANInterface.h"
#include "lorawan/system/lorawan_data_structures.h"
#include "events/EventQueue.h"
#include "psoc6_utils.h"
#include "mbed.h"
// Application helpers
#include "trace_helper.h"
#include "lora_radio_helper.h"
#include "BD2808.h"
using namespace events;
using namespace mbed;
// Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
// This example only communicates with much shorter messages (<30 bytes).
// If longer messages are used, these buffers must be changed accordingly.
uint8_t tx_buffer[30];
uint8_t rx_buffer[30];
/**
* Maximum number of events for the event queue.
* 10 is the safe number for the stack events, however, if application
* also uses the queue for whatever purposes, this number should be increased.
*/
#define MAX_NUMBER_OF_EVENTS 30
/**
* Maximum number of retries for CONFIRMED messages before giving up
*/
#define CONFIRMED_MSG_RETRY_COUNTER 3
/**
* This event queue is the global event queue for both the
* application and stack. To conserve memory, the stack is designed to run
* in the same thread as the application and the application is responsible for
* providing an event queue to the stack that will be used for ISR deferment as
* well as application information event queuing.
*/
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
/**
* Event handler.
*
* This will be passed to the LoRaWAN stack to queue events for the
* application which in turn drive the application.
*/
static void lora_event_handler(lorawan_event_t event);
/**
* Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
*/
static LoRaWANInterface lorawan(radio);
/**
* Application specific callbacks
*/
static lorawan_app_callbacks_t callbacks;
typedef enum {
DUMMY_MESSAGE,
SWITCH_MESSAGE
} message_type_t;
/**
* Button switch processing handler.
*/
static void button_handler(void);
static void send_message(message_type_t type);
Timer g_timer;
DigitalOut led(LED1);
DigitalIn button1(BUTTON1);
BD2808 leds;
bool frame_send = false;
bool is_connected = false;
bool tx_in_progress = false;
uint8_t power_on = 0;
uint8_t msg_id = 0;
uint32_t delay_counter = 0;
static uint32_t const INTER_FRAME_DELAY = 10;
//static const uint8_t target_device_eui[] = MBED_CONF_APP_TARGET_DEVICE_EUI;
static const uint8_t target_device_eui[] = { 0x00, 0xa0, 0x50, 0xff, 0xfe, 0x81, 0x27, 0x95 };
/**
* Helper routine to set RGB LEDs to specific color.
*/
static void leds_set(uint8_t red, uint8_t green, uint8_t blue)
{
for (int i = 0; i < 8; ++i) {
leds.set_color(i, BGR24_color_t(blue, green, red));
}
leds.refresh();
}
static void timer_one_sec(void)
{
if (is_connected) {
if (!tx_in_progress) {
led = 1;
ThisThread::sleep_for(40);
led = 0;
--delay_counter;
if (delay_counter == 0) {
delay_counter = INTER_FRAME_DELAY;
send_message(DUMMY_MESSAGE);
}
}
} else {
}
}
/**
* Entry point for application
*/
int main(void)
{
static uint8_t mac_address[6];
static uint8_t device_eui[8] = {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00};
static const uint8_t application_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
static const uint8_t application_key[] = MBED_CONF_LORA_APPLICATION_KEY;
static lorawan_connect_t connect_params = {
.connect_type = LORAWAN_CONNECTION_OTAA,
};
leds.set_dma_usage(DMA_USAGE_ALWAYS);
// setup tracing
setup_trace();
// stores the status of a call to LoRaWAN protocol
lorawan_status_t retcode;
// Create unique, hardware-dependent EUI.
cy_get_bd_mac_address(mac_address);
// MAC address is in reverse sequence.
for (int i = 0; i < 3; ++i) {
device_eui[i] = mac_address[5 - i];
device_eui[i + 5] = mac_address[2 - i];
}
printf("\r\nDevice EUI is %02X", device_eui[0]);
for (int i = 1; i < 8; ++i) {
printf(":%02X", device_eui[i]);
}
printf(" [ ");
for (int i = 0; i < 8; ++i) {
printf("%02x", device_eui[i]);
}
printf(" ]\r\n");
// Initialize LoRaWAN stack
if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
printf("\r\n LoRa initialization failed! \r\n");
return -1;
}
printf("\r\n Mbed LoRaWANStack initialized \r\n");
// prepare application callbacks
callbacks.events = mbed::callback(lora_event_handler);
lorawan.add_app_callbacks(&callbacks);
// Set number of retries in case of CONFIRMED messages
if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
!= LORAWAN_STATUS_OK) {
printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
return -1;
}
printf("\r\n CONFIRMED message retries : %d \r\n",
CONFIRMED_MSG_RETRY_COUNTER);
// Enable adaptive data rate
if (lorawan.enable_adaptive_datarate() != LORAWAN_STATUS_OK) {
printf("\r\n enable_adaptive_datarate failed! \r\n");
return -1;
}
printf("\r\n Adaptive data rate (ADR) - Enabled \r\n");
// Specify class C
if (lorawan.set_device_class(CLASS_C) != LORAWAN_STATUS_OK) {
printf("\r\n setting class C failed! \r\n");
return -1;
}
printf("\r\n Class C - Enabled \r\n");
connect_params.connection_u.otaa.dev_eui = device_eui;
connect_params.connection_u.otaa.app_eui = const_cast<uint8_t *>(application_eui);
connect_params.connection_u.otaa.app_key = const_cast<uint8_t *>(application_key);
connect_params.connection_u.otaa.nb_trials = MBED_CONF_LORA_NB_TRIALS;
g_timer.start();
retcode = lorawan.connect(connect_params);
if (retcode == LORAWAN_STATUS_OK ||
retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
} else {
printf("\r\n Connection error, code = %d \r\n", retcode);
return -1;
}
printf("\r\n Connection - In Progress ...\r\n");
// Start button handler; will check button switch every 100ms.
ev_queue.call_every(100, button_handler);
ev_queue.call_every(1000, timer_one_sec);
// make your event queue dispatching events forever
ev_queue.dispatch_forever();
return 0;
}
/**
* Sends a message to the Network Server
*/
static void send_message(message_type_t type)
{
uint16_t packet_len;
int16_t retcode;
uint8_t port = MBED_CONF_LORA_APP_PORT;
printf("\r\n[%8u] Sending message (%d) \r\n", g_timer.read_ms(), msg_id);
switch (type) {
case SWITCH_MESSAGE:
memcpy(tx_buffer, target_device_eui, 8);
for (int i = 8; i < 11; ++i) {
tx_buffer[8] = power_on? 0xf0 : 0x00;
}
packet_len = 11;
break;
case DUMMY_MESSAGE:
tx_buffer[1] = msg_id;
packet_len = 1;
port += 1;
}
led = 1;
tx_in_progress = true;
retcode = lorawan.send(port, tx_buffer, packet_len, MSG_UNCONFIRMED_FLAG);
if (retcode < 0) {
retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
: printf("\r\n send() - Error code %d \r\n", retcode);
if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
lorawan.cancel_sending();
led = 0;
//retry in 3 seconds
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
ev_queue.call_in(3000, send_message, type);
}
}
return;
}
frame_send = true;
printf("\r\n[%8u] %d bytes scheduled for transmission \r\n", g_timer.read_ms(), retcode);
memset(tx_buffer, 0, sizeof(tx_buffer));
}
/**
* Receive a message from the Network Server
*/
static void receive_message()
{
uint8_t port;
int flags;
int16_t retcode = lorawan.receive(rx_buffer, sizeof(rx_buffer), port, flags);
if (retcode < 0) {
printf("\r\n receive() - Error code %d \r\n", retcode);
return;
}
printf("[%8u] RX Data on port %u (%d bytes): ", g_timer.read_ms(), port, retcode);
for (uint8_t i = 0; i < retcode; i++) {
printf("%02x ", rx_buffer[i]);
}
// Expecting exactly 3 bytes: red, green + blue color value.
// Other messages are ignored.
if ((retcode == 3) && (port == MBED_CONF_LORA_APP_PORT)) {
leds_set(rx_buffer[0], rx_buffer[1], rx_buffer[2]);
} else {
printf(" - ignored (%d)", MBED_CONF_LORA_APP_PORT);
}
printf("\r\n");
memset(rx_buffer, 0, sizeof(rx_buffer));
}
/**
* Detects and processes button events.
*/
static void button_handler(void)
{
static uint8_t prev_state = 1;
static uint8_t stable_state = 1;
static uint8_t count = 2;
uint8_t curr_state = button1;
if (curr_state != prev_state) {
count = 2;
} else {
if (count > 0) {
--count;
} else {
if ((stable_state == 0) && (curr_state != 0)) {
// we react on release of the button
if (is_connected) {
power_on = power_on? 0 : 1;
send_message(SWITCH_MESSAGE);
}
}
stable_state = curr_state;
}
}
prev_state = curr_state;
}
/**
* Event handler
*/
static void lora_event_handler(lorawan_event_t event)
{
switch (event) {
case CONNECTED:
printf("\r\n[%8u] Connection - Successful \r\n", g_timer.read_ms());
is_connected = true;
msg_id = 0;
delay_counter = INTER_FRAME_DELAY;
send_message(DUMMY_MESSAGE);
break;
case DISCONNECTED:
led = 0;
frame_send = false;
ev_queue.break_dispatch();
printf("\r\n[%8u] Disconnected Successfully \r\n", g_timer.read_ms());
break;
case TX_DONE:
led = 0;
tx_in_progress = false;
if (frame_send) {
frame_send = false;
delay_counter = INTER_FRAME_DELAY;
++msg_id;
printf("\r\n[%8u] Message Sent to Network Server \r\n", g_timer.read_ms());
} else {
// printf("\r\n[%8u] Duplicate TX_DONE !!! \r\n", g_timer.read_ms());
}
break;
case TX_TIMEOUT:
case TX_ERROR:
case TX_CRYPTO_ERROR:
case TX_SCHEDULING_ERROR:
led = 0;
frame_send = false;
tx_in_progress = false;
delay_counter = INTER_FRAME_DELAY;
printf("\r\n[%8u] Transmission Error - EventCode = %d \r\n", g_timer.read_ms(), event);
break;
case RX_DONE:
printf("\r\n[%8u] Received message from Network Server \r\n", g_timer.read_ms());
receive_message();
break;
case RX_TIMEOUT:
case RX_ERROR:
printf("\r\n[%8u] Error in reception - Code = %d \r\n", g_timer.read_ms(), event);
break;
case JOIN_FAILURE:
printf("\r\n OTAA Failed - Check Keys \r\n");
break;
case UPLINK_REQUIRED:
printf("\r\n[%8u] Uplink required by NS \r\n", g_timer.read_ms());
break;
default:
MBED_ASSERT("Unknown Event");
}
}
// EOF