示例#1
0
文件: alarm.c 项目: aeliot/openthread
inline uint64_t nrf5AlarmGetCurrentTime()
{
    uint32_t rtcValue1;
    uint32_t rtcValue2;
    uint32_t offset;

    rtcValue1 = nrf_rtc_counter_get(RTC_INSTANCE);

    __DMB();

    offset = sTimeOffset;

    __DMB();

    rtcValue2 = nrf_rtc_counter_get(RTC_INSTANCE);

    if ((rtcValue2 < rtcValue1) || (rtcValue1 == 0))
    {
        // Overflow detected. Additional condition (rtcValue1 == 0) covers situation when overflow occurred in
        // interrupt state, before this function was entered. But in general, this function shall not be called
        // from interrupt other than alarm interrupt.

        // Wait at least 20 cycles, to ensure that if interrupt is going to be called, it will be called now.
        for (uint32_t i = 0; i < 4; i++)
        {
            __NOP();
            __NOP();
            __NOP();
        }

        // If the event flag is still on, it means that the interrupt was not called, as we are in interrupt state.
        if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW))
        {
            HandleOverflow();
        }

        offset = sTimeOffset;
    }

    return US_PER_MS * (uint64_t)offset + TicksToTime(rtcValue2);
}
示例#2
0
CMIDISource::CMIDISource(CMediaSource *pSource, int nIndex) : CMediaSource(pSource, nIndex)
{
	char str[5];
	int i;
	StreamPos *pPos;
	MIDITrack *pTrack;
	TempoEvent *pEvent;
	unsigned char pData[1024];
	int nSize;

	m_pStreamPos = NULL;
	m_pTracks = NULL;
	m_pTempoEvents = NULL;
	m_nDuration = 0;

	str[4] = '\0';
	SourceReadData(str, 4);
	if (strcmp(str, "MThd") != 0)
		return;
	if (SourceReadBigEndian(4) != 6)  //header length
		return;

	m_MIDIInfo.nFormat = SourceReadBigEndian(2);
	m_nOutputNum = SourceReadBigEndian(2);  //number of track
	m_nTicksPerQuarterNote = SourceReadBigEndian(2);
	m_pStreamPos = new StreamPos[m_nOutputNum];
	m_pTracks = new MIDITrack[m_nOutputNum];
	for (i = 0; i < m_nOutputNum; i++)
	{
		pPos = m_pStreamPos + i;
		SourceReadData(str, 4);  //track id
		pPos->nSize = SourceReadBigEndian(4);  //track length
		if (strcmp(str, "MTrk") == 0)
			pPos->nHeadPos = SourceGetPosition();
		else
			pPos->nHeadPos = 0;  //invalid track
		SourceSeekData(pPos->nSize, SEEK_CUR);  //skip to next track
	}

	if (m_nOutputNum == 0)
		return;

	pTrack = m_pTracks;  //first track;
	m_pTempoEvents = new TempoEvent[m_pStreamPos[0].nSize / 6];  //minimum size of a change tempo event is 6
	m_nTempoEventNum = 1;
	pEvent = m_pTempoEvents;
	pEvent->nTempo = 500000;  //default tempo in microseconds per quarter note
	pEvent->nTicks = 0;
	pEvent->nTime = 0;

	SeekTime(0);
	for (;;)
	{
		nSize = ReadData(0, pData, sizeof(pData));
		if (nSize == 0)
			break;

		if (pData[0] == 0xFF && pData[1] == 0x51)  //set tempo
		{
			pEvent = m_pTempoEvents + m_nTempoEventNum;
			pEvent->nTempo = (pData[2] << 16) | (pData[3] << 8) | pData[4];  //microseconds per quarter note
			pEvent->nTicks = pTrack->nTicks;
			pEvent->nTime = TicksToTime(pTrack->nTicks);
			++m_nTempoEventNum;
		}
	}

	m_nDuration = m_pStreamPos[0].nTime;
	for (i = 1; i < m_nOutputNum; i++)  //for each track except the first one
	{
		do
		{
			nSize = ReadData(i, pData, sizeof(pData));
		} while (nSize > 0);  //until the last event of this track
		if (m_pStreamPos[i].nTime > m_nDuration)
			m_nDuration = m_pStreamPos[i].nTime;
	}
	SeekTime(0);
}
示例#3
0
int CMIDISource::ReadData(int nIndex, void *pData, int nSize)
{
	StreamPos *pPos;
	unsigned char *pBuffer;
	MIDITrack *pTrack;
	int nStatus;
	int nValue;

	if (nIndex >= m_nOutputNum)
		return 0;

	pPos = m_pStreamPos + nIndex;
	if (pPos->nHeadPos == 0)  //invalid track
		return 0;
	if (pPos->nRelPos >= pPos->nSize)
		return 0;

	SourceSeekData(pPos->nAbsPos, SEEK_SET);
	pBuffer = (unsigned char *)pData;
	pTrack = m_pTracks + nIndex;

	pTrack->nTicks += ReadVarLen();  //delta time
	nStatus = SourceReadData();
	if (nStatus >= 0xF0 && nStatus < 0xFF)  //system exclusive event
	{
		pBuffer[0] = nStatus;
		nValue = ReadVarLen();
		SourceReadData(pBuffer + 1, nValue);
		assert(nSize >= 1 + nValue);
		if (nSize > 1 + nValue)
			nSize = 1 + nValue;
	}
	else
	{
		if ((nStatus & 0x80) == 0)  //running status
		{
			pBuffer[0] = pTrack->nStatus;
			pBuffer[1] = nStatus;
		}
		else  //MIDI event or meta event
		{
			pTrack->nStatus = nStatus;
			pBuffer[0] = nStatus;
			pBuffer[1] = SourceReadData();
		}
		switch (pBuffer[0] & 0xF0)
		{
			case 0x80:
			case 0x90:
			case 0xA0:
			case 0xB0:
			case 0xE0:
				pBuffer[2] = SourceReadData();
				nSize = 3;
				break;
			case 0xC0:
			case 0xD0:
				nSize = 2;
				break;
			case 0xF0:
				nValue = ReadVarLen();  //data length
				SourceReadData(pBuffer + 2, nValue);
				assert(nSize >= 2 + nValue);
				if (nSize > 2 + nValue)
					nSize = 2 + nValue;
				break;
			default:
				nSize = 0;
				break;
		}  //switch
	}  //else

	pPos->nAbsPos = SourceGetPosition();
	pPos->nRelPos = pPos->nAbsPos - pPos->nHeadPos;
	pPos->nTime = TicksToTime(pTrack->nTicks);
	if (pPos->nTime < m_nSeekTime)  //event before seektime
	{
		pPos->nTime = 0;  //render immediately
		if (pBuffer[0] >= 0x80 && pBuffer[0] <= 0x9F)  //note on or note off
			pBuffer[0] = 0x00;  //invalid event, should not be renderered
	}

	return nSize;
}