machines/components/pid-controller/firmware/common/PinGroup.h
2024-01-20 15:04:46 +01:00

470 lines
6.8 KiB
C++

#ifndef PIN_GROUP_H
#define PIN_GROUP_H
#include "Pin.h"
/**
Class for simultaneous operations on Arduino I/O pins
*/
class PinGroup
{
public:
template <size_t N>
PinGroup(Pin (&pins)[N])
{
_offset = pins[0].getOffset();
_PIN = pins[0].getPIN();
_PORT = pins[0].getPORT();
_DDR = pins[0].getDDR();
_numbers[0] = pins[0].getNumber();
_valid = true;
for (int i = 1; i < N; i++)
{
if (_DDR != pins[i].getDDR())
{
_valid = false;
}
_offset |= pins[i].getOffset();
_numbers[i] = pins[i].getNumber();
}
_ioffset = ~_offset;
}
// ################################# Operators #################################
/**
Compare the value of the pin
@param value the state of the pin (HIGH, LOW)
@return true if the value of all of the pins are equal to the value passed in, false otherwise
*/
bool operator==(uint8_t value)
{
uint8_t status = *_PIN;
if ((status & _offset) == _offset)
{
return (value == HIGH);
}
else if ((status | _ioffset) == _ioffset)
{
return (value == LOW);
}
else
{
return false;
}
}
/**
Compare the value of the pin
@param value the state of the pin (HIGH, LOW)
@return true if the value of all of the pins are not equal to the value passed in, false otherwise
*/
bool operator!=(uint8_t value)
{
uint8_t status = *_PIN;
if ((status & _offset) == _offset)
{
return (value == LOW);
}
else if ((status | _ioffset) == _ioffset)
{
return (value == HIGH);
}
else
{
return false;
}
}
/**
Set the pin state
@param state the state of the pin (HIGH, LOW)
*/
PinGroup &operator=(uint8_t state)
{
oldSREG = SREG;
cli();
if (state == LOW)
{
PORT_LOW;
}
else
{
PORT_HIGH;
}
SREG = oldSREG;
return *this;
}
// ################################# Getters #################################
/**
Get the pin numbers
@return array of pin numbers
*/
uint8_t *getNumbers()
{
return _numbers;
}
/**
Get the pin offset
@return pin offset
*/
uint8_t getOffset()
{
return _offset;
}
/**
Get the inverse pin offset
@return inverse pin offset
*/
uint8_t getInverseOffset()
{
return _ioffset;
}
/**
Get a pointer to the PIN register
@return pointer to the PIN register
*/
volatile uint8_t *getPIN()
{
return _PIN;
}
/**
Get a pointer to the PORT register
@return pointer to the PORT register
*/
volatile uint8_t *getPORT()
{
return _PORT;
}
/**
Get a pointer to the DDR register
@return pointer to the DDR register
*/
volatile uint8_t *getDDR()
{
return _DDR;
}
/**
Get the mode of the pin from the DDR register
@return mode of the pin (OUTPUT, INPUT, -1)
*/
uint8_t getMode()
{
uint8_t status = *_DDR;
if ((status & _offset) == _offset)
{
return OUTPUT;
}
else if ((status | _ioffset) == _ioffset)
{
return INPUT;
}
else
{
return -1;
}
}
/**
Get the state of the pin from the PORT register
@return state of the pin (HIGH, LOW, -1)
*/
uint8_t getState()
{
uint8_t status = *_PORT;
if ((status & _offset) == _offset)
{
return HIGH;
}
else if ((status | _ioffset) == _ioffset)
{
return LOW;
}
else
{
return -1;
}
}
/**
Get the value of the pin from the PIN register
@return value of the pin (HIGH, LOW, -1)
*/
uint8_t getValue()
{
uint8_t status = *_PIN;
if ((status & _offset) == _offset)
{
return HIGH;
}
else if ((status | _ioffset) == _ioffset)
{
return LOW;
}
else
{
return -1;
}
}
/**
Check the group to ensure all pins use the same registers
@return true if the pins in the group all use the same registers, false otherwise
*/
bool isValid()
{
return _valid;
}
// ################################# Setters #################################
// #################### Generic ####################
/**
Set the pin mode and pin state
@param mode the mode of the pin (OUTPUT, INPUT)
@param state the state of the pin (HIGH, LOW)
*/
void set(uint8_t mode, uint8_t state)
{
oldSREG = SREG;
cli();
if (mode == INPUT)
{
DDR_LOW;
}
else
{
DDR_HIGH;
}
if (state == LOW)
{
PORT_LOW;
}
else
{
PORT_HIGH;
}
SREG = oldSREG;
}
/**
Set the pin mode
@param mode the mode of the pin (OUTPUT, INPUT)
*/
void setMode(uint8_t mode)
{
oldSREG = SREG;
cli();
if (mode == INPUT)
{
DDR_LOW;
}
else
{
DDR_HIGH;
}
SREG = oldSREG;
}
/**
Set the pin state
@param state the state of the pin (HIGH, LOW)
*/
void setState(uint8_t state)
{
oldSREG = SREG;
cli();
if (state == LOW)
{
PORT_LOW;
}
else
{
PORT_HIGH;
}
SREG = oldSREG;
}
// #################### Input ####################
/**
Set the pin mode to input
*/
void setInput()
{
oldSREG = SREG;
cli();
DDR_LOW;
SREG = oldSREG;
}
/**
Set the pin pullup resistor to on
*/
void setPullupOn()
{
oldSREG = SREG;
cli();
PORT_HIGH;
SREG = oldSREG;
}
/**
Set the pin pullup resistor to off
*/
void setPullupOff()
{
oldSREG = SREG;
cli();
PORT_LOW;
SREG = oldSREG;
}
/**
Set the pin mode to input and the pin pullup resistor to on
*/
void setInputPullupOn()
{
oldSREG = SREG;
cli();
DDR_LOW;
PORT_HIGH;
SREG = oldSREG;
}
/**
Set the pin mode to input and the pin pullup resistor to off
*/
void setInputPullupOff()
{
oldSREG = SREG;
cli();
DDR_LOW;
PORT_LOW;
SREG = oldSREG;
}
// #################### Output ####################
/**
Set the pin mode to output
*/
void setOutput()
{
oldSREG = SREG;
cli();
DDR_HIGH;
SREG = oldSREG;
}
/**
Set the pin output to HIGH
*/
void setHigh()
{
oldSREG = SREG;
cli();
PORT_HIGH;
SREG = oldSREG;
}
/**
Set the pin output to LOW
*/
void setLow()
{
oldSREG = SREG;
cli();
PORT_LOW;
SREG = oldSREG;
}
/**
Set the pin mode to output and the pin output to HIGH
*/
void setOutputHigh()
{
oldSREG = SREG;
cli();
DDR_HIGH;
PORT_HIGH;
SREG = oldSREG;
}
/**
Set the pin mode to output and the pin output to LOW
*/
void setOutputLow()
{
oldSREG = SREG;
cli();
DDR_HIGH;
PORT_LOW;
SREG = oldSREG;
}
// ################################# Utilities #################################
// #################### Toggle ####################
/**
Toggle the pin mode (OUTPUT -> INPUT, INPUT -> OUTPUT)
*/
void toggleMode()
{
oldSREG = SREG;
cli();
DDR_TOGGLE;
SREG = oldSREG;
}
/**
Toggle the pin state (HIGH -> LOW, LOW -> HIGH)
*/
void toggleState()
{
oldSREG = SREG;
cli();
PORT_TOGGLE;
SREG = oldSREG;
}
private:
uint8_t _numbers[8];
uint8_t _offset;
uint8_t _ioffset;
bool _valid;
uint8_t oldSREG;
volatile uint8_t *_PIN;
volatile uint8_t *_PORT;
volatile uint8_t *_DDR;
};