prepare for ESPMegaPRO OOP

This commit is contained in:
Siwat Sirichai 2023-12-28 01:25:35 +07:00
parent 51e9f5258a
commit fc692ef0b0
9 changed files with 266 additions and 71 deletions

View File

@ -1,4 +1,3 @@
#include <ESPMegaPRO.h>
#include <AnalogCard.hpp>
AnalogCard::AnalogCard() : dac0(DAC0_ADDRESS),

View File

@ -1,5 +1,5 @@
#pragma once
#include <ESPMegaPRO.h>
#include <ExpansionCard.hpp>
#include <Adafruit_ADS1X15.h>
#include <MCP4725.h>
@ -10,7 +10,7 @@
#define DAC2_ADDRESS 0x62
#define DAC3_ADDRESS 0x63
class AnalogCard {
class AnalogCard : public ExpansionCard {
public:
AnalogCard();
void dacWrite(uint8_t pin, uint16_t value);

View File

@ -1,96 +1,188 @@
#pragma once
#include <ESPMegaPRO.h>
#include <DigitalInputCard.hpp>
// Instantiate the card with the specified address
DigitalInputCard::DigitalInputCard(uint8_t address_a, uint8_t address_b) {
DigitalInputCard::DigitalInputCard(uint8_t address_a, uint8_t address_b)
{
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
DigitalInputCard::DigitalInputCard(bool bit0, bool bit1, bool bit2, bool bit3, bool bit4, bool bit5) {
DigitalInputCard::DigitalInputCard(bool bit0, bool bit1, bool bit2, bool bit3, bool bit4, bool bit5)
{
this->address_a = 0x20;
this->address_b = 0x20;
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;
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;
}
// Initialize the card
void DigitalInputCard::begin() {
void DigitalInputCard::begin()
{
this->inputBankA = PCF8574(this->address_a);
this->inputBankB = PCF8574(this->address_b);
this->inputBankA.begin();
this->inputBankB.begin();
// 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;
}
}
// Refresh and Read the input from the specified pin, always refresh the input buffers
uint8_t DigitalInputCard::digitalRead(uint8_t pin) {
digitalRead(pin, true);
bool DigitalInputCard::digitalRead(uint8_t pin)
{
return this->digitalRead(pin, true);
}
// Read the input from the specified pin, also refresh the input buffers if refresh is true
uint8_t DigitalInputCard::digitalRead(uint8_t pin, bool refresh) {
bool DigitalInputCard::digitalRead(uint8_t pin, bool refresh)
{
pin = pinMap[pin];
// First check if the pin is in bank A or B
if (pin >= 0 && pin <= 7) {
if (pin >= 0 && pin <= 7)
{
// Refresh the input buffers if refresh is true
if (refresh) refreshInputBankA();
if (refresh)
refreshInputBankA();
// Extract the bit from the buffer
return ((inputBufferA >> (7 - pin)) & 1);
} else if (pin >= 8 && pin <= 15) {
}
else if (pin >= 8 && pin <= 15)
{
// Refresh the input buffers if refresh is true
if (refresh) refreshInputBankB();
if (refresh)
refreshInputBankB();
// Extract the bit from the buffer
return ((inputBufferB >> (15 - pin)) & 1);
}
return 255;
}
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));
if (callback != NULL)
callback(virtualPin, ((currentBuffer >> (7 - pin)) & 1));
}
}
// 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));
if (callback != NULL)
callback(virtualPin, ((currentBuffer >> (15 - pin)) & 1));
}
}
}
// Preform a loop to refresh the input buffers
void DigitalInputCard::loop() {
// Store the current input buffers
uint8_t inputBufferA_old = inputBufferA;
uint8_t inputBufferB_old = inputBufferB;
void DigitalInputCard::loop()
{
// Refresh the input buffers
refreshInputBankA();
refreshInputBankB();
// Iterate over all pins and check if they changed
for (int i = 0; i < 16; i++) {
for (int i = 0; i < 16; i++)
{
// Check which bank the pin is in
if (i<8) {
// Check if the pin changed
if (((inputBufferA_old >> (7 - i)) & 1) != ((inputBufferA >> (7 - i)) & 1)) {
// Call the callback function if it is not null and pass the pin and the new value
if (callback != NULL) callback(i, ((inputBufferA >> (7 - i)) & 1));
}
} else {
// Check if the pin changed
if (((inputBufferB_old >> (15 - i)) & 1) != ((inputBufferB >> (15 - i)) & 1)) {
// Call the callback function if it is not null and pass the pin and the new value
if (callback != NULL) callback(i, ((inputBufferB >> (15 - i)) & 1));
}
if (i < 8)
{
handlePinChange(i, inputBufferA, previousInputBufferA);
}
else if (i >= 8 && i <= 15)
{
handlePinChange(i, inputBufferB, previousInputBufferB);
}
}
}
// Get the input buffer for bank A
uint8_t DigitalInputCard::getInputBufferA() {
return inputBufferA;
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;
}
// Get the input buffer for bank B
uint8_t DigitalInputCard::getInputBufferB() {
return inputBufferB;
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;
}
// Register a callback function to be called when a pin changes
void DigitalInputCard::registerCallback(void (*callback)(int, bool)) {
void DigitalInputCard::registerCallback(void (*callback)(uint8_t, bool))
{
this->callback = callback;
}
// Refresh the input buffer for bank A
void DigitalInputCard::refreshInputBankA() {
void DigitalInputCard::refreshInputBankA()
{
inputBufferA = inputBankA.read8();
}
// Refresh the input buffer for bank B
void DigitalInputCard::refreshInputBankB() {
void DigitalInputCard::refreshInputBankB()
{
inputBufferB = inputBankB.read8();
}
void DigitalInputCard::setDebounceTime(uint8_t pin, uint32_t debounceTime)
{
pin = pinMap[pin];
this->debounceTime[pin] = debounceTime;
}
void DigitalInputCard::unregisterCallback()
{
this->callback = NULL;
}
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;
}
}

View File

@ -1,8 +1,8 @@
#pragma once
#include <ESPMegaPRO.h>
#include <ExpansionCard.hpp>
#include <PCF8574.h>
class DigitalInputCard {
class DigitalInputCard : public ExpansionCard {
public:
// Instantiate the card with the specified address
DigitalInputCard(uint8_t address_a, uint8_t address_b);
@ -11,17 +11,23 @@ class DigitalInputCard {
// Initialize the card
void begin();
// Refresh and Read the input from the specified pin, always refresh the input buffers
uint8_t digitalRead(uint8_t pin);
bool digitalRead(uint8_t pin);
// Read the input from the specified pin, also refresh the input buffers if refresh is true
uint8_t digitalRead(uint8_t pin, bool refresh);
bool digitalRead(uint8_t pin, bool refresh);
// Preform a loop to refresh the input buffers
void loop();
// Get the input buffer for bank A
uint8_t getInputBufferA();
// Get the input buffer for bank B
uint8_t getInputBufferB();
// Set the debounce time for the specified pin
void setDebounceTime(uint8_t pin, uint32_t debounceTime);
// Register a callback function to be called when a pin changes
void registerCallback(void (*callback)(int, bool));
void registerCallback(void (*callback)(uint8_t, bool));
// Unregister the callback function
void unregisterCallback();
// Load a new pin map
void loadPinMap(uint8_t pinMap[16]);
private:
PCF8574 inputBankA;
PCF8574 inputBankB;
@ -29,7 +35,16 @@ class DigitalInputCard {
uint8_t address_b;
uint8_t inputBufferA;
uint8_t inputBufferB;
void (*callback)(int, bool);
uint8_t previousInputBufferA;
uint8_t previousInputBufferB;
uint32_t debounceTime[16];
uint32_t lastDebounceTime[16];
// A map of the physical pin to the virtual pin
uint8_t pinMap[16];
// A map of the virtual pin to the physical pin
uint8_t virtualPinMap[16];
void (*callback)(uint8_t, bool);
void refreshInputBankA();
void refreshInputBankB();
void handlePinChange(int pin, uint8_t& currentBuffer, uint8_t& previousBuffer);
};

View File

@ -1,7 +1,7 @@
#pragma once
#include <ESPMegaPRO.h>
#include <ExpansionCard.hpp>
#include <Adafruit_PWMServoDriver.h>
class DigitalOutputCard
class DigitalOutputCard : public ExpansionCard
{
public:
// Instantiate the card with the specified address

View File

@ -0,0 +1,43 @@
#pragma once
#include <ExpansionCard.hpp>
#include <DigitalInputCard.hpp>
#include <DigitalOutputCard.hpp>
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <PCF8574.h>
#include <FRAM.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <time.h>
struct rtctime_t {
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
uint8_t day;
uint8_t month;
uint16_t year;
};
#define FRAM_ADDRESS 0x56
#define INPUT_BANK_A_ADDRESS 0x21
#define INPUT_BANK_B_ADDRESS 0x22
#define PWM_BANK_ADDRESS 0x5F
#define RTC_ADDRESS 0x68
class ESPMegaPRO {
public:
ESPMegaPRO();
void begin();
void loop();
void installCard(uint8_t slot, ExpansionCard* card);
bool updateTimeFromNTP();
rtctime_t getTime();
FRAM fram;
private:
ExpansionCard* cards[255];
uint8_t cardCount = 0;
DigitalInputCard inputs = DigitalInputCard(INPUT_BANK_A_ADDRESS, INPUT_BANK_B_ADDRESS);
DigitalOutputCard outputs = DigitalOutputCard(PWM_BANK_ADDRESS);
};

View File

@ -0,0 +1,11 @@
#pragma once
#include <ESPMegaPRO.h>
class ExpansionCard {
public:
// Instantiate the card with the specified address
ExpansionCard() {}
virtual void begin() {}
// Preform a loop to refresh the input buffers
virtual void loop() {}
};

View File

@ -5,24 +5,19 @@
// This code demonstrates how to use the cards
uint8_t pinMap[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 14, 13, 12};
DigitalInputCard icard = DigitalInputCard(0x21, 0x22);
DigitalOutputCard ocard = DigitalOutputCard(0x5F);
AnalogCard acard = AnalogCard();
void setup() {
Serial.begin(115200);
// Instantiate Input Card
icard.begin();
// Instantiate Output Card
ocard.begin();
// Instantiate Analog Card
acard.begin();
// Set output 0 to 4095
ocard.analogWrite(0, 4095);
void inputCallback(uint8_t pin, bool state) {
Serial.print("Input ");
Serial.print(pin);
Serial.print(" changed to ");
Serial.println(state);
}
void loop() {
// put your main code here, to run repeatedly:
void printInputs() {
for (int i = 0; i < 16; i++) {
Serial.print("Input ");
Serial.print(i);
@ -30,9 +25,49 @@ void loop() {
Serial.print(icard.digitalRead(i));
Serial.println();
}
// Pad the output
Serial.println();
Serial.println();
// Delay for 1 second
delay(1000);
}
void setup() {
Serial.begin(115200);
Wire.begin(14, 33);
// Instantiate Input Card
Serial.println("Initializing Input Card");
icard.begin();
Serial.println("Initialized Input Card");
// Instantiate Output Card
Serial.println("Initializing Output Card");
ocard.begin();
Serial.println("Initialized Output Card");
icard.loadPinMap(pinMap);
// Read all the inputs and print them
printInputs();
// Turn on all the outputs
for (int i = 0; i < 16; i++) {
ocard.digitalWrite(i, true);
}
// Set the debounce time for all inputs to 200ms
for (int i = 0; i < 16; i++) {
icard.setDebounceTime(i, 200);
}
// Register the callback function
icard.registerCallback(inputCallback);
}
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // 1 second
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
printInputs();
}
icard.loop();
}