These are the custom libraries
ds4.cpp
#include"Ds4.h"
Ds4::Ds4() {}
void Ds4::init() {
USB usb;
PS4USB ps4 = PS4USB(&usb);
usb_setup();
}
void Ds4::get() {
usb.Task();
// Check if DS4 is correctly recognized and get DS4 Data
if (ps4.connected()) {
axis[0] = ps4.getAnalogHat(LeftHatX);
axis[1] = ps4.getAnalogHat(LeftHatY);
axis[2] = ps4.getAnalogHat(RightHatX);
axis[3] = ps4.getAnalogHat(RightHatY);
axis[4] = ps4.getAnalogButton(L2);
axis[5] = ps4.getAnalogButton(R2);
button.options = ps4.getButtonClick(OPTIONS);
button.up = ps4.getButtonClick(UP);
button.down = ps4.getButtonClick(DOWN);
button.left = ps4.getButtonClick(LEFT);
button.right = ps4.getButtonClick(RIGHT);
button.x = ps4.getButtonClick(X);
button.circle = ps4.getButtonClick(CIRCLE);
button.square = ps4.getButtonClick(SQUARE);
button.triangle = ps4.getButtonClick(TRIANGLE);
button.r1 = ps4.getButtonClick(R1);
button.l1 = ps4.getButtonClick(L1);
battery = ps4.getBatteryLevel();
}
else {
usb_setup();
}
}
void Ds4::usb_setup() {
if (usb.Init() == -1) {
}
else {
}
}
bool Ds4::connected() {
bool flag = false;
usb.Task();
if (ps4.connected())
flag = true;
return flag;
}
Ds4.h
#ifndef DS4_H
#define DS4_H
#endif
#include <PS4USB.h>
#include <usbhub.h>
class Ds4 {
typedef struct button {
bool x, circle, square, triangle, up, down, left, right, options, r1, l1;
};
private:
USB usb;
PS4USB ps4 = PS4USB(&usb);
uint8_t middle = 127;
uint8_t deadzone = 50;
void usb_setup();
public:
char *status;
uint8_t axis[6];
button button;
uint8_t battery;
uint8_t motor;
Ds4();
void init();
void get();
void controller();
bool connected();
};
screen.cpp
#include"Screen.h"
Screen::Screen(RF24 *radio, uint8_t *channel_map, uint8_t *axis_range_min, uint8_t *axis_range_max) {
tft = new Adafruit_TFTLCD(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
this->radio = radio;
this->channel_map = channel_map;
menu = Menu(tft, radio);
menu_channels = Menu(tft, channel_map);
menu_range = Menu(tft, axis_range_min, axis_range_max, &view);
}
void Screen::init() {
tft->reset();
tft->begin(0x9341);
tft->setRotation(3);
delay(50);
initial_view();
}
bool Screen::update() {
if (millis() - update_counter > SCREENUPDATE) {
update_counter = millis();
return true;
}
return false;
}
char* Screen::navigate(bool left, bool right, bool up, bool down, bool x, bool circle, bool options, bool l1, bool r1) {
char *action = "";
char *output = "";
if (view == "options") {
action = menu.execute(left, right, x, circle);
if (action == "exit") {
switch_view("control");
output = "back to control";
}
if (action == "Channels") {
switch_view("channels");
}
else if (action == "Axis Range") {
switch_view("range");
}
if (up) {
menu.previous();
}
else if (down) {
menu.next();
}
if (options || circle) {
switch_view("control");
output = "back to control";
}
}
else if (view == "channels") {
action = menu_channels.execute(left, right, x, circle);
if (up) {
menu_channels.previous();
}
else if (down) {
menu_channels.next();
}
if (options) {
switch_view("control");
output = "back to control";
}
if (circle || action == "exit") {
switch_view("options");
}
}
else if (view == "range") {
action = menu_range.execute(left, right, x, circle);
if (up) {
menu_range.previous();
}
else if (down) {
menu_range.next();
}
if (circle || action == "exit") {
switch_view("options");
}
}
else if (view == "set_range") {
action = menu_range.execute(left, right, x, circle);
if (left || right) {
menu_range.range_toggle();
}
else if (r1) {
menu_range.range_set(+10);
}
else if (l1) {
menu_range.range_set(-10);
}
else if (up) {
menu_range.range_set(+1);
}
else if (down) {
menu_range.range_set(-1);
}
if (circle) {
switch_view("range");
}
}
return output;
}
void Screen::print_peripheral_status(int id, char *type, char *message, bool force) {
char *status = "";
bool status_updated=false;
if (id == 0)
status = transmitter_status;
else if (id == 2)
status = controller_status;
if (status != message || force) {
if (type == "success") tft->setTextColor(GREEN);
else if (type == "warning") tft->setTextColor(YELLOW);
else if (type == "danger") tft->setTextColor(RED);
tft->setCursor(150, 40 + 10 * id);
tft->fillRect(150, 40 + 10 * id, 100, 10, BLACK);
tft->println(message);
status_updated = true;
delay(3);
}
if (status_updated) {
if (id == 0)
transmitter_status = message;
else if (id == 2)
controller_status = message;
}
}
void Screen::update_analog_axis(uint8_t axis, uint8_t x, uint8_t y, bool force) {
uint8_t width = 48;
uint8_t height = 48;
if (axis == 0) { // Left Stick
if (x != left_axis_pos[0] || y != left_axis_pos[1] || force) {
tft->drawLine(11 + left_axis_pos[0] / 255.0*width, 177 + left_axis_pos[1] / 255.0*height, 15 + left_axis_pos[0] / 255.0*width, 177 + left_axis_pos[1] / 255.0 * height, BLACK);
tft->drawLine(13 + left_axis_pos[0] / 255.0*width, 175 + left_axis_pos[1] / 255.0*height, 13 + left_axis_pos[0] / 255.0*width, 179 + left_axis_pos[1] / 255.0 * height, BLACK);
tft->drawLine(11 + 24, 177 + 24, 15 + 24, 177 + 24, TEALBLUE);
tft->drawLine(13 + 24, 175 + 24, 13 + 24, 179 + 24, TEALBLUE);
tft->drawLine(11 + x / 255.0*width, 177 + y / 255.0*height, 15 + x / 255.0*width, 177 + y / 255.0 * height, ORANGE);
tft->drawLine(13 + x / 255.0*width, 175 + y / 255.0*height, 13 + x / 255.0*width, 179 + y / 255.0 * height, ORANGE);
left_axis_pos[0] = x;
left_axis_pos[1] = y;
}
}else if (axis == 1) { // Left Stick
if (x != right_axis_pos[0] || y != right_axis_pos[1] || force) {
tft->drawLine(255 + right_axis_pos[0] / 255.0*width, 177 + right_axis_pos[1] / 255.0*height, 259 + right_axis_pos[0] / 255.0*width, 177 + right_axis_pos[1] / 255.0 * height, BLACK);
tft->drawLine(257 + right_axis_pos[0] / 255.0*width, 175 + right_axis_pos[1] / 255.0*height, 257 + right_axis_pos[0] / 255.0*width, 179 + right_axis_pos[1] / 255.0 * height, BLACK);
tft->drawLine(255 + 24, 177 + 24, 259 + 24, 177 + 24, TEALBLUE);
tft->drawLine(257 + 24, 175 + 24, 257 + 24, 179 + 24, TEALBLUE);
tft->drawLine(255 + x / 255.0*width, 177 + y / 255.0*height, 259 + x / 255.0*width, 177 + y / 255.0 * height, ORANGE);
tft->drawLine(257 + x / 255.0*width, 175 + y / 255.0*height, 257 + x / 255.0*width, 179 + y / 255.0 * height, ORANGE);
right_axis_pos[0] = x;
right_axis_pos[1] = y;
}
}
}
void Screen::update_motor(uint8_t motor) {
//if (motor != motor_state) {
tft->fillRect(11, 101, 4, 62 - motor / 255.0 * 62, DARKGRAY);
tft->fillRect(11, 101 + 62 - motor / 255.0 * 62, 4, motor / 255.0 * 62, ORANGE);
motor_state = motor;
//}
}
void Screen::update_battery(uint8_t ds4_battery, bool force) {
if (ds4_battery_state != ds4_battery || force) {
tft->fillRect(303, 11, 6, 18-ds4_battery/15.0*18, DARKGRAY);
tft->fillRect(303, 11+18-18*ds4_battery/15.0, 6, ds4_battery/15.0*18, GREEN);
ds4_battery_state = ds4_battery;
}
delay(5);
}
void Screen::switch_view(String change_to) {
view = change_to;
if (view == "control") initial_view();
else if (view == "options") menu.display("");
else if (view == "channels") menu_channels.display("");
else if (view == "range") menu_range.display("");
}
void Screen::update_voltage(float voltage, bool force) {
if (battery_state != voltage || force) {
if (voltage < 10) {
tft->setTextColor(ORANGE);
tft->setCursor(278, 40);
}
else {
tft->setTextColor(WHITE);
tft->setCursor(272, 40);
}
tft->fillRect(272, 40, 30, 10, BLACK);
tft->println(voltage);
battery_state = voltage;
}
delay(3);
}
void Screen::draw_plane(double x, double y, double z) {
// Draws black lines over the old orange lines
// Calculates the new rotation matrix and the position of the new lines
// in x and z plane. Afterwards print the new lines on the tft
if (Rot[0][0] != NULL) {
for (uint8_t i = 0; i < 12; i++) {
line[0] = origin[0] + Rot[0][0] * plane_vec[i][0] + Rot[0][1] * plane_vec[i][1] + Rot[0][2] * plane_vec[i][2];
line[2] = origin[0] + Rot[0][0] * plane_vec[i][3] + Rot[0][1] * plane_vec[i][4] + Rot[0][2] * plane_vec[i][5];
line[1] = origin[0] + Rot[2][0] * plane_vec[i][0] + Rot[2][1] * plane_vec[i][1] + Rot[2][2] * plane_vec[i][2];
line[3] = origin[0] + Rot[2][0] * plane_vec[i][3] + Rot[2][1] * plane_vec[i][4] + Rot[2][2] * plane_vec[i][5];
tft->drawLine(line[0], line[1], line[2], line[3], BLACK);
}
}
double d = sqrt(x * x + y * y + z * z);
double norm[3] = { x / d, y / d, z / d };
alpha = acos(norm[0]) + PI/2;
phi = acos(norm[2]);
double n[3] = { cos(alpha), sin(alpha), 0 };
Rot[0][0] = n[0] * n[0] * (1 - cos(phi)) + cos(phi);
Rot[0][1] = n[0] * n[1] * (1 - cos(phi)) - n[2] * sin(phi);
Rot[0][2] = n[0] * n[2] * (1 - cos(phi)) + n[1] * sin(phi);
Rot[1][0] = n[0] * n[1] * (1 - cos(phi)) + n[2] * sin(phi);
Rot[1][1] = n[1] * n[1] * (1 - cos(phi)) + cos(phi);
Rot[1][2] = n[1] * n[2] * (1 - cos(phi)) - n[0] * sin(phi);
Rot[2][0] = n[0] * n[2] * (1 - cos(phi)) - n[1] * sin(phi);
Rot[2][1] = n[1] * n[2] * (1 - cos(phi)) + n[0] * sin(phi);
Rot[2][2] = n[2] * n[2] * (1 - cos(phi)) + cos(phi);
for (uint8_t i = 0; i < 12; i++) {
line[0] = origin[0] + Rot[0][0] * plane_vec[i][0] + Rot[0][1] * plane_vec[i][1] + Rot[0][2] * plane_vec[i][2];
line[2] = origin[0] + Rot[0][0] * plane_vec[i][3] + Rot[0][1] * plane_vec[i][4] + Rot[0][2] * plane_vec[i][5];
line[1] = origin[0] + Rot[2][0] * plane_vec[i][0] + Rot[2][1] * plane_vec[i][1] + Rot[2][2] * plane_vec[i][2];
line[3] = origin[0] + Rot[2][0] * plane_vec[i][3] + Rot[2][1] * plane_vec[i][4] + Rot[2][2] * plane_vec[i][5];
tft->drawLine(line[0], line[1], line[2], line[3], ORANGE);
}
}
void Screen::initial_view() {
tft->fillScreen(BLACK);
tft->setCursor(10, 10);
tft->setTextColor(ORANGE);
tft->setTextSize(2);
tft->println("RC Flight Control");
tft->setTextColor(WHITE);
tft->setTextSize(1);
// Add peripherals entry under title
tft->setCursor(10, 40);
tft->println("NRF24L01+");
tft->setCursor(10, 50);
tft->println("USB Host Shield");
tft->setCursor(10, 60);
tft->println("PS4 Controller");
// Add subsection titles
tft->setTextColor(ORANGE);
tft->setCursor(10, 75);
tft->println("Device Feedback");
tft->drawLine(10, 85, 242, 85, ORANGE);
tft->setCursor(260, 75);
tft->println("DS4");
tft->drawLine(260, 85, 310, 85, ORANGE);
tft->setTextColor(WHITE);
// Draw Motor Status box
tft->setCursor(10, 90);
tft->println("Motor");
tft->drawRect(10, 100, 6, 64, WHITE);
// Draw Left Axis Box
tft->drawRect(10, 174, 56, 56, WHITE);
// Draw Right Axis Box
tft->drawRect(254, 174, 56, 56, WHITE);
// Draw Battery Level Boxes
tft->drawRect(302, 10, 8, 20, WHITE);
tft->drawRect(304, 8, 4, 3, WHITE);
// Draw Accelerometer box
tft->drawRect(76, 100, 168, 130, WHITE);
draw_plane(-4, 0, -9);
tft->setCursor(304, 40);
tft->println("V");
}
Screen.h
#ifndef SCREEN_H
#define SCREEN_H
#endif
#include <SPFD5408_Adafruit_GFX.h>
#include <SPFD5408_Adafruit_TFTLCD.h>
#include <stdlib.h>
#include "menu/Menu.h"
#include "RF24.h"
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4
#define SCREENUPDATE 100 // Update screen every x[ms]
#define BLACK 0x0000
#define BLUE 0x001F
#define RED int(238/8*2048) + int(0) + int(0)
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define DARKGREEN int(255/8*2048) + int(255/4*32) + int(0/8)
#define DARKGRAY int(70/8*2048) + int(70/4*32) + int(70/8)
#define LIGHTGRAY int(180/8*2048) + int(180/4*32) + int(180/8)
#define ORANGE int(255/8*2048) + int(120/4*32) + int(0/8)
#define TEALBLUE int(56/8*2048) + int(142/4*32) + int(142/8)
#define TURQUISE int(0/8*2048) + int(245/4*32) + int(255/8)
class Screen {
private:
Adafruit_TFTLCD *tft;
RF24 *radio;
uint8_t *channel_map;
unsigned int update_counter = 0;
char *controller_status = "";
char *transmitter_status = "";
uint8_t left_axis_pos[2] = { 0, 0 };
uint8_t right_axis_pos[2] = { 0,0 };
uint8_t ds4_battery_state = 0;
uint8_t motor_state = -1;
float battery_state = 0.0;
int16_t plane_vec[12][6] = {
{ 0, 30, 0, 0, -58, 0 }, // Rumpf
{ 0, 30, -4, 0, -70, -4 }, // Rumpf
{ -60, 0, 0, 60, 0, 0 }, // Fl¸gel front
{ -60, -10, 0, 60, -10, 0 }, // Fl¸gel hinten
{ -20, -70, 18, 20, -70, 18 }, // Side rudder
{ 0, -70, -4, 0, -70, 18 }, // Height rudder
{ 60, 0, 0, 60, -10, 0 },
{ -60, 0, 0, -60, -10, 0},
{ -20, -65, 18, 20, -65, 18},
{ -20, -65, 18, -20, -70, 18},
{ 20, -65, 18, 20, -70, 18},
{ 0, -65, 18, 0, -58, 0}
};
int16_t line[4];
int16_t origin[2] = { 160, 165 };
double phi = 0, alpha = 0;
double Rot[3][3];
void initial_view();
public:
String view = "control";
Menu menu;
Menu menu_channels;
Menu menu_range;
Screen(RF24 *radio, uint8_t *channel_map, uint8_t *axis_range_min, uint8_t *axis_range_max);
void init();
char* navigate(bool left, bool right, bool up, bool down, bool x, bool circle, bool options, bool l1, bool r1);
void switch_view(String view);
void print_peripheral_status(int id, char* type, char *message, bool force);
void update_analog_axis(uint8_t axis, uint8_t x, uint8_t y, bool force);
bool update();
void update_motor(uint8_t motor);
void update_battery(uint8_t ds4_battery, bool force);
void update_voltage(float voltage, bool force);
void draw_plane(double x, double y, double z);
};
menu.cpp
#include"Menu.h"
Menu::Menu() {}
Menu::Menu(Adafruit_TFTLCD *tft, RF24 *radio) {
// Not default constructor with getting the
// tfts address and creating the main options menu
this->tft = tft;
this->radio = radio;
options = new Option[5];
options[0] = Option("Channels", "enter");
options[1] = Option("Axis Range", "enter");
options[2] = Option("NRF24 PA Level", "select");
options[3] = Option("NRF24 Data Rate", "select");
options[4] = Option("Exit", "exit");
options[0].active = true;
options_size = 5;
title = "Options";
}
Menu::Menu(Adafruit_TFTLCD *tft, uint8_t *channel_map) {
// Not default constructor with getting the
// tfts address and creating the options for the channel selection
this->tft = tft;
this->channel_map = channel_map;
options = new Option[5];
options[0] = Option("Channel 1", "channel");
options[1] = Option("Channel 2", "channel");
options[2] = Option("Channel 3", "channel");
options[3] = Option("Channel 4", "channel");
options[4] = Option("Exit", "exit");
options[0].active = true;
options_size = 5;
title = "Channels";
}
Menu::Menu(Adafruit_TFTLCD *tft, uint8_t *axis_range_min, uint8_t *axis_range_max, String *view) {
// Not default constructor with getting the
// tfts address and creating the options for the axis range adjustment
this->tft = tft;
this->axis_range_min = axis_range_min;
this->axis_range_max = axis_range_max;
this->view = view;
options = new Option[5];
options[0] = Option("Channel 1", "range");
options[1] = Option("Channel 2", "range");
options[2] = Option("Channel 3", "range");
options[3] = Option("Channel 4", "range");
options[4] = Option("Exit", "exit");
options[0].active = true;
options_size = 5;
title = "Axis Range";
}
void Menu::display(char *type) {
// Creates the title on the tft display
tft->fillScreen(BLACK);
tft->setTextColor(ORANGE);
tft->setTextSize(2);
tft->setCursor(10, 10);
tft->println(title);
tft->setTextColor(WHITE);
tft->setTextSize(1);
init_main();
}
void Menu::init_main() {
uint8_t index = 0;
for (uint8_t i = 0; i < options_size; i++) {
tft->setCursor(30, 60 + 30 * i);
tft->println(options[i].getName());
tft->drawLine(20, 78 + 30 * i, 300, 78 + 30 * i, DARKGRAY);
if (options[i].active) {
index = i;
}
}
setMarker(index);
printParameter(-1);
}
void Menu::next() {
// Same as previous except of the direction
int8_t index = getActiveElement();
if (index > -1) {
options[index].active = false;
if (index == options_size - 1) {
index = 0;
}
else {
index = index + 1;
}
options[index].active = true;
}
else {
options[0].active = true;
index = 0;
}
setMarker(index);
}
void Menu::previous() {
// Set active for current element to false
// Get previous index (modulo-like) and set
// Next elements active variable to true
int8_t index = getActiveElement();
if (index > -1) {
options[index].active = false;
if (index == 0) {
index = options_size - 1;
}
else {
index = index - 1;
}
options[index].active = true;
}
else {
options[0].active = true;
index = 0;
}
setMarker(index);
}
void Menu::setMarker(uint8_t position) {
tft->fillRect(0, 60, 20, 160, BLACK);
tft->fillRect(5, 60 + 30 * position, 6, 6, ORANGE);
}
int8_t Menu::getActiveElement() {
int8_t index = -1;
for (int8_t i = 0; i < options_size; i++) {
if (options[i].active) {
index = i;
break;
}
}
return index;
}
char* Menu::execute(bool left, bool right, bool x, bool circle) {
int8_t active = getActiveElement();
char *action = "";
if (options[active].getType() == "enter" && x) { // Select channels
action = options[active].getName();
}
else if (options[active].getName() == "NRF24 PA Level") { // NRF24
if (left) {
char* state = options[active].previous();
setRadioLevel(state);
printParameter(active);
}
else if (right) {
char* state = options[active].next();
setRadioLevel(state);
printParameter(active);
}
}
else if (options[active].getName() == "NRF24 Data Rate") { // NRF24
if (left) {
char* state = options[active].previous();
setRadioDatarate(state);
printParameter(active);
}
else if (right) {
char* state = options[active].next();
setRadioDatarate(state);
printParameter(active);
}
}
else if (options[active].getType() == "channel") {
if (left) {
options[active].previous();
setChannelMap(active, options[active].getActiveParameter());
printParameter(active);
}
else if (right) {
options[active].next();
setChannelMap(active, options[active].getActiveParameter());
printParameter(active);
}
}
else if (options[active].getType() == "range" && x) {
channel = active;
*view = "set_range";
display_range_adjustment(active);
}
else if (options[active].getType() == "exit" && x) { // Exit
action = "exit";
}
return action;
}
void Menu::printParameter(int8_t id) {
if (id == -1) {
for (uint8_t i = 0; i < options_size; i++) {
if (options[i].getType() == "select" || options[i].getType() == "channel") {
tft->fillRect(200, 60 + 30 * i, 100, 8, BLACK);
tft->setCursor(200, 60 + 30 * i);
tft->setTextColor(WHITE);
tft->println(options[i].selectedParam());
}
}
}
else {
if (options[id].getType() == "select" || options[id].getType() == "channel") {
tft->fillRect(200, 60 + 30 * id, 100, 8, BLACK);
tft->setCursor(200, 60 + 30 * id);
tft->setTextColor(WHITE);
tft->println(options[id].selectedParam());
}
}
}
void Menu::display_range_adjustment(uint8_t id) {
tft->fillScreen(BLACK);
tft->setCursor(10, 10);
tft->setTextColor(ORANGE);
tft->setTextSize(2);
tft->println(options[id].getName());
tft->drawLine(30, 220, 290, 220, WHITE);
tft->drawLine(160, 90, 160, 160, WHITE);
tft->drawCircle(160, 220, 120, WHITE);
tft->fillRect(40, 221, 3, 19, BLACK);
tft->fillRect(278, 221, 3, 19, BLACK);
min_selected = false;
range_display_chart(ORANGE);
min_selected = true;
range_display_chart(ORANGE);
range_display_values(false);
}
void Menu::range_set(int8_t value) {
range_display_values(true);
range_display_chart(BLACK);
if (min_selected) {
axis_range_min[channel] = axis_range_min[channel] + value;
}
else {
axis_range_max[channel] = axis_range_max[channel] + value;
}
range_display_chart(ORANGE);
range_display_values(false);
}
void Menu::range_toggle() {
min_selected = !min_selected;
range_display_values(false);
}
void Menu::range_display_chart(uint16_t color) {
float center = (axis_range_min[channel] + axis_range_max[channel]) / 2.0;
if(min_selected)
tft->drawLine(cos(PI - axis_range_min[channel] / 180.0*PI) * 119 + 160, -sin(PI - axis_range_min[channel] / 180.0*PI) * 119 + 220, 160, 220, color);
else
tft->drawLine(cos(PI - axis_range_max[channel] / 180.0*PI) * 119 + 160, -sin(PI - axis_range_max[channel] / 180.0*PI) * 119 + 220, 160, 220, color);
tft->drawLine(cos(PI - center / 180.0*PI) * 59 + 160, -sin(PI - center / 180.0*PI) * 59 + 220, 160, 220, color);
}
void Menu::range_display_values(bool overwrite) {
if (overwrite) {
tft->setTextColor(BLACK);
if (min_selected) {
tft->setCursor(30, 100);
tft->println(axis_range_min[channel]);
}
else {
tft->setCursor(250, 100);
tft->println(axis_range_max[channel]);
}
}
else {
if (min_selected)
tft->setTextColor(WHITE);
else
tft->setTextColor(DARKGRAY);
tft->setCursor(30, 100);
tft->println(axis_range_min[channel]);
if (min_selected)
tft->setTextColor(DARKGRAY);
else
tft->setTextColor(WHITE);
tft->setCursor(250, 100);
tft->println(axis_range_max[channel]);
}
}
void Menu::setChannelMap(uint8_t id, uint8_t value) {
if(id >= 0 && id <= 3)
channel_map[id] = value;
}
void Menu::setRadioLevel(char *level) {
if (level == " 1.5 mW") {
radio->setPALevel(RF24_PA_MIN);
}
else if (level == " 6.3 mW") {
radio->setPALevel(RF24_PA_LOW);
}
else if (level == " 25.1 mW") {
radio->setPALevel(RF24_PA_HIGH);
}
else if (level == "100.0 mW") {
radio->setPALevel(RF24_PA_MAX);
}
delay(20);
}
void Menu::setRadioDatarate(char *rate) {
if (rate == "250 kb/s") {
radio->setDataRate(RF24_250KBPS);
}
else if (rate == " 1 Mb/s") {
radio->setDataRate(RF24_1MBPS);
}
else if (rate == " 2 Mb/s") {
radio->setDataRate(RF24_2MBPS);
}
}
Menu.h
#ifndef MENU_H
#define MENU_H
#endif
#define DARKGRAY int(70/8*2048) + int(70/4*32) + int(70/8)
#define BLACK 0x0000
#define ORANGE int(255/8*2048) + int(120/4*32) + int(0/8)
#define WHITE 0xFFFF
#define ARRAY_SIZE(X) sizeof(X)/sizeof(X[0])
#include<Arduino.h>
#include<SPFD5408_Adafruit_GFX.h>
#include<SPFD5408_Adafruit_TFTLCD.h>
#include"../option/Option.h"
#include "RF24.h"
class Menu {
private:
Adafruit_TFTLCD *tft;
RF24 *radio;
uint8_t *channel_map;
uint8_t *axis_range_min;
uint8_t *axis_range_max;
char *current_menu = "base";
String *view;
Option *options;
int options_size = 0;
bool min_selected = true; // true = min, false = max
uint8_t channel;
void init_main();
int8_t getActiveElement();
void setMarker(uint8_t position);
void setRadioLevel(char *level);
void setRadioDatarate(char *rate);
void setChannelMap(uint8_t id, uint8_t value);
char *title;
void display_range_adjustment(uint8_t id);
void range_display_values(bool overwrite);
void range_display_chart(uint16_t color);
public:
Menu();
Menu(Adafruit_TFTLCD *tft, RF24 *radio);
Menu(Adafruit_TFTLCD *tft, uint8_t *channel_map);
Menu(Adafruit_TFTLCD *tft, uint8_t *axis_range_min, uint8_t *axis_range_max, String *view);
void display(char *type);
void next();
void previous();
char *execute(bool left, bool right, bool x, bool circle);
void printParameter(int8_t id);
void range_toggle();
void range_set(int8_t value);
};
option.cpp
#include"Option.h"
Option::Option() {}
Option::Option(char *name, char *type) {
this->name = name;
this->type = type;
initialize();
}
char* Option::getName() {
return this->name;
}
void Option::initialize() {
//if (name == "NRF24 PA Level") {
//Parameter params[4];
//char name[6] = " Min ";
if (name == "NRF24 PA Level") {
params = new Parameter[4];
params[0] = Parameter(" 1.5 mW");
params[1] = Parameter(" 6.3 mW");
params[2] = Parameter(" 25.1 mW");
params[3] = Parameter("100.0 mW");
params_size = 4;
params[2].active = true;
}
else if (name == "NRF24 Data Rate") {
params = new Parameter[3];
params[0] = Parameter("250 kb/s");
params[1] = Parameter(" 1 Mb/s");
params[2] = Parameter(" 2 Mb/s");
params_size = 3;
params[0].active = true;
}
else if (type == "channel") {
params = new Parameter[8];
params[0] = Parameter("Left X");
params[1] = Parameter("Left X Inv.");
params[2] = Parameter("Left Y");
params[3] = Parameter("Left Y Inv.");
params[4] = Parameter("Right X");
params[5] = Parameter("Right X Inv.");
params[6] = Parameter("Right Y");
params[7] = Parameter("Right Y Inv.");
params_size = 8;
params[0].active = true;
}
}
char* Option::selectedParam() {
int8_t index = getActiveParameter();
char *output = "";
if (index > -1 && index < params_size) {
output = params[index].getName();
}
return output;
}
char* Option::getType() {
return this->type;
}
char* Option::next() {
int8_t index = getActiveParameter();
if (index >= 0) {
params[index].active = false;
if (index < params_size - 1) {
index = index + 1;
}
params[index].active = true;
}
else {
params[0].active = true;
}
return params[index].getName();
}
char* Option::previous() {
int8_t index = getActiveParameter();
if (index >= 0) {
params[index].active = false;
if (index > 0) {
index = index - 1;
}
params[index].active = true;
}
else {
index = 0;
params[0].active = true;
}
return params[index].getName();
}
int8_t Option::getActiveParameter() {
int8_t index = -1;
for (int8_t i = 0; i < params_size; i++) {
if (params[i].active) {
index = i;
break;
}
}
return index;
}
Option.h
#ifndef OPTION_H
#define OPTION_H
#endif
#include"parameter/Parameter.h"
#include<Arduino.h>
#define ARRAY_SIZE(X) sizeof(X)/sizeof(X[0])
class Option {
private:
char *name;
char *type;
Parameter *params;
uint8_t params_size;
void initialize();
public:
bool active = false;
Option();
Option(char *name, char *type);
char* getName();
char* getType();
char* selectedParam();
int8_t getActiveParameter();
char* next();
char* previous();
};
parameter.cpp
#include"Parameter.h"
Parameter::Parameter() {}
Parameter::Parameter(char *name) {
this->name = name;
}
char* Parameter::getName() {
return name;
}
Parameter.h
#ifndef PARAMETER_H
#define PARAMETER_H
#endif
#include<Arduino.h>
class Parameter {
private:
char *name;
public:
bool active = false;
Parameter();
Parameter(char *name);
char* getName();
};
options.cpp
/*#include"Options.h"
Options::Options(Adafruit_TFTLCD *tft) {
this->tft = tft;
}
Options::Options() {}
void Options::init() {
//String params[4] = ;
char *empty[] = { "test" };
char *params[] = { "31", "32", "23", "13" };
menu[0].init("Channels", "sub", empty, 0);
menu[1].init("NRF24 PA Level", "select", params, 1);
menu[2].init("Exit", "parent", empty, 0);
}
void Options::next() {
if (active_option_view == "main") {
for (uint8_t i = 0; i < ARRAY_SIZE(menu); i++) {
if (menu[i].active) {
menu[i].active = false;
if (i == ARRAY_SIZE(menu) - 1)
menu[0].active = true;
else
menu[i + 1].active = true;
break;
}
}
}
setMarker();
}
void Options::previous() {
if (active_option_view == "main") {
for (uint8_t i = 0; i < ARRAY_SIZE(menu); i++) {
if (menu[i].active) {
menu[i].active = false;
if (i == 0)
menu[ARRAY_SIZE(menu) - 1].active = true;
else
menu[i - 1].active = true;
break;
}
}
}
setMarker();
}
void Options::setMarker() {
tft->fillRect(0, 60, 20, 200, BLACK);
if (active_option_view == "main") {
bool active = false;
for (uint8_t i = 0; i < ARRAY_SIZE(menu); i++) {
if (menu[i].active) {
tft->fillRect(5, 60 + 30 * i, 10, 10, ORANGE);
active = true;
break;
}
}
if (!active) {
menu[0].active = true;
setMarker();
}
}
}
void Options::print(char *type) {
active_option_view = type;
tft->fillScreen(BLACK);
tft->setTextColor(ORANGE);
tft->setTextSize(2);
tft->setCursor(10, 10);
tft->println("Options");
tft->setTextColor(WHITE);
tft->setTextSize(1.6);
if (active_option_view == "main") {
for (uint8_t i = 0; i < ARRAY_SIZE(menu); i++) {
tft->setCursor(40, 60 + 30 * i);
tft->println(menu[i].name);
tft->drawLine(20, 78 + 30 * i, 300, 78 + 30 * i, DARKGRAY);
//if(menu[i].type == "select")
if (menu[i].type == "select") {
tft->setCursor(220, 60 + 30 * i);
Serial.begin(9600);
Serial.println(menu[i].name);
//tft->print(menu[i].params[0]);
}
}
setMarker();
}
else {
tft->setCursor(20, 60);
tft->println("Option menu not found");
}
}*/
Options.h
/*#ifndef OPTIONS_H
#define OPTIONS_H
#endif
#define DARKGRAY int(70/8*2048) + int(70/4*32) + int(70/8)
#define BLACK 0x0000
#define ORANGE int(255/8*2048) + int(120/4*32) + int(0/8)
#define WHITE 0xFFFF
#define ARRAY_SIZE(X) sizeof(X)/sizeof(X[0])
#include<SPFD5408_Adafruit_GFX.h>
#include<SPFD5408_Adafruit_TFTLCD.h>
#include"../option/Option.h"
//#include <StandardCplusplus.h>
//#include <serstream>
//#include <string>
//#include <vector>
//#include <iterator>
class Options {
private:
typedef struct params {
int id;
String name;
} parameter_t;
typedef struct option{
int id;
String name;
parameter_t params[];
} options_t;
options_t *menu;
Option menu[3];
Adafruit_TFTLCD *tft;
char *active_option_view;
void setMarker();
public:
Options();
Options(Adafruit_TFTLCD *tft);
void next();
void previous();
void print(char *type);
void init();
};*/