further module implementation

feature/yukon
ZodiusInfuser 2023-08-05 15:35:00 +01:00
rodzic 30547952f2
commit 52a8246dee
19 zmienionych plików z 464 dodań i 97 usunięć

Wyświetl plik

@ -3,14 +3,14 @@
namespace pimoroni {
IO::IO(uint pin) :
pin(pin) {
gpio_init(pin);
};
gpio_init(pin);
};
IO::IO(uint pin, bool out, bool pull_up, bool pull_down) :
pin(pin) {
gpio_init(pin);
direction(out, pull_up, pull_down);
};
gpio_init(pin);
direction(out, pull_up, pull_down);
};
bool IO::direction() {
return gpio_is_dir_out(pin);

Wyświetl plik

@ -1,6 +1,7 @@
#include "audio_amp.hpp"
#include "../../logging.hpp"
#include "../../errors.hpp"
#include "tas_regs.hpp"
namespace pimoroni {
@ -15,7 +16,10 @@ namespace pimoroni {
}
AudioAmpModule::AudioAmpModule() :
YukonModule() {
YukonModule(),
slow_sda(nullptr),
slow_scl(nullptr),
amp_en(nullptr) {
}
AudioAmpModule::~AudioAmpModule() {
@ -26,6 +30,13 @@ namespace pimoroni {
}
void AudioAmpModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
// Create the "I2C" pin objects
slow_sda = new TCA_IO(slot.SLOW1, accessor);
slow_scl = new TCA_IO(slot.SLOW2, accessor);
// Create the enable pin object
amp_en = new TCA_IO(slot.SLOW3, accessor);
// Configure strip and power pins
configure();
@ -34,27 +45,99 @@ namespace pimoroni {
}
void AudioAmpModule::configure() {
slow_sda->to_output(true);
slow_scl->to_output(true);
amp_en->to_output(false);
}
void AudioAmpModule::enable() {
CHECK_INITIALISED
amp_en->value(true);
// Pre-Reset Configuration
write_i2c_reg(PAGE, 0x01); // Page 1
write_i2c_reg(0x37, 0x3a); // Bypass
write_i2c_reg(PAGE, 0xFD); // Page FD
write_i2c_reg(0x0D, 0x0D); // Access page
write_i2c_reg(0x06, 0xC1); // Set Dmin
write_i2c_reg(PAGE, 0x01); // Page 1
write_i2c_reg(0x19, 0xC0); // Force modulation
write_i2c_reg(PAGE, 0xFD); // Page FD
write_i2c_reg(0x0D, 0x0D); // Access page
write_i2c_reg(0x06, 0xD5); // Set Dmin
// Software Reset
write_i2c_reg(PAGE, 0x00); // Page 0
write_i2c_reg(0x7F, 0x00); // Book 0
write_i2c_reg(0x01, 0x01); // Software Reset
// Post-Reset Configuration
write_i2c_reg(PAGE, 0x01); // Page 1
write_i2c_reg(0x37, 0x3a); // Bypass
write_i2c_reg(PAGE, 0xFD); // Page FD
write_i2c_reg(0x0D, 0x0D); // Access page
write_i2c_reg(0x06, 0xC1); // Set Dmin
write_i2c_reg(0x06, 0xD5); // Set Dmin
// Initial Device Configuration - PWR_MODE0
write_i2c_reg(PAGE, 0x00); // Page 0
write_i2c_reg(0x0E, 0x44); // TDM tx vsns transmit enable with slot 4
write_i2c_reg(0x0F, 0x40); // TDM tx isns transmit enable with slot 0
write_i2c_reg(PAGE, 0x01); // Page 1
write_i2c_reg(0x21, 0x00); // Disable Comparator Hysterisis
write_i2c_reg(0x17, 0xC8); // SARBurstMask=0
write_i2c_reg(0x19, 0x00); // LSR Mode
write_i2c_reg(0x35, 0x74); // Noise minimized
write_i2c_reg(PAGE, 0xFD); // Page FD
write_i2c_reg(0x0D, 0x0D); // Access page
write_i2c_reg(0x3E, 0x4A); // Optimal Dmin
write_i2c_reg(0x0D, 0x00); // Remove access
write_i2c_reg(PAGE, 0x00); // Page 0
write_i2c_reg(CHNL_0, 0xA8); // PWR_MODE0 selected
write_i2c_reg(PVDD_UVLO, 0x00); // PVDD UVLO set to 2.76V
// My addition
write_i2c_reg(DC_BLK0, 0xA1); // VBAT1S_MODE set to internally generated
write_i2c_reg(DVC, 0x68); // Go to a low default
write_i2c_reg(INT_CLK_CFG, 0x99 + 0b0100000); // CLK_PWR_UD_EN abled, with long time. This causes output to stay active without mute.
write_i2c_reg(INT_MASK0, 0xFF);
write_i2c_reg(INT_MASK1, 0xFF);
write_i2c_reg(INT_MASK2, 0xFF);
write_i2c_reg(INT_MASK3, 0xFF);
write_i2c_reg(INT_MASK4, 0xFF);
write_i2c_reg(MODE_CTRL, 0x80); // Play audio, power up with playback, IV enabled
// A second play command is required for some reason, to take it out of software shutdown
// Temp commented out self.write_i2c_reg(MODE_CTRL, 0x80) # Play audio, power up with playback, IV enabled
}
void AudioAmpModule::disable() {
CHECK_INITIALISED
amp_en->value(false);
}
bool AudioAmpModule::is_enabled() {
return 0; // TODO
CHECK_INITIALISED
return amp_en->value();
}
void AudioAmpModule::exit_soft_shutdown() {
CHECK_INITIALISED
write_i2c_reg(MODE_CTRL, 0x80); // Calling this after a play seems to wake the amp up, but adds around 16ms
}
void AudioAmpModule::set_volume(float volume) {
if(volume < 0.0f || volume > 1.0f) {
throw std::invalid_argument("Volume out of range. Expected 0.0 to 1.0\n");
}
write_i2c_reg(DVC, (uint8_t)((1.0f - volume) * 0xC8));
}
float AudioAmpModule::read_temperature() {

Wyświetl plik

@ -44,10 +44,9 @@ namespace pimoroni {
uint I2S_CLK;
uint I2S_FS;
private:
TCA slow_sda;
TCA slow_scl;
TCA amp_en;
TCA_IO* slow_sda;
TCA_IO* slow_scl;
TCA_IO* amp_en;
//--------------------------------------------------

Wyświetl plik

@ -0,0 +1,119 @@
namespace pimoroni {
enum TASRegs {
// PAGE 0 Regs
PAGE = 0x00, // Device Page Section 8.9.5
SW_RESET = 0x01, // Software Reset Section 8.9.6
MODE_CTRL = 0x02, // Device operational mode Section 8.9.7
CHNL_0 = 0x03, // Y Bridge and Channel settings Section 8.9.8
DC_BLK0 = 0x04, // SAR Filter and DC Path Blocker Section 8.9.9
DC_BLK1 = 0x05, // Record DC Blocker Section 8.9.10
MISC_CFG1 = 0x06, // Misc Configuration 1 Section 8.9.11
MISC_CFG2 = 0x07, // Misc Configuration 2 Section 8.9.12
TDM_CFG0 = 0x08, // TDM Configuration 0 Section 8.9.13
TDM_CFG1 = 0x09, // TDM Configuration 1 Section 8.9.14
TDM_CFG2 = 0x0A, // TDM Configuration 2 Section 8.9.15
LIM_MAX_ATTN = 0x0B, // Limiter Section 8.9.16
TDM_CFG3 = 0x0C, // TDM Configuration 3 Section 8.9.17
TDM_CFG4 = 0x0D, // TDM Configuration 4 Section 8.9.18
TDM_CFG5 = 0x0E, // TDM Configuration 5 Section 8.9.19
TDM_CFG6 = 0x0F, // TDM Configuration 6 Section 8.9.20
TDM_CFG7 = 0x10, // TDM Configuration 7 Section 8.9.21
TDM_CFG8 = 0x11, // TDM Configuration 8 Section 8.9.22
TDM_CFG9 = 0x12, // TDM Configuration 9 Section 8.9.23
TDM_CFG10 = 0x13, // TDM Configuration 10 Section 8.9.24
TDM_CFG11 = 0x14, // TDM Configuration 11 Section 8.9.25
ICC_CNFG2 = 0x15, // ICC Mode Section 8.9.26
TDM_CFG12 = 0x16, // TDM Configuration 12 Section 8.9.27
ICLA_CFG0 = 0x17, // Inter Chip Limiter Alignment 0 Section 8.9.28
ICLA_CFG1 = 0x18, // Inter Chip Gain Alignment 1 Section 8.9.29
DG_0 = 0x19, // Diagnostic Signal Section 8.9.30
DVC = 0x1A, // Digital Volume Control Section 8.9.31
LIM_CFG0 = 0x1B, // Limiter Configuration 0 Section 8.9.32
LIM_CFG1 = 0x1C, // Limiter Configuration 1 Section 8.9.33
BOP_CFG0 = 0x1D, // Brown Out Prevention 0 Section 8.9.34
BOP_CFG1 = 0x1E, // Brown Out Prevention 1 Section 8.9.35
BOP_CFG2 = 0x1F, // Brown Out Prevention 2 Section 8.9.36
BOP_CFG3 = 0x20, // Brown Out Prevention 3 Section 8.9.37
BOP_CFG4 = 0x21, // Brown Out Prevention 4 Section 8.9.38
BOP_CFG5 = 0x22, // BOP Configuration 5 Section 8.9.40
BOP_CFG6 = 0x23, // Brown Out Prevention 6 Section 8.9.41
BOP_CFG7 = 0x24, // Brown Out Prevention 7 Section 8.9.42
BOP_CFG8 = 0x25, // Brown Out Prevention 8 Section 8.9.43
BOP_CFG9 = 0x26, // Brown Out Prevention 9 Section 8.9.44
BOP_CFG10 = 0x27, // BOP Configuration 10 Section 8.9.45
BOP_CFG11 = 0x28, // Brown Out Prevention 11 Section 8.9.46
BOP_CFG12 = 0x29, // Brown Out Prevention 12 Section 8.9.47
BOP_CFG13 = 0x2A, // Brown Out Prevention 13 Section 8.9.48
BOP_CFG14 = 0x2B, // Brown Out Prevention 14 Section 8.9.49
BOP_CFG15 = 0x2C, // BOP Configuration 15 Section 8.9.50
BOP_CFG17 = 0x2D, // Brown Out Prevention 16 Section 8.9.51
BOP_CFG18 = 0x2E, // Brown Out Prevention 17 Section 8.9.52
BOP_CFG19 = 0x2F, // Brown Out Prevention 18 Section 8.9.53
BOP_CFG20 = 0x30, // Brown Out Prevention 19 Section 8.9.54
BOP_CFG21 = 0x31, // BOP Configuration 21 Section 8.9.55
BOP_CFG22 = 0x32, // Brown Out Prevention 22 Section 8.9.56
BOP_CFG23 = 0x33, // Lowest PVDD Measured Section 8.9.57
BOP_CFG24 = 0x34, // Lowest BOP Attack Rate Section 8.9.57
NG_CFG0 = 0x35, // Noise Gate 0 Section 8.9.60
NG_CFG1 = 0x36, // Noise Gate 1 Section 8.9.61
LVS_CFG0 = 0x37, // Low Voltage Signaling Section 8.9.62
DIN_PD = 0x38, // Digital Input Pin Pull Down Section 8.9.63
IO_DRV0 = 0x39, // Output Driver Strength Section 8.9.64
IO_DRV1 = 0x3A, // Output Driver Strength Section 8.9.65
INT_MASK0 = 0x3B, // Interrupt Mask 0 Section 8.9.66
INT_MASK1 = 0x3C, // Interrupt Mask 1 Section 8.9.67
INT_MASK4 = 0x3D, // Interrupt Mask 4 Section 8.9.68
INT_MASK2 = 0x40, // Interrupt Mask 2 Section 8.9.69
INT_MASK3 = 0x41, // Interrupt Mask 3 Section 8.9.70
INT_LIVE0 = 0x42, // Live Interrupt Read-back 0 Section 8.9.71
INT_LIVE1 = 0x43, // Live Interrupt Read-back 1 Section 8.9.72
INT_LIVE1_0 = 0x44, // Live Interrupt Read-back 1_0 Section 8.9.73
INT_LIVE2 = 0x47, // Live Interrupt Read-back 2 Section 8.9.74
INT_LIVE3 = 0x48, // Live Interrupt Read-back 3 Section 8.9.75
INT_LTCH0 = 0x49, // Latched Interrupt Read-back 0 Section 8.9.76
INT_LTCH1 = 0x4A, // Latched Interrupt Read-back 1 Section 8.9.77
INT_LTCH1_0 = 0x4B, // Latched Interrupt Read-back 1_0 Section 8.9.78
INT_LTCH2 = 0x4F, // Latched Interrupt Read-back 2 Section 8.9.79
INT_LTCH3 = 0x50, // Latched Interrupt Read-back 3 Section 8.9.80
INT_LTCH4 = 0x51, // Latched Interrupt Read-back 4 Section 8.9.81
VBAT_MSB = 0x52, // SAR VBAT1S 0 Section 8.9.82
VBAT_LSB = 0x53, // SAR VBAT1S 1 Section 8.9.83
PVDD_MSB = 0x54, // SAR PVDD 0 Section 8.9.84
PVDD_LSB = 0x55, // SAR PVDD 1 Section 8.9.85
TEMP = 0x56, // SAR ADC Conversion 2 Section 8.9.86
INT_CLK_CFG = 0x5C, // Clock Setting and IRQZ Section 8.9.87
MISC_CFG3 = 0x5D, // Misc Configuration 3 Section 8.9.88
CLOCK_CFG = 0x60, // Clock Configuration Section 8.9.89
IDLE_IND = 0x63, // Idle channel current optimization Section 8.9.90
MISC_CFG4 = 0x65, // Misc Configuration 4 Section 8.9.91
TG_CFG0 = 0x67, // Tone Generator Section 8.9.92
CLK_CFG = 0x68, // Detect Clock Ration and Sample Rate Section 8.9.93
LV_EN_CFG = 0x6A, // Class-D and LVS Delays Section 8.9.94
NG_CFG2 = 0x6B, // Noise Gate 2 Section 8.9.95
NG_CFG3 = 0x6C, // Noise Gate 3 Section 8.9.96
NG_CFG4 = 0x6D, // Noise Gate 4 Section 8.9.97
NG_CFG5 = 0x6E, // Noise Gate 5 Section 8.9.98
NG_CFG6 = 0x6F, // Noise Gate 6 Section 8.9.99
NG_CFG7 = 0x70, // Noise Gate 7 Section 8.9.100
PVDD_UVLO = 0x71, // UVLO Threshold Section 8.9.101
DMD = 0x73, // DAC Modulator Dither Section 8.9.102
I2C_CKSUM = 0x7E, // I2C Checksum Section 8.9.104
BOOK = 0x7F, // Device Book Section 8.9.105
// PAGE 1 Regs
LSR = 0x19, // Modulation Section 8.9.106
INT_LDO = 0x36, // Internal LDO Setting Section 8.9.107
SDOUT_HIZ_1 = 0x3D, // Slots Control Section 8.9.108
SDOUT_HIZ_2 = 0x3E, // Slots Control Section 8.9.109
SDOUT_HIZ_3 = 0x3F, // Slots Control Section 8.9.110
SDOUT_HIZ_4 = 0x40, // Slots Control Section 8.9.111
SDOUT_HIZ_5 = 0x41, // Slots Control Section 8.9.112
SDOUT_HIZ_6 = 0x42, // Slots Control Section 8.9.113
SDOUT_HIZ_7 = 0x43, // Slots Control Section 8.9.114
SDOUT_HIZ_8 = 0x44, // Slots Control Section 8.9.115
SDOUT_HIZ_9 = 0x45, // Slots Control Section 8.9.116
TG_EN = 0x47, // Thermal Detection Enable Section 8.9.117
};
}

Wyświetl plik

@ -34,6 +34,13 @@ namespace pimoroni {
}
void BenchPowerModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
// Create the voltage pwm object
voltage_pwm = new PWMCluster(pio0, 0, slot.FAST2, 1, true);
// Create the power control pin objects
power_en = new IO(slot.FAST1);
power_good = new TCA_IO(slot.SLOW1, accessor);
// Configure strip and power pins
configure();
@ -42,47 +49,87 @@ namespace pimoroni {
}
void BenchPowerModule::configure() {
// Calculate a suitable pwm wrap period for this frequency
uint32_t period; uint32_t div256;
if(pimoroni::PWMCluster::calculate_pwm_factors(250000, period, div256)) {
pwm_period = period;
// Update the pwm before setting the new wrap
voltage_pwm->set_chan_level(0, 0, false);
voltage_pwm->set_chan_offset(0, 0, false);
// Set the new wrap (should be 1 less than the period to get full 0 to 100%)
voltage_pwm->set_wrap(pwm_period, true); // NOTE Minus 1 not needed here. Maybe should change Wrap behaviour so it is needed, for consistency with hardware pwm?
// Apply the new divider
// This is done after loading new PWM values to avoid a lockup condition
uint8_t div = div256 >> 8;
uint8_t mod = div256 % 256;
voltage_pwm->set_clkdiv_int_frac(div, mod);
}
power_en->to_output(false);
power_good->to_input();
}
void BenchPowerModule::enable() {
CHECK_INITIALISED
power_en->value(true);
}
void BenchPowerModule::disable() {
CHECK_INITIALISED
power_en->value(false);
}
bool BenchPowerModule::is_enabled() {
return 0; // TODO
CHECK_INITIALISED
return power_en->value();
}
void BenchPowerModule::set_pwm(float percent) {
voltage_pwm->set_chan_level(0, (uint32_t)(percent * (float)pwm_period));
}
void BenchPowerModule::set_target_voltage(float voltage) {
CHECK_INITIALISED
float percent;
if(voltage >= VOLTAGE_MID) {
percent = (voltage - VOLTAGE_MID) * 0.5f / (VOLTAGE_MAX - VOLTAGE_MID) + 0.5f;
percent = MIN(percent, 1.0f);
}
else {
percent = (voltage - VOLTAGE_MIN) * 0.5f / (VOLTAGE_MID - VOLTAGE_MIN);
percent = MAX(percent, 0.0);
}
set_target(percent);
}
void BenchPowerModule::set_target(float percent) {
CHECK_INITIALISED
if(percent < 0.0f || percent > 1.0f) {
throw std::invalid_argument("percent out of range. Expected 0.0 to 1.0\n");
}
set_pwm((percent * (PWM_MAX - PWM_MIN)) + PWM_MIN);
}
float BenchPowerModule::read_voltage() {
// return (self.__shared_adc_voltage() * (100 + 22)) / 22
float value = __read_adc1();
float voltage;
if(value >= VOLTAGE_MID_MEASURE) {
return ((value - VOLTAGE_MID_MEASURE) * (VOLTAGE_MAX - VOLTAGE_MID)) / (VOLTAGE_MAX_MEASURE - VOLTAGE_MID_MEASURE) + VOLTAGE_MID;
voltage = ((value - VOLTAGE_MID_MEASURE) * (VOLTAGE_MAX - VOLTAGE_MID)) / (VOLTAGE_MAX_MEASURE - VOLTAGE_MID_MEASURE) + VOLTAGE_MID;
}
else {
float voltage = ((value - VOLTAGE_MIN_MEASURE) * (VOLTAGE_MID - VOLTAGE_MIN)) / (VOLTAGE_MID_MEASURE - VOLTAGE_MIN_MEASURE) + VOLTAGE_MIN;
return MAX(voltage, 0.0);
voltage = ((value - VOLTAGE_MIN_MEASURE) * (VOLTAGE_MID - VOLTAGE_MIN)) / (VOLTAGE_MID_MEASURE - VOLTAGE_MIN_MEASURE) + VOLTAGE_MIN;
voltage = MAX(voltage, 0.0);
}
return voltage;
}
bool BenchPowerModule::read_power_good() {
return 0; // TODO
return power_good->value();
}
float BenchPowerModule::read_temperature() {

Wyświetl plik

@ -47,12 +47,14 @@ namespace pimoroni {
float min_temperature;
float avg_temperature;
float count_avg;
//--------------------------------------------------
private:
PWMCluster* voltage_pwm;
IO* power_en;
IO* power_good;
TCA_IO* power_good;
uint32_t pwm_period;
//--------------------------------------------------

Wyświetl plik

@ -18,12 +18,16 @@ namespace pimoroni {
YukonModule(),
frequency(frequency),
motor(nullptr),
encoder(nullptr) {
encoder(nullptr),
motor_en(nullptr),
motor_nfault(nullptr) {
}
BigMotorModule::~BigMotorModule() {
delete(motor);
delete(encoder);
delete(motor_en);
delete(motor_nfault);
}
std::string BigMotorModule::name() {
@ -31,6 +35,13 @@ namespace pimoroni {
}
void BigMotorModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
// Create motor object
motor = new MotorCluster(pio0, 0, slot.FAST3, NUM_MOTORS);
// Create motor control pin objects
motor_en = new TCA_IO(slot.SLOW3, accessor);
motor_nfault = new TCA_IO(slot.SLOW2, accessor);
// Configure strip and power pins
configure();
@ -39,23 +50,31 @@ namespace pimoroni {
}
void BigMotorModule::configure() {
motor->disable_all();
motor->decay_mode(0, SLOW_DECAY);
motor_nfault ->to_input();
motor_en->to_output(false);
}
void BigMotorModule::enable() {
CHECK_INITIALISED
motor_en->value(true);
}
void BigMotorModule::disable() {
CHECK_INITIALISED
motor_en->value(true);
}
bool BigMotorModule::is_enabled() {
return 0; // TODO
CHECK_INITIALISED
return motor_en->value();
}
bool BigMotorModule::read_fault() {
return 0; // TODO
CHECK_INITIALISED
return !motor_nfault->value();
}
bool BigMotorModule::read_current() {

Wyświetl plik

@ -15,6 +15,7 @@ namespace pimoroni {
//--------------------------------------------------
public:
static const std::string NAME;
static const uint NUM_MOTORS = 2;
static constexpr float DEFAULT_FREQUENCY = 25000.0f;
static constexpr float TEMPERATURE_THRESHOLD = 50.0f;
static constexpr float CURRENT_THRESHOLD = 25.0f;
@ -50,8 +51,8 @@ namespace pimoroni {
MotorCluster* motor;
Encoder* encoder;
private:
TCA motor_en;
TCA motor_nfault;
TCA_IO* motor_en;
TCA_IO* motor_nfault;
//--------------------------------------------------

Wyświetl plik

@ -0,0 +1,50 @@
#include "common.hpp"
namespace pimoroni {
TCA_IO::TCA_IO(TCA pin, TCAAccessor& accessor) :
pin(pin),
accessor(accessor) {
to_input();
};
TCA_IO::TCA_IO(TCA pin, TCAAccessor& accessor, bool out) :
pin(pin),
accessor(accessor) {
direction(out);
};
//TCA_IO::~TCA_IO() {
// to_input();
//}
bool TCA_IO::direction() {
return accessor.get_slow_config(pin);
}
void TCA_IO::direction(bool out) {
accessor.set_slow_config(pin, out);
}
void TCA_IO::to_output(bool val) {
value(val);
direction(GPIO_OUT);
}
void TCA_IO::to_input() {
direction(GPIO_IN);
value(false);
}
bool TCA_IO::value() {
if(direction()) {
return accessor.get_slow_output(pin);
}
else {
return accessor.get_slow_input(pin);
}
}
void TCA_IO::value(bool val) {
accessor.set_slow_output(pin, val);
}
};

Wyświetl plik

@ -8,6 +8,11 @@
#include <stdexcept>
namespace pimoroni {
#define CHECK_INITIALISED \
if(!is_initialised()) { \
throw std::runtime_error("Module not initialised\n"); \
}
struct TCA {
uint CHIP;
uint GPIO;
@ -43,7 +48,7 @@ namespace pimoroni {
HIGH = true
};
class SlotAccessor {
class TCAAccessor {
public:
virtual bool get_slow_input(TCA gpio) = 0;
virtual bool get_slow_output(TCA gpio) = 0;
@ -53,11 +58,30 @@ namespace pimoroni {
virtual void set_slow_output(TCA gpio, bool value) = 0;
virtual void set_slow_config(TCA gpio, bool output) = 0;
virtual void set_slow_polarity(TCA gpio, bool polarity) = 0;
};
class SlotAccessor : public TCAAccessor {
public:
virtual float read_slot_adc1(SLOT slot) = 0;
virtual float read_slot_adc2(SLOT slot) = 0;
};
class TCA_IO {
public:
TCA_IO(TCA pin, TCAAccessor& accessor);
TCA_IO(TCA pin, TCAAccessor& accessor, bool out);
//~TCA_IO();
bool direction();
void direction(bool out);
void to_output(bool val);
void to_input();
bool value();
void value(bool val);
private:
TCA pin;
TCAAccessor& accessor;
};
class YukonModule {
public:
static constexpr float ROOM_TEMP = 273.15f + 25.0f;
@ -102,23 +126,17 @@ namespace pimoroni {
}
float __read_adc1() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
return __accessor->read_slot_adc1(slot);
}
float __read_adc2() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
return __accessor->read_slot_adc2(slot);
}
float __read_adc2_as_temp() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
float sense = __accessor->read_slot_adc2(slot);
float r_thermistor = sense / ((3.3f - sense) / 5100.0f);
float t_kelvin = (BETA * ROOM_TEMP) / (BETA + (ROOM_TEMP * log(r_thermistor / RESISTOR_AT_ROOM_TEMP)));

Wyświetl plik

@ -18,11 +18,17 @@ namespace pimoroni {
YukonModule(),
motor_type(DUAL),
frequency(frequency),
motors(nullptr) {
motors(nullptr),
motors_decay(nullptr),
motors_toff(nullptr),
motors_en(nullptr) {
}
DualMotorModule::~DualMotorModule() {
delete(motors);
delete(motors_decay);
delete(motors_toff);
delete(motors_en);
}
std::string DualMotorModule::name() {
@ -30,7 +36,15 @@ namespace pimoroni {
}
void DualMotorModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
// Configure strip and power pins
// Create motor objects
motors = new MotorCluster(pio0, 0, slot.FAST1, NUM_MOTORS);
// Create motor control pin objects
motors_decay = new TCA_IO(slot.SLOW1, accessor);
motors_toff = new TCA_IO(slot.SLOW2, accessor);
motors_en = new TCA_IO(slot.SLOW3, accessor);
// Configure motors
configure();
// Pass the slot and adc functions up to the parent now that module specific initialisation has finished
@ -38,35 +52,46 @@ namespace pimoroni {
}
void DualMotorModule::configure() {
motors->disable_all();
motors_decay->to_output(false);
motors_toff->to_output(false);
motors_en->to_output(false);
}
void DualMotorModule::enable() {
CHECK_INITIALISED
motors_en->value(true);
}
void DualMotorModule::disable() {
CHECK_INITIALISED
motors_en->value(false);
}
bool DualMotorModule::is_enabled() {
return 0; // TODO
CHECK_INITIALISED
return motors_en->value();
}
bool DualMotorModule::decay() {
return 0; // TODO
CHECK_INITIALISED
return motors_decay->value();
}
void DualMotorModule::decay(bool val) {
CHECK_INITIALISED
motors_decay->value(val);
}
bool DualMotorModule::toff() {
return 0; // TODO
CHECK_INITIALISED
return motors_toff->value();
}
void DualMotorModule::toff(bool val) {
CHECK_INITIALISED
return motors_toff->value(val);
}
bool DualMotorModule::read_fault() {

Wyświetl plik

@ -55,9 +55,9 @@ namespace pimoroni {
//--------------------------------------------------
private:
MotorCluster* motors;
TCA motors_decay;
TCA motors_toff;
TCA motors_en;
TCA_IO* motors_decay;
TCA_IO* motors_toff;
TCA_IO* motors_en;
//--------------------------------------------------

Wyświetl plik

@ -27,6 +27,8 @@ namespace pimoroni {
delete(sw_output[1]);
delete(sw_enable[0]);
delete(sw_enable[1]);
delete(power_good[0]);
delete(power_good[1]);
}
std::string DualSwitchedModule::name() {
@ -39,8 +41,8 @@ namespace pimoroni {
sw_output[1] = new IO(slot.FAST3);
sw_enable[0] = new IO(slot.FAST1);
sw_enable[1] = new IO(slot.FAST3);
power_good[0] = slot.SLOW1;
power_good[1] = slot.SLOW3;
power_good[0] = new TCA_IO(slot.SLOW1, accessor);
power_good[1] = new TCA_IO(slot.SLOW3, accessor);
// Configure switch and power pins
configure();
@ -56,14 +58,12 @@ namespace pimoroni {
sw_enable[0]->to_output(false);
sw_enable[1]->to_output(false);
__accessor->set_slow_config(power_good[0], false);
__accessor->set_slow_config(power_good[1], false);
power_good[0]->to_input();
power_good[1]->to_input();
}
void DualSwitchedModule::enable(uint output) {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
if(output < 1 || output > NUM_SWITCHES) {
throw std::runtime_error("switch index out of range. Expected 1 to 2\n");
}
@ -72,9 +72,7 @@ namespace pimoroni {
}
void DualSwitchedModule::disable(uint output) {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
if(output < 1 || output > NUM_SWITCHES) {
throw std::runtime_error("switch index out of range. Expected 1 to 2\n");
}
@ -83,9 +81,7 @@ namespace pimoroni {
}
bool DualSwitchedModule::is_enabled(uint output) {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
if(output < 1 || output > NUM_SWITCHES) {
throw std::runtime_error("switch index out of range. Expected 1 to 2\n");
}
@ -94,9 +90,7 @@ namespace pimoroni {
}
void DualSwitchedModule::output(uint output, bool val) {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
if(output < 1 || output > NUM_SWITCHES) {
throw std::runtime_error("switch index out of range. Expected 1 to 2\n");
}
@ -105,9 +99,7 @@ namespace pimoroni {
}
bool DualSwitchedModule:: read_output(uint output) {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
if(output < 1 || output > NUM_SWITCHES) {
throw std::runtime_error("switch index out of range. Expected 1 to 2\n");
}
@ -116,14 +108,12 @@ namespace pimoroni {
}
bool DualSwitchedModule::read_power_good(uint output) {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
if(output < 1 || output > NUM_SWITCHES) {
throw std::runtime_error("switch index out of range. Expected 1 to 2\n");
}
return __accessor->get_slow_input(power_good[output - 1]);
return power_good[output - 1]->value();
}
float DualSwitchedModule::read_temperature() {

Wyświetl plik

@ -43,7 +43,7 @@ namespace pimoroni {
private:
IO* sw_output[2];
IO* sw_enable[2];
TCA power_good[2];
TCA_IO* power_good[2];
//--------------------------------------------------

Wyświetl plik

@ -86,30 +86,22 @@ namespace pimoroni {
}
void LEDStripModule::enable() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
power_en->value(true);
}
void LEDStripModule::disable() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
power_en->value(false);
}
bool LEDStripModule::is_enabled() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
return power_en->value();
}
bool LEDStripModule::read_power_good() {
if(!is_initialised()) {
throw std::runtime_error("Module not initialised\n");
}
CHECK_INITIALISED
return power_good->value();
}

Wyświetl plik

@ -27,6 +27,9 @@ namespace pimoroni {
}
void QuadServoDirectModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
// Create servo cluster object
servos = new ServoCluster(pio0, 0, slot.FAST1, NUM_SERVOS);
// Configure strip and power pins
configure();
@ -35,7 +38,7 @@ namespace pimoroni {
}
void QuadServoDirectModule::configure() {
servos->disable_all();
}
float QuadServoDirectModule::read_adc1() {

Wyświetl plik

@ -16,11 +16,15 @@ namespace pimoroni {
QuadServoRegModule::QuadServoRegModule(bool halt_on_not_pgood) :
YukonModule(),
halt_on_not_pgood(halt_on_not_pgood),
servos(nullptr) {
servos(nullptr),
power_en(nullptr),
power_good(nullptr) {
}
QuadServoRegModule::~QuadServoRegModule() {
delete(servos);
delete(power_en);
delete(power_good);
}
std::string QuadServoRegModule::name() {
@ -28,6 +32,13 @@ namespace pimoroni {
}
void QuadServoRegModule::initialise(const SLOT& slot, SlotAccessor& accessor) {
// Create servo cluster object
servos = new ServoCluster(pio0, 0, slot.FAST1, NUM_SERVOS);
// Create the power control pin objects
power_en = new TCA_IO(slot.SLOW1, accessor);
power_good = new TCA_IO(slot.SLOW2, accessor);
// Configure strip and power pins
configure();
@ -36,23 +47,30 @@ namespace pimoroni {
}
void QuadServoRegModule::configure() {
servos->disable_all();
power_en->to_output(false);
power_good->to_input();
}
void QuadServoRegModule::enable() {
CHECK_INITIALISED
power_en->value(true);
}
void QuadServoRegModule::disable() {
CHECK_INITIALISED
power_en->value(false);
}
bool QuadServoRegModule::is_enabled() {
return 0; // TODO
CHECK_INITIALISED
return power_en->value();
}
bool QuadServoRegModule::read_power_good() {
return 0; // TODO
CHECK_INITIALISED
return power_good->value();
}
float QuadServoRegModule::read_temperature() {

Wyświetl plik

@ -44,8 +44,8 @@ public:
public:
ServoCluster* servos;
private:
IO* power_en;
IO* power_good;
TCA_IO* power_en;
TCA_IO* power_good;
//--------------------------------------------------

Wyświetl plik

@ -2,6 +2,7 @@ add_library(yukon INTERFACE)
target_sources(yukon INTERFACE
${CMAKE_CURRENT_LIST_DIR}/yukon.cpp
${CMAKE_CURRENT_LIST_DIR}/modules/common.cpp
${CMAKE_CURRENT_LIST_DIR}/logging.cpp
${CMAKE_CURRENT_LIST_DIR}/modules/led_strip/led_strip.cpp
${CMAKE_CURRENT_LIST_DIR}/modules/quad_servo/quad_servo_direct.cpp