6 #include <satcat5/cfgbus_remote.h>
7 #include <satcat5/ip_dispatch.h>
10 #include <satcat5/udp_dispatch.h>
13 namespace cfg = satcat5::cfg;
14 namespace util = satcat5::util;
19 #ifndef SATCAT5_CFGBUS_IGNORE_SEQ
20 #define SATCAT5_CFGBUS_IGNORE_SEQ 0
24 static const unsigned DEBUG_VERBOSE = 0;
27 static const u8 OPCODE_WRITE0 = 0x2F;
28 static const u8 OPCODE_WRITE1 = 0x3F;
29 static const u8 OPCODE_READ0 = 0x40;
30 static const u8 OPCODE_READ1 = 0x50;
33 static const u32 STATUS_PENDING = (1u << 0);
34 static const u32 STATUS_BUSY = (1u << 1);
35 static const u32 STATUS_POLLING = (1u << 2);
38 static const Type TYPE_ETH_ACK =
39 Type(satcat5::eth::ETYPE_CFGBUS_ACK.value);
40 static const Type TYPE_UDP_ACK =
41 Type(satcat5::udp::PORT_CFGBUS_ACK.value);
44 : satcat5::eth::AddressContainer(iface)
50 void satcat5::eth::ConfigBus::connect(
53 m_addr.
connect(dst, satcat5::eth::ETYPE_CFGBUS_CMD);
56 satcat5::udp::ConfigBus::ConfigBus(
58 : satcat5::udp::AddressContainer(udp)
64 void satcat5::udp::ConfigBus::connect(
69 satcat5::udp::PORT_CFGBUS_CMD,
70 satcat5::udp::PORT_CFGBUS_ACK);
73 ConfigBusRemote::ConfigBusRemote(
77 , satcat5::net::Protocol(ack)
79 , m_timeout_rd(100000)
83 , m_response_opcode(0)
86 , m_response_status(cfg::
IoStatus::OK)
92 #if SATCAT5_ALLOW_DELETION
93 ConfigBusRemote::~ConfigBusRemote()
102 return send_and_wait(OPCODE_READ1, regaddr, 1, &rdval, m_timeout_rd);
107 return send_and_wait(OPCODE_WRITE1, regaddr, 1, &wrval, m_timeout_wr);
111 unsigned regaddr,
unsigned count, u32* result)
113 return send_and_wait(OPCODE_READ1, regaddr, count, result, m_timeout_rd);
117 unsigned regaddr,
unsigned count, u32* result)
119 return send_and_wait(OPCODE_READ0, regaddr, count, result, m_timeout_rd);
123 unsigned regaddr,
unsigned count,
const u32* data)
125 return send_and_wait(OPCODE_WRITE1, regaddr, count, data, m_timeout_wr);
129 unsigned regaddr,
unsigned count,
const u32* data)
131 return send_and_wait(OPCODE_WRITE0, regaddr, count, data, m_timeout_wr);
136 if (DEBUG_VERBOSE > 1)
log::Log(log::DEBUG,
"CfgRemote: frame_rcvd");
139 if (!(m_status & STATUS_PENDING))
return;
143 log::Log(log::ERROR,
"CfgRemote: Invalid response");
152 u32 addr = src.read_u32();
153 unsigned len = 1 + (unsigned)len8;
159 if (!(opcode == m_response_opcode && len == m_response_len
160 && (SATCAT5_CFGBUS_IGNORE_SEQ || seq == m_sequence))) {
161 if (DEBUG_VERBOSE > 1) {
162 log::Log(log::DEBUG,
"CfgRemote: Response ignored")
166 }
else if (DEBUG_VERBOSE > 0) {
167 log::Log(log::DEBUG,
"CfgRemote: Response received")
172 unsigned rdbytes = 4 * m_response_len + 1;
174 for (
unsigned a = 0 ; a < m_response_len ; ++a)
175 m_response_ptr[a] = src.read_u32();
178 log::Log(log::WARNING,
"CfgRemote: Read error");
179 m_response_status = cfg::IoStatus::BUSERROR;
181 }
else if (m_response_ptr) {
182 log::Log msg(log::ERROR,
"CfgRemote: Invalid response");
183 m_response_status = cfg::IoStatus::CMDERROR;
184 if (DEBUG_VERBOSE > 1) {
192 util::clr_mask_u32(m_status, STATUS_PENDING);
198 if (m_status)
return;
201 satcat5::poll::service_all();
204 util::set_mask_u32(m_status, STATUS_POLLING);
206 util::clr_mask_u32(m_status, STATUS_POLLING);
210 u8 opcode,
unsigned addr,
unsigned len,
const u32* ptr,
unsigned timeout)
217 return cfg::IoStatus::CMDERROR;
218 }
else if (timeout) {
221 return cfg::IoStatus::OK;
226 u8 opcode,
unsigned addr,
unsigned len,
const u32* ptr)
228 if (DEBUG_VERBOSE > 1) {
229 log::Log(log::DEBUG,
"CfgRemote: send_command")
234 if (m_status & STATUS_BUSY) {
235 log::Log(log::ERROR,
"CfgRemote: Already busy");
241 log::Log(log::ERROR,
"CfgRemote: Bad length");
246 unsigned cmd_bytes = 8;
247 if ((opcode == OPCODE_WRITE0) || (opcode == OPCODE_WRITE1))
248 cmd_bytes += 4 * len;
253 log::Log(log::ERROR,
"CfgRemote: Connection error");
255 }
else if (DEBUG_VERBOSE > 0) {
256 log::Log(log::DEBUG,
"CfgRemote: Sending command")
261 m_response_opcode = opcode;
262 m_response_len = len;
267 dst->write_u32(addr);
268 if ((opcode == OPCODE_WRITE0) || (opcode == OPCODE_WRITE1)) {
269 for (
unsigned a = 0 ; a < len ; ++a)
270 dst->write_u32(ptr[a]);
273 m_response_ptr = (u32*)ptr;
282 m_response_status = cfg::IoStatus::OK;
285 util::set_mask_u32(m_status, STATUS_BUSY | STATUS_PENDING);
288 auto tref = SATCAT5_CLOCK->checkpoint_usec(timeout);
290 satcat5::poll::service();
291 if (!(m_status & STATUS_PENDING)) {
293 }
else if (tref.checkpoint_elapsed()) {
294 log::Log(log::ERROR,
"CfgRemote: Timeout");
295 m_response_status = cfg::IoStatus::TIMEOUT;
301 util::clr_mask_u32(m_status, STATUS_BUSY | STATUS_PENDING);
302 return m_response_status;
IoStatus
Status codes for ConfigBus read/write operations.
void irq_poll()
Poll all registered ConfigBus interrupt handlers.
Controller for a remote ConfigBus, connected over network.
satcat5::cfg::IoStatus read_array(unsigned regaddr, unsigned count, u32 *result) override
Bulk read from consecutive registers.
satcat5::cfg::IoStatus write_repeat(unsigned regaddr, unsigned count, const u32 *data) override
Repeated write to the same register.
satcat5::net::Address *const m_dst
MAC address for the remote interface.
satcat5::cfg::IoStatus wait_response(unsigned timeout)
Busywait until response is received.
void timer_event() override
Child class MUST override this method.
void frame_rcvd(satcat5::io::LimitedRead &src) override
Dispatch calls frame_rcvd(...) for each incoming frame with with a matching net::Type value.
bool send_command(u8 opcode, unsigned addr, unsigned len, const u32 *ptr)
Send the specified opcode.
satcat5::cfg::IoStatus read_repeat(unsigned regaddr, unsigned count, u32 *result) override
Repeated read from the same register.
satcat5::cfg::IoStatus send_and_wait(u8 opcode, unsigned addr, unsigned len, const u32 *ptr, unsigned timeout)
Send, then wait if requested.
satcat5::cfg::IoStatus write(unsigned regaddr, u32 wrval) override
Basic read and write operations (ConfigBus API).
satcat5::cfg::IoStatus write_array(unsigned regaddr, unsigned count, const u32 *data) override
Bulk write to consecutive registers.
satcat5::cfg::IoStatus read(unsigned regaddr, u32 &rdval) override
Basic read and write operations (ConfigBus API).
void connect(const satcat5::eth::MacAddr &addr, const satcat5::eth::MacType &type, const satcat5::eth::VlanTag &vtag=satcat5::eth::VTAG_NONE)
Connect to the designated address.
Implemention of "net::Dispatch" for Ethernet frames.
Limited read of next N bytes.
unsigned get_read_ready() const override
How many bytes can be read without blocking?
u8 read_u8()
One of many functions for reading integer/floating point values, see details.
Abstract API for writing byte-streams and packets.
void write_u8(u8 data)
One of many functions for writing integer/floating point values, see details.
virtual bool write_finalize()
Mark end of frame and release temporary working data.
The Log class creates and formats one log message.
Log & write(const char *str)
Formatting methods for various data types.
Defines a generic API for sending data to a specific destination, such as a MAC address,...
virtual satcat5::net::Dispatch * iface() const =0
Fetch a pointer to the underlying interface.
virtual satcat5::io::Writeable * open_write(unsigned len)=0
Open a new frame to the designated address and type.
void add(satcat5::net::Protocol *proto)
Register a Protocol object.
void remove(satcat5::net::Protocol *proto)
Unregister a Protocol object.
void connect(const satcat5::udp::Addr &dstaddr, const satcat5::eth::MacAddr &dstmac, const satcat5::udp::Port &dstport, const satcat5::udp::Port &srcport=satcat5::udp::PORT_NONE, const satcat5::eth::VlanTag &vtag=satcat5::eth::VTAG_NONE)
Manual address resolution (user supplies IP + MAC).
Dispatcher sorts incoming UDP messages by port index.
Diagnostic logging to UART and/or Ethernet ports.
An Ethernet MAC address (with serializable interface).
IPv4 address is a 32-bit unsigned integer.
Multipurpose filter for matching fields in network packets.
TimeRef and TimeVal define the API for monotonic timers.
Miscellaneous mathematical utility functions.