📄 rds.c
字号:
}
else if(rtTmp0[i] == 0x0d)
{
break;
}
}
if (complete)
{
// Copy the message to the display
for (j=0;j<i;j++)
{
rtDisplay[j] = rtTmp0[j];
rtTmp0[j] = 0;
}
// Clear everything after the end-of-message flag
for (;j<sizeof(rtDisplay);j++)
{
rtDisplay[j] = 0;
}
}
}
//-----------------------------------------------------------------------------
// This implelentation of the Radio Text update attempts to display
// only complete messages even if the A/B flag does not toggle as well
// as provide additional error detection.
//-----------------------------------------------------------------------------
#define RT_VALIDATE_LIMIT 2
static void
display_rt(void)
{
bit rtComplete = 1;
u8 i;
// The Radio Text is incomplete if any character in the high
// probability array has been seen fewer times than the
// validation limit.
for (i=0; i<sizeof(rtTmp0);i++)
{
if(rtCnt[i] < RT_VALIDATE_LIMIT)
{
rtComplete = 0;
break;
}
if(rtTmp0[i] == 0x0d)
{
// The array is shorter than the maximum allowed
break;
}
}
// If the Radio Text in the high probability array is complete
// copy it to the display array
if (rtComplete)
{
for (i=0;i<sizeof(rtDisplay); i++)
{
rtDisplay[i] = rtTmp0[i];
if(rtTmp0[i] == 0x0d)
{
break;
}
}
// Wipe out everything after the end-of-message marker
for (i++;i<sizeof(rtDisplay);i++)
{
rtDisplay[i] = 0;
rtCnt[i] = 0;
rtTmp0[i] = 0;
rtTmp1[i] = 0;
}
}
}
static void
update_rt(bit abFlag, u8 count, u8 addr, u8* byte)
{
u8 i;
bit textChange = 0; // indicates if the Radio Text is changing
if (abFlag != rtFlag && rtFlagValid)
{
// If the A/B message flag changes, try to force a display
// by increasing the validation count of each byte
for (i=0;i<sizeof(rtCnt);i++)
{
rtCnt[addr+i]++;
}
display_rt();
// Wipe out the cached text
for (i=0;i<sizeof(rtCnt);i++)
{
rtCnt[i] = 0;
rtTmp0[i] = 0;
rtTmp1[i] = 0;
}
}
rtFlag = abFlag; // Save the A/B flag
rtFlagValid = 1; // Our copy of the A/B flag is now valid
for(i=0;i<count;i++)
{
if(!byte[i])
{
byte[i] = ' '; // translate nulls to spaces
}
// The new byte matches the high probability byte
if(rtTmp0[addr+i] == byte[i])
{
if(rtCnt[addr+i] < RT_VALIDATE_LIMIT)
{
rtCnt[addr+i]++;
}
else
{
// we have recieved this byte enough to max out our counter
// and push it into the low probability array as well
rtCnt[addr+i] = RT_VALIDATE_LIMIT;
rtTmp1[addr+i] = byte[i];
}
}
else if(rtTmp1[addr+i] == byte[i])
{
// The new byte is a match with the low probability byte. Swap
// them, reset the counter and flag the text as in transition.
// Note that the counter for this character goes higher than
// the validation limit because it will get knocked down later
rtCnt[addr+i] = RT_VALIDATE_LIMIT + 1;
rtTmp1[addr+i] = rtTmp0[addr+i];
rtTmp0[addr+i] = byte[i];
textChange = 1;
}
else if(!rtCnt[addr+i])
{
// The new byte is replacing an empty byte in the high
// proability array
rtTmp0[addr+i] = byte[i];
rtCnt[addr+i] = 1;
}
else
{
// The new byte doesn't match anything, put it in the
// low probablity array.
rtTmp1[addr+i] = byte[i];
}
}
if(textChange)
{
// When the text is changing, decrement the count for all
// characters to prevent displaying part of a message
// that is in transition.
for(i=0;i<sizeof(rtCnt);i++)
{
if(rtCnt[i] > 1)
{
rtCnt[i]--;
}
}
}
// Display the Radio Text
display_rt();
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
static void
update_alt_freq(u16 current_alt_freq)
{
// unimplemented
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void
updateRds(void)
{
u8 group_type; // bits 4:1 = type, bit 0 = version
u8 addr;
u8 errorCount;
bit abflag;
RdsDataAvailable = 0;
// read rds registers
si470x_reg_read(10, 15); // update rds registers
errorCount = (si470x_shadow[0xa] & 0x0e00) >> 9;
if (errorCount < 4)
{
RdsBlocksValid += (4 - errorCount);
}
// Drop the data if there are any errors
if (errorCount)
{
return;
}
RdsIndicator = 100; // Reset RdsIndicator
LED = ~LED; // Toggle LED
group_type = si470x_shadow[0xd]>>11; // upper five bits are the group type and version
debug_group_counters[group_type] += 1;
// Update pi code. Version B formats always have the pi code in words A and C
update_pi (si470x_shadow[0xc]);
if (group_type & 0x01)
{
update_pi(si470x_shadow[0xe]);
}
// update pty code.
update_pty((si470x_shadow[0xd]>>5) & 0x1f); // gdc: fix this so all 16 bits are passed and other bits are also updated here?
switch (group_type) {
case RDS_TYPE_0A:
update_alt_freq(si470x_shadow[0xe]);
// fallthrough
case RDS_TYPE_0B:
addr = (si470x_shadow[0xd]&0x3)*2;
if(rdsBasic)
{
update_ps_basic(addr+0, si470x_shadow[0xf] >> 8 );
update_ps_basic(addr+1, si470x_shadow[0xf] & 0xff);
}
else
{
update_ps(addr+0, si470x_shadow[0xf] >> 8 );
update_ps(addr+1, si470x_shadow[0xf] & 0xff);
}
break;
case RDS_TYPE_2A:
addr = (si470x_shadow[0xd] & 0xf) * 4;
//??abflag = (si470x_shadow[0xb] & 0x0010) >> 4;
if(rdsBasic)
{
update_rt_basic(abflag, 4, addr, (u8*)&(si470x_shadow[0xe]));
}
else
{
update_rt(abflag, 4, addr, (u8*)&(si470x_shadow[0xe]));
}
break;
case RDS_TYPE_2B:
addr = (si470x_shadow[0xd] & 0xf) * 2;
abflag = (si470x_shadow[0xb] & 0x0010) >> 4;
// The last 32 bytes are unused in this format
rtTmp0[32] = 0x0d;
rtTmp1[32] = 0x0d;
rtCnt[32] = RT_VALIDATE_LIMIT;
if(rdsBasic)
{
update_rt_basic(abflag, 2, addr, (u8*)&(si470x_shadow[0xe]));
}
else
{
update_rt(abflag, 2, addr, (u8*)&(si470x_shadow[0xe]));
}
break;
default:
break;
}
}
void
rdsGetIndicator(u8 *indicator)
{
*indicator = !!RdsIndicator;
}
void
rdsGetBler(u16 *bler)
{
if (RdsBlocksTotal < RdsBlocksValid)
{
// The timer which generates the total block count is not synchronized
// to the RDS signal, so occasionally it looks like we received more
// valid blocks than we should have. In this case, just assume no
// errors.
*bler = 0;
}
else if (!RdsBlocksTotal)
{
// If the timer has not fired, we will assume 100% errors
*bler = BLER_SCALE_MAX;
}
else
{
// Calculate the block error rate
*bler = BLER_SCALE_MAX - ((RdsBlocksValid * BLER_SCALE_MAX) / RdsBlocksTotal);
}
}
// ISR for /INT0
void GPIO2_ISR(void) interrupt 0
{
RdsDataAvailable++;
// If more than one group is available then one has been lost
if (RdsDataAvailable > 1)
{
RdsDataLost++;
}
}
// ISR for counting total number of expected RDS blocks
void RDS_TIMER_ISR(void) interrupt 5
{
RdsBlocksTotal++;
if (RdsBlocksTotal > (0xFFFF / BLER_SCALE_MAX))
{
// Drop about 6% blocks from totals
RdsBlocksTotal = (RdsBlocksTotal * 15) / 16;
RdsBlocksValid = (RdsBlocksValid * 15) / 16;
}
if (RdsIndicator)
{
// Make the RdsIndicator decay if no valid data
// has been seen for a while
RdsIndicator--;
}
TF2H = 0;
TF2L = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -