57#ifndef _FREERTOS_DRIVERS_TI_TIVARAILCOM_HXX_
58#define _FREERTOS_DRIVERS_TI_TIVARAILCOM_HXX_
60#if (!defined(TIVADCC_TIVA)) && (!defined(TIVADCC_CC3200))
61#error must define either TIVADCC_TIVA or TIVADCC_CC3200
109 static uint8_t sample() {
111 if (!CH1_Pin::get()) ret |= 1;
112 if (!CH2_Pin::get()) ret |= 2;
113 if (!CH3_Pin::get()) ret |= 4;
114 if (!CH4_Pin::get()) ret |= 8;
119// The weak attribute is needed if the definition is put into a header file.
120const uint32_t RailcomHw::UART_BASE[] __attribute__((weak)) = {UART4_BASE, UART3_BASE, UART2_BASE, UART7_BASE};
121const uint32_t RailcomHw::UART_PERIPH[]
122__attribute__((weak)) = {SYSCTL_PERIPH_UART4, SYSCTL_PERIPH_UART3, SYSCTL_PERIPH_UART2, SYSCTL_PERIPH_UART7};
141 MAP_IntPrioritySet(HW::OS_INTERRUPT, configKERNEL_INTERRUPT_PRIORITY);
142 MAP_IntEnable(HW::OS_INTERRUPT);
147 MAP_IntDisable(HW::OS_INTERRUPT);
182 int ioctl(
File *file,
unsigned long int key,
unsigned long data)
override
193 portENTER_CRITICAL();
227 n->notify_from_isr();
228 os_isr_exit_yield_test(
true);
262 if (sample < 0)
return;
264 extern uint32_t feedback_sample_overflow_count;
265 ++feedback_sample_overflow_count;
271 uint32_t tick_timer = HW::get_timer_tick();
274 MAP_IntPendSet(HW::OS_INTERRUPT);
309 for (
unsigned i = 0; i <
ARRAYSIZE(HW::UART_BASE); ++i)
312 MAP_SysCtlPeripheralEnable(HW::UART_PERIPH[i]);
313#elif defined(TIVADCC_CC3200)
314 MAP_PRCMPeripheralClkEnable(HW::UART_PERIPH[i], PRCM_RUN_MODE_CLK);
316 MAP_UARTConfigSetExpClk(HW::UART_BASE[i], cm3_cpu_clock_hz, 250000,
317 UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
318 UART_CONFIG_PAR_NONE);
319 MAP_UARTFIFOEnable(HW::UART_BASE[i]);
321 HWREGBITW(HW::UART_BASE[i] + UART_O_CTL, UART_CTL_RXE) = 0;
322 MAP_UARTEnable(HW::UART_BASE[i]);
327 for (
unsigned i = 0; i <
ARRAYSIZE(HW::UART_BASE); ++i)
329 MAP_UARTDisable(HW::UART_BASE[i]);
335 HW::enable_measurement(
true);
337 HW::disable_measurement();
342 HW::enable_measurement(
false);
343 const bool need_ch1_cutout = HW::need_ch1_cutout() || (this->
feedbackKey_ < 11000);
344 Debug::RailcomRxActivate::set(
true);
345 for (
unsigned i = 0; i <
ARRAYSIZE(HW::UART_BASE); ++i)
349 HWREG(HW::UART_BASE[i] + UART_O_CTL) |= UART_CTL_RXE;
354 while (MAP_UARTCharGetNonBlocking(HW::UART_BASE[i]) >= 0)
358 Debug::RailcomDriverCutout::set(
true);
363 Debug::RailcomDriverCutout::set(
false);
364 for (
unsigned i = 0; i <
ARRAYSIZE(HW::UART_BASE); ++i)
366 while (MAP_UARTCharsAvail(HW::UART_BASE[i]))
368 Debug::RailcomDataReceived::toggle();
369 Debug::RailcomAnyData::set(
true);
378 long data = MAP_UARTCharGetNonBlocking(HW::UART_BASE[i]);
379 if (data < 0 || data > 0xff) {
388 HWREG(HW::UART_BASE[i] + UART_O_CTL) &= ~UART_CTL_RXE;
389 Debug::RailcomError::toggle();
395 HWREG(HW::UART_BASE[i] + UART_O_CTL) |= UART_CTL_RXE;
397 HW::middle_cutout_hook();
398 Debug::RailcomDriverCutout::set(
true);
403 HW::disable_measurement();
404 bool have_packets =
false;
405 for (
unsigned i = 0; i <
ARRAYSIZE(HW::UART_BASE); ++i)
407 while (MAP_UARTCharsAvail(HW::UART_BASE[i]))
409 Debug::RailcomDataReceived::toggle();
410 Debug::RailcomAnyData::set(
true);
411 Debug::RailcomCh2Data::set(
true);
420 long data = MAP_UARTCharGetNonBlocking(HW::UART_BASE[i]);
421 if (data < 0 || data > 0xff) {
422 Debug::RailcomError::toggle();
427 Debug::RailcomE0::toggle();
431 HWREG(HW::UART_BASE[i] + UART_O_CTL) &= ~UART_CTL_RXE;
432 Debug::RailcomRxActivate::set(
false);
437 Debug::RailcomPackets::toggle();
439 MAP_IntPendSet(HW::OS_INTERRUPT);
450 Debug::RailcomPackets::toggle();
451 MAP_IntPendSet(HW::OS_INTERRUPT);
454 Debug::RailcomCh2Data::set(
false);
455 Debug::RailcomDriverCutout::set(
false);
460 for (
unsigned i = 0; i <
ARRAYSIZE(HW::UART_BASE); ++i)
469 Debug::RailcomPackets::toggle();
471 MAP_IntPendSet(HW::OS_INTERRUPT);
const char * name
device name
This structure is safe to use from an interrupt context and a regular context at the same time,...
void increment_front()
Removes the head of the FIFO from the queue.
bool has_noncommit_space()
void increment_back()
Commits the element at back() into the queue.
void commit_back()
Commits the oldest entry reserved by noncommit_back.
T & front()
Returns the head of the FIFO (next element to read).
T & back()
Returns the space to write the next element to.
void noncommit_back()
Increments the back pointer without committing the entry into the queue.
OSMutex lock_
protects internal structures.
An object that can schedule itself on an executor to run.
virtual void notify()=0
Generic callback.
Class to allow convenient locking and unlocking of mutexes in a C context.
Base class for railcom drivers.
Notifiable * readableNotifiable_
Notify this when we have data in our buffers.
void os_interrupt_handler()
Implementation of the interrupt handler running at the kernel interrupt priority.
RailcomDriverBase(const char *name)
Constructor.
dcc::Feedback * returnedPackets_[HW::CHANNEL_COUNT]
Stores pointers to packets we are filling right now, one for each channel.
uint32_t feedbackKey_
Stores the key for the next packets to read.
ssize_t read(File *file, void *buf, size_t count) OVERRIDE
Read from a file or device.
void flush_buffers() OVERRIDE
Instructs the device driver to drop all TX and RX queues.
dcc::Feedback * alloc_new_packet(uint8_t channel)
Takes a new empty packet at the front of the queue, fills in feedback key and channel information.
void set_feedback_key(uint32_t key) OVERRIDE
Specifies the feedback key to write into the received railcom data packets.
int ioctl(File *file, unsigned long int key, unsigned long data) override
Request an ioctl transaction.
void add_sample(int sample)
Adds a sample for a preamble bit.
FixedQueue< dcc::Feedback, HW::Q_SIZE > feedbackQueue_
The packets we have read so far.
ssize_t write(File *, const void *, size_t) OVERRIDE
Write to a file or device.
Abstract base class for railcom drivers.
Railcom driver for TI Tiva-class microcontrollers using the TivaWare peripheral library.
bool inCutout_
True when we are currently within a cutout.
TivaRailcomDriver(const char *path)
Constructor.
void start_cutout() OVERRIDE
Instructs the driver that the railcom cutout is starting now.
void disable() OVERRIDE
This will be called when reference count goes from non-zero to 0.
void end_cutout() OVERRIDE
Instructs the driver that the railcom cutout is over now.
void no_cutout() OVERRIDE
Called instead of start/mid/end-cutout at the end of the current packet if there was no cutout reques...
void enable() OVERRIDE
This will be called once when reference-count goes from 0 to positive.
void middle_cutout() OVERRIDE
Notifies the driver that the railcom cutout has reached the middle point, i.e., the first window is p...
void feedback_sample() OVERRIDE
Call to the driver for sampling the current sensors.
#define CAN_IOC_READ_ACTIVE
read active ioctl.
#define NOTIFIABLE_TYPE
ioctl minor type used for the read/write active notifiable integration.
#define CAN_IOC_MAGIC
Magic number for this driver's ioctl calls.
#define IOC_SIZE(_num)
Decode ioctl size.
#define IOC_TYPE(_num)
Decode ioctl type.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
#define ARRAYSIZE(a)
Returns the number of elements in a statically defined array (of static size)
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
uint8_t channel
Used by multi-channel railcom receiver drivers.
uint8_t ch2Data[6]
Payload of channel 2.
Structure used for reading (railcom) feedback data from DCC / Railcom device drivers.
void reset(uint32_t feedback_key)
Clears the structure and sets the feedback key to a specific value.
void add_ch1_data(uint8_t data)
Appends a byte to the channel 1 payload.
void add_ch2_data(uint8_t data)
Appends a byte to the channel 2 payload.