Initial detection of modules
This commit is contained in:
parent
fcd88de69b
commit
193211b772
|
@ -7,6 +7,7 @@ project(pico_examples C CXX ASM)
|
|||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(PICO_CXX_ENABLE_EXCEPTIONS 1)
|
||||
set(PICO_CXX_ENABLE_RTTI 1)
|
||||
|
||||
# Initialize the SDK
|
||||
pico_sdk_init()
|
||||
|
|
|
@ -26,6 +26,8 @@ Yukon y = Yukon();
|
|||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
y.change_logging(3);
|
||||
|
||||
// Initialise the servo
|
||||
y.init();
|
||||
|
||||
|
@ -35,6 +37,17 @@ int main() {
|
|||
sleep_ms(1000);
|
||||
printf("tud_cdc_connected()\n");
|
||||
|
||||
y.find_slots_with_module(LEDStripModule::info());
|
||||
y.find_slots_with_module(DualSwitchedModule::info());
|
||||
y.find_slots_with_module(BenchPowerModule::info());
|
||||
|
||||
//y.detect_module(Yukon::SLOT1);
|
||||
//y.detect_module(Yukon::SLOT2);
|
||||
//y.detect_module(Yukon::SLOT3);
|
||||
//y.detect_module(Yukon::SLOT4);
|
||||
//y.detect_module(Yukon::SLOT5);
|
||||
//y.detect_module(Yukon::SLOT6);
|
||||
|
||||
try {
|
||||
y.enable_main_output();
|
||||
|
||||
|
|
|
@ -91,6 +91,32 @@ namespace pimoroni {
|
|||
10, // ADC2_TEMP_ADDR (0b1010)
|
||||
};
|
||||
|
||||
bool LEDStripModule::is_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
return adc_level == ADC_LOW && slow1 == HIGH && slow2 == HIGH && slow3 == HIGH;
|
||||
}
|
||||
|
||||
bool DualMotorModule::is_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
return adc_level == ADC_HIGH && slow2 == HIGH && slow3 == HIGH;
|
||||
}
|
||||
|
||||
bool DualSwitchedModule::is_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
return adc_level == ADC_FLOAT && slow1 == HIGH && slow2 == LOW && slow3 == HIGH;
|
||||
}
|
||||
|
||||
bool BenchPowerModule::is_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
return slow1 == HIGH && slow2 == LOW && slow3 == LOW;
|
||||
}
|
||||
|
||||
|
||||
//module_callback Yukon::KNOWN_MODULES[] = {&LEDStripModule::is_module, &DualMotorModule::is_module};
|
||||
//const std::type_index Yukon::KNOWN_MODULES[] = {typeid(LEDStripModule), typeid(DualMotorModule)};
|
||||
|
||||
const ModuleInfo Yukon::KNOWN_MODULES[] = {
|
||||
LEDStripModule::info(),
|
||||
DualMotorModule::info(),
|
||||
DualSwitchedModule::info(),
|
||||
BenchPowerModule::info()
|
||||
};
|
||||
|
||||
const TCA Yukon::MAIN_EN = {0, 6};
|
||||
const TCA Yukon::USER_SW = {0, 7};
|
||||
|
@ -253,25 +279,25 @@ namespace pimoroni {
|
|||
return slot;
|
||||
}
|
||||
|
||||
std::vector<uint> Yukon::find_slots_with_module(std::type_info module_type) {
|
||||
std::vector<uint> Yukon::find_slots_with_module(ModuleInfo module_type) {
|
||||
if(is_main_output()) {
|
||||
throw std::runtime_error("Cannot find slots with modules whilst the main output is active\n");
|
||||
}
|
||||
|
||||
logging.info("> Finding slots with '{module_type.NAME}' module\n");
|
||||
logging.info("> Finding slots with '" + module_type.name + "' module\n");
|
||||
|
||||
std::vector<uint> slot_ids;
|
||||
for(auto it = slot_assignments.begin(); it != slot_assignments.end(); it++) {
|
||||
SLOT slot = it->first;
|
||||
logging.info("[Slot" + std::to_string(slot.ID) + "] ");
|
||||
std::type_info* detected = __detect_module(slot); // Need to have a return type that can be null
|
||||
const ModuleInfo* detected = __detect_module(slot); // Need to have a return type that can be null
|
||||
|
||||
if(detected != nullptr && (*detected) == module_type) {
|
||||
logging.info("Found '{detected.NAME}' module\n");
|
||||
if(detected != nullptr && detected->type == module_type.type) {
|
||||
logging.info("Found '" + detected->name + "' module\n");
|
||||
slot_ids.push_back(slot.ID);
|
||||
}
|
||||
else {
|
||||
logging.info("No '{module_type.NAME}` module\n");
|
||||
logging.info("No '" + module_type.name + "' module\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,20 +358,72 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
uint __match_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
return 0; //TODO
|
||||
const ModuleInfo* Yukon::__match_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
for(uint i = 0; i < count_of(KNOWN_MODULES); i++) {
|
||||
const ModuleInfo& m = KNOWN_MODULES[i];
|
||||
//printf("%s\n", std::get<0>(KNOWN_MODULES[i]).name());
|
||||
//printf("%s\n", std::get<1>(KNOWN_MODULES[i]).c_str());
|
||||
//printf("%d\n", std::get<2>(KNOWN_MODULES[i])(adc_level, slow1, slow2, slow3));
|
||||
//printf("%s\n", KNOWN_MODULES[i]..name());
|
||||
if(m.is_module(adc_level, slow1, slow2, slow3)) {
|
||||
return &m;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
std::type_info* __detect_module(uint slot_id) {
|
||||
return nullptr; //TODO
|
||||
|
||||
const ModuleInfo* Yukon::__detect_module(SLOT slot) {
|
||||
set_slow_config(slot.SLOW1, false);
|
||||
set_slow_config(slot.SLOW2, false);
|
||||
set_slow_config(slot.SLOW3, false);
|
||||
|
||||
get_slow_input(USER_SW);
|
||||
|
||||
__select_address(slot.ADC1_ADDR);
|
||||
float adc_val = 0.0f;
|
||||
for(uint i = 0; i < DETECTION_SAMPLES; i++) {
|
||||
adc_val += __shared_adc_voltage();
|
||||
}
|
||||
adc_val /= DETECTION_SAMPLES;
|
||||
|
||||
bool slow1 = get_slow_input(slot.SLOW1);
|
||||
bool slow2 = get_slow_input(slot.SLOW2);
|
||||
bool slow3 = get_slow_input(slot.SLOW3);
|
||||
|
||||
logging.debug("ADC1 = " + std::to_string(adc_val) + ", SLOW1 = " + std::to_string((int)slow1) + ", SLOW2 = " + std::to_string((int)slow2) + ", SLOW3 = " + std::to_string((int)slow3) + ", ");
|
||||
|
||||
uint adc_level = ADC_FLOAT;
|
||||
if(adc_val <= DETECTION_ADC_LOW) {
|
||||
adc_level = ADC_LOW;
|
||||
}
|
||||
else if(adc_val >= DETECTION_ADC_HIGH) {
|
||||
adc_level = ADC_HIGH;
|
||||
}
|
||||
|
||||
const ModuleInfo* detected = __match_module(adc_level, slow1, slow2, slow3);
|
||||
|
||||
__deselect_address();
|
||||
|
||||
return detected;
|
||||
}
|
||||
std::type_info* __detect_module(SLOT slot) {
|
||||
return nullptr; //TODO
|
||||
const ModuleInfo* Yukon::detect_module(uint slot_id) {
|
||||
if(is_main_output()) {
|
||||
throw std::runtime_error("Cannot detect modules whilst the main output is active\n");
|
||||
}
|
||||
|
||||
SLOT slot = __check_slot(slot_id);
|
||||
|
||||
return __detect_module(slot);
|
||||
}
|
||||
uint detect_module(uint slot) {
|
||||
return 0;
|
||||
}
|
||||
uint detect_module(SLOT slot) {
|
||||
return 0;
|
||||
|
||||
const ModuleInfo* Yukon::detect_module(SLOT slot) {
|
||||
if(is_main_output()) {
|
||||
throw std::runtime_error("Cannot detect modules whilst the main output is active\n");
|
||||
}
|
||||
|
||||
slot = __check_slot(slot);
|
||||
|
||||
return __detect_module(slot);
|
||||
}
|
||||
|
||||
void __expand_slot_list(std::vector<SLOT> slot_list) {
|
||||
|
@ -535,8 +613,6 @@ namespace pimoroni {
|
|||
return __shared_adc_voltage();
|
||||
}
|
||||
/*
|
||||
float time();
|
||||
|
||||
void assign_monitor_action(void* callback_function);
|
||||
*/
|
||||
void Yukon::monitor() {
|
||||
|
|
|
@ -6,9 +6,101 @@
|
|||
#include "errors.hpp"
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <typeindex>
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
class YukonModule {
|
||||
public:
|
||||
//static const std::string NAME = "Unnamed";
|
||||
|
||||
static constexpr float ROOM_TEMP = 273.15f + 25.0f;
|
||||
static constexpr float RESISTOR_AT_ROOM_TEMP = 10000.0f;
|
||||
static constexpr float BETA = 3435;
|
||||
|
||||
static bool is_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enum ADC {
|
||||
ADC_LOW = 0,
|
||||
ADC_HIGH = 1,
|
||||
ADC_FLOAT = 2,
|
||||
ADC_ANY = 3
|
||||
};
|
||||
|
||||
enum IO {
|
||||
LOW = false,
|
||||
HIGH = true
|
||||
};
|
||||
|
||||
typedef bool (*module_callback)(uint, bool, bool, bool) ;
|
||||
|
||||
struct ModuleInfo {
|
||||
std::type_index type;
|
||||
std::string name;
|
||||
module_callback is_module;
|
||||
};
|
||||
|
||||
#define INFO_FUNC(module_name) \
|
||||
static ModuleInfo info() { \
|
||||
return { typeid(module_name), module_name::name(), &module_name::is_module }; \
|
||||
}
|
||||
|
||||
class LEDStripModule : public YukonModule {
|
||||
public:
|
||||
//static const std::string NAME = "Unnamed";
|
||||
|
||||
static bool is_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
|
||||
static std::string name() {
|
||||
return "LED Strip";
|
||||
}
|
||||
|
||||
INFO_FUNC(LEDStripModule)
|
||||
};
|
||||
|
||||
|
||||
class DualMotorModule : public YukonModule {
|
||||
public:
|
||||
//static const std::string NAME = "Unnamed";
|
||||
|
||||
static bool is_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
|
||||
static std::string name() {
|
||||
return "Dual Motor";
|
||||
}
|
||||
|
||||
INFO_FUNC(DualMotorModule)
|
||||
};
|
||||
|
||||
class DualSwitchedModule : public YukonModule {
|
||||
public:
|
||||
//static const std::string NAME = "Unnamed";
|
||||
|
||||
static bool is_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
|
||||
static std::string name() {
|
||||
return "Dual Switched Output";
|
||||
}
|
||||
|
||||
INFO_FUNC(DualSwitchedModule)
|
||||
};
|
||||
|
||||
class BenchPowerModule : public YukonModule {
|
||||
public:
|
||||
//static const std::string NAME = "Unnamed";
|
||||
|
||||
static bool is_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
|
||||
static std::string name() {
|
||||
return "Bench Power";
|
||||
}
|
||||
|
||||
INFO_FUNC(BenchPowerModule)
|
||||
};
|
||||
|
||||
struct TCA {
|
||||
uint CHIP;
|
||||
uint GPIO;
|
||||
|
@ -67,6 +159,7 @@ namespace pimoroni {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class Yukon {
|
||||
public:
|
||||
static const SLOT SLOT1;
|
||||
|
@ -126,6 +219,13 @@ namespace pimoroni {
|
|||
static constexpr float DEFAULT_CURRENT_LIMIT = 20.0f;
|
||||
static constexpr float DEFAULT_TEMPERATURE_LIMIT = 90.0f;
|
||||
static constexpr float ABSOLUTE_MAX_VOLTAGE_LIMIT = 18.0f;
|
||||
|
||||
static const uint DETECTION_SAMPLES = 64;
|
||||
static constexpr float DETECTION_ADC_LOW = 0.1f;
|
||||
static constexpr float DETECTION_ADC_HIGH = 3.2f;
|
||||
|
||||
//static module_callback KNOWN_MODULES[];
|
||||
static const ModuleInfo KNOWN_MODULES[];
|
||||
private:
|
||||
I2C i2c;
|
||||
TCA9555 tca0;
|
||||
|
@ -182,7 +282,6 @@ namespace pimoroni {
|
|||
void set_slow_polarity(TCA gpio, bool polarity);
|
||||
|
||||
void change_output_mask(uint8_t chip, uint16_t mask, uint16_t state);
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
void change_logging(uint logging_level);
|
||||
|
@ -190,7 +289,7 @@ namespace pimoroni {
|
|||
SLOT __check_slot(uint slot_id);
|
||||
SLOT __check_slot(SLOT slot);
|
||||
|
||||
std::vector<uint> find_slots_with_module(std::type_info module_type);
|
||||
std::vector<uint> find_slots_with_module(ModuleInfo module_type);
|
||||
|
||||
void register_with_slot(Module* module, uint slot_id);
|
||||
void register_with_slot(Module* module, SLOT slot);
|
||||
|
@ -198,11 +297,10 @@ namespace pimoroni {
|
|||
void deregister_slot(uint slot_id);
|
||||
void deregister_slot(SLOT slot);
|
||||
|
||||
uint __match_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
std::type_info* __detect_module(uint slot_id);
|
||||
std::type_info* __detect_module(SLOT slot);
|
||||
uint detect_module(uint slot_id);
|
||||
uint detect_module(SLOT slot);
|
||||
const ModuleInfo* __match_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||
const ModuleInfo* __detect_module(SLOT slot);
|
||||
const ModuleInfo* detect_module(uint slot_id);
|
||||
const ModuleInfo* detect_module(SLOT slot);
|
||||
|
||||
void __expand_slot_list(std::vector<SLOT> slot_list);
|
||||
void __verify_modules(bool allow_unregistered, bool allow_undetected, bool allow_discrepencies, bool allow_no_modules);
|
||||
|
|
Loading…
Reference in New Issue