ESPMegaPRO-v3-SDK/ESPMegaPRO-firmware/lib/ESPMegaPRO/DigitalInputCard.cpp

209 lines
6.3 KiB
C++
Raw Normal View History

2023-12-27 16:15:11 +00:00
#include <DigitalInputCard.hpp>
// Instantiate the card with the specified address
2023-12-30 11:27:39 +00:00
DigitalInputCard::DigitalInputCard(uint8_t address_a, uint8_t address_b) : callbacks()
2023-12-27 18:25:35 +00:00
{
2023-12-27 16:15:11 +00:00
this->address_a = address_a;
this->address_b = address_b;
}
// Instantiate the card with the specified position on the dip switch
// Bit 0,1,2 are for bank A
// Bit 3,4,5 are for bank B
2023-12-27 18:25:35 +00:00
DigitalInputCard::DigitalInputCard(bool bit0, bool bit1, bool bit2, bool bit3, bool bit4, bool bit5)
{
2023-12-27 16:15:11 +00:00
this->address_a = 0x20;
this->address_b = 0x20;
2023-12-27 18:25:35 +00:00
this->inputBufferA = 0;
this->inputBufferB = 0;
if (bit0)
this->address_a += 1;
if (bit1)
this->address_a += 2;
if (bit2)
this->address_a += 4;
if (bit3)
this->address_b += 1;
if (bit4)
this->address_b += 2;
if (bit5)
this->address_b += 4;
2023-12-27 16:15:11 +00:00
}
// Initialize the card
2023-12-27 19:18:21 +00:00
bool DigitalInputCard::begin()
2023-12-27 18:25:35 +00:00
{
2023-12-27 16:15:11 +00:00
this->inputBankA = PCF8574(this->address_a);
this->inputBankB = PCF8574(this->address_b);
2023-12-27 19:18:21 +00:00
if (!this->inputBankA.begin()) {
2023-12-30 11:47:52 +00:00
ESP_LOGE("DigitalInputCard", "Input Card ERROR: Failed to install input bank A");
2023-12-27 19:18:21 +00:00
return false;
}
if (!this->inputBankB.begin()) {
2023-12-30 11:47:52 +00:00
ESP_LOGE("DigitalInputCard", "Input Card ERROR: Failed to install input bank B");
2023-12-27 19:18:21 +00:00
return false;
}
2023-12-27 18:25:35 +00:00
// Set the debounce time for all pins to 50ms
for (int i = 0; i < 16; i++)
{
this->debounceTime[i] = 50;
this->lastDebounceTime[i] = 0;
}
// Initialize the pin map to the default values
for (int i = 0; i < 16; i++)
{
this->pinMap[i] = i;
this->virtualPinMap[i] = i;
}
2023-12-27 19:18:21 +00:00
return true;
2023-12-27 16:15:11 +00:00
}
// Refresh and Read the input from the specified pin, always refresh the input buffers
2023-12-27 18:25:35 +00:00
bool DigitalInputCard::digitalRead(uint8_t pin)
{
return this->digitalRead(pin, true);
2023-12-27 16:15:11 +00:00
}
// Read the input from the specified pin, also refresh the input buffers if refresh is true
2023-12-27 18:25:35 +00:00
bool DigitalInputCard::digitalRead(uint8_t pin, bool refresh)
{
pin = pinMap[pin];
2023-12-27 16:15:11 +00:00
// First check if the pin is in bank A or B
2023-12-27 18:25:35 +00:00
if (pin >= 0 && pin <= 7)
{
2023-12-27 16:15:11 +00:00
// Refresh the input buffers if refresh is true
2023-12-27 18:25:35 +00:00
if (refresh)
refreshInputBankA();
2023-12-27 16:15:11 +00:00
// Extract the bit from the buffer
return ((inputBufferA >> (7 - pin)) & 1);
2023-12-27 18:25:35 +00:00
}
else if (pin >= 8 && pin <= 15)
{
2023-12-27 16:15:11 +00:00
// Refresh the input buffers if refresh is true
2023-12-27 18:25:35 +00:00
if (refresh)
refreshInputBankB();
2023-12-27 16:15:11 +00:00
// Extract the bit from the buffer
return ((inputBufferB >> (15 - pin)) & 1);
}
2023-12-27 18:25:35 +00:00
return 255;
2023-12-27 16:15:11 +00:00
}
2023-12-27 18:25:35 +00:00
void DigitalInputCard::handlePinChange(int pin, uint8_t &currentBuffer, uint8_t &previousBuffer)
{
// Get the index of the pin in the pin map
uint8_t virtualPin = virtualPinMap[pin];
// Handle Bank A
if (((previousBuffer >> (7 - pin)) & 1) != ((currentBuffer >> (7 - pin)) & 1))
{
if (millis() - lastDebounceTime[pin] > debounceTime[pin])
{
lastDebounceTime[pin] = millis();
previousBuffer ^= (-((currentBuffer >> (7 - pin)) & 1) ^ previousBuffer) & (1UL << (7 - pin));
2023-12-29 17:49:09 +00:00
for (int i = 0; i < callbacks.size(); i++)
callbacks[i](virtualPin, ((currentBuffer >> (7 - pin)) & 1));
2023-12-27 18:25:35 +00:00
}
}
// Handle Bank B
if (((previousBuffer >> (15 - pin)) & 1) != ((currentBuffer >> (15 - pin)) & 1))
{
if (millis() - lastDebounceTime[pin] > debounceTime[pin])
{
lastDebounceTime[pin] = millis();
previousBuffer ^= (-((currentBuffer >> (15 - pin)) & 1) ^ previousBuffer) & (1UL << (15 - pin));
2023-12-29 17:49:09 +00:00
for (int i = 0; i < callbacks.size(); i++)
callbacks[i](virtualPin, ((currentBuffer >> (15 - pin)) & 1));
2023-12-27 18:25:35 +00:00
}
}
}
2023-12-29 17:49:09 +00:00
2023-12-27 16:15:11 +00:00
// Preform a loop to refresh the input buffers
2023-12-27 18:25:35 +00:00
void DigitalInputCard::loop()
{
2023-12-27 16:15:11 +00:00
// Refresh the input buffers
refreshInputBankA();
refreshInputBankB();
// Iterate over all pins and check if they changed
2023-12-27 18:25:35 +00:00
for (int i = 0; i < 16; i++)
{
2023-12-27 16:15:11 +00:00
// Check which bank the pin is in
2023-12-27 18:25:35 +00:00
if (i < 8)
{
handlePinChange(i, inputBufferA, previousInputBufferA);
}
else if (i >= 8 && i <= 15)
{
handlePinChange(i, inputBufferB, previousInputBufferB);
2023-12-27 16:15:11 +00:00
}
}
}
// Get the input buffer for bank A
2023-12-27 18:25:35 +00:00
uint8_t DigitalInputCard::getInputBufferA()
{
// Rearrange the bits to match the pin map
uint8_t inputBufferA_rearranged = 0;
for (int i = 0; i < 8; i++)
{
inputBufferA_rearranged |= ((inputBufferA >> i) & 1) << (7 - i);
}
return inputBufferA_rearranged;
2023-12-27 16:15:11 +00:00
}
// Get the input buffer for bank B
2023-12-27 18:25:35 +00:00
uint8_t DigitalInputCard::getInputBufferB()
{
// Rearrange the bits to match the pin map
uint8_t inputBufferB_rearranged = 0;
for (int i = 0; i < 8; i++)
{
inputBufferB_rearranged |= ((inputBufferB >> i) & 1) << (7 - i);
}
return inputBufferB_rearranged;
2023-12-27 16:15:11 +00:00
}
// Register a callback function to be called when a pin changes
2023-12-28 12:01:37 +00:00
void DigitalInputCard::registerCallback(std::function<void(uint8_t, bool)> callback)
2023-12-27 18:25:35 +00:00
{
2023-12-30 11:47:52 +00:00
ESP_LOGD("DigitalInputCard", "Registering callback");
2023-12-29 17:49:09 +00:00
callbacks.push_back(callback);
2023-12-30 11:47:52 +00:00
ESP_LOGD("DigitalInputCard", "Callback registered");
2023-12-27 16:15:11 +00:00
}
// Refresh the input buffer for bank A
2023-12-27 18:25:35 +00:00
void DigitalInputCard::refreshInputBankA()
{
2023-12-27 16:15:11 +00:00
inputBufferA = inputBankA.read8();
}
// Refresh the input buffer for bank B
2023-12-27 18:25:35 +00:00
void DigitalInputCard::refreshInputBankB()
{
2023-12-27 16:15:11 +00:00
inputBufferB = inputBankB.read8();
2023-12-27 18:25:35 +00:00
}
void DigitalInputCard::setDebounceTime(uint8_t pin, uint32_t debounceTime)
{
pin = pinMap[pin];
this->debounceTime[pin] = debounceTime;
}
2023-12-29 17:49:09 +00:00
// void DigitalInputCard::unregisterCallback(std::function<void(uint8_t, bool)> callback)
// {
// for (int i = 0; i < callbacks.size(); i++)
// {
// if (callbacks[i].target<void(uint8_t, bool)>() == callback.target<void(uint8_t, bool)>())
// {
// callbacks.erase(callbacks.begin() + i);
// break;
// }
// }
// }
2023-12-27 18:25:35 +00:00
void DigitalInputCard::loadPinMap(uint8_t pinMap[16])
{
for (int i = 0; i < 16; i++)
{
// Load the pin map (physical pin to virtual pin)
this->pinMap[i] = pinMap[i];
// Load the virtual pin map (virtual pin to physical pin)
this->virtualPinMap[pinMap[i]] = i;
}
2023-12-28 04:41:20 +00:00
}
uint8_t DigitalInputCard::getType()
{
return CARD_TYPE_DIGITAL_INPUT;
2023-12-27 16:15:11 +00:00
}