kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Initial detection of modules
rodzic
fcd88de69b
commit
193211b772
|
@ -7,6 +7,7 @@ project(pico_examples C CXX ASM)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(PICO_CXX_ENABLE_EXCEPTIONS 1)
|
set(PICO_CXX_ENABLE_EXCEPTIONS 1)
|
||||||
|
set(PICO_CXX_ENABLE_RTTI 1)
|
||||||
|
|
||||||
# Initialize the SDK
|
# Initialize the SDK
|
||||||
pico_sdk_init()
|
pico_sdk_init()
|
||||||
|
|
|
@ -26,6 +26,8 @@ Yukon y = Yukon();
|
||||||
int main() {
|
int main() {
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
|
y.change_logging(3);
|
||||||
|
|
||||||
// Initialise the servo
|
// Initialise the servo
|
||||||
y.init();
|
y.init();
|
||||||
|
|
||||||
|
@ -35,6 +37,17 @@ int main() {
|
||||||
sleep_ms(1000);
|
sleep_ms(1000);
|
||||||
printf("tud_cdc_connected()\n");
|
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 {
|
try {
|
||||||
y.enable_main_output();
|
y.enable_main_output();
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,32 @@ namespace pimoroni {
|
||||||
10, // ADC2_TEMP_ADDR (0b1010)
|
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::MAIN_EN = {0, 6};
|
||||||
const TCA Yukon::USER_SW = {0, 7};
|
const TCA Yukon::USER_SW = {0, 7};
|
||||||
|
@ -253,25 +279,25 @@ namespace pimoroni {
|
||||||
return slot;
|
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()) {
|
if(is_main_output()) {
|
||||||
throw std::runtime_error("Cannot find slots with modules whilst the main output is active\n");
|
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;
|
std::vector<uint> slot_ids;
|
||||||
for(auto it = slot_assignments.begin(); it != slot_assignments.end(); it++) {
|
for(auto it = slot_assignments.begin(); it != slot_assignments.end(); it++) {
|
||||||
SLOT slot = it->first;
|
SLOT slot = it->first;
|
||||||
logging.info("[Slot" + std::to_string(slot.ID) + "] ");
|
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) {
|
if(detected != nullptr && detected->type == module_type.type) {
|
||||||
logging.info("Found '{detected.NAME}' module\n");
|
logging.info("Found '" + detected->name + "' module\n");
|
||||||
slot_ids.push_back(slot.ID);
|
slot_ids.push_back(slot.ID);
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
const ModuleInfo* Yukon::__match_module(uint adc_level, bool slow1, bool slow2, bool slow3) {
|
||||||
return 0; //TODO
|
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) {
|
const ModuleInfo* Yukon::detect_module(uint slot_id) {
|
||||||
return nullptr; //TODO
|
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;
|
const ModuleInfo* Yukon::detect_module(SLOT slot) {
|
||||||
}
|
if(is_main_output()) {
|
||||||
uint detect_module(SLOT slot) {
|
throw std::runtime_error("Cannot detect modules whilst the main output is active\n");
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
slot = __check_slot(slot);
|
||||||
|
|
||||||
|
return __detect_module(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __expand_slot_list(std::vector<SLOT> slot_list) {
|
void __expand_slot_list(std::vector<SLOT> slot_list) {
|
||||||
|
@ -535,8 +613,6 @@ namespace pimoroni {
|
||||||
return __shared_adc_voltage();
|
return __shared_adc_voltage();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
float time();
|
|
||||||
|
|
||||||
void assign_monitor_action(void* callback_function);
|
void assign_monitor_action(void* callback_function);
|
||||||
*/
|
*/
|
||||||
void Yukon::monitor() {
|
void Yukon::monitor() {
|
||||||
|
|
|
@ -6,9 +6,101 @@
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
namespace pimoroni {
|
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 {
|
struct TCA {
|
||||||
uint CHIP;
|
uint CHIP;
|
||||||
uint GPIO;
|
uint GPIO;
|
||||||
|
@ -67,6 +159,7 @@ namespace pimoroni {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Yukon {
|
class Yukon {
|
||||||
public:
|
public:
|
||||||
static const SLOT SLOT1;
|
static const SLOT SLOT1;
|
||||||
|
@ -126,6 +219,13 @@ namespace pimoroni {
|
||||||
static constexpr float DEFAULT_CURRENT_LIMIT = 20.0f;
|
static constexpr float DEFAULT_CURRENT_LIMIT = 20.0f;
|
||||||
static constexpr float DEFAULT_TEMPERATURE_LIMIT = 90.0f;
|
static constexpr float DEFAULT_TEMPERATURE_LIMIT = 90.0f;
|
||||||
static constexpr float ABSOLUTE_MAX_VOLTAGE_LIMIT = 18.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:
|
private:
|
||||||
I2C i2c;
|
I2C i2c;
|
||||||
TCA9555 tca0;
|
TCA9555 tca0;
|
||||||
|
@ -182,7 +282,6 @@ namespace pimoroni {
|
||||||
void set_slow_polarity(TCA gpio, bool polarity);
|
void set_slow_polarity(TCA gpio, bool polarity);
|
||||||
|
|
||||||
void change_output_mask(uint8_t chip, uint16_t mask, uint16_t state);
|
void change_output_mask(uint8_t chip, uint16_t mask, uint16_t state);
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
void change_logging(uint logging_level);
|
void change_logging(uint logging_level);
|
||||||
|
@ -190,7 +289,7 @@ namespace pimoroni {
|
||||||
SLOT __check_slot(uint slot_id);
|
SLOT __check_slot(uint slot_id);
|
||||||
SLOT __check_slot(SLOT slot);
|
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, uint slot_id);
|
||||||
void register_with_slot(Module* module, SLOT slot);
|
void register_with_slot(Module* module, SLOT slot);
|
||||||
|
@ -198,11 +297,10 @@ namespace pimoroni {
|
||||||
void deregister_slot(uint slot_id);
|
void deregister_slot(uint slot_id);
|
||||||
void deregister_slot(SLOT slot);
|
void deregister_slot(SLOT slot);
|
||||||
|
|
||||||
uint __match_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
const ModuleInfo* __match_module(uint adc_level, bool slow1, bool slow2, bool slow3);
|
||||||
std::type_info* __detect_module(uint slot_id);
|
const ModuleInfo* __detect_module(SLOT slot);
|
||||||
std::type_info* __detect_module(SLOT slot);
|
const ModuleInfo* detect_module(uint slot_id);
|
||||||
uint detect_module(uint slot_id);
|
const ModuleInfo* detect_module(SLOT slot);
|
||||||
uint detect_module(SLOT slot);
|
|
||||||
|
|
||||||
void __expand_slot_list(std::vector<SLOT> slot_list);
|
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);
|
void __verify_modules(bool allow_unregistered, bool allow_undetected, bool allow_discrepencies, bool allow_no_modules);
|
||||||
|
|
Ładowanie…
Reference in New Issue