cwIo.h/cpp : Added timer implementation.

This commit is contained in:
kevin 2021-04-10 13:37:07 -04:00
parent df29219edf
commit c66b1f4470
2 changed files with 277 additions and 28 deletions

262
cwIo.cpp
View File

@ -37,6 +37,16 @@ namespace cw
{
struct io_str;
typedef struct timer_str
{
struct io_str* io;
bool deletedFl;
bool startedFl;
char* label;
unsigned id;
unsigned periodMicroSec;
} timer_t;
typedef struct serialPort_str
{
@ -91,6 +101,9 @@ namespace cw
thread_mach::handle_t threadMachH;
object_t* cfg;
timer_t* timerA;
unsigned timerN;
serialPort_t* serialA;
unsigned serialN;
@ -127,6 +140,99 @@ namespace cw
io_t* _handleToPtr( handle_t h )
{ return handleToPtr<handle_t,io_t>(h); }
//----------------------------------------------------------------------------------------------------------
//
// Timer
//
bool _timerThreadCb( void* arg )
{
timer_t* t = (timer_t*)arg;
sleepUs( t->periodMicroSec );
if( t->startedFl && !t->deletedFl )
{
msg_t m;
timer_msg_t tm;
tm.id = t->id;
m.tid = kTimerTId;
m.u.timer = &tm;
t->io->cbFunc( t->io->cbArg, &m );
}
return !t->deletedFl;
}
rc_t _timerCreate( io_t* p, const char* label, unsigned id, unsigned periodMicroSec )
{
rc_t rc = kOkRC;
timer_t* t = nullptr;
// look for a deleted timer
for(unsigned i=0; i<p->timerN; ++i)
if( p->timerA[i].deletedFl )
{
t = p->timerA + i;
break;
}
// if no deleted timer was found
if( t == nullptr )
{
// reallocate the timer array with an additional slot
timer_t* tA = mem::allocZ< timer_t >( p->timerN + 1 );
for(unsigned i=0; i<p->timerN; ++i)
tA[i] = p->timerA[i];
// keep a pointer to the empty slot
t = tA + p->timerN;
// update the timer array
mem::release( p->timerA );
p->timerA = tA;
p->timerN = p->timerN + 1;
}
assert( t != nullptr );
t->io = p;
t->label = mem::duplStr(label);
t->id = id;
t->periodMicroSec = periodMicroSec;
if((rc = thread_mach::add(p->threadMachH,_timerThreadCb,t)) != kOkRC )
{
rc = cwLogError(rc,"Timer thread assignment failed.");
}
return rc;
}
timer_t* _timerIndexToPtr( io_t* p, unsigned timerIdx )
{
if( timerIdx >= p->timerN || p->timerA[ timerIdx ].deletedFl == true )
{
cwLogError(kInvalidIdRC,"The timer index '%i' is invalid.", timerIdx );
return nullptr;
}
return p->timerA + timerIdx;
}
rc_t _timerStart( io_t* p, unsigned timerIdx, bool startFl )
{
rc_t rc = kOkRC;
timer_t* t = _timerIndexToPtr(p,timerIdx);
if( t == nullptr )
rc = kInvalidIdRC;
else
p->timerA[ timerIdx ].startedFl = startFl;
return rc;
}
//----------------------------------------------------------------------------------------------------------
//
@ -252,19 +358,28 @@ namespace cw
//
void _midiCallback( const midi::packet_t* pktArray, unsigned pktCnt )
{
unsigned i,j;
unsigned i;
for(i=0; i<pktCnt; ++i)
{
const midi::packet_t* pkt = pktArray + i;
//io_t* p = reinterpret_cast<io_t*>(pkt->cbDataPtr);
msg_t m;
midi_msg_t mm;
const midi::packet_t* pkt = pktArray + i;
io_t* p = reinterpret_cast<io_t*>(pkt->cbDataPtr);
for(j=0; j<pkt->msgCnt; ++j)
mm.pkt = pkt;
m.tid = kMidiTId;
m.u.midi = &mm;
p->cbFunc( p->cbArg, &m );
/*
for(unsigned j=0; j<pkt->msgCnt; ++j)
if( pkt->msgArray != NULL )
printf("io midi cb: %ld %ld 0x%x %i %i\n", pkt->msgArray[j].timeStamp.tv_sec, pkt->msgArray[j].timeStamp.tv_nsec, pkt->msgArray[j].status,pkt->msgArray[j].d0, pkt->msgArray[j].d1);
else
printf("io midi cb: 0x%x ",pkt->sysExMsg[j]);
*/
}
}
@ -474,12 +589,13 @@ namespace cw
}
}
// create the audio group thread
if((rc = thread_mach::add(p->threadMachH,_socketThreadFunc,p)) != kOkRC )
{
rc = cwLogError(rc,"Error creating socket thread.");
goto errLabel;
}
// create the socket thread
if( p->sockN > 0 )
if((rc = thread_mach::add(p->threadMachH,_socketThreadFunc,p)) != kOkRC )
{
rc = cwLogError(rc,"Error creating socket thread.");
goto errLabel;
}
errLabel:
@ -1449,6 +1565,9 @@ namespace cw
if((rc = thread_mach::destroy(p->threadMachH)) != kOkRC )
return rc;
mem::free(p->timerA);
p->timerN = 0;
for(unsigned i=0; i<p->serialN; ++i)
serialPortSrv::destroy( p->serialA[i].serialH );
@ -1539,6 +1658,8 @@ cw::rc_t cw::io::create(
// duplicate the cfg object so that we can maintain pointers into its elements without
// any chance that they will be delted before the application completes
p->cfg = o->duplicate();
p->cbFunc = cbFunc;
p->cbArg = cbArg;
// create the the thread machine
if((rc = thread_mach::create( p->threadMachH )) != kOkRC )
@ -1565,13 +1686,9 @@ cw::rc_t cw::io::create(
goto errLabel;
p->cbFunc = cbFunc;
p->cbArg = cbArg;
p->quitFl.store(false);
time::get(p->t0);
h.set(p);
errLabel:
@ -1667,6 +1784,113 @@ void cw::io::report( handle_t h )
}
//----------------------------------------------------------------------------------------------------------
//
// Timer
//
cw::rc_t cw::io::timerCreate( handle_t h, const char* label, unsigned id, unsigned periodMicroSec )
{
io_t* p = _handleToPtr(h);
return _timerCreate(p, label, id, periodMicroSec );
}
cw::rc_t cw::io::timerDestroy( handle_t h, unsigned timerIdx )
{
io_t* p = _handleToPtr(h);
timer_t* t = _timerIndexToPtr( p, timerIdx );
if( t != nullptr )
{
t->startedFl = false;
t->deletedFl = true;
}
return t==nullptr ? kInvalidIdRC : kOkRC;
}
unsigned cw::io::timerCount( handle_t h )
{
io_t* p = _handleToPtr(h);
return p->timerN;
}
unsigned cw::io::timerLabelToIndex( handle_t h, const char* label )
{
io_t* p = _handleToPtr(h);
for(unsigned i=0; i<p->timerN; ++i)
if( !p->timerA[i].deletedFl && strcmp(label,p->timerA[i].label) == 0 )
return i;
return kInvalidIdx;
}
unsigned cw::io::timerIdToIndex( handle_t h, unsigned timerId )
{
io_t* p = _handleToPtr(h);
for(unsigned i=0; i<p->timerN; ++i)
{
timer_t* t = p->timerA + i;
if( !t->deletedFl && t->id == timerId )
return i;
}
return kInvalidIdx;
}
const char* cw::io::timerLabel( handle_t h, unsigned timerIdx )
{
io_t* p = _handleToPtr(h);
timer_t* t = _timerIndexToPtr( p, timerIdx );
return t==nullptr ? nullptr : t->label;
}
unsigned cw::io::timerId( handle_t h, unsigned timerIdx )
{
io_t* p = _handleToPtr(h);
timer_t* t = _timerIndexToPtr( p, timerIdx );
return t==nullptr ? kInvalidId : t->id;
}
unsigned cw::io::timerPeriodMicroSec( handle_t h, unsigned timerIdx )
{
io_t* p = _handleToPtr(h);
timer_t* t = _timerIndexToPtr( p, timerIdx );
return t==nullptr ? 0 : t->periodMicroSec;
}
cw::rc_t cw::io::timerSetPeriodMicroSec( handle_t h, unsigned timerIdx, unsigned periodMicroSec )
{
rc_t rc = kOkRC;
io_t* p = _handleToPtr(h);
timer_t* t = _timerIndexToPtr(p, timerIdx);
if( t == nullptr )
rc = kInvalidIdRC;
else
p->timerA[ timerIdx ].periodMicroSec = periodMicroSec;
return rc;
}
cw::rc_t cw::io::timerStart( handle_t h, unsigned timerIdx )
{
io_t* p = _handleToPtr(h);
return _timerStart( p, timerIdx, true );
}
cw::rc_t cw::io::timerStop( handle_t h, unsigned timerIdx )
{
io_t* p = _handleToPtr(h);
return _timerStart( p, timerIdx, false );
}
//----------------------------------------------------------------------------------------------------------
//
@ -1746,10 +1970,8 @@ unsigned cw::io::midiDevicePortIndex( handle_t h, unsigned devIdx, bool inputFl,
cw::rc_t cw::io::midiDeviceSend( handle_t h, unsigned devIdx, unsigned portIdx, uint8_t status, uint8_t d0, uint8_t d1 )
{
rc_t rc = kOkRC;
//io_t* p = _handleToPtr(h);
//return midi::device::send( p->midiH, devIdx, portIdx, status, d0, d1 );
return rc;
io_t* p = _handleToPtr(h);
return midi::device::send( p->midiH, devIdx, portIdx, status, d0, d1 );
}
//----------------------------------------------------------------------------------------------------------

43
cwIo.h
View File

@ -27,15 +27,21 @@ namespace cw
enum
{
kSerialTId,
kMidiTId,
kAudioTId,
kAudioMeterTId,
kSockTId,
kWebSockTId,
kUiTId
kTimerTId,
kSerialTId,
kMidiTId,
kAudioTId,
kAudioMeterTId,
kSockTId,
kWebSockTId,
kUiTId
};
typedef struct timer_msg_str
{
unsigned id;
} timer_msg_t;
typedef struct serial_msg_str
{
unsigned devId;
@ -45,7 +51,7 @@ namespace cw
typedef struct midi_msg_str
{
midi::packet_t* pkt;
const midi::packet_t* pkt;
} midi_msg_t;
typedef audio::device::sample_t sample_t;
@ -113,6 +119,7 @@ namespace cw
unsigned tid;
union
{
timer_msg_t* timer;
serial_msg_t* serial;
midi_msg_t* midi;
audio_msg_t* audio;
@ -142,6 +149,25 @@ namespace cw
bool isShuttingDown( handle_t h );
void report( handle_t h );
//----------------------------------------------------------------------------------------------------------
//
// Timer
//
rc_t timerCreate( handle_t h, const char* label, unsigned id, unsigned periodMicroSec );
rc_t timerDestroy( handle_t h, unsigned timerIdx );
unsigned timerCount( handle_t h );
unsigned timerLabelToIndex( handle_t h, const char* label );
unsigned timerIdToIndex( handle_t h, unsigned timerId );
const char* timerLabel( handle_t h, unsigned timerIdx );
unsigned timerId( handle_t h, unsigned timerIdx );
unsigned timerPeriodMicroSec( handle_t h, unsigned timerIdx );
rc_t timerSetPeriodMicroSec( handle_t h, unsigned timerIdx, unsigned periodMicroSec );
rc_t timerStart( handle_t h, unsigned timerIdx );
rc_t timerStop( handle_t h, unsigned timerIdx );
//----------------------------------------------------------------------------------------------------------
//
// Serial
@ -278,6 +304,7 @@ namespace cw
rc_t uiRegisterAppIdMap( handle_t h, const ui::appIdMap_t* map, unsigned mapN );
// Send a value from the application to the UI.
// Set wsSessId to kInvalidId to send to all sessions.
rc_t uiSendValue( handle_t h, unsigned wsSessId, unsigned uuId, bool value );
rc_t uiSendValue( handle_t h, unsigned wsSessId, unsigned uuId, int value );
rc_t uiSendValue( handle_t h, unsigned wsSessId, unsigned uuId, unsigned value );