📄 swrxuart.c
字号:
/************************************************************
Copyright (C) 1995-2002 Pumpkin, Inc. and its
Licensor(s). Freely distributable.
$Source: C:\\RCS\\D\\salvo\\demo\\d5\\swrxuart.c,v $
$Author: aek $
$Revision: 1.7 $
$Date: 2001-10-25 19:56:53-07 $
Support file.
************************************************************/
#ifndef SWRXUART_C_INCLUDES
#define SWRXUART_C_INCLUDES
#include "d5.h"
#include "main.h"
#include "salvo.h"
/* measured instructions between obtaining desired */
/* delay in cycles and when task has been enqueued */
/* into delay queue. This is an average of the */
/* non-interrupted and interrupted case. */
#define OVERHEAD 200
/* these are the desired times, in number of */
/* instruction cycles from the start bit going low,*/
/* when we want to sample data. */
/* see discussion in BitDelay() below for timing */
/* issues. */
#if RECEIVERS >= 1
const unsigned int samplePts[9] = {
(unsigned int) (1.625*FULL_BIT_CYCLES),
(unsigned int) (2.625*FULL_BIT_CYCLES),
(unsigned int) (3.625*FULL_BIT_CYCLES),
(unsigned int) (4.625*FULL_BIT_CYCLES),
(unsigned int) (5.625*FULL_BIT_CYCLES),
(unsigned int) (6.625*FULL_BIT_CYCLES),
(unsigned int) (7.625*FULL_BIT_CYCLES),
(unsigned int) (8.625*FULL_BIT_CYCLES),
(unsigned int) (9.625*FULL_BIT_CYCLES) };
#if ENABLE_TEST_CODE
LOC_TEST_VARS long unsigned int rxErrors = 0;
#endif
#endif
#if RECEIVERS >= 1
_OSLabel(TaskRx1a);
_OSLabel(TaskRx1b);
_OSLabel(TaskRx1c);
_OSLabel(TaskRx1d);
_OSLabel(TaskRx1e);
#endif
#if RECEIVERS >= 2
_OSLabel(TaskRx2a);
_OSLabel(TaskRx2b);
_OSLabel(TaskRx2c);
_OSLabel(TaskRx2d);
_OSLabel(TaskRx2e);
#endif
#if RECEIVERS >= 3
_OSLabel(TaskRx3a);
_OSLabel(TaskRx3b);
_OSLabel(TaskRx3c);
_OSLabel(TaskRx3d);
_OSLabel(TaskRx3e);
#endif
#if RECEIVERS >= 4
_OSLabel(TaskRx4a);
_OSLabel(TaskRx4b);
_OSLabel(TaskRx4c);
_OSLabel(TaskRx4d);
_OSLabel(TaskRx4e);
#endif
/************************************************************
**** ****
** **
BitDelay(timestamp, period)
This is an interesting function. It returns its best-fit
estimate for how many ticks we should delay the receiver
task before sampling the incoming bitstream.
There are several source of error to contend with: 1) system
timer jitter (-1, +0 system ticks), 2) errors resulting from
the quantization of the delay in cycles into system ticks,
3) the number of cycles from when the delay is calculated
to when the task is actually delayed, 4) interrupts and 5)
delays from when the task is made eligible to when it can
actually run.
1) and 2) result in delays that can be too short. 3), 4) and
5) result in delays that can be too long. 1) and 2) are up to
one system tick in size. 3), 4) and 5) are smaller.
By attempting to sample the bitstream one half of one
quarter-cycle after the theoretical mid-time of the data
bit, we hope to increase our chances of sampling between
3/8 and 5/8 into the data bit, i.e. during a one-quarter
bit-time period in the middle of the data bit. Empirical
data suggests this works quite well.
** **
**** ****
************************************************************/
#if RECEIVERS >= 1
OStypeDelay BitDelay( unsigned int timestamp,
unsigned char period )
{
unsigned int tmr;
unsigned int elapsed;
unsigned int desired;
/* capture current instruction cycle count. */
DisableTMR1();
tmr = TMR1;
EnableTMR1();
/* calculate instruction cycles elapsed since time- */
/* stamp. Deal with wrap as necessary. */
/* OVERHEAD is derived from the average number of */
/* instruction cycles from here to exiting the */
/* function, below. */
if ( tmr < timestamp )
elapsed = tmr + 65536 - timestamp;
else
elapsed = tmr - timestamp;
/* obtain the desired total cycle count (in the */
/* future) for when we want to sample the data */
/* again. Adjust slightly for the time we're */
/* spending in here. */
desired = samplePts[period] - elapsed - OVERHEAD;
/* now we know when (in terms of instruction cycles */
/* from now) we want to sample data again. Figure */
/* out how many ticks into the future that is. */
/* this could use some optimization ... but */
/* */
/* return (OStypeDelay) \ */
/* ((4 * desired)/FULL_BIT_CYCLES) */
/* */
/* takes more ROM and is likely to be slower. */
if ( desired < (unsigned int) (0.25*FULL_BIT_CYCLES) )
return 0;
else if ( desired < (unsigned int) (0.50*FULL_BIT_CYCLES) )
return 1;
else if ( desired < (unsigned int) (0.75*FULL_BIT_CYCLES) )
return 2;
else if ( desired < (unsigned int) (1.00*FULL_BIT_CYCLES) )
return 3;
else if ( desired < (unsigned int) (1.25*FULL_BIT_CYCLES) )
return 4;
else if ( desired < (unsigned int) (1.50*FULL_BIT_CYCLES) )
return 5;
else if ( desired < (unsigned int) (1.75*FULL_BIT_CYCLES) )
return 6;
else
/* this catches case of (desired < 0), i.e. */
/* we're too late, as well as (desired > 1 3/4 */
/* bit times. */
return 0xFF;
}
#endif
/************************************************************
**** ****
** **
TaskRx1(timestamp, period)
Receiver task. Is normally stopped, wakes up when interrupt-
driven start bit detector sees start bit go low.
Uses BitDelay() to re-synchronize itself to the start bit.
O/wise looks like a normal software UART, with delays
implemented via OS_Delay() instead of looping.
** **
**** ****
************************************************************/
#if RECEIVERS >= 1
void TaskRx1( void )
{
LOC_RX_LOCALS static char c;
LOC_RX_LOCALS static char i;
OStypeDelay delay;
InitBcb(RX1BCBP, RX1_BUFF_SIZE);
for (;;) {
/* sample incoming data as soon as the start-bit*/
/* detector in the ISR starts this task. We */
/* remain stopped until this happens. */
OS_Stop(TaskRx1a);
/* now that we're here, calculate the right */
/* delay so that when we return we're ready */
/* to sample the next data bit (in this case, */
/* the LSB -- data bit 0). */
delay = BitDelay(rx1Timestamp, 0);
/* if we're too late then we have to give up. */
/* Re-activate start-bit detector one full */
/* character time from now. */
if ( delay == 0xFF ) {
OS_Delay(8*FULL_BIT_TICKS, TaskRx1e);
rxStatus.rx1Active = 0;
continue;
}
/* else we seem to have enough time to delay */
/* and return to sample the data bit. */
else {
ToggleTPRx1SC();
/* if time is really short, don't delay, */
/* o/wise go ahead and delay. */
if ( delay )
OS_Delay(delay, TaskRx1d);
/* we're back, ready to begin sampling data */
/* bits. c need not be initialized since */
/* all 8 bits will be shifted out. */
i = 8;
rxStatus.rx1Error = FALSE;
do {
ToggleTPRx1SC();
c = (c >> 1) | (RX1 << 7);
delay = BitDelay(rx1Timestamp, 9-i);
if ( delay == 0xFF ) {
rxStatus.rx1Error = TRUE;
break;
}
else if ( delay )
OS_Delay(delay, TaskRx1b);
} while (--i);
ToggleTPRx1SC();
/* if the stop bit is still high, we got */
/* valid data. */
if ( RX1 && !rxStatus.rx1Error )
PutRx1Buff(c);
#if ENABLE_TEST_CODE
else
rxErrors++;
#endif
/* done receiving char -- re-enable start */
/* bit detection. No need to control */
/* interrupts, as OSStartTask() can only */
/* start a stopped task, and right now */
/* we're still running. */
rxStatus.rx1Active = 0;
}
/* now we're done receiving a char. Return to */
/* top of loop and remain in the stopped state */
/* until the start-bit detector wakes us up. */
}
}
#endif
/************************************************************
**** ****
** **
TaskRx2/3/4(timestamp, period)
Like TaskRX1(), but operating on the associated input pin
and receive buffer.
** **
**** ****
************************************************************/
#if RECEIVERS >= 2
void TaskRx2( void )
{
LOC_RX_LOCALS static char c;
LOC_RX_LOCALS static char i;
OStypeDelay delay;
InitBcb(RX2BCBP, RX2_BUFF_SIZE);
for (;;) {
OS_Stop(TaskRx2a);
delay = BitDelay(rx2Timestamp, 0);
if ( delay == 0xFF ) {
OS_Delay(8*FULL_BIT_TICKS, TaskRx2e);
rxStatus.rx2Active = 0;
continue;
}
else {
ToggleTPRx2SC();
if ( delay )
OS_Delay(delay, TaskRx2d);
i = 8;
rxStatus.rx2Error = FALSE;
do {
ToggleTPRx2SC();
c = (c >> 1) | (RX2 << 7);
delay = BitDelay(rx2Timestamp, 9-i);
if ( delay == 0xFF ) {
rxStatus.rx2Error = TRUE;
break;
}
else if ( delay )
OS_Delay(delay, TaskRx2b);
} while (--i);
ToggleTPRx2SC();
if ( RX2 && !rxStatus.rx2Error )
PutRx2Buff(c);
#if ENABLE_TEST_CODE
else
rxErrors++;
#endif
rxStatus.rx2Active = 0;
}
}
}
#endif
/***********************************************************/
#if RECEIVERS >= 3
void TaskRx3( void )
{
LOC_RX_LOCALS static char c;
LOC_RX_LOCALS static char i;
OStypeDelay delay;
InitBcb(RX3BCBP, RX3_BUFF_SIZE);
for (;;) {
OS_Stop(TaskRx3a);
delay = BitDelay(rx3Timestamp, 0);
if ( delay == 0xFF ) {
OS_Delay(8*FULL_BIT_TICKS, TaskRx3e);
rxStatus.rx3Active = 0;
continue;
}
else {
ToggleTPRx3SC();
if ( delay )
OS_Delay(delay, TaskRx3d);
i = 8;
rxStatus.rx3Error = FALSE;
do {
ToggleTPRx3SC();
c = (c >> 1) | (RX3 << 7);
delay = BitDelay(rx3Timestamp, 9-i);
if ( delay == 0xFF ) {
rxStatus.rx3Error = TRUE;
break;
}
else if ( delay )
OS_Delay(delay, TaskRx3b);
} while (--i);
ToggleTPRx3SC();
if ( RX3 && !rxStatus.rx3Error )
PutRx3Buff(c);
#if ENABLE_TEST_CODE
else
rxErrors++;
#endif
rxStatus.rx3Active = 0;
}
}
}
#endif
/***********************************************************/
#if RECEIVERS >= 4
void TaskRx4( void )
{
LOC_RX_LOCALS static char c;
LOC_RX_LOCALS static char i;
OStypeDelay delay;
InitBcb(RX4BCBP, RX4_BUFF_SIZE);
for (;;) {
OS_Stop(TaskRx4a);
delay = BitDelay(rx4Timestamp, 0);
if ( delay == 0xFF ) {
OS_Delay(8*FULL_BIT_TICKS, TaskRx4e);
rxStatus.rx4Active = 0;
continue;
}
else {
ToggleTPRx4SC();
if ( delay )
OS_Delay(delay, TaskRx4d);
i = 8;
rxStatus.rx4Error = FALSE;
do {
ToggleTPRx4SC();
c = (c >> 1) | (RX4 << 7);
delay = BitDelay(rx4Timestamp, 9-i);
if ( delay == 0xFF ) {
rxStatus.rx4Error = TRUE;
break;
}
else if ( delay )
OS_Delay(delay, TaskRx4b);
} while (--i);
ToggleTPRx4SC();
if ( RX4 && !rxStatus.rx4Error )
PutRx4Buff(c);
#if ENABLE_TEST_CODE
else
rxErrors++;
#endif
rxStatus.rx4Active = 0;
}
}
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -