6 #include <satcat5/cfgbus_multiserial.h>
11 namespace log = satcat5::log;
12 namespace util = satcat5::util;
15 const unsigned MultiSerial::REGADDR_IRQ = 0;
16 const unsigned MultiSerial::REGADDR_CFG = 1;
17 const unsigned MultiSerial::REGADDR_STATUS = 2;
18 const unsigned MultiSerial::REGADDR_DATA = 3;
21 static const u32 MS_DVALID = (1u << 8);
22 static const u32 MS_RD_READY = (1u << 0);
23 static const u32 MS_CMD_FULL = (1u << 1);
24 static const u32 MS_BUSY = (1u << 2);
25 static const u32 MS_ERROR = (1u << 3);
29 static const unsigned HW_COPY_MAX =
32 MultiSerial::MultiSerial(
35 u8* txbuff,
unsigned txsize,
36 u8* rxbuff,
unsigned rxsize)
37 : cfg::
Interrupt(cfg, devaddr, REGADDR_IRQ)
38 , m_ctrl(cfg->get_register(devaddr))
39 , m_tx(txbuff, txsize, maxpkt)
40 , m_rx(rxbuff, rxsize, maxpkt)
56 if (ncmd == 0)
return false;
57 if (m_cmd_queued >= m_cmd_max)
return false;
61 m_new_wralloc = 1 + 2*ncmd;
66 m_new_rdalloc = nread + 1;
67 if (m_new_rdalloc > m_rdalloc)
return false;
76 unsigned idx = util::modulo_add_uns(m_cmd_cbidx + m_cmd_queued, m_cmd_max);
80 if (m_new_wralloc != actual) {
81 log::Log(log::ERROR,
"MST: Write-length mismatch")
87 m_rdalloc -= m_new_rdalloc;
104 m_cmd_cbidx = util::modulo_add_uns(m_cmd_cbidx + 1, m_cmd_max);
115 while (m_irq_rdrem > 1) {
116 u32 tmp = m_ctrl[REGADDR_DATA];
117 if (tmp & MS_DVALID) {
126 if (m_irq_wrrem == 0 && m_irq_rdrem == 1) {
128 u32 status = m_ctrl[REGADDR_STATUS];
129 if (status & MS_BUSY) {
143 if (m_irq_wrrem == 0 && m_irq_rdrem == 0) {
153 while (m_irq_wrrem) {
156 util::min_unsigned(HW_COPY_MAX, m_irq_wrrem);
157 u32 status = m_ctrl[REGADDR_STATUS];
158 if (status & MS_CMD_FULL)
break;
159 if (status & MS_BUSY) num_copy = 1;
161 u32 temp[HW_COPY_MAX];
162 for (
unsigned a = 0 ; a < num_copy ; ++a) {
163 temp[a] = (u32)
m_tx.read_u16();
166 #if SATCAT5_CFGBUS_DIRECT
167 m_ctrl[REGADDR_DATA] = temp[0];
169 m_ctrl[REGADDR_DATA].write_repeat(num_copy, temp);
171 m_irq_wrrem -= num_copy;
#define SATCAT5_CFGBUS_DIRECT
By default, use the general-purpose interface (see above).
Event-handler for individual ConfigBus interrupts.
Partial driver for the multipurpose serial peripheral.
void data_rcvd(satcat5::io::Readable *src) override
The data_rcvd() callback is polled whenever data is available.
satcat5::io::PacketBuffer m_tx
Buffer for hardware commands.
void poll_demand()
Deferred event handler, called after request().
satcat5::io::PacketBuffer m_rx
Buffer for reply data.
virtual void read_done(unsigned cidx)=0
Callback when each transaction is finished.
unsigned write_finish()
Enqueue transaction after calling write_check().
bool write_check(unsigned ncmd, unsigned nread)
Is there enough space in the software queue? If it returns true, write each opcode and then call writ...
void irq_event()
Interrupt service routine.
unsigned get_write_partial() const
Get number of bytes in a partial packet, or -1 on overflow.
bool write_finalize() override
Mark end of frame and release temporary working data.
unsigned get_write_space() const override
How many bytes can be written without blocking?
unsigned get_read_ready() const override
How many bytes can be read without blocking?
void write_abort() override
If possible, abort the current partially-written packet.
void read_finalize() override
Consume any remaining bytes in this frame, if applicable.
Abstract API for reading byte-streams and packets.
u8 read_u8()
One of many functions for reading integer/floating point values, see details.
virtual void set_callback(satcat5::io::EventListener *callback)
Update registered callback for data_rcvd() events.
void write_u8(u8 data)
One of many functions for writing integer/floating point values, see details.
The Log class creates and formats one log message.
Log & write(const char *str)
Formatting methods for various data types.
void request_poll()
Call this method to request polling at a later time.
Diagnostic logging to UART and/or Ethernet ports.
Miscellaneous mathematical utility functions.