355 lines
9.5 KiB
C++
355 lines
9.5 KiB
C++
#include <stm32f1xx_hal.h>
|
|
#include <stm32f1xx_hal_uart.h>
|
|
|
|
#include <tuple>
|
|
|
|
#include "commons.hpp"
|
|
#include "logging.hpp"
|
|
#include "spi.hpp"
|
|
|
|
/*
|
|
* reserve PB11-PB15 for SPI2
|
|
*/
|
|
|
|
// STM32VL-Discovery green led - PC9
|
|
#define BTN_PORT GPIOA
|
|
#define LED_PORT GPIOC
|
|
#define LED1_PIN GPIO_PIN_8
|
|
#define LED2_PIN GPIO_PIN_9
|
|
#define BTN_PIN GPIO_PIN_0
|
|
#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE
|
|
|
|
#define LoRa_RESET_Pin GPIO_PIN_4
|
|
#define LoRa_RESET_GPIO_Port GPIOC
|
|
#define LoRa_CS_Pin GPIO_PIN_5
|
|
#define LoRa_CS_GPIO_Port GPIOC
|
|
|
|
#include "rfm95.hpp"
|
|
|
|
extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE];
|
|
extern SPI_HandleTypeDef hspi1;
|
|
|
|
void print_version(void) { log::info("running PentaTrack v0.1.3"); }
|
|
void print_help(void);
|
|
|
|
void loglevel_error(void) { log::set_loglevel(LogLevel::ERROR); }
|
|
void loglevel_info(void) { log::set_loglevel(LogLevel::INFO); }
|
|
void loglevel_debug(void) { log::set_loglevel(LogLevel::DEBUG); }
|
|
|
|
template <size_t Size>
|
|
class cmd_holder {
|
|
public:
|
|
typedef void (*functionPointerType)(void);
|
|
|
|
using command_t =
|
|
std::tuple<std::string_view, std::string_view, functionPointerType>;
|
|
template <size_t S>
|
|
using command_array_t = std::array<command_t, Size>;
|
|
|
|
template <typename... Args>
|
|
constexpr cmd_holder(Args... command_list)
|
|
: commands{std::forward<Args>(command_list)...} {}
|
|
|
|
constexpr functionPointerType get_func(std::string_view message) const {
|
|
for (const auto &[cmd_name, cmd_help, func] : commands) {
|
|
if (message == cmd_name) {
|
|
return func;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void print_help() const {
|
|
log::info("Listing available commands:");
|
|
for (const auto &[cmd_name, cmd_help, func] : commands) {
|
|
log::info("\t", cmd_name, " - ", cmd_help);
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::array<command_t, Size> commands;
|
|
};
|
|
|
|
static bool updated_main_buf = false;
|
|
static bool print_main_buf = false;
|
|
static buffer<uint8_t, 512> main_buffer{};
|
|
static gps_data gps;
|
|
|
|
void print_buf(void) { main_buffer.print(); }
|
|
void print_gps(void) { gps.print(); }
|
|
void print_buf_toggle(void) { print_main_buf = !print_main_buf; }
|
|
|
|
class cmd_handler {
|
|
public:
|
|
static constexpr auto MaxCmdLength = 24;
|
|
using array_t = std::array<uint8_t, MaxCmdLength>;
|
|
using iterator_t = array_t::iterator;
|
|
using const_iterator_t = array_t::const_iterator;
|
|
|
|
constexpr cmd_handler() : symbols{}, iterator{symbols.begin()} {}
|
|
|
|
static cmd_handler &get() {
|
|
static auto c = cmd_handler{};
|
|
return c;
|
|
};
|
|
|
|
void add_symbol(uint8_t symbol) {
|
|
*iterator = symbol;
|
|
iterator++;
|
|
if (iterator == symbols.end()) {
|
|
iterator = symbols.begin();
|
|
}
|
|
}
|
|
|
|
std::string_view get_current_cmd() const {
|
|
return {reinterpret_cast<const char *>(symbols.data()),
|
|
static_cast<size_t>(
|
|
std::distance(symbols.begin(), const_iterator_t{iterator}))};
|
|
}
|
|
|
|
bool exists() const {
|
|
return commands.get_func(get_current_cmd()) != nullptr;
|
|
}
|
|
|
|
void execute() {
|
|
const auto current_cmd = get_current_cmd();
|
|
log::debug("Try executing command: ", current_cmd);
|
|
const auto func = commands.get_func(current_cmd);
|
|
iterator = symbols.begin();
|
|
|
|
if (func == nullptr) {
|
|
log::info("Unknown Command: ", current_cmd);
|
|
log::info("Type 'help' to show available commands.");
|
|
return;
|
|
}
|
|
|
|
func();
|
|
}
|
|
|
|
void queue_execution() { ShouldExecute = true; }
|
|
|
|
void run() {
|
|
if (ShouldExecute) {
|
|
execute();
|
|
ShouldExecute = false;
|
|
}
|
|
}
|
|
|
|
void print_help_() const { commands.print_help(); }
|
|
|
|
private:
|
|
static constexpr cmd_holder<8> commands{
|
|
std::make_tuple("ver", "Prints current version.", &print_version),
|
|
std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error),
|
|
std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info),
|
|
std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug),
|
|
std::make_tuple("gps", "Prints captured gps data", &print_gps),
|
|
std::make_tuple("buf", "Prints uart2 buffer", &print_buf),
|
|
std::make_tuple("buft", "toggles continous printing of uart2 buffer",
|
|
&print_buf_toggle),
|
|
std::make_tuple("help", "Prints available commands", &print_help)};
|
|
|
|
array_t symbols;
|
|
iterator_t iterator;
|
|
bool ShouldExecute = false;
|
|
};
|
|
|
|
void print_help(void) { cmd_handler::get().print_help_(); }
|
|
|
|
// This prevent name mangling for functions used in C/assembly files.
|
|
extern "C" {
|
|
void SysTick_Handler(void) {
|
|
HAL_IncTick();
|
|
HAL_SYSTICK_IRQHandler();
|
|
}
|
|
|
|
void USART2_IRQHandler(void) {
|
|
HAL_UART_IRQHandler(&gps_interface::s_UARTHandle);
|
|
HAL_UART_Receive_IT(&gps_interface::s_UARTHandle, uart_interface::get_buf(),
|
|
1);
|
|
}
|
|
|
|
void USART1_IRQHandler(void) {
|
|
HAL_UART_IRQHandler(&uart_interface::s_UARTHandle);
|
|
HAL_UART_Receive_IT(&uart_interface::s_UARTHandle, uart_interface::get_buf(),
|
|
1);
|
|
}
|
|
|
|
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
|
|
if (huart == &gps_interface::s_UARTHandle) {
|
|
return;
|
|
}
|
|
|
|
const uint8_t value = *uart_interface::get_buf();
|
|
|
|
if (value == '\r') {
|
|
cmd_handler::get().queue_execution();
|
|
return;
|
|
}
|
|
|
|
cmd_handler::get().add_symbol(value);
|
|
}
|
|
|
|
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
|
// const uint8_t value = *gps_interface::get_buf();
|
|
// gps_interface::write({reinterpret_cast<const char *>(&value), 1});
|
|
}
|
|
|
|
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
|
|
// log::debug("DMA Callback");
|
|
|
|
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET);
|
|
if (main_buffer.copy_from(gps_interface::new_rx_buf, Size)) {
|
|
updated_main_buf = true;
|
|
}
|
|
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET);
|
|
|
|
HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle,
|
|
gps_interface::new_rx_buf.data(),
|
|
gps_interface::new_rx_buf.size());
|
|
__HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT);
|
|
}
|
|
|
|
/**
|
|
* @brief This function handles DMA1 channel6 global interrupt.
|
|
*/
|
|
void DMA1_Channel6_IRQHandler(void) {
|
|
/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
|
|
|
|
/* USER CODE END DMA1_Channel6_IRQn 0 */
|
|
HAL_DMA_IRQHandler(&gps_interface::s_DMAHandle);
|
|
|
|
/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
|
|
|
|
/* USER CODE END DMA1_Channel6_IRQn 1 */
|
|
}
|
|
}
|
|
|
|
void initGPIO() {
|
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
|
|
|
GPIO_InitTypeDef GPIO_Config2;
|
|
GPIO_Config2.Mode = GPIO_MODE_INPUT;
|
|
GPIO_Config2.Pull = GPIO_PULLDOWN;
|
|
GPIO_Config2.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
GPIO_Config2.Pin = BTN_PIN;
|
|
|
|
GPIO_InitTypeDef GPIO_Config;
|
|
GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP;
|
|
GPIO_Config.Pull = GPIO_NOPULL;
|
|
GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
GPIO_Config.Pin = LED1_PIN | LED2_PIN;
|
|
|
|
GPIO_InitTypeDef GPIO_ConfigSPI;
|
|
GPIO_ConfigSPI.Mode = GPIO_MODE_OUTPUT_PP;
|
|
// GPIO_ConfigSPI.Pull = GPIO_NOPULL;
|
|
GPIO_ConfigSPI.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
GPIO_ConfigSPI.Pin = LoRa_CS_Pin | LoRa_RESET_Pin;
|
|
|
|
// bare metal init of led1:
|
|
// volatile uint32_t* CRH = reinterpret_cast<uint32_t*>(0x40011000 +
|
|
// 0x04);
|
|
//*CRH |= 0x3;
|
|
//*CRH &= (~0xC);
|
|
|
|
HAL_GPIO_Init(LED_PORT, &GPIO_Config);
|
|
HAL_GPIO_Init(BTN_PORT, &GPIO_Config2);
|
|
HAL_GPIO_Init(LoRa_CS_GPIO_Port, &GPIO_ConfigSPI);
|
|
// HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET);
|
|
// HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin,
|
|
// GPIO_PIN_SET);
|
|
}
|
|
|
|
extern "C" {
|
|
#include <stdio.h>
|
|
|
|
void start_interrupt() {
|
|
HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle,
|
|
gps_interface::new_rx_buf.data(),
|
|
gps_interface::new_rx_buf.size());
|
|
__HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT);
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
HAL_Init();
|
|
HAL_SYSTICK_Config(1);
|
|
initGPIO();
|
|
|
|
if (!log::init<uart_logger>()) {
|
|
// toggle status led or something
|
|
}
|
|
log::set_loglevel(LogLevel::DEBUG);
|
|
log::info("logging Initialized");
|
|
|
|
if (!MX_SPI1_Init()) {
|
|
// toggle status led or something
|
|
}
|
|
HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET);
|
|
HAL_Delay(10);
|
|
|
|
log::debug("SPI1 Initialized.");
|
|
|
|
if (!gps_interface::init()) {
|
|
log::error("UART2 Initialization failed, needed for GPS");
|
|
} else {
|
|
log::debug("Uart2 Initialized");
|
|
}
|
|
|
|
log::debug("Initialization done.");
|
|
|
|
char OP_Mode = 0x01;
|
|
char buff = 0x7F & OP_Mode;
|
|
char res = 0;
|
|
|
|
HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET);
|
|
[[maybe_unused]] auto result =
|
|
HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100);
|
|
HAL_SPI_Receive(&hspi1, (uint8_t *)&res, 1, 100);
|
|
HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET);
|
|
|
|
// RF95_Init();
|
|
|
|
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET);
|
|
|
|
while (1) {
|
|
cmd_handler::get().run();
|
|
|
|
// gps_interface::write("TEST");
|
|
// RF95_setModeRx_Continuous();
|
|
// HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET);
|
|
// RF95_receive(LoRa_buff);
|
|
// HAL_Delay(100);
|
|
// HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET);
|
|
// HAL_Delay(100);
|
|
|
|
if (gps.is_valid()) {
|
|
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET);
|
|
}
|
|
|
|
if (updated_main_buf) {
|
|
updated_main_buf = false;
|
|
gps.extract_gps_data(main_buffer);
|
|
|
|
if (print_main_buf) {
|
|
updated_main_buf = !main_buffer.print();
|
|
}
|
|
}
|
|
|
|
// std::string_view msg{reinterpret_cast<char *>(LoRa_buff)};
|
|
// log::info("Received Message");
|
|
// log::debug("Received Message");
|
|
// log::debug(msg);
|
|
|
|
// std::string_view foo{"Das ist ein test"};
|
|
// strcpy((char *)LoRa_buff, foo.data());
|
|
|
|
// RF95_send(LoRa_buff);
|
|
}
|
|
|
|
return 0;
|
|
}
|