dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_rcvr.c
Go to the documentation of this file.
1 /* Project Includes */
2 #include "pios.h"
3 
4 #include "pios_semaphore.h"
5 #include "pios_thread.h"
6 
7 #if defined(PIOS_INCLUDE_RCVR)
8 
9 #include <pios_rcvr_priv.h>
10 
11 enum pios_rcvr_dev_magic {
12  PIOS_RCVR_DEV_MAGIC = 0x99aabbcc,
13 };
14 
15 struct pios_rcvr_dev {
16  enum pios_rcvr_dev_magic magic;
17  uintptr_t lower_id;
18  const struct pios_rcvr_driver * driver;
19 };
20 
21 static bool PIOS_RCVR_validate(struct pios_rcvr_dev * rcvr_dev)
22 {
23  return (rcvr_dev->magic == PIOS_RCVR_DEV_MAGIC);
24 }
25 
26 static struct pios_rcvr_dev * PIOS_RCVR_alloc(void)
27 {
28  struct pios_rcvr_dev * rcvr_dev;
29 
30  rcvr_dev = (struct pios_rcvr_dev *)PIOS_malloc(sizeof(*rcvr_dev));
31  if (!rcvr_dev) return (NULL);
32 
33  rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC;
34  return(rcvr_dev);
35 }
36 
37 static struct pios_semaphore *rcvr_activity;
38 static uint32_t rcvr_last_wake;
39 
47 int32_t PIOS_RCVR_Init(uintptr_t * rcvr_id, const struct pios_rcvr_driver * driver, uintptr_t lower_id)
48 {
49  PIOS_DEBUG_Assert(rcvr_id);
50  PIOS_DEBUG_Assert(driver);
51 
52  struct pios_rcvr_dev * rcvr_dev;
53 
54  // For idempotency in all environments...
56  if (!rcvr_activity) {
57  rcvr_activity = PIOS_Semaphore_Create();
58  }
60 
61  rcvr_dev = (struct pios_rcvr_dev *) PIOS_RCVR_alloc();
62  if (!rcvr_dev) goto out_fail;
63 
64  rcvr_dev->driver = driver;
65  rcvr_dev->lower_id = lower_id;
66 
67  *rcvr_id = (uintptr_t)rcvr_dev;
68  return(0);
69 
70 out_fail:
71  return(-1);
72 }
73 
79 uintptr_t PIOS_RCVR_GetLowerDevice(uintptr_t rcvr_id)
80 {
81  struct pios_rcvr_dev *dev = (struct pios_rcvr_dev*)rcvr_id;
82 
83  if (!PIOS_RCVR_validate(dev))
84  return 0;
85 
86  return dev->lower_id;
87 }
88 
98 int32_t PIOS_RCVR_Read(uintptr_t rcvr_id, uint8_t channel)
99 {
100  // Publicly facing API uses channel 1 for first channel
101  if(channel == 0)
102  return PIOS_RCVR_INVALID;
103  else
104  channel--;
105 
106  if (rcvr_id == 0)
107  return PIOS_RCVR_NODRIVER;
108 
109  struct pios_rcvr_dev * rcvr_dev = (struct pios_rcvr_dev *)rcvr_id;
110 
111  if (!PIOS_RCVR_validate(rcvr_dev)) {
112  /* Undefined RCVR port for this board (see pios_board.c) */
113  PIOS_Assert(0);
114  }
115 
116  PIOS_DEBUG_Assert(rcvr_dev->driver->read);
117 
118  return rcvr_dev->driver->read(rcvr_dev->lower_id, channel);
119 }
120 
121 #define MIN_WAKE_INTERVAL_uS 4000 /* 250Hz ought to be enough for anyone*/
122 
123 bool PIOS_RCVR_WaitActivity(uint32_t timeout_ms) {
124  if (rcvr_activity) {
125  bool result = PIOS_Semaphore_Take(rcvr_activity, timeout_ms);
126  if(!result) {
127  // If the semaphore times out, update last wake, to try to avoid
128  // resonance due to jitter, when the update rate of the receiver
129  // matches the timeout.
130  rcvr_last_wake = PIOS_DELAY_GetRaw();
131  }
132  return result;
133  } else {
134  PIOS_Thread_Sleep(timeout_ms);
135 
136  return false;
137  }
138 }
139 
140 void PIOS_RCVR_Active() {
141  if (PIOS_DELAY_DiffuS(rcvr_last_wake) >= MIN_WAKE_INTERVAL_uS) {
142  if (rcvr_activity) {
143  rcvr_last_wake = PIOS_DELAY_GetRaw();
144  PIOS_Semaphore_Give(rcvr_activity);
145  }
146  }
147 #ifdef FLIGHT_POSIX
149  PIOS_Thread_FakeClock_UpdateBarrier(100);
150  }
151 #endif
152 }
153 
155  if (PIOS_DELAY_DiffuS(rcvr_last_wake) >= MIN_WAKE_INTERVAL_uS) {
156  bool dont_care;
157 
158  if (rcvr_activity) {
159  rcvr_last_wake = PIOS_DELAY_GetRaw();
160  PIOS_Semaphore_Give_FromISR(rcvr_activity, &dont_care);
161  }
162  }
163 }
164 
165 #endif
166 
uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
Subtract raw time from now and convert to us.
Definition: pios_delay.c:159
int32_t PIOS_IRQ_Enable(void)
Definition: pios_irq.c:53
Main PiOS header to include all the compiled in PiOS options.
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_Semaphore_Give_FromISR(struct pios_semaphore *sema, bool *woken)
void PIOS_RCVR_ActiveFromISR()
int32_t PIOS_RCVR_Init(uintptr_t *rcvr_id, const struct pios_rcvr_driver *driver, const uintptr_t lower_id)
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
Gives binary semaphore.
uintptr_t PIOS_RCVR_GetLowerDevice(uintptr_t rcvr_id)
uint32_t magic
int32_t PIOS_IRQ_Disable(void)
Definition: pios_irq.c:40
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
int32_t PIOS_RCVR_Read(uintptr_t rcvr_id, uint8_t channel)
void PIOS_RCVR_Active()
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
bool PIOS_RCVR_WaitActivity(uint32_t timeout_ms)
#define PIOS_Assert(test)
Definition: pios_debug.h:52
USART private definitions.
bool PIOS_Thread_FakeClock_IsActive(void)
Definition: pios_thread.c:207
uint32_t PIOS_DELAY_GetRaw()
Get the raw delay timer, useful for timing.
Definition: pios_delay.c:153