115 lines
2.9 KiB
C++
115 lines
2.9 KiB
C++
/*
|
|
* DigitalIoPin.cpp
|
|
*
|
|
* Created on: Aug 29, 2022
|
|
* Author: Vasily Davydov
|
|
*/
|
|
|
|
#include "DigitalIoPin.h"
|
|
|
|
DigitalIoPin::DigitalIoPin (int port, int pin, bool input, bool pullup,
|
|
bool invert, bool isr, IRQn_Type isr_index)
|
|
{
|
|
assert ((port <= UINT8_MAX_VALUE) && (pin <= UINT8_MAX_VALUE));
|
|
_io._port = (uint8_t)port;
|
|
_io._pin = (uint8_t)pin;
|
|
_io._input = input;
|
|
_io._pullup = pullup;
|
|
_io._invert = invert;
|
|
_io.IOCON_mode = IOCON_MODE_INACT;
|
|
_io.IOCON_inv = IOCON_FUNC0;
|
|
if (isr){
|
|
_io.isr_i = isr_index;
|
|
setIsr();
|
|
} else {
|
|
setIoPin ();
|
|
}
|
|
}
|
|
|
|
DigitalIoPin::~DigitalIoPin ()
|
|
{
|
|
}
|
|
|
|
void
|
|
DigitalIoPin::setIoPin ()
|
|
{
|
|
bool direction = true;
|
|
if (_io._input)
|
|
{
|
|
direction = false;
|
|
_io.IOCON_mode = IOCON_MODE_PULLUP;
|
|
if (!_io._pullup)
|
|
{
|
|
_io.IOCON_mode = IOCON_MODE_PULLDOWN;
|
|
}
|
|
if (_io._invert)
|
|
{
|
|
_io.IOCON_inv = IOCON_INV_EN;
|
|
}
|
|
}
|
|
Chip_IOCON_PinMuxSet (LPC_IOCON, _io._port, _io._pin,
|
|
(_io.IOCON_mode | _io.DigitalEn | _io.IOCON_inv));
|
|
/** False direction equals input */
|
|
Chip_GPIO_SetPinDIR (LPC_GPIO, _io._port, _io._pin, direction);
|
|
}
|
|
|
|
void
|
|
DigitalIoPin::setIsr ()
|
|
{
|
|
bool direction = true;
|
|
if (_io._input)
|
|
{
|
|
direction = false;
|
|
_io.IOCON_mode = IOCON_MODE_PULLUP;
|
|
if (!_io._pullup)
|
|
{
|
|
_io.IOCON_mode = IOCON_MODE_PULLDOWN;
|
|
}
|
|
if (_io._invert)
|
|
{
|
|
_io.IOCON_inv = IOCON_INV_EN;
|
|
}
|
|
}
|
|
/* We'll use an optional IOCON filter (0) with a divider of 64 for the
|
|
input pin to be used for PININT */
|
|
Chip_Clock_SetIOCONFiltClockDiv(0, 64);
|
|
|
|
Chip_IOCON_PinMuxSet (LPC_IOCON, _io._port, _io._pin,
|
|
(_io.IOCON_mode | _io.DigitalEn
|
|
| _io.IOCON_inv | IOCON_CLKDIV(0)
|
|
| IOCON_S_MODE(3)));
|
|
/** False direction equals input */
|
|
Chip_GPIO_SetPinDIR (LPC_GPIO, _io._port, _io._pin, direction);
|
|
|
|
/* Enable PININT clock if it was not enabled before */
|
|
if ((LPC_SYSCTL->SYSAHBCLKCTRL & (1 << SYSCTL_CLOCK_PINT)) == 0)
|
|
{
|
|
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_PINT);
|
|
}
|
|
/* Configure interrupt channel for the GPIO pin in SysCon block */
|
|
Chip_SYSCTL_SetPinInterrupt(_io.isr_i, _io._port, _io._pin);
|
|
|
|
/* Configure channel interrupt as edge sensitive and falling edge interrupt */
|
|
Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(_io.isr_i));
|
|
Chip_PININT_SetPinModeEdge(LPC_PININT, PININTCH(_io.isr_i));
|
|
Chip_PININT_EnableIntLow(LPC_PININT, PININTCH(_io.isr_i));
|
|
|
|
/* Enable interrupt in the NVIC */
|
|
NVIC_ClearPendingIRQ(_io.isr_i);
|
|
NVIC_EnableIRQ(_io.isr_i);
|
|
}
|
|
|
|
bool
|
|
DigitalIoPin::read ()
|
|
{
|
|
bool state = (Chip_GPIO_GetPinState (LPC_GPIO, _io._port, _io._pin));
|
|
return (_io._invert && !_io._input) ? !state : state;
|
|
}
|
|
|
|
void
|
|
DigitalIoPin::write (bool value)
|
|
{
|
|
assert (!(_io._input));
|
|
Chip_GPIO_SetPinState (LPC_GPIO, _io._port, _io._pin, ((_io._invert) ? !value : value));
|
|
}
|