Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
SN74HC595GPO.hxx
Go to the documentation of this file.
1
36#ifndef _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
37#define _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
38
39#include <atomic>
40#include <cstddef>
41#include <cstdint>
42#include <fcntl.h>
43#include <unistd.h>
44
45#include "SPI.hxx"
46
47#include "os/Gpio.hxx"
48#include "os/OS.hxx"
49
50template <uint8_t N = 1> class SN74HC595GPO;
51
58template <uint8_t N = 1> class SN74HC595 : public OSThread
59{
60public:
67 SN74HC595(void (*request_refresh_operation)(void))
68 : requestRefreshOperation_(request_refresh_operation)
69 , spiFd_(-1)
70 , sem_()
71 , ioPending_(false)
72 {
73 HASSERT(N > 0);
74 for (unsigned i = 0; i < N; ++i)
75 {
76 gpoData_[i] = 0;
77 }
78 }
79
84 void init(const char *spi_name, int priority = get_priority_max())
85 {
86 spiFd_ = ::open(spi_name, O_WRONLY);
87 HASSERT(spiFd_ >= 0);
88
89 // configure SPI bus settings
90 uint8_t spi_mode = SPI_MODE_0;
91 uint8_t spi_bpw = 8;
92 uint32_t spi_max_speed_hz = SPI_MAX_SPEED_HZ;
93 ::ioctl(spiFd_, SPI_IOC_WR_MODE, &spi_mode);
94 ::ioctl(spiFd_, SPI_IOC_WR_BITS_PER_WORD, &spi_bpw);
95 ::ioctl(spiFd_, SPI_IOC_WR_MAX_SPEED_HZ, &spi_max_speed_hz);
96
98
99 // start the thread at the highest priority in the system
100 start("SN74HC595", priority, 384 + N);
101 }
102
105 void refresh(bool from_isr = false)
106 {
107 if (!ioPending_)
108 {
109 ioPending_ = true;
110 if (from_isr)
111 {
112 int woken;
113 sem_.post_from_isr(&woken);
114 }
115 else
116 {
117 sem_.post();
118 }
119 }
120 }
121
122private:
124 static constexpr uint32_t SPI_MAX_SPEED_HZ = 4000000;
125
128 void *entry() override
129 {
130 for ( ; /* forever */ ; )
131 {
132 sem_.wait();
133 if (ioPending_)
134 {
135 ioPending_ = false;
136 uint8_t data[N];
137 for (unsigned i = 0; i < N; ++i)
138 {
139 data[i] = gpoData_[i];
140 }
141 ::write(spiFd_, data, N);
142 }
143 }
144 }
145
148
149 int spiFd_;
151 uint8_t ioPending_ : 1;
152
154 std::atomic<uint8_t> gpoData_[N];
155
157 friend class SN74HC595GPO<N>;
158
160};
161
164template <uint8_t N> class SN74HC595GPO : public Gpio
165{
166public:
171 constexpr SN74HC595GPO(SN74HC595<N> *instance, uint8_t chip_index, uint8_t bit)
172 : Gpio()
173 , instance_(instance)
174 , chipIndex_(chip_index)
175 , bit_(bit)
176 {
177#ifndef __PIC32MX__
178 HASSERT(bit < 8);
179 HASSERT(chip_index < sizeof(instance->gpoData_));
180 HASSERT(N == sizeof(instance->gpoData_));
181#endif
182 }
183
186 void write(Value new_state) const override
187 {
188 new_state ? set() : clr();
189 }
190
193 Value read() const override
194 {
195 return instance_->gpoData_[chipIndex_] & (0x1 << bit_) ?
196 Gpio::SET : Gpio::CLR;
197 }
198
200 void set() const override
201 {
202 if (!(instance_->gpoData_[chipIndex_] & (0x1 << bit_)))
203 {
204 instance_->gpoData_[chipIndex_] |= 0x1 << bit_;
206 }
207 }
208
210 void clr() const override
211 {
212 if ((instance_->gpoData_[chipIndex_] & (0x1 << bit_)))
213 {
214 instance_->gpoData_[chipIndex_] &= ~(0x1 << bit_);
216 }
217 }
218
221 void set_direction(Gpio::Direction dir) const override
222 {
223 HASSERT(dir == Gpio::Direction::DOUTPUT);
224 }
225
228 Direction direction() const override
229 {
230 return Gpio::Direction::DOUTPUT;
231 }
232
233private:
236
238 const uint8_t chipIndex_;
239
241 const uint8_t bit_;
242
244};
245
246#endif // _FREERTOS_DRIVERS_COMMON_SN74HC595GPO_HXX_
int ioctl(int fd, unsigned long int key,...)
Request and ioctl transaction.
Definition Fileio.cxx:452
OS-independent abstraction for GPIO.
Definition Gpio.hxx:43
Value
Defines the options for GPIO level.
Definition Gpio.hxx:62
Direction
Defines the options for GPIO direction.
Definition Gpio.hxx:73
This class provides a counting semaphore API.
Definition OS.hxx:243
void post()
Post (increment) a semaphore.
Definition OS.hxx:260
void wait()
Wait on (decrement) a semaphore.
Definition OS.hxx:279
This class provides a threading API.
Definition OS.hxx:46
static int get_priority_max()
Get the maximum thread priority.
Definition OS.hxx:132
void start(const char *name, int priority, size_t stack_size)
Starts the thread.
Definition OS.hxx:78
General Purpose Output (GPO) instance on the 74HC595.
Value read() const override
Retrieves the current Value of a GPO output sate (requested).
void set_direction(Gpio::Direction dir) const override
Sets the GPO direction (does nothing).
const uint8_t bit_
bit number representative of the bit
const uint8_t chipIndex_
index on the bus for the chip
void set() const override
Sets the GPO pin to high.
void write(Value new_state) const override
Writes a GPO pin (set or clear to a specific state).
Direction direction() const override
Gets the GPO direction.
constexpr SN74HC595GPO(SN74HC595< N > *instance, uint8_t chip_index, uint8_t bit)
Constructor.
void clr() const override
Clears the GPO pin to low.
SN74HC595< N > *const instance_
reference to chip instance
Driver for the 74HC595 shift register.
OSSem sem_
semaphore for posting events
void init(const char *spi_name, int priority=get_priority_max())
Initialize the SN74HC595 settings.
SN74HC595(void(*request_refresh_operation)(void))
Constructor.
int spiFd_
SPI bus that accesses the SN74HC595.
void refresh(bool from_isr=false)
Triggers the helper thread to wakeup and refresh the outputs.
void * entry() override
User entry point for the created thread.
static constexpr uint32_t SPI_MAX_SPEED_HZ
maximum SPI clock speed in Hz
uint8_t ioPending_
true if an update is pending
void(* requestRefreshOperation_)(void)
Request that the GPIO cache be refreshed.
std::atomic< uint8_t > gpoData_[N]
local copy of the expansion output data
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171