Add define `PROFILE` and code to show CPU usage

https://github.com/probonopd/MiniDexed/issues/12#issuecomment-1051853664
Thanks @rsta2
pull/30/head
probonopd 3 years ago
parent 997d1c9f5f
commit cdd603091b
  1. 3
      src/Makefile
  2. 37
      src/minidexed.cpp
  3. 50
      src/perftimer.cpp
  4. 30
      src/perftimer.h

@ -5,7 +5,8 @@
CIRCLE_STDLIB_DIR = ../circle-stdlib CIRCLE_STDLIB_DIR = ../circle-stdlib
SYNTH_DEXED_DIR = ../Synth_Dexed/src SYNTH_DEXED_DIR = ../Synth_Dexed/src
OBJS = main.o kernel.o minidexed.o pckeyboard.o $(SYNTH_DEXED_DIR)/synth_dexed.o OBJS = main.o kernel.o minidexed.o pckeyboard.o $(SYNTH_DEXED_DIR)/synth_dexed.o \
perftimer.o
INCLUDE += -I $(SYNTH_DEXED_DIR) INCLUDE += -I $(SYNTH_DEXED_DIR)

@ -2,10 +2,12 @@
// minidexed.cpp // minidexed.cpp
// //
#include "minidexed.h" #include "minidexed.h"
#include "perftimer.h"
#include <circle/devicenameservice.h> #include <circle/devicenameservice.h>
#include <stdio.h> #include <stdio.h>
#define MIDI_DUMP #define MIDI_DUMP
#define PROFILE
#define MIDI_NOTE_OFF 0b1000 #define MIDI_NOTE_OFF 0b1000
#define MIDI_NOTE_ON 0b1001 #define MIDI_NOTE_ON 0b1001
@ -17,6 +19,10 @@ CMiniDexed *CMiniDexed::s_pThis = 0;
extern uint8_t voices_bank[1][32][156]; extern uint8_t voices_bank[1][32][156];
#ifdef PROFILE
CPerformanceTimer GetChunkTimer ("GetChunk", 1000000U * CHUNK_SIZE/2 / SAMPLE_RATE);
#endif
bool CMiniDexed::Initialize (void) bool CMiniDexed::Initialize (void)
{ {
if (!m_Serial.Initialize(31250)) if (!m_Serial.Initialize(31250))
@ -33,6 +39,10 @@ bool CMiniDexed::Initialize (void)
void CMiniDexed::Process(boolean bPlugAndPlayUpdated) void CMiniDexed::Process(boolean bPlugAndPlayUpdated)
{ {
#ifdef PROFILE
GetChunkTimer.Dump ();
#endif
if (m_pMIDIDevice != 0) if (m_pMIDIDevice != 0)
{ {
return; return;
@ -193,6 +203,10 @@ bool CMiniDexedPWM::Initialize (void)
unsigned CMiniDexedPWM::GetChunk(u32 *pBuffer, unsigned nChunkSize) unsigned CMiniDexedPWM::GetChunk(u32 *pBuffer, unsigned nChunkSize)
{ {
#ifdef PROFILE
GetChunkTimer.Start();
#endif
unsigned nResult = nChunkSize; unsigned nResult = nChunkSize;
int16_t int16_buf[nChunkSize/2]; int16_t int16_buf[nChunkSize/2];
@ -209,6 +223,11 @@ unsigned CMiniDexedPWM::GetChunk(u32 *pBuffer, unsigned nChunkSize)
*pBuffer++ = nSample; // 2 stereo channels *pBuffer++ = nSample; // 2 stereo channels
*pBuffer++ = nSample; *pBuffer++ = nSample;
} }
#ifdef PROFILE
GetChunkTimer.Stop();
#endif
return(nResult); return(nResult);
}; };
@ -224,6 +243,10 @@ bool CMiniDexedI2S::Initialize (void)
unsigned CMiniDexedI2S::GetChunk(u32 *pBuffer, unsigned nChunkSize) unsigned CMiniDexedI2S::GetChunk(u32 *pBuffer, unsigned nChunkSize)
{ {
#ifdef PROFILE
GetChunkTimer.Start();
#endif
unsigned nResult = nChunkSize; unsigned nResult = nChunkSize;
int16_t int16_buf[nChunkSize/2]; int16_t int16_buf[nChunkSize/2];
@ -238,6 +261,11 @@ unsigned CMiniDexedI2S::GetChunk(u32 *pBuffer, unsigned nChunkSize)
*pBuffer++ = nSample; // 2 stereo channels *pBuffer++ = nSample; // 2 stereo channels
*pBuffer++ = nSample; *pBuffer++ = nSample;
} }
#ifdef PROFILE
GetChunkTimer.Stop();
#endif
return(nResult); return(nResult);
}; };
@ -253,6 +281,10 @@ bool CMiniDexedHDMI::Initialize (void)
unsigned CMiniDexedHDMI::GetChunk(u32 *pBuffer, unsigned nChunkSize) unsigned CMiniDexedHDMI::GetChunk(u32 *pBuffer, unsigned nChunkSize)
{ {
#ifdef PROFILE
GetChunkTimer.Start();
#endif
unsigned nResult = nChunkSize; unsigned nResult = nChunkSize;
int16_t int16_buf[nChunkSize/2]; int16_t int16_buf[nChunkSize/2];
@ -273,5 +305,10 @@ unsigned CMiniDexedHDMI::GetChunk(u32 *pBuffer, unsigned nChunkSize)
*pBuffer++ = nSample; // 2 stereo channels *pBuffer++ = nSample; // 2 stereo channels
*pBuffer++ = nSample; *pBuffer++ = nSample;
} }
#ifdef PROFILE
GetChunkTimer.Stop();
#endif
return(nResult); return(nResult);
}; };

@ -0,0 +1,50 @@
//
// perftimer.cpp
//
#include "perftimer.h"
#include <iostream>
CPerformanceTimer::CPerformanceTimer (const char *pName, unsigned nDeadlineMicros)
: m_Name (pName),
m_nDeadlineMicros (nDeadlineMicros),
m_nMaximumMicros (0),
m_nLastDumpTicks (0)
{
}
void CPerformanceTimer::Start (void)
{
m_nStartTicks = CTimer::GetClockTicks ();
}
void CPerformanceTimer::Stop (void)
{
unsigned nEndTicks = CTimer::GetClockTicks ();
unsigned nMicros = (nEndTicks - m_nStartTicks) / (CLOCKHZ / 1000000);
if (nMicros > m_nMaximumMicros)
{
m_nMaximumMicros = nMicros;
}
}
void CPerformanceTimer::Dump (unsigned nIntervalTicks)
{
unsigned nTicks = CTimer::GetClockTicks ();
if (nTicks - m_nLastDumpTicks >= nIntervalTicks)
{
m_nLastDumpTicks = nTicks;
unsigned nMaximumMicros = m_nMaximumMicros; // may be overwritten from interrupt
std::cout << m_Name << ": Maximum duration was " << nMaximumMicros << "us";
if (m_nDeadlineMicros != 0)
{
std::cout << " (" << nMaximumMicros*100 / m_nDeadlineMicros << "%)";
}
std::cout << std::endl;
}
}

@ -0,0 +1,30 @@
//
// perftimer.h
//
#ifndef _perftimer_h
#define _perftimer_h
#include <string>
#include <circle/timer.h>
class CPerformanceTimer
{
public:
CPerformanceTimer (const char *pName, unsigned nDeadlineMicros = 0);
void Start (void);
void Stop (void);
void Dump (unsigned nIntervalTicks = CLOCKHZ);
private:
std::string m_Name;
unsigned m_nDeadlineMicros;
unsigned m_nStartTicks;
unsigned m_nMaximumMicros;
unsigned m_nLastDumpTicks;
};
#endif
Loading…
Cancel
Save