SatCat5
cfgbus_uart.cc
1 // Copyright 2021-2024 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <satcat5/cfgbus_uart.h>
7 #include <satcat5/utils.h>
8 
9 namespace cfg = satcat5::cfg;
10 namespace util = satcat5::util;
11 
12 // Define hardware register map.
13 static const unsigned REGADDR_IRQ = 0;
14 static const unsigned REGADDR_CFG = 1;
15 static const unsigned REGADDR_STATUS = 2;
16 static const unsigned REGADDR_DATA = 3;
17 
18 // Status and command codes for the multiserial control registers.
19 static const u32 MS_DVALID = (1u << 8);
20 static const u32 MS_RD_READY = (1u << 0);
21 static const u32 MS_CMD_FULL = (1u << 1);
22 
23 cfg::Uart::Uart(cfg::ConfigBus* cfg, unsigned devaddr)
24  : io::BufferedIO(m_txbuff, SATCAT5_UART_BUFFSIZE, 0,
25  m_rxbuff, SATCAT5_UART_BUFFSIZE, 0)
26  , cfg::Interrupt(cfg, devaddr, REGADDR_IRQ)
27  , m_ctrl(cfg->get_register(devaddr))
28 {
29  // No other initialization at this time.
30 }
31 
33  unsigned clkref_hz,
34  unsigned baud_hz,
35  bool ignore_cts)
36 {
37  // Note: Writing to Config register also resets hardware FIFOs.
38  u32 clkdiv = util::div_round_u32(clkref_hz, baud_hz);
39  m_ctrl[REGADDR_CFG] = (ignore_cts << 31) | clkdiv;
40 }
41 
43 {
44  // Forward data from Tx-FIFO to hardware.
45  while (m_tx.get_read_ready()) {
46  u32 status = m_ctrl[REGADDR_STATUS];
47  if (status & MS_CMD_FULL) break;
48  m_ctrl[REGADDR_DATA] = m_tx.read_u8();
49  }
50 }
51 
53 {
54  // Read any data waiting in the hardware FIFO.
55  // (Let PacketBuffer object handle overflow, if it occurs.)
56  unsigned nwrite = 0;
57  while (1) {
58  u32 data = m_ctrl[REGADDR_DATA];
59  if (data & MS_DVALID) {
60  u8 byte = (u8)(data & 0xFF);
61  m_rx.write_u8(byte);
62  ++nwrite;
63  } else {
64  break;
65  }
66  }
67 
68  // Finalize new data to ensure downstream notifications.
69  if (nwrite) m_rx.write_finalize();
70 }
Generic ConfigBus API.
Definition: cfgbus_core.h:124
Event-handler for individual ConfigBus interrupts.
void irq_event()
Interrupt service routine.
Definition: cfgbus_uart.cc:52
void data_rcvd(satcat5::io::Readable *src)
The data_rcvd() callback is polled whenever data is available.
Definition: cfgbus_uart.cc:42
void configure(unsigned clkref_hz, unsigned baud_hz, bool ignore_cts=true)
Set baud rate and flow-control.
Definition: cfgbus_uart.cc:32
Uart(satcat5::cfg::ConfigBus *cfg, unsigned devaddr)
Initialize this UART and link to a specific register bank.
Definition: cfgbus_uart.cc:23
Abstract API for reading byte-streams and packets.
Definition: io_readable.h:68
Miscellaneous mathematical utility functions.