179 lines
5.3 KiB
C++
179 lines
5.3 KiB
C++
#include <math.h>
|
|
|
|
#include "automation.hpp"
|
|
|
|
namespace automation {
|
|
|
|
const uint Automation2040W::ADC_LED_PINS[] = {6, 7, 8};
|
|
const uint Automation2040W::RELAY_PINS[] = {9, 10, 11};
|
|
const uint Automation2040W::USER_SW_PINS[] = {12, 13};
|
|
const uint Automation2040W::USER_LED_PINS[] = {14, 15};
|
|
const uint Automation2040W::OUTPUT_PINS[] = {16, 17, 18};
|
|
const uint Automation2040W::IN_BUFFERED_PINS[] = {19, 20, 21, 22};
|
|
const uint Automation2040W::ADC_PINS[] = {26, 27, 28};
|
|
|
|
|
|
Automation2040W::Automation2040W()
|
|
: i2c(I2C_SDA_PIN, I2C_SCL_PIN, 100000)
|
|
, analogs{Analog(ADC_PINS[0], VOLTAGE_GAIN, 0.0f, VOLTAGE_OFFSET),
|
|
Analog(ADC_PINS[1], VOLTAGE_GAIN, 0.0f, VOLTAGE_OFFSET),
|
|
Analog(ADC_PINS[2], VOLTAGE_GAIN, 0.0f, VOLTAGE_OFFSET)} {
|
|
}
|
|
|
|
bool Automation2040W::init() {
|
|
// Set up the relay pins
|
|
for(auto i = 0u; i < NUM_RELAYS; i++) {
|
|
gpio_set_function(RELAY_PINS[i], GPIO_FUNC_SIO);
|
|
gpio_set_dir(RELAY_PINS[i], GPIO_OUT);
|
|
release_relay(i);
|
|
}
|
|
|
|
// Set up the output pins
|
|
for(auto i = 0u; i < NUM_OUTPUTS; i++) {
|
|
gpio_set_function(OUTPUT_PINS[i], GPIO_FUNC_SIO);
|
|
gpio_set_dir(OUTPUT_PINS[i], GPIO_OUT);
|
|
output(i, false);
|
|
}
|
|
|
|
// Set up the input pins
|
|
for(auto i = 0u; i < NUM_INPUTS; i++) {
|
|
gpio_set_function(IN_BUFFERED_PINS[i], GPIO_FUNC_SIO);
|
|
gpio_set_dir(IN_BUFFERED_PINS[i], GPIO_IN);
|
|
}
|
|
|
|
// Set up the adc leds
|
|
for(auto i = 0u; i < NUM_ADCS; i++) {
|
|
gpio_put(ADC_LED_PINS[i], false);
|
|
pwm_config cfg = pwm_get_default_config();
|
|
pwm_set_wrap(pwm_gpio_to_slice_num(ADC_LED_PINS[i]), 65535);
|
|
pwm_init(pwm_gpio_to_slice_num(ADC_LED_PINS[i]), &cfg, true);
|
|
gpio_set_function(ADC_LED_PINS[i], GPIO_FUNC_PWM);
|
|
pwm_set_gpio_level(ADC_LED_PINS[i], 0);
|
|
}
|
|
|
|
// Set up the user switches and LEDs
|
|
for(auto i = 0u; i < NUM_SWITCHES; i++) {
|
|
gpio_set_function(USER_SW_PINS[i], GPIO_FUNC_SIO);
|
|
gpio_set_dir(USER_SW_PINS[i], GPIO_IN);
|
|
gpio_pull_up(USER_SW_PINS[i]);
|
|
|
|
gpio_put(USER_LED_PINS[i], false);
|
|
pwm_config cfg = pwm_get_default_config();
|
|
pwm_set_wrap(pwm_gpio_to_slice_num(USER_LED_PINS[i]), 65535);
|
|
pwm_init(pwm_gpio_to_slice_num(USER_LED_PINS[i]), &cfg, true);
|
|
gpio_set_function(USER_LED_PINS[i], GPIO_FUNC_PWM);
|
|
pwm_set_gpio_level(USER_LED_PINS[i], 0);
|
|
}
|
|
|
|
// Set up the connectivity LED
|
|
gpio_put(CONN_LED_PIN, false);
|
|
pwm_config cfg = pwm_get_default_config();
|
|
pwm_set_wrap(pwm_gpio_to_slice_num(CONN_LED_PIN), 65535);
|
|
pwm_init(pwm_gpio_to_slice_num(CONN_LED_PIN), &cfg, true);
|
|
gpio_set_function(CONN_LED_PIN, GPIO_FUNC_PWM);
|
|
pwm_set_gpio_level(CONN_LED_PIN, 0);
|
|
|
|
return true; // We just return true for now, but could expand in the future
|
|
}
|
|
|
|
void Automation2040W::conn_led(bool on) {
|
|
pwm_set_gpio_level(CONN_LED_PIN, on ? 65535 : 0);
|
|
}
|
|
|
|
void Automation2040W::conn_led(float brightness) {
|
|
brightness = CLAMP(brightness, 0.0f, 100.0f);
|
|
const float gamma = 2.8f;
|
|
uint16_t value = (uint16_t)(powf(brightness / 100.0f, gamma) * 65535.0f + 0.5f);
|
|
pwm_set_gpio_level(CONN_LED_PIN, value);
|
|
}
|
|
|
|
bool Automation2040W::switch_pressed(uint sw) {
|
|
assert(sw < NUM_SWITCHES);
|
|
return !gpio_get(USER_SW_PINS[sw]);
|
|
}
|
|
|
|
void Automation2040W::switch_led(uint sw, bool on) {
|
|
assert(sw < NUM_SWITCHES);
|
|
pwm_set_gpio_level(USER_LED_PINS[sw], on ? 65535 : 0);
|
|
}
|
|
|
|
void Automation2040W::switch_led(uint sw, float brightness) {
|
|
assert(sw < NUM_SWITCHES);
|
|
|
|
brightness = CLAMP(brightness, 0.0f, 100.0f);
|
|
const float gamma = 2.8f;
|
|
|
|
uint16_t value = (uint16_t)(powf(brightness / 100.0f, gamma) * 65535.0f + 0.5f);
|
|
pwm_set_gpio_level(USER_LED_PINS[sw], value);
|
|
}
|
|
|
|
bool Automation2040W::relay(uint relay) {
|
|
assert(relay < NUM_RELAYS);
|
|
return gpio_get(RELAY_PINS[relay]);
|
|
}
|
|
|
|
void Automation2040W::relay(uint relay, bool actuate) {
|
|
assert(relay < NUM_RELAYS);
|
|
gpio_put(RELAY_PINS[relay], actuate);
|
|
}
|
|
|
|
void Automation2040W::actuate_relay(uint relay) {
|
|
assert(relay < NUM_RELAYS);
|
|
gpio_put(RELAY_PINS[relay], true);
|
|
}
|
|
|
|
void Automation2040W::release_relay(uint relay) {
|
|
assert(relay < NUM_RELAYS);
|
|
gpio_put(RELAY_PINS[relay], false);
|
|
}
|
|
|
|
bool Automation2040W::output(uint output) {
|
|
assert(output < NUM_OUTPUTS);
|
|
return gpio_get(OUTPUT_PINS[output]);
|
|
}
|
|
|
|
void Automation2040W::output(uint output, bool value) {
|
|
assert(output < NUM_OUTPUTS);
|
|
gpio_put(OUTPUT_PINS[output], value);
|
|
}
|
|
|
|
bool Automation2040W::read_input(uint input) {
|
|
assert(input < NUM_INPUTS);
|
|
return gpio_get(IN_BUFFERED_PINS[input]);
|
|
}
|
|
|
|
float Automation2040W::read_adc(uint adc) {
|
|
assert(adc < NUM_ADCS);
|
|
float voltage = analogs[adc].read_voltage();
|
|
const float gamma = 2.8f;
|
|
uint16_t value = (uint16_t)(powf(voltage / MAX_ADC_LED_VOLTAGE, gamma) * 65535.0f + 0.5f);
|
|
pwm_set_gpio_level(ADC_LED_PINS[adc], value);
|
|
return voltage;
|
|
}
|
|
|
|
void Automation2040W::reset() {
|
|
// Reset the relays
|
|
for(auto i = 0u; i < NUM_RELAYS; i++) {
|
|
release_relay(i);
|
|
}
|
|
|
|
// Reset the outputs
|
|
for(auto i = 0u; i < NUM_OUTPUTS; i++) {
|
|
output(i, false);
|
|
}
|
|
|
|
// Reset the adc leds
|
|
for(auto i = 0u; i < NUM_ADCS; i++) {
|
|
pwm_set_gpio_level(ADC_LED_PINS[i], 0);
|
|
}
|
|
|
|
// Reset the switch LEDs
|
|
for(auto i = 0u; i < NUM_SWITCHES; i++) {
|
|
pwm_set_gpio_level(USER_LED_PINS[i], 0);
|
|
}
|
|
|
|
// Reset the connectivity LED
|
|
pwm_set_gpio_level(CONN_LED_PIN, 0);
|
|
}
|
|
}
|