mirror of
https://github.com/Hopiu/rpi-rgb-led-matrix.git
synced 2026-03-16 22:10:27 +00:00
109 lines
3.4 KiB
C++
109 lines
3.4 KiB
C++
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
|
// Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
|
|
//
|
|
// 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 version 2.
|
|
//
|
|
// 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. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
|
|
|
#ifndef RPI_GPIO_H
|
|
#define RPI_GPIO_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <vector>
|
|
|
|
// Putting this in our namespace to not collide with other things called like
|
|
// this.
|
|
namespace rgb_matrix {
|
|
// For now, everything is initialized as output.
|
|
class GPIO {
|
|
public:
|
|
// Available bits that actually have pins.
|
|
static const uint32_t kValidBits;
|
|
|
|
GPIO();
|
|
|
|
// Initialize before use. Returns 'true' if successful, 'false' otherwise
|
|
// (e.g. due to a permission problem).
|
|
bool Init(int
|
|
#if RGB_SLOWDOWN_GPIO
|
|
slowdown = RGB_SLOWDOWN_GPIO
|
|
#else
|
|
slowdown = 1
|
|
#endif
|
|
);
|
|
|
|
// Initialize outputs.
|
|
// Returns the bits that are actually set.
|
|
uint32_t InitOutputs(uint32_t outputs);
|
|
|
|
// Set the bits that are '1' in the output. Leave the rest untouched.
|
|
inline void SetBits(uint32_t value) {
|
|
if (!value) return;
|
|
*gpio_set_bits_ = value;
|
|
for (int i = 0; i < slowdown_; ++i) {
|
|
*gpio_set_bits_ = value;
|
|
}
|
|
}
|
|
|
|
// Clear the bits that are '1' in the output. Leave the rest untouched.
|
|
inline void ClearBits(uint32_t value) {
|
|
if (!value) return;
|
|
*gpio_clr_bits_ = value;
|
|
for (int i = 0; i < slowdown_; ++i) {
|
|
*gpio_clr_bits_ = value;
|
|
}
|
|
}
|
|
|
|
// Write all the bits of "value" mentioned in "mask". Leave the rest untouched.
|
|
inline void WriteMaskedBits(uint32_t value, uint32_t mask) {
|
|
// Writing a word is two operations. The IO is actually pretty slow, so
|
|
// this should probably be unnoticable.
|
|
ClearBits(~value & mask);
|
|
SetBits(value & mask);
|
|
}
|
|
|
|
inline void Write(uint32_t value) { WriteMaskedBits(value, output_bits_); }
|
|
|
|
private:
|
|
uint32_t output_bits_;
|
|
int slowdown_;
|
|
volatile uint32_t *gpio_port_;
|
|
volatile uint32_t *gpio_set_bits_;
|
|
volatile uint32_t *gpio_clr_bits_;
|
|
};
|
|
|
|
// A PinPulser is a utility class that pulses a GPIO pin. There can be various
|
|
// implementations.
|
|
class PinPulser {
|
|
public:
|
|
// Factory for a PinPulser. Chooses the right implementation depending
|
|
// on the context (CPU and which pins are affected).
|
|
// "gpio_mask" is the mask that should be output (since we only
|
|
// need negative pulses, this is what it does)
|
|
// "nano_wait_spec" contains a list of time periods we'd like
|
|
// invoke later. This can be used to pre-process timings if needed.
|
|
static PinPulser *Create(GPIO *io, uint32_t gpio_mask,
|
|
bool allow_hardware_pulsing,
|
|
const std::vector<int> &nano_wait_spec);
|
|
|
|
virtual ~PinPulser() {}
|
|
|
|
// Send a pulse with a given length (index into nano_wait_spec array).
|
|
virtual void SendPulse(int time_spec_number) = 0;
|
|
|
|
// If SendPulse() is asynchronously implemented, wait for pulse to finish.
|
|
virtual void WaitPulseFinished() {}
|
|
};
|
|
|
|
} // end namespace rgb_matrix
|
|
|
|
#endif // RPI_GPIO_H
|