mirror of https://github.com/ArduPilot/ardupilot
150 lines
3.5 KiB
C++
150 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include "AP_HAL_Linux.h"
|
|
#include "RCInput.h"
|
|
#include <signal.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <assert.h>
|
|
#include <queue>
|
|
|
|
#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH
|
|
#define RCIN_RPI_CHN_NUM 8
|
|
#else
|
|
#define RCIN_RPI_CHN_NUM 1
|
|
#endif
|
|
|
|
namespace Linux {
|
|
|
|
enum state_t{
|
|
RCIN_RPI_INITIAL_STATE = -1,
|
|
RCIN_RPI_ZERO_STATE = 0,
|
|
RCIN_RPI_ONE_STATE = 1
|
|
};
|
|
|
|
//Memory table structure
|
|
typedef struct {
|
|
void **virt_pages;
|
|
void **phys_pages;
|
|
uint32_t page_count;
|
|
} memory_table_t;
|
|
|
|
|
|
//DMA control block structure
|
|
typedef struct {
|
|
uint32_t info, src, dst, length,
|
|
stride, next, pad[2];
|
|
} dma_cb_t;
|
|
|
|
class Memory_table {
|
|
// Allow RCInput_RPI access to private members of Memory_table
|
|
friend class RCInput_RPI;
|
|
|
|
private:
|
|
void** _virt_pages;
|
|
void** _phys_pages;
|
|
uint32_t _page_count;
|
|
|
|
public:
|
|
Memory_table();
|
|
Memory_table(uint32_t, int);
|
|
~Memory_table();
|
|
|
|
//Get virtual address from the corresponding physical address from memory_table.
|
|
void* get_virt_addr(const uint32_t phys_addr) const;
|
|
|
|
// This function returns physical address with help of pointer, which is offset from the beginning of the buffer.
|
|
void* get_page(void **pages, const uint32_t addr) const;
|
|
|
|
// This function returns offset from the beginning of the buffer using (virtual) address in 'pages' and memory_table.
|
|
uint32_t get_offset(void **pages, const uint32_t addr) const;
|
|
|
|
//How many bytes are available for reading in circle buffer?
|
|
uint32_t bytes_available(const uint32_t read_addr, const uint32_t write_addr) const;
|
|
|
|
uint32_t get_page_count() const;
|
|
};
|
|
|
|
|
|
class RCInput_RPI : public RCInput
|
|
{
|
|
public:
|
|
void init();
|
|
void _timer_tick(void);
|
|
RCInput_RPI();
|
|
~RCInput_RPI();
|
|
|
|
private:
|
|
|
|
//Physical adresses of peripherals. Are different on different Raspberries.
|
|
uint32_t dma_base;
|
|
uint32_t clk_base;
|
|
uint32_t pcm_base;
|
|
|
|
//registers
|
|
static volatile uint32_t *pcm_reg;
|
|
static volatile uint32_t *clk_reg;
|
|
static volatile uint32_t *dma_reg;
|
|
|
|
Memory_table *circle_buffer;
|
|
Memory_table *con_blocks;
|
|
|
|
uint64_t curr_tick;
|
|
|
|
uint32_t curr_tick_inc;
|
|
uint32_t curr_pointer;
|
|
uint32_t curr_channel;
|
|
|
|
struct RcChannel {
|
|
RcChannel() :
|
|
prev_tick(0), delta_time(0),
|
|
width_s0(0), width_s1(0),
|
|
curr_signal(0), last_signal(0),
|
|
enable_pin(0), state(RCIN_RPI_INITIAL_STATE)
|
|
{}
|
|
|
|
uint64_t prev_tick;
|
|
uint64_t delta_time;
|
|
|
|
uint16_t width_s0;
|
|
uint16_t width_s1;
|
|
|
|
uint8_t curr_signal;
|
|
uint8_t last_signal;
|
|
|
|
state_t state;
|
|
|
|
AP_HAL::DigitalSource *enable_pin;
|
|
} rc_channels[RCIN_RPI_CHN_NUM];
|
|
|
|
bool _initialized = false;
|
|
|
|
void init_dma_cb(dma_cb_t** cbp, uint32_t mode, uint32_t source, uint32_t dest, uint32_t length, uint32_t stride, uint32_t next_cb);
|
|
void* map_peripheral(uint32_t base, uint32_t len);
|
|
void init_registers();
|
|
void init_ctrl_data();
|
|
void init_PCM();
|
|
void init_DMA();
|
|
void init_buffer();
|
|
static void stop_dma();
|
|
static void termination_handler(int signum);
|
|
void set_sigaction();
|
|
void set_physical_addresses(int version);
|
|
void teardown() override;
|
|
};
|
|
|
|
}
|