Implement I2C communication with STM
This commit is contained in:
parent
49f703f4d4
commit
c553ea36d4
@ -68,6 +68,10 @@ ForEachMacros:
|
|||||||
- BOOST_FOREACH
|
- BOOST_FOREACH
|
||||||
IncludeBlocks: Regroup
|
IncludeBlocks: Regroup
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
|
# This will hopefully only catch stdlib headers
|
||||||
|
- Regex: "^<[^/]*>"
|
||||||
|
Priority: 5
|
||||||
|
SortPriority: 0
|
||||||
- Regex: '^[<"]SDL2/'
|
- Regex: '^[<"]SDL2/'
|
||||||
Priority: 2
|
Priority: 2
|
||||||
SortPriority: 0
|
SortPriority: 0
|
||||||
|
@ -11,6 +11,12 @@ set(CMAKE_CXX_STANDARD 17)
|
|||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(SDL2TTF REQUIRED)
|
find_package(SDL2TTF REQUIRED)
|
||||||
find_package(SDL2IMAGE REQUIRED)
|
find_package(SDL2IMAGE REQUIRED)
|
||||||
|
find_library(I2C_LIBRARY i2c REQUIRED)
|
||||||
|
if ("${I2C_LIBRARY}" STREQUAL "I2C_LIBRARY-NOTFOUND")
|
||||||
|
message(FATAL_ERROR "libi2c not found!")
|
||||||
|
else()
|
||||||
|
message("libi2c found at ${I2C_LIBRARY}")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
@ -48,6 +54,7 @@ add_executable(
|
|||||||
stw-display
|
stw-display
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/App.cpp
|
src/App.cpp
|
||||||
|
src/AppState.cpp
|
||||||
src/View.cpp
|
src/View.cpp
|
||||||
src/MissionSelect.cpp
|
src/MissionSelect.cpp
|
||||||
src/widgets.cpp
|
src/widgets.cpp
|
||||||
@ -67,6 +74,7 @@ target_link_libraries(
|
|||||||
${SDL2_LIBRARIES}
|
${SDL2_LIBRARIES}
|
||||||
${SDL2TTF_LIBRARY}
|
${SDL2TTF_LIBRARY}
|
||||||
${SDL2IMAGE_LIBRARY}
|
${SDL2IMAGE_LIBRARY}
|
||||||
|
${I2C_LIBRARY}
|
||||||
fmt
|
fmt
|
||||||
spdlog::spdlog)
|
spdlog::spdlog)
|
||||||
add_dependencies(stw-display fmt)
|
add_dependencies(stw-display fmt)
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "AppState.h"
|
||||||
#include "MissionSelect.h"
|
#include "MissionSelect.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
@ -7,8 +8,6 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
enum class AppView { MISSION_SELECT, AMI, DRIVER, TESTING };
|
|
||||||
|
|
||||||
class SDLManager {
|
class SDLManager {
|
||||||
public:
|
public:
|
||||||
SDLManager();
|
SDLManager();
|
||||||
@ -24,6 +23,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void init_sdl();
|
void init_sdl();
|
||||||
|
void init_state();
|
||||||
|
|
||||||
void handle_events();
|
void handle_events();
|
||||||
void render();
|
void render();
|
||||||
@ -33,10 +33,10 @@ private:
|
|||||||
// others and its destructor is called after the others.
|
// others and its destructor is called after the others.
|
||||||
SDLManager sdl_manager;
|
SDLManager sdl_manager;
|
||||||
|
|
||||||
|
std::unique_ptr<AppState> state;
|
||||||
std::unique_ptr<MissionSelect> mission_select;
|
std::unique_ptr<MissionSelect> mission_select;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
AppView view;
|
|
||||||
|
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
|
29
include/AppState.h
Normal file
29
include/AppState.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/ostream.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
constexpr int I2C_SLAVE_ADDR = 0x20;
|
||||||
|
constexpr int I2C_POLL_COMMAND = 0x00;
|
||||||
|
|
||||||
|
enum class AppView { MISSION_SELECT, AMI, DRIVER, TESTING };
|
||||||
|
std::ostream& operator<<(std::ostream& os, AppView view);
|
||||||
|
|
||||||
|
class AppState {
|
||||||
|
public:
|
||||||
|
AppState(const std::string& i2c_dev_path);
|
||||||
|
~AppState();
|
||||||
|
|
||||||
|
void poll();
|
||||||
|
|
||||||
|
AppView get_view();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This is optional so that we can still run the code on a PC without I2C
|
||||||
|
std::optional<int> i2c_dev_file;
|
||||||
|
|
||||||
|
AppView view;
|
||||||
|
};
|
25
src/App.cpp
25
src/App.cpp
@ -1,5 +1,6 @@
|
|||||||
#include "App.h"
|
#include "App.h"
|
||||||
|
|
||||||
|
#include "AppState.h"
|
||||||
#include "MissionSelect.h"
|
#include "MissionSelect.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
|
|
||||||
@ -13,10 +14,14 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
App::App() : view{AppView::MISSION_SELECT} { init_sdl(); }
|
App::App() {
|
||||||
|
init_sdl();
|
||||||
|
init_state();
|
||||||
|
}
|
||||||
|
|
||||||
App::~App() {
|
App::~App() {
|
||||||
// Destroy window
|
// Destroy window
|
||||||
@ -43,6 +48,14 @@ void App::init_sdl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::init_state() {
|
||||||
|
try {
|
||||||
|
state = std::make_unique<AppState>("/dev/i2c-3");
|
||||||
|
} catch (const std::runtime_error& e) {
|
||||||
|
spdlog::error("Couldn't create AppState: {}", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int App::run() {
|
int App::run() {
|
||||||
mission_select = std::make_unique<MissionSelect>(renderer);
|
mission_select = std::make_unique<MissionSelect>(renderer);
|
||||||
|
|
||||||
@ -58,6 +71,10 @@ int App::run() {
|
|||||||
frames = 0;
|
frames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state != nullptr) {
|
||||||
|
state->poll();
|
||||||
|
}
|
||||||
|
|
||||||
handle_events();
|
handle_events();
|
||||||
render();
|
render();
|
||||||
|
|
||||||
@ -93,22 +110,24 @@ void App::handle_events() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AppView view = state->get_view();
|
||||||
switch (view) {
|
switch (view) {
|
||||||
case AppView::MISSION_SELECT:
|
case AppView::MISSION_SELECT:
|
||||||
mission_select->handle_events(events);
|
mission_select->handle_events(events);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(fmt::format("Unknown view: {}", (int)view));
|
throw std::runtime_error(fmt::format("Unknown view: {}", view));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::render() {
|
void App::render() {
|
||||||
|
AppView view = state->get_view();
|
||||||
switch (view) {
|
switch (view) {
|
||||||
case AppView::MISSION_SELECT:
|
case AppView::MISSION_SELECT:
|
||||||
mission_select->draw();
|
mission_select->draw();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(fmt::format("Unknown view: {}", (int)view));
|
throw std::runtime_error(fmt::format("Unknown view: {}", view));
|
||||||
}
|
}
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
69
src/AppState.cpp
Normal file
69
src/AppState.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "AppState.h"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <optional>
|
||||||
|
extern "C" {
|
||||||
|
#include <i2c/smbus.h>
|
||||||
|
}
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, AppView view) {
|
||||||
|
switch (view) {
|
||||||
|
case AppView::MISSION_SELECT:
|
||||||
|
return os << "MISSION_SELECT";
|
||||||
|
case AppView::AMI:
|
||||||
|
return os << "AMI";
|
||||||
|
case AppView::DRIVER:
|
||||||
|
return os << "DRIVER";
|
||||||
|
case AppView::TESTING:
|
||||||
|
return os << "TESTING";
|
||||||
|
default:
|
||||||
|
return os << "UNKNOWN_VIEW[" << static_cast<int>(view) << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppState::AppState(const std::string& i2c_dev_path)
|
||||||
|
: view{AppView::MISSION_SELECT} {
|
||||||
|
i2c_dev_file = open(i2c_dev_path.c_str(), O_RDWR);
|
||||||
|
if (i2c_dev_file < 0) {
|
||||||
|
spdlog::error("Couldn't open I2C device: {}", errno);
|
||||||
|
i2c_dev_file = std::nullopt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(*i2c_dev_file, I2C_SLAVE, I2C_SLAVE_ADDR) < 0) {
|
||||||
|
spdlog::error("Couldn't set I2C slave address: {}", errno);
|
||||||
|
close(*i2c_dev_file);
|
||||||
|
i2c_dev_file = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppState::~AppState() {
|
||||||
|
if (i2c_dev_file) {
|
||||||
|
close(*i2c_dev_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppState::poll() {
|
||||||
|
if (!i2c_dev_file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t data[32];
|
||||||
|
int count = i2c_smbus_read_block_data(*i2c_dev_file, I2C_POLL_COMMAND, data);
|
||||||
|
if (count < 0) {
|
||||||
|
throw std::runtime_error(fmt::format("Couldn't poll I2C slave: {}", errno));
|
||||||
|
}
|
||||||
|
view = static_cast<AppView>(data[0]);
|
||||||
|
spdlog::info("View after poll: {}", view);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppView AppState::get_view() { return view; }
|
Loading…
x
Reference in New Issue
Block a user