@@ -0,0 +1,512 @@
|
||||
#ifndef PIN_H
|
||||
#define PIN_H
|
||||
|
||||
// this class doesn't outperform fastgpio but is works with AtmelMega
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define DDR_HIGH (*_DDR |= _offset) ///< Set the DDR register to HIGH for the pin
|
||||
#define DDR_TOGGLE (*_DDR ^= _offset) ///< Set the DDR register to the inverse for the pin
|
||||
#define DDR_LOW (*_DDR &= _ioffset) ///< Set the DDR register to LOW for the pin
|
||||
|
||||
#define PORT_HIGH (*_PORT |= _offset) ///< Set the PORT register to HIGH for the pin
|
||||
#define PORT_TOGGLE (*_PORT ^= _offset) ///< Set the PORT register to the inverse for the pin
|
||||
#define PORT_LOW (*_PORT &= _ioffset) ///< Set the PORT register to LOW for the pin
|
||||
|
||||
#define DDR_ON (*_DDR & _offset) ///< Get the DDR register for the pin (HIGH, LOW) with other pins forced to 0
|
||||
#define DDR_OFF (*_DDR | _ioffset) ///< Get the DDR register for the pin (HIGH, LOW) with other pins forced to 1
|
||||
|
||||
#define PORT_ON (*_PORT & _offset) ///< Get the PORT register for the pin (HIGH, LOW) with other pins forced to 0
|
||||
#define PORT_OFF (*_PORT | _ioffset) ///< Get the PORT register for the pin (HIGH, LOW) with other pins forced to 1
|
||||
|
||||
#define PIN_ON (*_PIN & _offset) ///< Get the PIN register for the pin (HIGH, LOW) with other pins forced to 0
|
||||
#define PIN_OFF (*_PIN | _ioffset) ///< Get the PIN register for the pin (HIGH, LOW) with other pins forced to 1
|
||||
|
||||
class Pin
|
||||
{
|
||||
public:
|
||||
Pin(uint8_t number)
|
||||
{
|
||||
_number = number;
|
||||
_offset = digitalPinToBitMask(_number);
|
||||
_ioffset = ~_offset;
|
||||
_timer = digitalPinToTimer(_number);
|
||||
_PIN = portInputRegister(digitalPinToPort(_number));
|
||||
_PORT = portOutputRegister(digitalPinToPort(_number));
|
||||
_DDR = portModeRegister(digitalPinToPort(_number));
|
||||
}
|
||||
|
||||
/**
|
||||
Custom board constructor
|
||||
|
||||
getAnalogValue() and setDutyCycle(int value) not supported
|
||||
|
||||
@param number pin number written on board
|
||||
@param offset bit mask used to access pin in registers
|
||||
@param timer timer for pin
|
||||
@param PIN input register for pin
|
||||
@param PORT data register for pin
|
||||
@param DDR data direction register for pin
|
||||
*/
|
||||
Pin(uint8_t number, uint8_t offset, uint8_t timer, volatile uint8_t *PIN, volatile uint8_t *PORT, volatile uint8_t *DDR)
|
||||
{
|
||||
_number = number;
|
||||
_offset = offset;
|
||||
_ioffset = ~_offset;
|
||||
_timer = timer;
|
||||
_PIN = PIN;
|
||||
_PORT = PORT;
|
||||
_DDR = DDR;
|
||||
}
|
||||
|
||||
// ################################# Operators #################################
|
||||
|
||||
/**
|
||||
Get the value of the pin from the PIN register
|
||||
|
||||
@return true if the value of the pin is HIGH, false otherwise
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return bool(PIN_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin state
|
||||
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
Pin &operator=(uint8_t state)
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ################################# Getters #################################
|
||||
|
||||
/**
|
||||
Get the pin number
|
||||
|
||||
@return pin number
|
||||
*/
|
||||
uint8_t getNumber()
|
||||
{
|
||||
return _number;
|
||||
}
|
||||
|
||||
/**
|
||||
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 the pin timer
|
||||
|
||||
@return pin timer
|
||||
*/
|
||||
uint8_t getTimer()
|
||||
{
|
||||
return _timer;
|
||||
}
|
||||
|
||||
/**
|
||||
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)
|
||||
*/
|
||||
uint8_t getMode()
|
||||
{
|
||||
if (DDR_ON)
|
||||
{
|
||||
return OUTPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the state of the pin from the PORT register
|
||||
|
||||
@return state of the pin (HIGH, LOW)
|
||||
*/
|
||||
uint8_t getState()
|
||||
{
|
||||
if (PORT_ON)
|
||||
{
|
||||
return HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the value of the pin from the PIN register
|
||||
|
||||
@return value of the pin (HIGH, LOW)
|
||||
*/
|
||||
uint8_t getValue()
|
||||
{
|
||||
if (PIN_ON)
|
||||
{
|
||||
return HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the analog value of the pin
|
||||
|
||||
@return analog value of the pin (0-1023)
|
||||
*/
|
||||
uint16_t getAnalogValue()
|
||||
{
|
||||
return analogRead(_number);
|
||||
}
|
||||
|
||||
/**
|
||||
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)
|
||||
{
|
||||
uint8_t 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)
|
||||
{
|
||||
uint8_t 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)
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### Input ####################
|
||||
|
||||
void setInput()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin pullup resistor to on
|
||||
*/
|
||||
void setPullupOn()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin pullup resistor to off
|
||||
*/
|
||||
void setPullupOff()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to input and the pin pullup resistor to on
|
||||
*/
|
||||
void setInputPullupOn()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to input and the pin pullup resistor to off
|
||||
*/
|
||||
void setInputPullupOff()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### Output ####################
|
||||
|
||||
/**
|
||||
Set the pin mode to output
|
||||
*/
|
||||
void setOutput()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin output to HIGH
|
||||
*/
|
||||
void setHigh()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin output to LOW
|
||||
*/
|
||||
void setLow()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to output and the pin output to HIGH
|
||||
*/
|
||||
void setOutputHigh()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to output and the pin output to LOW
|
||||
*/
|
||||
void setOutputLow()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the PWM duty cycle
|
||||
|
||||
@param value the duty cycle (0-255)
|
||||
*/
|
||||
void setDutyCycle(int value)
|
||||
{
|
||||
analogWrite(_number, value);
|
||||
}
|
||||
|
||||
// ################################# Utilities #################################
|
||||
|
||||
/**
|
||||
Toggle the pin mode (OUTPUT -> INPUT, INPUT -> OUTPUT)
|
||||
*/
|
||||
void toggleMode()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_TOGGLE;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Toggle the pin state (HIGH -> LOW, LOW -> HIGH)
|
||||
*/
|
||||
void toggleState()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_TOGGLE;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### RC Timer ####################
|
||||
|
||||
/**
|
||||
Set the pin mode to input and decrement a counter until the pin goes HIGH or the counter reaches 0 then set the pin mode to output and return the counter value
|
||||
|
||||
@param count the initial value for the counter to start at (0-65535)
|
||||
|
||||
@return the value remaining on the counter when the pin state went to HIGH or 0 if the counter reached 0
|
||||
*/
|
||||
volatile unsigned int rcTimer(volatile unsigned int count)
|
||||
{
|
||||
uint8_t status;
|
||||
asm volatile(
|
||||
// Save interupt status and disable interupts
|
||||
"in %[status], __SREG__ \n\t" // Store current interupt status in variable 's'
|
||||
"cli \n\t" // Disable interupts
|
||||
|
||||
// Set Pin to input mode to start charging capacitor
|
||||
"ld __tmp_reg__, %a[_DDR] \n\t" // Load the DDR register into r0 (__tmp_reg__)
|
||||
"and __tmp_reg__, %[_ioffset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
|
||||
"st %a[_DDR], __tmp_reg__ \n\t" // Store r0 (__tmp_reg__) in the DDR register
|
||||
|
||||
// Count time before Pin becomes high
|
||||
"loop%=: \n\t" // Label for looping
|
||||
//"ld __tmp_reg__,%a[_PIN] \n\t" // Load the PIN register into r0 (__tmp_reg__)
|
||||
"and __tmp_reg__, %[_offset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
|
||||
"brne end%= \n\t" // End the loop if r0 (__tmp_reg__) is not equal to zero by branching to label 'end'
|
||||
"dec %[count] \n\t" // Decrement the value of 'count' by one
|
||||
"brne loop%= \n\t" // If the value of 'count' is not equal to zero continue the loop by branching to label 'loop'
|
||||
|
||||
// Done counting
|
||||
"end%=: \n\t" // Label for ending loop
|
||||
// Set Pin to output mode to start discharging capacitor
|
||||
"ld __tmp_reg__, %a[_DDR] \n\t" // Load the DDR register into r0 (__tmp_reg__)
|
||||
"or __tmp_reg__, %[_offset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
|
||||
"st %a[_DDR], __tmp_reg__ \n\t" // Store r0 (__tmp_reg__) in the PORT register
|
||||
|
||||
// Restore interupt status
|
||||
"out __SREG__, %[status] \n\t" // Load interupt status from variable 's'
|
||||
|
||||
// Outputs
|
||||
:
|
||||
[ count ] "+r"(count), // The value the counter was at when the pin went high
|
||||
[ status ] "=&r"(status) // The interupt status
|
||||
|
||||
// Inputs
|
||||
:
|
||||
[ _DDR ] "e"(_DDR), // The address of the DDR register for the pin
|
||||
[ _PIN ] "e"(_PIN), // The address of the PIN register for the pin
|
||||
[ _offset ] "r"(_offset), // The bit mask used to access pin in registers
|
||||
[ _ioffset ] "r"(_ioffset) // The inverse bit mask used to access pin in registers
|
||||
);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _number;
|
||||
uint8_t _offset;
|
||||
uint8_t _ioffset;
|
||||
uint8_t _timer;
|
||||
volatile uint8_t *_PIN;
|
||||
volatile uint8_t *_PORT;
|
||||
volatile uint8_t *_DDR;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,469 @@
|
||||
#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;
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef MACROS_H
|
||||
#define MACROS_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// Macros for adding
|
||||
#define INC_0 1
|
||||
#define INC_1 2
|
||||
#define INC_2 3
|
||||
#define INC_3 4
|
||||
#define INC_4 5
|
||||
#define INC_5 6
|
||||
#define INC_6 7
|
||||
#define INC_7 8
|
||||
#define INC_8 9
|
||||
#define INCREMENT_(n) INC_ ##n
|
||||
#define INCREMENT(n) INCREMENT_(n)
|
||||
|
||||
// Macros for subtracting
|
||||
#define DEC_1 0
|
||||
#define DEC_2 1
|
||||
#define DEC_3 2
|
||||
#define DEC_4 3
|
||||
#define DEC_5 4
|
||||
#define DEC_6 5
|
||||
#define DEC_7 6
|
||||
#define DEC_8 7
|
||||
#define DEC_9 8
|
||||
#define DECREMENT_(n) DEC_ ##n
|
||||
#define DECREMENT(n) DECREMENT_(n)
|
||||
|
||||
// compiler - & C quirks
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#define _UNUSED __attribute__((unused))
|
||||
|
||||
// fallback noop
|
||||
#define NOOP do{} while(0)
|
||||
|
||||
//Option testing
|
||||
#define _CAT(a, ...) a ## __VA_ARGS__
|
||||
#define SWITCH_ENABLED_ 1
|
||||
#define ENABLED(b) _CAT(SWITCH_ENABLED_, b)
|
||||
|
||||
// time
|
||||
#define PENDING(NOW,SOON) ((long)(NOW-(SOON))<0)
|
||||
#define ELAPSED(NOW,SOON) (!PENDING(NOW,SOON))
|
||||
|
||||
#define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
|
||||
#define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
|
||||
#define HOUR_MS ((millis_t)1000 * (millis_t)(60 * 60))
|
||||
#define MIN_MS ((millis_t)1000 * (millis_t)(60))
|
||||
#define SECS ((millis_t)1000)
|
||||
|
||||
// bit masks
|
||||
#undef _BV
|
||||
#define _BV(b) (1 << (b))
|
||||
#define TEST(n,b) !!((n)&_BV(b))
|
||||
#define SBI(n,b) (n |= _BV(b))
|
||||
#define CBI(n,b) (n &= ~_BV(b))
|
||||
#define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
|
||||
|
||||
#define _BV32(b) (1UL << (b))
|
||||
#define TEST32(n,b) !!((n)&_BV32(b))
|
||||
#define SBI32(n,b) (n |= _BV32(b))
|
||||
#define CBI32(n,b) (n &= ~_BV32(b))
|
||||
#define SIGN(a) ((a>0)-(a<0))
|
||||
|
||||
// math basics
|
||||
|
||||
#define WITHIN(V,L,H) ((V) >= (L) && (V) <= (H))
|
||||
#define NUMERIC(a) WITHIN(a, '0', '9')
|
||||
#define DECIMAL(a) (NUMERIC(a) || a == '.')
|
||||
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+')
|
||||
#define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
|
||||
#define COUNT(a) (sizeof(a)/sizeof(*a))
|
||||
#define ZERO(a) memset(a,0,sizeof(a))
|
||||
#define COPY(a,b) memcpy(a,b,MIN(sizeof(a),sizeof(b)))
|
||||
|
||||
|
||||
// #define M_PI 3.14159265358979323846f
|
||||
#define RADIANS(d) ((d)*M_PI/180.0f)
|
||||
#define DEGREES(r) ((r)*180.0f/M_PI)
|
||||
#define CEILING(x,y) (((x) + (y) - 1) / (y))
|
||||
|
||||
// Macros for initializing arrays
|
||||
#define ARRAY_6(v1, v2, v3, v4, v5, v6, ...) { v1, v2, v3, v4, v5, v6 }
|
||||
#define ARRAY_5(v1, v2, v3, v4, v5, ...) { v1, v2, v3, v4, v5 }
|
||||
#define ARRAY_4(v1, v2, v3, v4, ...) { v1, v2, v3, v4 }
|
||||
#define ARRAY_3(v1, v2, v3, ...) { v1, v2, v3 }
|
||||
#define ARRAY_2(v1, v2, ...) { v1, v2 }
|
||||
#define ARRAY_1(v1, ...) { v1 }
|
||||
|
||||
#define _ARRAY_N(N, ...) ARRAY_ ##N(__VA_ARGS__)
|
||||
#define ARRAY_N(N, ...) _ARRAY_N(N, __VA_ARGS__)
|
||||
|
||||
#define SPACE(A) " " << A << " "
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef PPMATH_H
|
||||
#define PPMATH_H
|
||||
|
||||
template <typename T>
|
||||
T clamp(const T &value, const T &low, const T &high)
|
||||
{
|
||||
return value < low ? low : (value > high ? high : value);
|
||||
}
|
||||
|
||||
#define RANGE(i, min, max) ((i > min) && (i < max)) ? true : false
|
||||
|
||||
#define NCLAMP(x, min, max) (x - min) / (max - min)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
#ifndef TIMER_MAX_TASKS
|
||||
#define TIMER_MAX_TASKS 0x10
|
||||
#endif
|
||||
|
||||
template <
|
||||
size_t max_tasks = TIMER_MAX_TASKS, /* max allocated tasks */
|
||||
unsigned long (*time_func)() = millis /* time function for timer */
|
||||
>
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
typedef bool (*handler_t)(void *opaque); /* task handler func signature */
|
||||
/* Calls handler with opaque as argument in delay units of time */
|
||||
bool
|
||||
in(unsigned long delay, handler_t h, void *opaque = NULL)
|
||||
{
|
||||
return add_task(time_func(), delay, h, opaque);
|
||||
}
|
||||
|
||||
/* Calls handler with opaque as argument at time */
|
||||
bool
|
||||
at(unsigned long time, handler_t h, void *opaque = NULL)
|
||||
{
|
||||
const unsigned long now = time_func();
|
||||
return add_task(now, time - now, h, opaque);
|
||||
}
|
||||
|
||||
/* Calls handler with opaque as argument every interval units of time */
|
||||
bool
|
||||
every(unsigned long interval, handler_t h, void *opaque = NULL)
|
||||
{
|
||||
return add_task(time_func(), interval, h, opaque, interval);
|
||||
}
|
||||
|
||||
|
||||
/* Ticks the timer forward - call this function in loop() */
|
||||
void
|
||||
tick()
|
||||
{
|
||||
tick(time_func());
|
||||
}
|
||||
|
||||
/* Ticks the timer forward - call this function in loop() */
|
||||
inline void
|
||||
tick(unsigned long t)
|
||||
{
|
||||
for (size_t i = 0; i < max_tasks; ++i)
|
||||
{
|
||||
struct task *const task = &tasks[i];
|
||||
const unsigned long duration = t - task->start;
|
||||
|
||||
if (task->handler && duration >= task->expires)
|
||||
{
|
||||
task->repeat = task->handler(task->opaque) && task->repeat;
|
||||
|
||||
if (task->repeat)
|
||||
task->start = t;
|
||||
else
|
||||
remove(task);
|
||||
}else{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct task
|
||||
{
|
||||
handler_t handler; /* task handler callback func */
|
||||
void *opaque; /* argument given to the callback handler */
|
||||
unsigned long start,
|
||||
expires, /* when the task expires */
|
||||
repeat; /* repeat task */
|
||||
} tasks[max_tasks];
|
||||
|
||||
inline void
|
||||
remove(struct task *task)
|
||||
{
|
||||
task->handler = NULL;
|
||||
task->opaque = NULL;
|
||||
task->start = 0;
|
||||
task->expires = 0;
|
||||
task->repeat = 0;
|
||||
}
|
||||
|
||||
inline struct task *
|
||||
next_task_slot()
|
||||
{
|
||||
for (size_t i = 0; i < max_tasks; ++i)
|
||||
{
|
||||
struct task *const slot = &tasks[i];
|
||||
if (slot->handler == NULL)
|
||||
return slot;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline struct task *
|
||||
add_task(unsigned long start, unsigned long expires,
|
||||
handler_t h, void *opaque, bool repeat = 0)
|
||||
{
|
||||
struct task *const slot = next_task_slot();
|
||||
|
||||
if (!slot){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slot->handler = h;
|
||||
slot->opaque = opaque;
|
||||
slot->start = start;
|
||||
slot->expires = expires;
|
||||
slot->repeat = repeat;
|
||||
|
||||
return slot;
|
||||
}
|
||||
};
|
||||
|
||||
/* create a timer with the default settings */
|
||||
inline Timer<>
|
||||
timer_create_default()
|
||||
{
|
||||
return Timer<>();
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user