⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rds.c

📁 美国模拟混合器件领导厂商Silabs 芯科实验室 收音机系列 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		}
		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 + -