/* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * * This file is part of PortaPack. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifndef __GPIO_H__ #define __GPIO_H__ #include #include "ch.h" #include "hal.h" struct PinConfig { const uint32_t mode; const uint32_t pd; const uint32_t pu; const uint32_t fast; const uint32_t input; const uint32_t ifilt; constexpr operator uint16_t() const { return (((~ifilt) & 1) << 7) | ((input & 1) << 6) | ((fast & 1) << 5) | (((~pu) & 1) << 4) | ((pd & 1) << 3) | ((mode & 7) << 0); } /* constexpr operator uint32_t() { return scu::sfs::mode::value(mode) << scu::sfs::epd::value(pd) << scu::sfs::epun::value(~pu) << scu::sfs::ehs::value(fast) << scu::sfs::ezi::value(input) << scu::sfs::zif::value(~ifilt) ; } */ static constexpr PinConfig reset() { return {.mode = 0, .pd = 0, .pu = 1, .fast = 0, .input = 0, .ifilt = 1}; } static constexpr PinConfig floating( const uint32_t mode) { return { .mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 0, .ifilt = 1}; } static constexpr PinConfig floating_input( const uint32_t mode) { return { .mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 1, .ifilt = 1}; } static constexpr PinConfig floating_input_with_pull( const uint32_t pull_direction, const uint32_t mode) { return { .mode = mode, .pd = (pull_direction == 0) ? 1U : 0U, .pu = (pull_direction == 1) ? 1U : 0U, .fast = 0, .input = 1, .ifilt = 1}; } static constexpr PinConfig gpio_led(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 0, .ifilt = 1}; } static constexpr PinConfig gpio_inout_with_pull( const uint32_t mode, const uint32_t pull_direction) { return { .mode = mode, .pd = (pull_direction == 0) ? 1U : 0U, .pu = (pull_direction == 1) ? 1U : 0U, .fast = 0, .input = 1, .ifilt = 1}; } static constexpr PinConfig gpio_inout_with_pullup(const uint32_t mode) { return gpio_inout_with_pull(mode, 1); } static constexpr PinConfig gpio_inout_with_pulldown(const uint32_t mode) { return gpio_inout_with_pull(mode, 0); } static constexpr PinConfig gpio_out_with_pull( const uint32_t mode, const uint32_t pull_direction) { return { .mode = mode, .pd = (pull_direction == 0) ? 1U : 0U, .pu = (pull_direction == 1) ? 1U : 0U, .fast = 0, .input = 0, .ifilt = 1}; } static constexpr PinConfig gpio_out_with_pulldown(const uint32_t mode) { return gpio_out_with_pull(mode, 0); } static constexpr PinConfig gpio_out_with_pullup(const uint32_t mode) { return gpio_out_with_pull(mode, 1); } static constexpr PinConfig sgpio_in_fast(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 1, .ifilt = 0}; } static constexpr PinConfig sgpio_out_fast_with_pull( const uint32_t mode, const uint32_t pull_direction) { return { .mode = mode, .pd = (pull_direction == 0) ? 1U : 0U, .pu = (pull_direction == 1) ? 1U : 0U, .fast = 1, .input = 0, .ifilt = 1}; } static constexpr PinConfig sgpio_out_fast_with_pullup(const uint32_t mode) { return sgpio_out_fast_with_pull(mode, 1); } static constexpr PinConfig sgpio_inout_fast(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 1, .ifilt = 0}; } static constexpr PinConfig i2c(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 1, .ifilt = 1}; } static constexpr PinConfig spifi_sck(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 1, .ifilt = 0}; } static constexpr PinConfig spifi_inout(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 1, .ifilt = 0}; } static constexpr PinConfig spifi_cs(const uint32_t mode) { return {.mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 1, .ifilt = 0}; } }; struct Pin { // Pin() = delete; // Pin(const Pin&) = delete; // Pin(Pin&&) = delete; constexpr Pin( const uint8_t port, const uint8_t pad) : _pin_port{port}, _pin_pad{pad} { } void mode(const uint_fast16_t mode) const { LPC_SCU->SFSP[_pin_port][_pin_pad] = (LPC_SCU->SFSP[_pin_port][_pin_pad] & 0xfffffff8) | mode; } void configure(const PinConfig config) const { LPC_SCU->SFSP[_pin_port][_pin_pad] = config; } uint8_t _pin_port; uint8_t _pin_pad; }; struct GPIO { // GPIO() = delete; // GPIO(const GPIO& gpio) = delete; // GPIO(GPIO&&) = delete; constexpr GPIO( const Pin& pin, const ioportid_t gpio_port, const iopadid_t gpio_pad, const uint16_t gpio_mode) : _pin{pin}, _gpio_port{gpio_port}, _gpio_pad{gpio_pad}, _gpio_mode{gpio_mode} { } /* constexpr GPIO( const GPIO& gpio ) : _pin { gpio._pin }, _gpio_port { gpio._gpio_port }, _gpio_pad { gpio._gpio_pad }, _gpio_mode { gpio._gpio_mode } { } */ constexpr ioportid_t port() const { return _gpio_port; } constexpr iopadid_t pad() const { return _gpio_pad; } constexpr Pin pin() const { return _pin; } void configure() const { _pin.mode(_gpio_mode); } uint_fast16_t mode() const { return _gpio_mode; } void set() const { palSetPad(_gpio_port, _gpio_pad); } void clear() const { palClearPad(_gpio_port, _gpio_pad); } void toggle() const { palTogglePad(_gpio_port, _gpio_pad); } void output() const { palSetPadMode(_gpio_port, _gpio_pad, PAL_MODE_OUTPUT_PUSHPULL); } void input() const { palSetPadMode(_gpio_port, _gpio_pad, PAL_MODE_INPUT); } void write(const bool value) const { palWritePad(_gpio_port, _gpio_pad, value); } bool read() const { return palReadPad(_gpio_port, _gpio_pad); } bool operator!=(const GPIO& other) const { return (port() != other.port()) || (pad() != other.pad()); } const Pin _pin; const ioportid_t _gpio_port; const iopadid_t _gpio_pad; const uint16_t _gpio_mode; }; #endif /*__GPIO_H__*/