📄 main.c
字号:
//
// monitorChannel() - Resynchronize or change channels as needed
//
// Periodically evaluate Rx Packet average. Average reflects the number of
// missed voice samples (ie: BOTH slots were bad and speaker audio was lost).
//
// The risetime of the FAST average (rxPktAve_Q3) is ~16 samples or ~50 mS
// The risetime of the SLOW average (rxPktAve_Q8) is ~560 samples or ~1.5 sec
//
// The FAST average detects total signal loss quickly, while the SLOW average
// detects maginal signal quality.
//
// ---------------------------------------------------------------------------
// When perfect, Gast average rxPktAve_Q3 = 127 or (15*8)
#define BAD_FAST (rxPktAve_Q3 < 32) // 32 = BAD_SLOW = 25% * FastPerfect
// When perfect, Slow average rxPktAve_Q8 = 127 or (127*256/256)
#define BAD_SLOW (rxPktAve_Q8 < 121) // 121 = BAD_FAST = 95% * SlowPerfect
static void monitorChannel(void) {
if (BAD_FAST || BAD_SLOW) {
if (BAD_SLOW) { // If SLOW trigger, then always change chan
nxtVoiceCh(); // because after resync, assume PERFECT
}
slotCt = 0xFF; // synchronize at next ISR
while (slotCt == 0xFF); // Wait for ISR to synchronize
rxPktAve_Q8 = 127; // Slow filter starts PERFECT
}
}
/////////////////////////////////////////////////////////////////////////////
// ---------------------------------------------------------------------------
//
// serveSw1() - Monitor SW1 for activity
//
// ---------------------------------------------------------------------------
//BYTE serveSw1(void) {
// static WORD swTimer;
// static BYTE swState;
// #define SW1_OFF 0
// #define SW1_GOING_ON 1
// #define SW1_ON 2
// #define SW1_GOING_OFF 3
// BYTE retval = SW1_IDLE;
//
// switch (swState) {
// case SW1_OFF:
// if (IS_SW1_ON) {
// swState = SW1_GOING_ON;
// timeSet(&swTimer, 10); // 3 * 10 mS debounce
// }
// break;
// case SW1_GOING_ON:
// if (IS_SW1_ON) {
// if (timeExpired(&swTimer)) {
// swState = SW1_ON;
// retval = SW1_JUST_ON;
// }
// }
// else {
// swState = SW1_OFF; // Switch bounced, ingore
// }
// break;
// case SW1_ON:
// if (IS_SW1_OFF) {
// swState = SW1_GOING_OFF;
// timeSet(&swTimer, 10); // 3 * 10 mS debounce
// }
// retval = SW1_IS_ON;
// break;
// case SW1_GOING_OFF:
// if (IS_SW1_OFF) {
// if (timeExpired(&swTimer)) {
// retval = SW1_JUST_OFF;
// swState = SW1_OFF;
// }
// }
// else {
// swState = SW1_ON; // Switch bounced, ingore
// }
// break;
// }
// return(retval);
//}
extern BYTE testDelta;
// ---------------------------------------------------------------------------
//
// Service arriving PCM data from PC
//
// ---------------------------------------------------------------------------
static void doUsbOut(void) {
WORD *ptmp;
BYTE count;
signed char ivar;
static BYTE ledScaler;
// -----------------------------------------------------------------------
// If endpoint has data, then copy it to RAM page
// -----------------------------------------------------------------------
if (INT_CLR2 & INT_MSK2_EP2)
{
INT_CLR2 &= ~INT_MSK2_EP2;
count = USB_bReadOutEP(2, (BYTE *)usbOutIn, USB_EPOUT_BYTE_LEN);
USB_EnableOutISOCEP(2);
// -------------------------------------------------------------------
// Preprocess 8 samples just loaded
// 1) Convert data from 2's complement to unipolar
// 0x8000 --> 0x0000 ( 0 scale voltage)
// 0xFFFF --> 0x7FFF (0.5 scale voltage - 1)
// 0x0000 --> 0x8000 (0.5 scale voltage)
// 0x7FFF --> 0xFFFF (1.0 scale voltage)
// 2) Convert to 15-bit number
// High bit will eventually indicate insert/delete point
// -------------------------------------------------------------------
usbOutIn = outPreprocess(usbOutIn); // Also circular advance ptr
// if (testDelta == 0) LED_RED_ON; //; TEST ONLY
// else LED_RED_OFF; //; TEST ONLY
if (++ledScaler == 120)
{
LED_RED_ON;
}
else if (ledScaler == 130)
{
LED_RED_OFF;
ledScaler = 0;
}
}
// -----------------------------------------------------------------------
// Insert or delete PCM sample to maintain nominal PCM buffer depth
// -----------------------------------------------------------------------
ivar = usbOutIn - usbOutOt; // ivar = # words in buffer
if (ivar < 0) // If negative, it's more than 50%
ivar += USB_BUF_SIZE;
if (ivar > 24*4) // ivar = # samples in buffer
{
// search backwards 24 samples from usbOutIn to locate closest values
// delete ONE sample from buffer
decUsbOutInCyclic();
++outDeleteCt;
// LED_RED_ON;
// LED_RED_OFF;
}
else if (ivar < 24*2)
{
// search backwards 24 samples from usbOutOt to locate closest values
// insert ONE sample to buffer
*usbOutIn = 0x4000; // 0.5 scale (15-bit unipolar for ADPCM)
incUsbOutInCyclic();
++outInsertCt;
// LED_RED_ON;
LED_RED_OFF;
}
}
static BYTE findClosest(BYTE *pBuf)
{
return(0);
}
// ---------------------------------------------------------------------------
//
// Service departing PCM data to PC
//
// ---------------------------------------------------------------------------
static void doUsbIn(void) {
if (asmIsUsbInEnough() == TRUE // If enough data in buffer
&& (INT_CLR2 & INT_MSK2_EP1) != 0 // If endpoint is is empty
) {
INT_CLR2 &= ~INT_MSK2_EP1;
USB_LoadInISOCEP(1, (BYTE*)&usbInOt[0], 16, USB_TOGGLE);
asmUsbInOtAdv();
LED_RED_OFF;
}
}
/////////////////////////////////////////////////////////////////////////////
void timeSet(WORD *pTimer, WORD time) // 3 mS per count
{
WORD VoipCt;
do { // ISR may update this 16-bit value and PSoC
VoipCt = voipCt; // doesn't have atomic access,
} while (VoipCt != voipCt); // so read until stable
*pTimer = VoipCt + time;
}
BOOL timeExpired(WORD *pTimer)
{
WORD delta;
WORD VoipCt;
do { // ISR may update this 16-bit value and PSoC
VoipCt = voipCt; // doesn't have atomic access,
} while (VoipCt != voipCt); // so read until stable
delta = *pTimer - VoipCt;
if (((BYTE)(delta>>8)&0x80) == 0) return FALSE; // not expired
else return TRUE; // expired
}
// ---------------------------------------------------------------------------
//
// doRs232Stats() - Create UART debug data stream.
//
// The 4800,n,8,1 UART attached in the 8KHz ISR sends a 10-bit character
// every 3 mS (24 interrupts). Since 1/4800 Hz = 208 uS and the 8KHz ISR
// is every 125 uS, the bits are generated about every 1.67 interrupts
// (this is approximated by either every other or every interrupt).
//
// Every 3 mS, an unbuffered character is sent from the "holding register".
//
// ---------------------------------------------------------------------------
static void doRs232Stats(void)
{
#pragma data:Page3Data
static BYTE charState;
static WORD num0; //
static WORD num1; // Static copy of data to decompose
static WORD num2; // Static copy of data to decompose
static BYTE delta;
static BYTE neg;
static BYTE min;
static BYTE num8;
static BYTE num9;
#pragma data:data
switch (charState) {
case 0:
uartTxD = CR;
num0 = hexdec(voiceCh+1); // RF is 1 MHz above CHANNEL_ADR
num1 = mibMissRx_1 > 0xFFF ? 0xFFF : mibMissRx_1; // saturate
num2 = mibMissRx_2 > 0x0FF ? 0x0FF : mibMissRx_2; // saturate
num8 = hexdec(rssiAveA_Q3>>3); // Ave RSSI: Antenna A
// num9 = rxPktAve_Q3>>3;
num9 = rxPktAve_Q8;
// ---------------------------------------------------------------
// Get RSSI difference between each antenna time-slot
// Get worst RSSI of best antenna
// ---------------------------------------------------------------
delta = 0x99; // default to meaningless Delta
#define RESET_MIN 0xFF
if (tstRssiMin1 == RESET_MIN) min = hexdec(tstRssiMin0);
else if (tstRssiMin0 == RESET_MIN) min = hexdec(tstRssiMin1);
else if (tstRssiMin0 >= tstRssiMin1) {
delta = hexdec(tstRssiMin0 - tstRssiMin1);
neg = 0; // positive delta
min = hexdec(tstRssiMin0);
}
else {
delta = hexdec(tstRssiMin1 - tstRssiMin0);
neg = 1; // negative delta
min = hexdec(tstRssiMin1);
}
tstRssiMin0 = tstRssiMin1 = RESET_MIN;
tstRssiMax0 = tstRssiMax1 = 0x00;
break;
case 1 : uartTxD = LF; break;
case 2 : uartTxD = hexAscMsn((BYTE)(num0)); break;
case 3 : uartTxD = hexAscLsn((BYTE)(num0)); break;
case 4 : uartTxD = ' '; break;
case 5 : uartTxD = hexAscLsn((BYTE)(num1>>8)); break;
case 6 : uartTxD = hexAscMsn((BYTE)(num1>>0)); break;
case 7 : uartTxD = hexAscLsn((BYTE)(num1>>0)); break;
case 8 : uartTxD = ':'; break;
case 9 : uartTxD = hexAscMsn((BYTE)(num2>>0)); break;
case 10: uartTxD = hexAscLsn((BYTE)(num2>>0)); break;
case 11: uartTxD = neg == 0 ? ' ':'-'; break;
case 12: uartTxD = hexAscMsn(delta); break;
case 13: uartTxD = hexAscLsn(delta); break;
case 14: uartTxD = ' '; break;
case 15: uartTxD = hexAscMsn(min); break; // Max of the Min
case 16: uartTxD = hexAscLsn(min); break;
case 17: uartTxD = ' '; break;
case 18: uartTxD = hexAscMsn(num8); break;
case 19: uartTxD = hexAscLsn(num8); break;
case 20: uartTxD = ' '; break;
case 21: uartTxD = hexAscMsn(num9); break;
case 22: uartTxD = hexAscLsn(num9);
// fallthru
default: charState = 0xFF; break;
}
++charState;
}
// ###########################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -