Commit 26451868 authored by Guillaume Gonnet's avatar Guillaume Gonnet
Browse files

Complete implementation of benchmark app.

parent 65c85224
...@@ -23,9 +23,9 @@ DEVELHELP ?= 1 ...@@ -23,9 +23,9 @@ DEVELHELP ?= 1
QUIET ?= 1 QUIET ?= 1
# Reset EEPROM data on start? # Board number (starting at 1).
RESET_ON_START ?= 1 BOARD_NUMBER ?= 1
CFLAGS += -DRESET_ON_START=$(RESET_ON_START) CFLAGS += -DBOARD_NUMBER=$(BOARD_NUMBER)
# We use "IMAG" region in LoRaMAC-node. # We use "IMAG" region in LoRaMAC-node.
REGION ?= IMAG REGION ?= IMAG
...@@ -35,7 +35,6 @@ CFLAGS += -DREGION_$(REGION) ...@@ -35,7 +35,6 @@ CFLAGS += -DREGION_$(REGION)
# All modules defined in this application. # All modules defined in this application.
USEMODULE += cubsat-app USEMODULE += cubsat-app
USEMODULE += cubsat-app-benchmark USEMODULE += cubsat-app-benchmark
USEMODULE += cubsat-app-cmds
USEMODULE += cubsat-app-providers USEMODULE += cubsat-app-providers
USEMODULE += cubsat-app-drivers USEMODULE += cubsat-app-drivers
USEMODULE += lorariot-ctrl USEMODULE += lorariot-ctrl
...@@ -52,9 +51,6 @@ USEMODULE += periph_eeprom ...@@ -52,9 +51,6 @@ USEMODULE += periph_eeprom
USEMODULE += periph_uart USEMODULE += periph_uart
USEMODULE += periph_i2c USEMODULE += periph_i2c
# TMP.
FEATURES_REQUIRED += periph_rtc
# Source directory is "src". # Source directory is "src".
DIRS += src DIRS += src
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
| Longitude | | 3 * 8 = 24 | | Longitude | | 3 * 8 = 24 |
| Altitude | 0 - 65535 | 2 * 8 = 16 | | Altitude | 0 - 65535 | 2 * 8 = 16 |
This total length of the payload (without LoRaWAN header) is 10 bytes. This total length of the payload (without LoRaWAN header) is 10 bytes.
All integers are big endian. All integers are big endian.
...@@ -32,9 +32,9 @@ coding rate of `4/8`. ...@@ -32,9 +32,9 @@ coding rate of `4/8`.
## Transmission power ## Transmission power
This parameter is the index in the array below (values in dBm). This parameter is the index in the array below (values in dBm).
> `2, 5, 8, 11, 14, 15, 16, 17, 18, 19` > `2, 5, 8, 11, 13, 15, 17, 18, 19`
This array has 10 elements so this parameter is coded on **4 bits**. This array has 9 elements so this parameter is coded on **4 bits**.
## Temperature ## Temperature
......
...@@ -45,7 +45,7 @@ const DataRate = (byte >> 5) & 0b111; ...@@ -45,7 +45,7 @@ const DataRate = (byte >> 5) & 0b111;
const CodingRate = (byte >> 4) & 0b1; const CodingRate = (byte >> 4) & 0b1;
let Power = byte & 0b1111; let Power = byte & 0b1111;
Power = [2, 5, 8, 11, 14, 15, 16, 17, 18, 19][Power]; Power = [2, 5, 8, 11, 13, 15, 17, 18, 19][Power];
// Extract temperature. // Extract temperature.
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
MODULE := cubsat-app MODULE := cubsat-app
DIRS += benchmark DIRS += benchmark
DIRS += commands
DIRS += providers DIRS += providers
DIRS += drivers DIRS += drivers
......
...@@ -9,9 +9,19 @@ This project is under the MIT license ...@@ -9,9 +9,19 @@ This project is under the MIT license
#include "benchmark.h" #include "benchmark.h"
#include <xtimer.h>
// Stack of the benchmark thread.
#define BM_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
static char bm_stack[BM_STACKSIZE];
// PID of benchmark thread.
kernel_pid_t bm_pid;
// Transmission powers to test. // Transmission powers to test.
uint8_t bm_power[] = { 2, 5, 8, 11, 14, 15, 16, 17, 18, 19 }; uint8_t bm_power[] = { 2, 5, 8, 11, 13, 15, 17, 18, 19 };
// Datarates to test. // Datarates to test.
uint8_t bm_dr[] = { DR_0, DR_1, DR_2, DR_3, DR_4, DR_5 }; uint8_t bm_dr[] = { DR_0, DR_1, DR_2, DR_3, DR_4, DR_5 };
...@@ -20,7 +30,16 @@ uint8_t bm_dr[] = { DR_0, DR_1, DR_2, DR_3, DR_4, DR_5 }; ...@@ -20,7 +30,16 @@ uint8_t bm_dr[] = { DR_0, DR_1, DR_2, DR_3, DR_4, DR_5 };
uint8_t bm_cr[] = { CR_4_5, CR_4_8 }; uint8_t bm_cr[] = { CR_4_5, CR_4_8 };
// Providers to test. // Providers to test.
const provider_t *bm_pvd[] = { &pvd_orange_bm, &pvd_ttn_bm }; const provider_t *bm_pvd[] = { &pvd_orange_bm, &pvd_campus_bm, &pvd_ttn_bm };
// Ports to use for benchmark.
#define MIN_PORT 10
#define MAX_PORT 220
// Buffer and payload for benchmark.
static uint8_t bm_buffer[10];
lorariot_mcps_t bm_payload = LORARIOT_UNCONFIRMED_EX(DR_0, 50, 10, bm_buffer);
// Count the number of elements in an array. // Count the number of elements in an array.
...@@ -31,16 +50,44 @@ const provider_t *bm_pvd[] = { &pvd_orange_bm, &pvd_ttn_bm }; ...@@ -31,16 +50,44 @@ const provider_t *bm_pvd[] = { &pvd_orange_bm, &pvd_ttn_bm };
for (uint8_t name ## _i = 0; name ## _i < CNT(bm_ ## name); name ## _i++) for (uint8_t name ## _i = 0; name ## _i < CNT(bm_ ## name); name ## _i++)
// Run the benchmark. // Run the benchmark one time.
void bm_run(void) void bm_run(uint8_t port)
{ {
bm_payload.port = 50; // TODO: change port. bm_payload.port = port;
foreach_param(power) // Power: 10 values foreach_param(power) // Power: 9 values
foreach_param(cr) // Coding rate: 2 values foreach_param(cr) // Coding rate: 2 values
foreach_param(dr) // Datarate: 6 values foreach_param(dr) // Datarate: 6 values
foreach_param(pvd) { // Providers: 2 values foreach_param(pvd) { // Providers: 3 values
bm_encode_payload(power_i, dr_i, cr_i); bm_encode_payload(&bm_payload, power_i, dr_i, cr_i);
pvd_send(bm_pvd[pvd_i], &bm_payload); pvd_send(bm_pvd[pvd_i], &bm_payload);
xtimer_usleep(50 * 1000); // 50 ms
}
}
// Thread that run the benchmark indefinitely.
static void *bm_thread(void *args)
{
(void)args;
xtimer_sleep(5); // Wait 5s and start running benchmark.
printf("Staring benchmark!\n");
uint8_t port = MIN_PORT;
while (true) {
bm_run(port);
xtimer_sleep(5); // 5s
port = MIN_PORT + ((port + 1 - MIN_PORT) % (MAX_PORT - MIN_PORT));
} }
return NULL;
}
// Start benchmark thread.
void bm_start_thread(void)
{
bm_pid = thread_create(bm_stack, sizeof(bm_stack),
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST,
bm_thread, NULL, "bm-thread");
} }
...@@ -12,6 +12,8 @@ This project is under the MIT license ...@@ -12,6 +12,8 @@ This project is under the MIT license
#include "providers/providers.h" #include "providers/providers.h"
#include "lorariot.h" #include "lorariot.h"
#include <thread.h>
// Update temperature value every .. ms // Update temperature value every .. ms
#define TEMPERATURE_UPDATE_MS 1500 #define TEMPERATURE_UPDATE_MS 1500
...@@ -33,15 +35,27 @@ extern uint8_t bm_cr[]; ...@@ -33,15 +35,27 @@ extern uint8_t bm_cr[];
extern const provider_t *bm_pvd[]; extern const provider_t *bm_pvd[];
// PID of benchmark thread.
extern kernel_pid_t bm_pid;
/** /**
* @brief Encode message data to the payload. * @brief Encode message data to the payload.
* @param mcps MCPS message that will be sent.
* @param power_i Transmission power (index in `bm_power`). * @param power_i Transmission power (index in `bm_power`).
* @param dr_i Datarate (index in `bm_dr`). * @param dr_i Datarate (index in `bm_dr`).
* @param cr_i Coding rate (index in `bm_cr`). * @param cr_i Coding rate (index in `bm_cr`).
*/ */
void bm_encode_payload(uint8_t power_i, uint8_t dr_i, uint8_t cr_i); void bm_encode_payload(lorariot_mcps_t *mcps, uint8_t power_i, uint8_t dr_i,
uint8_t cr_i);
/**
* @brief Run the benchmark one time.
* @param port LoRaWAN port to use in messages.
*/
void bm_run(uint8_t port);
/** /**
* @brief Run the benchmark. * @brief Start benchmark thread.
*/ */
void bm_run(void); void bm_start_thread(void);
...@@ -12,39 +12,46 @@ This project is under the MIT license ...@@ -12,39 +12,46 @@ This project is under the MIT license
#include "drivers/ds75lx.h" #include "drivers/ds75lx.h"
#include <xtimer.h> #include <xtimer.h>
#include <mutex.h>
// Buffer that contains encoded data.
static uint8_t bm_buffer[10];
// Temperature cache. // Temperature cache.
static uint32_t temp_last_usec; static uint32_t temp_last_usec;
static uint16_t temp_cache = 0; static uint16_t temp_cache = 0;
// Static payload for benchmark. // Mutex that protect temperature cache.
lorariot_mcps_t bm_payload = LORARIOT_UNCONFIRMED_EX(DR_0, 50, 10, bm_buffer); static mutex_t temp_mutex = MUTEX_INIT;
// Get temperature with right payload format. // Get temperature with right payload format.
static uint16_t bm_get_temperature(void) static uint16_t bm_get_temperature(void)
{ {
uint32_t now = xtimer_now_usec(); // There are two threads that can use this function: benchmark thread and
if (now - temp_last_usec < (TEMPERATURE_UPDATE_MS * 1000)) // ping thread.
return temp_cache; mutex_lock(&temp_mutex);
int16_t temp; // Limit the number of times we read the temperature.
ds75_read_temperature(&temp); uint32_t now = xtimer_now_usec();
if (now - temp_last_usec >= (TEMPERATURE_UPDATE_MS * 1000)) {
int16_t temp;
ds75_read_temperature(&temp);
temp_cache = ((uint16_t)(temp + (55 << 8)) >> 6) & 0x1FF; temp_cache = ((uint16_t)(temp + (55 << 8)) >> 6) & 0x1FF;
temp_last_usec = now; temp_last_usec = now;
}
// Unlock one other waiting thread.
mutex_unlock(&temp_mutex);
return temp_cache; return temp_cache;
} }
// Encode message data to the payload. // Encode message data to the payload.
void bm_encode_payload(uint8_t power_i, uint8_t dr_i, uint8_t cr_i) void bm_encode_payload(lorariot_mcps_t *mcps, uint8_t power_i, uint8_t dr_i,
uint8_t cr_i)
{ {
assert(mcps->buffer && mcps->len >= 10);
// Retreive GPS data. // Retreive GPS data.
int32_t lat, lon; int32_t lat, lon;
int16_t alt; int16_t alt;
...@@ -55,32 +62,33 @@ void bm_encode_payload(uint8_t power_i, uint8_t dr_i, uint8_t cr_i) ...@@ -55,32 +62,33 @@ void bm_encode_payload(uint8_t power_i, uint8_t dr_i, uint8_t cr_i)
// Encode LoRa settings (on 8 bits). // Encode LoRa settings (on 8 bits).
bm_buffer[0] = uint8_t *buffer = (uint8_t *)mcps->buffer;
buffer[0] =
((dr_i & 0b111) << 5) | ((dr_i & 0b111) << 5) |
((cr_i & 0b1) << 4) | ((cr_i & 0b1) << 4) |
((power_i & 0b1111) << 0); ((power_i & 0b1111) << 0);
// Encode latitude (on 23 bits, we assume it's > 0). // Encode latitude (on 23 bits, we assume it's > 0).
bm_buffer[2] = ((uint32_t)lat >> 16) & 0x7F; buffer[2] = ((uint32_t)lat >> 16) & 0x7F;
bm_buffer[3] = ((uint32_t)lat >> 8) & 0xFF; buffer[3] = ((uint32_t)lat >> 8) & 0xFF;
bm_buffer[4] = ((uint32_t)lat >> 0) & 0xFF; buffer[4] = ((uint32_t)lat >> 0) & 0xFF;
// Encode longitude (on 24 bits). // Encode longitude (on 24 bits).
bm_buffer[5] = ((uint32_t)lon >> 16) & 0xFF; buffer[5] = ((uint32_t)lon >> 16) & 0xFF;
bm_buffer[6] = ((uint32_t)lon >> 8) & 0xFF; buffer[6] = ((uint32_t)lon >> 8) & 0xFF;
bm_buffer[7] = ((uint32_t)lon >> 0) & 0xFF; buffer[7] = ((uint32_t)lon >> 0) & 0xFF;
// Encode temperature (on 9 bits). // Encode temperature (on 9 bits).
bm_buffer[1] = (temp >> 1) & 0xFF; buffer[1] = (temp >> 1) & 0xFF;
bm_buffer[2] |= temp & 0b1; buffer[2] |= temp & 0b1;
// Encode altitude (on 16 bits); // Encode altitude (on 16 bits);
bm_buffer[8] = ((uint16_t)alt >> 8) & 0xFF; buffer[8] = ((uint16_t)alt >> 8) & 0xFF;
bm_buffer[9] = ((uint16_t)alt >> 0) & 0xFF; buffer[9] = ((uint16_t)alt >> 0) & 0xFF;
// Change MCPS parameters for the next frame. // Change MCPS parameters for the next frame.
bm_payload.code_rate = bm_cr[cr_i]; mcps->code_rate = bm_cr[cr_i];
bm_payload.power = bm_power[power_i]; mcps->power = bm_power[power_i];
bm_payload.dr = bm_dr[dr_i]; mcps->dr = bm_dr[dr_i];
} }
#
# Cubsat command module.
#
# Copyright (C) 2019, ENSIMAG students
# This project is under the MIT license
MODULE := cubsat-app-cmds
CFLAGS += -Wno-unused-parameter
include $(RIOTBASE)/Makefile.base
/*
Base commands.
Copyright (C) 2019, ENSIMAG students
This project is under the MIT license
*/
#include "commands.h"
// Debug "d" command.
int cmd_debug(int argc, char **argv)
{
// TODO.
return APP_CMD_OK;
}
// Reset "r" command.
int cmd_reset(int argc, char **argv)
{
// TODO.
return APP_CMD_OK;
}
/*
Controll commands (received from LoRaWAN or UART RX).
Copyright (C) 2019, ENSIMAG students
This project is under the MIT license
*/
#include "commands.h"
#include <string.h>
// All command entries.
static const app_cmd_ent_t cmd_entries[] = {
{ "d", cmd_debug },
{ "r", cmd_reset },
};
// Number of entries.
#define CMD_COUNT (sizeof(cmd_entries) / sizeof(*cmd_entries))
// Parse a command.
int cmds_parse(char *line)
{
// Count the number of arguments.
int argc = 1;
for (char *s = line; *s; s++) {
if (*s == ';') argc++;
}
// Split line into arguments.
char *argv[argc];
char *c = line;
for (char i = 0, *s = line; *s; s++) {
if (*s == ';') {
*s++ = '\0';
argv[(int)i++] = c;
c = s;
}
}
argv[argc - 1] = c;
// Get the command to run.
char *cmd = argv[0];
for (size_t i = 0; i < CMD_COUNT; i++) {
if (!strcmp(cmd, cmd_entries[i].name))
return cmd_entries[i].func(argc, argv);
}
// Command is not found.
return APP_CMD_NOT_FOUND;
}
/*
Controll commands (received from LoRaWAN or UART RX).
Copyright (C) 2019, ENSIMAG students
This project is under the MIT license
*/
#pragma once
/*
This module provides some commands for controlling this benchmark application.
There are two ways for sending a command: via a LoRaWAN packet on port 6 and via
Serial RX (message format is "§[msg]\n", without quotes, [msg] contains the
message).
Command messages are as following: "[cmd];[arg1];[arg2];.." (without quotes, no
new line at end), where [cmd] is the name of the command, [arg1] .. [argN] are
the command arguments.
*/
// An application command.
typedef int (*app_cmd_t)(int argc, char **argv);
// A command entry.
typedef struct {
char *name;
app_cmd_t func;
} app_cmd_ent_t;
// Standard command errors.
enum {
APP_CMD_OK = 0,
APP_CMD_NOT_FOUND = -50,
APP_CMD_INV_PARAMS = -51,
};
// Parse a command.
int cmds_parse(char *line);
// Initialize command module.
void cmds_init(void);
// All application commands.
int cmd_debug(int argc, char **argv);
int cmd_reset(int argc, char **argv);
/*
Received from LoRaWAN or UART RX.
Copyright (C) 2019, ENSIMAG students
This project is under the MIT license
*/
#include "commands.h"
#include "lorariot.h"
#include <thread.h>
#include <msg.h>
// Message queue of receive thread.
#define MSG_QUEUE_SIZE (4U)
static msg_t msg_queue[MSG_QUEUE_SIZE];
// LoRaRIOT event loop.
#define RECV_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
static char recv_stack[RECV_STACKSIZE];
// Thread that receive commands.
static void *recv_thread(void *args)
{
(void)args;
msg_init_queue(msg_queue, MSG_QUEUE_SIZE);
while (true) {
msg_t msg;
msg_receive(&msg);
switch (msg.type) {
// TODO.
}
}
return NULL;
}
// Initialize command module.
void cmds_init(void)
{
kernel_pid_t pid = thread_create(recv_stack, sizeof(recv_stack),
THREAD_PRIORITY_MAIN + 3, THREAD_CREATE_STACKTEST,
recv_thread, NULL, "recv-thread");
lorariot_set_recv_thread(pid);
}
...@@ -9,6 +9,8 @@ This file is based on LoRaMAC-node from Semtech, under Revised BSD License. ...@@ -9,6 +9,8 @@ This file is based on LoRaMAC-node from Semtech, under Revised BSD License.
#include "gps.h" #include "gps.h"
#include <mutex.h>
#include <string.h>