2023-12-27 16:15:11 +00:00
|
|
|
#include <DigitalOutputCard.hpp>
|
|
|
|
|
|
|
|
DigitalOutputCard::DigitalOutputCard(uint8_t address) {
|
|
|
|
this->address = address;
|
2023-12-28 12:01:37 +00:00
|
|
|
// load default pin map
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
|
|
this->pinMap[i] = i;
|
|
|
|
this->virtualPinMap[i] = i;
|
|
|
|
}
|
2023-12-27 16:15:11 +00:00
|
|
|
}
|
|
|
|
// Instantiate the card with the specified position on the dip switch
|
|
|
|
DigitalOutputCard::DigitalOutputCard(bool bit0, bool bit1, bool bit2, bool bit3, bool bit4) {
|
|
|
|
this->address = 0x20;
|
|
|
|
if (bit0) this->address += 1;
|
|
|
|
if (bit1) this->address += 2;
|
|
|
|
if (bit2) this->address += 4;
|
|
|
|
if (bit3) this->address += 8;
|
|
|
|
if (bit4) this->address += 16;
|
|
|
|
|
|
|
|
}
|
|
|
|
// Initialize the card
|
2023-12-27 19:18:21 +00:00
|
|
|
bool DigitalOutputCard::begin() {
|
2023-12-27 16:15:11 +00:00
|
|
|
this->pwm = Adafruit_PWMServoDriver(this->address);
|
2023-12-27 19:18:21 +00:00
|
|
|
this->pwm.begin();
|
|
|
|
pwm.setOutputMode(true);
|
|
|
|
// Output card don't send ack, we can't check if it's connected
|
|
|
|
// so we just return true
|
|
|
|
return true;
|
2023-12-27 16:15:11 +00:00
|
|
|
}
|
|
|
|
// Set the output to the specified state
|
|
|
|
void DigitalOutputCard::digitalWrite(uint8_t pin, bool state) {
|
2023-12-28 12:01:37 +00:00
|
|
|
this->pwm.setPin(virtualPinMap[pin], state ? 4095 : 0);
|
2023-12-28 05:46:39 +00:00
|
|
|
this->state_buffer[pin] = state;
|
|
|
|
this->value_buffer[pin] = state ? 4095 : 0;
|
2023-12-28 12:35:53 +00:00
|
|
|
if (this->framAutoSave) {
|
|
|
|
this->saveStateToFRAM();
|
|
|
|
this->savePinValueToFRAM(pin);
|
|
|
|
}
|
2023-12-29 17:49:09 +00:00
|
|
|
for (int i = 0; i < change_callbacks.size(); i++) {
|
|
|
|
change_callbacks[i](pin, state, state ? 4095 : 0);
|
2023-12-28 12:01:37 +00:00
|
|
|
}
|
2023-12-27 16:15:11 +00:00
|
|
|
}
|
|
|
|
// Set the output to the specified pwm value
|
|
|
|
void DigitalOutputCard::analogWrite(uint8_t pin, uint16_t value) {
|
|
|
|
// If value is greater than 4095, set it to 4095
|
|
|
|
if (value > 4095) value = 4095;
|
|
|
|
// Set the pwm value
|
2023-12-28 12:01:37 +00:00
|
|
|
this->pwm.setPin(virtualPinMap[pin], value);
|
2023-12-28 12:35:53 +00:00
|
|
|
if (this->framAutoSave) {
|
|
|
|
this->saveStateToFRAM();
|
|
|
|
this->savePinValueToFRAM(pin);
|
|
|
|
}
|
2023-12-28 05:46:39 +00:00
|
|
|
this->state_buffer[pin] = value > 0;
|
|
|
|
this->value_buffer[pin] = value;
|
2023-12-29 17:49:09 +00:00
|
|
|
for (int i = 0; i < change_callbacks.size(); i++) {
|
|
|
|
change_callbacks[i](pin, value > 0, value);
|
2023-12-28 12:01:37 +00:00
|
|
|
}
|
2023-12-27 19:18:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Dummy loop function
|
|
|
|
void DigitalOutputCard::loop() {
|
2023-12-28 04:41:20 +00:00
|
|
|
}
|
|
|
|
|
2023-12-28 05:46:39 +00:00
|
|
|
// Get the state of the specified pin
|
|
|
|
bool DigitalOutputCard::getState(uint8_t pin) {
|
|
|
|
return this->state_buffer[pin];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the pwm value of the specified pin
|
|
|
|
uint16_t DigitalOutputCard::getValue(uint8_t pin) {
|
|
|
|
return this->value_buffer[pin];
|
|
|
|
}
|
|
|
|
|
2023-12-28 04:41:20 +00:00
|
|
|
// Get type of card
|
|
|
|
uint8_t DigitalOutputCard::getType() {
|
|
|
|
return CARD_TYPE_DIGITAL_OUTPUT;
|
2023-12-28 10:03:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::setState(uint8_t pin, bool state) {
|
|
|
|
this-> state_buffer[pin] = state;
|
|
|
|
this->pwm.setPin(pin, state*value_buffer[pin]);
|
2023-12-28 12:35:53 +00:00
|
|
|
if(this->framAutoSave) {
|
|
|
|
this->saveStateToFRAM();
|
|
|
|
}
|
2023-12-29 17:49:09 +00:00
|
|
|
for(int i = 0; i < change_callbacks.size(); i++) {
|
|
|
|
change_callbacks[i](pin, state, value_buffer[pin]);
|
2023-12-28 12:01:37 +00:00
|
|
|
}
|
2023-12-28 10:03:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::setValue(uint8_t pin, uint16_t value) {
|
|
|
|
// If value is greater than 4095, set it to 4095
|
|
|
|
if (value > 4095) value = 4095;
|
|
|
|
this-> value_buffer[pin] = value;
|
|
|
|
this->pwm.setPin(pin, state_buffer[pin]*value);
|
2023-12-28 12:35:53 +00:00
|
|
|
if (this->framAutoSave) {
|
|
|
|
this->savePinValueToFRAM(pin);
|
|
|
|
}
|
2023-12-29 17:49:09 +00:00
|
|
|
for (int i = 0; i < change_callbacks.size(); i++) {
|
|
|
|
change_callbacks[i](pin, state_buffer[pin], value);
|
2023-12-28 12:01:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::registerChangeCallback(std::function<void(uint8_t, bool, uint16_t)> callback) {
|
2023-12-29 17:49:09 +00:00
|
|
|
this->change_callbacks.push_back(callback);
|
2023-12-28 10:03:47 +00:00
|
|
|
}
|
2023-12-28 12:01:37 +00:00
|
|
|
|
2023-12-29 17:49:09 +00:00
|
|
|
// void DigitalOutputCard::deregisterChangeCallback(std::function<void(uint8_t, bool, uint16_t)> callback) {
|
|
|
|
// for(int i = 0; i < change_callbacks.size(); i++) {
|
|
|
|
// if(change_callbacks[i].target<void(uint8_t, bool, uint16_t)>() == callback.target<void(uint8_t, bool, uint16_t)>()) {
|
|
|
|
// change_callbacks.erase(change_callbacks.begin()+i);
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2023-12-28 12:01:37 +00:00
|
|
|
|
|
|
|
void DigitalOutputCard::loadPinMap(uint8_t pinMap[16]) {
|
|
|
|
for(int i = 0; i < 16; i++) {
|
|
|
|
this->pinMap[i] = pinMap[i];
|
|
|
|
this->virtualPinMap[pinMap[i]] = i;
|
|
|
|
}
|
2023-12-28 12:35:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::bindFRAM(FRAM *fram, uint16_t address) {
|
|
|
|
this->fram = fram;
|
|
|
|
this->framBinded = true;
|
|
|
|
this->framAddress = address;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t DigitalOutputCard::packStates() {
|
|
|
|
uint16_t packed = 0;
|
|
|
|
for(int i = 0; i < 16; i++) {
|
|
|
|
packed |= (state_buffer[i] << i);
|
|
|
|
}
|
|
|
|
return packed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::unpackStates(uint16_t states) {
|
|
|
|
for(int i = 0; i < 16; i++) {
|
|
|
|
this->setState(i, (states >> i) & 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::saveToFRAM() {
|
|
|
|
if(!framBinded) return;
|
|
|
|
// Save the state
|
|
|
|
uint16_t packed = packStates();
|
|
|
|
this->fram->write16(framAddress, packed);
|
|
|
|
// Save the value
|
|
|
|
this->fram->write(framAddress+2, (uint8_t*)value_buffer, 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::loadFromFRAM() {
|
|
|
|
if(!framBinded) return;
|
|
|
|
// Load the state
|
|
|
|
uint16_t packed = this->fram->read16(framAddress);
|
|
|
|
unpackStates(packed);
|
|
|
|
// Load the value
|
|
|
|
uint16_t value[16];
|
|
|
|
this->fram->read(framAddress+2, (uint8_t*)value, 32);
|
|
|
|
for(int i = 0; i < 16; i++) {
|
|
|
|
this->setValue(i, value[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::setAutoSaveToFRAM(bool autoSave) {
|
|
|
|
this->framAutoSave = autoSave;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::savePinValueToFRAM(uint8_t pin) {
|
|
|
|
if(!framBinded) return;
|
|
|
|
this->fram->write(framAddress+2+pin*2, (uint8_t*)&value_buffer[pin], 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DigitalOutputCard::saveStateToFRAM() {
|
|
|
|
if(!framBinded) return;
|
|
|
|
uint16_t packed = packStates();
|
|
|
|
this->fram->write16(framAddress, packed);
|
2023-12-28 12:01:37 +00:00
|
|
|
}
|