/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
* AP_KDECAN.h
*
* Author: Francisco Ferreira and Tom Pittenger
*/
#pragma once
#include
#if AP_KDECAN_ENABLED
#include
#include
#include
#include
#define AP_KDECAN_USE_EVENTS (defined(CH_CFG_USE_EVENTS) && CH_CFG_USE_EVENTS == TRUE)
#if AP_KDECAN_USE_EVENTS
#include
#endif
#define DEFAULT_NUM_POLES 14
#define KDECAN_MAX_NUM_ESCS 8
class AP_KDECAN_Driver : public CANSensor
#if HAL_WITH_ESC_TELEM
, public AP_ESC_Telem_Backend
#endif
{
public:
AP_KDECAN_Driver();
// called from SRV_Channels
void update(const uint8_t num_poles);
private:
// handler for incoming frames
void handle_frame(AP_HAL::CANFrame &frame) override;
bool send_packet_uint16(const uint8_t address, const uint8_t dest_id, const uint32_t timeout_ms, const uint16_t data);
bool send_packet(const uint8_t address, const uint8_t dest_id, const uint32_t timeout_ms, const uint8_t *data = nullptr, const uint8_t data_len = 0);
void loop();
struct {
uint32_t detected_bitmask;
uint32_t detected_bitmask_ms;
} _init;
struct {
HAL_Semaphore sem;
bool is_new;
uint32_t last_new_ms;
uint16_t pwm[NUM_SERVO_CHANNELS];
#if AP_KDECAN_USE_EVENTS
thread_t *thread_ctx;
#endif
} _output;
#if HAL_WITH_ESC_TELEM
struct {
uint8_t num_poles;
uint32_t timer_ms;
} _telemetry;
#endif
union frame_id_t {
struct PACKED {
uint8_t object_address;
uint8_t destination_id;
uint8_t source_id;
uint8_t priority:5;
uint8_t unused:3;
};
uint32_t value;
};
static const uint8_t AUTOPILOT_NODE_ID = 0;
static const uint8_t BROADCAST_NODE_ID = 1;
static const uint8_t ESC_NODE_ID_FIRST = 2;
static const uint8_t ESC_INFO_OBJ_ADDR = 0;
static const uint8_t SET_PWM_OBJ_ADDR = 1;
static const uint8_t VOLTAGE_OBJ_ADDR = 2;
static const uint8_t CURRENT_OBJ_ADDR = 3;
static const uint8_t RPM_OBJ_ADDR = 4;
static const uint8_t TEMPERATURE_OBJ_ADDR = 5;
static const uint8_t GET_PWM_INPUT_OBJ_ADDR = 6;
static const uint8_t GET_PWM_OUTPUT_OBJ_ADDR = 7;
static const uint8_t MCU_ID_OBJ_ADDR = 8;
static const uint8_t UPDATE_NODE_ID_OBJ_ADDR = 9;
static const uint8_t ENUM_OBJ_ADDR = 10;
static const uint8_t TELEMETRY_OBJ_ADDR = 11;
static const uint32_t TELEMETRY_INTERVAL_MS = 100;
};
class AP_KDECAN {
public:
AP_KDECAN();
/* Do not allow copies */
CLASS_NO_COPY(AP_KDECAN);
static const struct AP_Param::GroupInfo var_info[];
void init();
void update();
static AP_KDECAN *get_singleton() { return _singleton; }
private:
static AP_KDECAN *_singleton;
AP_Int8 _num_poles;
AP_KDECAN_Driver *_driver;
};
namespace AP {
AP_KDECAN *kdecan();
};
#endif // AP_KDECAN_ENABLED