2023-10-26 02:17:19 -03:00
|
|
|
#include "AP_ICEngine_config.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
support for TCA9554 for starter control on I2C
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if AP_ICENGINE_TCA9554_STARTER_ENABLED
|
|
|
|
#include "AP_ICEngine.h"
|
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TCA9554 output register mapping for PMB Rev E
|
|
|
|
* P0 = PMU_EN - PMU output ON/OFF (CN6 pin 2)
|
|
|
|
* P1 = ECU_EN - Unused (previously Engine Kill Switch)
|
|
|
|
* P2 = I2C_P2 - Unused
|
|
|
|
* P3 = LED (active low)
|
|
|
|
* P4 = PMU_START - Crank Direction (CN6 pin 5)
|
|
|
|
* P5 = PMU_ARM - Crank Signal (CN6 pin 6)
|
|
|
|
* P6 = PMU_STAT_IN - Unused
|
|
|
|
* P7 = PMU_STAT - Unused
|
|
|
|
*/
|
|
|
|
#define TCA9554_I2C_BUS 1
|
|
|
|
#define TCA9554_I2C_ADDR 0x20
|
|
|
|
#define TCA9554_OUTPUT 0x01 // Output Port register address. Outgoing logic levels
|
|
|
|
#define TCA9554_OUT_DEFAULT 0x30 // 0011 0000
|
|
|
|
#define TCA9554_CONF 0x03 // Configuration Port register address [0 = Output]
|
|
|
|
#define TCA9554_PINS 0xC2 // Set all used ports to outputs = 1100 0010
|
|
|
|
|
|
|
|
/*
|
|
|
|
initialise TCA9554
|
|
|
|
*/
|
|
|
|
bool AP_ICEngine_TCA9554::TCA9554_init()
|
|
|
|
{
|
|
|
|
dev_TCA9554 = std::move(hal.i2c_mgr->get_device(TCA9554_I2C_BUS, TCA9554_I2C_ADDR));
|
|
|
|
if (!dev_TCA9554) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
WITH_SEMAPHORE(dev_TCA9554->get_semaphore());
|
|
|
|
|
|
|
|
// setup 1 checked registers
|
|
|
|
dev_TCA9554->setup_checked_registers(1);
|
|
|
|
|
|
|
|
dev_TCA9554->set_retries(10);
|
|
|
|
|
|
|
|
// set outputs
|
|
|
|
bool ret = dev_TCA9554->write_register(TCA9554_OUTPUT, TCA9554_OUT_DEFAULT);
|
|
|
|
if (!ret) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ret = dev_TCA9554->write_register(TCA9554_CONF, TCA9554_PINS, true);
|
|
|
|
if (!ret) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev_TCA9554->set_retries(1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
set the state of the i2c controller
|
|
|
|
*/
|
|
|
|
void AP_ICEngine_TCA9554::TCA9554_set(TCA9554_state_t value)
|
|
|
|
{
|
|
|
|
const uint32_t now_ms = AP_HAL::millis();
|
|
|
|
if (now_ms - last_reg_check_ms > 100) {
|
|
|
|
/*
|
|
|
|
register checking at 10Hz allows us to cope with the i2c
|
|
|
|
device being power cycled after boot
|
|
|
|
*/
|
|
|
|
last_reg_check_ms = now_ms;
|
|
|
|
WITH_SEMAPHORE(dev_TCA9554->get_semaphore());
|
|
|
|
dev_TCA9554->check_next_register();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value != last_state) {
|
|
|
|
WITH_SEMAPHORE(dev_TCA9554->get_semaphore());
|
|
|
|
// set outputs and status leds
|
|
|
|
if (dev_TCA9554->write_register(TCA9554_OUTPUT, (~(value<<2) & 0x0C) | value)) {
|
|
|
|
last_state = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-15 22:18:05 -03:00
|
|
|
void AP_ICEngine_TCA9554::set_starter(bool on, bool crank_dir_reverse)
|
2023-10-26 02:17:19 -03:00
|
|
|
{
|
|
|
|
if (!initialised) {
|
|
|
|
initialised = TCA9554_init();
|
|
|
|
if (!initialised) {
|
|
|
|
// waiting for power to PMU
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2024-08-15 22:18:05 -03:00
|
|
|
if (!crank_dir_reverse) {
|
|
|
|
TCA9554_set(on? STARTER_FORWARD : STARTER_OFF);
|
|
|
|
} else {
|
|
|
|
TCA9554_set(on? STARTER_REVERSE : STARTER_OFF);
|
|
|
|
}
|
2023-10-26 02:17:19 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // AP_ICENGINE_TCA9554_STARTER_ENABLED
|