Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TivaDCC< HW > Class Template Reference

A device driver for sending DCC packets. More...

#include <TivaDCC.hxx>

Inheritance diagram for TivaDCC< HW >:
Node Device FileIO

Classes

struct  Timing
 Structure for supporting bit timing. More...
 

Public Member Functions

 TivaDCC (const char *name, RailcomDriver *railcom)
 Constructor.
 
 ~TivaDCC ()
 Destructor.
 
void interrupt_handler ()
 Handle an interrupt.
 
void os_interrupt_handler ()
 Handles a software interrupt to FreeRTOS.
 
- Public Member Functions inherited from Device
 Device (const char *name)
 Constructor.
 
virtual ~Device ()
 Destructor.
 

Static Public Member Functions

static void hw_preinit ()
 Initializes the DCC output hardware.
 
- Static Public Member Functions inherited from Device
static int open (struct _reent *reent, const char *path, int flags, int mode)
 Open a file or device.
 
static int close (struct _reent *reent, int fd)
 Close a file or device.
 
static int stat (struct _reent *reent, const char *path, struct stat *stat)
 Get the status information of a file or device.
 
static int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, long long timeout)
 POSIX select().
 
static void select_clear ()
 Clears the current thread's select bits.
 
- Static Public Member Functions inherited from FileIO
static ssize_t read (struct _reent *reent, int fd, void *buf, size_t count)
 Read from a file or device.
 
static ssize_t write (struct _reent *reent, int fd, const void *buf, size_t count)
 Write to a file or device.
 
static _off_t lseek (struct _reent *reent, int fd, _off_t offset, int whence)
 Change the offset index of a file or device.
 
static int fstat (struct _reent *reent, int fd, struct stat *stat)
 Get the status information of a file or device.
 
static int ioctl (int fd, unsigned long int key, unsigned long data)
 Request and ioctl transaction.
 
static int fcntl (int fd, int cmd, unsigned long data)
 Manipulate a file descriptor.
 
static bool is_device (int fd)
 Test if the file descriptor belongs to a device.
 

Private Types

enum  BitEnum {
  DCC_ZERO , DCC_ONE , DCC_EOP_ONE , DCC_RC_ONE ,
  DCC_RC_HALF_ZERO , RAILCOM_CUTOUT_PRE , RAILCOM_CUTOUT_FIRST , RAILCOM_CUTOUT_SECOND ,
  RAILCOM_CUTOUT_POST , MM_PREAMBLE , MM_ZERO , MM_ONE ,
  NUM_TIMINGS
}
 Bit timings that we store and precalculate. More...
 
enum  State {
  PREAMBLE , START , DATA_0 , DATA_1 ,
  DATA_2 , DATA_3 , DATA_4 , DATA_5 ,
  DATA_6 , DATA_7 , FRAME , ST_MM_PREAMBLE ,
  MM_DATA_0 , MM_DATA_1 , MM_DATA_2 , MM_DATA_3 ,
  MM_DATA_4 , MM_DATA_5 , MM_DATA_6 , MM_DATA_7 ,
  RESYNC , DCC_MAYBE_RAILCOM , DCC_NO_CUTOUT , DCC_CUTOUT_PRE ,
  DCC_START_RAILCOM_RECEIVE , DCC_MIDDLE_RAILCOM_CUTOUT , DCC_STOP_RAILCOM_RECEIVE , MM_LEADOUT ,
  POWER_IMM_TURNON
}
 Internal state machine states. More...
 

Private Member Functions

ssize_t read (File *file, void *buf, size_t count) OVERRIDE
 Read from a file or device.
 
ssize_t write (File *file, const void *buf, size_t count) OVERRIDE
 Write to a file or device.
 
int ioctl (File *file, unsigned long int key, unsigned long data) OVERRIDE
 Request an ioctl transaction.
 
void enable () OVERRIDE
 function to enable device
 
void disable () OVERRIDE
 function to disable device
 
void flush_buffers () override
 Discards all pending buffers.
 
void fill_timing (BitEnum ofs, uint32_t period_usec, uint32_t transition_usec, uint32_t interval_period_usec, uint32_t timing_spread_usec=0)
 Prepares a timing entry.
 
void check_and_enable_outputs ()
 Checks each output and enables those that need to be on.
 
 TivaDCC ()
 Default constructor.
 
 DISALLOW_COPY_AND_ASSIGN (TivaDCC)
 

Private Attributes

int hDeadbandDelay_
 low->high deadband delay in clock count
 
int lDeadbandDelay_
 high->low deadband delay in clock count
 
int usecDelay_
 1 usec of delay in clock count
 
Timing timings [NUM_TIMINGS]
 Precalculated bit timings (translated to clock cycles).
 
State state_
 Current state of internal state machine.
 
FixedQueue< dcc::Packet, HW::Q_SIZE > packetQueue_
 Packets still waiting to be sent.
 
NotifiablewritableNotifiable_
 Notify this when we have free buffers.
 
RailcomDriverrailcomDriver_
 Will be notified for railcom cutout events.
 
unsigned seed_ = 0xb7a11bae
 Seed for a pseudorandom sequence.
 

Static Private Attributes

static const size_t MAX_PKT_SIZE = 6
 maximum packet size we can support
 
static dcc::Packet IDLE_PKT = dcc::Packet::DCC_IDLE()
 idle packet
 
static constexpr unsigned RAILCOM_CUTOUT_START_USEC = 26
 Standard timing value of when the railcom cutout should start, measured from the transition of the end-of-packet-one-bit.
 
static constexpr unsigned RAILCOM_CUTOUT_MID_USEC = 185
 Standard timing value of the railcom cutout middle, measured from the transition of the end-of-packet-one-bit.
 
static constexpr unsigned RAILCOM_CUTOUT_END_USEC = 486
 Standard timing value of the railcom cutout end, measured from the transition of the end-of-packet-one-bit.
 
static constexpr unsigned PMOD = 65213
 Parameters for a linear RNG: modulus.
 
static constexpr unsigned PMUL = 52253
 Parameters for a linear RNG: multiplier.
 
static constexpr unsigned PADD = 42767
 Parameters for a linear RNG: additive.
 

Additional Inherited Members

- Protected Member Functions inherited from Node
 Node (const char *name)
 Constructor.
 
virtual ~Node ()
 Destructor.
 
int open (File *, const char *, int, int) OVERRIDE
 Open method.
 
int close (File *) OVERRIDE
 Close method.
 
virtual int fstat (File *file, struct stat *stat) override
 Get the status information of a file or device.
 
- Protected Member Functions inherited from FileIO
 FileIO (const char *name)
 Constructor.
 
virtual ~FileIO ()
 Destructor.
 
virtual off_t lseek (File *f, off_t offset, int whence)
 Seek method.
 
virtual int fcntl (File *file, int cmd, unsigned long data)
 Manipulate a file descriptor.
 
virtual bool select (File *file, int mode)
 Device select method.
 
- Static Protected Member Functions inherited from Device
static void select_insert (SelectInfo *info)
 Add client to list of clients needing woken.
 
static void select_wakeup (SelectInfo *info)
 Wakeup the list of clients needing woken.
 
static void select_wakeup_from_isr (SelectInfo *info, int *woken)
 Wakeup the list of clients needing woken.
 
- Static Protected Member Functions inherited from FileIO
static int fd_alloc (void)
 Allocate a free file descriptor.
 
static void fd_free (int fd)
 Free up a file descriptor.
 
static Filefile_lookup (int fd)
 Looks up a reference to a File corresponding to a given file descriptor.
 
static int fd_lookup (File *file)
 Looks up a file descriptor corresponding to a given File reference.
 
- Protected Attributes inherited from Node
OSMutex lock_
 protects internal structures.
 
mode_t mode_
 File open mode, such as O_NONBLOCK.
 
unsigned int references_
 number of open references
 
- Protected Attributes inherited from FileIO
const char * name
 device name
 
- Static Protected Attributes inherited from FileIO
static const unsigned int numOpenFiles = 20
 
static File files []
 File descriptor pool.
 
static OSMutex mutex
 mutual exclusion for fileio
 

Detailed Description

template<class HW>
class TivaDCC< HW >

A device driver for sending DCC packets.

If the packet queue is empty, then the device driver automatically sends out idle DCC packets. The device driver uses two instances of the 16/32-bit timer pairs. The user is responsible for providing interrupt entry point for the interval timer and calling the inline method interrupt_handler on behalf of this device driver.

Write calls work by sending the packet in the format of dcc::Packet. The payload should include the X-OR linkage byte. Only one DCC packet may be written per call to the write method. If there is no space currently available in the write queue, the write method will return -1 with errno set to ENOSPC.

Handling of write throttling:

The driver uses a second interrupt, used as a software interrupt at the FreeRTOS priority level, to communicate back information on when the device is writable. It is okay to use the interrupt for the second timer for this purpose. This interrupt will be enabled in the IOCTL after the writenotifiable is set, disabled in the interrupt itself when the writenotifiable is cleared. It is set pending at startup and when the dcc interrupt frees up a packet from the queue, and it is cleared pending when a write realizes there is no space for a buffer.

The user must ensure that the 'interrupt' has a very high priority, whereas 'os_interrupt' has a priority that's at or lower than the FreeRTOS kernel.

Handling of feedback data:

The driver may generate return data for the application layer in the form of dcc::Feedback messages. These will be attributed to the incoming packets by an opaque key that the application sets. For each packet that has a non-zero feedback a dcc::Feedback message will be sent to the application layer, which will be readable using the read method on the fd.

The application can request notification of readable and writable status using the regular IOCTL method.

EMC spectrum spreading

There is an optional feature that helps with passing EMC certification for systems that are built on this driver. The observation is that if the output signal has may repeats of a certain period, then in the measured spectrum there will be a big spike in energy that might exceed the thresholds for compliance. However, by slightly varying the timing of the output signal, the energy will be spread across a wider spectrum, thus the peak of emission will be smaller.

This feature is enabled by extern uint8_t spreadSpectrum;. This can come from a constant or configuration dependent variable. If enabled, then the timing of DCC zero bits are stretched to be a random value between 100.5 and 105 usec each half; the timing of DCC one bits will be stretched from 56.5 to 60 usec per half. The symmetry within each bit is still perfectly matched. Marklin-Motorola packets get up to 2 usec of stretching on each phase.

The actual stretching is generated using a uniform random number generator within said limits to ensure we spread uniformly across the available timings. Up to four bits are output with the same timing, then a new random timing is generated.

Definition at line 143 of file TivaDCC.hxx.

Member Enumeration Documentation

◆ BitEnum

template<class HW >
enum TivaDCC::BitEnum
private

Bit timings that we store and precalculate.

Enumerator
DCC_ZERO 

Zero bit for DCC (this is the longer)

DCC_ONE 

One bit for DCC (this is the shorter)

DCC_EOP_ONE 

One bit for DCC that we generate at the end of packet transition.

This has a stretched negative part so that the next packet resync avoids a glitch in the output.

DCC_RC_ONE 

One bit for DCC that we generate during the railcom cutout.

Can be used to play with alignment of edges coming out of the railcom cutout.

DCC_RC_HALF_ZERO 

Half zero bit which is sent directly after the railcom cutout is over.

Needed to reset certain old decoders packet recognizer. Recommended by https://nmra.org/sites/default/files/standards/sandrp/pdf/tn-2-05draft2005-02-25_for_rp-9.2.3.pdf

RAILCOM_CUTOUT_PRE 

This is not a bit, but specifies when to wake up during the railcom cutout.

The time is T_CS, usually 26 usec.

RAILCOM_CUTOUT_FIRST 

This is not a bit, but specifies when to wake up during the railcom cutout.

The time is the time elapsed between T_CS and the middle of the two windows.

RAILCOM_CUTOUT_SECOND 

This is not a bit, but specifies when to wake up during the railcom cutout.

The time is the time elapsed between the end of the cutout and the the middle of the two windows.

RAILCOM_CUTOUT_POST 

This is not a bit, but specifies when to wake up during the railcom cutout.

This is used for re-synchronizing the

MM_PREAMBLE 

Long negative DC pulse to act as a preamble for a Marklin packet.

MM_ZERO 

Zero bit for MM packet, which is a short pulse in one direction, then a long pulse in the other.

MM_ONE 

One bit for MM packet, which is a long pulse in one direction, then a short pulse in the other.

Definition at line 257 of file TivaDCC.hxx.

◆ State

template<class HW >
enum TivaDCC::State
private

Internal state machine states.

Definition at line 310 of file TivaDCC.hxx.

Constructor & Destructor Documentation

◆ TivaDCC()

template<class HW >
TivaDCC< HW >::TivaDCC ( const char *  name,
RailcomDriver railcom 
)

Constructor.

Parameters
namename of this device instance in the file system
railcomis the associated railcom driver, which will get the callbacks from the timing derived by the internal signal generator.
Todo:
tune this bit to line up with the bit stream starting after the railcom cutout.

Definition at line 965 of file TivaDCC.hxx.

◆ ~TivaDCC()

template<class HW >
TivaDCC< HW >::~TivaDCC ( )
inline

Destructor.

Definition at line 155 of file TivaDCC.hxx.

Member Function Documentation

◆ check_and_enable_outputs()

template<class HW >
void TivaDCC< HW >::check_and_enable_outputs ( )
inlineprivate

Checks each output and enables those that need to be on.

Definition at line 389 of file TivaDCC.hxx.

◆ disable()

template<class HW >
void TivaDCC< HW >::disable ( )
inlineprivatevirtual

function to disable device

Implements Node.

Definition at line 243 of file TivaDCC.hxx.

◆ enable()

template<class HW >
void TivaDCC< HW >::enable ( )
inlineprivatevirtual

function to enable device

Implements Node.

Definition at line 242 of file TivaDCC.hxx.

◆ fill_timing()

template<class HW >
void TivaDCC< HW >::fill_timing ( BitEnum  ofs,
uint32_t  period_usec,
uint32_t  transition_usec,
uint32_t  interval_period_usec,
uint32_t  timing_spread_usec = 0 
)
private

Prepares a timing entry.

Parameters
ofsis the bit timing that we are defining.
period_usecis the total length of the bit.
transition_usecis the time of the transition inside the bit, counted from the beginning of the bit (i.e. the length of the HIGH part of the period). Can be zero for DC output LOW or can be == period_usec for DC output HIGH.
interval_period_usectells when the interval timer should expire (next interrupt). Most of the time this should be the same as period_usec.
timing_spread_usecif non-zero, allows the high and low of the timing to be stretched by at most this many usec.

Definition at line 933 of file TivaDCC.hxx.

◆ flush_buffers()

template<class HW >
void TivaDCC< HW >::flush_buffers ( )
inlineoverrideprivatevirtual

Discards all pending buffers.

Called after disable().

Implements Node.

Definition at line 247 of file TivaDCC.hxx.

◆ hw_preinit()

template<class HW >
static void TivaDCC< HW >::hw_preinit ( )
inlinestatic

Initializes the DCC output hardware.

Definition at line 192 of file TivaDCC.hxx.

◆ interrupt_handler()

template<class HW >
void TivaDCC< HW >::interrupt_handler ( )
inline

Handle an interrupt.

Definition at line 450 of file TivaDCC.hxx.

◆ ioctl()

template<class HW >
int TivaDCC< HW >::ioctl ( File file,
unsigned long int  key,
unsigned long  data 
)
privatevirtual

Request an ioctl transaction.

Parameters
filefile reference for this device
keyioctl key
datakey data
filefile reference for this device
nodenode reference for this device
keyioctl key
datakey data

Reimplemented from FileIO.

Definition at line 1174 of file TivaDCC.hxx.

◆ os_interrupt_handler()

template<class HW >
void TivaDCC< HW >::os_interrupt_handler ( )
inline

Handles a software interrupt to FreeRTOS.

This should be called on the interrupt number that is submitted as os_interrupt to the constructor.

Definition at line 1209 of file TivaDCC.hxx.

◆ read()

template<class HW >
ssize_t TivaDCC< HW >::read ( File file,
void *  buf,
size_t  count 
)
privatevirtual

Read from a file or device.

Parameters
filefile reference for this device
buflocation to place read data
countnumber of bytes to read
Returns
number of bytes read upon success, -1 upon failure with errno containing the cause

Implements FileIO.

Definition at line 1114 of file TivaDCC.hxx.

◆ write()

template<class HW >
ssize_t TivaDCC< HW >::write ( File file,
const void *  buf,
size_t  count 
)
privatevirtual

Write to a file or device.

Parameters
filefile reference for this device
buflocation to find write data
countnumber of bytes to write
Returns
number of bytes written upon success, -1 upon failure with errno containing the cause

Implements FileIO.

Definition at line 1127 of file TivaDCC.hxx.

Member Data Documentation

◆ hDeadbandDelay_

template<class HW >
int TivaDCC< HW >::hDeadbandDelay_
private

low->high deadband delay in clock count

Definition at line 302 of file TivaDCC.hxx.

◆ IDLE_PKT

template<class HW >
dcc::Packet TivaDCC< HW >::IDLE_PKT = dcc::Packet::DCC_IDLE()
staticprivate

idle packet

Definition at line 254 of file TivaDCC.hxx.

◆ lDeadbandDelay_

template<class HW >
int TivaDCC< HW >::lDeadbandDelay_
private

high->low deadband delay in clock count

Definition at line 303 of file TivaDCC.hxx.

◆ MAX_PKT_SIZE

template<class HW >
const size_t TivaDCC< HW >::MAX_PKT_SIZE = 6
staticprivate

maximum packet size we can support

Definition at line 250 of file TivaDCC.hxx.

◆ packetQueue_

template<class HW >
FixedQueue<dcc::Packet, HW::Q_SIZE> TivaDCC< HW >::packetQueue_
private

Packets still waiting to be sent.

Definition at line 426 of file TivaDCC.hxx.

◆ PADD

template<class HW >
constexpr unsigned TivaDCC< HW >::PADD = 42767
staticconstexprprivate

Parameters for a linear RNG: additive.

Definition at line 437 of file TivaDCC.hxx.

◆ PMOD

template<class HW >
constexpr unsigned TivaDCC< HW >::PMOD = 65213
staticconstexprprivate

Parameters for a linear RNG: modulus.

Definition at line 433 of file TivaDCC.hxx.

◆ PMUL

template<class HW >
constexpr unsigned TivaDCC< HW >::PMUL = 52253
staticconstexprprivate

Parameters for a linear RNG: multiplier.

Definition at line 435 of file TivaDCC.hxx.

◆ RAILCOM_CUTOUT_END_USEC

template<class HW >
constexpr unsigned TivaDCC< HW >::RAILCOM_CUTOUT_END_USEC = 486
staticconstexprprivate

Standard timing value of the railcom cutout end, measured from the transition of the end-of-packet-one-bit.

Minimum 454 (end of channel one), maximum 488. Can be adjusted by HW.

Definition at line 423 of file TivaDCC.hxx.

◆ RAILCOM_CUTOUT_MID_USEC

template<class HW >
constexpr unsigned TivaDCC< HW >::RAILCOM_CUTOUT_MID_USEC = 185
staticconstexprprivate

Standard timing value of the railcom cutout middle, measured from the transition of the end-of-packet-one-bit.

Minimum 177 (end of channel one), maximum 193 (start channel 2) usec. Can be adjusted by HW.

Definition at line 419 of file TivaDCC.hxx.

◆ RAILCOM_CUTOUT_START_USEC

template<class HW >
constexpr unsigned TivaDCC< HW >::RAILCOM_CUTOUT_START_USEC = 26
staticconstexprprivate

Standard timing value of when the railcom cutout should start, measured from the transition of the end-of-packet-one-bit.

Minimum 26, max 32 usec. Can be adjusted by HW.

Definition at line 415 of file TivaDCC.hxx.

◆ railcomDriver_

template<class HW >
RailcomDriver* TivaDCC< HW >::railcomDriver_
private

Will be notified for railcom cutout events.

Definition at line 428 of file TivaDCC.hxx.

◆ seed_

template<class HW >
unsigned TivaDCC< HW >::seed_ = 0xb7a11bae
private

Seed for a pseudorandom sequence.

Definition at line 430 of file TivaDCC.hxx.

◆ state_

template<class HW >
State TivaDCC< HW >::state_
private

Current state of internal state machine.

Definition at line 368 of file TivaDCC.hxx.

◆ timings

template<class HW >
Timing TivaDCC< HW >::timings[NUM_TIMINGS]
private

Precalculated bit timings (translated to clock cycles).

Definition at line 307 of file TivaDCC.hxx.

◆ usecDelay_

template<class HW >
int TivaDCC< HW >::usecDelay_
private

1 usec of delay in clock count

Definition at line 304 of file TivaDCC.hxx.

◆ writableNotifiable_

template<class HW >
Notifiable* TivaDCC< HW >::writableNotifiable_
private

Notify this when we have free buffers.

Definition at line 427 of file TivaDCC.hxx.


The documentation for this class was generated from the following file: